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