/* This code is part of the tng compression routines. * * Written by Daniel Spangberg and Magnus Lundborg * Copyright (c) 2010, 2013-2014 The GROMACS development team. * * * This program is free software; you can redistribute it and/or * modify it under the terms of the Revised BSD License. */ /* This code is heavily influenced by http://hpcv100.rc.rug.nl/xdrf.html Based on coordinate compression (c) by Frans van Hoesel. and GROMACS xtc files (http://www.gromacs.org) (c) Copyright (c) Erik Lindahl, David van der Spoel */ #include #include #include #include #include "../../include/compression/coder.h" #include "../../include/compression/widemuldiv.h" #include "../../include/compression/warnmalloc.h" /* Generated by gen_magic.py */ #define MAX_MAGIC 92 #ifdef USE_WINDOWS #define TNG_INLINE __inline #else #define TNG_INLINE inline #endif static unsigned int magic[MAX_MAGIC]={ 2U, 3U, 4U, 5U, 6U, 8U, 10U, 12U, 16U, 20U, 25U, 32U, 40U, 50U, 64U, 80U, 101U, 128U, 161U, 203U, 256U, 322U, 406U, 512U, 645U, 812U, 1024U, 1290U, 1625U, 2048U, 2580U, 3250U, 4096U, 5160U, 6501U, 8192U, 10321U, 13003U, 16384U, 20642U, 26007U, 32768U, 41285U, 52015U, 65536U, 82570U, 104031U, 131072U, 165140U, 208063U, 262144U, 330280U, 416127U, 524288U, 660561U, 832255U, 1048576U, 1321122U, 1664510U, 2097152U, 2642245U, 3329021U, 4194304U, 5284491U, 6658042U, 8388608U, 10568983U, 13316085U, 16777216U, 21137967U, 26632170U, 33554432U, 42275935U, 53264340U, 67108864U, 84551870U, 106528681U, 134217728U, 169103740U, 213057362U, 268435456U, 338207481U, 426114725U, 536870912U, 676414963U, 852229450U, 1073741824U, 1352829926U, 1704458900U, 2147483648U, 2705659852U, 3408917801U, }; static unsigned int magic_bits[MAX_MAGIC][8]={ { 3, 6, 9, 12, 15, 18, 21, 24, }, { 5, 10, 15, 20, 24, 29, 34, 39, }, { 6, 12, 18, 24, 30, 36, 42, 48, }, { 7, 14, 21, 28, 35, 42, 49, 56, }, { 8, 16, 24, 32, 39, 47, 55, 63, }, { 9, 18, 27, 36, 45, 54, 63, 72, }, { 10, 20, 30, 40, 50, 60, 70, 80, }, { 11, 22, 33, 44, 54, 65, 76, 87, }, { 12, 24, 36, 48, 60, 72, 84, 97, }, { 13, 26, 39, 52, 65, 78, 91, 104, }, { 14, 28, 42, 56, 70, 84, 98, 112, }, { 15, 30, 45, 60, 75, 90, 105, 120, }, { 16, 32, 48, 64, 80, 96, 112, 128, }, { 17, 34, 51, 68, 85, 102, 119, 136, }, { 18, 36, 54, 72, 90, 108, 127, 144, }, { 19, 38, 57, 76, 95, 114, 133, 152, }, { 20, 40, 60, 80, 100, 120, 140, 160, }, { 21, 42, 63, 84, 105, 127, 147, 168, }, { 22, 44, 66, 88, 110, 132, 154, 176, }, { 23, 46, 69, 92, 115, 138, 161, 184, }, { 24, 48, 72, 97, 120, 144, 168, 192, }, { 25, 50, 75, 100, 125, 150, 175, 200, }, { 26, 52, 78, 104, 130, 156, 182, 208, }, { 27, 54, 81, 108, 135, 162, 190, 216, }, { 28, 56, 84, 112, 140, 168, 196, 224, }, { 29, 58, 87, 116, 145, 174, 203, 232, }, { 30, 60, 90, 120, 150, 180, 210, 240, }, { 31, 62, 93, 124, 155, 186, 217, 248, }, { 32, 64, 96, 128, 160, 192, 224, 256, }, { 33, 66, 99, 132, 165, 198, 231, 264, }, { 34, 68, 102, 136, 170, 204, 238, 272, }, { 35, 70, 105, 140, 175, 210, 245, 280, }, { 36, 72, 108, 144, 180, 216, 252, 288, }, { 37, 74, 111, 148, 185, 222, 259, 296, }, { 38, 76, 114, 152, 190, 228, 266, 304, }, { 39, 78, 117, 157, 195, 234, 273, 312, }, { 40, 80, 120, 160, 200, 240, 280, 320, }, { 41, 82, 123, 164, 205, 246, 287, 328, }, { 42, 84, 127, 168, 210, 252, 294, 336, }, { 43, 86, 129, 172, 215, 258, 301, 344, }, { 44, 88, 132, 176, 220, 264, 308, 352, }, { 45, 90, 135, 180, 225, 270, 315, 360, }, { 46, 92, 138, 184, 230, 276, 322, 368, }, { 47, 94, 141, 188, 235, 282, 329, 376, }, { 48, 97, 144, 192, 240, 288, 336, 384, }, { 49, 98, 147, 196, 245, 294, 343, 392, }, { 50, 100, 150, 200, 250, 300, 350, 400, }, { 52, 102, 153, 204, 255, 306, 357, 408, }, { 52, 104, 156, 208, 260, 312, 364, 416, }, { 53, 106, 159, 212, 265, 318, 371, 424, }, { 54, 108, 162, 216, 270, 324, 378, 432, }, { 55, 110, 165, 220, 275, 330, 385, 440, }, { 56, 112, 168, 224, 280, 336, 392, 448, }, { 57, 114, 172, 228, 285, 342, 399, 456, }, { 58, 116, 174, 232, 290, 348, 406, 464, }, { 59, 118, 177, 236, 295, 354, 413, 472, }, { 60, 120, 180, 240, 300, 360, 420, 480, }, { 61, 122, 183, 244, 305, 366, 427, 488, }, { 62, 124, 186, 248, 310, 372, 434, 496, }, { 63, 127, 190, 252, 315, 378, 442, 505, }, { 64, 128, 192, 256, 320, 384, 448, 512, }, { 65, 130, 195, 260, 325, 390, 455, 520, }, { 66, 132, 198, 264, 330, 396, 462, 528, }, { 67, 134, 201, 268, 335, 402, 469, 536, }, { 68, 136, 204, 272, 340, 408, 476, 544, }, { 69, 138, 207, 276, 345, 414, 483, 552, }, { 70, 140, 210, 280, 350, 420, 490, 560, }, { 71, 142, 213, 284, 355, 426, 497, 568, }, { 72, 144, 216, 288, 360, 432, 505, 576, }, { 73, 146, 219, 292, 365, 438, 511, 584, }, { 74, 148, 222, 296, 370, 444, 518, 592, }, { 75, 150, 225, 300, 375, 451, 525, 600, }, { 76, 152, 228, 304, 380, 456, 532, 608, }, { 77, 154, 231, 308, 385, 462, 539, 616, }, { 78, 157, 234, 312, 390, 469, 546, 625, }, { 79, 158, 237, 316, 395, 474, 553, 632, }, { 80, 160, 240, 320, 400, 480, 560, 640, }, { 81, 162, 243, 324, 406, 486, 568, 648, }, { 82, 164, 246, 328, 410, 492, 574, 656, }, { 83, 166, 249, 332, 415, 498, 581, 664, }, { 84, 168, 252, 336, 420, 505, 588, 672, }, { 85, 170, 255, 340, 425, 510, 595, 680, }, { 86, 172, 258, 344, 430, 516, 602, 688, }, { 87, 174, 261, 348, 435, 522, 609, 696, }, { 88, 176, 264, 352, 440, 528, 616, 704, }, { 89, 178, 267, 356, 445, 534, 623, 712, }, { 90, 180, 270, 360, 451, 540, 631, 720, }, { 91, 182, 273, 364, 455, 546, 637, 728, }, { 92, 184, 276, 368, 460, 552, 644, 736, }, { 94, 187, 279, 373, 466, 558, 651, 745, }, { 94, 188, 282, 376, 470, 564, 658, 752, }, { 95, 190, 285, 380, 475, 570, 665, 760, }, }; static const double iflipgaincheck=0.89089871814033927; /* 1./(2**(1./6)) */ /* Difference in indices used for determining whether to store as large or small */ #define QUITE_LARGE 3 #define IS_LARGE 6 #if 0 #define SHOWIT #endif #ifdef USE_WINDOWS #define TNG_INLINE __inline #else #define TNG_INLINE inline #endif int Ptngc_magic(const unsigned int i) { return magic[i]; } int Ptngc_find_magic_index(const unsigned int maxval) { int i; if(maxval > magic[MAX_MAGIC/4]) { if(maxval > magic[MAX_MAGIC/2]) { i = MAX_MAGIC/2 + 1; } else { i = MAX_MAGIC/4 + 1; } } else { i = 0; } while (magic[i]<=maxval) i++; return i; } static TNG_INLINE unsigned int positive_int(const int item) { int s=0; if (item>0) s=1+(item-1)*2; else if (item<0) s=2+(-item-1)*2; return s; } static TNG_INLINE int unpositive_int(const int val) { int s=(val+1)/2; if ((val%2)==0) s=-s; return s; } /* Sequence instructions */ #define INSTR_DEFAULT 0 #define INSTR_BASE_RUNLENGTH 1 #define INSTR_ONLY_LARGE 2 #define INSTR_ONLY_SMALL 3 #define INSTR_LARGE_BASE_CHANGE 4 #define INSTR_FLIP 5 #define INSTR_LARGE_RLE 6 #define MAXINSTR 7 #ifdef SHOWIT static char *instrnames[MAXINSTR]={ "large+small", "base+run", "large", "small", "large base change", "flip", "large rle", }; #endif /* Bit patterns in the compressed code stream: */ static const int seq_instr[MAXINSTR][2]= { { 1,1 }, /* 1 : one large atom + runlength encoded small integers. Use same settings as before. */ { 0,2 }, /* 00 : set base and runlength in next four bits (x). base (increase/keep/decrease)=x%3-1. runlength=1+x/3. The special value 1111 in the four bits means runlength=6 and base change=0 */ { 4,4 }, /* 0100 : next only a large atom comes. */ { 5,4 }, /* 0101 : next only runlength encoded small integers. Use same settings as before. */ { 6,4 }, /* 0110 : Large change in base. Change is encoded in the following 2 bits. change direction (sign) is the first bit. The next bit +1 is the actual change. This allows the change of up to +/- 2 indices. */ { 14,5 }, /* 01110 : flip whether integers should be modified to compress water better */ { 15,5 }, /* 01111 : Large rle. The next 4 bits encode how many large atoms are in the following sequence: 3-18. (2 is more efficiently coded with two large instructions. */ }; static void write_instruction(struct coder *coder, const int instr, unsigned char **output_ptr) { Ptngc_writebits(coder,seq_instr[instr][0],seq_instr[instr][1],output_ptr); #ifdef SHOWIT fprintf(stderr,"INSTR: %s (%d bits)\n",instrnames[instr],seq_instr[instr][1]); #endif } static unsigned int readbits(unsigned char **ptr, int *bitptr, int nbits) { unsigned int val=0U; unsigned int extract_mask=0x80U>>*bitptr; unsigned char thisval=**ptr; #ifdef SHOWIT fprintf(stderr,"Read nbits=%d val=",nbits); #endif while (nbits--) { val<<=1; val|=((extract_mask & thisval)!=0); *bitptr=(*bitptr)+1; extract_mask>>=1; if (!extract_mask) { extract_mask=0x80U; *ptr=(*ptr)+1; *bitptr=0; if (nbits) thisval=**ptr; } } #ifdef SHOWIT fprintf(stderr,"%x\n",val); #endif return val; } static void readmanybits(unsigned char **ptr, int *bitptr, int nbits, unsigned char *buffer) { while (nbits>=8) { *buffer++=readbits(ptr,bitptr,8); nbits-=8; #ifdef SHOWIT fprintf(stderr,"Read value %02x\n",buffer[-1]); #endif } if (nbits) { *buffer++=readbits(ptr,bitptr,nbits); #ifdef SHOWIT fprintf(stderr,"Read value %02x\n",buffer[-1]); #endif } } static int read_instruction(unsigned char **ptr, int *bitptr) { int instr=-1; unsigned int bits=readbits(ptr,bitptr,1); if (bits) instr=INSTR_DEFAULT; else { bits=readbits(ptr,bitptr,1); if (!bits) instr=INSTR_BASE_RUNLENGTH; else { bits=readbits(ptr,bitptr,2); if (bits==0) instr=INSTR_ONLY_LARGE; else if (bits==1) instr=INSTR_ONLY_SMALL; else if (bits==2) instr=INSTR_LARGE_BASE_CHANGE; else if (bits==3) { bits=readbits(ptr,bitptr,1); if (bits==0) instr=INSTR_FLIP; else instr=INSTR_LARGE_RLE; } } } return instr; } /* Modifies three integer values for better compression of water */ static void swap_ints(int *in, int *out) { out[0]=in[0]+in[1]; out[1]=-in[1]; out[2]=in[1]+in[2]; } static void swap_is_better(int *input, int *minint, int *sum_normal, int *sum_swapped) { int normal_max=0; int swapped_max=0; int i,j; int normal[3]; int swapped[3]; for (i=0; i<3; i++) { normal[0]=input[i]-minint[i]; normal[1]=input[3+i]-input[i]; /* minint[i]-minint[i] cancels out */ normal[2]=input[6+i]-input[3+i]; /* minint[i]-minint[i] cancels out */ swap_ints(normal,swapped); for (j=1; j<3; j++) { if (positive_int(normal[j])>(unsigned int)normal_max) normal_max=positive_int(normal[j]); if (positive_int(swapped[j])>(unsigned int)swapped_max) swapped_max=positive_int(swapped[j]); } } if (normal_max==0) normal_max=1; if (swapped_max==0) swapped_max=1; *sum_normal=normal_max; *sum_swapped=swapped_max; } static void swapdecide(struct coder *coder, int *input, int *swapatoms, int *large_index, int *minint, unsigned char **output_ptr) { int didswap=0; int normal,swapped; (void)large_index; swap_is_better(input,minint,&normal,&swapped); /* We have to determine if it is worth to change the behaviour. If diff is positive it means that it is worth something to swap. But it costs 4 bits to do the change. If we assume that we gain 0.17 bit by the swap per value, and the runlength>2 for four molecules in a row, we gain something. So check if we gain at least 0.17 bits to even attempt the swap. */ #ifdef SHOWIT fprintf(stderr,"Trying Flip: %g %g\n",(double)swapped/normal, (double)normal/swapped); #endif if (((swapped 0) { Ptngc_largeint_add(input[0],largeint,19); } for (i=1; i>shift) & 0xFFU; shift+=8; } } } /* The opposite of base_compress. */ static void trajcoder_base_decompress(unsigned char *input, const int n, int *index, int *output) { unsigned int largeint[19]; unsigned int largeint_tmp[19]; int i,j; /* Convert the sequence of bytes to a largeint. */ for (i=0; i<18; i++) { int shift=0; largeint[i]=0U; for (j=0; j<4; j++) { largeint[i]|=((unsigned int)input[i*4+j])<=0; i--) { unsigned int remainder=Ptngc_largeint_div(magic[index[i%3]],largeint,largeint_tmp,19); #if 0 #ifdef SHOWIT fprintf(stderr,"Remainder: %u\n",remainder); #endif #endif #if 0 for (j=0; j<19; j++) largeint[j]=largeint_tmp[j]; #endif memcpy(largeint,largeint_tmp,19*sizeof *largeint); output[i]=remainder; } } /* It is "large" if we have to increase the small index quite a bit. Not so much to be rejected by the not very large check later. */ static int is_quite_large(int *input, const int small_index, const int max_large_index) { int is=0; int i; if (small_index+QUITE_LARGE>=max_large_index) is=1; else { for (i=0; i<3; i++) if (positive_int(input[i])>magic[small_index+QUITE_LARGE]) { is=1; break; } } return is; } #ifdef SHOWIT int nbits_sum; int nvalues_sum; #endif static void write_three_large(struct coder *coder, int *encode_ints, int *large_index, const int nbits, unsigned char *compress_buffer, unsigned char **output_ptr) { trajcoder_base_compress(encode_ints,3,large_index,compress_buffer); Ptngc_writemanybits(coder,compress_buffer,nbits,output_ptr); #ifdef SHOWIT fprintf(stderr,"nbits=%d (%g)\n",nbits,nbits/3.); nbits_sum+=nbits; nvalues_sum+=3; fprintf(stderr,"Large: %d %d %d\n",encode_ints[0],encode_ints[1],encode_ints[2]); #endif } static void insert_batch(int *input_ptr, int ntriplets_left, const int *prevcoord,int *minint, int *encode_ints, const int startenc, int *nenc) { int nencode=startenc*3; int tmp_prevcoord[3]; tmp_prevcoord[0]=prevcoord[0]; tmp_prevcoord[1]=prevcoord[1]; tmp_prevcoord[2]=prevcoord[2]; if (startenc) { int i; for (i=0; imaxint[j]) maxint[j]=input[i*3+j]; if (input[i*3+j]max_large_index) max_large_index=large_index[1]; if (large_index[2]>max_large_index) max_large_index=large_index[2]; #ifdef SHOWIT for (j=0; j<3; j++) fprintf(stderr,"minint[%d]=%d. maxint[%d]=%d large_index[%d]=%d value=%d\n",j,minint[j],j,maxint[j], j,large_index[j],magic[large_index[j]]); fprintf(stderr,"large_nbits=%d\n",large_nbits); #endif /* Guess initial small index */ small_index=max_large_index/2; /* Find the largest value that is not large. Not large is half index of large. */ max_small=magic[small_index]; intmax=0; for (i=0; i<*length; i++) { int item=input[i]; int s=positive_int(item); if (s>intmax) if (spack_temporary_bits=32; coder->pack_temporary=positive_int(minint[0]); Ptngc_out8bits(coder,&output_ptr); coder->pack_temporary_bits=32; coder->pack_temporary=positive_int(minint[1]); Ptngc_out8bits(coder,&output_ptr); coder->pack_temporary_bits=32; coder->pack_temporary=positive_int(minint[2]); Ptngc_out8bits(coder,&output_ptr); /* Store max indices */ coder->pack_temporary_bits=8; coder->pack_temporary=large_index[0]; Ptngc_out8bits(coder,&output_ptr); coder->pack_temporary_bits=8; coder->pack_temporary=large_index[1]; Ptngc_out8bits(coder,&output_ptr); coder->pack_temporary_bits=8; coder->pack_temporary=large_index[2]; Ptngc_out8bits(coder,&output_ptr); /* Store initial small index */ coder->pack_temporary_bits=8; coder->pack_temporary=small_index; Ptngc_out8bits(coder,&output_ptr); #if 0 #ifdef SHOWIT for (i=0; ilargest_required_base) largest_required_base=encode_ints[ienc]; /* Also compute what the largest base is for the current runlength setting! */ largest_runlength_base=0; for (ienc=0; (ienclargest_runlength_base) largest_runlength_base=encode_ints[ienc]; largest_required_index=Ptngc_find_magic_index(largest_required_base); largest_runlength_index=Ptngc_find_magic_index(largest_runlength_base); if (largest_required_indexntriplets_left) new_runlength=ntriplets_left; /* We must at least try to get some small integers going. */ if (new_runlength==0) { new_runlength=1; new_small_index=small_index; } iter_runlength=new_runlength; iter_small_index=new_small_index; /* Iterate to find optimal encoding and runlength */ #ifdef SHOWIT fprintf(stderr,"Entering iterative loop.\n"); fflush(stderr); #endif do { new_runlength=iter_runlength; new_small_index=iter_small_index; #ifdef SHOWIT fprintf(stderr,"Test new_small_index=%d Base=%d\n",new_small_index,magic[new_small_index]); #endif /* What is the largest runlength we can do with the currently selected encoding? Also the max supported runlength is 6 triplets! */ for (ienc=0; iencnew_small_index) break; } if (ienc/3>new_runlength) { iter_runlength=ienc/3; #ifdef SHOWIT fprintf(stderr,"I found a new possible runlength: %d\n",iter_runlength); #endif } /* How large encoding do we have to use? */ largest_runlength_base=0; for (ienc=0; ienclargest_runlength_base) largest_runlength_base=encode_ints[ienc]; largest_runlength_index=Ptngc_find_magic_index(largest_runlength_base); if (largest_runlength_index!=new_small_index) { iter_small_index=largest_runlength_index; #ifdef SHOWIT fprintf(stderr,"I found a new possible small index: %d Base=%d\n",iter_small_index,magic[iter_small_index]); #endif } } while ((new_runlength!=iter_runlength) || (new_small_index!=iter_small_index)); #ifdef SHOWIT fprintf(stderr,"Exit iterative loop.\n"); fflush(stderr); #endif /* Verify that we got something good. We may have caught a substantially larger atom. If so we should just bail out and let the loop get on another lap. We may have a minimum runlength though and then we have to fulfill the request to write out these atoms! */ rle_index_dep=0; if (new_runlength<3) rle_index_dep=IS_LARGE; else if (new_runlength<6) rle_index_dep=QUITE_LARGE; if ((min_runlength) || ((new_small_index=%g?\n",change,isum,(double)magic[small_index+change]*(double)magic[small_index+change]); #endif if (isum>(double)magic[small_index+change]*(double)magic[small_index+change]) { #ifdef SHOWIT fprintf(stderr,"Rejected decrease %d of index due to length of vector: %g>=%g\n",change,isum,(double)magic[small_index+change]*(double)magic[small_index+change]); #endif rejected=1; change++; } } while ((change<0) && (rejected)); if (change==0) break; } } /* If the only thing to do is to change the base by only one -1 it is probably not worth it. */ if (!((change==-1) && (runlength==new_runlength))) { /* If we have a very short runlength we do not want to do large base changes. It costs 6 extra bits to do -2. We gain 2/3 bits per value to decrease the index by -2, ie 2 bits, so to any changes down we must have a runlength of 3 or more to do it for one molecule! If we have several molecules we will gain of course, so not be so strict. */ if ((change==-2) && (new_runlength<3)) { if (runlength==new_runlength) change=0; else change=-1; #ifdef SHOWIT fprintf(stderr,"Rejected change by -2 due to too short runlenght. Change set to %d\n",change); #endif } /* First adjust base using large base change instruction (if necessary) */ while ((change>1) || (change<-1) || ((new_runlength==6) && (change))) { unsigned int code=0U; int this_change=change; if (this_change>2) this_change=2; if (this_change<-2) this_change=-2; change-=this_change; #ifdef SHOWIT fprintf(stderr,"Large base change: %d.\n",this_change); #endif small_index+=this_change; if (this_change<0) { code|=2U; this_change=-this_change; } code|=(unsigned int)(this_change-1); write_instruction(coder,INSTR_LARGE_BASE_CHANGE,&output_ptr); Ptngc_writebits(coder,code,2,&output_ptr); } /* If there is still base change or runlength changes to do, we do them now. */ if ((new_runlength!=runlength) || (change)) { unsigned int ichange=(unsigned int)(change+1); unsigned int code=0U; unsigned int irun=(unsigned int)((new_runlength-1)*3); if (new_runlength==6) ichange=0; /* Means no change. The change has been taken care of explicitly by a large base change instruction above. */ code=ichange+irun; #ifdef SHOWIT fprintf(stderr,"Small base change: %d Runlength change: %d\n",change,new_runlength); #endif small_index+=change; write_instruction(coder,INSTR_BASE_RUNLENGTH,&output_ptr); Ptngc_writebits(coder,code,4,&output_ptr); runlength=new_runlength; } } #ifdef SHOWIT else fprintf(stderr,"Rejected base change due to only change==-1\n"); #endif #ifdef SHOWIT fprintf(stderr,"Current small index: %d Base=%d\n",small_index,magic[small_index]); #endif } /* If we have a large previous integer we can combine it with a sequence of small ints. */ if (has_large) { /* If swapatoms is set to 1 but we did actually not do any swapping, we must first write out the large atom and then the small. If swapatoms is 1 and we did swapping we can use the efficient encoding. */ if ((swapatoms) && (!didswap)) { #ifdef SHOWIT fprintf(stderr,"Swapatoms was set to 1 but we did not do swapping!\n"); fprintf(stderr,"Only one large integer.\n"); #endif /* Flush all large atoms. */ flush_large(coder,&has_large,has_large_ints,has_large,large_index,large_nbits,compress_buffer,&output_ptr); #ifdef SHOWIT fprintf(stderr,"Sequence of only small integers.\n"); #endif write_instruction(coder,INSTR_ONLY_SMALL,&output_ptr); } else { #ifdef SHOWIT fprintf(stderr,"Sequence of one large and small integers (good compression).\n"); #endif /* Flush all large atoms but one! */ if (has_large>1) flush_large(coder,&has_large,has_large_ints,has_large-1,large_index,large_nbits,compress_buffer,&output_ptr); write_instruction(coder,INSTR_DEFAULT,&output_ptr); write_three_large(coder,has_large_ints,large_index,large_nbits,compress_buffer,&output_ptr); has_large=0; } } else { #ifdef SHOWIT fprintf(stderr,"Sequence of only small integers.\n"); #endif write_instruction(coder,INSTR_ONLY_SMALL,&output_ptr); } /* Base compress small integers using the current parameters. */ nbits=magic_bits[small_index][runlength-1]; /* The same base is used for the small changes. */ small_idx[0]=small_index; small_idx[1]=small_index; small_idx[2]=small_index; trajcoder_base_compress(encode_ints,runlength*3,small_idx,compress_buffer); #ifdef SHOWIT fprintf(stderr,"nbits=%d (%g)\n",nbits,nbits/(runlength*3.)); nbits_sum+=nbits; nvalues_sum+=runlength*3; fprintf(stderr,"Runlength encoded small integers. runlength=%d\n",runlength); #endif /* write out base compressed small integers */ Ptngc_writemanybits(coder,compress_buffer,nbits,&output_ptr); #ifdef SHOWIT for (ienc=0; ienc=0) && (instr