NCEPLIBS-g2c  1.7.0
misspack.c
Go to the documentation of this file.
1 
7 #include <stdlib.h>
8 #include <math.h>
9 #include "grib2_int.h"
10 
41 void
42 misspack(float *fld, g2int ndpts, g2int idrsnum, g2int *idrstmpl,
43  unsigned char *cpack, g2int *lcpack)
44 {
45  g2int *ifld, *ifldmiss, *jfld;
46  g2int *jmin, *jmax, *lbit;
47  static g2int zero = 0;
48  g2int *gref, *gwidth, *glen;
49  g2int glength, grpwidth;
50  g2int i, n, iofst, imin, ival1, ival2, isd, minsd, nbitsd = 0;
51  g2int nbitsgref, left, iwmax, ngwidthref, nbitsgwidth, ilmax;
52  g2int nglenref, nglenlast, nbitsglen;
53  g2int j, missopt, nonmiss, itemp, maxorig, nbitorig, miss1, miss2;
54  g2int ngroups, ng, num0, num1, num2;
55  g2int imax, lg, mtemp, ier, igmax;
56  g2int kfildo, minpk, inc, maxgrps, ibit, jbit, kbit, novref, lbitref;
57  float rmissp, rmisss, bscale, dscale, 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  missopt = idrstmpl[6];
64  if (missopt != 1 && missopt != 2)
65  {
66  printf("misspack: Unrecognized option.\n");
67  *lcpack = -1;
68  return;
69  }
70  else
71  { /* Get missing values */
72  rdieee(idrstmpl + 7, &rmissp, 1);
73  if (missopt == 2)
74  rdieee(idrstmpl + 8, &rmisss, 1);
75  }
76 
77  /* Find min value of non-missing values in the data, AND set up
78  * missing value mapping of the field. */
79  ifldmiss = calloc(ndpts, sizeof(g2int));
80  rmin = 1E+37;
81  if (missopt == 1)
82  { /* Primary missing value only */
83  for (j = 0; j < ndpts; j++)
84  {
85  if (fld[j] == rmissp)
86  {
87  ifldmiss[j] = 1;
88  }
89  else
90  {
91  ifldmiss[j] = 0;
92  if (fld[j] < rmin)
93  rmin = fld[j];
94  }
95  }
96  }
97  if (missopt == 2)
98  { /* Primary and secondary missing values */
99  for (j = 0; j < ndpts; j++)
100  {
101  if (fld[j] == rmissp)
102  {
103  ifldmiss[j] = 1;
104  }
105  else if (fld[j] == rmisss)
106  {
107  ifldmiss[j] = 2;
108  }
109  else
110  {
111  ifldmiss[j] = 0;
112  if (fld[j] < rmin)
113  rmin = fld[j];
114  }
115  }
116  }
117 
118  /* Allocate work arrays: Note: -ifldmiss[j],j = 0,ndpts-1 is a map
119  * of original field indicating which of the original data values
120  * are primary missing (1), sencondary missing (2) or non-missing
121  * (0). -jfld[j],j = 0,nonmiss-1 is a subarray of just the
122  * non-missing values from the original field. */
123  iofst = 0;
124  ifld = calloc(ndpts, sizeof(g2int));
125  jfld = calloc(ndpts, sizeof(g2int));
126  gref = calloc(ndpts, sizeof(g2int));
127  gwidth = calloc(ndpts, sizeof(g2int));
128  glen = calloc(ndpts, sizeof(g2int));
129 
130  /* Scale original data. */
131  nonmiss = 0;
132  if (idrstmpl[1] == 0)
133  { /* No binary scaling */
134  imin = (g2int)rint(rmin * dscale);
135  rmin = (float)imin;
136  for (j = 0; j < ndpts; j++)
137  {
138  if (ifldmiss[j] == 0)
139  {
140  jfld[nonmiss] = (g2int)rint(fld[j] * dscale) - imin;
141  nonmiss++;
142  }
143  }
144  }
145  else
146  { /* Use binary scaling factor */
147  rmin = rmin * dscale;
148  for (j = 0; j < ndpts; j++)
149  {
150  if (ifldmiss[j] == 0)
151  {
152  jfld[nonmiss] = (g2int)rint(((fld[j] * dscale) - rmin) * bscale);
153  nonmiss++;
154  }
155  }
156  }
157 
158  /* Calculate Spatial differences, if using DRS Template 5.3. */
159  if (idrsnum == 3)
160  { /* spatial differences */
161  if (idrstmpl[16] != 1 && idrstmpl[16] != 2)
162  idrstmpl[16] = 2;
163  if (idrstmpl[16] == 1)
164  { /* first order */
165  ival1 = jfld[0];
166  for (j = nonmiss - 1; j > 0; j--)
167  jfld[j] = jfld[j] - jfld[j - 1];
168  jfld[0] = 0;
169  }
170  else if (idrstmpl[16] == 2)
171  { /* second order */
172  ival1 = jfld[0];
173  ival2 = jfld[1];
174  for (j = nonmiss - 1; j > 1; j--)
175  jfld[j] = jfld[j] - (2 * jfld[j - 1]) + jfld[j - 2];
176  jfld[0] = 0;
177  jfld[1] = 0;
178  }
179 
180  /* Subtract min value from spatial diff field. */
181  isd = idrstmpl[16];
182  minsd = jfld[isd];
183  for (j = isd; j < nonmiss; j++)
184  if (jfld[j] < minsd)
185  minsd = jfld[j];
186  for (j = isd; j < nonmiss; j++)
187  jfld[j] = jfld[j] - minsd;
188 
189  /* Find num of bits need to store minsd and add 1 extra bit to
190  * indicate sign. */
191  temp = log((double)(abs(minsd) + 1)) / alog2;
192  nbitsd = (g2int)ceil(temp) + 1;
193 
194  /* Find num of bits need to store ifld[0] (and ifld[1] if
195  * using 2nd order differencing). */
196  maxorig = ival1;
197  if (idrstmpl[16] == 2 && ival2 > ival1)
198  maxorig = ival2;
199  temp = log((double)(maxorig + 1)) / alog2;
200  nbitorig = (g2int)ceil(temp) + 1;
201  if (nbitorig > nbitsd)
202  nbitsd = nbitorig;
203 
204  /* increase number of bits to even multiple of 8 (octet) */
205  if (nbitsd % 8)
206  nbitsd = nbitsd + (8 - (nbitsd % 8));
207 
208  /* Store extra spatial differencing info into the packed data
209  * section. */
210  if (nbitsd != 0)
211  {
212  /* pack first original value */
213  if (ival1 >= 0) {
214  sbit(cpack, &ival1, iofst, nbitsd);
215  iofst = iofst + nbitsd;
216  }
217  else
218  {
219  sbit(cpack, &one, iofst, 1);
220  iofst = iofst + 1;
221  itemp = abs(ival1);
222  sbit(cpack, &itemp, iofst, nbitsd-1);
223  iofst = iofst + nbitsd - 1;
224  }
225  if (idrstmpl[16] == 2)
226  {
227  /* pack second original value */
228  if (ival2 >= 0)
229  {
230  sbit(cpack, &ival2, iofst, nbitsd);
231  iofst = iofst + nbitsd;
232  }
233  else
234  {
235  sbit(cpack, &one, iofst, 1);
236  iofst = iofst + 1;
237  itemp = abs(ival2);
238  sbit(cpack, &itemp, iofst, nbitsd-1);
239  iofst = iofst + nbitsd - 1;
240  }
241  }
242  /* pack overall min of spatial differences */
243  if (minsd >= 0)
244  {
245  sbit(cpack, &minsd, iofst, nbitsd);
246  iofst = iofst + nbitsd;
247  }
248  else
249  {
250  sbit(cpack, &one, iofst, 1);
251  iofst = iofst + 1;
252  itemp = abs(minsd);
253  sbit(cpack, &itemp, iofst, nbitsd-1);
254  iofst = iofst + nbitsd - 1;
255  }
256  }
257  } /* end of spatial diff section */
258 
259  /* Expand non-missing data values to original grid. */
260  miss1 = jfld[0];
261  for (j = 0; j < nonmiss; j++)
262  if (jfld[j] < miss1)
263  miss1 = jfld[j];
264  miss1--;
265  miss2 = miss1-1;
266  n = 0;
267  for (j = 0; j < ndpts; j++)
268  {
269  if (ifldmiss[j] == 0)
270  {
271  ifld[j] = jfld[n];
272  n++;
273  }
274  else if (ifldmiss[j] == 1)
275  {
276  ifld[j] = miss1;
277  }
278  else if (ifldmiss[j] == 2)
279  {
280  ifld[j] = miss2;
281  }
282  }
283 
284  /* Determine Groups to be used. Use Dr. Glahn's algorithm for
285  * determining grouping. */
286  kfildo = 6;
287  minpk = 10;
288  inc = 1;
289  maxgrps = (ndpts / minpk) + 1;
290  jmin = calloc(maxgrps, sizeof(g2int));
291  jmax = calloc(maxgrps, sizeof(g2int));
292  lbit = calloc(maxgrps, sizeof(g2int));
293  pack_gp(&kfildo, ifld, &ndpts, &missopt, &minpk, &inc, &miss1, &miss2,
294  jmin, jmax, lbit, glen, &maxgrps, &ngroups, &ibit, &jbit,
295  &kbit, &novref, &lbitref, &ier);
296  for (ng = 0; ng < ngroups; ng++)
297  glen[ng] = glen[ng] + novref;
298  free(jmin);
299  free(jmax);
300  free(lbit);
301 
302  /* For each group, find the group's reference value (min) and the
303  * number of bits needed to hold the remaining values. */
304  n = 0;
305  for (ng = 0; ng < ngroups; ng++)
306  {
307  /* how many of each type? */
308  num0 = num1 = num2 = 0;
309  for (j = n; j < n + glen[ng]; j++)
310  {
311  if (ifldmiss[j] == 0)
312  num0++;
313  if (ifldmiss[j] == 1)
314  num1++;
315  if (ifldmiss[j] == 2)
316  num2++;
317  }
318  if (num0 == 0)
319  { /* all missing values */
320  if (num1 == 0)
321  { /* all secondary missing */
322  gref[ng] = -2;
323  gwidth[ng] = 0;
324  }
325  else if (num2 == 0)
326  { /* all primary missing */
327  gref[ng] = -1;
328  gwidth[ng] = 0;
329  }
330  else
331  { /* both primary and secondary */
332  gref[ng] = 0;
333  gwidth[ng] = 1;
334  }
335  }
336  else
337  { /* contains some non-missing data */
338  /* find max and min values of group */
339  gref[ng] = 2147483647;
340  imax = -2147483647;
341  j = n;
342  for (lg = 0; lg < glen[ng]; lg++)
343  {
344  if (ifldmiss[j] == 0)
345  {
346  if (ifld[j] < gref[ng])
347  gref[ng] = ifld[j];
348  if (ifld[j] > imax)
349  imax = ifld[j];
350  }
351  j++;
352  }
353  if (missopt == 1)
354  imax = imax+1;
355  if (missopt == 2)
356  imax = imax+2;
357  /* calc num of bits needed to hold data */
358  if (gref[ng] != imax)
359  {
360  temp = log((double)(imax - gref[ng] + 1)) / alog2;
361  gwidth[ng] = (g2int)ceil(temp);
362  }
363  else
364  {
365  gwidth[ng] = 0;
366  }
367  }
368  /* Subtract min from data */
369  j = n;
370  mtemp = (g2int)int_power(2., gwidth[ng]);
371  for (lg = 0; lg < glen[ng]; lg++)
372  {
373  if (ifldmiss[j] == 0) /* non-missing */
374  ifld[j] = ifld[j] - gref[ng];
375  else if (ifldmiss[j] == 1) /* primary missing */
376  ifld[j] = mtemp - 1;
377  else if (ifldmiss[j] == 2) /* secondary missing */
378  ifld[j] = mtemp - 2;
379  j++;
380  }
381  /* increment fld array counter */
382  n = n + glen[ng];
383  }
384 
385  /* Find max of the group references and calc num of bits needed to
386  * pack each groups reference value, then pack up group reference
387  * values. */
388  igmax = gref[0];
389  for (j = 1; j < ngroups; j++)
390  if (gref[j] > igmax)
391  igmax = gref[j];
392  if (missopt == 1)
393  igmax = igmax + 1;
394  if (missopt == 2)
395  igmax = igmax + 2;
396  if (igmax != 0)
397  {
398  temp = log((double)(igmax + 1)) / alog2;
399  nbitsgref = (g2int)ceil(temp);
400  /* reset the ref values of any "missing only" groups. */
401  mtemp = (g2int)int_power(2., nbitsgref);
402  for (j = 0; j < ngroups; j++)
403  {
404  if (gref[j] == -1)
405  gref[j] = mtemp-1;
406  if (gref[j] == -2)
407  gref[j] = mtemp-2;
408  }
409  sbits(cpack, gref, iofst, nbitsgref, 0, ngroups);
410  itemp = nbitsgref * ngroups;
411  iofst = iofst + itemp;
412  /* Pad last octet with Zeros, if necessary. */
413  if ((itemp % 8) != 0)
414  {
415  left = 8 - (itemp % 8);
416  sbit(cpack, &zero, iofst, left);
417  iofst = iofst + left;
418  }
419  }
420  else
421  {
422  nbitsgref = 0;
423  }
424 
425  /* Find max/min of the group widths and calc num of bits needed to
426  * pack each groups width value, then pack up group width
427  * values. */
428  iwmax = gwidth[0];
429  ngwidthref = gwidth[0];
430  for (j = 1; j < ngroups; j++)
431  {
432  if (gwidth[j] > iwmax)
433  iwmax = gwidth[j];
434  if (gwidth[j] < ngwidthref)
435  ngwidthref = gwidth[j];
436  }
437  if (iwmax != ngwidthref)
438  {
439  temp = log((double)(iwmax - ngwidthref + 1)) / alog2;
440  nbitsgwidth = (g2int)ceil(temp);
441  for (i = 0; i<ngroups; i++)
442  gwidth[i] = gwidth[i]-ngwidthref;
443  sbits(cpack, gwidth, iofst, nbitsgwidth, 0, ngroups);
444  itemp = nbitsgwidth * ngroups;
445  iofst = iofst + itemp;
446  /* Pad last octet with Zeros, if necessary. */
447  if ((itemp %8) != 0)
448  {
449  left = 8 - (itemp % 8);
450  sbit(cpack, &zero, iofst, left);
451  iofst = iofst + left;
452  }
453  }
454  else
455  {
456  nbitsgwidth = 0;
457  for (i = 0; i < ngroups; i++)
458  gwidth[i] = 0;
459  }
460 
461  /* Find max/min of the group lengths and calc num of bits needed
462  * to pack each groups length value, then pack up group length
463  * values. */
464  ilmax = glen[0];
465  nglenref = glen[0];
466  for (j = 1; j < ngroups - 1; j++)
467  {
468  if (glen[j] > ilmax)
469  ilmax = glen[j];
470  if (glen[j] < nglenref)
471  nglenref = glen[j];
472  }
473  nglenlast = glen[ngroups - 1];
474  if (ilmax != nglenref)
475  {
476  temp = log((double)(ilmax - nglenref + 1)) / alog2;
477  nbitsglen = (g2int)ceil(temp);
478  for (i = 0; i < ngroups - 1; i++)
479  glen[i] = glen[i] - nglenref;
480  sbits(cpack, glen, iofst, nbitsglen, 0, ngroups);
481  itemp = nbitsglen * ngroups;
482  iofst = iofst + itemp;
483  /* Pad last octet with Zeros, if necessary. */
484  if ((itemp % 8) != 0)
485  {
486  left = 8 - (itemp % 8);
487  sbit(cpack, &zero, iofst, left);
488  iofst = iofst + left;
489  }
490  }
491  else
492  {
493  nbitsglen = 0;
494  for (i = 0; i < ngroups; i++)
495  glen[i] = 0;
496  }
497 
498  /* For each group, pack data values. */
499  n = 0;
500  for (ng = 0; ng < ngroups; ng++)
501  {
502  glength = glen[ng] + nglenref;
503  if (ng == (ngroups - 1))
504  glength = nglenlast;
505  grpwidth = gwidth[ng] + ngwidthref;
506  if (grpwidth != 0)
507  {
508  sbits(cpack, ifld + n, iofst, grpwidth, 0, glength);
509  iofst = iofst + (grpwidth * glength);
510  }
511  n = n + glength;
512  }
513 
514  /* Pad last octet with Zeros, if necessary, */
515  if ((iofst % 8) != 0)
516  {
517  left = 8 - (iofst % 8);
518  sbit(cpack, &zero, iofst, left);
519  iofst = iofst + left;
520  }
521  *lcpack = iofst / 8;
522 
523  if (ifld)
524  free(ifld);
525  if (jfld)
526  free(jfld);
527  if (ifldmiss)
528  free(ifldmiss);
529  if (gref)
530  free(gref);
531  if (gwidth)
532  free(gwidth);
533  if (glen)
534  free(glen);
535 
536  /* Fill in ref value and number of bits in Template 5.2. */
537  mkieee(&rmin, idrstmpl, 1); /* ensure reference value is IEEE format */
538  idrstmpl[3] = nbitsgref;
539  idrstmpl[4] = 0; /* original data were reals */
540  idrstmpl[5] = 1; /* general group splitting */
541  idrstmpl[9] = ngroups; /* Number of groups */
542  idrstmpl[10] = ngwidthref; /* reference for group widths */
543  idrstmpl[11] = nbitsgwidth; /* num bits used for group widths */
544  idrstmpl[12] = nglenref; /* Reference for group lengths */
545  idrstmpl[13] = 1; /* length increment for group lengths */
546  idrstmpl[14] = nglenlast; /* True length of last group */
547  idrstmpl[15] = nbitsglen; /* num bits used for group lengths */
548  if (idrsnum == 3)
549  idrstmpl[17] = nbitsd / 8; /* num bits used for extra spatial differencing values */
550 }
rdieee
void rdieee(g2int *rieee, float *a, g2int num)
This subroutine reads a list of real values in 32-bit IEEE floating point format.
Definition: rdieee.c:21
int_power
double int_power(double x, g2int y)
Function similar to C pow() power function.
Definition: int_power.c:18
grib2_int.h
Header file with internal function prototypes NCEPLIBS-g2c library.
sbits
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:114
mkieee
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
pack_gp
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
g2int
int64_t g2int
Long integer type.
Definition: grib2.h:28
misspack
void misspack(float *fld, g2int ndpts, g2int idrsnum, g2int *idrstmpl, unsigned char *cpack, g2int *lcpack)
This function packs up a data field using a complex packing algorithm as defined in the GRIB2 documen...
Definition: misspack.c:42
ALOG2
#define ALOG2
ln(2.0)
Definition: grib2_int.h:21
sbit
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