/src/gdal/frmts/grib/degrib/g2clib/simpack.c
Line | Count | Source |
1 | | #include <stdlib.h> |
2 | | #include <math.h> |
3 | | #include <limits.h> |
4 | | #include <float.h> |
5 | | #include "grib2.h" |
6 | | |
7 | | |
8 | | void simpack(g2float *fld,g2int ndpts,g2int *idrstmpl,unsigned char *cpack,g2int *lcpack) |
9 | | //$$$ SUBPROGRAM DOCUMENTATION BLOCK |
10 | | // . . . . |
11 | | // SUBPROGRAM: simpack |
12 | | // PRGMMR: Gilbert ORG: W/NP11 DATE: 2002-11-06 |
13 | | // |
14 | | // ABSTRACT: This subroutine packs up a data field using the simple |
15 | | // packing algorithm as defined in the GRIB2 documentation. It |
16 | | // also fills in GRIB2 Data Representation Template 5.0 with the |
17 | | // appropriate values. |
18 | | // |
19 | | // PROGRAM HISTORY LOG: |
20 | | // 2002-11-06 Gilbert |
21 | | // |
22 | | // USAGE: CALL simpack(fld,ndpts,idrstmpl,cpack,lcpack) |
23 | | // INPUT ARGUMENT LIST: |
24 | | // fld[] - Contains the data values to pack |
25 | | // ndpts - The number of data values in array fld[] |
26 | | // idrstmpl - Contains the array of values for Data Representation |
27 | | // Template 5.0 |
28 | | // [0] = Reference value - ignored on input |
29 | | // [1] = Binary Scale Factor |
30 | | // [2] = Decimal Scale Factor |
31 | | // [3] = Number of bits used to pack data, if value is |
32 | | // > 0 and <= 31. |
33 | | // If this input value is 0 or outside above range |
34 | | // then the num of bits is calculated based on given |
35 | | // data and scale factors. |
36 | | // [4] = Original field type - currently ignored on input |
37 | | // Data values assumed to be reals. |
38 | | // |
39 | | // OUTPUT ARGUMENT LIST: |
40 | | // idrstmpl - Contains the array of values for Data Representation |
41 | | // Template 5.0 |
42 | | // [0] = Reference value - set by simpack routine. |
43 | | // [1] = Binary Scale Factor - unchanged from input |
44 | | // [2] = Decimal Scale Factor - unchanged from input |
45 | | // [3] = Number of bits used to pack data, unchanged from |
46 | | // input if value is between 0 and 31. |
47 | | // If this input value is 0 or outside above range |
48 | | // then the num of bits is calculated based on given |
49 | | // data and scale factors. |
50 | | // [4] = Original field type - currently set = 0 on output. |
51 | | // Data values assumed to be reals. |
52 | | // cpack - The packed data field |
53 | | // lcpack - length of packed field starting at cpack. |
54 | | // |
55 | | // REMARKS: None |
56 | | // |
57 | | // ATTRIBUTES: |
58 | | // LANGUAGE: C |
59 | | // MACHINE: |
60 | | // |
61 | | //$$$ |
62 | 262 | { |
63 | | |
64 | 262 | const g2int zero=0; |
65 | 262 | g2int *ifld; |
66 | 262 | g2int j,nbits,maxdif,nbittot,left; |
67 | 262 | g2float bscale,dscale,rmax,rmin,temp, ref, rmin_dscaled, rmax_dscaled; |
68 | 262 | double maxnum; |
69 | 262 | const g2float alog2=0.69314718f; // ln(2.0) |
70 | | |
71 | 262 | bscale=(float)int_power(2.0,-idrstmpl[1]); |
72 | 262 | dscale=(float)int_power(10.0,idrstmpl[2]); |
73 | 262 | if (idrstmpl[3] <= 0 || idrstmpl[3] > 31) |
74 | 262 | nbits=0; |
75 | 0 | else |
76 | 0 | nbits=idrstmpl[3]; |
77 | | |
78 | 262 | if( dscale == 0.0 ) |
79 | 0 | { |
80 | 0 | fprintf(stderr, "Invalid dscale == 0 value\n"); |
81 | 0 | *lcpack = -1; |
82 | 0 | return; |
83 | 0 | } |
84 | | // |
85 | | // Find max and min values in the data |
86 | | // |
87 | 262 | rmax=fld[0]; |
88 | 262 | rmin=fld[0]; |
89 | 384k | for (j=1;j<ndpts;j++) { |
90 | 384k | if (fld[j] > rmax) rmax=fld[j]; |
91 | 384k | if (fld[j] < rmin) rmin=fld[j]; |
92 | 384k | } |
93 | 262 | if( !(floor((double)rmin*dscale) >= -FLT_MAX && floor((double)rmin*dscale) <= FLT_MAX) ) |
94 | 0 | { |
95 | 0 | fprintf(stderr, |
96 | 0 | "Scaled min value not representable on IEEE754 " |
97 | 0 | "single precision float\n"); |
98 | 0 | *lcpack = -1; |
99 | 0 | return; |
100 | 0 | } |
101 | 262 | if( !(floor((double)rmax*dscale) >= -FLT_MAX && floor((double)rmax*dscale) <= FLT_MAX) ) |
102 | 0 | { |
103 | 0 | fprintf(stderr, |
104 | 0 | "Scaled max value not representable on IEEE754 " |
105 | 0 | "single precision float\n"); |
106 | 0 | *lcpack = -1; |
107 | 0 | return; |
108 | 0 | } |
109 | 262 | rmin_dscaled = rmin*dscale; |
110 | 262 | rmax_dscaled = rmax*dscale; |
111 | | |
112 | 262 | ifld=calloc(ndpts,sizeof(g2int)); |
113 | 262 | if( ifld == NULL ) |
114 | 0 | { |
115 | 0 | fprintf(stderr, "Cannot allocate ifld in simpack()\n"); |
116 | 0 | *lcpack = -1; |
117 | 0 | return; |
118 | 0 | } |
119 | | |
120 | | // |
121 | | // If max and min values are not equal, pack up field. |
122 | | // If they are equal, we have a constant field, and the reference |
123 | | // value (rmin) is the value for each point in the field and |
124 | | // set nbits to 0. |
125 | | // |
126 | 262 | if ( (rmax_dscaled - rmin_dscaled >= 1) || |
127 | 210 | (rmin != rmax && nbits!=0 && idrstmpl[1]==0) ) { |
128 | 52 | int done = 0; |
129 | | // |
130 | | // Determine which algorithm to use based on user-supplied |
131 | | // binary scale factor and number of bits. |
132 | | // |
133 | 52 | if (nbits==0 && idrstmpl[1]==0) { |
134 | | // |
135 | | // No binary scaling and calculate minimum number of |
136 | | // bits in which the data will fit. |
137 | | // |
138 | 52 | if( dscale != 1.0 ) |
139 | 0 | { |
140 | 0 | rmin_dscaled = (float)floor(rmin_dscaled); |
141 | 0 | } |
142 | 52 | if( (double)(rmax_dscaled - rmin_dscaled) > (double)INT_MAX ) |
143 | 0 | { |
144 | 0 | nbits = 31; |
145 | 0 | } |
146 | 52 | else |
147 | 52 | { |
148 | 52 | temp=(float)(log(ceil(rmax_dscaled - rmin_dscaled))/alog2); |
149 | 52 | nbits=(g2int)ceil(temp); |
150 | | // scale data |
151 | 52 | if( nbits > 31 ) |
152 | 0 | { |
153 | 0 | nbits = 31; |
154 | 0 | } |
155 | 52 | else |
156 | 52 | { |
157 | 52 | done = 1; |
158 | 186k | for(j=0;j<ndpts;j++) |
159 | 186k | ifld[j]=(g2int)RINT(fld[j]*dscale -rmin_dscaled); |
160 | 52 | ref = rmin_dscaled; |
161 | 52 | } |
162 | 52 | } |
163 | 52 | } |
164 | | |
165 | 52 | if (!done && nbits!=0 && idrstmpl[1]==0) { |
166 | | // |
167 | | // Use number of bits specified by user and |
168 | | // adjust binary scaling factor to accommodate data. |
169 | | // |
170 | 0 | if( dscale != 1.0 ) |
171 | 0 | { |
172 | 0 | rmin_dscaled = (float)floor(rmin_dscaled); |
173 | 0 | } |
174 | 0 | maxnum=int_power(2.0,nbits)-1; |
175 | 0 | temp=(float)(log(maxnum/(rmax_dscaled-rmin_dscaled))/alog2); |
176 | 0 | idrstmpl[1]=(g2int)ceil(-1.0*temp); |
177 | 0 | bscale=(float)int_power(2.0,-idrstmpl[1]); |
178 | | // scale data |
179 | 0 | for (j=0;j<ndpts;j++) |
180 | 0 | ifld[j]=(g2int)RINT(((fld[j]*dscale)-rmin_dscaled)*bscale); |
181 | 0 | ref=rmin_dscaled; |
182 | 0 | } |
183 | 52 | else if (nbits==0 && idrstmpl[1]!=0) { |
184 | | // |
185 | | // Use binary scaling factor and calculate minimum number of |
186 | | // bits in which the data will fit. |
187 | | // |
188 | 0 | maxdif=(g2int)RINT((rmax_dscaled-rmin_dscaled)*bscale); |
189 | 0 | temp=(float)(log((double)(maxdif+1))/alog2); |
190 | 0 | nbits=(g2int)ceil(temp); |
191 | | // scale data |
192 | 0 | for (j=0;j<ndpts;j++) |
193 | 0 | ifld[j]=(g2int)RINT(((fld[j]*dscale)-rmin_dscaled)*bscale); |
194 | 0 | ref=rmin_dscaled; |
195 | 0 | } |
196 | 52 | else if (nbits!=0 && idrstmpl[1]!=0) { |
197 | | // |
198 | | // Use binary scaling factor and use minimum number of |
199 | | // bits specified by user. Dangerous - may loose |
200 | | // information if binary scale factor and nbits not set |
201 | | // properly by user. |
202 | | // |
203 | | // scale data |
204 | 0 | for (j=0;j<ndpts;j++) |
205 | 0 | ifld[j]=(g2int)RINT(((fld[j]*dscale)-rmin_dscaled)*bscale); |
206 | 0 | ref=rmin_dscaled; |
207 | 0 | } |
208 | | // |
209 | | // Pack data, Pad last octet with Zeros, if necessary, |
210 | | // and calculate the length of the packed data in bytes |
211 | | // |
212 | 52 | sbits(cpack,ifld+0,0,nbits,0,ndpts); |
213 | 52 | nbittot=nbits*ndpts; |
214 | 52 | left=8-(nbittot%8); |
215 | 52 | if (left != 8) { |
216 | 0 | sbit(cpack,&zero,nbittot,left); // Pad with zeros to fill Octet |
217 | 0 | nbittot=nbittot+left; |
218 | 0 | } |
219 | 52 | *lcpack=nbittot/8; |
220 | 52 | } |
221 | 210 | else { |
222 | | /* Force E and D to 0 to avoid compatibility issues */ |
223 | 210 | idrstmpl[1]=0; |
224 | 210 | idrstmpl[2]=0; |
225 | 210 | if( dscale != 1.0 ) |
226 | 0 | { |
227 | 0 | ref = (float)floor((double)rmin * dscale) / dscale; |
228 | 0 | } |
229 | 210 | else |
230 | 210 | { |
231 | 210 | ref = rmin; |
232 | 210 | } |
233 | 210 | nbits=0; |
234 | 210 | *lcpack=0; |
235 | 210 | } |
236 | | |
237 | | // |
238 | | // Fill in ref value and number of bits in Template 5.0 |
239 | | // |
240 | | //printf("SAGmkieee %f\n",ref); |
241 | 262 | mkieee(&ref,idrstmpl+0,1); // ensure reference value is IEEE format |
242 | | //printf("SAGmkieee %ld\n",idrstmpl[0]); |
243 | 262 | idrstmpl[3]=nbits; |
244 | 262 | idrstmpl[4]=0; // original data were reals |
245 | | |
246 | 262 | free(ifld); |
247 | 262 | } |