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