NCEPLIBS-g2c  1.8.0
comunpack.c
Go to the documentation of this file.
1 
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include "grib2_int.h"
9 
41 int
42 comunpack(unsigned char *cpack, g2int lensec, g2int idrsnum,
43  g2int *idrstmpl, g2int ndpts, float *fld)
44 {
45  g2int nbitsd=0, isign;
46  g2int j, iofst, ival1, ival2, minsd, itemp, l, k, n, non=0;
47  g2int *ifld, *ifldmiss=0;
48  g2int *gref, *gwidth, *glen;
49  g2int itype, ngroups, nbitsgref, nbitsgwidth, nbitsglen;
50  g2int msng1, msng2;
51  float ref, bscale, dscale, rmiss1, rmiss2;
52  g2int totBit, totLen;
53 
54  LOG((3, "comunpack lensec %ld idrsnum %ld ndpts %ld", lensec, idrsnum, ndpts));
55 
56  rdieee(idrstmpl, &ref, 1);
57  bscale = (float)int_power(2.0, idrstmpl[1]);
58  dscale = (float)int_power(10.0, -idrstmpl[2]);
59  nbitsgref = idrstmpl[3];
60  itype = idrstmpl[4];
61  ngroups = idrstmpl[9];
62  nbitsgwidth = idrstmpl[11];
63  nbitsglen = idrstmpl[15];
64  if (idrsnum == 3)
65  nbitsd=idrstmpl[17] * 8;
66 
67  /* Constant field */
68  if (ngroups == 0)
69  {
70  for (j = 0; j < ndpts; j++)
71  fld[j] = ref;
72  return(0);
73  }
74 
75  iofst = 0;
76  ifld = (g2int *)calloc(ndpts, sizeof(g2int));
77  gref = (g2int *)calloc(ngroups, sizeof(g2int));
78  gwidth = (g2int *)calloc(ngroups, sizeof(g2int));
79 
80  /* Get missing values, if supplied */
81  if (idrstmpl[6] == 1)
82  {
83  if (itype == 0)
84  rdieee(idrstmpl+7,&rmiss1,1);
85  else
86  rmiss1 = (float)idrstmpl[7];
87  }
88  if (idrstmpl[6] == 2)
89  {
90  if (itype == 0)
91  {
92  rdieee(idrstmpl+7,&rmiss1,1);
93  rdieee(idrstmpl+8,&rmiss2,1);
94  }
95  else {
96  rmiss1 = (float)idrstmpl[7];
97  rmiss2 = (float)idrstmpl[8];
98  }
99  }
100 
101  /* Extract Spatial differencing values, if using DRS Template 5.3 */
102  if (idrsnum == 3)
103  {
104  if (nbitsd != 0)
105  {
106  /* wne mistake here shoujld be unsigned int */
107  gbit(cpack, &ival1, iofst, nbitsd);
108  iofst = iofst + nbitsd;
109  if (idrstmpl[16] == 2)
110  {
111  /* wne mistake here shoujld be unsigned int */
112  gbit(cpack, &ival2, iofst, nbitsd);
113  iofst = iofst + nbitsd;
114  }
115  gbit(cpack, &isign, iofst, 1);
116  iofst = iofst + 1;
117  gbit(cpack, &minsd, iofst, nbitsd - 1);
118  iofst = iofst + nbitsd - 1;
119  if (isign == 1)
120  minsd = -minsd;
121  }
122  else {
123  ival1 = 0;
124  ival2 = 0;
125  minsd = 0;
126  }
127  }
128 
129  /* Extract Each Group's reference value */
130  if (nbitsgref != 0)
131  {
132  gbits(cpack, gref, iofst, nbitsgref, 0, ngroups);
133  itemp = nbitsgref * ngroups;
134  iofst = iofst + itemp;
135  if (itemp % 8 != 0)
136  iofst = iofst + (8 - (itemp % 8));
137  }
138  else
139  {
140  for (j = 0; j < ngroups; j++)
141  gref[j] = 0;
142  }
143 
144  /* Extract Each Group's bit width */
145  if (nbitsgwidth != 0) {
146  gbits(cpack, gwidth, iofst, nbitsgwidth, 0, ngroups);
147  itemp = nbitsgwidth * ngroups;
148  iofst = iofst + itemp;
149  if (itemp % 8 != 0)
150  iofst = iofst + (8 - (itemp % 8));
151  }
152  else {
153  for (j = 0; j < ngroups; j++)
154  gwidth[j] = 0;
155  }
156 
157  for (j = 0; j < ngroups; j++)
158  gwidth[j] = gwidth[j] + idrstmpl[10];
159 
160  /* Extract Each Group's length (number of values in each group) */
161  glen = calloc(ngroups, sizeof(g2int));
162  if (nbitsglen != 0)
163  {
164  gbits(cpack, glen, iofst, nbitsglen, 0, ngroups);
165  itemp = nbitsglen * ngroups;
166  iofst = iofst + itemp;
167  if (itemp % 8 != 0)
168  iofst = iofst + (8 - (itemp % 8));
169  }
170  else
171  {
172  for (j = 0; j < ngroups; j++)
173  glen[j] = 0;
174  }
175  for (j = 0;j<ngroups;j++)
176  glen[j] = (glen[j]*idrstmpl[13])+idrstmpl[12];
177  glen[ngroups-1] = idrstmpl[14];
178 
179  /* Test to see if the group widths and lengths are consistent
180  * with number of values, and length of section 7. */
181  totBit = 0;
182  totLen = 0;
183  for (j = 0; j < ngroups; j++)
184  {
185  totBit += (gwidth[j] * glen[j]);
186  totLen += glen[j];
187  }
188  if (totLen != ndpts)
189  return 1;
190  if (totBit / 8. > lensec)
191  return 1;
192 
193  /* For each group, unpack data values */
194  if (idrstmpl[6] == 0)
195  { /* no missing values */
196  n = 0;
197  for (j = 0; j < ngroups; j++)
198  {
199  if (gwidth[j] != 0)
200  {
201  gbits(cpack, ifld + n, iofst, gwidth[j], 0, glen[j]);
202  for (k = 0; k < glen[j]; k++)
203  {
204  ifld[n] = ifld[n] + gref[j];
205  n = n + 1;
206  }
207  }
208  else
209  {
210  for (l = n; l < n + glen[j]; l++)
211  ifld[l] = gref[j];
212  n = n + glen[j];
213  }
214  iofst = iofst + (gwidth[j] * glen[j]);
215  }
216  }
217  else if (idrstmpl[6] == 1 || idrstmpl[6] == 2)
218  {
219  /* missing values included */
220  ifldmiss = malloc(ndpts * sizeof(g2int));
221  for (j = 0; j < ndpts; j++)
222  ifldmiss[j] = 0;
223  n = 0;
224  non = 0;
225  for (j = 0; j < ngroups; j++)
226  {
227  if (gwidth[j] != 0)
228  {
229  msng1 = (g2int)int_power(2.0, gwidth[j]) - 1;
230  msng2 = msng1 - 1;
231  gbits(cpack, ifld + n, iofst, gwidth[j], 0, glen[j]);
232  iofst = iofst + (gwidth[j] * glen[j]);
233  for (k = 0; k < glen[j]; k++)
234  {
235  if (ifld[n] == msng1)
236  ifldmiss[n] = 1;
237  else if (idrstmpl[6] == 2 && ifld[n] == msng2)
238  ifldmiss[n] = 2;
239  else {
240  ifldmiss[n] = 0;
241  ifld[non++] = ifld[n] + gref[j];
242  }
243  n++;
244  }
245  }
246  else
247  {
248  msng1 = (g2int)int_power(2.0, nbitsgref) -1;
249  msng2 = msng1 - 1;
250  if (gref[j] == msng1)
251  {
252  for (l = n; l < n + glen[j]; l++)
253  ifldmiss[l] = 1;
254  }
255  else if (idrstmpl[6] == 2 && gref[j] == msng2)
256  {
257  for (l = n; l < n + glen[j]; l++)
258  ifldmiss[l] = 2;
259  }
260  else
261  {
262  for (l = n; l < n + glen[j]; l++)
263  ifldmiss[l] = 0;
264  for (l = non; l < non + glen[j]; l++)
265  ifld[l] = gref[j];
266  non += glen[j];
267  }
268  n = n + glen[j];
269  }
270  }
271  }
272 
273  if (gref)
274  free(gref);
275  if (gwidth)
276  free(gwidth);
277  if (glen)
278  free(glen);
279 
280  /* If using spatial differences, add overall min value, and sum up recursively */
281  if (idrsnum == 3)
282  { /* spatial differencing */
283  if (idrstmpl[16] == 1)
284  { /* first order */
285  ifld[0] = ival1;
286  if (idrstmpl[6] == 0)
287  itemp = ndpts; /* no missing values */
288  else
289  itemp = non;
290  for (n = 1; n < itemp; n++)
291  {
292  ifld[n] = ifld[n] + minsd;
293  ifld[n] = ifld[n] + ifld[n - 1];
294  }
295  }
296  else if (idrstmpl[16] == 2)
297  { /* second order */
298  ifld[0] = ival1;
299  ifld[1] = ival2;
300  if (idrstmpl[6] == 0)
301  itemp = ndpts; /* no missing values */
302  else
303  itemp = non;
304  for (n = 2; n < itemp; n++)
305  {
306  ifld[n] = ifld[n] + minsd;
307  ifld[n] = ifld[n] + (2 * ifld[n - 1]) - ifld[n - 2];
308  }
309  }
310  }
311 
312  /* Scale data back to original form */
313  if (idrstmpl[6] == 0)
314  { /* no missing values */
315  for (n = 0; n <ndpts; n++)
316  {
317  fld[n] = (((float)ifld[n] * bscale) + ref) * dscale;
318  }
319  }
320  else if (idrstmpl[6] == 1 || idrstmpl[6] == 2)
321  {
322  /* missing values included */
323  non = 0;
324  for (n = 0; n < ndpts; n++)
325  {
326  if (ifldmiss[n] == 0)
327  {
328  fld[n] = (((float)ifld[non++] * bscale) + ref) * dscale;
329  }
330  else if (ifldmiss[n] == 1)
331  fld[n] = rmiss1;
332  else if (ifldmiss[n] == 2)
333  fld[n] = rmiss2;
334  }
335  if (ifldmiss)
336  free(ifldmiss);
337  }
338 
339  if (ifld)
340  free(ifld);
341 
342  return 0;
343 }
int comunpack(unsigned char *cpack, g2int lensec, g2int idrsnum, g2int *idrstmpl, g2int ndpts, float *fld)
This subroutine unpacks a data field that was packed using a complex packing algorithm as defined in ...
Definition: comunpack.c:42
void gbit(unsigned char *in, g2int *iout, g2int iskip, g2int nbits)
Get bits - unpack bits: Extract arbitrary size values from a packed bit string, right justifying each...
Definition: gbits.c:20
void gbits(unsigned char *in, g2int *iout, g2int iskip, g2int nbits, g2int nskip, g2int n)
Get bits - unpack bits: Extract arbitrary size values from a packed bit string, right justifying each...
Definition: gbits.c:57
int64_t g2int
Long integer type.
Definition: grib2.h:33
Header file with internal function prototypes NCEPLIBS-g2c library.
double int_power(double x, g2int y)
Function similar to C pow() power function.
Definition: int_power.c:18
#define LOG(e)
Ignore logging to stdout.
Definition: grib2_int.h:426
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