/src/gdal/frmts/grib/degrib/g2clib/comunpack.c
Line | Count | Source |
1 | | #include <float.h> |
2 | | #include <limits.h> |
3 | | #include <stdio.h> |
4 | | #include <stdlib.h> |
5 | | #include "grib2.h" |
6 | | |
7 | | #ifndef DoubleToFloatClamp_defined |
8 | | #define DoubleToFloatClamp_defined |
9 | 818 | static float DoubleToFloatClamp(double val) { |
10 | 818 | if (val >= FLT_MAX) return FLT_MAX; |
11 | 818 | if (val <= -FLT_MAX) return -FLT_MAX; |
12 | 818 | return (float)val; |
13 | 818 | } |
14 | | #endif |
15 | | |
16 | | int comunpack(unsigned char *cpack,g2int cpack_length,g2int lensec,g2int idrsnum,g2int *idrstmpl,g2int ndpts,g2float *fld) |
17 | | ////$$$ SUBPROGRAM DOCUMENTATION BLOCK |
18 | | // . . . . |
19 | | // SUBPROGRAM: comunpack |
20 | | // PRGMMR: Gilbert ORG: W/NP11 DATE: 2002-10-29 |
21 | | // |
22 | | // ABSTRACT: This subroutine unpacks a data field that was packed using a |
23 | | // complex packing algorithm as defined in the GRIB2 documentation, |
24 | | // using info from the GRIB2 Data Representation Template 5.2 or 5.3. |
25 | | // Supports GRIB2 complex packing templates with or without |
26 | | // spatial differences (i.e. DRTs 5.2 and 5.3). |
27 | | // |
28 | | // PROGRAM HISTORY LOG: |
29 | | // 2002-10-29 Gilbert |
30 | | // 2004-12-16 Gilbert - Added test ( provided by Arthur Taylor/MDL ) |
31 | | // to verify that group widths and lengths are |
32 | | // consistent with section length. |
33 | | // |
34 | | // USAGE: int comunpack(unsigned char *cpack,g2int lensec,g2int idrsnum, |
35 | | // g2int *idrstmpl, g2int ndpts,g2float *fld) |
36 | | // INPUT ARGUMENT LIST: |
37 | | // cpack - pointer to the packed data field. |
38 | | // lensec - length of section 7 (used for error checking). |
39 | | // idrsnum - Data Representation Template number 5.N |
40 | | // Must equal 2 or 3. |
41 | | // idrstmpl - pointer to the array of values for Data Representation |
42 | | // Template 5.2 or 5.3 |
43 | | // ndpts - The number of data values to unpack |
44 | | // |
45 | | // OUTPUT ARGUMENT LIST: |
46 | | // fld - Contains the unpacked data values. fld must be allocated |
47 | | // with at least ndpts*sizeof(g2float) bytes before |
48 | | // calling this routine. |
49 | | // |
50 | | // REMARKS: None |
51 | | // |
52 | | // ATTRIBUTES: |
53 | | // LANGUAGE: C |
54 | | // MACHINE: |
55 | | // |
56 | | //$$$// |
57 | 409 | { |
58 | | |
59 | 409 | g2int nbitsd=0,isign; |
60 | 409 | g2int j,iofst,ival1,ival2,minsd,itemp,l,k,n,non=0; |
61 | 409 | g2int *ifld=NULL,*ifldmiss=NULL; |
62 | 409 | g2int *gref=NULL,*gwidth=NULL,*glen=NULL; |
63 | 409 | g2int itype,ngroups,nbitsgref,nbitsgwidth,nbitsglen; |
64 | 409 | g2int msng1,msng2; |
65 | 409 | g2float ref,bscale,dscale,rmiss1,rmiss2; |
66 | 409 | g2int totBit, totLen; |
67 | 409 | g2int errorOccurred = 0; |
68 | | |
69 | | //printf('IDRSTMPL: ',(idrstmpl(j),j=1,16) |
70 | 409 | rdieee(idrstmpl+0,&ref,1); |
71 | | // printf("SAGTref: %f\n",ref); |
72 | 409 | bscale = DoubleToFloatClamp(int_power(2.0,idrstmpl[1])); |
73 | 409 | dscale = DoubleToFloatClamp(int_power(10.0,-idrstmpl[2])); |
74 | 409 | nbitsgref = idrstmpl[3]; |
75 | 409 | itype = idrstmpl[4]; |
76 | 409 | ngroups = idrstmpl[9]; |
77 | 409 | nbitsgwidth = idrstmpl[11]; |
78 | 409 | nbitsglen = idrstmpl[15]; |
79 | 409 | if (idrsnum == 3) |
80 | 77 | nbitsd=idrstmpl[17]*8; |
81 | | |
82 | | // Constant field |
83 | | |
84 | 409 | if (ngroups == 0) { |
85 | 0 | for (j=0;j<ndpts;j++) fld[j]=ref; |
86 | 0 | return(0); |
87 | 0 | } |
88 | | |
89 | | /* To avoid excessive memory allocations. Not completely sure */ |
90 | | /* if this test is appropriate (the 10 and 2 are arbitrary), */ |
91 | | /* but it doesn't seem to make sense to have ngroups much larger than */ |
92 | | /* ndpts */ |
93 | 409 | if( ngroups < 0 || ngroups - 10 > ndpts / 2 ) { |
94 | 27 | return -1; |
95 | 27 | } |
96 | | |
97 | | /* Early test in particular case for more general test below */ |
98 | | /* "Test to see if the group widths and lengths are consistent with number of */ |
99 | | /* values, and length of section 7. */ |
100 | 382 | if( idrstmpl[12] < 0 || idrstmpl[14] < 0 || idrstmpl[14] > ndpts ) |
101 | 10 | return -1; |
102 | 372 | if( nbitsglen == 0 && |
103 | 0 | ((ngroups > 1 && idrstmpl[12] != (ndpts - idrstmpl[14]) / (ngroups - 1)) || |
104 | 0 | idrstmpl[12] * (ngroups-1) + idrstmpl[14] != ndpts) ) |
105 | 0 | { |
106 | 0 | return -1; |
107 | 0 | } |
108 | | |
109 | 372 | iofst=0; |
110 | 372 | ifld=(g2int *)calloc(ndpts,sizeof(g2int)); |
111 | | //printf("ALLOC ifld: %d %x\n",(int)ndpts,ifld); |
112 | 372 | gref=(g2int *)calloc(ngroups,sizeof(g2int)); |
113 | | //printf("ALLOC gref: %d %x\n",(int)ngroups,gref); |
114 | 372 | gwidth=(g2int *)calloc(ngroups,sizeof(g2int)); |
115 | | //printf("ALLOC gwidth: %d %x\n",(int)ngroups,gwidth); |
116 | 372 | if( ifld == NULL || gref == NULL || gwidth == NULL ) |
117 | 0 | { |
118 | 0 | free(ifld); |
119 | 0 | free(gref); |
120 | 0 | free(gwidth); |
121 | 0 | return -1; |
122 | 0 | } |
123 | | // |
124 | | // Get missing values, if supplied |
125 | | // |
126 | 372 | if ( idrstmpl[6] == 1 ) { |
127 | 341 | if (itype == 0) |
128 | 341 | rdieee(idrstmpl+7,&rmiss1,1); |
129 | 0 | else |
130 | 0 | rmiss1=(g2float)idrstmpl[7]; |
131 | 341 | } |
132 | 372 | if ( idrstmpl[6] == 2 ) { |
133 | 0 | if (itype == 0) { |
134 | 0 | rdieee(idrstmpl+7,&rmiss1,1); |
135 | 0 | rdieee(idrstmpl+8,&rmiss2,1); |
136 | 0 | } |
137 | 0 | else { |
138 | 0 | rmiss1=(g2float)idrstmpl[7]; |
139 | 0 | rmiss2=(g2float)idrstmpl[8]; |
140 | 0 | } |
141 | 0 | } |
142 | | |
143 | | //printf("RMISSs: %f %f %f \n",rmiss1,rmiss2,ref); |
144 | | // |
145 | | // Extract spatial differencing values, if using DRS Template 5.3 |
146 | | // |
147 | 372 | if (idrsnum == 3) { |
148 | 76 | if (nbitsd != 0) { |
149 | | // one mistake here should be unsigned int |
150 | 76 | int ok = gbit2(cpack, cpack_length, &ival1, iofst,nbitsd) != -1; |
151 | 76 | iofst=iofst+nbitsd; |
152 | | // gbit(cpack,&isign,iofst,1); |
153 | | // iofst=iofst+1 |
154 | | // gbit(cpack,&ival1,iofst,nbitsd-1); |
155 | | // iofst=iofst+nbitsd-1; |
156 | | // if (isign == 1) ival1=-ival1; |
157 | 76 | if (idrstmpl[16] == 2) { |
158 | | // one mistake here should be unsigned int |
159 | 50 | ok = ok && gbit2(cpack, cpack_length, &ival2,iofst,nbitsd) != -1; |
160 | 50 | iofst=iofst+nbitsd; |
161 | | // gbit(cpack,&isign,iofst,1); |
162 | | // iofst=iofst+1; |
163 | | // gbit(cpack,&ival2,iofst,nbitsd-1); |
164 | | // iofst=iofst+nbitsd-1; |
165 | | // if (isign == 1) ival2=-ival2; |
166 | 50 | } |
167 | 76 | ok = ok && gbit2(cpack, cpack_length, &isign,iofst,1) != -1; |
168 | 76 | iofst=iofst+1; |
169 | 76 | ok = ok && gbit2(cpack, cpack_length, &minsd,iofst,nbitsd-1) != - 1; |
170 | 76 | iofst=iofst+nbitsd-1; |
171 | | |
172 | 76 | if (!ok) |
173 | 0 | { |
174 | 0 | free(ifld); |
175 | 0 | free(gref); |
176 | 0 | free(gwidth); |
177 | 0 | return -1; |
178 | 0 | } |
179 | | |
180 | 76 | if (isign == 1 && minsd != INT_MIN) minsd=-minsd; |
181 | 76 | } |
182 | 0 | else { |
183 | 0 | ival1=0; |
184 | 0 | ival2=0; |
185 | 0 | minsd=0; |
186 | 0 | } |
187 | | //printf("SDu %ld %ld %ld %ld \n",ival1,ival2,minsd,nbitsd); |
188 | 76 | } |
189 | | // |
190 | | // Extract Each Group's reference value |
191 | | // |
192 | | //printf("SAG1: %ld %ld %ld \n",nbitsgref,ngroups,iofst); |
193 | 372 | if (nbitsgref != 0) { |
194 | 372 | if( gbits(cpack,cpack_length,gref+0,iofst,nbitsgref,0,ngroups) != 0 ) |
195 | 10 | { |
196 | 10 | free(ifld); |
197 | 10 | free(gwidth); |
198 | 10 | free(gref); |
199 | 10 | return -1; |
200 | 10 | } |
201 | 362 | itemp=nbitsgref*ngroups; |
202 | 362 | iofst=iofst+itemp; |
203 | 362 | if (itemp%8 != 0) iofst=iofst+(8-(itemp%8)); |
204 | 362 | } |
205 | | #if 0 |
206 | | else { |
207 | | for (j=0;j<ngroups;j++) |
208 | | gref[j]=0; |
209 | | } |
210 | | #endif |
211 | | |
212 | | // |
213 | | // Extract Each Group's bit width |
214 | | // |
215 | | //printf("SAG2: %ld %ld %ld %ld \n",nbitsgwidth,ngroups,iofst,idrstmpl[10]); |
216 | 362 | if (nbitsgwidth != 0) { |
217 | 362 | if( gbits(cpack,cpack_length,gwidth+0,iofst,nbitsgwidth,0,ngroups) != 0 ) |
218 | 0 | { |
219 | 0 | free(ifld); |
220 | 0 | free(gwidth); |
221 | 0 | free(gref); |
222 | 0 | return -1; |
223 | 0 | } |
224 | 362 | itemp=nbitsgwidth*ngroups; |
225 | 362 | iofst=iofst+itemp; |
226 | 362 | if (itemp%8 != 0) iofst=iofst+(8-(itemp%8)); |
227 | 362 | } |
228 | | #if 0 |
229 | | else { |
230 | | for (j=0;j<ngroups;j++) |
231 | | gwidth[j]=0; |
232 | | } |
233 | | #endif |
234 | | |
235 | 778k | for (j=0;j<ngroups;j++) |
236 | 778k | { |
237 | 778k | if( gwidth[j] > INT_MAX - idrstmpl[10] ) |
238 | 0 | { |
239 | 0 | free(ifld); |
240 | 0 | free(gwidth); |
241 | 0 | free(gref); |
242 | 0 | return -1; |
243 | 0 | } |
244 | 778k | gwidth[j]=gwidth[j]+idrstmpl[10]; |
245 | 778k | } |
246 | | |
247 | | // |
248 | | // Extract Each Group's length (number of values in each group) |
249 | | // |
250 | 362 | glen=(g2int *)calloc(ngroups,sizeof(g2int)); |
251 | 362 | if( glen == NULL ) |
252 | 0 | { |
253 | 0 | free(ifld); |
254 | 0 | free(gwidth); |
255 | 0 | free(gref); |
256 | 0 | return -1; |
257 | 0 | } |
258 | | //printf("ALLOC glen: %d %x\n",(int)ngroups,glen); |
259 | | //printf("SAG3: %ld %ld %ld %ld %ld \n",nbitsglen,ngroups,iofst,idrstmpl[13],idrstmpl[12]); |
260 | 362 | if (nbitsglen != 0) { |
261 | 362 | if( gbits(cpack,cpack_length,glen,iofst,nbitsglen,0,ngroups) != 0 ) |
262 | 16 | { |
263 | 16 | free(ifld); |
264 | 16 | free(gwidth); |
265 | 16 | free(glen); |
266 | 16 | free(gref); |
267 | 16 | return -1; |
268 | 16 | } |
269 | 346 | itemp=nbitsglen*ngroups; |
270 | 346 | iofst=iofst+itemp; |
271 | 346 | if (itemp%8 != 0) iofst=iofst+(8-(itemp%8)); |
272 | 346 | } |
273 | | #if 0 |
274 | | else { |
275 | | for (j=0;j<ngroups;j++) |
276 | | glen[j]=0; |
277 | | } |
278 | | #endif |
279 | | |
280 | | // Note: iterate only to ngroups - 1 since we override just after the |
281 | | // loop. Otherwise the security checks in the loop might trigger, like |
282 | | // on band 23 of |
283 | | // https://nomads.ncep.noaa.gov/pub/data/nccf/com/blend/prod/blend.20200605/16/grib2/blend.t16z.master.f001.co.grib2 |
284 | 777k | for (j=0;j<ngroups - 1;j++) |
285 | 776k | { |
286 | 776k | if( glen[j] < 0 || |
287 | 776k | (idrstmpl[13] != 0 && glen[j] > INT_MAX / idrstmpl[13]) || |
288 | 776k | glen[j] * idrstmpl[13] > INT_MAX - idrstmpl[12] ) |
289 | 0 | { |
290 | 0 | free(ifld); |
291 | 0 | free(gwidth); |
292 | 0 | free(glen); |
293 | 0 | free(gref); |
294 | 0 | return -1; |
295 | 0 | } |
296 | 776k | glen[j]=(glen[j]*idrstmpl[13])+idrstmpl[12]; |
297 | 776k | } |
298 | 346 | glen[ngroups-1]=idrstmpl[14]; |
299 | | // |
300 | | // Test to see if the group widths and lengths are consistent with number of |
301 | | // values, and length of section 7. |
302 | | // |
303 | 346 | totBit = 0; |
304 | 346 | totLen = 0; |
305 | 777k | for (j=0;j<ngroups;j++) { |
306 | 777k | g2int width_mult_len; |
307 | 777k | if( gwidth[j] < 0 || glen[j] < 0 || |
308 | 777k | (gwidth[j] > 0 && glen[j] > INT_MAX / gwidth[j]) ) |
309 | 0 | { |
310 | 0 | errorOccurred = 1; |
311 | 0 | break; |
312 | 0 | } |
313 | 777k | width_mult_len = gwidth[j]*glen[j]; |
314 | 777k | if( totBit > INT_MAX - width_mult_len ) |
315 | 0 | { |
316 | 0 | errorOccurred = 1; |
317 | 0 | break; |
318 | 0 | } |
319 | 777k | totBit += width_mult_len; |
320 | 777k | if( totLen > INT_MAX - glen[j] ) |
321 | 0 | { |
322 | 0 | errorOccurred = 1; |
323 | 0 | break; |
324 | 0 | } |
325 | 777k | totLen += glen[j]; |
326 | 777k | } |
327 | 346 | if (errorOccurred || totLen != ndpts || totBit / 8. > lensec) { |
328 | 105 | free(ifld); |
329 | 105 | free(gwidth); |
330 | 105 | free(glen); |
331 | 105 | free(gref); |
332 | 105 | return 1; |
333 | 105 | } |
334 | | // |
335 | | // For each group, unpack data values |
336 | | // |
337 | 241 | if ( idrstmpl[6] == 0 ) { // no missing values |
338 | 20 | n=0; |
339 | 254k | for (j=0;j<ngroups;j++) { |
340 | 254k | if (gwidth[j] != 0) { |
341 | 239k | if( gbits(cpack,cpack_length,ifld+n,iofst,gwidth[j],0,glen[j]) != 0 ) |
342 | 0 | { |
343 | 0 | free(ifld); |
344 | 0 | free(gwidth); |
345 | 0 | free(glen); |
346 | 0 | free(gref); |
347 | 0 | return -1; |
348 | 0 | } |
349 | 3.73M | for (k=0;k<glen[j];k++) { |
350 | 3.49M | ifld[n]=ifld[n]+gref[j]; |
351 | 3.49M | n=n+1; |
352 | 3.49M | } |
353 | 239k | } |
354 | 15.4k | else { |
355 | 33.4k | for (l=n;l<n+glen[j];l++) ifld[l]=gref[j]; |
356 | 15.4k | n=n+glen[j]; |
357 | 15.4k | } |
358 | 254k | iofst=iofst+(gwidth[j]*glen[j]); |
359 | 254k | } |
360 | 20 | } |
361 | 221 | else if ( idrstmpl[6]==1 || idrstmpl[6]==2 ) { |
362 | | // missing values included |
363 | 220 | ifldmiss=(g2int *)malloc(ndpts*sizeof(g2int)); |
364 | | //printf("ALLOC ifldmiss: %d %x\n",(int)ndpts,ifldmiss); |
365 | | //for (j=0;j<ndpts;j++) ifldmiss[j]=0; |
366 | 220 | n=0; |
367 | 220 | non=0; |
368 | 512k | for (j=0;j<ngroups;j++) { |
369 | | //printf(" SAGNGP %d %d %d %d\n",j,gwidth[j],glen[j],gref[j]); |
370 | 512k | if (gwidth[j] != 0) { |
371 | 446k | msng1=(g2int)int_power(2.0,gwidth[j])-1; |
372 | 446k | msng2=msng1-1; |
373 | 446k | if( gbits(cpack,cpack_length,ifld+n,iofst,gwidth[j],0,glen[j]) != 0 ) |
374 | 8 | { |
375 | 8 | free(ifld); |
376 | 8 | free(gwidth); |
377 | 8 | free(glen); |
378 | 8 | free(gref); |
379 | 8 | free(ifldmiss); |
380 | 8 | return -1; |
381 | 8 | } |
382 | 446k | iofst=iofst+(gwidth[j]*glen[j]); |
383 | 6.44M | for (k=0;k<glen[j];k++) { |
384 | 5.99M | if (ifld[n] == msng1) { |
385 | 576k | ifldmiss[n]=1; |
386 | | //ifld[n]=0; |
387 | 576k | } |
388 | 5.42M | else if (idrstmpl[6]==2 && ifld[n]==msng2) { |
389 | 0 | ifldmiss[n]=2; |
390 | | //ifld[n]=0; |
391 | 0 | } |
392 | 5.42M | else { |
393 | 5.42M | ifldmiss[n]=0; |
394 | 5.42M | ifld[non++]=ifld[n]+gref[j]; |
395 | 5.42M | } |
396 | 5.99M | n++; |
397 | 5.99M | } |
398 | 446k | } |
399 | 65.2k | else { |
400 | 65.2k | msng1=(g2int)int_power(2.0,nbitsgref)-1; |
401 | 65.2k | msng2=msng1-1; |
402 | 65.2k | if (gref[j] == msng1) { |
403 | 7.12M | for (l=n;l<n+glen[j];l++) ifldmiss[l]=1; |
404 | 64.8k | } |
405 | 384 | else if (idrstmpl[6]==2 && gref[j]==msng2) { |
406 | 0 | for (l=n;l<n+glen[j];l++) ifldmiss[l]=2; |
407 | 0 | } |
408 | 384 | else { |
409 | 5.33k | for (l=n;l<n+glen[j];l++) ifldmiss[l]=0; |
410 | 5.33k | for (l=non;l<non+glen[j];l++) ifld[l]=gref[j]; |
411 | 384 | non += glen[j]; |
412 | 384 | } |
413 | 65.2k | n=n+glen[j]; |
414 | 65.2k | } |
415 | 512k | } |
416 | 220 | } |
417 | | |
418 | 233 | if ( gref != 0 ) free(gref); |
419 | 233 | if ( gwidth != 0 ) free(gwidth); |
420 | 233 | if ( glen != 0 ) free(glen); |
421 | | // |
422 | | // If using spatial differences, add overall min value, and |
423 | | // sum up recursively |
424 | | // |
425 | | //printf("SAGod: %ld %ld\n",idrsnum,idrstmpl[16]); |
426 | 233 | if (idrsnum == 3) { // spatial differencing |
427 | 66 | if (idrstmpl[16] == 1) { // first order |
428 | 24 | ifld[0]=ival1; |
429 | 24 | if ( idrstmpl[6] == 0 ) itemp=ndpts; // no missing values |
430 | 24 | else itemp=non; |
431 | 442k | for (n=1;n<itemp;n++) { |
432 | 442k | if( (minsd > 0 && ifld[n] > INT_MAX - minsd) || |
433 | 442k | (minsd < 0 && ifld[n] < INT_MIN - minsd) ) |
434 | 0 | { |
435 | 0 | free(ifldmiss); |
436 | 0 | free(ifld); |
437 | 0 | return -1; |
438 | 0 | } |
439 | 442k | ifld[n]=ifld[n]+minsd; |
440 | 442k | if( (ifld[n-1] > 0 && ifld[n] > INT_MAX - ifld[n-1]) || |
441 | 442k | (ifld[n-1] < 0 && ifld[n] < INT_MIN - ifld[n-1]) ) |
442 | 0 | { |
443 | 0 | free(ifldmiss); |
444 | 0 | free(ifld); |
445 | 0 | return -1; |
446 | 0 | } |
447 | 442k | ifld[n]=ifld[n]+ifld[n-1]; |
448 | 442k | } |
449 | 24 | } |
450 | 42 | else if (idrstmpl[16] == 2) { // second order |
451 | 42 | ifld[0]=ival1; |
452 | 42 | ifld[1]=ival2; |
453 | 42 | if ( idrstmpl[6] == 0 ) itemp=ndpts; // no missing values |
454 | 28 | else itemp=non; |
455 | 3.12M | for (n=2;n<itemp;n++) { |
456 | | /* Lazy way of detecting int overflows: operate on double */ |
457 | 3.12M | double tmp = (double)ifld[n]+(double)minsd+(2.0 * ifld[n-1])-ifld[n-2]; |
458 | 3.12M | if( tmp > INT_MAX || tmp < INT_MIN ) |
459 | 8 | { |
460 | 8 | free(ifldmiss); |
461 | 8 | free(ifld); |
462 | 8 | return -1; |
463 | 8 | } |
464 | 3.12M | ifld[n]=(int)tmp; |
465 | 3.12M | } |
466 | 42 | } |
467 | 66 | } |
468 | | // |
469 | | // Scale data back to original form |
470 | | // |
471 | | //printf("SAGT: %f %f %f\n",ref,bscale,dscale); |
472 | 225 | if ( idrstmpl[6] == 0 ) { // no missing values |
473 | 1.50M | for (n=0;n<ndpts;n++) { |
474 | 1.50M | fld[n]=(((g2float)ifld[n]*bscale)+ref)*dscale; |
475 | 1.50M | } |
476 | 12 | } |
477 | 213 | else if ( idrstmpl[6]==1 || idrstmpl[6]==2 ) { |
478 | | // missing values included |
479 | 212 | non=0; |
480 | 5.38M | for (n=0;n<ndpts;n++) { |
481 | 5.38M | if ( ifldmiss[n] == 0 ) { |
482 | 2.45M | fld[n]=(((g2float)ifld[non++]*bscale)+ref)*dscale; |
483 | | //printf(" SAG %d %f %d %f %f %f\n",n,fld[n],ifld[non-1],bscale,ref,dscale); |
484 | 2.45M | } |
485 | 2.92M | else if ( ifldmiss[n] == 1 ) |
486 | 2.92M | fld[n]=rmiss1; |
487 | 0 | else if ( ifldmiss[n] == 2 ) |
488 | 0 | fld[n]=rmiss2; |
489 | 5.38M | } |
490 | 212 | if ( ifldmiss != 0 ) free(ifldmiss); |
491 | 212 | } |
492 | | |
493 | 225 | if ( ifld != 0 ) free(ifld); |
494 | | |
495 | 225 | return(0); |
496 | | |
497 | 233 | } |