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