1 #include <stdlib.h>
2 #include <math.h>
3 #include "grib2.h"
4 
5 
compack(g2float * fld,g2int ndpts,g2int idrsnum,g2int * idrstmpl,unsigned char * cpack,g2int * lcpack)6 void compack(g2float *fld,g2int ndpts,g2int idrsnum,g2int *idrstmpl,
7              unsigned char *cpack,g2int *lcpack)
8 //$$$  SUBPROGRAM DOCUMENTATION BLOCK
9 //                .      .    .                                       .
10 // SUBPROGRAM:    compack
11 //   PRGMMR: Gilbert          ORG: W/NP11    DATE: 2002-11-07
12 //
13 // ABSTRACT: This subroutine packs up a data field using a complex
14 //   packing algorithm as defined in the GRIB2 documention.  It
15 //   supports GRIB2 complex packing templates with or without
16 //   spatial differences (i.e. DRTs 5.2 and 5.3).
17 //   It also fills in GRIB2 Data Representation Template 5.2 or 5.3
18 //   with the appropriate values.
19 //
20 // PROGRAM HISTORY LOG:
21 // 2002-11-07  Gilbert
22 //
23 // USAGE:    void compack(g2float *fld,g2int ndpts,g2int idrsnum,
24 //                g2int *idrstmpl,unsigned char *cpack,g2int *lcpack)
25 //
26 //   INPUT ARGUMENTS:
27 //     fld[]    - Contains the data values to pack
28 //     ndpts    - The number of data values in array fld[]
29 //     idrsnum  - Data Representation Template number 5.N
30 //                Must equal 2 or 3.
31 //     idrstmpl - Contains the array of values for Data Representation
32 //                Template 5.2 or 5.3
33 //                [0] = Reference value - ignored on input
34 //                [1] = Binary Scale Factor
35 //                [2] = Decimal Scale Factor
36 //                    .
37 //                    .
38 //                [6] = Missing value management
39 //                [7] = Primary missing value
40 //                [8] = Secondary missing value
41 //                    .
42 //                    .
43 //               [16] = Order of Spatial Differencing  ( 1 or 2 )
44 //                    .
45 //                    .
46 //
47 //   OUTPUT ARGUMENTS:
48 //     idrstmpl - Contains the array of values for Data Representation
49 //                Template 5.3
50 //                [0] = Reference value - set by compack routine.
51 //                [1] = Binary Scale Factor - unchanged from input
52 //                [2] = Decimal Scale Factor - unchanged from input
53 //                    .
54 //                    .
55 //     cpack    - The packed data field
56 //     lcpack   - length of packed field cpack.
57 //
58 // REMARKS: None
59 //
60 // ATTRIBUTES:
61 //   LANGUAGE: C
62 //   MACHINE:
63 //
64 //$$$
65 {
66 
67       static g2int zero=0;
68       g2int  *ifld,*gref,*glen,*gwidth;
69       g2int  *jmin, *jmax, *lbit;
70       g2int  i,j,n, /* nbits, */ imin,imax,left;
71       g2int  isd,itemp,ilmax,ngwidthref=0,nbitsgwidth=0;
72       g2int  nglenref=0,nglenlast=0,iofst,ival1,ival2;
73       g2int  minsd,nbitsd=0,maxorig,nbitorig,ngroups;
74       g2int  lg,ng,igmax,iwmax,nbitsgref;
75       g2int  glength,grpwidth,nbitsglen=0;
76       g2int  kfildo, minpk, inc, maxgrps, ibit, jbit, kbit, novref, lbitref;
77       g2int  missopt, miss1, miss2, ier;
78       g2float  bscale,dscale,rmax,rmin,temp;
79       static g2int simple_alg = 0;
80       static g2float alog2=0.69314718;       //  ln(2.0)
81       static g2int one=1;
82 
83       bscale=int_power(2.0,-idrstmpl[1]);
84       dscale=int_power(10.0,idrstmpl[2]);
85 //
86 //  Find max and min values in the data
87 //
88       rmax=fld[0];
89       rmin=fld[0];
90       for (j=1;j<ndpts;j++) {
91         if (fld[j] > rmax) rmax=fld[j];
92         if (fld[j] < rmin) rmin=fld[j];
93       }
94 
95 //
96 //  If max and min values are not equal, pack up field.
97 //  If they are equal, we have a constant field, and the reference
98 //  value (rmin) is the value for each point in the field and
99 //  set nbits to 0.
100 //
101       if (rmin != rmax) {
102         iofst=0;
103         ifld=calloc(ndpts,sizeof(g2int));
104         gref=calloc(ndpts,sizeof(g2int));
105         gwidth=calloc(ndpts,sizeof(g2int));
106         glen=calloc(ndpts,sizeof(g2int));
107         //
108         //  Scale original data
109         //
110         if (idrstmpl[1] == 0) {        //  No binary scaling
111            imin=(g2int)RINT(rmin*dscale);
112            //imax=(g2int)rint(rmax*dscale);
113            rmin=(g2float)imin;
114            for (j=0;j<ndpts;j++)
115               ifld[j]=(g2int)RINT(fld[j]*dscale)-imin;
116         }
117         else {                             //  Use binary scaling factor
118            rmin=rmin*dscale;
119            //rmax=rmax*dscale;
120            for (j=0;j<ndpts;j++)
121              ifld[j]=(g2int)RINT(((fld[j]*dscale)-rmin)*bscale);
122         }
123         //
124         //  Calculate Spatial differences, if using DRS Template 5.3
125         //
126         if (idrsnum == 3) {        // spatial differences
127            if (idrstmpl[16]!=1 && idrstmpl[16]!=2) idrstmpl[16]=1;
128            if (idrstmpl[16] == 1) {      // first order
129               ival1=ifld[0];
130               for (j=ndpts-1;j>0;j--)
131                  ifld[j]=ifld[j]-ifld[j-1];
132               ifld[0]=0;
133            }
134            else if (idrstmpl[16] == 2) {      // second order
135               ival1=ifld[0];
136               ival2=ifld[1];
137               for (j=ndpts-1;j>1;j--)
138                  ifld[j]=ifld[j]-(2*ifld[j-1])+ifld[j-2];
139               ifld[0]=0;
140               ifld[1]=0;
141            }
142            //
143            //  subtract min value from spatial diff field
144            //
145            isd=idrstmpl[16];
146            minsd=ifld[isd];
147            for (j=isd;j<ndpts;j++)  if ( ifld[j] < minsd ) minsd=ifld[j];
148            for (j=isd;j<ndpts;j++)  ifld[j]=ifld[j]-minsd;
149            //
150            //   find num of bits need to store minsd and add 1 extra bit
151            //   to indicate sign
152            //
153            temp=log((double)(abs(minsd)+1))/alog2;
154            nbitsd=(g2int)ceil(temp)+1;
155            //
156            //   find num of bits need to store ifld[0] ( and ifld[1]
157            //   if using 2nd order differencing )
158            //
159            maxorig=ival1;
160            if (idrstmpl[16]==2 && ival2>ival1) maxorig=ival2;
161            temp=log((double)(maxorig+1))/alog2;
162            nbitorig=(g2int)ceil(temp)+1;
163            if (nbitorig > nbitsd) nbitsd=nbitorig;
164            //   increase number of bits to even multiple of 8 ( octet )
165            if ( (nbitsd%8) != 0) nbitsd=nbitsd+(8-(nbitsd%8));
166            //
167            //  Store extra spatial differencing info into the packed
168            //  data section.
169            //
170            if (nbitsd != 0) {
171               //   pack first original value
172               if (ival1 >= 0) {
173                  sbit(cpack,&ival1,iofst,nbitsd);
174                  iofst=iofst+nbitsd;
175               }
176               else {
177                  sbit(cpack,&one,iofst,1);
178                  iofst=iofst+1;
179                  itemp=abs(ival1);
180                  sbit(cpack,&itemp,iofst,nbitsd-1);
181                  iofst=iofst+nbitsd-1;
182               }
183               if (idrstmpl[16] == 2) {
184                //  pack second original value
185                  if (ival2 >= 0) {
186                     sbit(cpack,&ival2,iofst,nbitsd);
187                     iofst=iofst+nbitsd;
188                  }
189                  else {
190                     sbit(cpack,&one,iofst,1);
191                     iofst=iofst+1;
192                     itemp=abs(ival2);
193                     sbit(cpack,&itemp,iofst,nbitsd-1);
194                     iofst=iofst+nbitsd-1;
195                  }
196               }
197               //  pack overall min of spatial differences
198               if (minsd >= 0) {
199                  sbit(cpack,&minsd,iofst,nbitsd);
200                  iofst=iofst+nbitsd;
201               }
202               else {
203                  sbit(cpack,&one,iofst,1);
204                  iofst=iofst+1;
205                  itemp=abs(minsd);
206                  sbit(cpack,&itemp,iofst,nbitsd-1);
207                  iofst=iofst+nbitsd-1;
208               }
209            }
210            //printf("SDp %ld %ld %ld %ld\n",ival1,ival2,minsd,nbitsd);
211         }     //  end of spatial diff section
212         //
213         //   Determine Groups to be used.
214         //
215         if ( simple_alg == 1 ) {
216            //  set group length to 10;  calculate number of groups
217            //  and length of last group
218            ngroups=ndpts/10;
219            for (j=0;j<ngroups;j++) glen[j]=10;
220            itemp=ndpts%10;
221            if (itemp != 0) {
222               ngroups=ngroups+1;
223               glen[ngroups-1]=itemp;
224            }
225         }
226         else {
227            // Use Dr. Glahn's algorithm for determining grouping.
228            //
229            kfildo=6;
230            minpk=10;
231            inc=1;
232            maxgrps=(ndpts/minpk)+1;
233            jmin = calloc(maxgrps,sizeof(g2int));
234            jmax = calloc(maxgrps,sizeof(g2int));
235            lbit = calloc(maxgrps,sizeof(g2int));
236            missopt=0;
237            pack_gp(&kfildo,ifld,&ndpts,&missopt,&minpk,&inc,&miss1,&miss2,
238                         jmin,jmax,lbit,glen,&maxgrps,&ngroups,&ibit,&jbit,
239                         &kbit,&novref,&lbitref,&ier);
240            //print *,'SAGier = ',ier,ibit,jbit,kbit,novref,lbitref
241            for ( ng=0; ng<ngroups; ng++) glen[ng]=glen[ng]+novref;
242            free(jmin);
243            free(jmax);
244            free(lbit);
245         }
246         //
247         //  For each group, find the group's reference value
248         //  and the number of bits needed to hold the remaining values
249         //
250         n=0;
251         for (ng=0;ng<ngroups;ng++) {
252            //    find max and min values of group
253            gref[ng]=ifld[n];
254            imax=ifld[n];
255            j=n+1;
256            for (lg=1;lg<glen[ng];lg++) {
257               if (ifld[j] < gref[ng]) gref[ng]=ifld[j];
258               if (ifld[j] > imax) imax=ifld[j];
259               j++;
260            }
261            //   calc num of bits needed to hold data
262            if ( gref[ng] != imax ) {
263               temp=log((double)(imax-gref[ng]+1))/alog2;
264               gwidth[ng]=(g2int)ceil(temp);
265            }
266            else
267               gwidth[ng]=0;
268            //   Subtract min from data
269            j=n;
270            for (lg=0;lg<glen[ng];lg++) {
271               ifld[j]=ifld[j]-gref[ng];
272               j++;
273            }
274            //   increment fld array counter
275            n=n+glen[ng];
276         }
277         //
278         //  Find max of the group references and calc num of bits needed
279         //  to pack each groups reference value, then
280         //  pack up group reference values
281         //
282         igmax=gref[0];
283         for (j=1;j<ngroups;j++) if (gref[j] > igmax) igmax=gref[j];
284         if (igmax != 0) {
285            temp=log((double)(igmax+1))/alog2;
286            nbitsgref=(g2int)ceil(temp);
287            sbits(cpack,gref,iofst,nbitsgref,0,ngroups);
288            itemp=nbitsgref*ngroups;
289            iofst=iofst+itemp;
290            //         Pad last octet with Zeros, if necessary,
291            if ( (itemp%8) != 0) {
292               left=8-(itemp%8);
293               sbit(cpack,&zero,iofst,left);
294               iofst=iofst+left;
295            }
296         }
297         else
298            nbitsgref=0;
299         //
300         //  Find max/min of the group widths and calc num of bits needed
301         //  to pack each groups width value, then
302         //  pack up group width values
303         //
304         iwmax=gwidth[0];
305         ngwidthref=gwidth[0];
306         for (j=1;j<ngroups;j++) {
307            if (gwidth[j] > iwmax) iwmax=gwidth[j];
308            if (gwidth[j] < ngwidthref) ngwidthref=gwidth[j];
309         }
310         if (iwmax != ngwidthref) {
311            temp=log((double)(iwmax-ngwidthref+1))/alog2;
312            nbitsgwidth=(g2int)ceil(temp);
313            for (i=0;i<ngroups;i++)
314               gwidth[i]=gwidth[i]-ngwidthref;
315            sbits(cpack,gwidth,iofst,nbitsgwidth,0,ngroups);
316            itemp=nbitsgwidth*ngroups;
317            iofst=iofst+itemp;
318            //         Pad last octet with Zeros, if necessary,
319            if ( (itemp%8) != 0) {
320               left=8-(itemp%8);
321               sbit(cpack,&zero,iofst,left);
322               iofst=iofst+left;
323            }
324         }
325         else {
326            nbitsgwidth=0;
327            for (i=0;i<ngroups;i++) gwidth[i]=0;
328         }
329         //
330         //  Find max/min of the group lengths and calc num of bits needed
331         //  to pack each groups length value, then
332         //  pack up group length values
333         //
334         //write(77,*)'GLENS: ',(glen(j),j=1,ngroups)
335         ilmax=glen[0];
336         nglenref=glen[0];
337         for (j=1;j<ngroups-1;j++) {
338            if (glen[j] > ilmax) ilmax=glen[j];
339            if (glen[j] < nglenref) nglenref=glen[j];
340         }
341         nglenlast=glen[ngroups-1];
342         if (ilmax != nglenref) {
343            temp=log((double)(ilmax-nglenref+1))/alog2;
344            nbitsglen=(g2int)ceil(temp);
345            for (i=0;i<ngroups-1;i++)  glen[i]=glen[i]-nglenref;
346            sbits(cpack,glen,iofst,nbitsglen,0,ngroups);
347            itemp=nbitsglen*ngroups;
348            iofst=iofst+itemp;
349            //         Pad last octet with Zeros, if necessary,
350            if ( (itemp%8) != 0) {
351               left=8-(itemp%8);
352               sbit(cpack,&zero,iofst,left);
353               iofst=iofst+left;
354            }
355         }
356         else {
357            nbitsglen=0;
358            for (i=0;i<ngroups;i++) glen[i]=0;
359         }
360         //
361         //  For each group, pack data values
362         //
363         n=0;
364         for (ng=0;ng<ngroups;ng++) {
365            glength=glen[ng]+nglenref;
366            if (ng == (ngroups-1) ) glength=nglenlast;
367            grpwidth=gwidth[ng]+ngwidthref;
368            if ( grpwidth != 0 ) {
369               sbits(cpack,ifld+n,iofst,grpwidth,0,glength);
370               iofst=iofst+(grpwidth*glength);
371            }
372            n=n+glength;
373         }
374         //         Pad last octet with Zeros, if necessary,
375         if ( (iofst%8) != 0) {
376            left=8-(iofst%8);
377            sbit(cpack,&zero,iofst,left);
378            iofst=iofst+left;
379         }
380         *lcpack=iofst/8;
381         //
382         if ( ifld!=0 ) free(ifld);
383         if ( gref!=0 ) free(gref);
384         if ( gwidth!=0 ) free(gwidth);
385         if ( glen!=0 ) free(glen);
386       }
387       else {          //   Constant field ( max = min )
388         /* nbits=0; */
389         *lcpack=0;
390         nbitsgref=0;
391         ngroups=0;
392       }
393 
394 //
395 //  Fill in ref value and number of bits in Template 5.2
396 //
397       mkieee(&rmin,idrstmpl+0,1);   // ensure reference value is IEEE format
398       idrstmpl[3]=nbitsgref;
399       idrstmpl[4]=0;         // original data were reals
400       idrstmpl[5]=1;         // general group splitting
401       idrstmpl[6]=0;         // No internal missing values
402       idrstmpl[7]=0;         // Primary missing value
403       idrstmpl[8]=0;         // secondary missing value
404       idrstmpl[9]=ngroups;          // Number of groups
405       idrstmpl[10]=ngwidthref;       // reference for group widths
406       idrstmpl[11]=nbitsgwidth;      // num bits used for group widths
407       idrstmpl[12]=nglenref;         // Reference for group lengths
408       idrstmpl[13]=1;                // length increment for group lengths
409       idrstmpl[14]=nglenlast;        // True length of last group
410       idrstmpl[15]=nbitsglen;        // num bits used for group lengths
411       if (idrsnum == 3) {
412          idrstmpl[17]=nbitsd/8;      // num bits used for extra spatial
413                                      // differencing values
414       }
415 
416 }
417