NCEPLIBS-g2c  1.6.4
compack.c
Go to the documentation of this file.
1 
8 #include <stdlib.h>
9 #include <math.h>
10 #include "grib2.h"
11 
41 void
42 compack(g2float *fld, g2int ndpts, g2int idrsnum, g2int *idrstmpl,
43  unsigned char *cpack, g2int *lcpack)
44 {
45 
46  static g2int zero = 0;
47  g2int *ifld, *gref, *glen, *gwidth;
48  g2int *jmin, *jmax, *lbit;
49  g2int i, j, n, imin, imax, left;
50  g2int isd, itemp, ilmax, ngwidthref = 0, nbitsgwidth = 0;
51  g2int nglenref = 0, nglenlast = 0, iofst, ival1, ival2;
52  g2int minsd, nbitsd = 0, maxorig, nbitorig, ngroups;
53  g2int lg, ng, igmax, iwmax, nbitsgref;
54  g2int glength, grpwidth, nbitsglen = 0;
55  g2int kfildo, minpk, inc, maxgrps, ibit, jbit, kbit, novref, lbitref;
56  g2int missopt, miss1, miss2, ier;
57  g2float bscale, dscale, rmax, rmin, temp;
58  static g2int simple_alg = 0;
59  static g2float alog2 = 0.69314718; /* ln(2.0) */
60  static g2int one = 1;
61 
62  bscale = int_power(2.0, -idrstmpl[1]);
63  dscale = int_power(10.0, idrstmpl[2]);
64 
65  /* Find max and min values in the data. */
66  rmax = fld[0];
67  rmin = fld[0];
68  for (j = 1; j < ndpts; j++)
69  {
70  if (fld[j] > rmax) rmax = fld[j];
71  if (fld[j] < rmin) rmin = fld[j];
72  }
73 
74  /* If max and min values are not equal, pack up field. If they are
75  * equal, we have a constant field, and the reference value (rmin)
76  * is the value for each point in the field and set nbits to 0. */
77  if (rmin != rmax)
78  {
79  iofst = 0;
80  ifld = calloc(ndpts, sizeof(g2int));
81  gref = calloc(ndpts, sizeof(g2int));
82  gwidth = calloc(ndpts, sizeof(g2int));
83  glen = calloc(ndpts, sizeof(g2int));
84 
85  /* Scale original data. */
86  if (idrstmpl[1] == 0)
87  { /* No binary scaling. */
88  imin = (g2int)rint(rmin*dscale);
89  /*imax = (g2int)rint(rmax*dscale); */
90  rmin = (g2float)imin;
91  for (j = 0; j < ndpts; j++)
92  ifld[j] = (g2int)rint(fld[j] * dscale) - imin;
93  }
94  else
95  { /* Use binary scaling factor */
96  rmin = rmin * dscale;
97  /*rmax = rmax*dscale; */
98  for (j = 0; j < ndpts; j++)
99  ifld[j] = (g2int)rint(((fld[j] * dscale) - rmin) * bscale);
100  }
101 
102  /* Calculate Spatial differences, if using DRS Template
103  * 5.3. */
104  if (idrsnum == 3)
105  { /* spatial differences */
106  if (idrstmpl[16] !=1 && idrstmpl[16] != 2)
107  idrstmpl[16] = 1;
108  if (idrstmpl[16] == 1)
109  { /* first order */
110  ival1 = ifld[0];
111  for (j = ndpts-1; j > 0; j--)
112  ifld[j] = ifld[j] - ifld[j - 1];
113  ifld[0] = 0;
114  }
115  else if (idrstmpl[16] == 2)
116  { /* second order */
117  ival1 = ifld[0];
118  ival2 = ifld[1];
119  for (j = ndpts - 1; j > 1; j--)
120  ifld[j] = ifld[j] - (2 * ifld[j - 1]) + ifld[j - 2];
121  ifld[0] = 0;
122  ifld[1] = 0;
123  }
124 
125  /* Subtract min value from spatial diff field. */
126  isd = idrstmpl[16];
127  minsd = ifld[isd];
128  for (j = isd; j < ndpts; j++)
129  if (ifld[j] < minsd)
130  minsd = ifld[j];
131  for (j = isd; j < ndpts; j++)
132  ifld[j] = ifld[j] - minsd;
133 
134  /* Find num of bits need to store minsd and add 1 extra bit to indicate sign. */
135  temp = log((double)(abs(minsd) + 1)) / alog2;
136  nbitsd = (g2int)ceil(temp) + 1;
137 
138  /* Find num of bits need to store ifld[0] (and ifld[1] if
139  * using 2nd order differencing). */
140  maxorig = ival1;
141  if (idrstmpl[16] == 2 && ival2 > ival1)
142  maxorig = ival2;
143  temp = log((double)(maxorig + 1)) / alog2;
144  nbitorig = (g2int)ceil(temp) + 1;
145  if (nbitorig > nbitsd)
146  nbitsd = nbitorig;
147 
148  /* Increase number of bits to even multiple of 8 (octet). */
149  if ((nbitsd % 8) != 0)
150  nbitsd = nbitsd+(8-(nbitsd%8));
151 
152  /* Store extra spatial differencing info into the packed
153  * data section. */
154  if (nbitsd != 0)
155  {
156  /* pack first original value */
157  if (ival1 >= 0)
158  {
159  sbit(cpack, &ival1, iofst, nbitsd);
160  iofst = iofst+nbitsd;
161  }
162  else
163  {
164  sbit(cpack, &one, iofst, 1);
165  iofst = iofst + 1;
166  itemp = abs(ival1);
167  sbit(cpack, &itemp, iofst, nbitsd-1);
168  iofst = iofst + nbitsd - 1;
169  }
170  if (idrstmpl[16] == 2)
171  {
172  /* pack second original value */
173  if (ival2 >= 0)
174  {
175  sbit(cpack, &ival2, iofst, nbitsd);
176  iofst = iofst + nbitsd;
177  }
178  else
179  {
180  sbit(cpack, &one, iofst, 1);
181  iofst = iofst + 1;
182  itemp = abs(ival2);
183  sbit(cpack, &itemp, iofst, nbitsd - 1);
184  iofst = iofst + nbitsd - 1;
185  }
186  }
187 
188  /* pack overall min of spatial differences */
189  if (minsd >= 0)
190  {
191  sbit(cpack, &minsd, iofst, nbitsd);
192  iofst = iofst + nbitsd;
193  }
194  else
195  {
196  sbit(cpack, &one, iofst, 1);
197  iofst = iofst + 1;
198  itemp = abs(minsd);
199  sbit(cpack, &itemp, iofst, nbitsd - 1);
200  iofst = iofst + nbitsd - 1;
201  }
202  }
203  } /* end of spatial diff section */
204 
205  /* Determine Groups to be used. */
206  if (simple_alg == 1)
207  {
208  /* Set group length to 10; calculate number of groups and
209  * length of last group. */
210  ngroups = ndpts / 10;
211  for (j = 0; j < ngroups; j++)
212  glen[j] = 10;
213  itemp = ndpts % 10;
214  if (itemp != 0)
215  {
216  ngroups = ngroups + 1;
217  glen[ngroups - 1] = itemp;
218  }
219  }
220  else
221  {
222  /* Use Dr. Glahn's algorithm for determining grouping. */
223  kfildo = 6;
224  minpk = 10;
225  inc = 1;
226  maxgrps = (ndpts / minpk) + 1;
227  jmin = calloc(maxgrps, sizeof(g2int));
228  jmax = calloc(maxgrps, sizeof(g2int));
229  lbit = calloc(maxgrps, sizeof(g2int));
230  missopt = 0;
231  pack_gp(&kfildo, ifld, &ndpts, &missopt, &minpk, &inc, &miss1, &miss2,
232  jmin, jmax, lbit, glen, &maxgrps, &ngroups, &ibit, &jbit,
233  &kbit, &novref, &lbitref, &ier);
234  for (ng = 0; ng<ngroups; ng++)
235  glen[ng] = glen[ng] + novref;
236  free(jmin);
237  free(jmax);
238  free(lbit);
239  }
240 
241  /* For each group, find the group's reference value and the
242  * number of bits needed to hold the remaining values. */
243  n = 0;
244  for (ng = 0; ng < ngroups; ng++)
245  {
246  /* find max and min values of group */
247  gref[ng] = ifld[n];
248  imax = ifld[n];
249  j = n + 1;
250  for (lg = 1; lg < glen[ng]; lg++)
251  {
252  if (ifld[j] < gref[ng])
253  gref[ng] = ifld[j];
254  if (ifld[j] > imax)
255  imax = ifld[j];
256  j++;
257  }
258 
259  /* calc num of bits needed to hold data */
260  if (gref[ng] != imax)
261  {
262  temp = log((double)(imax - gref[ng] + 1))/alog2;
263  gwidth[ng] = (g2int)ceil(temp);
264  }
265  else
266  gwidth[ng] = 0;
267  /* Subtract min from data */
268  j = n;
269  for (lg = 0; lg < glen[ng]; lg++)
270  {
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
279  * needed to pack each groups reference value, then pack up
280  * group reference values. */
281  igmax = gref[0];
282  for (j = 1; j < ngroups; j++)
283  if (gref[j] > igmax)
284  igmax = gref[j];
285  if (igmax != 0)
286  {
287  temp = log((double)(igmax + 1)) / alog2;
288  nbitsgref = (g2int)ceil(temp);
289  sbits(cpack, gref, iofst, nbitsgref, 0, ngroups);
290  itemp = nbitsgref * ngroups;
291  iofst = iofst + itemp;
292  /* Pad last octet with Zeros, if necessary. */
293  if ((itemp % 8) != 0)
294  {
295  left = 8 - (itemp % 8);
296  sbit(cpack, &zero, iofst, left);
297  iofst = iofst + left;
298  }
299  }
300  else
301  nbitsgref = 0;
302 
303  /* Find max/min of the group widths and calc num of bits
304  * needed to pack each groups width value, then pack up group
305  * width values. */
306  iwmax = gwidth[0];
307  ngwidthref = gwidth[0];
308  for (j = 1; j < ngroups; j++)
309  {
310  if (gwidth[j] > iwmax)
311  iwmax = gwidth[j];
312  if (gwidth[j] < ngwidthref)
313  ngwidthref = gwidth[j];
314  }
315  if (iwmax != ngwidthref)
316  {
317  temp = log((double)(iwmax - ngwidthref +1)) / alog2;
318  nbitsgwidth = (g2int)ceil(temp);
319  for (i = 0; i < ngroups; i++)
320  gwidth[i] = gwidth[i] - ngwidthref;
321  sbits(cpack, gwidth, iofst, nbitsgwidth, 0, ngroups);
322  itemp = nbitsgwidth * ngroups;
323  iofst = iofst + itemp;
324  /* Pad last octet with Zeros, if necessary. */
325  if ((itemp % 8) != 0)
326  {
327  left = 8 - (itemp % 8);
328  sbit(cpack, &zero, iofst, left);
329  iofst = iofst + left;
330  }
331  }
332  else
333  {
334  nbitsgwidth = 0;
335  for (i = 0; i < ngroups; i++)
336  gwidth[i] = 0;
337  }
338 
339  /* Find max/min of the group lengths and calc num of bits
340  * needed to pack each groups length value, then pack up group
341  * length values. */
342  ilmax = glen[0];
343  nglenref = glen[0];
344  for (j = 1; j < ngroups - 1; j++)
345  {
346  if (glen[j] > ilmax)
347  ilmax = glen[j];
348  if (glen[j] < nglenref)
349  nglenref = glen[j];
350  }
351  nglenlast = glen[ngroups - 1];
352  if (ilmax != nglenref)
353  {
354  temp = log((double)(ilmax - nglenref + 1)) / alog2;
355  nbitsglen = (g2int)ceil(temp);
356  for (i = 0; i < ngroups - 1; i++)
357  glen[i] = glen[i] - nglenref;
358  sbits(cpack, glen, iofst, nbitsglen, 0, ngroups);
359  itemp = nbitsglen * ngroups;
360  iofst = iofst + itemp;
361  /* Pad last octet with Zeros, if necessary, */
362  if ((itemp % 8) != 0)
363  {
364  left = 8 - (itemp % 8);
365  sbit(cpack, &zero, iofst, left);
366  iofst = iofst + left;
367  }
368  }
369  else
370  {
371  nbitsglen = 0;
372  for (i = 0; i < ngroups; i++)
373  glen[i] = 0;
374  }
375 
376  /* For each group, pack data values. */
377  n = 0;
378  for (ng = 0; ng < ngroups; ng++)
379  {
380  glength = glen[ng] + nglenref;
381  if (ng == (ngroups - 1))
382  glength = nglenlast;
383  grpwidth = gwidth[ng] + ngwidthref;
384  if (grpwidth != 0)
385  {
386  sbits(cpack, ifld + n, iofst, grpwidth, 0, glength);
387  iofst = iofst + (grpwidth * glength);
388  }
389  n = n + glength;
390  }
391  /* Pad last octet with Zeros, if necessary. */
392  if ((iofst % 8) != 0)
393  {
394  left = 8 - (iofst % 8);
395  sbit(cpack, &zero, iofst, left);
396  iofst = iofst + left;
397  }
398  *lcpack = iofst / 8;
399 
400  if (ifld)
401  free(ifld);
402  if (gref)
403  free(gref);
404  if (gwidth)
405  free(gwidth);
406  if (glen)
407  free(glen);
408  }
409  else
410  { /* Constant field (max = min) */
411  *lcpack = 0;
412  nbitsgref = 0;
413  ngroups = 0;
414  }
415 
416  /* Fill in ref value and number of bits in Template 5.2. */
417 
418  /* Ensure reference value is IEEE format. */
419  mkieee(&rmin, idrstmpl, 1);
420  idrstmpl[3] = nbitsgref;
421  idrstmpl[4] = 0; /* original data were reals */
422  idrstmpl[5] = 1; /* general group splitting */
423  idrstmpl[6] = 0; /* No internal missing values */
424  idrstmpl[7] = 0; /* Primary missing value */
425  idrstmpl[8] = 0; /* secondary missing value */
426  idrstmpl[9] = ngroups; /* Number of groups */
427  idrstmpl[10] = ngwidthref; /* reference for group widths */
428  idrstmpl[11] = nbitsgwidth; /* num bits used for group widths */
429  idrstmpl[12] = nglenref; /* Reference for group lengths */
430  idrstmpl[13] = 1; /* length increment for group lengths */
431  idrstmpl[14] = nglenlast; /* True length of last group */
432  idrstmpl[15] = nbitsglen; /* num bits used for group lengths */
433  if (idrsnum == 3)
434  {
435  idrstmpl[17] = nbitsd / 8; /* num bits used for extra spatial */
436  /* differencing values */
437  }
438 }
void compack(g2float *fld, g2int ndpts, g2int idrsnum, g2int *idrstmpl, unsigned char *cpack, g2int *lcpack)
This subroutine packs up a data field using a complex packing algorithm as defined in the GRIB2 docum...
Definition: compack.c:42
void sbit(unsigned char *out, g2int *in, g2int iskip, g2int nbyte)
Store bits - put arbitrary size values into a packed bit string, taking the low order bits from each ...
Definition: gbits.c:38
void sbits(unsigned char *out, g2int *in, g2int iskip, g2int nbyte, g2int nskip, g2int n)
Store bits - put arbitrary size values into a packed bit string, taking the low order bits from each ...
Definition: gbits.c:114
Header file for NCEPLIBS-g2c library.
float g2float
Float type.
Definition: grib2.h:22
int64_t g2int
Long integer type.
Definition: grib2.h:20
double int_power(double x, g2int y)
Function similar to C pow() power function.
Definition: int_power.c:17
void mkieee(g2float *a, g2int *rieee, g2int num)
This subroutine stores a list of real values in 32-bit IEEE floating point format.
Definition: mkieee.c:21
int pack_gp(integer *kfildo, integer *ic, integer *nxy, integer *is523, integer *minpk, integer *inc, integer *missp, integer *misss, integer *jmin, integer *jmax, integer *lbit, integer *nov, integer *ndg, integer *lx, integer *ibit, integer *jbit, integer *kbit, integer *novref, integer *lbitref, integer *ier)
Determines groups of variable size, but at least of size minpk, the associated max (jmax( )) and min ...
Definition: pack_gp.c:256