1
2 /* Automatically generated by m214003 at 2021-09-09, do not edit */
3
4 /* CGRIBEXLIB_VERSION="2.0.0" */
5
6 #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 5) || defined (__clang__)
7 #pragma GCC diagnostic push
8 #pragma GCC diagnostic ignored "-Wconversion"
9 #pragma GCC diagnostic ignored "-Wsign-conversion"
10 #pragma GCC diagnostic warning "-Wstrict-overflow"
11 #endif
12
13 #if defined(_ARCH_PWR6) && defined(__GLIBC__)
14 #pragma options nostrict
15 #include <ppu_intrinsics.h>
16 #endif
17
18 #ifdef HAVE_CONFIG_H
19 #include "config.h"
20 #endif
21
22 #include <string.h>
23 #include <ctype.h>
24 #include <stdarg.h>
25 #include <stdbool.h>
26 #include <sys/types.h>
27 #include <inttypes.h>
28
29
30 #include "file.h"
31 #include "dmemory.h"
32 #include "dtypes.h"
33 #include "calendar.h"
34 #include "timebase.h"
35
36 #ifndef CGRIBEX_TEMPLATES_H
37 #define CGRIBEX_TEMPLATES_H
38
39 #define CAT(X,Y) X##_##Y
40 #define TEMPLATE(X,Y) CAT(X,Y)
41
42 #endif
43 #ifndef GRIB_INT_H
44 #define GRIB_INT_H
45
46 #ifdef HAVE_CONFIG_H
47 #include "config.h"
48 #endif
49
50 #include <inttypes.h>
51 #include <stdio.h>
52 #include <stdlib.h>
53 #include <stdbool.h>
54 #include <math.h>
55 #include <float.h>
56
57
58 #ifndef CGRIBEX_H
59 #include "cgribex.h"
60 #endif
61 #ifndef ERROR_H
62 #include "error.h"
63 #endif
64 #ifndef TYPES_H
65 #include "dtypes.h"
66 #endif
67
68
69 #ifndef UCHAR
70 #define UCHAR unsigned char
71 #endif
72
73
74 #if defined (CRAY) || defined (SX) || defined (__uxpch__)
75 #define VECTORCODE
76 #endif
77
78
79 #ifdef VECTORCODE
80 #ifdef INT32
81 # define GRIBPACK unsigned INT32
82 # define PACK_GRIB packInt32
83 # define UNPACK_GRIB unpackInt32
84 #else
85 # define GRIBPACK unsigned INT64
86 # define PACK_GRIB packInt64
87 # define UNPACK_GRIB unpackInt64
88 #endif
89 #else
90 # define GRIBPACK unsigned char
91 #endif
92
93 #ifndef HOST_ENDIANNESS
94 #ifdef __cplusplus
95 static const uint32_t HOST_ENDIANNESS_temp[1] = { UINT32_C(0x00030201) };
96 #define HOST_ENDIANNESS (((const unsigned char *)HOST_ENDIANNESS_temp)[0])
97 #else
98 #define HOST_ENDIANNESS (((const unsigned char *)&(const uint32_t[1]){UINT32_C(0x00030201)})[0])
99 #endif
100 #endif
101
102 #define U_BYTEORDER
103 #define IS_BIGENDIAN() (HOST_ENDIANNESS == 0)
104
105 #if defined (__xlC__) /* performance problems on IBM */
106 #ifndef DBL_IS_NAN
107 # define DBL_IS_NAN(x) ((x) != (x))
108 #endif
109 #else
110 #ifndef DBL_IS_NAN
111 #if defined (HAVE_DECL_ISNAN)
112 # define DBL_IS_NAN(x) (isnan(x))
113 #elif defined (FP_NAN)
114 # define DBL_IS_NAN(x) (fpclassify(x) == FP_NAN)
115 #else
116 # define DBL_IS_NAN(x) ((x) != (x))
117 #endif
118 #endif
119 #endif
120
121 #ifndef IS_EQUAL
122 # define IS_NOT_EQUAL(x,y) (x < y || y < x)
123 # define IS_EQUAL(x,y) (!IS_NOT_EQUAL(x,y))
124 #endif
125
126 /* dummy use of unused parameters to silence compiler warnings */
127 #ifndef UNUSED
128 #define UNUSED(x) (void)(x)
129 #endif
130
131 #define JP24SET 0xFFFFFF /* 2**24 (---> 16777215) */
132 #define JP23SET 0x7FFFFF /* 2**23 - 1 (---> 8388607) */
133
134 #define POW_2_M24 0.000000059604644775390625 /* pow(2.0, -24.0) */
135
136 #ifdef __cplusplus
137 extern "C" {
138 #endif
139
140 #define intpow2(x) (ldexp(1.0, (x)))
141
142 static inline int
gribrec_len(unsigned b1,unsigned b2,unsigned b3)143 gribrec_len(unsigned b1, unsigned b2, unsigned b3)
144 {
145 /*
146 If bit 7 of b1 is set, we have to rescale by factor of 120.
147 This is a fixup to get round the restriction on product lengths
148 due to the count being only 24 bits. It is only possible because
149 the (default) rounding for GRIB products is 120 bytes.
150 */
151 const int needRescaling = b1 & (1 << 7);
152
153 int gribsize = (int)((((b1&127) << 16)+(b2<<8) + b3));
154
155 if ( needRescaling ) gribsize *= 120;
156
157 return gribsize;
158
159 }
160
161 unsigned correct_bdslen(unsigned bdslen, long recsize, long gribpos);
162
163 /* CDI converter routines */
164
165 /* param format: DDDCCCNNN */
166
167 void cdiDecodeParam(int param, int *pnum, int *pcat, int *pdis);
168 int cdiEncodeParam(int pnum, int pcat, int pdis);
169
170 /* date format: YYYYMMDD */
171 /* time format: hhmmss */
172
173 void cdiDecodeDate(int64_t date, int *year, int *month, int *day);
174 int64_t cdiEncodeDate(int year, int month, int day);
175
176 void cdiDecodeTime(int time, int *hour, int *minute, int *second);
177 int cdiEncodeTime(int hour, int minute, int second);
178
179 /* CALENDAR types */
180
181 #define CALENDAR_STANDARD 0 /* don't change this value (used also in cgribexlib)! */
182 #define CALENDAR_GREGORIAN 1
183 #define CALENDAR_PROLEPTIC 2
184 #define CALENDAR_360DAYS 3
185 #define CALENDAR_365DAYS 4
186 #define CALENDAR_366DAYS 5
187 #define CALENDAR_NONE 6
188
189 extern FILE *grprsm;
190
191 extern int CGRIBEX_Debug, CGRIBEX_Fix_ZSE, CGRIBEX_Const;
192 extern int CGRIBEX_grib_calendar;
193
194 void gprintf(const char *caller, const char *fmt, ...);
195
196 void grsdef(void);
197
198 void prtbin(int kin, int knbit, int *kout, int *kerr);
199 void confp3(double pval, int *kexp, int *kmant, int kbits, int kround);
200 double decfp2(int kexp, int kmant);
201 void ref2ibm(double *pref, int kbits);
202
203 void scale_complex_double(double *fpdata, int pcStart, int pcScale, int trunc, int inv);
204 void scale_complex_float(float *fpdata, int pcStart, int pcScale, int trunc, int inv);
205 void scatter_complex_double(double *fpdata, int pcStart, int trunc, int nsp);
206 void scatter_complex_float(float *fpdata, int pcStart, int trunc, int nsp);
207 void gather_complex_double(double *fpdata, size_t pcStart, size_t trunc, size_t nsp);
208 void gather_complex_float(float *fpdata, size_t pcStart, size_t trunc, size_t nsp);
209
210 int qu2reg2(double *pfield, int *kpoint, int klat, int klon,
211 double *ztemp, double msval, int *kret);
212 int qu2reg3_double(double *pfield, int *kpoint, int klat, int klon,
213 double msval, int *kret, int omisng, int operio, int oveggy);
214 int qu2reg3_float(float *pfield, int *kpoint, int klat, int klon,
215 float msval, int *kret, int omisng, int operio, int oveggy);
216
217 #ifdef INT32
218 long packInt32(unsigned INT32 *up, unsigned char *cp, long bc, long tc);
219 #endif
220 long packInt64(unsigned INT64 *up, unsigned char *cp, long bc, long tc);
221 #ifdef INT32
222 long unpackInt32(const unsigned char *cp, unsigned INT32 *up, long bc, long tc);
223 #endif
224 long unpackInt64(const unsigned char *cp, unsigned INT64 *up, long bc, long tc);
225
226 void grib_encode_double(int *isec0, int *isec1, int *isec2, double *fsec2, int *isec3,
227 double *fsec3, int *isec4, double *fsec4, int klenp, int *kgrib,
228 int kleng, int *kword, int efunc, int *kret);
229 void grib_encode_float(int *isec0, int *isec1, int *isec2, float *fsec2, int *isec3,
230 float *fsec3, int *isec4, float *fsec4, int klenp, int *kgrib,
231 int kleng, int *kword, int efunc, int *kret);
232
233 void grib_decode_double(int *isec0, int *isec1, int *isec2, double *fsec2, int *isec3,
234 double *fsec3, int *isec4, double *fsec4, int klenp, int *kgrib,
235 int kleng, int *kword, int dfunc, int *kret);
236 void grib_decode_float(int *isec0, int *isec1, int *isec2, float *fsec2, int *isec3,
237 float *fsec3, int *isec4, float *fsec4, int klenp, int *kgrib,
238 int kleng, int *kword, int dfunc, int *kret);
239
240
241 int grib1Sections(unsigned char *gribbuffer, long gribbufsize, unsigned char **pdsp,
242 unsigned char **gdsp, unsigned char **bmsp, unsigned char **bdsp, long *gribrecsize);
243 int grib2Sections(unsigned char *gribbuffer, long gribbufsize, unsigned char **idsp,
244 unsigned char **lusp, unsigned char **gdsp, unsigned char **pdsp,
245 unsigned char **drsp, unsigned char **bmsp, unsigned char **bdsp);
246
247 #ifdef __cplusplus
248 }
249 #endif
250
251 #endif /* GRIB_INT_H */
252 #ifndef GRIBDECODE_H
253 #define GRIBDECODE_H
254
255 #define UNDEFINED 9.999e20
256
257
258 #define GET_INT3(a,b,c) ((1-(int) ((unsigned) (a & 128) >> 6)) * (int) (((a & 127) << 16)+(b<<8)+c))
259 #define GET_INT2(a,b) ((1-(int) ((unsigned) (a & 128) >> 6)) * (int) (((a & 127) << 8) + b))
260 #define GET_INT1(a) ((1-(int) ((unsigned) (a & 128) >> 6)) * (int) (a&127))
261
262 /* this requires a 32-bit default integer machine */
263 #define GET_UINT4(a,b,c,d) ((unsigned) ((a << 24) + (b << 16) + (c << 8) + (d)))
264 #define GET_UINT3(a,b,c) ((unsigned) ((a << 16) + (b << 8) + (c)))
265 #define GET_UINT2(a,b) ((unsigned) ((a << 8) + (b)))
266 #define GET_UINT1(a) ((unsigned) (a))
267
268 #define BUDG_START(s) (s[0]=='B' && s[1]=='U' && s[2]=='D' && s[3]=='G')
269 #define TIDE_START(s) (s[0]=='T' && s[1]=='I' && s[2]=='D' && s[3]=='E')
270 #define GRIB_START(s) (s[0]=='G' && s[1]=='R' && s[2]=='I' && s[3]=='B')
271 #define GRIB_FIN(s) (s[0]=='7' && s[1]=='7' && s[2]=='7' && s[3]=='7')
272
273 /* GRIB1 Section 0: Indicator Section (IS) */
274
275 #define GRIB1_SECLEN(s) GET_UINT3(s[ 4], s[ 5], s[ 6])
276 #define GRIB_EDITION(s) GET_UINT1(s[ 7])
277
278 /* GRIB1 Section 1: Product Definition Section (PDS) */
279
280 #define PDS_Len GET_UINT3(pds[ 0], pds[ 1], pds[ 2])
281 #define PDS_CodeTable GET_UINT1(pds[ 3])
282 #define PDS_CenterID GET_UINT1(pds[ 4])
283 #define PDS_ModelID GET_UINT1(pds[ 5])
284 #define PDS_GridDefinition GET_UINT1(pds[ 6])
285 #define PDS_Sec2Or3Flag GET_UINT1(pds[ 7])
286 #define PDS_HAS_GDS ((pds[7] & 128) != 0)
287 #define PDS_HAS_BMS ((pds[7] & 64) != 0)
288 #define PDS_Parameter GET_UINT1(pds[ 8])
289 #define PDS_LevelType GET_UINT1(pds[ 9])
290 #define PDS_Level1 (pds[10])
291 #define PDS_Level2 (pds[11])
292 #define PDS_Level GET_UINT2(pds[10], pds[11])
293 #define PDS_Year GET_INT1(pds[12])
294 #define PDS_Month GET_UINT1(pds[13])
295 #define PDS_Day GET_UINT1(pds[14])
296 #define PDS_Hour GET_UINT1(pds[15])
297 #define PDS_Minute GET_UINT1(pds[16])
298 #define PDS_Date (PDS_Year*10000+PDS_Month*100+PDS_Day)
299 #define PDS_Time (PDS_Hour*100+PDS_Minute)
300 #define PDS_TimeUnit GET_UINT1(pds[17])
301 #define PDS_TimePeriod1 GET_UINT1(pds[18])
302 #define PDS_TimePeriod2 GET_UINT1(pds[19])
303 #define PDS_TimeRange GET_UINT1(pds[20])
304 #define PDS_AvgNum GET_UINT2(pds[21], pds[22])
305 #define PDS_AvgMiss GET_UINT1(pds[23])
306 #define PDS_Century GET_UINT1(pds[24])
307 #define PDS_Subcenter GET_UINT1(pds[25])
308 #define PDS_DecimalScale GET_INT2(pds[26],pds[27])
309
310
311 /* GRIB1 Section 2: Grid Description Section (GDS) */
312
313 #define GDS_Len ((gds) == NULL ? 0 : GET_UINT3(gds[0], gds[1], gds[2]))
314 #define GDS_NV GET_UINT1(gds[ 3])
315 #define GDS_PVPL GET_UINT1(gds[ 4])
316 #define GDS_PV ((gds[3] == 0) ? -1 : (int) gds[4] - 1)
317 #define GDS_PL ((gds[4] == 0xFF) ? -1 : (int) gds[3] * 4 + (int) gds[4] - 1)
318 #define GDS_GridType GET_UINT1(gds[ 5])
319
320
321 /* GRIB1 Triangular grid of DWD */
322 #define GDS_GME_NI2 GET_UINT2(gds[ 6], gds[ 7])
323 #define GDS_GME_NI3 GET_UINT2(gds[ 8], gds[ 9])
324 #define GDS_GME_ND GET_UINT3(gds[10], gds[11], gds[12])
325 #define GDS_GME_NI GET_UINT3(gds[13], gds[14], gds[15])
326 #define GDS_GME_AFlag GET_UINT1(gds[16])
327 #define GDS_GME_LatPP GET_INT3(gds[17], gds[18], gds[19])
328 #define GDS_GME_LonPP GET_INT3(gds[20], gds[21], gds[22])
329 #define GDS_GME_LonMPL GET_INT3(gds[23], gds[24], gds[25])
330 #define GDS_GME_BFlag GET_UINT1(gds[27])
331
332 /* GRIB1 Spectral */
333 #define GDS_PentaJ GET_UINT2(gds[ 6], gds[ 7])
334 #define GDS_PentaK GET_UINT2(gds[ 8], gds[ 9])
335 #define GDS_PentaM GET_UINT2(gds[10], gds[11])
336 #define GDS_RepType GET_UINT1(gds[12])
337 #define GDS_RepMode GET_UINT1(gds[13])
338
339 /* GRIB1 Regular grid */
340 #define GDS_NumLon GET_UINT2(gds[ 6], gds[ 7])
341 #define GDS_NumLat GET_UINT2(gds[ 8], gds[ 9])
342 #define GDS_FirstLat GET_INT3(gds[10], gds[11], gds[12])
343 #define GDS_FirstLon GET_INT3(gds[13], gds[14], gds[15])
344 #define GDS_ResFlag GET_UINT1(gds[16])
345 #define GDS_LastLat GET_INT3(gds[17], gds[18], gds[19])
346 #define GDS_LastLon GET_INT3(gds[20], gds[21], gds[22])
347 #define GDS_LonIncr GET_UINT2(gds[23], gds[24])
348 #define GDS_LatIncr GET_UINT2(gds[25], gds[26])
349 #define GDS_NumPar GET_UINT2(gds[25], gds[26])
350 #define GDS_ScanFlag GET_UINT1(gds[27])
351 #define GDS_LatSP GET_INT3(gds[32], gds[33], gds[34])
352 #define GDS_LonSP GET_INT3(gds[35], gds[36], gds[37])
353 #define GDS_RotAngle (GET_Real(&(gds[38])))
354
355 /* GRIB1 Lambert */
356 #define GDS_Lambert_Lov GET_INT3(gds[17], gds[18], gds[19])
357 #define GDS_Lambert_dx GET_INT3(gds[20], gds[21], gds[22])
358 #define GDS_Lambert_dy GET_INT3(gds[23], gds[24], gds[25])
359 #define GDS_Lambert_ProjFlag GET_UINT1(gds[26])
360 #define GDS_Lambert_LatS1 GET_INT3(gds[28], gds[29], gds[30])
361 #define GDS_Lambert_LatS2 GET_INT3(gds[31], gds[32], gds[33])
362 #define GDS_Lambert_LatSP GET_INT3(gds[34], gds[35], gds[36])
363 #define GDS_Lambert_LonSP GET_INT3(gds[37], gds[37], gds[37])
364
365 /* GRIB1 Section 3: Bit Map Section (BMS) */
366
367 #define BMS_Len ((bms) == NULL ? 0 : GET_UINT3(bms[0], bms[1], bms[2]))
368 #define BMS_UnusedBits (bms[3])
369 #define BMS_Bitmap ((bms) == NULL ? NULL : (bms)+6)
370 #define BMS_BitmapSize (((((bms[0]<<16)+(bms[1]<<8)+bms[2]) - 6)<<3) - bms[3])
371
372 /* GRIB1 Section 4: Binary Data Section (BDS) */
373
374 #define BDS_Len GET_UINT3(bds[0], bds[1], bds[2])
375 #define BDS_Flag (bds[3])
376 #define BDS_BinScale GET_INT2(bds[ 4], bds[ 5])
377 #define BDS_RefValue (decfp2((int)bds[ 6], GET_UINT3(bds[7], bds[8], bds[9])))
378 #define BDS_NumBits ((int) bds[10])
379 #define BDS_RealCoef (decfp2((int)bds[zoff+11], GET_UINT3(bds[zoff+12], bds[zoff+13], bds[zoff+14])))
380 #define BDS_PackData ((int) ((bds[zoff+11]<<8) + bds[zoff+12]))
381 #define BDS_Power GET_INT2(bds[zoff+13], bds[zoff+14])
382 #define BDS_Z (bds[13])
383
384 /* GRIB1 Section 5: End Section (ES) */
385
386 /* GRIB2 */
387
388 #define GRIB2_SECLEN(section) (GET_UINT4(section[0], section[1], section[2], section[3]))
389 #define GRIB2_SECNUM(section) (GET_UINT1(section[4]))
390
391 #endif /* GRIBDECODE_H */
392 #ifndef CGRIBEX_GRIB_ENCODE_H
393 #define CGRIBEX_GRIB_ENCODE_H
394
395 #include <limits.h>
396
397 #define PutnZero(n) \
398 { \
399 for ( size_t i___ = z >= 0 ? (size_t)z : 0; i___ < (size_t)(z+n); i___++ ) lGrib[i___] = 0; \
400 z += n; \
401 }
402
403 #define Put1Byte(Value) (lGrib[z++] = (GRIBPACK)(Value))
404 #define Put2Byte(Value) ((lGrib[z++] = (GRIBPACK)((Value) >> 8)), \
405 (lGrib[z++] = (GRIBPACK)(Value)))
406 #define Put3Byte(Value) ((lGrib[z++] = (GRIBPACK)((Value) >> 16)), \
407 (lGrib[z++] = (GRIBPACK)((Value) >> 8)), \
408 (lGrib[z++] = (GRIBPACK)(Value)))
409 #define Put4Byte(Value) ((lGrib[z++] = (GRIBPACK)((Value) >> 24)), \
410 (lGrib[z++] = (GRIBPACK)((Value) >> 16)), \
411 (lGrib[z++] = (GRIBPACK)((Value) >> 8)), \
412 (lGrib[z++] = (GRIBPACK)(Value)))
413
414 #define Put1Int(Value) {ival = Value; if ( ival < 0 ) ival = 0x80 - ival; Put1Byte(ival);}
415 #define Put2Int(Value) {ival = Value; if ( ival < 0 ) ival = 0x8000 - ival; Put2Byte(ival);}
416 #define Put3Int(Value) {ival = Value; if ( ival < 0 ) ival = 0x800000 - ival; Put3Byte(ival);}
417
418 enum {
419 BitsPerInt = (int) (sizeof(int) * CHAR_BIT),
420 };
421
422
423 #define Put1Real(Value) \
424 { \
425 confp3(Value, &exponent, &mantissa, BitsPerInt, 1); \
426 Put1Byte(exponent); \
427 Put3Byte(mantissa); \
428 }
429
430 #endif /* CGRIBEX_GRIB_ENCODE_H */
431 #ifndef CODEC_COMMON_H
432 #define CODEC_COMMON_H
433 #define gribSwapByteOrder_uint16(ui16) ((uint16_t)((ui16<<8) | (ui16>>8)))
434 #endif /* CODEC_COMMON_H */
435 /*
436 icc -g -Wall -O3 -march=native -std=c99 -qopt-report=5 -DTEST_MINMAXVAL -qopenmp -DOMP_SIMD minmax_val.c
437 result on hama2 (icc 16.0.0):
438 float:
439 minmax_val: fmin: -500000 fmax: 499999 time: 1.22s
440 simd : fmin: -500000 fmax: 499999 time: 1.20s
441 double:
442 minmax_val: fmin: -500000 fmax: 499999 time: 2.86s
443 orig : fmin: -500000 fmax: 499999 time: 2.74s
444 simd : fmin: -500000 fmax: 499999 time: 2.70s
445 avx : fmin: -500000 fmax: 499999 time: 2.99s
446
447 gcc -g -Wall -O3 -march=native -std=c99 -DTEST_MINMAXVAL -fopenmp -DOMP_SIMD -Wa,-q minmax_val.c
448 result on thunder5 (gcc 6.1.0):
449 float:
450 minmax_val: fmin: -500000 fmax: 499999 time: 8.25s
451 simd : fmin: -500000 fmax: 499999 time: 1.24s
452 double:
453 minmax_val: fmin: -500000 fmax: 499999 time: 2.73s
454 orig : fmin: -500000 fmax: 499999 time: 9.24s
455 simd : fmin: -500000 fmax: 499999 time: 2.78s
456 avx : fmin: -500000 fmax: 499999 time: 2.90s
457
458 gcc -g -Wall -O3 -march=native -std=c99 -DTEST_MINMAXVAL minmax_val.c
459 result on bailung (gcc 4.8.2):
460 orig : fmin: -500000 fmax: 499999 time: 4.82s
461 sse2 : fmin: -500000 fmax: 499999 time: 4.83s
462
463 gcc -g -Wall -O3 -march=native -std=c99 -DTEST_MINMAXVAL -fopenmp -DOMP_SIMD -Wa,-q minmax_val.c
464 result on thunder5 (gcc 4.8.2):
465 orig : fmin: -500000 fmax: 499999 time: 3.10s
466 simd : fmin: -500000 fmax: 499999 time: 3.10s # omp simd in gcc 4.9
467 avx : fmin: -500000 fmax: 499999 time: 2.84s
468
469 icc -g -Wall -O3 -march=native -std=c99 -qopt-report=5 -DTEST_MINMAXVAL -openmp -DOMP_SIMD minmax_val.c
470 result on thunder5 (icc 14.0.2):
471 orig : fmin: -500000 fmax: 499999 time: 2.83s
472 simd : fmin: -500000 fmax: 499999 time: 2.83s
473 avx : fmin: -500000 fmax: 499999 time: 2.92s
474
475 xlc_r -g -O3 -qhot -q64 -qarch=auto -qtune=auto -qreport -DTEST_MINMAXVAL minmax_val.c
476 result on blizzard (xlc 12):
477 orig : fmin: -500000 fmax: 499999 time: 7.26s
478 pwr6u6 : fmin: -500000 fmax: 499999 time: 5.92s
479 */
480 #ifdef _ARCH_PWR6
481 #pragma options nostrict
482 #endif
483
484 #ifdef OMP_SIMD
485 #include <omp.h>
486 #endif
487
488 #include <stdlib.h>
489
490 //#undef _GET_X86_COUNTER
491 //#undef _GET_IBM_COUNTER
492 //#undef _GET_MACH_COUNTER
493 //#undef _ARCH_PWR6
494
495 #if defined(_GET_IBM_COUNTER)
496 #include <libhpc.h>
497 #elif defined(_GET_X86_COUNTER)
498 #include <x86intrin.h>
499 #elif defined(_GET_MACH_COUNTER)
500 #include <mach/mach_time.h>
501 #endif
502
503 #if defined(__GNUC__) && !defined(__ICC) && !defined(__clang__)
504 #if (__GNUC__ >= 4) && (__GNUC_MINOR__ >= 4)
505 #define GNUC_PUSH_POP
506 #endif
507 #endif
508
509 #ifndef DISABLE_SIMD
510 #if defined(__GNUC__) && (__GNUC__ >= 4)
511 #elif defined(__ICC) && (__ICC >= 1100)
512 #elif defined(__clang__)
513 #else
514 #define DISABLE_SIMD
515 #endif
516 #endif
517
518 #ifdef DISABLE_SIMD
519 #define DISABLE_SIMD_MINMAXVAL
520 #endif
521
522 #ifndef TEST_MINMAXVAL
523 #define DISABLE_SIMD_MINMAXVAL
524 #endif
525
526 #ifdef DISABLE_SIMD_MINMAXVAL
527 #ifdef ENABLE_AVX
528 #define _ENABLE_AVX
529 #endif
530 #ifdef ENABLE_SSE2
531 #define _ENABLE_SSE2
532 #endif
533 #endif
534
535 #ifndef DISABLE_SIMD_MINMAXVAL
536 #ifdef __AVX__
537 #define _ENABLE_AVX
538 #endif
539 #ifdef __SSE2__
540 #define _ENABLE_SSE2
541 #endif
542 #endif
543
544 #include <float.h>
545 #include <stdint.h>
546 #include <inttypes.h>
547
548 #if defined(_ENABLE_AVX)
549 #include <immintrin.h>
550 #elif defined(_ENABLE_SSE2)
551 #include <emmintrin.h>
552 #endif
553
554
555 #if defined(_ENABLE_AVX)
556
557 static
avx_minmax_val_double(const double * restrict buf,size_t nframes,double * min,double * max)558 void avx_minmax_val_double(const double *restrict buf, size_t nframes, double *min, double *max)
559 {
560 double fmin[4], fmax[4];
561 __m256d current_max, current_min, work;
562
563 // load max and min values into all four slots of the YMM registers
564 current_min = _mm256_set1_pd(*min);
565 current_max = _mm256_set1_pd(*max);
566
567 // Work input until "buf" reaches 32 byte alignment
568 while ( ((unsigned long)buf) % 32 != 0 && nframes > 0) {
569
570 // Load the next double into the work buffer
571 work = _mm256_set1_pd(*buf);
572 current_min = _mm256_min_pd(current_min, work);
573 current_max = _mm256_max_pd(current_max, work);
574 buf++;
575 nframes--;
576 }
577
578 while (nframes >= 16) {
579
580 (void) _mm_prefetch((const char *)(buf+8), _MM_HINT_NTA);
581
582 work = _mm256_load_pd(buf);
583 current_min = _mm256_min_pd(current_min, work);
584 current_max = _mm256_max_pd(current_max, work);
585 buf += 4;
586
587 work = _mm256_load_pd(buf);
588 current_min = _mm256_min_pd(current_min, work);
589 current_max = _mm256_max_pd(current_max, work);
590 buf += 4;
591
592 (void) _mm_prefetch((const char *)(buf+8), _MM_HINT_NTA);
593
594 work = _mm256_load_pd(buf);
595 current_min = _mm256_min_pd(current_min, work);
596 current_max = _mm256_max_pd(current_max, work);
597 buf += 4;
598
599 work = _mm256_load_pd(buf);
600 current_min = _mm256_min_pd(current_min, work);
601 current_max = _mm256_max_pd(current_max, work);
602 buf += 4;
603 nframes -= 16;
604 }
605
606 // work through aligned buffers
607 while (nframes >= 4) {
608 work = _mm256_load_pd(buf);
609 current_min = _mm256_min_pd(current_min, work);
610 current_max = _mm256_max_pd(current_max, work);
611 buf += 4;
612 nframes -= 4;
613 }
614
615 // work through the remainung values
616 while ( nframes > 0) {
617 work = _mm256_set1_pd(*buf);
618 current_min = _mm256_min_pd(current_min, work);
619 current_max = _mm256_max_pd(current_max, work);
620 buf++;
621 nframes--;
622 }
623
624 // find min & max value through shuffle tricks
625
626 work = current_min;
627 work = _mm256_shuffle_pd(work, work, 5);
628 work = _mm256_min_pd (work, current_min);
629 current_min = work;
630 work = _mm256_permute2f128_pd(work, work, 1);
631 work = _mm256_min_pd (work, current_min);
632 _mm256_storeu_pd(fmin, work);
633
634 work = current_max;
635 work = current_max;
636 work = _mm256_shuffle_pd(work, work, 5);
637 work = _mm256_max_pd (work, current_max);
638 current_max = work;
639 work = _mm256_permute2f128_pd(work, work, 1);
640 work = _mm256_max_pd (work, current_max);
641 _mm256_storeu_pd(fmax, work);
642
643 *min = fmin[0];
644 *max = fmax[0];
645
646 return;
647 }
648
649 #elif defined(_ENABLE_SSE2)
650
651 static
sse2_minmax_val_double(const double * restrict buf,size_t nframes,double * min,double * max)652 void sse2_minmax_val_double(const double *restrict buf, size_t nframes, double *min, double *max)
653 {
654 __m128d current_max, current_min, work;
655
656 // load starting max and min values into all slots of the XMM registers
657 current_min = _mm_set1_pd(*min);
658 current_max = _mm_set1_pd(*max);
659
660 // work on input until buf reaches 16 byte alignment
661 while ( ((unsigned long)buf) % 16 != 0 && nframes > 0) {
662
663 // load one double and replicate
664 work = _mm_set1_pd(*buf);
665 current_min = _mm_min_pd(current_min, work);
666 current_max = _mm_max_pd(current_max, work);
667 buf++;
668 nframes--;
669 }
670
671 while (nframes >= 8) {
672 // use 64 byte prefetch for double octetts
673 // __builtin_prefetch(buf+64,0,0); // for GCC 4.3.2 +
674
675 work = _mm_load_pd(buf);
676 current_min = _mm_min_pd(current_min, work);
677 current_max = _mm_max_pd(current_max, work);
678 buf += 2;
679 work = _mm_load_pd(buf);
680 current_min = _mm_min_pd(current_min, work);
681 current_max = _mm_max_pd(current_max, work);
682 buf += 2;
683 work = _mm_load_pd(buf);
684 current_min = _mm_min_pd(current_min, work);
685 current_max = _mm_max_pd(current_max, work);
686 buf += 2;
687 work = _mm_load_pd(buf);
688 current_min = _mm_min_pd(current_min, work);
689 current_max = _mm_max_pd(current_max, work);
690 buf += 2;
691 nframes -= 8;
692 }
693
694 // work through smaller chunks of aligned buffers without prefetching
695 while (nframes >= 2) {
696 work = _mm_load_pd(buf);
697 current_min = _mm_min_pd(current_min, work);
698 current_max = _mm_max_pd(current_max, work);
699 buf += 2;
700 nframes -= 2;
701 }
702
703 // work through the remaining value
704 while ( nframes > 0) {
705 // load the last double and replicate
706 work = _mm_set1_pd(*buf);
707 current_min = _mm_min_pd(current_min, work);
708 current_max = _mm_max_pd(current_max, work);
709 buf++;
710 nframes--;
711 }
712
713 // find final min and max value through shuffle tricks
714 work = current_min;
715 work = _mm_shuffle_pd(work, work, _MM_SHUFFLE2(0, 1));
716 work = _mm_min_pd (work, current_min);
717 _mm_store_sd(min, work);
718 work = current_max;
719 work = _mm_shuffle_pd(work, work, _MM_SHUFFLE2(0, 1));
720 work = _mm_max_pd (work, current_max);
721 _mm_store_sd(max, work);
722
723 return;
724 }
725
726 #endif // SIMD
727
728 #if defined(_ARCH_PWR6)
729
730 #ifndef __fsel
731 static __inline__ double __fsel(double x, double y, double z)
732 __attribute__((always_inline));
733 static __inline__ double
__fsel(double x,double y,double z)734 __fsel(double x, double y, double z)
735 {
736 double r;
737 __asm__("fsel %0,%1,%2,%3" : "=d"(r) : "d"(x),"d"(y),"d"(z));
738 return r;
739 }
740 #endif
741
742 static
pwr6_minmax_val_double_unrolled6(const double * restrict data,size_t datasize,double * fmin,double * fmax)743 void pwr6_minmax_val_double_unrolled6(const double *restrict data, size_t datasize, double *fmin, double *fmax)
744 {
745 #define __UNROLL_DEPTH_1 6
746
747 // to allow pipelining we have to unroll
748
749 {
750 size_t i, j;
751 size_t residual = datasize % __UNROLL_DEPTH_1;
752 size_t ofs = datasize - residual;
753 double register dmin[__UNROLL_DEPTH_1];
754 double register dmax[__UNROLL_DEPTH_1];
755
756 for ( j = 0; j < __UNROLL_DEPTH_1; j++)
757 {
758 dmin[j] = data[0];
759 dmax[j] = data[0];
760 }
761
762 for ( i = 0; i < datasize - residual; i += __UNROLL_DEPTH_1 )
763 {
764 for (j = 0; j < __UNROLL_DEPTH_1; j++)
765 {
766 dmin[j] = __fsel(dmin[j] - data[i+j], data[i+j], dmin[j]);
767 dmax[j] = __fsel(data[i+j] - dmax[j], data[i+j], dmax[j]);
768 }
769 }
770
771 for (j = 0; j < residual; j++)
772 {
773 dmin[j] = __fsel(dmin[j] - data[ofs+j], data[ofs+j], dmin[j]);
774 dmax[j] = __fsel(data[ofs+j] - dmax[j], data[ofs+j], dmax[j]);
775 }
776
777 for ( j = 0; j < __UNROLL_DEPTH_1; j++)
778 {
779 *fmin = __fsel(*fmin - dmin[j], dmin[j], *fmin);
780 *fmax = __fsel(dmax[j] - *fmax, dmax[j], *fmax);
781 }
782 }
783 #undef __UNROLL_DEPTH_1
784 }
785 #endif
786
787 #if defined(TEST_MINMAXVAL) && defined(__GNUC__)
788 static
789 void minmax_val_double_orig(const double *restrict data, size_t datasize, double *fmin, double *fmax) __attribute__ ((noinline));
790 static
791 void minmax_val_double_simd(const double *restrict data, size_t datasize, double *fmin, double *fmax) __attribute__ ((noinline));
792 static
793 void minmax_val_double_omp(const double *restrict data, size_t datasize, double *fmin, double *fmax) __attribute__ ((noinline));
794 static
795 void minmax_val_float(const float *restrict data, long datasize, float *fmin, float *fmax) __attribute__ ((noinline));
796 static
797 void minmax_val_float_simd(const float *restrict data, size_t datasize, float *fmin, float *fmax) __attribute__ ((noinline));
798 #endif
799
800 #if defined(GNUC_PUSH_POP)
801 #pragma GCC push_options
802 #pragma GCC optimize ("O3", "fast-math")
803 #endif
804 static
minmax_val_double_orig(const double * restrict data,size_t datasize,double * fmin,double * fmax)805 void minmax_val_double_orig(const double *restrict data, size_t datasize, double *fmin, double *fmax)
806 {
807 double dmin = *fmin, dmax = *fmax;
808
809 #if defined(CRAY)
810 #pragma _CRI ivdep
811 #elif defined(SX)
812 #pragma vdir nodep
813 #elif defined(__uxp__)
814 #pragma loop novrec
815 #elif defined (__ICC)
816 #pragma ivdep
817 #endif
818 for ( size_t i = 0; i < datasize; ++i )
819 {
820 dmin = (dmin < data[i]) ? dmin : data[i];
821 dmax = (dmax > data[i]) ? dmax : data[i];
822 }
823
824 *fmin = dmin;
825 *fmax = dmax;
826 }
827
828 static
minmax_val_float(const float * restrict data,long idatasize,float * fmin,float * fmax)829 void minmax_val_float(const float *restrict data, long idatasize, float *fmin, float *fmax)
830 {
831 size_t datasize = (size_t)idatasize;
832 float dmin = *fmin, dmax = *fmax;
833
834 #if defined(CRAY)
835 #pragma _CRI ivdep
836 #elif defined(SX)
837 #pragma vdir nodep
838 #elif defined(__uxp__)
839 #pragma loop novrec
840 #elif defined (__ICC)
841 #pragma ivdep
842 #endif
843 for ( size_t i = 0; i < datasize; ++i )
844 {
845 dmin = (dmin < data[i]) ? dmin : data[i];
846 dmax = (dmax > data[i]) ? dmax : data[i];
847 }
848
849 *fmin = dmin;
850 *fmax = dmax;
851 }
852 #if defined(GNUC_PUSH_POP)
853 #pragma GCC pop_options
854 #endif
855
856 // TEST
857 #if defined(OMP_SIMD)
858
859 #if defined(GNUC_PUSH_POP)
860 #pragma GCC push_options
861 #pragma GCC optimize ("O3", "fast-math")
862 #endif
863 static
minmax_val_double_omp(const double * restrict data,size_t datasize,double * fmin,double * fmax)864 void minmax_val_double_omp(const double *restrict data, size_t datasize, double *fmin, double *fmax)
865 {
866 double dmin = *fmin, dmax = *fmax;
867
868 #if defined(_OPENMP)
869 #pragma omp parallel for simd reduction(min:dmin) reduction(max:dmax)
870 #endif
871 for ( size_t i = 0; i < datasize; ++i )
872 {
873 dmin = (dmin < data[i]) ? dmin : data[i];
874 dmax = (dmax > data[i]) ? dmax : data[i];
875 }
876
877 *fmin = dmin;
878 *fmax = dmax;
879 }
880
881 static
minmax_val_double_simd(const double * restrict data,size_t datasize,double * fmin,double * fmax)882 void minmax_val_double_simd(const double *restrict data, size_t datasize, double *fmin, double *fmax)
883 {
884 double dmin = *fmin, dmax = *fmax;
885
886 #ifdef _OPENMP
887 #pragma omp simd reduction(min:dmin) reduction(max:dmax)
888 #endif
889 for ( size_t i = 0; i < datasize; ++i )
890 {
891 dmin = (dmin < data[i]) ? dmin : data[i];
892 dmax = (dmax > data[i]) ? dmax : data[i];
893 }
894
895 *fmin = dmin;
896 *fmax = dmax;
897 }
898
899 static
minmax_val_float_simd(const float * restrict data,size_t datasize,float * fmin,float * fmax)900 void minmax_val_float_simd(const float *restrict data, size_t datasize, float *fmin, float *fmax)
901 {
902 float dmin = *fmin, dmax = *fmax;
903
904 #if defined(_OPENMP)
905 #pragma omp simd reduction(min:dmin) reduction(max:dmax)
906 #endif
907 for ( size_t i = 0; i < datasize; ++i )
908 {
909 dmin = (dmin < data[i]) ? dmin : data[i];
910 dmax = (dmax > data[i]) ? dmax : data[i];
911 }
912
913 *fmin = dmin;
914 *fmax = dmax;
915 }
916 #if defined(GNUC_PUSH_POP)
917 #pragma GCC pop_options
918 #endif
919 #endif
920
921 static
minmax_val_double(const double * restrict data,long idatasize,double * fmin,double * fmax)922 void minmax_val_double(const double *restrict data, long idatasize, double *fmin, double *fmax)
923 {
924 #if defined(_GET_X86_COUNTER) || defined(_GET_MACH_COUNTER)
925 uint64_t start_minmax, end_minmax;
926 #endif
927 size_t datasize = (size_t)idatasize;
928
929 if ( idatasize >= 1 ) ; else return;
930
931 #if defined(_GET_X86_COUNTER)
932 start_minmax = _rdtsc();
933 #endif
934 #if defined(_GET_MACH_COUNTER)
935 start_minmax = mach_absolute_time();
936 #endif
937
938 #if defined(_ENABLE_AVX)
939
940 avx_minmax_val_double(data, datasize, fmin, fmax);
941
942 #elif defined(_ENABLE_SSE2)
943
944 sse2_minmax_val_double(data, datasize, fmin, fmax);
945
946 #else
947
948 #if defined(_ARCH_PWR6)
949 #define __UNROLL_DEPTH_1 6
950
951 // to allow pipelining we have to unroll
952
953 #if defined(_GET_IBM_COUNTER)
954 hpmStart(1, "minmax fsel");
955 #endif
956
957 pwr6_minmax_val_double_unrolled6(data, datasize, fmin, fmax);
958
959 #if defined(_GET_IBM_COUNTER)
960 hpmStop(1);
961 #endif
962
963 #undef __UNROLL_DEPTH_1
964
965 #else // original loop
966
967 #if defined(_GET_IBM_COUNTER)
968 hpmStart(1, "minmax base");
969 #endif
970
971 minmax_val_double_orig(data, datasize, fmin, fmax);
972
973 #if defined(_GET_IBM_COUNTER)
974 hpmStop(1);
975 #endif
976
977 #endif // _ARCH_PWR6 && original loop
978 #endif // SIMD
979
980 #if defined(_GET_X86_COUNTER) || defined(_GET_MACH_COUNTER)
981 #if defined(_GET_X86_COUNTER)
982 end_minmax = _rdtsc();
983 #endif
984 #if defined(_GET_MACH_COUNTER)
985 end_minmax = mach_absolute_time();
986 #endif
987 #if defined(_ENABLE_AVX)
988 printf("AVX minmax cycles:: %" PRIu64 "\n", end_minmax-start_minmax);
989 fprintf (stderr, "AVX min: %lf max: %lf\n", *fmin, *fmax);
990 #elif defined(_ENABLE_SSE2)
991 printf("SSE2 minmax cycles:: %" PRIu64 "\n", end_minmax-start_minmax);
992 fprintf (stderr, "SSE2 min: %lf max: %lf\n", *fmin, *fmax);
993 #else
994 printf("loop minmax cycles:: %" PRIu64 "\n", end_minmax-start_minmax);
995 fprintf (stderr, "loop min: %lf max: %lf\n", *fmin, *fmax);
996 #endif
997 #endif
998
999 return;
1000 }
1001
1002 #if defined(TEST_MINMAXVAL)
1003
1004 #include <stdio.h>
1005 #include <sys/time.h>
1006
1007 static
dtime()1008 double dtime()
1009 {
1010 double tseconds = 0.0;
1011 struct timeval mytime;
1012 gettimeofday(&mytime, NULL);
1013 tseconds = (double) (mytime.tv_sec + (double)mytime.tv_usec*1.0e-6);
1014 return (tseconds);
1015 }
1016
1017 #define NRUN 10000
1018
main(void)1019 int main(void)
1020 {
1021 long datasize = 1000000;
1022 double t_begin, t_end;
1023
1024 printf("datasize %ld\n", datasize);
1025 #if defined(_OPENMP)
1026 printf("_OPENMP=%d\n", _OPENMP);
1027 #endif
1028
1029 #if defined(__ICC)
1030 printf("icc\n");
1031 #elif defined(__clang__)
1032 printf("clang\n");
1033 #elif defined(__GNUC__)
1034 printf("gcc\n");
1035 #endif
1036
1037 {
1038 float fmin, fmax;
1039 float *data_sp = (float*) malloc(datasize*sizeof(float));
1040
1041 for ( long i = 0; i < datasize/2; i++ ) data_sp[i] = (float) (i);
1042 for ( long i = datasize/2; i < datasize; i++ ) data_sp[i] = (float) (-datasize + i);
1043
1044 printf("float:\n");
1045
1046 t_begin = dtime();
1047 for ( int i = 0; i < NRUN; ++i )
1048 {
1049 fmin = fmax = data_sp[0];
1050 minmax_val_float(data_sp, datasize, &fmin, &fmax);
1051 }
1052 t_end = dtime();
1053 printf("minmax_val: fmin: %ld fmax: %ld time: %6.2fs\n", (long)fmin, (long) fmax, t_end-t_begin);
1054
1055 #if defined(OMP_SIMD)
1056 t_begin = dtime();
1057 for ( int i = 0; i < NRUN; ++i )
1058 {
1059 fmin = fmax = data_sp[0];
1060 minmax_val_float_simd(data_sp, datasize, &fmin, &fmax);
1061 }
1062 t_end = dtime();
1063 printf("simd : fmin: %ld fmax: %ld time: %6.2fs\n", (long)fmin, (long) fmax, t_end-t_begin);
1064 #endif
1065
1066 free(data_sp);
1067 }
1068
1069 {
1070 double fmin, fmax;
1071 double *data_dp = (double*) malloc(datasize*sizeof(double));
1072
1073 // for ( long i = datasize-1; i >= 0; i-- ) data[i] = (double) (-datasize/2 + i);
1074 for ( long i = 0; i < datasize/2; i++ ) data_dp[i] = (double) (i);
1075 for ( long i = datasize/2; i < datasize; i++ ) data_dp[i] = (double) (-datasize + i);
1076
1077 printf("double:\n");
1078
1079 t_begin = dtime();
1080 for ( int i = 0; i < NRUN; ++i )
1081 {
1082 fmin = fmax = data_dp[0];
1083 minmax_val_double(data_dp, datasize, &fmin, &fmax);
1084 }
1085 t_end = dtime();
1086 printf("minmax_val: fmin: %ld fmax: %ld time: %6.2fs\n", (long)fmin, (long) fmax, t_end-t_begin);
1087
1088 t_begin = dtime();
1089 for ( int i = 0; i < NRUN; ++i )
1090 {
1091 fmin = fmax = data_dp[0];
1092 minmax_val_double_orig(data_dp, datasize, &fmin, &fmax);
1093 }
1094 t_end = dtime();
1095 printf("orig : fmin: %ld fmax: %ld time: %6.2fs\n", (long)fmin, (long) fmax, t_end-t_begin);
1096
1097 #if defined(OMP_SIMD)
1098 t_begin = dtime();
1099 for ( int i = 0; i < NRUN; ++i )
1100 {
1101 fmin = fmax = data_dp[0];
1102 minmax_val_double_simd(data_dp, datasize, &fmin, &fmax);
1103 }
1104 t_end = dtime();
1105 printf("simd : fmin: %ld fmax: %ld time: %6.2fs\n", (long)fmin, (long) fmax, t_end-t_begin);
1106
1107 t_begin = dtime();
1108 for ( int i = 0; i < NRUN; ++i )
1109 {
1110 fmin = fmax = data_dp[0];
1111 minmax_val_double_omp(data_dp, datasize, &fmin, &fmax);
1112 }
1113 t_end = dtime();
1114 printf("openmp %d : fmin: %ld fmax: %ld time: %6.2fs\n", omp_get_max_threads(), (long)fmin, (long) fmax, t_end-t_begin);
1115 #endif
1116
1117 #if defined(_ENABLE_AVX)
1118 t_begin = dtime();
1119 for ( int i = 0; i < NRUN; ++i )
1120 {
1121 fmin = fmax = data_dp[0];
1122 avx_minmax_val_double(data_dp, datasize, &fmin, &fmax);
1123 }
1124 t_end = dtime();
1125 printf("avx : fmin: %ld fmax: %ld time: %6.2fs\n", (long)fmin, (long) fmax, t_end-t_begin);
1126 #elif defined(_ENABLE_SSE2)
1127 t_begin = dtime();
1128 for ( int i = 0; i < NRUN; ++i )
1129 {
1130 fmin = fmax = data_dp[0];
1131 sse2_minmax_val_double(data_dp, datasize, &fmin, &fmax);
1132 }
1133 t_end = dtime();
1134 printf("sse2 : fmin: %ld fmax: %ld time: %6.2fs\n", (long)fmin, (long) fmax, t_end-t_begin);
1135 #endif
1136 #if defined(_ARCH_PWR6)
1137 t_begin = dtime();
1138 for ( int i = 0; i < NRUN; ++i )
1139 {
1140 fmin = fmax = data_dp[0];
1141 pwr6_minmax_val_double_unrolled6(data_dp, datasize, &fmin, &fmax);
1142 }
1143 t_end = dtime();
1144 printf("pwr6u6 : fmin: %ld fmax: %ld time: %6.2fs\n", (long)fmin, (long) fmax, t_end-t_begin);
1145 #endif
1146 free(data_dp);
1147 }
1148
1149 return (0);
1150 }
1151 #endif // TEST_MINMAXVAL
1152
1153 #undef DISABLE_SIMD_MINMAXVAL
1154 #undef _ENABLE_AVX
1155 #undef _ENABLE_SSE2
1156 #undef GNUC_PUSH_POP
1157 /*
1158 ### new version with gribSwapByteOrder_uint16()
1159 icc -g -Wall -O3 -march=native -std=c99 -qopt-report=5 -DTEST_ENCODE encode_array.c
1160 result on hama2 (icc 16.0.2):
1161 float:
1162 orig: val1: 1 val2: 1 val3: 2 valn: 66 time: 1.8731s
1163 unrolled: val1: 1 val2: 1 val3: 2 valn: 66 time: 2.0898s
1164 double:
1165 orig: val1: 1 val2: 1 val3: 2 valn: 66 time: 3.68089s
1166 unrolled: val1: 1 val2: 1 val3: 2 valn: 66 time: 4.30798s
1167 avx: val1: 1 val2: 1 val3: 2 valn: 66 time: 4.23864s
1168
1169 gcc -g -Wall -O3 -march=native -Wa,-q -std=c99 -DTEST_ENCODE encode_array.c
1170 result on hama2 (gcc 6.1.0):
1171 float:
1172 orig: val1: 1 val2: 1 val3: 2 valn: 66 time: 2.22871s
1173 unrolled: val1: 1 val2: 1 val3: 2 valn: 66 time: 2.30281s
1174 double:
1175 orig: val1: 1 val2: 1 val3: 2 valn: 66 time: 4.2669s
1176 unrolled: val1: 1 val2: 1 val3: 2 valn: 66 time: 4.81643s
1177 avx: val1: 1 val2: 1 val3: 2 valn: 66 time: 3.98415s
1178
1179 ###
1180 icc -g -Wall -O3 -march=native -std=c99 -qopt-report=5 -DTEST_ENCODE encode_array.c
1181 result on hama2 (icc 16.0.0):
1182 float:
1183 orig: val1: 1 val2: 1 val3: 2 valn: 66 time: 9.10691s
1184 unrolled: val1: 1 val2: 1 val3: 2 valn: 66 time: 8.63584s
1185 double:
1186 orig: val1: 1 val2: 1 val3: 2 valn: 66 time: 13.5768s
1187 unrolled: val1: 1 val2: 1 val3: 2 valn: 66 time: 9.17742s
1188 avx: val1: 1 val2: 1 val3: 2 valn: 66 time: 3.9488s
1189
1190 gcc -g -Wall -O3 -std=c99 -DTEST_ENCODE encode_array.c
1191 result on hama2 (gcc 5.2.0):
1192 float:
1193 orig: val1: 1 val2: 1 val3: 2 valn: 66 time: 5.32775s
1194 unrolled: val1: 1 val2: 1 val3: 2 valn: 66 time: 7.87125s
1195 double:
1196 orig: val1: 1 val2: 1 val3: 2 valn: 66 time: 7.85873s
1197 unrolled: val1: 1 val2: 1 val3: 2 valn: 66 time: 12.9979s
1198
1199 ###
1200 gcc -g -Wall -O3 -march=native -std=c99 -DTEST_ENCODE encode_array.c
1201 result on bailung (gcc 4.7):
1202 orig : val1: 1 val2: 1 val3: 2 valn: 66 time: 8.4166s
1203 sse41 : val1: 1 val2: 1 val3: 2 valn: 66 time: 7.1522s
1204
1205 gcc -g -Wall -O3 -march=native -std=c99 -DTEST_ENCODE encode_array.c
1206 result on thunder5 (gcc 4.7):
1207 orig : val1: 1 val2: 1 val3: 2 valn: 66 time: 6.21976s
1208 avx : val1: 1 val2: 1 val3: 2 valn: 66 time: 4.54485s
1209
1210 icc -g -Wall -O3 -march=native -std=c99 -vec-report=1 -DTEST_ENCODE encode_array.c
1211 result on thunder5 (icc 13.2):
1212 orig : val1: 1 val2: 1 val3: 2 valn: 66 time: 14.6279s
1213 avx : val1: 1 val2: 1 val3: 2 valn: 66 time: 4.9776s
1214
1215 xlc_r -g -O3 -qhot -q64 -qarch=auto -qtune=auto -qreport -DTEST_ENCODE encode_array.c
1216 result on blizzard (xlc 12):
1217 orig : val1: 1 val2: 1 val3: 2 valn: 66 time: 132.25s
1218 unrolled: val1: 1 val2: 1 val3: 2 valn: 66 time: 27.202s
1219 orig : val1: 1 val2: 1 val3: 2 valn: 66 time: 106.627s // without -qhot
1220 unrolled: val1: 1 val2: 1 val3: 2 valn: 66 time: 39.929s // without -qhot
1221 */
1222 #ifdef _ARCH_PWR6
1223 #pragma options nostrict
1224 #endif
1225
1226 #ifdef TEST_ENCODE
1227 #include <stdio.h>
1228 #include <stdlib.h>
1229 #define GRIBPACK unsigned char
1230
1231 #ifndef HOST_ENDIANNESS
1232 #ifdef __cplusplus
1233 static const uint32_t HOST_ENDIANNESS_temp[1] = { UINT32_C(0x00030201) };
1234 #define HOST_ENDIANNESS (((const unsigned char *)HOST_ENDIANNESS_temp)[0])
1235 #else
1236 #define HOST_ENDIANNESS (((const unsigned char *)&(const uint32_t[1]){UINT32_C(0x00030201)})[0])
1237 #endif
1238 #endif
1239
1240 #define U_BYTEORDER
1241 #define IS_BIGENDIAN() (HOST_ENDIANNESS == 0)
1242 #define Error(x,y)
1243 #endif
1244
1245 //#undef _GET_X86_COUNTER
1246 //#undef _GET_MACH_COUNTER
1247 //#undef _GET_IBM_COUNTER
1248 //#undef _ARCH_PWR6
1249
1250 #if defined _GET_IBM_COUNTER
1251 #include <libhpc.h>
1252 #elif defined _GET_X86_COUNTER
1253 #include <x86intrin.h>
1254 #elif defined _GET_MACH_COUNTER
1255 #include <mach/mach_time.h>
1256 #endif
1257
1258 #include <stdint.h>
1259 #include <math.h>
1260
1261 #ifndef DISABLE_SIMD
1262 #if defined(__GNUC__) && (__GNUC__ >= 4)
1263 #elif defined(__ICC) && (__ICC >= 1100)
1264 #elif defined(__clang__)
1265 #else
1266 #define DISABLE_SIMD
1267 #endif
1268 #endif
1269
1270 #ifdef DISABLE_SIMD
1271 #define DISABLE_SIMD_ENCODE
1272 #endif
1273
1274 //#define DISABLE_SIMD_ENCODE
1275
1276 #ifdef DISABLE_SIMD_ENCODE
1277 # ifdef ENABLE_AVX
1278 # define _ENABLE_AVX
1279 # endif
1280 # ifdef ENABLE_SSE4_1
1281 # define _ENABLE_SSE4_1
1282 # endif
1283 #endif
1284
1285 #ifndef DISABLE_SIMD_ENCODE
1286 # ifdef __AVX__
1287 # define _ENABLE_AVX
1288 # endif
1289 # ifdef __SSE4_1__
1290 # define _ENABLE_SSE4_1
1291 # endif
1292 #endif
1293
1294 #if defined _ENABLE_AVX
1295 #include <immintrin.h>
1296 #elif defined _ENABLE_SSE4_1
1297 #include <smmintrin.h>
1298 #endif
1299
1300 #if defined _ENABLE_AVX
1301
1302 static
avx_encode_array_2byte_double(size_t datasize,unsigned char * restrict lGrib,const double * restrict data,double zref,double factor,size_t * gz)1303 void avx_encode_array_2byte_double(size_t datasize,
1304 unsigned char * restrict lGrib,
1305 const double * restrict data,
1306 double zref, double factor, size_t *gz)
1307 {
1308 size_t i, j, residual;
1309 const double *dval = data;
1310 __m128i *sgrib = (__m128i *) (lGrib+(*gz));
1311
1312 const __m128i swap = _mm_set_epi8(14, 15, 12, 13, 10, 11, 8, 9, 6, 7, 4, 5, 2, 3, 0, 1);
1313
1314 const __m256d c0 = _mm256_set1_pd(zref);
1315 const __m256d c1 = _mm256_set1_pd(factor);
1316 const __m256d c2 = _mm256_set1_pd(0.5);
1317
1318 __m256d d0, d3, d2, d1;
1319 __m128i i0, i1, i2, i3;
1320 __m128i s0, s1;
1321
1322 residual = datasize % 16;
1323
1324 for (i = 0; i < (datasize-residual); i += 16)
1325 {
1326 (void) _mm_prefetch((const char*)(dval+8), _MM_HINT_NTA);
1327 //_____________________________________________________________________________
1328
1329 d0 = _mm256_loadu_pd (dval);
1330 d0 = _mm256_sub_pd (d0, c0);
1331 d0 = _mm256_mul_pd (d0, c1);
1332 d0 = _mm256_add_pd (d0, c2);
1333
1334 i0 = _mm256_cvttpd_epi32 (d0);
1335
1336 //_____________________________________________________________________________
1337
1338 d1 = _mm256_loadu_pd (dval+4);
1339 d1 = _mm256_sub_pd (d1, c0);
1340 d1 = _mm256_mul_pd (d1, c1);
1341 d1 = _mm256_add_pd (d1, c2);
1342
1343 i1 = _mm256_cvttpd_epi32 (d1);
1344
1345 //_____________________________________________________________________________
1346
1347 s0 = _mm_packus_epi32(i0, i1);
1348 s0 = _mm_shuffle_epi8 (s0, swap);
1349 (void) _mm_storeu_si128 (sgrib, s0);
1350
1351 //_____________________________________________________________________________
1352
1353 (void) _mm_prefetch((const char*)(dval+16), _MM_HINT_NTA);
1354
1355 //_____________________________________________________________________________
1356
1357 d2 = _mm256_loadu_pd (dval+8);
1358 d2 = _mm256_sub_pd (d2, c0);
1359 d2 = _mm256_mul_pd (d2, c1);
1360 d2 = _mm256_add_pd (d2, c2);
1361
1362 i2 = _mm256_cvttpd_epi32 (d2);
1363
1364 //_____________________________________________________________________________
1365
1366 d3 = _mm256_loadu_pd (dval+12);
1367 d3 = _mm256_sub_pd (d3, c0);
1368 d3 = _mm256_mul_pd (d3, c1);
1369 d3 = _mm256_add_pd (d3, c2);
1370
1371 i3 = _mm256_cvttpd_epi32 (d3);
1372
1373 //_____________________________________________________________________________
1374
1375 s1 = _mm_packus_epi32(i2, i3);
1376 s1 = _mm_shuffle_epi8 (s1, swap);
1377 (void) _mm_storeu_si128 (sgrib+1, s1);
1378
1379 //_____________________________________________________________________________
1380
1381 dval += 16;
1382 sgrib += 2;
1383 }
1384
1385 if (i != datasize)
1386 {
1387 uint16_t ui16;
1388 for ( j = i; j < datasize; j++ )
1389 {
1390 ui16 = (uint16_t) ((data[j] - zref) * factor + 0.5);
1391 lGrib[*gz+2*j ] = ui16 >> 8;
1392 lGrib[*gz+2*j+1] = ui16;
1393 }
1394 }
1395
1396 *gz += 2*datasize;
1397
1398 return;
1399 }
1400
1401 #define grib_encode_array_2byte_double avx_encode_array_2byte_double
1402
1403 #elif defined _ENABLE_SSE4_1
1404
1405 static
sse41_encode_array_2byte_double(size_t datasize,unsigned char * restrict lGrib,const double * restrict data,double zref,double factor,size_t * gz)1406 void sse41_encode_array_2byte_double(size_t datasize,
1407 unsigned char * restrict lGrib,
1408 const double * restrict data,
1409 double zref, double factor, size_t *gz)
1410 {
1411 size_t i, j, residual;
1412 const double *dval = data;
1413 __m128i *sgrib = (__m128i *) (lGrib+(*gz));
1414
1415 const __m128i swap = _mm_set_epi8(14, 15, 12, 13, 10, 11, 8, 9, 6, 7, 4, 5, 2, 3, 0, 1);
1416
1417 const __m128d c0 = _mm_set1_pd(zref);
1418 const __m128d c1 = _mm_set1_pd(factor);
1419 const __m128d c2 = _mm_set1_pd(0.5);
1420
1421 __m128d d0, d4, d3, d2, d1;
1422 __m128i i0, i1, i2, i3, i4;
1423 __m128i s0, s1;
1424
1425 residual = datasize % 16;
1426
1427 for (i = 0; i < (datasize-residual); i += 16)
1428 {
1429 (void) _mm_prefetch((const char*)(dval+8), _MM_HINT_NTA);
1430 //_____________________________________________________________________________
1431
1432 d0 = _mm_loadu_pd (dval);
1433 d0 = _mm_sub_pd (d0, c0);
1434 d0 = _mm_mul_pd (d0, c1);
1435 d0 = _mm_add_pd (d0, c2);
1436
1437 d4 = _mm_loadu_pd (dval+2);
1438 d4 = _mm_sub_pd (d4, c0);
1439 d4 = _mm_mul_pd (d4, c1);
1440 d4 = _mm_add_pd (d4, c2);
1441
1442 i0 = _mm_cvttpd_epi32 (d0);
1443 i4 = _mm_cvttpd_epi32 (d4);
1444 i0 = _mm_unpacklo_epi64 (i0, i4);
1445
1446 //_____________________________________________________________________________
1447
1448 d1 = _mm_loadu_pd (dval+4);
1449 d1 = _mm_sub_pd (d1, c0);
1450 d1 = _mm_mul_pd (d1, c1);
1451 d1 = _mm_add_pd (d1, c2);
1452
1453 d4 = _mm_loadu_pd (dval+6);
1454 d4 = _mm_sub_pd (d4, c0);
1455 d4 = _mm_mul_pd (d4, c1);
1456 d4 = _mm_add_pd (d4, c2);
1457
1458 i1 = _mm_cvttpd_epi32 (d1);
1459 i4 = _mm_cvttpd_epi32 (d4);
1460 i1 = _mm_unpacklo_epi64 (i1, i4);
1461
1462 //_____________________________________________________________________________
1463
1464 s0 = _mm_packus_epi32(i0, i1);
1465 s0 = _mm_shuffle_epi8 (s0, swap);
1466 (void) _mm_storeu_si128 (sgrib, s0);
1467
1468 //_____________________________________________________________________________
1469
1470 (void) _mm_prefetch((const char*)(dval+16), _MM_HINT_NTA);
1471
1472 //_____________________________________________________________________________
1473
1474 d2 = _mm_loadu_pd (dval+8);
1475 d2 = _mm_sub_pd (d2, c0);
1476 d2 = _mm_mul_pd (d2, c1);
1477 d2 = _mm_add_pd (d2, c2);
1478
1479 d4 = _mm_loadu_pd (dval+10);
1480 d4 = _mm_sub_pd (d4, c0);
1481 d4 = _mm_mul_pd (d4, c1);
1482 d4 = _mm_add_pd (d4, c2);
1483
1484 i2 = _mm_cvttpd_epi32 (d2);
1485 i4 = _mm_cvttpd_epi32 (d4);
1486 i2 = _mm_unpacklo_epi64 (i2, i4);
1487
1488 //_____________________________________________________________________________
1489
1490 d3 = _mm_loadu_pd (dval+12);
1491 d3 = _mm_sub_pd (d3, c0);
1492 d3 = _mm_mul_pd (d3, c1);
1493 d3 = _mm_add_pd (d3, c2);
1494
1495 d4 = _mm_loadu_pd (dval+14);
1496 d4 = _mm_sub_pd (d4, c0);
1497 d4 = _mm_mul_pd (d4, c1);
1498 d4 = _mm_add_pd (d4, c2);
1499
1500 i3 = _mm_cvttpd_epi32 (d3);
1501 i4 = _mm_cvttpd_epi32 (d4);
1502 i3 = _mm_unpacklo_epi64 (i3, i4);
1503
1504 //_____________________________________________________________________________
1505
1506 s1 = _mm_packus_epi32(i2, i3);
1507 s1 = _mm_shuffle_epi8 (s1, swap);
1508 (void) _mm_storeu_si128 (sgrib+1, s1);
1509
1510 //_____________________________________________________________________________
1511
1512 dval += 16;
1513 sgrib += 2;
1514 }
1515
1516 if (i != datasize)
1517 {
1518 uint16_t ui16;
1519 for ( j = i; j < datasize; j++ )
1520 {
1521 ui16 = (uint16_t) ((data[j] - zref) * factor + 0.5);
1522 lGrib[*gz+2*j ] = ui16 >> 8;
1523 lGrib[*gz+2*j+1] = ui16;
1524 }
1525 }
1526
1527 *gz += 2*datasize;
1528
1529 return;
1530 }
1531
1532 #define grib_encode_array_2byte_double sse41_encode_array_2byte_double
1533
1534 #else
1535
1536 #define grib_encode_array_2byte_double encode_array_2byte_double
1537
1538 #endif // SIMD variants
1539
1540
1541 #ifdef TEST_ENCODE
1542
1543 #define CAT(X,Y) X##_##Y
1544 #define TEMPLATE(X,Y) CAT(X,Y)
1545
1546 #ifdef T
1547 #undef T
1548 #endif
1549 #define T double
1550
1551 #ifdef T
1552 #undef T
1553 #endif
1554 #define T float
1555
1556
1557 #include <sys/time.h>
1558
1559 static
dtime()1560 double dtime()
1561 {
1562 double tseconds = 0.0;
1563 struct timeval mytime;
1564 gettimeofday(&mytime, NULL);
1565 tseconds = (double) (mytime.tv_sec + (double)mytime.tv_usec*1.0e-6);
1566 return (tseconds);
1567 }
1568
1569
1570 static
pout(char * name,int s,unsigned char * lgrib,long datasize,double tt)1571 void pout(char *name, int s, unsigned char *lgrib, long datasize, double tt)
1572 {
1573 printf("%8s: val1: %d val2: %d val3: %d valn: %d time: %gs\n",
1574 name, (int) lgrib[s*1+1], (int) lgrib[s*2+1], (int) lgrib[s*3+1], (int) lgrib[2*datasize-1], tt);
1575 }
1576
main(void)1577 int main(void)
1578 {
1579 enum {
1580 datasize = 1000000,
1581 NRUN = 10000,
1582 };
1583
1584 double t_begin, t_end;
1585
1586 float *dataf = (float*) malloc(datasize*sizeof(float));
1587 double *data = (double*) malloc(datasize*sizeof(double));
1588 unsigned char *lgrib = (unsigned char*) malloc(2*datasize*sizeof(unsigned char));
1589
1590 for ( long i = 0; i < datasize; ++i ) dataf[i] = (float) (-datasize/2 + i);
1591 for ( long i = 0; i < datasize; ++i ) data[i] = (double) (-datasize/2 + i);
1592
1593 int PackStart = 0;
1594 int nbpv = 16;
1595 double zref = data[0];
1596 size_t z;
1597 double factor = 0.00390625;
1598 int s = 256;
1599
1600 if ( 0 )
1601 {
1602 encode_array_float(0, 0, 0, NULL, NULL, 0, 0, NULL);
1603 encode_array_double(0, 0, 0, NULL, NULL, 0, 0, NULL);
1604 }
1605
1606 #if defined(__ICC)
1607 printf("icc\n");
1608 #elif defined(__clang__)
1609 printf("clang\n");
1610 #elif defined(__GNUC__)
1611 printf("gcc\n");
1612 #endif
1613
1614 printf("float:\n");
1615
1616 t_begin = dtime();
1617 for ( int i = 0; i < NRUN; ++i )
1618 {
1619 z = 0;
1620 encode_array_2byte_float(datasize, lgrib, dataf, (float)zref, (float)factor, &z);
1621 }
1622 t_end = dtime();
1623 pout("orig", s, lgrib, datasize, t_end-t_begin);
1624
1625 t_begin = dtime();
1626 for ( int i = 0; i < NRUN; ++i )
1627 {
1628 z = 0;
1629 encode_array_unrolled_float(nbpv, PackStart, datasize, lgrib, dataf, (float)zref, (float)factor, &z);
1630 }
1631 t_end = dtime();
1632 pout("unrolled", s, lgrib, datasize, t_end-t_begin);
1633
1634 printf("double:\n");
1635
1636 t_begin = dtime();
1637 for ( int i = 0; i < NRUN; ++i )
1638 {
1639 z = 0;
1640 encode_array_2byte_double(datasize, lgrib, data, zref, factor, &z);
1641 }
1642 t_end = dtime();
1643 pout("orig", s, lgrib, datasize, t_end-t_begin);
1644
1645 t_begin = dtime();
1646 for ( int i = 0; i < NRUN; ++i )
1647 {
1648 z = 0;
1649 encode_array_unrolled_double(nbpv, PackStart, datasize, lgrib, data, zref, factor, &z);
1650 }
1651 t_end = dtime();
1652 pout("unrolled", s, lgrib, datasize, t_end-t_begin);
1653
1654 #if defined _ENABLE_AVX
1655 t_begin = dtime();
1656 for ( int i = 0; i < NRUN; ++i )
1657 {
1658 z = 0;
1659 avx_encode_array_2byte_double(datasize, lgrib, data, zref, factor, &z);
1660 }
1661 t_end = dtime();
1662 pout("avx", s, lgrib, datasize, t_end-t_begin);
1663 #elif defined _ENABLE_SSE4_1
1664 t_begin = dtime();
1665 for ( int i = 0; i < NRUN; ++i )
1666 {
1667 z = 0;
1668 sse41_encode_array_2byte_double(datasize, lgrib, data, zref, factor, &z);
1669 }
1670 t_end = dtime();
1671 pout("sse41", s, lgrib, datasize, t_end-t_begin);
1672 #endif
1673
1674 return 0;
1675 }
1676 #endif // TEST_ENCODE
1677
1678 #undef DISABLE_SIMD_ENCODE
1679 #undef _ENABLE_AVX
1680 #undef _ENABLE_SSE4_1
1681
1682
confp3(double pval,int * kexp,int * kmant,int kbits,int kround)1683 void confp3(double pval, int *kexp, int *kmant, int kbits, int kround)
1684 {
1685 /*
1686
1687 Purpose:
1688 --------
1689
1690 Convert floating point number from machine
1691 representation to GRIB representation.
1692
1693 Input Parameters:
1694 -----------------
1695
1696 pval - Floating point number to be converted.
1697 kbits - Number of bits in computer word.
1698 kround - Conversion type.
1699 0 , Closest number in GRIB format less than
1700 original number.
1701 1 , Closest number in GRIB format to the
1702 original number (equal to, greater than or
1703 less than original number).
1704
1705 Output Parameters:
1706 ------------------
1707
1708 kexp - 8 Bit signed exponent.
1709 kmant - 24 Bit mantissa.
1710
1711 Method:
1712 -------
1713
1714 Floating point number represented as 8 bit signed
1715 exponent and 24 bit mantissa in integer values.
1716
1717 Externals.
1718 ----------
1719
1720 decfp2 - Decode from IBM floating point format.
1721
1722 Reference:
1723 ----------
1724
1725 WMO Manual on Codes re GRIB representation.
1726
1727 Comments:
1728 ---------
1729
1730 Routine aborts if an invalid conversion type parameter
1731 is used or if a 24 bit mantissa is not produced.
1732
1733 Author:
1734 -------
1735
1736 John Hennessy ECMWF 18.06.91
1737
1738 Modifications:
1739 --------------
1740
1741 Uwe Schulzweida MPIfM 01/04/2001
1742
1743 Convert to C from EMOS library version 130
1744
1745 Uwe Schulzweida MPIfM 02/08/2002
1746
1747 - speed up by factor 1.6 on NEC SX6
1748 - replace 1.0 / pow(16.0, (double)(iexp - 70)) by rpow16m70tab[iexp]
1749 */
1750
1751 // extern int CGRIBEX_Debug;
1752
1753 /* ----------------------------------------------------------------- */
1754 /* Section 1 . Initialise */
1755 /* ----------------------------------------------------------------- */
1756
1757 // Check conversion type parameter.
1758
1759 int iround = kround;
1760 if ( iround != 0 && iround != 1 )
1761 {
1762 Error("Invalid conversion type = %d", iround);
1763
1764 // If not aborting, arbitrarily set rounding to 'up'.
1765 iround = 1;
1766 }
1767
1768 /* ----------------------------------------------------------------- */
1769 /* Section 2 . Convert value of zero. */
1770 /* ----------------------------------------------------------------- */
1771
1772 if (fabs(pval) <= 0)
1773 {
1774 *kexp = 0;
1775 *kmant = 0;
1776 goto LABEL900;
1777 }
1778
1779 /* ----------------------------------------------------------------- */
1780 /* Section 3 . Convert other values. */
1781 /* ----------------------------------------------------------------- */
1782 {
1783 const double zeps = (kbits != 32) ? 1.0e-12 : 1.0e-8;
1784 double zref = pval;
1785
1786 // Sign of value.
1787 const int isign = (zref >= 0.0) ? 0 : 128;
1788 zref = fabs(zref);
1789
1790 // Exponent.
1791 int iexp = (int) (log(zref)/log(16.0) + 65.0 + zeps);
1792
1793 // only ANSI C99 has log2
1794 // iexp = (int) (log2(zref) * 0.25 + 65.0 + zeps);
1795
1796 if ( iexp < 0 ) iexp = 0;
1797 if ( iexp > 127 ) iexp = 127;
1798
1799 // double rpowref = zref / pow(16.0, (double)(iexp - 70));
1800 double rpowref = ldexp(zref, 4 * -(iexp - 70));
1801
1802 // Mantissa.
1803 if ( iround == 0 )
1804 {
1805 /* Closest number in GRIB format less than original number. */
1806 /* Truncate for positive numbers. */
1807 /* Round up for negative numbers. */
1808 *kmant = (isign == 0) ? (int)rpowref : (int)lround(rpowref + 0.5);
1809 }
1810 else
1811 {
1812 /* Closest number in GRIB format to the original number */
1813 /* (equal to, greater than or less than original number). */
1814 *kmant = (int)lround(rpowref);
1815 }
1816
1817 /* Check that mantissa value does not exceed 24 bits. */
1818 /* If it does, adjust the exponent upwards and recalculate the mantissa. */
1819 /* 16777215 = 2**24 - 1 */
1820 if ( *kmant > 16777215 )
1821 {
1822
1823 LABEL350:
1824
1825 ++iexp;
1826
1827 // Check for exponent overflow during adjustment
1828 if ( iexp > 127 )
1829 {
1830 Message("Exponent overflow");
1831 Message("Original number = %30.20f", pval);
1832 Message("Sign = %3d, Exponent = %3d, Mantissa = %12d", isign, iexp, *kmant);
1833
1834 Error("Exponent overflow");
1835
1836 // If not aborting, arbitrarily set value to zero
1837 Message("Value arbitrarily set to zero.");
1838 *kexp = 0;
1839 *kmant = 0;
1840 goto LABEL900;
1841 }
1842
1843 rpowref = ldexp(zref, 4 * -(iexp - 70));
1844
1845 if ( iround == 0 )
1846 {
1847 /* Closest number in GRIB format less than original number. */
1848 /* Truncate for positive numbers. */
1849 /* Round up for negative numbers. */
1850 *kmant = (isign == 0) ? (int)rpowref : (int)lround(rpowref + 0.5);
1851 }
1852 else
1853 {
1854 /* Closest number in GRIB format to the original number */
1855 /* (equal to, greater or less than original number). */
1856 *kmant = (int)lround(rpowref);
1857 }
1858
1859 // Repeat calculation (with modified exponent) if still have mantissa overflow.
1860 if ( *kmant > 16777215 ) goto LABEL350;
1861 }
1862
1863 // Add sign bit to exponent.
1864 *kexp = iexp + isign;
1865 }
1866
1867 /* ----------------------------------------------------------------- */
1868 /* Section 9. Return */
1869 /* ----------------------------------------------------------------- */
1870
1871 LABEL900:
1872 /*
1873 if ( CGRIBEX_Debug )
1874 {
1875 double zval;
1876
1877 Message("Conversion type parameter = %4d", kround);
1878 Message("Original number = %30.20f", pval);
1879
1880 zval = decfp2(*kexp, *kmant);
1881
1882 Message("Converted to %30.20f", zval);
1883 Message("Sign = %3d, Exponent = %3d, Mantissa = %12d", isign, iexp, *kmant);
1884 }
1885 */
1886 return;
1887 } /* confp3 */
1888 #include <math.h>
1889
1890
decfp2(int kexp,int kmant)1891 double decfp2(int kexp, int kmant)
1892 {
1893 /*
1894
1895 Purpose:
1896 --------
1897
1898 Convert GRIB representation of a floating point
1899 number to machine representation.
1900
1901 Input Parameters:
1902 -----------------
1903
1904 kexp - 8 Bit signed exponent.
1905 kmant - 24 Bit mantissa.
1906
1907 Output Parameters:
1908 ------------------
1909
1910 Return value - Floating point number represented
1911 by kexp and kmant.
1912
1913 Method:
1914 -------
1915
1916 Floating point number represented as 8 bit exponent
1917 and 24 bit mantissa in integer values converted to
1918 machine floating point format.
1919
1920 Externals:
1921 ----------
1922
1923 None.
1924
1925 Reference:
1926 ----------
1927
1928 WMO Manual on Codes re GRIB representation.
1929
1930 Comments:
1931 ---------
1932
1933 Rewritten from DECFP, to conform to programming standards.
1934 Sign bit on 0 value now ignored, if present.
1935 If using 32 bit reals, check power of 16 is not so small as to
1936 cause overflows (underflows!); this causes warning to be given
1937 on Fujitsus.
1938
1939 Author:
1940 -------
1941
1942 John Hennessy ECMWF 18.06.91
1943
1944 Modifications:
1945 --------------
1946
1947 Uwe Schulzweida MPIfM 01/04/2001
1948
1949 - Convert to C from EMOS library version 130
1950
1951 Uwe Schulzweida MPIfM 02/08/2002
1952
1953 - speed up by factor 2 on NEC SX6
1954 - replace pow(2.0, -24.0) by constant POW_2_M24
1955 - replace pow(16.0, (double)(iexp - 64)) by pow16m64tab[iexp]
1956 */
1957
1958 /* ----------------------------------------------------------------- */
1959 /* Section 1 . Convert value of 0.0. Ignore sign bit. */
1960 /* ----------------------------------------------------------------- */
1961
1962 if ( (kexp == 128) || (kexp == 0) || (kexp == 255) ) return 0.0;
1963
1964 /* ----------------------------------------------------------------- */
1965 /* Section 2 . Convert other values. */
1966 /* ----------------------------------------------------------------- */
1967
1968 /* Sign of value. */
1969
1970 int iexp = kexp;
1971 const int isign = (iexp < 128) * 2 - 1;
1972
1973 iexp -= iexp < 128 ? 0 : 128;
1974
1975 /* Decode value. */
1976
1977 /* pval = isign * pow(2.0, -24.0) * kmant * pow(16.0, (double)(iexp - 64)); */
1978
1979 iexp -= 64;
1980
1981 const double pval = ldexp(1.0, 4 * iexp) * isign * POW_2_M24 * kmant;
1982
1983 /* ----------------------------------------------------------------- */
1984 /* Section 9. Return to calling routine. */
1985 /* ----------------------------------------------------------------- */
1986
1987 return pval;
1988 } /* decfp2 */
1989 #include <stdarg.h>
1990 #include <stdint.h>
1991
1992
1993 static
gribDecodeRefDate(const int * isec1,int * year,int * month,int * day)1994 void gribDecodeRefDate(const int *isec1, int *year, int *month, int *day)
1995 {
1996 int ryear = ISEC1_Year;
1997
1998 int century = ISEC1_Century;
1999 if (century < 0) century = -century;
2000 century -= 1;
2001
2002 if (century == -255 && ryear == 127)
2003 {
2004 ryear = 0;
2005 }
2006 else
2007 {
2008 // if ( century != 0 )
2009 {
2010 if ( ryear == 100 )
2011 {
2012 ryear = 0;
2013 century += 1;
2014 }
2015
2016 if ( ryear != 255 )
2017 {
2018 ryear = century*100 + ryear;
2019 if ( ISEC1_Century < 0 ) ryear = -ryear;
2020 }
2021 else
2022 {
2023 ryear = 1;
2024 }
2025 }
2026 }
2027
2028 *year = ryear;
2029 *month = ISEC1_Month;
2030 *day = ISEC1_Day;
2031 }
2032
2033
gribRefDate(const int * isec1)2034 int gribRefDate(const int *isec1)
2035 {
2036 int ryear, rmonth, rday;
2037 gribDecodeRefDate(isec1, &ryear, &rmonth, &rday);
2038 return cdiEncodeDate(ryear, rmonth, rday);
2039 }
2040
2041 static
gribDecodeRefTime(const int * isec1,int * hour,int * minute,int * second)2042 void gribDecodeRefTime(const int *isec1, int *hour, int *minute, int *second)
2043 {
2044 *hour = ISEC1_Hour;
2045 *minute = ISEC1_Minute;
2046 *second = 0;
2047 }
2048
2049
gribRefTime(const int * isec1)2050 int gribRefTime(const int *isec1)
2051 {
2052 int rhour, rminute, rsecond;
2053 gribDecodeRefTime(isec1, &rhour, &rminute, &rsecond);
2054 return cdiEncodeTime(rhour, rminute, rsecond);
2055 }
2056
2057
gribTimeIsFC(const int * isec1)2058 bool gribTimeIsFC(const int *isec1)
2059 {
2060 bool isFC = false;
2061
2062 const int time_period = (ISEC1_TimeRange == 10) ? (ISEC1_TimePeriod1<<8) + ISEC1_TimePeriod2 : ISEC1_TimePeriod1;
2063
2064 if (time_period > 0 && ISEC1_Day > 0)
2065 {
2066 isFC = (ISEC1_TimeRange == 0 || ISEC1_TimeRange == 10);
2067 }
2068
2069 return isFC;
2070 }
2071
2072 static
getTimeUnitFactor(int timeUnit)2073 int getTimeUnitFactor(int timeUnit)
2074 {
2075 static bool lprint = true;
2076 switch ( timeUnit )
2077 {
2078 case ISEC1_TABLE4_MINUTE: return 60; break;
2079 case ISEC1_TABLE4_QUARTER: return 900; break;
2080 case ISEC1_TABLE4_30MINUTES: return 1800; break;
2081 case ISEC1_TABLE4_HOUR: return 3600; break;
2082 case ISEC1_TABLE4_3HOURS: return 10800; break;
2083 case ISEC1_TABLE4_6HOURS: return 21600; break;
2084 case ISEC1_TABLE4_12HOURS: return 43200; break;
2085 case ISEC1_TABLE4_DAY: return 86400; break;
2086 default:
2087 if ( lprint )
2088 {
2089 gprintf(__func__, "Time unit %d unsupported", timeUnit);
2090 lprint = false;
2091 }
2092 break;
2093 }
2094
2095 return 0;
2096 }
2097
2098
gribDateTimeX(int * isec1,int * date,int * time,int * startDate,int * startTime)2099 void gribDateTimeX(int *isec1, int *date, int *time, int *startDate, int *startTime)
2100 {
2101 *startDate = 0;
2102 *startTime = 0;
2103
2104 int ryear, rmonth, rday;
2105 gribDecodeRefDate(isec1, &ryear, &rmonth, &rday);
2106
2107 int rhour, rminute, rsecond;
2108 gribDecodeRefTime(isec1, &rhour, &rminute, &rsecond);
2109
2110 // printf("ref %d/%d/%d %d:%d\n", ryear, rmonth, rday, rhour, rminute);
2111
2112 int64_t time_period = 0, time_period_x = 0;
2113 if ( ISEC1_TimeRange == 10 )
2114 time_period = (ISEC1_TimePeriod1<<8) + ISEC1_TimePeriod2;
2115 else if ( ISEC1_TimeRange >=2 && ISEC1_TimeRange <= 5 )
2116 {
2117 time_period_x = ISEC1_TimePeriod1;
2118 time_period = ISEC1_TimePeriod2;
2119 }
2120 else if ( ISEC1_TimeRange == 0 )
2121 time_period = ISEC1_TimePeriod1;
2122
2123 if ( time_period > 0 && rday > 0 )
2124 {
2125 int64_t julday = 0;
2126 int secofday = 0;
2127 encode_caldaysec(CGRIBEX_grib_calendar, ryear, rmonth, rday, rhour, rminute, rsecond, &julday, &secofday);
2128
2129 int time_unit_factor = getTimeUnitFactor(ISEC1_TimeUnit);
2130
2131 if (time_period_x > 0)
2132 {
2133 int64_t julday_x = julday;
2134 int secofday_x = secofday;
2135 julday_add_seconds(time_unit_factor * time_period_x, &julday_x, &secofday_x);
2136 decode_caldaysec(CGRIBEX_grib_calendar, julday_x, secofday_x, &ryear, &rmonth, &rday, &rhour, &rminute, &rsecond);
2137 *startDate = cdiEncodeDate(ryear, rmonth, rday);
2138 *startTime = cdiEncodeTime(rhour, rminute, 0);
2139 }
2140
2141 julday_add_seconds(time_unit_factor * time_period, &julday, &secofday);
2142 decode_caldaysec(CGRIBEX_grib_calendar, julday, secofday, &ryear, &rmonth, &rday, &rhour, &rminute, &rsecond);
2143 }
2144
2145 // printf("new %d/%d/%d %d:%d\n", ryear, rmonth, rday, rhour, rminute);
2146 *date = (int)cdiEncodeDate(ryear, rmonth, rday);
2147 *time = cdiEncodeTime(rhour, rminute, 0);
2148 }
2149
2150
gribDateTime(int * isec1,int * date,int * time)2151 void gribDateTime(int *isec1, int *date, int *time)
2152 {
2153 int sdate, stime;
2154 gribDateTimeX(isec1, date, time, &sdate, &stime);
2155 }
2156
2157
gprintf(const char * caller,const char * fmt,...)2158 void gprintf(const char *caller, const char *fmt, ...)
2159 {
2160 va_list args;
2161
2162 if ( grprsm == NULL ) Error("GRIBEX initialization missing!");
2163
2164 va_start(args, fmt);
2165
2166 fprintf(grprsm, "%-18s : ", caller);
2167 vfprintf(grprsm, fmt, args);
2168 fputs("\n", grprsm);
2169
2170 va_end(args);
2171 }
2172
2173
2174 void
gribExDP(int * isec0,int * isec1,int * isec2,double * fsec2,int * isec3,double * fsec3,int * isec4,double * fsec4,int klenp,int * kgrib,int kleng,int * kword,const char * hoper,int * kret)2175 gribExDP(int *isec0, int *isec1, int *isec2, double *fsec2, int *isec3,
2176 double *fsec3, int *isec4, double *fsec4, int klenp, int *kgrib,
2177 int kleng, int *kword, const char *hoper, int *kret)
2178 {
2179 int yfunc = *hoper;
2180
2181 if ( yfunc == 'C' )
2182 {
2183 grib_encode_double(isec0, isec1, isec2, fsec2, isec3,
2184 fsec3, isec4, fsec4, klenp, kgrib,
2185 kleng, kword, yfunc, kret);
2186 }
2187 else if ( yfunc == 'D' || yfunc == 'J' || yfunc == 'R' )
2188 {
2189 grib_decode_double(isec0, isec1, isec2, fsec2, isec3,
2190 fsec3, isec4, fsec4, klenp, kgrib,
2191 kleng, kword, yfunc, kret);
2192 }
2193 else if ( yfunc == 'V' )
2194 {
2195 fprintf(stderr, " cgribex: Version is %s\n", cgribexLibraryVersion());
2196 }
2197 else
2198 {
2199 Error("oper %c unsupported!", yfunc);
2200 *kret=-9;
2201 }
2202 }
2203
2204
2205 void
gribExSP(int * isec0,int * isec1,int * isec2,float * fsec2,int * isec3,float * fsec3,int * isec4,float * fsec4,int klenp,int * kgrib,int kleng,int * kword,const char * hoper,int * kret)2206 gribExSP(int *isec0, int *isec1, int *isec2, float *fsec2, int *isec3,
2207 float *fsec3, int *isec4, float *fsec4, int klenp, int *kgrib,
2208 int kleng, int *kword, const char *hoper, int *kret)
2209 {
2210 int yfunc = *hoper;
2211
2212 if ( yfunc == 'C' )
2213 {
2214 grib_encode_float(isec0, isec1, isec2, fsec2, isec3,
2215 fsec3, isec4, fsec4, klenp, kgrib,
2216 kleng, kword, yfunc, kret);
2217 }
2218 else if ( yfunc == 'D' || yfunc == 'J' || yfunc == 'R' )
2219 {
2220 grib_decode_float(isec0, isec1, isec2, fsec2, isec3,
2221 fsec3, isec4, fsec4, klenp, kgrib,
2222 kleng, kword, yfunc, kret);
2223 }
2224 else if ( yfunc == 'V' )
2225 {
2226 fprintf(stderr, " cgribex: Version is %s\n", cgribexLibraryVersion());
2227 }
2228 else
2229 {
2230 Error("oper %c unsupported!", yfunc);
2231 *kret=-9;
2232 }
2233 }
2234
2235 int CGRIBEX_Fix_ZSE = 0; /* 1: Fix ZeroShiftError of simple packed spherical harmonics */
2236 int CGRIBEX_Const = 0; /* 1: Don't pack constant fields on regular grids */
2237 int CGRIBEX_Debug = 0; /* 1: Debugging */
2238
gribSetDebug(int debug)2239 void gribSetDebug(int debug)
2240 {
2241 CGRIBEX_Debug = debug;
2242
2243 if ( CGRIBEX_Debug )
2244 Message("debug level %d", debug);
2245 }
2246
2247
gribFixZSE(int flag)2248 void gribFixZSE(int flag)
2249 {
2250 CGRIBEX_Fix_ZSE = flag;
2251
2252 if ( CGRIBEX_Debug )
2253 Message("Fix ZeroShiftError set to %d", flag);
2254 }
2255
2256
gribSetConst(int flag)2257 void gribSetConst(int flag)
2258 {
2259 CGRIBEX_Const = flag;
2260
2261 if ( CGRIBEX_Debug )
2262 Message("Const set to %d", flag);
2263 }
2264
2265
gribSetRound(int round)2266 void gribSetRound(int round)
2267 {
2268 UNUSED(round);
2269 }
2270
2271
gribSetRefDP(double refval)2272 void gribSetRefDP(double refval)
2273 {
2274 UNUSED(refval);
2275 }
2276
2277
gribSetRefSP(float refval)2278 void gribSetRefSP(float refval)
2279 {
2280 gribSetRefDP((double) refval);
2281 }
2282
2283
gribSetValueCheck(int vcheck)2284 void gribSetValueCheck(int vcheck)
2285 {
2286 UNUSED(vcheck);
2287 }
2288 #include <string.h>
2289 #include <math.h>
2290
2291
2292
gribPrintSec0(int * isec0)2293 void gribPrintSec0(int *isec0)
2294 {
2295 /*
2296
2297 Print the information in the Indicator
2298 Section (Section 0) of decoded GRIB data.
2299
2300 Input Parameters:
2301
2302 isec0 - Array of decoded integers from Section 0
2303
2304
2305 Converted from EMOS routine GRPRS0.
2306
2307 Uwe Schulzweida MPIfM 01/04/2001
2308
2309 */
2310
2311 grsdef();
2312
2313 fprintf(grprsm, " \n");
2314 fprintf(grprsm, " Section 0 - Indicator Section. \n");
2315 fprintf(grprsm, " -------------------------------------\n");
2316 fprintf(grprsm, " Length of GRIB message (octets). %9d\n", ISEC0_GRIB_Len);
2317 fprintf(grprsm, " GRIB Edition Number. %9d\n", ISEC0_GRIB_Version);
2318 }
2319
gribPrintSec1(int * isec0,int * isec1)2320 void gribPrintSec1(int *isec0, int *isec1)
2321 {
2322 /*
2323
2324 Print the information in the Product Definition
2325 Section (Section 1) of decoded GRIB data.
2326
2327 Input Parameters:
2328
2329 isec0 - Array of decoded integers from Section 0
2330
2331 isec1 - Array of decoded integers from Section 1
2332
2333 Comments:
2334
2335 When decoding data from Experimental Edition or Edition 0,
2336 routine GRIBEX adds the additional fields available in
2337 Edition 1.
2338
2339
2340 Converted from EMOS routine GRPRS1.
2341
2342 Uwe Schulzweida MPIfM 01/04/2001
2343
2344 */
2345
2346 int iprev, icurr, ioffset;
2347 int ibit, ierr, iout, iyear;
2348 int jloop, jiloop;
2349 float value;
2350
2351 char hversion[9];
2352 /*
2353 char hfirst[121], hsecond[121], hthird[121], hfourth[121];
2354 */
2355
2356 grsdef();
2357
2358 /*
2359 -----------------------------------------------------------------
2360 Section 0 . Print required information.
2361 -----------------------------------------------------------------
2362 */
2363
2364 fprintf(grprsm, " \n");
2365 fprintf(grprsm, " Section 1 - Product Definition Section.\n");
2366 fprintf(grprsm, " ---------------------------------------\n");
2367
2368 fprintf(grprsm, " Code Table 2 Version Number. %9d\n", isec1[0]);
2369 fprintf(grprsm, " Originating centre identifier. %9d\n", isec1[1]);
2370 fprintf(grprsm, " Model identification. %9d\n", isec1[2]);
2371 fprintf(grprsm, " Grid definition. %9d\n", isec1[3]);
2372
2373 ibit = 8;
2374 prtbin(isec1[4], ibit, &iout, &ierr);
2375 fprintf(grprsm, " Flag (Code Table 1) %8.8d\n", iout);
2376 fprintf(grprsm, " Parameter identifier (Code Table 2). %9d\n", isec1[5]);
2377
2378 /*
2379 IERR = CHKTAB2(ISEC1,HFIRST,HSECOND,HTHIRD,HFOURTH)
2380 IF( IERR .EQ. 0 ) THEN
2381 DO JLOOP = 121, 1, -1
2382 IF( HSECOND(JLOOP:JLOOP).NE.' ' ) THEN
2383 IOFFSET = JLOOP
2384 GOTO 110
2385 ENDIF
2386 ENDDO
2387 GOTO 120
2388 110 CONTINUE
2389 WRITE(*,'(2H ",A,1H")') HSECOND(1:IOFFSET)
2390 120 CONTINUE
2391 ENDIF
2392 */
2393
2394 if ( isec1[5] != 127 )
2395 {
2396 fprintf(grprsm, " Type of level (Code Table 3). %9d\n", isec1[6]);
2397 fprintf(grprsm, " Value 1 of level (Code Table 3). %9d\n", isec1[7]);
2398 fprintf(grprsm, " Value 2 of level (Code Table 3). %9d\n", isec1[8]);
2399 }
2400 else
2401 {
2402 fprintf(grprsm, " Satellite identifier. %9d\n", isec1[6]);
2403 fprintf(grprsm, " Spectral band. %9d\n", isec1[7]);
2404 }
2405
2406 iyear = isec1[9];
2407 if ( iyear != 255 )
2408 {
2409 int date, time;
2410 /* iyear = ((isec1[20]-1)*100 + isec1[9]); */
2411 gribDateTime(isec1, &date, &time);
2412 iyear = date/10000;
2413 fprintf(grprsm, " Year of reference time of data. %9d (%4d)\n", isec1[9], iyear);
2414 }
2415 else
2416 {
2417 fprintf(grprsm, " Year of reference time of data MISSING (=255)\n");
2418 }
2419
2420 fprintf(grprsm, " Month of reference time of data. %9d\n", isec1[10]);
2421 fprintf(grprsm, " Day of reference time of data. %9d\n", isec1[11]);
2422 fprintf(grprsm, " Hour of reference time of data. %9d\n", isec1[12]);
2423 fprintf(grprsm, " Minute of reference time of data. %9d\n", isec1[13]);
2424 fprintf(grprsm, " Time unit (Code Table 4). %9d\n", isec1[14]);
2425 fprintf(grprsm, " Time range one. %9d\n", isec1[15]);
2426 fprintf(grprsm, " Time range two. %9d\n", isec1[16]);
2427 fprintf(grprsm, " Time range indicator (Code Table 5) %9d\n", isec1[17]);
2428 fprintf(grprsm, " Number averaged. %9d\n", isec1[18]);
2429 fprintf(grprsm, " Number missing from average. %9d\n", isec1[19]);
2430 /*
2431 All ECMWF data in GRIB Editions before Edition 1 is decoded
2432 as 20th century data. Other centres are decoded as missing.
2433 */
2434 if ( isec0[1] < 1 && isec1[1] != 98 )
2435 fprintf(grprsm, " Century of reference time of data. Not given\n");
2436 else
2437 fprintf(grprsm, " Century of reference time of data. %9d\n", isec1[20]);
2438
2439 /* Print sub-centre */
2440 fprintf(grprsm, " Sub-centre identifier. %9d\n", ISEC1_SubCenterID);
2441
2442 /* Decimal scale factor */
2443 fprintf(grprsm, " Units decimal scaling factor. %9d\n", isec1[22]);
2444
2445 /*
2446 -----------------------------------------------------------------
2447 Section 1 . Print local DWD information.
2448 -----------------------------------------------------------------
2449 */
2450 if ( (ISEC1_CenterID == 78 || ISEC1_CenterID == 215 || ISEC1_CenterID == 250) &&
2451 (isec1[36] == 253 || isec1[36] == 254) )
2452 {
2453 fprintf(grprsm, " DWD local usage identifier. %9d\n", isec1[36]);
2454 if ( isec1[36] == 253 )
2455 fprintf(grprsm, " (Database labelling and ensemble forecast)\n");
2456 if ( isec1[36] == 254 )
2457 fprintf(grprsm, " (Database labelling)\n");
2458
2459 fprintf(grprsm, " Year of database entry %3d (%4d)\n", isec1[43], 1900+isec1[43]);
2460 fprintf(grprsm, " Month of database entry %3d\n", isec1[44]);
2461 fprintf(grprsm, " Day of database entry %3d\n", isec1[45]);
2462 fprintf(grprsm, " Hour of database entry %3d\n", isec1[46]);
2463 fprintf(grprsm, " Minute of database entry %3d\n", isec1[47]);
2464 fprintf(grprsm, " DWD experiment number %9d\n",isec1[48]);
2465 fprintf(grprsm, " DWD run type %9d\n",isec1[49]);
2466 if ( isec1[36] == 253 )
2467 {
2468 fprintf(grprsm, " User id %9d\n",isec1[50]);
2469 fprintf(grprsm, " Experiment identifier %9d\n",isec1[51]);
2470 fprintf(grprsm, " Ensemble identification type %9d\n",isec1[52]);
2471 fprintf(grprsm, " Number of ensemble members %9d\n",isec1[53]);
2472 fprintf(grprsm, " Actual number of ensemble member %9d\n",isec1[54]);
2473 fprintf(grprsm, " Model version %2d.%2.2d\n",isec1[55],isec1[56]);
2474 }
2475 }
2476
2477 /*
2478 -----------------------------------------------------------------
2479 Section 2 . Print local ECMWF information.
2480 -----------------------------------------------------------------
2481 */
2482 /*
2483 Regular MARS labelling, or reformatted Washington EPS products.
2484 */
2485 if ( (ISEC1_CenterID == 98 && ISEC1_LocalFLag == 1) ||
2486 (ISEC1_SubCenterID == 98 && ISEC1_LocalFLag == 1) ||
2487 (ISEC1_CenterID == 7 && ISEC1_SubCenterID == 98) )
2488 {
2489 /* Parameters common to all definitions. */
2490
2491 fprintf(grprsm, " ECMWF local usage identifier. %9d\n", isec1[36]);
2492 if ( isec1[36] == 1 )
2493 fprintf(grprsm, " (Mars labelling or ensemble forecast)\n");
2494 if ( isec1[36] == 2 )
2495 fprintf(grprsm, " (Cluster means and standard deviations)\n");
2496 if ( isec1[36] == 3 )
2497 fprintf(grprsm, " (Satellite image data)\n");
2498 if ( isec1[36] == 4 )
2499 fprintf(grprsm, " (Ocean model data)\n");
2500 if ( isec1[36] == 5 )
2501 fprintf(grprsm, " (Forecast probability data)\n");
2502 if ( isec1[36] == 6 )
2503 fprintf(grprsm, " (Surface temperature data)\n");
2504 if ( isec1[36] == 7 )
2505 fprintf(grprsm, " (Sensitivity data)\n");
2506 if ( isec1[36] == 8 )
2507 fprintf(grprsm, " (ECMWF re-analysis data)\n");
2508 if ( isec1[36] == 9 )
2509 fprintf(grprsm, " (Singular vectors and ensemble perturbations)\n");
2510 if ( isec1[36] == 10 )
2511 fprintf(grprsm, " (EPS tubes)\n");
2512 if ( isec1[36] == 11 )
2513 fprintf(grprsm, " (Supplementary data used by analysis)\n");
2514 if ( isec1[36] == 13 )
2515 fprintf(grprsm, " (Wave 2D spectra direction and frequency)\n");
2516
2517 fprintf(grprsm, " Class. %9d\n", isec1[37]);
2518 fprintf(grprsm, " Type. %9d\n", isec1[38]);
2519 fprintf(grprsm, " Stream. %9d\n", isec1[39]);
2520 sprintf(hversion, "%4s", (char*)&isec1[40]); hversion[4] = 0;
2521 fprintf(grprsm, " Version number or Experiment identifier. %4s\n", hversion);
2522 /*
2523 ECMWF Local definition 1.
2524 (MARS labelling or ensemble forecast data)
2525 */
2526 if ( isec1[36] == 1 )
2527 {
2528 fprintf(grprsm, " Forecast number. %9d\n", isec1[41]);
2529 if ( isec1[39] != 1090 )
2530 fprintf(grprsm, " Total number of forecasts. %9d\n", isec1[42]);
2531
2532 return;
2533 }
2534 /*
2535 ECMWF Local definition 2.
2536 (Cluster means and standard deviations)
2537 */
2538 if ( isec1[36] == 2 )
2539 {
2540 fprintf(grprsm, " Cluster number. %9d\n", isec1[41]);
2541 fprintf(grprsm, " Total number of clusters. %9d\n", isec1[42]);
2542 fprintf(grprsm, " Clustering method. %9d\n", isec1[43]);
2543 fprintf(grprsm, " Start time step when clustering. %9d\n", isec1[44]);
2544 fprintf(grprsm, " End time step when clustering. %9d\n", isec1[45]);
2545 fprintf(grprsm, " Northern latitude of domain. %9d\n", isec1[46]);
2546 fprintf(grprsm, " Western longitude of domain. %9d\n", isec1[47]);
2547 fprintf(grprsm, " Southern latitude of domain. %9d\n", isec1[48]);
2548 fprintf(grprsm, " Eastern longitude of domain. %9d\n", isec1[49]);
2549 fprintf(grprsm, " Operational forecast in cluster %9d\n", isec1[50]);
2550 fprintf(grprsm, " Control forecast in cluster %9d\n", isec1[51]);
2551 fprintf(grprsm, " Number of forecasts in cluster. %9d\n", isec1[52]);
2552
2553 for (jloop = 0; jloop < isec1[52]; jloop++)
2554 fprintf(grprsm, " Forecast number %9d\n", isec1[jloop+53]);
2555
2556 return;
2557 }
2558 /*
2559 ECMWF Local definition 3.
2560 (Satellite image data)
2561 */
2562 if ( isec1[36] == 3 )
2563 {
2564 fprintf(grprsm, " Satellite spectral band. %9d\n", isec1[41]);
2565 fprintf(grprsm, " Function code. %9d\n", isec1[42]);
2566 return;
2567 }
2568 /*
2569 ECMWF Local definition 4.
2570 (Ocean model data)
2571 */
2572 if ( isec1[36] == 4 )
2573 {
2574 fprintf(grprsm, " Satellite spectral band. %9d\n", isec1[41]);
2575 if ( isec1[39] != 1090 )
2576 fprintf(grprsm, " Function code. %9d\n", isec1[42]);
2577 fprintf(grprsm, " Coordinate structure definition.\n");
2578 fprintf(grprsm, " Fundamental spatial reference system.%9d\n", isec1[43]);
2579 fprintf(grprsm, " Fundamental time reference. %9d\n", isec1[44]);
2580 fprintf(grprsm, " Space unit flag. %9d\n", isec1[45]);
2581 fprintf(grprsm, " Vertical coordinate definition. %9d\n", isec1[46]);
2582 fprintf(grprsm, " Horizontal coordinate definition. %9d\n", isec1[47]);
2583 fprintf(grprsm, " Time unit flag. %9d\n", isec1[48]);
2584 fprintf(grprsm, " Time coordinate definition. %9d\n", isec1[49]);
2585 fprintf(grprsm, " Position definition. \n");
2586 fprintf(grprsm, " Mixed coordinate field flag. %9d\n", isec1[50]);
2587 fprintf(grprsm, " Coordinate 1 flag. %9d\n", isec1[51]);
2588 fprintf(grprsm, " Averaging flag. %9d\n", isec1[52]);
2589 fprintf(grprsm, " Position of level 1. %9d\n", isec1[53]);
2590 fprintf(grprsm, " Position of level 2. %9d\n", isec1[54]);
2591 fprintf(grprsm, " Coordinate 2 flag. %9d\n", isec1[55]);
2592 fprintf(grprsm, " Averaging flag. %9d\n", isec1[56]);
2593 fprintf(grprsm, " Position of level 1. %9d\n", isec1[57]);
2594 fprintf(grprsm, " Position of level 2. %9d\n", isec1[58]);
2595 fprintf(grprsm, " Grid Definition.\n");
2596 fprintf(grprsm, " Coordinate 3 flag (x-axis) %9d\n", isec1[59]);
2597 fprintf(grprsm, " Coordinate 4 flag (y-axis) %9d\n", isec1[60]);
2598 fprintf(grprsm, " Coordinate 4 of first grid point. %9d\n", isec1[61]);
2599 fprintf(grprsm, " Coordinate 3 of first grid point. %9d\n", isec1[62]);
2600 fprintf(grprsm, " Coordinate 4 of last grid point. %9d\n", isec1[63]);
2601 fprintf(grprsm, " Coordinate 3 of last grid point. %9d\n", isec1[64]);
2602 fprintf(grprsm, " i - increment. %9d\n", isec1[65]);
2603 fprintf(grprsm, " j - increment. %9d\n", isec1[66]);
2604 fprintf(grprsm, " Flag for irregular grid coordinates. %9d\n", isec1[67]);
2605 fprintf(grprsm, " Flag for normal or staggered grids. %9d\n", isec1[68]);
2606 fprintf(grprsm, " Further information.\n");
2607 fprintf(grprsm, " Further information flag. %9d\n", isec1[69]);
2608 fprintf(grprsm, " Auxiliary information.\n");
2609 fprintf(grprsm, " No. entries in horizontal coordinate %9d\n", isec1[70]);
2610 fprintf(grprsm, " No. entries in mixed coordinate defn.%9d\n", isec1[71]);
2611 fprintf(grprsm, " No. entries in grid coordinate list. %9d\n", isec1[72]);
2612 fprintf(grprsm, " No. entries in auxiliary array. %9d\n", isec1[73]);
2613 /*
2614 Horizontal coordinate supplement.
2615 */
2616 fprintf(grprsm, " Horizontal coordinate supplement.\n");
2617 if ( isec1[70] == 0 )
2618 {
2619 fprintf(grprsm, "(None).\n");
2620 }
2621 else
2622 {
2623 fprintf(grprsm, "Number of items = %d\n", isec1[70]);
2624 for (jloop = 0; jloop < isec1[70]; jloop++)
2625 fprintf(grprsm, " %12d\n", isec1[74+jloop]);
2626 }
2627 /*
2628 Mixed coordinate definition.
2629 */
2630 fprintf(grprsm, " Mixed coordinate definition.\n");
2631 if ( isec1[71] == 0 )
2632 {
2633 fprintf(grprsm, "(None).\n");
2634 }
2635 else
2636 {
2637 fprintf(grprsm, "Number of items = %d\n", isec1[71]);
2638 ioffset = 74 + isec1[70];
2639 for (jloop = 0; jloop < isec1[71]; jloop++)
2640 fprintf(grprsm, " %12d\n", isec1[ioffset+jloop]);
2641 }
2642 /*
2643 Grid coordinate list.
2644 */
2645 fprintf(grprsm, " Grid coordinate list. \n");
2646 if ( isec1[72] == 0 )
2647 {
2648 fprintf(grprsm, "(None).\n");
2649 }
2650 else
2651 {
2652 fprintf(grprsm, "Number of items = %d\n", isec1[72]);
2653 ioffset = 74 + isec1[70] + isec1[71];
2654 for (jloop = 0; jloop < isec1[72]; jloop++)
2655 fprintf(grprsm, " %12d\n", isec1[ioffset+jloop]);
2656 }
2657 /*
2658 Auxiliary array.
2659 */
2660 fprintf(grprsm, " Auxiliary array. \n");
2661 if ( isec1[73] == 0 )
2662 {
2663 fprintf(grprsm, "(None).\n");
2664 }
2665 else
2666 {
2667 fprintf(grprsm, "Number of items = %d\n", isec1[73]);
2668 ioffset = 74 + isec1[70] + isec1[71] + isec1[72];
2669 for (jloop = 0; jloop < isec1[73]; jloop++)
2670 fprintf(grprsm, " %12d\n", isec1[ioffset+jloop]);
2671 }
2672 /*
2673 Post-auxiliary array.
2674 */
2675 fprintf(grprsm, " Post-auxiliary array. \n");
2676 ioffset = 74 + isec1[70] + isec1[71] + isec1[72] + isec1[73];
2677 if ( isec1[ioffset] == 0 )
2678 {
2679 fprintf(grprsm, "(None).\n");
2680 }
2681 else
2682 {
2683 fprintf(grprsm, "Number of items = %d\n", isec1[ioffset]);
2684 for (jloop = 1; jloop < isec1[ioffset]; jloop++)
2685 fprintf(grprsm, " %12d\n", isec1[ioffset+jloop]);
2686 }
2687
2688 return;
2689 }
2690 /*
2691 ECMWF Local definition 5.
2692 (Forecast probability data)
2693 */
2694 if ( isec1[36] == 5 )
2695 {
2696 fprintf(grprsm, " Forecast probability number %9d\n", isec1[41]);
2697 fprintf(grprsm, " Total number of forecast probabilities %7d\n", isec1[42]);
2698 fprintf(grprsm, " Threshold units decimal scale factor %9d\n", isec1[43]);
2699 fprintf(grprsm, " Threshold indicator(1=lower,2=upper,3=both) %2d\n", isec1[44]);
2700 if ( isec1[44] != 2 )
2701 fprintf(grprsm, " Lower threshold value %9d\n", isec1[45]);
2702 if ( isec1[44] != 1 )
2703 fprintf(grprsm, " Upper threshold value %9d\n", isec1[46]);
2704 return;
2705 }
2706 /*
2707 ECMWF Local definition 6.
2708 (Surface temperature data)
2709 */
2710 if ( isec1[36] == 6 )
2711 {
2712 iyear = isec1[43];
2713 if ( iyear > 100 )
2714 {
2715 if ( iyear < 19000000 ) iyear = iyear + 19000000;
2716 fprintf(grprsm, " Date of SST field used %9d\n", iyear);
2717 }
2718 else
2719 fprintf(grprsm, "Date of SST field used Not given\n");
2720 }
2721 if ( isec1[44] == 0 )
2722 fprintf(grprsm, " Type of SST field (= climatology) %9d\n", isec1[44]);
2723 if ( isec1[44] == 1 )
2724 fprintf(grprsm, " Type of SST field (= 1/1 degree) %9d\n", isec1[44]);
2725 if ( isec1[44] == 2 )
2726 fprintf(grprsm, " Type of SST field (= 2/2 degree) %9d\n", isec1[44]);
2727
2728 fprintf(grprsm, " Number of ICE fields used: %9d\n", isec1[45]);
2729
2730 for (jloop = 1; jloop <= isec1[45]; jloop++)
2731 {
2732 iyear = isec1[44+(jloop*2)];
2733 if ( iyear > 100 )
2734 {
2735 if ( iyear < 19000000 ) iyear = iyear + 19000000;
2736 fprintf(grprsm, " Date of ICE field%3d %9d\n", jloop, iyear);
2737 fprintf(grprsm, " Satellite number (ICE field%3d) %9d\n", jloop,
2738 isec1[45+(jloop*2)]);
2739 }
2740 else
2741 fprintf(grprsm, "Date of SST field used Not given\n");
2742 }
2743 /*
2744 ECMWF Local definition 7.
2745 (Sensitivity data)
2746 */
2747 if ( isec1[36] == 7 )
2748 {
2749 if ( isec1[38] == 51 )
2750 fprintf(grprsm, " Forecast number %9d\n", isec1[41]);
2751 if ( isec1[38] != 51 )
2752 fprintf(grprsm, " Iteration number %9d\n", isec1[41]);
2753 if ( isec1[38] != 52 )
2754 fprintf(grprsm, " Total number of diagnostics %9d\n", isec1[42]);
2755 if ( isec1[38] == 52 )
2756 fprintf(grprsm, " No.interations in diag. minimisation %9d\n", isec1[42]);
2757 fprintf(grprsm, " Domain(0=Global,1=Europe,2=N.Hem.,3=S.Hem.) %2d\n", isec1[43]);
2758 fprintf(grprsm, " Diagnostic number %9d\n", isec1[44]);
2759 }
2760 /*
2761 ECMWF Local definition 8.
2762 (ECMWF re-analysis data)
2763 */
2764 if ( isec1[36] == 8 )
2765 {
2766 if ( (isec1[39] == 1043) ||
2767 (isec1[39] == 1070) ||
2768 (isec1[39] == 1071) )
2769 {
2770 fprintf(grprsm, " Interval between reference times %9d\n", isec1[41]);
2771 for (jloop = 43; jloop <= 54; jloop++)
2772 {
2773 jiloop = jloop + 8;
2774 fprintf(grprsm, " ERA section 1 octet %2d. %9d\n",
2775 jiloop, isec1[jloop-1]);
2776 }
2777 }
2778 else
2779 {
2780 for (jloop = 42; jloop <= 54; jloop++)
2781 {
2782 jiloop = jloop + 8;
2783 fprintf(grprsm, " ERA section 1 octet %2d. %9d\n",
2784 jiloop, isec1[jloop-1]);
2785 }
2786 }
2787 return;
2788 }
2789
2790 if ( isec1[38] > 4 && isec1[38] < 9 )
2791 {
2792 fprintf(grprsm, " Simulation number. %9d\n", isec1[41]);
2793 fprintf(grprsm, " Total number of simulations. %9d\n", isec1[42]);
2794 }
2795 /*
2796 ECMWF Local definition 9.
2797 (Singular vectors and ensemble perturbations)
2798 */
2799 if ( isec1[36] == 9 )
2800 {
2801 if ( isec1[38] == 60 )
2802 fprintf(grprsm, " Perturbed ensemble forecast number %9d\n", isec1[41]);
2803 if ( isec1[38] == 61 )
2804 fprintf(grprsm, " Initial state perturbation number %9d\n", isec1[41]);
2805 if ( isec1[38] == 62 )
2806 fprintf(grprsm, " Singular vector number %9d\n", isec1[41]);
2807 if ( isec1[38] == 62 )
2808 {
2809 fprintf(grprsm, " Number of iterations %9d\n", isec1[42]);
2810 fprintf(grprsm, " Number of singular vectors computed %9d\n", isec1[43]);
2811 fprintf(grprsm, " Norm used at initial time %9d\n", isec1[44]);
2812 fprintf(grprsm, " Norm used at final time %9d\n", isec1[45]);
2813 fprintf(grprsm, " Multiplication factor %9d\n", isec1[46]);
2814 fprintf(grprsm, " Latitude of north-west corner %9d\n", isec1[47]);
2815 fprintf(grprsm, " Longitude of north-west corner %9d\n", isec1[48]);
2816 fprintf(grprsm, " Latitude of south-east corner %9d\n", isec1[49]);
2817 fprintf(grprsm, " Longitude of south-east corner %9d\n", isec1[50]);
2818 fprintf(grprsm, " Accuracy %9d\n", isec1[51]);
2819 fprintf(grprsm, " Number of singular vectors evolved %9d\n", isec1[52]);
2820 fprintf(grprsm, " Ritz number one %9d\n", isec1[53]);
2821 fprintf(grprsm, " Ritz number two %9d\n", isec1[54]);
2822 }
2823 }
2824 /*
2825 ECMWF Local definition 10.
2826 (EPS tubes)
2827 */
2828 if ( isec1[36] == 10 )
2829 {
2830 fprintf(grprsm, " Tube number %9d\n", isec1[41]);
2831 fprintf(grprsm, " Total number of tubes %9d\n", isec1[42]);
2832 fprintf(grprsm, " Central cluster definition %9d\n", isec1[43]);
2833 fprintf(grprsm, " Parameter %9d\n", isec1[44]);
2834 fprintf(grprsm, " Type of level %9d\n", isec1[45]);
2835 fprintf(grprsm, " Northern latitude of domain of tubing%9d\n", isec1[46]);
2836 fprintf(grprsm, " Western longitude of domain of tubing%9d\n", isec1[47]);
2837 fprintf(grprsm, " Southern latitude of domain of tubing%9d\n", isec1[48]);
2838 fprintf(grprsm, " Eastern longitude of domain of tubing%9d\n", isec1[49]);
2839 fprintf(grprsm, " Tube number of operational forecast %9d\n", isec1[50]);
2840 fprintf(grprsm, " Tube number of control forecast %9d\n", isec1[51]);
2841 fprintf(grprsm, " Height/pressure of level %9d\n", isec1[52]);
2842 fprintf(grprsm, " Reference step %9d\n", isec1[53]);
2843 fprintf(grprsm, " Radius of central cluster %9d\n", isec1[54]);
2844 fprintf(grprsm, " Ensemble standard deviation %9d\n", isec1[55]);
2845 fprintf(grprsm, " Dist.of tube extreme to ensemble mean%9d\n", isec1[56]);
2846 fprintf(grprsm, " Number of forecasts in the tube %9d\n", isec1[57]);
2847
2848 fprintf(grprsm, " List of ensemble forecast numbers:\n");
2849 for (jloop = 1; jloop <= isec1[57]; jloop++)
2850 fprintf(grprsm, " %9d\n", isec1[57+jloop]);
2851 }
2852 /*
2853 ECMWF Local definition 11.
2854 (Supplementary data used by the analysis)
2855 */
2856 if ( isec1[36] == 11 )
2857 {
2858 fprintf(grprsm, " Details of analysis which used the supplementary data:\n");
2859 fprintf(grprsm, " Class %9d\n", isec1[41]);
2860 fprintf(grprsm, " Type %9d\n", isec1[42]);
2861 fprintf(grprsm, " Stream %9d\n", isec1[43]);
2862 /*
2863 sprintf(hversion, "%8d", isec1[44]);
2864 fprintf(grprsm, " Version number/experiment identifier: %4s\n", &hversion[4]);
2865 */
2866 iyear = isec1[45];
2867 if ( iyear > 50 )
2868 iyear = iyear + 1900;
2869 else
2870 iyear = iyear + 2000;
2871
2872 fprintf(grprsm, " Year %9d\n", iyear);
2873 fprintf(grprsm, " Month %9d\n", isec1[46]);
2874 fprintf(grprsm, " Day %9d\n", isec1[47]);
2875 fprintf(grprsm, " Hour %9d\n", isec1[48]);
2876 fprintf(grprsm, " Minute %9d\n", isec1[49]);
2877 fprintf(grprsm, " Century %9d\n", isec1[50]);
2878 fprintf(grprsm, " Originating centre %9d\n", isec1[51]);
2879 fprintf(grprsm, " Sub-centre %9d\n", isec1[52]);
2880 }
2881 /*
2882 ECMWF Local definition 12.
2883 */
2884 if ( isec1[36] == 12 )
2885 {
2886 fprintf(grprsm, " (Mean, average, etc)\n");
2887 fprintf(grprsm, " Start date of the period %8d\n", isec1[41]);
2888 fprintf(grprsm, " Start time of the period %4.4d\n", isec1[42]);
2889 fprintf(grprsm, " Finish date of the period %8d\n", isec1[43]);
2890 fprintf(grprsm, " Finish time of the period %4.4d\n", isec1[44]);
2891 fprintf(grprsm, " Verifying date of the period %8d\n", isec1[45]);
2892 fprintf(grprsm, " Verifying time of the period %4.4d\n", isec1[46]);
2893 fprintf(grprsm, " Code showing method %8d\n", isec1[47]);
2894 fprintf(grprsm, " Number of different time intervals used %5d\n", isec1[48]);
2895 fprintf(grprsm, " List of different time intervals used:\n");
2896 iprev = isec1[49];
2897 unsigned icount = 0;
2898 for (jloop = 1; jloop <= isec1[48]; jloop++)
2899 {
2900 icurr = isec1[48+jloop];
2901 if ( icurr != iprev )
2902 {
2903 if ( icount == 1 )
2904 fprintf(grprsm, " - interval %5.4d used once\n", iprev);
2905 if ( icount == 2 )
2906 fprintf(grprsm, " - interval %5.4d used twice\n", iprev);
2907 if ( icount > 2 )
2908 fprintf(grprsm, " - interval %5.4d used %5u times\n", iprev, icount);
2909 iprev = icurr;
2910 icount = 1;
2911 }
2912 else
2913 icount = icount + 1;
2914 }
2915 if ( icount == 1 )
2916 fprintf(grprsm, " - interval %5.4d used once\n", iprev);
2917 if ( icount == 2 )
2918 fprintf(grprsm, " - interval %5.4d used twice\n", iprev);
2919 if ( icount > 2 )
2920 fprintf(grprsm, " - interval %5.4d used %5u times\n", iprev, icount);
2921 }
2922 /*
2923 ECMWF Local definition 13.
2924 (Wave 2D spectra direction and frequency)
2925 */
2926 if ( isec1[36] == 13 )
2927 {
2928 fprintf(grprsm, " Direction number %9d\n", isec1[43]);
2929 fprintf(grprsm, " Frequency number %9d\n", isec1[44]);
2930 fprintf(grprsm, " Total number of directions %9d\n", isec1[45]);
2931 fprintf(grprsm, " Total number of frequencies %9d\n", isec1[46]);
2932 fprintf(grprsm, " Scale factor applied to directions %9d\n", isec1[47]);
2933 fprintf(grprsm, " Scale factor applied to frequencies %9d\n", isec1[48]);
2934 fprintf(grprsm, " List of directions:\n");
2935 for (jloop = 1; jloop <= isec1[45]; jloop++)
2936 {
2937 value = (float)(isec1[48+jloop])/(float)(isec1[47]);
2938 if ( isec1[43] == jloop )
2939 fprintf(grprsm, " %2.2d:%15.7f <-- this field value\n", jloop, value);
2940 else
2941 fprintf(grprsm, "%2.2d:%15.7f\n", jloop, value);
2942 }
2943 fprintf(grprsm, " List of frequencies:\n");
2944 for (jloop = 1; jloop <= isec1[46]; jloop++)
2945 {
2946 value = (float)(isec1[48+isec1[45]+jloop])/(float)(isec1[48]);
2947 if ( isec1[44] == jloop )
2948 fprintf(grprsm, " %2.2d:%15.7f <-- this field value\n", jloop, value);
2949 else
2950 fprintf(grprsm, "%2.2d:%15.7f\n", jloop, value);
2951
2952 if ( isec1[49+isec1[45]+isec1[46]] != 0 )
2953 {
2954 fprintf(grprsm, " System number (65535 = missing) %9d\n",
2955 isec1[49+isec1[45]+isec1[46]]);
2956 fprintf(grprsm, " Method number (65535 = missing) %9d\n",
2957 isec1[50+isec1[45]+isec1[46]]);
2958 }
2959 }
2960 /*
2961 ECMWF Local definition 14.
2962 (Brightness temperature)
2963 */
2964 if ( isec1[36] == 14 )
2965 {
2966 fprintf(grprsm, " Channel number %9d\n", isec1[43]);
2967 fprintf(grprsm, " Scale factor applied to frequencies %9d\n", isec1[44]);
2968 fprintf(grprsm, " Total number of frequencies %9d\n", isec1[45]);
2969 fprintf(grprsm, " List of frequencies:\n");
2970 for (jloop = 1; jloop <= isec1[45]; jloop++)
2971 {
2972 value = (float)(isec1[45+jloop])/(float)(isec1[44]);
2973 if ( isec1[43] == jloop )
2974 fprintf(grprsm, " %3d:%15.9f <-- this channel\n", jloop, value);
2975 else
2976 fprintf(grprsm, " %3d:%15.9f\n", jloop, value);
2977 }
2978 }
2979 /*
2980 ECMWF Local definition 15.
2981 (Ocean ensemble seasonal forecast)
2982 */
2983 if ( isec1[36] == 15 )
2984 {
2985 fprintf(grprsm, " Ensemble member number %9d\n", isec1[41]);
2986 fprintf(grprsm, " System number %9d\n", isec1[42]);
2987 fprintf(grprsm, " Method number %9d\n", isec1[43]);
2988 }
2989 /*
2990 ECMWF Local definition 16.
2991 (Seasonal forecast monthly mean atmosphere data)
2992 */
2993 if ( isec1[36] == 16 )
2994 {
2995 fprintf(grprsm, " Ensemble member number %9d\n", isec1[41]);
2996 fprintf(grprsm, " System number %9d\n", isec1[43]);
2997 fprintf(grprsm, " Method number %9d\n", isec1[44]);
2998 fprintf(grprsm, " Verifying month %9d\n", isec1[45]);
2999 fprintf(grprsm, " Averaging period %9d\n", isec1[46]);
3000 }
3001 /*
3002 ECMWF Local definition 17.
3003 (Sst or sea-ice used by analysis)
3004 */
3005 if ( isec1[36] == 17 )
3006 {
3007 iyear = isec1[43];
3008 if ( iyear > 100 )
3009 {
3010 if ( iyear < 19000000 ) iyear = iyear + 19000000;
3011 fprintf(grprsm, " Date of sst/ice field used %9d\n", iyear);
3012 }
3013 else
3014 fprintf(grprsm, " Date of sst/ice field used Not given\n");
3015
3016 if ( isec1[44] == 0 )
3017 fprintf(grprsm, " Type of sst/ice field (= climatology)%9d\n", isec1[44]);
3018 if ( isec1[44] == 1 )
3019 fprintf(grprsm, " Type of sst/ice field (= 1/1 degree) %9d\n", isec1[44]);
3020 if ( isec1[44] == 2 )
3021 fprintf(grprsm, " Type of sst/ice field (= 2/2 degree) %9d\n", isec1[44]);
3022
3023 fprintf(grprsm, " Number of ICE fields used: %9d\n", isec1[45]);
3024
3025 for (jloop = 1; jloop < isec1[45]; jloop++)
3026 {
3027 iyear = isec1[44+(jloop*2)];
3028 if ( iyear > 100 )
3029 {
3030 if ( iyear < 19000000 ) iyear = iyear + 19000000;
3031 fprintf(grprsm, " Date of ICE field%3d %9d\n", jloop,
3032 iyear);
3033 fprintf(grprsm, " Satellite number (ICE field%3d) %9d\n", jloop,
3034 isec1[45+(jloop*2)]);
3035 }
3036 else
3037 fprintf(grprsm, "Date of sst/ice field used Not given\n");
3038 }
3039 }
3040 }
3041 }
3042 /*
3043 -----------------------------------------------------------------
3044 Section 3 . Print Washington ensemble product information.
3045 -----------------------------------------------------------------
3046 */
3047 /*
3048 Washington EPS products (but not reformatted Washington EPS
3049 products.
3050 */
3051 if ( (isec1[1] == 7 && isec1[23] == 1) && (! (ISEC1_SubCenterID == 98)) )
3052 {
3053 /* CALL KWPRS1 (iSEC0,iSEC1)*/
3054 }
3055 /*
3056 -----------------------------------------------------------------
3057 Section 4 . Print local MPIM information.
3058 -----------------------------------------------------------------
3059 */
3060 if (isec1[ 1] == 252 && isec1[36] == 1)
3061 {
3062 fprintf(grprsm, " MPIM local usage identifier. %9d\n", isec1[36]);
3063 fprintf(grprsm, " Type of ensemble forecast %9d\n", isec1[37]);
3064 fprintf(grprsm, " Individual ensemble member %9d\n", isec1[38]);
3065 fprintf(grprsm, " Number of forecasts in ensemble %9d\n", isec1[39]);
3066 }
3067 }
3068
printQuasi(int * isec2)3069 static void printQuasi(int *isec2)
3070 {
3071 /*
3072
3073 Print the qusai-regular information in the Grid Description
3074 Section (Section 2) of decoded GRIB data.
3075
3076 Input Parameters:
3077
3078 isec2 - Array of decoded integers from Section 2.
3079
3080 Comments:
3081
3082 Only data representation types catered for are Gaussian
3083 grid, latitude/longitude grid, Spherical Harmonics,
3084 Polar stereographic and Space view perspective.
3085
3086 Converted from EMOS routine PTQUASI.
3087
3088 Uwe Schulzweida MPIfM 01/04/2001
3089
3090 */
3091
3092 char yout[64];
3093
3094 /*
3095 -----------------------------------------------------------------
3096 Section 1. Print quasi-grid data.
3097 -----------------------------------------------------------------
3098 */
3099 // See if scanning is north->south or south->north
3100 fprintf(grprsm, " Number of points along a parallel varies.\n");
3101
3102 int ntos = ( fmod((double) isec2[10], 128.) < 64 );
3103
3104 if ( ntos )
3105 fprintf(grprsm, " Number of points. Parallel. (North to South)\n");
3106 else
3107 fprintf(grprsm, " Number of points. Parallel. (South to North)\n");
3108
3109 // Display number of points for each latitude
3110 int latcnt = isec2[2];
3111 int nextlat = 0;
3112 memset(yout, ' ', (size_t) 11);
3113
3114 for (int j = 0; j < latcnt; j++)
3115 {
3116 nextlat = nextlat + 1;
3117 sprintf(yout, "%4d", nextlat);
3118
3119 // Finished?
3120 if ( nextlat > latcnt ) break;
3121 if ( nextlat == latcnt )
3122 {
3123 fprintf(grprsm, " %5d %-12s\n", isec2[nextlat+21], yout);
3124 break;
3125 }
3126 // Look for neighbouring latitudes with same number of points
3127 unsigned nrepeat = 0;
3128
3129 LABEL110:
3130 // If neighbouring latitudes have same number of points increase the repeat count.
3131 if ( isec2[nextlat+21+1] == isec2[nextlat+21] )
3132 {
3133 nrepeat = nrepeat + 1;
3134 nextlat = nextlat + 1;
3135 if ( nextlat < latcnt ) goto LABEL110;
3136 }
3137 // Display neighbouring latitudes with same number of points as 'nn to mm'.
3138 if ( nrepeat >= 1 ) sprintf(yout+4, "to %5d", nextlat);
3139 fprintf(grprsm, " %5d %-12s\n", isec2[nextlat+21], yout);
3140 memset(yout, ' ', (size_t) 11);
3141 }
3142 }
3143
gribPrintSec2DP(int * isec0,int * isec2,double * fsec2)3144 void gribPrintSec2DP(int *isec0, int *isec2, double *fsec2)
3145 {
3146 /*
3147
3148 Print the information in the Grid Description
3149 Section (Section 2) of decoded GRIB data.
3150
3151 Input Parameters:
3152
3153 isec0 - Array of decoded integers from Section 0
3154
3155 isec2 - Array of decoded integers from Section 2
3156
3157 fsec2 - Array of decoded floats from Section 2
3158
3159 Comments:
3160
3161 Only data representation types catered for are Gaussian
3162 grid, latitude/longitude grid, Spherical Harmonics,
3163 Polar stereographic and Space view perspective.
3164
3165
3166 Converted from EMOS routine GRPRS2.
3167
3168 Uwe Schulzweida MPIfM 01/04/2001
3169
3170 */
3171
3172 int i, ibit, iedit, ierr, iout, iresol;
3173
3174 grsdef();
3175 /*
3176 -----------------------------------------------------------------
3177 Section 1 . Print GRIB Edition number.
3178 -----------------------------------------------------------------
3179 */
3180 iedit = isec0[1];
3181 fprintf(grprsm, " \n");
3182 fprintf(grprsm, " Section 2 - Grid Description Section.\n");
3183 fprintf(grprsm, " -------------------------------------\n");
3184 /*
3185 -----------------------------------------------------------------
3186 Section 2 . Print spherical harmonic data.
3187 -----------------------------------------------------------------
3188 */
3189 if ( isec2[0] == 50 || isec2[0] == 60 ||
3190 isec2[0] == 70 || isec2[0] == 80 )
3191 {
3192 fprintf(grprsm, " Data represent type = spectral (Table 6) %9d\n", isec2[0]);
3193 fprintf(grprsm, " J - Pentagonal resolution parameter. %9d\n", isec2[1]);
3194 fprintf(grprsm, " K - Pentagonal resolution parameter. %9d\n", isec2[2]);
3195 fprintf(grprsm, " M - Pentagonal resolution parameter. %9d\n", isec2[3]);
3196 fprintf(grprsm, " Representation type (Table 9) %9d\n", isec2[4]);
3197 fprintf(grprsm, " Representation mode (Table 10). %9d\n", isec2[5]);
3198 for (i = 7; i <= 11; i++)
3199 fprintf(grprsm, " Not used. %9d\n", isec2[i-1]);
3200 fprintf(grprsm, " Number of vertical coordinate parameters. %9d\n", isec2[11]);
3201 goto LABEL800;
3202 }
3203 /*
3204 -----------------------------------------------------------------
3205 Section 3 . Print Gaussian grid data.
3206 -----------------------------------------------------------------
3207 */
3208 if ( isec2[0] == 4 || isec2[0] == 14 ||
3209 isec2[0] == 24 || isec2[0] == 34 )
3210 {
3211 fprintf(grprsm, " (Southern latitudes and Western longitudes are negative.)\n");
3212 fprintf(grprsm, " Data represent type = gaussian (Table 6) %9d\n", isec2[0]);
3213 /*
3214 Quasi-regular grids introduced in Edition 1.
3215 */
3216 if ( isec2[16] == 0 || iedit < 1 )
3217 fprintf(grprsm, " Number of points along a parallel. %9d\n", isec2[1]);
3218 else
3219 printQuasi(isec2);
3220
3221 fprintf(grprsm, " Number of points along a meridian. %9d\n", isec2[2]);
3222 fprintf(grprsm, " Latitude of first grid point. %9d\n", isec2[3]);
3223 fprintf(grprsm, " Longitude of first grid point. %9d\n", isec2[4]);
3224
3225 ibit = 8;
3226 iresol = isec2[5] + isec2[17] + isec2[18];
3227 prtbin(iresol, ibit, &iout, &ierr);
3228
3229 fprintf(grprsm, " Resolution and components flag. %8.8d\n", iout);
3230 fprintf(grprsm, " Latitude of last grid point. %9d\n", isec2[6]);
3231 fprintf(grprsm, " Longitude of last grid point. %9d\n", isec2[7]);
3232 /*
3233 Print increment if given.
3234 */
3235 if ( isec2[5] == 128 )
3236 fprintf(grprsm, " i direction (East-West) increment. %9d\n", isec2[8]);
3237 else
3238 fprintf(grprsm, " i direction (East-West) increment Not given\n");
3239
3240 fprintf(grprsm, " Number of parallels between pole and equator.%9d\n", isec2[9]);
3241
3242 ibit = 8;
3243 prtbin(isec2[10], ibit, &iout, &ierr);
3244
3245 fprintf(grprsm, " Scanning mode flags (Code Table 8) %8.8d\n", iout);
3246 fprintf(grprsm, " Number of vertical coordinate parameters. %9d\n", isec2[11]);
3247 goto LABEL800;
3248 }
3249 /*
3250 -----------------------------------------------------------------
3251 Section 4 . Print Latitude / longitude grid data.
3252 -----------------------------------------------------------------
3253 */
3254 if ( isec2[0] == 0 || isec2[0] == 10 ||
3255 isec2[0] == 20 || isec2[0] == 30 )
3256 {
3257 fprintf(grprsm, " (Southern latitudes and Western longitudes are negative.)\n");
3258 fprintf(grprsm, " Data represent type = lat/long (Table 6) %9d\n", isec2[0]);
3259 /*
3260 Quasi-regular lat/long grids also possible.
3261 */
3262 if ( isec2[16] == 0 )
3263 fprintf(grprsm, " Number of points along a parallel. %9d\n", isec2[1]);
3264 else
3265 printQuasi(isec2);
3266
3267 fprintf(grprsm, " Number of points along a meridian. %9d\n", isec2[2]);
3268 fprintf(grprsm, " Latitude of first grid point. %9d\n", isec2[3]);
3269 fprintf(grprsm, " Longitude of first grid point. %9d\n", isec2[4]);
3270
3271 ibit = 8;
3272 iresol = isec2[5] + isec2[17] + isec2[18];
3273 prtbin(iresol, ibit, &iout, &ierr);
3274
3275 fprintf(grprsm, " Resolution and components flag. %8.8d\n", iout);
3276 fprintf(grprsm, " Latitude of last grid point. %9d\n", isec2[6]);
3277 fprintf(grprsm, " Longitude of last grid point. %9d\n", isec2[7]);
3278 /*
3279 Print increment if given.
3280 */
3281 if ( isec2[8] < 0 )
3282 fprintf(grprsm, " i direction (East-West) increment Not given\n");
3283 else
3284 fprintf(grprsm, " i direction (East-West) increment. %9d\n", isec2[8]);
3285
3286 if ( isec2[9] < 0 )
3287 fprintf(grprsm, " j direction (North-South) increment Not given\n");
3288 else
3289 fprintf(grprsm, " j direction (North-South) increment. %9d\n", isec2[9]);
3290
3291 ibit = 8;
3292 prtbin(isec2[10], ibit, &iout, &ierr);
3293
3294 fprintf(grprsm, " Scanning mode flags (Code Table 8) %8.8d\n", iout);
3295 fprintf(grprsm, " Number of vertical coordinate parameters. %9d\n", isec2[11]);
3296 goto LABEL800;
3297 }
3298 /*
3299 -----------------------------------------------------------------
3300 Section 5 . Print polar stereographic data.
3301 -----------------------------------------------------------------
3302 */
3303 if ( isec2[0] == 5 )
3304 {
3305 fprintf(grprsm, " (Southern latitudes and Western longitudes are negative.)\n");
3306 fprintf(grprsm, " Data represent type = polar stereo (Table 6) %9d\n", isec2[0]);
3307 fprintf(grprsm, " Number of points along X axis. %9d\n", isec2[1]);
3308 fprintf(grprsm, " Number of points along Y axis. %9d\n", isec2[2]);
3309 fprintf(grprsm, " Latitude of first grid point. %9d\n", isec2[3]);
3310 fprintf(grprsm, " Longitude of first grid point. %9d\n", isec2[4]);
3311 ibit = 8;
3312 iresol = isec2[17] + isec2[18];
3313 prtbin(iresol, ibit, &iout, &ierr);
3314 fprintf(grprsm, " Resolution and components flag. %8.8d\n", iout);
3315 fprintf(grprsm, " Orientation of the grid. %9d\n", isec2[6]);
3316 fprintf(grprsm, " X direction increment. %9d\n", isec2[8]);
3317 fprintf(grprsm, " Y direction increment. %9d\n", isec2[9]);
3318 ibit = 8;
3319 prtbin(isec2[10], ibit, &iout, &ierr);
3320 fprintf(grprsm, " Scanning mode flags (Code Table 8) %8.8d\n", iout);
3321 fprintf(grprsm, " Number of vertical coordinate parameters. %9d\n", isec2[11]);
3322 fprintf(grprsm, " Projection centre flag. %9d\n", isec2[12]);
3323 goto LABEL800;
3324 }
3325 /*
3326 -----------------------------------------------------------------
3327 Section 6 . Print Lambert conformal data.
3328 -----------------------------------------------------------------
3329 */
3330 if ( isec2[0] == 3 )
3331 {
3332 fprintf(grprsm, " (Southern latitudes and Western longitudes are negative.)\n");
3333 fprintf(grprsm, " Data represent type = Lambert (Table 6) %9d\n", isec2[0]);
3334 fprintf(grprsm, " Number of points along X axis. %9d\n", isec2[1]);
3335 fprintf(grprsm, " Number of points along Y axis. %9d\n", isec2[2]);
3336 fprintf(grprsm, " Latitude of first grid point. %9d\n", isec2[3]);
3337 fprintf(grprsm, " Longitude of first grid point. %9d\n", isec2[4]);
3338 ibit = 8;
3339 iresol = isec2[17] + isec2[18] + isec2[5];
3340 prtbin(iresol, ibit, &iout, &ierr);
3341 fprintf(grprsm, " Resolution and components flag. %8.8d\n", iout);
3342 fprintf(grprsm, " Orientation of the grid. %9d\n", isec2[6]);
3343 fprintf(grprsm, " X direction increment. %9d\n", isec2[8]);
3344 fprintf(grprsm, " Y direction increment. %9d\n", isec2[9]);
3345 ibit = 8;
3346 prtbin(isec2[10], ibit, &iout, &ierr);
3347 fprintf(grprsm, " Scanning mode flags (Code Table 8) %8.8d\n", iout);
3348 fprintf(grprsm, " Number of vertical coordinate parameters. %9d\n", isec2[11]);
3349 fprintf(grprsm, " Projection centre flag. %9d\n", isec2[12]);
3350 fprintf(grprsm, " Latitude intersection 1 - Latin 1 -. %9d\n", isec2[13]);
3351 fprintf(grprsm, " Latitude intersection 2 - Latin 2 -. %9d\n", isec2[14]);
3352 fprintf(grprsm, " Latitude of Southern Pole. %9d\n", isec2[19]);
3353 fprintf(grprsm, " Longitude of Southern Pole. %9d\n", isec2[20]);
3354 goto LABEL800;
3355 }
3356 /*
3357 -----------------------------------------------------------------
3358 Section 7 . Print space view perspective or orthographic data.
3359 -----------------------------------------------------------------
3360 */
3361 if ( isec2[0] == 90 )
3362 {
3363 fprintf(grprsm, " (Southern latitudes and Western longitudes are negative.)\n");
3364 fprintf(grprsm, " Data represent type = space/ortho (Table 6) %9d\n", isec2[0]);
3365 fprintf(grprsm, " Number of points along X axis. %9d\n", isec2[1]);
3366 fprintf(grprsm, " Number of points along Y axis. %9d\n", isec2[2]);
3367 fprintf(grprsm, " Latitude of sub-satellite point. %9d\n", isec2[3]);
3368 fprintf(grprsm, " Longitude of sub-satellite point. %9d\n", isec2[4]);
3369 //iresol = isec2[17] + isec2[18];
3370 fprintf(grprsm, " Diameter of the earth in x direction. %9d\n", isec2[6]);
3371 fprintf(grprsm, " Y coordinate of sub-satellite point. %9d\n", isec2[9]);
3372 ibit = 8;
3373 prtbin(isec2[10], ibit, &iout, &ierr);
3374 fprintf(grprsm, " Scanning mode flags (Code Table 8) %8.8d\n", iout);
3375 fprintf(grprsm, " Number of vertical coordinate parameters. %9d\n", isec2[11]);
3376 fprintf(grprsm, " Orientation of the grid. %9d\n", isec2[6]);
3377 fprintf(grprsm, " Altitude of the camera. %9d\n", isec2[13]);
3378 fprintf(grprsm, " Y coordinate of origin of sector image. %9d\n", isec2[14]);
3379 fprintf(grprsm, " X coordinate of origin of sector image. %9d\n", isec2[15]);
3380 goto LABEL800;
3381 }
3382 /*
3383 -----------------------------------------------------------------
3384 Section 7.5 . Print ocean data
3385 -----------------------------------------------------------------
3386 */
3387 /*
3388 if ( isec2[0] == 192 && ISEC1_CenterID == 98 )
3389 {
3390 fprintf(grprsm, " Data represent type = ECMWF ocean (Table 6) %9d\n", isec2[0]);
3391 if ( isec2[1] == 32767 )
3392 fprintf(grprsm, " Number of points along the first axis. Not used\n");
3393 else
3394 fprintf(grprsm, " Number of points along the first axis. %9d\n", isec2[1]);
3395
3396 if ( isec2[2] == 32767 )
3397 fprintf(grprsm, " Number of points along the second axis. Not used\n");
3398 else
3399 fprintf(grprsm, " Number of points along the second axis. %9d\n", isec2[2]);
3400
3401 ibit = 8;
3402 prtbin(isec2[10], ibit, &iout, &ierr);
3403 fprintf(grprsm, " Scanning mode flags (Code Table 8) %8.8d\n", iout);
3404 goto LABEL800;
3405 }
3406 */
3407 /*
3408 -----------------------------------------------------------------
3409 Section 7.6 . Print triangular data
3410 -----------------------------------------------------------------
3411 */
3412 if ( isec2[0] == 192 /* && ISEC1_CenterID == 78 */ )
3413 {
3414 fprintf(grprsm, " Data represent type = triangular (Table 6) %9d\n", isec2[0]);
3415 fprintf(grprsm, " Number of factor 2 in factorisation of Ni. %9d\n", isec2[1]);
3416 fprintf(grprsm, " Number of factor 3 in factorisation of Ni. %9d\n", isec2[2]);
3417 fprintf(grprsm, " Number of diamonds (Nd). %9d\n", isec2[3]);
3418 fprintf(grprsm, " Number of triangular subdivisions of the\n");
3419 fprintf(grprsm, " icosahedron (Ni). %9d\n", isec2[4]);
3420 fprintf(grprsm, " Flag for orientation of diamonds (Table A). %9d\n", isec2[5]);
3421 fprintf(grprsm, " Latitude of pole point. %9d\n", isec2[6]);
3422 fprintf(grprsm, " Longitude of pole point. %9d\n", isec2[7]);
3423 fprintf(grprsm, " Longitude of the first diamond. %9d\n", isec2[8]);
3424 fprintf(grprsm, " Flag for storage sequence (Table B). %9d\n", isec2[9]);
3425 fprintf(grprsm, " Number of vertical coordinate parameters. %9d\n", isec2[11]);
3426 goto LABEL800;
3427 }
3428 /*
3429 -----------------------------------------------------------------
3430 Drop through to here => representation type not catered for.
3431 -----------------------------------------------------------------
3432 */
3433 fprintf(grprsm, "GRPRS2 :Data representation type not catered for -%d\n", isec2[0]);
3434
3435 goto LABEL900;
3436 /*
3437 -----------------------------------------------------------------
3438 Section 8 . Print vertical coordinate parameters,
3439 rotated grid information,
3440 stretched grid information, if any.
3441 -----------------------------------------------------------------
3442 */
3443 LABEL800:;
3444 /*
3445 Vertical coordinate parameters ...
3446 */
3447 if ( isec2[11] != 0 )
3448 {
3449 fprintf(grprsm, " \n");
3450 fprintf(grprsm, " Vertical Coordinate Parameters.\n");
3451 fprintf(grprsm, " -------------------------------\n");
3452 for ( i = 10; i < isec2[11]+10; i++ )
3453 fprintf(grprsm, " %20.12f\n", fsec2[i]);
3454 }
3455 /*
3456 Rotated and stretched grids introduced in Edition 1.
3457 */
3458 if ( iedit < 1 ) goto LABEL900;
3459 /*
3460 Rotated grid information ...
3461 */
3462 if ( isec2[0] == 10 || isec2[0] == 30 ||
3463 isec2[0] == 14 || isec2[0] == 34 ||
3464 isec2[0] == 60 || isec2[0] == 80 ||
3465 isec2[0] == 30 )
3466 {
3467 fprintf(grprsm, " \n");
3468 fprintf(grprsm, " Latitude of southern pole of rotation. %9d\n", isec2[12]);
3469 fprintf(grprsm, " Longitude of southern pole of rotation. %9d\n", isec2[13]);
3470 fprintf(grprsm, " Angle of rotation. %20.10f\n", fsec2[0]);
3471 }
3472 /*
3473 Stretched grid information ...
3474 */
3475 if ( isec2[0] == 20 || isec2[0] == 30 ||
3476 isec2[0] == 24 || isec2[0] == 34 ||
3477 isec2[0] == 70 || isec2[0] == 80 )
3478 {
3479 fprintf(grprsm, " \n");
3480 fprintf(grprsm, " Latitude of pole of stretching. %9d\n", isec2[14]);
3481 fprintf(grprsm, " Longitude of pole of stretching. %9d\n", isec2[15]);
3482 fprintf(grprsm, " Stretching factor. %20.10f\n", fsec2[1]);
3483 }
3484
3485 LABEL900:;
3486
3487 return;
3488 }
3489
gribPrintSec2SP(int * isec0,int * isec2,float * fsec2sp)3490 void gribPrintSec2SP(int *isec0, int *isec2, float *fsec2sp)
3491 {
3492 int inum;
3493 int j;
3494 double *fsec2;
3495
3496 inum = 10 + isec2[11];
3497
3498 fsec2 = (double*) Malloc((size_t)inum*sizeof(double));
3499 if ( fsec2 == NULL ) SysError("No Memory!");
3500
3501 for ( j = 0; j < inum; j++ )
3502 fsec2[j] = fsec2sp[j];
3503
3504 gribPrintSec2DP(isec0, isec2, fsec2);
3505
3506 Free(fsec2);
3507 }
3508
gribPrintSec3DP(int * isec0,int * isec3,double * fsec3)3509 void gribPrintSec3DP(int *isec0, int *isec3, double *fsec3)
3510 {
3511 /*
3512
3513 Print the information in the Bit-Map Section
3514 (Section 3) of decoded GRIB data.
3515
3516 Input Parameters:
3517
3518 isec0 - Array of decoded integers from Section 0
3519
3520 isec3 - Array of decoded integers from Section 3
3521
3522 fsec3 - Array of decoded floats from Section 3
3523
3524
3525 Converted from EMOS routine GRPRS3.
3526
3527 Uwe Schulzweida MPIfM 01/04/2001
3528
3529 */
3530
3531 UNUSED(isec0);
3532
3533 grsdef();
3534
3535 fprintf(grprsm, " \n");
3536 fprintf(grprsm, " Section 3 - Bit-map Section.\n");
3537 fprintf(grprsm, " -------------------------------------\n");
3538
3539 if ( isec3[0] != 0 )
3540 fprintf(grprsm, " Predetermined bit-map number. %9d\n", isec3[0]);
3541 else
3542 fprintf(grprsm, " No predetermined bit-map.\n");
3543
3544 fprintf(grprsm, " Missing data value for integer data. %14d\n", isec3[1]);
3545
3546 fprintf(grprsm, " Missing data value for real data. %20.6g\n", fsec3[1]);
3547 }
3548
gribPrintSec3SP(int * isec0,int * isec3,float * fsec3sp)3549 void gribPrintSec3SP(int *isec0, int *isec3, float *fsec3sp)
3550 {
3551 double fsec3[2];
3552
3553 fsec3[0] = fsec3sp[0];
3554 fsec3[1] = fsec3sp[1];
3555
3556 gribPrintSec3DP(isec0, isec3, fsec3);
3557 }
3558
gribPrintSec4DP(int * isec0,int * isec4,double * fsec4)3559 void gribPrintSec4DP(int *isec0, int *isec4, double *fsec4)
3560 {
3561 /*
3562
3563 Print the information in the Binary Data Section
3564 (Section 4) of decoded GRIB data.
3565
3566 Input Parameters:
3567
3568 isec0 - Array of decoded integers from Section 0
3569
3570 isec4 - Array of decoded integers from Section 4
3571
3572 fsec4 - Array of decoded floats from Section 4
3573
3574
3575 Converted from EMOS routine GRPRS4.
3576
3577 Uwe Schulzweida MPIfM 01/04/2001
3578
3579 */
3580 int inum;
3581 int j;
3582
3583 UNUSED(isec0);
3584
3585 grsdef();
3586
3587 /*
3588 -----------------------------------------------------------------
3589 Section 1 . Print integer information from isec4.
3590 -----------------------------------------------------------------
3591 */
3592 fprintf(grprsm, " \n");
3593 fprintf(grprsm, " Section 4 - Binary Data Section.\n");
3594 fprintf(grprsm, " -------------------------------------\n");
3595
3596 fprintf(grprsm, " Number of data values coded/decoded. %9d\n", isec4[0]);
3597 fprintf(grprsm, " Number of bits per data value. %9d\n", isec4[1]);
3598 fprintf(grprsm, " Type of data (0=grid pt, 128=spectral).%9d\n", isec4[2]);
3599 fprintf(grprsm, " Type of packing (0=simple, 64=complex). %9d\n", isec4[3]);
3600 fprintf(grprsm, " Type of data (0=float, 32=integer). %9d\n", isec4[4]);
3601 fprintf(grprsm, " Additional flags (0=none, 16=present). %9d\n", isec4[5]);
3602 fprintf(grprsm, " Reserved. %9d\n", isec4[6]);
3603 fprintf(grprsm, " Number of values (0=single, 64=matrix). %9d\n", isec4[7]);
3604 fprintf(grprsm, " Secondary bit-maps (0=none, 32=present). %9d\n", isec4[8]);
3605 fprintf(grprsm, " Values width (0=constant, 16=variable).%9d\n", isec4[9]);
3606 /*
3607 If complex packing ..
3608 */
3609 if ( isec4[3] == 64 )
3610 {
3611 if ( isec4[2] == 128 )
3612 {
3613 fprintf(grprsm, " Byte offset of start of packed data (N). %9d\n", isec4[15]);
3614 fprintf(grprsm, " Power (P * 1000). %9d\n", isec4[16]);
3615 fprintf(grprsm, " Pentagonal resolution parameter J for subset.%9d\n", isec4[17]);
3616 fprintf(grprsm, " Pentagonal resolution parameter K for subset.%9d\n", isec4[18]);
3617 fprintf(grprsm, " Pentagonal resolution parameter M for subset.%9d\n", isec4[19]);
3618 }
3619 else
3620 {
3621 fprintf(grprsm, " Bits number of 2nd order values (none=>0).%9d\n", isec4[10]);
3622 fprintf(grprsm, " General extend. 2-order packing (0=no,8=yes).%9d\n", isec4[11]);
3623 fprintf(grprsm, " Boustrophedonic ordering (0=no,4=yes).%9d\n", isec4[12]);
3624 fprintf(grprsm, " Spatial differencing order (0=none).%9d\n", isec4[13]+isec4[14]);
3625 }
3626 }
3627 /*
3628 Number of non-missing values
3629 */
3630 if ( isec4[20] != 0 )
3631 fprintf(grprsm, " Number of non-missing values %9d\n", isec4[20]);
3632 /*
3633 Information on matrix of values , if present.
3634 */
3635 if ( isec4[7] == 64 )
3636 {
3637 fprintf(grprsm, " First dimension (rows) of each matrix. %9d\n", isec4[49]);
3638 fprintf(grprsm, " Second dimension (columns) of each matrix. %9d\n", isec4[50]);
3639 fprintf(grprsm, " First dimension coordinate values definition.%9d\n", isec4[51]);
3640 fprintf(grprsm, " (Code Table 12)\n");
3641 fprintf(grprsm, " NC1 - Number of coefficients for 1st dimension.%7d\n", isec4[52]);
3642 fprintf(grprsm, " Second dimension coordinate values definition.%8d\n", isec4[53]);
3643 fprintf(grprsm, " (Code Table 12)\n");
3644 fprintf(grprsm, " NC2 - Number of coefficients for 2nd dimension.%7d\n", isec4[54]);
3645 fprintf(grprsm, " 1st dimension physical signifance (Table 13). %8d\n", isec4[55]);
3646 fprintf(grprsm, " 2nd dimension physical signifance (Table 13).%8d\n", isec4[56]);
3647 }
3648 /*
3649 -----------------------------------------------------------------
3650 Section 2. Print values from fsec4.
3651 -----------------------------------------------------------------
3652 */
3653
3654 inum = isec4[0];
3655 if ( inum < 0 ) inum = - inum;
3656 if ( inum > 20 ) inum = 20;
3657 /*
3658 Print first inum values.
3659 */
3660 fprintf(grprsm, " \n");
3661 fprintf(grprsm, " First %4d data values.\n", inum);
3662
3663 if ( isec4[4] == 0 )
3664 {
3665 /*
3666 Print real values ...
3667 */
3668 for ( j = 0; j < inum; j++ )
3669 {
3670 if ( fabs(fsec4[j]) > 0 )
3671 {
3672 if ( fabs(fsec4[j]) >= 0.1 && fabs(fsec4[j]) <= 1.e8 )
3673 fprintf(grprsm, " %#16.8G \n", fsec4[j]);
3674 else
3675 fprintf(grprsm, " %#20.8E\n", fsec4[j]);
3676 }
3677 else
3678 fprintf(grprsm, " %#16.0f \n", fabs(fsec4[j]));
3679 }
3680 }
3681 else
3682 {
3683 /*
3684 Print integer values ...
3685 */
3686 fprintf(grprsm, " Print of integer values not supported\n");
3687 /*
3688 CALL SETPAR(IBIT,IDUM,IDUM)
3689 DO 212 J=1,INUM
3690 INSPT = 0
3691 CALL INXBIT(IVALUE,1,INSPT,FSEC4(J),1,IBIT,IBIT,'C',IRET)
3692 WRITE (*,9033) IVALUE
3693 9033 FORMAT(' ',I15)
3694 212 CONTINUE
3695 ENDIF
3696 */
3697 }
3698 }
3699
gribPrintSec4SP(int * isec0,int * isec4,float * fsec4sp)3700 void gribPrintSec4SP(int *isec0, int *isec4, float *fsec4sp)
3701 {
3702 int inum;
3703 int j;
3704 double fsec4[20];
3705
3706 inum = isec4[0];
3707 if ( inum < 0 ) inum = -inum;
3708 if ( inum > 20 ) inum = 20;
3709
3710 for ( j = 0; j < inum; j++ ) fsec4[j] = fsec4sp[j];
3711
3712 gribPrintSec4DP(isec0, isec4, fsec4);
3713 }
3714
gribPrintSec4Wave(int * isec4)3715 void gribPrintSec4Wave(int *isec4)
3716 {
3717 /*
3718
3719 Print the wave coordinate information in the Binary Data
3720 Section (Section 4) of decoded GRIB data.
3721
3722 Input Parameters:
3723
3724 isec4 - Array of decoded integers from Section 4
3725
3726 Comments:
3727
3728 Wave coordinate information held in isec4 are 32-bit floats,
3729 hence the PTEMP and NTEMP used for printing are 4-byte variables.
3730
3731
3732 Converted from EMOS routine GRPRS4W.
3733
3734 Uwe Schulzweida MPIfM 01/04/2001
3735
3736 */
3737 int jloop;
3738 int ntemp[100];
3739 float *ptemp;
3740
3741 grsdef();
3742
3743 /*
3744 -----------------------------------------------------------------
3745 Section 1 . Print integer information from isec4.
3746 -----------------------------------------------------------------
3747 */
3748 fprintf(grprsm, " Coefficients defining first dimension coordinates:\n");
3749 for ( jloop = 0; jloop < isec4[52]; jloop++ )
3750 {
3751 ntemp[jloop] = isec4[59 + jloop];
3752 ptemp = (float *) &ntemp[jloop];
3753 fprintf(grprsm, "%20.10f\n", *ptemp);
3754 }
3755 fprintf(grprsm, " Coefficients defining second dimension coordinates:\n");
3756 for ( jloop = 0; jloop < isec4[54]; jloop++ )
3757 {
3758 ntemp[jloop] = isec4[59 + isec4[52] + jloop];
3759 ptemp = (float *) &ntemp[jloop];
3760 fprintf(grprsm, "%20.10f\n", *ptemp);
3761 }
3762 }
3763 #ifdef HAVE_CONFIG_H
3764 #endif
3765
3766 #include <string.h>
3767 #include <ctype.h>
3768
3769
3770
gribOpen(const char * filename,const char * mode)3771 int gribOpen(const char *filename, const char *mode)
3772 {
3773 int fileID = fileOpen(filename, mode);
3774
3775 #if defined (__sun)
3776 if ( fileID != FILE_UNDEFID && tolower(*mode) == 'r' )
3777 {
3778 fileSetBufferType(fileID, FILE_BUFTYPE_MMAP);
3779 }
3780 #endif
3781
3782 return fileID;
3783 }
3784
3785
gribClose(int fileID)3786 void gribClose(int fileID)
3787 {
3788 fileClose(fileID);
3789 }
3790
3791
gribGetPos(int fileID)3792 off_t gribGetPos(int fileID)
3793 {
3794 return fileGetPos(fileID);
3795 }
3796
3797
gribCheckSeek(int fileID,long * offset,int * version)3798 int gribCheckSeek(int fileID, long *offset, int *version)
3799 {
3800 int ierr = gribFileSeek(fileID, offset);
3801
3802 *version = -1;
3803 if ( !ierr )
3804 {
3805 char buffer[4];
3806 if ( fileRead(fileID, buffer, 4) == 4 )
3807 *version = buffer[3];
3808 }
3809
3810 return ierr;
3811 }
3812
3813
gribFileSeek(int fileID,long * offset)3814 int gribFileSeek(int fileID, long *offset)
3815 {
3816 /* position file pointer after GRIB */
3817 const long GRIB = 0x47524942;
3818 long code = 0;
3819 int ch;
3820 int retry = 4096*4096;
3821
3822 *offset = 0;
3823
3824 void *fileptr = filePtr(fileID);
3825
3826 while ( retry-- )
3827 {
3828 ch = filePtrGetc(fileptr);
3829 if ( ch == EOF ) return -1;
3830
3831 code = ( (code << 8) + ch ) & 0xFFFFFFFF;
3832 if ( code == GRIB )
3833 {
3834 if ( CGRIBEX_Debug ) Message("record offset = %ld", *offset);
3835 return 0;
3836 }
3837
3838 (*offset)++;
3839 }
3840
3841 if ( CGRIBEX_Debug ) Message("record offset = %ld", *offset);
3842
3843 return 1;
3844 }
3845
3846 static inline
read3ByteMSBFirst(void * fileptr)3847 unsigned read3ByteMSBFirst(void *fileptr)
3848 {
3849 unsigned b1 = (unsigned)(filePtrGetc(fileptr));
3850 unsigned b2 = (unsigned)(filePtrGetc(fileptr));
3851 unsigned b3 = (unsigned)(filePtrGetc(fileptr));
3852 return GET_UINT3(b1, b2, b3);
3853 }
3854
3855
gribReadSize(int fileID)3856 size_t gribReadSize(int fileID)
3857 {
3858 size_t rgribsize = 0;
3859 void *fileptr = filePtr(fileID);
3860 off_t pos = fileGetPos(fileID);
3861
3862 unsigned gribsize = read3ByteMSBFirst(fileptr);
3863
3864 int gribversion = filePtrGetc(fileptr);
3865
3866 if ( gribsize == 24 && gribversion != 1 && gribversion != 2 ) gribversion = 0;
3867
3868 if ( CGRIBEX_Debug ) Message("gribversion = %d", gribversion);
3869
3870 if ( gribversion == 0 )
3871 {
3872 unsigned gdssize = 0, bmssize = 0;
3873 unsigned issize = 4, essize = 4;
3874
3875 unsigned pdssize = gribsize;
3876 fileSetPos(fileID, (off_t) 3, SEEK_CUR);
3877 if ( CGRIBEX_Debug ) Message("pdssize = %u", pdssize);
3878 int flag = filePtrGetc(fileptr);
3879 if ( CGRIBEX_Debug ) Message("flag = %d", flag);
3880
3881 fileSetPos(fileID, (off_t) pdssize-8, SEEK_CUR);
3882
3883 if ( flag & 128 )
3884 {
3885 gdssize = read3ByteMSBFirst(fileptr);
3886 fileSetPos(fileID, (off_t) gdssize-3, SEEK_CUR);
3887 if ( CGRIBEX_Debug ) Message("gdssize = %u", gdssize);
3888 }
3889
3890 if ( flag & 64 )
3891 {
3892 bmssize = read3ByteMSBFirst(fileptr);
3893 fileSetPos(fileID, (off_t) bmssize-3, SEEK_CUR);
3894 if ( CGRIBEX_Debug ) Message("bmssize = %u", bmssize);
3895 }
3896
3897 unsigned bdssize = read3ByteMSBFirst(fileptr);
3898 if ( CGRIBEX_Debug ) Message("bdssize = %u", bdssize);
3899
3900 gribsize = issize + pdssize + gdssize + bmssize + bdssize + essize;
3901 rgribsize = (size_t) gribsize;
3902 }
3903 else if ( gribversion == 1 )
3904 {
3905 if ( gribsize > JP23SET ) // Large GRIB record
3906 {
3907 unsigned pdssize = read3ByteMSBFirst(fileptr);
3908 if ( CGRIBEX_Debug ) Message("pdssize = %u", pdssize);
3909
3910 int flag = 0;
3911 for ( int i = 0; i < 5; ++i ) flag = filePtrGetc(fileptr);
3912 if ( CGRIBEX_Debug ) Message("flag = %d", flag);
3913
3914 fileSetPos(fileID, (off_t) pdssize-8, SEEK_CUR);
3915
3916 unsigned gdssize = 0;
3917 if ( flag & 128 )
3918 {
3919 gdssize = read3ByteMSBFirst(fileptr);
3920 fileSetPos(fileID, (off_t) gdssize-3, SEEK_CUR);
3921 if ( CGRIBEX_Debug ) Message("gdssize = %u", gdssize);
3922 }
3923
3924 unsigned bmssize = 0;
3925 if ( flag & 64 )
3926 {
3927 bmssize = read3ByteMSBFirst(fileptr);
3928 fileSetPos(fileID, (off_t) bmssize-3, SEEK_CUR);
3929 if ( CGRIBEX_Debug ) Message("bmssize = %u", bmssize);
3930 }
3931
3932 unsigned bdssize = read3ByteMSBFirst(fileptr);
3933 if ( CGRIBEX_Debug ) Message("bdssize = %u", bdssize);
3934 if ( bdssize <= 120 )
3935 {
3936 const int issize = 4;
3937 gribsize &= JP23SET;
3938 gribsize *= 120;
3939 bdssize = correct_bdslen(bdssize, gribsize, issize+pdssize+gdssize+bmssize);
3940 if ( CGRIBEX_Debug ) Message("bdssize = %u", bdssize);
3941
3942 gribsize = issize + pdssize + gdssize + bmssize + bdssize + 4;
3943 }
3944 }
3945 rgribsize = (size_t) gribsize;
3946 }
3947 else if ( gribversion == 2 )
3948 {
3949 /* we set gribsize the following way because it doesn't matter then
3950 whether int is 4 or 8 bytes long - we don't have to care if the size
3951 really fits: if it does not, the record can not be read at all */
3952 rgribsize = 0;
3953 for ( int i = 0; i < 8; i++ ) rgribsize = (rgribsize << 8) | filePtrGetc(fileptr);
3954 }
3955 else
3956 {
3957 rgribsize = 0;
3958 Warning("GRIB version %d unsupported!", gribversion);
3959 }
3960
3961 if ( filePtrEOF(fileptr) ) rgribsize = 0;
3962
3963 if ( CGRIBEX_Debug ) Message("gribsize = %zu", rgribsize);
3964
3965 fileSetPos(fileID, pos, SEEK_SET);
3966
3967 return rgribsize;
3968 }
3969
3970
gribGetSize(int fileID)3971 size_t gribGetSize(int fileID)
3972 {
3973 long offset;
3974 int ierr = gribFileSeek(fileID, &offset); // position file pointer after GRIB
3975 if ( ierr > 0 )
3976 {
3977 Warning("GRIB record not found!");
3978 return 0;
3979 }
3980
3981 if ( ierr == -1 ) return 0;
3982 else if ( ierr == 1 ) return 0;
3983
3984 size_t recSize = gribReadSize(fileID);
3985
3986 if ( CGRIBEX_Debug ) Message("recsize = %zu", recSize);
3987
3988 fileSetPos(fileID, (off_t) -4, SEEK_CUR);
3989
3990 return recSize;
3991 }
3992
3993
gribRead(int fileID,void * buffer,size_t * buffersize)3994 int gribRead(int fileID, void *buffer, size_t *buffersize)
3995 {
3996 long offset;
3997 int ierr = gribFileSeek(fileID, &offset); // position file pointer after GRIB
3998 if ( ierr > 0 )
3999 {
4000 Warning("GRIB record not found!");
4001 return -2;
4002 }
4003
4004 if ( ierr == -1 ) { *buffersize = 0; return -1; }
4005 else if ( ierr == 1 ) { *buffersize = 0; return -2; }
4006
4007 size_t recSize = gribReadSize(fileID);
4008 size_t readSize = recSize;
4009
4010 if ( readSize > *buffersize )
4011 {
4012 readSize = *buffersize;
4013 ierr = -3; // Tell the caller that the buffer was insufficient.
4014 }
4015
4016 *buffersize = recSize; // Inform the caller about the record size.
4017
4018 // Write the stuff to the buffer that has already been read in gribFileSeek().
4019 memcpy(buffer, "GRIB", 4);
4020
4021 readSize -= 4;
4022 // Read the rest of the record into the buffer.
4023 size_t nread = fileRead(fileID, (char *)buffer + 4, readSize);
4024
4025 if ( nread != readSize ) ierr = 1;
4026
4027 return ierr;
4028 }
4029
4030
gribWrite(int fileID,void * buffer,size_t buffersize)4031 int gribWrite(int fileID, void *buffer, size_t buffersize)
4032 {
4033 int nwrite = (int)(fileWrite(fileID, buffer, buffersize));
4034 if (nwrite != (int) buffersize)
4035 {
4036 perror(__func__);
4037 nwrite = -1;
4038 }
4039
4040 return nwrite;
4041 }
4042 #include <string.h>
4043 #include <ctype.h>
4044
4045
4046 FILE *grprsm = NULL;
4047 int CGRIBEX_grib_calendar = -1;
4048
4049
gribSetCalendar(int calendar)4050 void gribSetCalendar(int calendar)
4051 {
4052 CGRIBEX_grib_calendar = calendar;
4053 }
4054
4055
grsdef(void)4056 void grsdef(void)
4057 {
4058 /*
4059 C---->
4060 C**** GRSDEF - Initial (default) setting of common area variables
4061 C for GRIBEX package.
4062 C
4063 C Purpose.
4064 C --------
4065 C
4066 C Sets initial values for common area variables for all
4067 C routines of GRIBEX package, if not already done.
4068 C
4069 C** Interface.
4070 C ----------
4071 C
4072 C CALL GRSDEF
4073 C
4074 C Input Parameters.
4075 C -----------------
4076 C
4077 C None.
4078 C
4079 C Output Parameters.
4080 C ------------------
4081 C
4082 C None.
4083 C
4084 C Method.
4085 C -------
4086 C
4087 C Self-explanatory.
4088 C
4089 C Externals.
4090 C ----------
4091 C
4092 C None.
4093 C
4094 C Reference.
4095 C ----------
4096 C
4097 C See subroutine GRIBEX.
4098 C
4099 C Comments.
4100 C ---------
4101 C
4102 C None
4103 C
4104 C Author.
4105 C -------
4106 C
4107 C J. Clochard, Meteo France, for ECMWF - March 1998.
4108 C
4109 C Modifications.
4110 C --------------
4111 C
4112 C J. Clochard, Meteo France, for ECMWF - June 1999.
4113 C Add variable NSUBCE.
4114 C Use a static variable to determine if initialisation has already
4115 C been done. NUSER removed .
4116 C Reverse defaults for NEXT2O and NLOC2O, for consistency with
4117 C version 13.023 of software .
4118 C
4119 */
4120 /*
4121 C ----------------------------------------------------------------
4122 C* Section 0 . Definition of variables.
4123 C ----------------------------------------------------------------
4124 */
4125 char *envString;
4126 char *env_stream;
4127 static bool lfirst = true;
4128 extern int CGRIBEX_Const;
4129
4130 if ( ! lfirst ) return;
4131
4132 /*
4133 ----------------------------------------------------------------
4134 Section 1 . Set values, conditionally.
4135 ----------------------------------------------------------------
4136 */
4137 /*
4138 Common area variables have not been set. Set them.
4139 */
4140 /*
4141 Set GRIB calendar.
4142 */
4143 if ( CGRIBEX_grib_calendar == -1 )
4144 {
4145 CGRIBEX_grib_calendar = CALENDAR_PROLEPTIC;
4146
4147 envString = getenv("GRIB_CALENDAR");
4148 if ( envString )
4149 {
4150 if ( strncmp(envString, "standard", 8) == 0 )
4151 CGRIBEX_grib_calendar = CALENDAR_STANDARD;
4152 else if ( strncmp(envString, "proleptic", 9) == 0 )
4153 CGRIBEX_grib_calendar = CALENDAR_PROLEPTIC;
4154 else if ( strncmp(envString, "360days", 7) == 0 )
4155 CGRIBEX_grib_calendar = CALENDAR_360DAYS;
4156 else if ( strncmp(envString, "365days", 7) == 0 )
4157 CGRIBEX_grib_calendar = CALENDAR_365DAYS;
4158 else if ( strncmp(envString, "366days", 7) == 0 )
4159 CGRIBEX_grib_calendar = CALENDAR_366DAYS;
4160 else if ( strncmp(envString, "none", 4) == 0 )
4161 CGRIBEX_grib_calendar = CALENDAR_NONE;
4162 }
4163 }
4164 /*
4165 Set GRIBEX compatibility mode.
4166 */
4167 envString = getenv("GRIB_GRIBEX_MODE_ON");
4168 if ( envString != NULL )
4169 {
4170 if ( atoi(envString) == 1 ) CGRIBEX_Const = 0;
4171 }
4172
4173 /*
4174 See if output stream needs changing
4175 */
4176 grprsm = stdout;
4177 env_stream = getenv("GRPRS_STREAM");
4178 if ( env_stream )
4179 {
4180 if ( isdigit((int) env_stream[0]) )
4181 {
4182 int unit;
4183 unit = atoi(env_stream);
4184 if ( unit < 1 || unit > 99 )
4185 Warning("Invalid number for GRPRS_STREAM: %d", unit);
4186 else if ( unit == 2 )
4187 grprsm = stderr;
4188 else if ( unit == 6 )
4189 grprsm = stdout;
4190 else
4191 {
4192 char filename[] = "unit.00";
4193 sprintf(filename, "%2.2d", unit);
4194 grprsm = fopen(filename, "w");
4195 if ( ! grprsm )
4196 SysError("GRPRS_STREAM = %d", unit);
4197 }
4198 }
4199 else
4200 {
4201 if ( env_stream[0] )
4202 {
4203 grprsm = fopen(env_stream, "w");
4204 if ( ! grprsm )
4205 SysError("GRPRS_STREAM = %s", env_stream);
4206 }
4207 }
4208 }
4209 /*
4210 Mark common area values set by user.
4211 */
4212 lfirst = false;
4213 }
4214
4215 /* pack 8-bit bytes from 64-bit words to a packed buffer */
4216 /* same as : for ( int i = 0; i < bc; ++i ) cp[i] = (unsigned char) up[i]; */
4217
packInt64(unsigned INT64 * up,unsigned char * cp,long bc,long tc)4218 long packInt64(unsigned INT64 *up, unsigned char *cp, long bc, long tc)
4219 {
4220 #if defined (CRAY)
4221 (void) _pack(up, cp, bc, tc);
4222 #else
4223 U_BYTEORDER;
4224 unsigned char *cp0;
4225 unsigned INT64 upi, *up0, *ip0, *ip1, *ip2, *ip3, *ip4, *ip5, *ip6, *ip7;
4226 long head, trail, inner, i, j;
4227 long ipack = sizeof(INT64);
4228
4229 /* Bytes until first word boundary in destination buffer */
4230
4231 head = ( (long) cp ) & (ipack-1);
4232 if ( head != 0 ) head = ipack - head;
4233
4234 inner = bc - head;
4235
4236 /* Trailing bytes which do not make a full word */
4237
4238 trail = inner & (ipack-1);
4239
4240 /* Number of bytes/words to be processed in fast loop */
4241
4242 inner -= trail;
4243 inner /= ipack;
4244
4245 ip0 = up + head;
4246 ip1 = ip0 + 1;
4247 ip2 = ip0 + 2;
4248 ip3 = ip0 + 3;
4249 ip4 = ip0 + 4;
4250 ip5 = ip0 + 5;
4251 ip6 = ip0 + 6;
4252 ip7 = ip0 + 7;
4253
4254 up0 = (unsigned INT64 *)(void *)(cp + head);
4255
4256 /* Here we should process any bytes until the first word boundary
4257 * of our destination buffer
4258 * That code is missing so far because our output buffer is
4259 * word aligned by FORTRAN
4260 */
4261
4262 j = 0;
4263
4264 if ( IS_BIGENDIAN() )
4265 {
4266 #if defined (CRAY)
4267 #pragma _CRI ivdep
4268 #endif
4269 #if defined (SX)
4270 #pragma vdir nodep
4271 #endif
4272 #ifdef __uxpch__
4273 #pragma loop novrec
4274 #endif
4275 for ( i = 0 ; i < inner ; i++ )
4276 {
4277 upi = ( ip0[j] << 56 )
4278 | ( ( ip1[j] & 0xFF ) << 48 )
4279 | ( ( ip2[j] & 0xFF ) << 40 )
4280 | ( ( ip3[j] & 0xFF ) << 32 )
4281 | ( ( ip4[j] & 0xFF ) << 24 ) ;
4282 up0[i] = upi | ( ( ip5[j] & 0xFF ) << 16 )
4283 | ( ( ip6[j] & 0xFF ) << 8 )
4284 | ( ip7[j] & 0xFF ) ;
4285 j += ipack;
4286 }
4287 }
4288 else
4289 {
4290 for ( i = 0 ; i < inner ; i++ )
4291 {
4292 upi = ( ip7[j] << 56 )
4293 | ( ( ip6[j] & 0xFF ) << 48 )
4294 | ( ( ip5[j] & 0xFF ) << 40 )
4295 | ( ( ip4[j] & 0xFF ) << 32 )
4296 | ( ( ip3[j] & 0xFF ) << 24 ) ;
4297 up0[i] = upi | ( ( ip2[j] & 0xFF ) << 16 )
4298 | ( ( ip1[j] & 0xFF ) << 8 )
4299 | ( ip0[j] & 0xFF ) ;
4300 j += ipack;
4301 }
4302 }
4303
4304 cp0 = (unsigned char *) ( up0 + inner );
4305 if ( trail > 0 )
4306 {
4307 up0[inner] = 0;
4308 for ( i = 0 ; i < trail ; i ++ )
4309 {
4310 *cp0 = (unsigned char) ip0[ipack*inner+i];
4311 cp0++;
4312 }
4313 }
4314
4315 if ( tc != -1 )
4316 {
4317 bc++;
4318 *cp0 = (unsigned char) tc;
4319 }
4320 #endif
4321 return (bc);
4322 }
4323
4324 /* unpack 8-bit bytes from a packed buffer with 64-bit words */
4325 /* same as : for ( int i = 0; i < bc; ++i ) up[i] = (INT64) cp[i]; */
4326
unpackInt64(const unsigned char * cp,unsigned INT64 * up,long bc,long tc)4327 long unpackInt64(const unsigned char *cp, unsigned INT64 *up, long bc, long tc)
4328 {
4329 U_BYTEORDER;
4330 const unsigned char *cp0;
4331 unsigned INT64 *ip0, *ip1, *ip2, *ip3, *ip4, *ip5, *ip6, *ip7;
4332 long head, trail, inner, i, j;
4333 long offset;
4334 long ipack = sizeof(INT64);
4335
4336 UNUSED(tc);
4337
4338 /* Bytes until first word boundary in source buffer */
4339
4340 head = ( (long) cp ) & (ipack-1);
4341 if ( head != 0 ) head = ipack - head;
4342 if ( head > bc ) head = bc;
4343
4344 inner = bc - head;
4345
4346 /* Trailing bytes which do not make a full word */
4347
4348 trail = inner & (ipack-1);
4349
4350 /* Number of bytes/words to be processed in fast loop */
4351
4352 inner -= trail;
4353 inner /= ipack;
4354
4355 ip0 = up + head;
4356 ip1 = ip0 + 1;
4357 ip2 = ip0 + 2;
4358 ip3 = ip0 + 3;
4359 ip4 = ip0 + 4;
4360 ip5 = ip0 + 5;
4361 ip6 = ip0 + 6;
4362 ip7 = ip0 + 7;
4363
4364 const unsigned INT64 *up0 = (const unsigned INT64 *)(const void *)(cp + head);
4365
4366 /* Process any bytes until the first word boundary
4367 * of our source buffer
4368 */
4369 for ( i = 0 ; i < head ; i++ ) up[i] = (unsigned INT64) cp[i];
4370
4371 j = 0;
4372
4373 if ( IS_BIGENDIAN() )
4374 {
4375 #if defined (CRAY)
4376 #pragma _CRI ivdep
4377 #endif
4378 #if defined (SX)
4379 #pragma vdir nodep
4380 #endif
4381 #ifdef __uxpch__
4382 #pragma loop novrec
4383 #endif
4384 for ( i = 0 ; i < inner ; i++ )
4385 {
4386 ip0[j] = (up0[i] >> 56) & 0xFF;
4387 ip1[j] = (up0[i] >> 48) & 0xFF;
4388 ip2[j] = (up0[i] >> 40) & 0xFF;
4389 ip3[j] = (up0[i] >> 32) & 0xFF;
4390 ip4[j] = (up0[i] >> 24) & 0xFF;
4391 ip5[j] = (up0[i] >> 16) & 0xFF;
4392 ip6[j] = (up0[i] >> 8) & 0xFF;
4393 ip7[j] = (up0[i]) & 0xFF;
4394
4395 j += ipack;
4396 }
4397 }
4398 else
4399 {
4400 for ( i = 0 ; i < inner ; i++ )
4401 {
4402 ip7[j] = (up0[i] >> 56) & 0xFF;
4403 ip6[j] = (up0[i] >> 48) & 0xFF;
4404 ip5[j] = (up0[i] >> 40) & 0xFF;
4405 ip4[j] = (up0[i] >> 32) & 0xFF;
4406 ip3[j] = (up0[i] >> 24) & 0xFF;
4407 ip2[j] = (up0[i] >> 16) & 0xFF;
4408 ip1[j] = (up0[i] >> 8) & 0xFF;
4409 ip0[j] = (up0[i]) & 0xFF;
4410
4411 j += ipack;
4412 }
4413 }
4414
4415 if ( trail > 0 )
4416 {
4417 offset = head + ipack*inner;
4418 cp0 = cp + offset;
4419 for ( i = 0 ; i < trail ; i++ ) up[i+offset] = (unsigned INT64) cp0[i];
4420 }
4421 /*
4422 if ( tc != -1 ) {
4423 bc++;
4424 *cp0 = (unsigned char) tc;
4425 }
4426 */
4427 return (bc);
4428 }
4429
4430 /* pack 8-bit bytes from 32-bit words to a packed buffer */
4431 /* same as : for ( int i = 0; i < bc; ++i ) cp[i] = (char) up[i]; */
4432
4433 #ifdef INT32
packInt32(unsigned INT32 * up,unsigned char * cp,long bc,long tc)4434 long packInt32(unsigned INT32 *up, unsigned char *cp, long bc, long tc)
4435 {
4436 U_BYTEORDER;
4437 unsigned char *cp0;
4438 unsigned INT32 *up0, *ip0, *ip1, *ip2, *ip3;
4439 long head, trail, inner, i, j;
4440 long ipack = sizeof(INT32);
4441
4442 /* Bytes until first word boundary in destination buffer */
4443
4444 head = ( (long) cp ) & (ipack-1);
4445 if ( head != 0 ) head = ipack - head;
4446
4447 inner = bc - head;
4448
4449 /* Trailing bytes which do not make a full word */
4450
4451 trail = inner & (ipack-1);
4452
4453 /* Number of bytes/words to be processed in fast loop */
4454
4455 inner -= trail;
4456 inner /= ipack;
4457
4458 ip0 = up + head;
4459 ip1 = ip0 + 1;
4460 ip2 = ip0 + 2;
4461 ip3 = ip0 + 3;
4462
4463 up0 = (unsigned INT32 *)(void *)(cp + head);
4464
4465 /* Here we should process any bytes until the first word boundary
4466 * of our destination buffer
4467 * That code is missing so far because our output buffer is
4468 * word aligned by FORTRAN
4469 */
4470
4471 j = 0;
4472
4473 if ( IS_BIGENDIAN() )
4474 {
4475 #if defined (CRAY)
4476 #pragma _CRI ivdep
4477 #endif
4478 #if defined (SX)
4479 #pragma vdir nodep
4480 #endif
4481 #ifdef __uxpch__
4482 #pragma loop novrec
4483 #endif
4484 for ( i = 0 ; i < inner ; i++ )
4485 {
4486 up0[i] = ( ip0[j] << 24 )
4487 | ( ( ip1[j] & 0xFF ) << 16 )
4488 | ( ( ip2[j] & 0xFF ) << 8 )
4489 | ( ip3[j] & 0xFF ) ;
4490 j += ipack;
4491 }
4492 }
4493 else
4494 {
4495 for ( i = 0 ; i < inner ; i++ )
4496 {
4497 up0[i] = ( ip3[j] << 24 )
4498 | ( ( ip2[j] & 0xFF ) << 16 )
4499 | ( ( ip1[j] & 0xFF ) << 8 )
4500 | ( ip0[j] & 0xFF ) ;
4501 j += ipack;
4502 }
4503 }
4504
4505 cp0 = (unsigned char *) ( up0 + inner );
4506 if ( trail > 0 )
4507 {
4508 up0[inner] = 0;
4509 for ( i = 0 ; i < trail ; i ++ )
4510 {
4511 *cp0 = (unsigned char) ip0[ipack*inner+i];
4512 cp0++;
4513 }
4514 }
4515
4516 if ( tc != -1 )
4517 {
4518 bc++;
4519 *cp0 = (unsigned char) tc;
4520 }
4521
4522 return (bc);
4523 }
4524 #endif
4525
4526 /* unpack 8-bit bytes from a packed buffer with 32-bit words */
4527 /* same as : for ( int i = 0; i < bc; ++i ) up[i] = (INT32) cp[i]; */
4528
4529 #ifdef INT32
unpackInt32(const unsigned char * cp,unsigned INT32 * up,long bc,long tc)4530 long unpackInt32(const unsigned char *cp, unsigned INT32 *up, long bc, long tc)
4531 {
4532 U_BYTEORDER;
4533 const unsigned char *cp0;
4534 unsigned INT32 *ip0, *ip1, *ip2, *ip3;
4535 long head, trail, inner, i, j;
4536 long offset;
4537 long ipack = sizeof(INT32);
4538
4539 UNUSED(tc);
4540
4541 /* Bytes until first word boundary in source buffer */
4542
4543 head = ( (long) cp ) & (ipack-1);
4544 if ( head != 0 ) head = ipack - head;
4545 if ( head > bc ) head = bc;
4546
4547 inner = bc - head;
4548
4549 /* Trailing bytes which do not make a full word */
4550
4551 trail = inner & (ipack-1);
4552
4553 /* Number of bytes/words to be processed in fast loop */
4554
4555 inner -= trail;
4556 inner /= ipack;
4557
4558 ip0 = up + head;
4559 ip1 = ip0 + 1;
4560 ip2 = ip0 + 2;
4561 ip3 = ip0 + 3;
4562
4563 const unsigned INT32 *up0 = (const unsigned INT32 *)(const void *)(cp + head);
4564
4565 /* Process any bytes until the first word boundary
4566 * of our source buffer
4567 */
4568 for ( i = 0 ; i < head ; i++ ) up[i] = (unsigned INT32) cp[i];
4569
4570 j = 0;
4571
4572 if ( IS_BIGENDIAN() )
4573 {
4574 #if defined (CRAY)
4575 #pragma _CRI ivdep
4576 #endif
4577 #if defined (SX)
4578 #pragma vdir nodep
4579 #endif
4580 #ifdef __uxpch__
4581 #pragma loop novrec
4582 #endif
4583 for ( i = 0 ; i < inner ; i++ )
4584 {
4585 ip0[j] = (up0[i] >> 24) & 0xFF;
4586 ip1[j] = (up0[i] >> 16) & 0xFF;
4587 ip2[j] = (up0[i] >> 8) & 0xFF;
4588 ip3[j] = (up0[i]) & 0xFF;
4589
4590 j += ipack;
4591 }
4592 }
4593 else
4594 {
4595 for ( i = 0 ; i < inner ; i++ )
4596 {
4597 ip3[j] = (up0[i] >> 24) & 0xFF;
4598 ip2[j] = (up0[i] >> 16) & 0xFF;
4599 ip1[j] = (up0[i] >> 8) & 0xFF;
4600 ip0[j] = (up0[i]) & 0xFF;
4601
4602 j += ipack;
4603 }
4604 }
4605
4606 if ( trail > 0 )
4607 {
4608 offset = head + ipack*inner;
4609 cp0 = cp + offset;
4610 for ( i = 0 ; i < trail ; i++ ) up[i+offset] = (unsigned INT32) cp0[i];
4611 }
4612 /*
4613 if ( tc != -1 ) {
4614 bc++;
4615 *cp0 = (unsigned char) tc;
4616 }
4617 */
4618
4619 return (bc);
4620 }
4621 #endif
4622 #include <stdio.h>
4623
4624
prtbin(int kin,int knbit,int * kout,int * kerr)4625 void prtbin(int kin, int knbit, int *kout, int *kerr)
4626 {
4627 /*
4628
4629 Produces a decimal number with ones and zeroes
4630 corresponding to the ones and zeroes of the input
4631 binary number.
4632 eg input number 1011 binary, output number 1011 decimal.
4633
4634
4635 Input Parameters:
4636
4637 kin - Integer variable containing binary number.
4638
4639 knbit - Number of bits in binary number.
4640
4641 Output Parameters:
4642
4643 kout - Integer variable containing decimal value
4644 with ones and zeroes corresponding to those of
4645 the input binary number.
4646
4647 kerr - 0, If no error.
4648 1, Number of bits in binary number exceeds
4649 maximum allowed or is less than 1.
4650
4651
4652 Converted from EMOS routine PRTBIN.
4653
4654 Uwe Schulzweida MPIfM 01/04/2001
4655
4656 */
4657 int idec;
4658 int ik;
4659 int itemp;
4660 int j;
4661
4662 /*
4663 Check length of binary number to ensure decimal number
4664 generated will fit in the computer word - in this case will
4665 it fit in a Cray 48 bit integer?
4666 */
4667 if ( knbit < 1 || knbit > 14 )
4668 {
4669 *kerr = 1;
4670 printf(" prtbin : Error in binary number length - %3d bits.\n", knbit);
4671 return;
4672 }
4673 else
4674 *kerr = 0;
4675 /*
4676 -----------------------------------------------------------------
4677 Section 1. Generate required number.
4678 -----------------------------------------------------------------
4679 */
4680 *kout = 0;
4681 ik = kin;
4682 idec = 1;
4683
4684 for ( j = 0; j < knbit; j++ )
4685 {
4686 itemp = ik - ( (ik/2)*2 );
4687 *kout = (*kout) + itemp * idec;
4688 ik = ik / 2;
4689 idec = idec * 10;
4690 }
4691
4692 return;
4693 }
4694
4695
ref2ibm(double * pref,int kbits)4696 void ref2ibm(double *pref, int kbits)
4697 {
4698 /*
4699
4700 Purpose:
4701 --------
4702
4703 Code and check reference value in IBM format
4704
4705 Input Parameters:
4706 -----------------
4707
4708 pref - Reference value
4709 kbits - Number of bits per computer word.
4710
4711 Output Parameters:
4712 ------------------
4713
4714 pref - Reference value
4715
4716 Method:
4717 -------
4718
4719 Codes in IBM format, then decides to ensure that reference
4720 value used for packing is not different from that stored
4721 because of packing differences.
4722
4723 Externals.
4724 ----------
4725
4726 confp3 - Encode into IBM floating point format.
4727 decfp2 - Decode from IBM floating point format.
4728
4729 Reference:
4730 ----------
4731
4732 None.
4733
4734 Comments:
4735 --------
4736
4737 None.
4738
4739 Author:
4740 -------
4741
4742 J.D.Chambers ECMWF 17:05:94
4743
4744 Modifications:
4745 --------------
4746
4747 Uwe Schulzweida MPIfM 01/04/2001
4748
4749 Convert to C from EMOS library version 130
4750
4751 */
4752
4753 int itrnd;
4754 int kexp, kmant;
4755 double ztemp, zdumm;
4756 extern int CGRIBEX_Debug;
4757
4758 /* ----------------------------------------------------------------- */
4759 /* Section 1. Convert to and from IBM format. */
4760 /* ----------------------------------------------------------------- */
4761
4762 /* Convert floating point reference value to IBM representation. */
4763
4764 itrnd = 1;
4765 zdumm = ztemp = *pref;
4766 confp3(zdumm, &kexp, &kmant, kbits, itrnd);
4767
4768 if ( kexp == 0 && kmant == 0 ) return;
4769
4770 /* Set reference value to that actually stored in the GRIB code. */
4771
4772 *pref = decfp2(kexp, kmant);
4773
4774 /* If the nearest number which can be represented in */
4775 /* GRIB format is greater than the reference value, */
4776 /* find the nearest number in GRIB format lower */
4777 /* than the reference value. */
4778
4779 if ( ztemp < *pref )
4780 {
4781 /* Convert floating point to GRIB representation */
4782 /* using truncation to ensure that the converted */
4783 /* number is smaller than the original one. */
4784
4785 itrnd = 0;
4786 zdumm = ztemp;
4787 confp3(zdumm, &kexp, &kmant, kbits, itrnd);
4788
4789 /* Set reference value to that stored in the GRIB code. */
4790
4791 *pref = decfp2(kexp, kmant);
4792
4793 if ( ztemp < *pref )
4794 {
4795 if ( CGRIBEX_Debug )
4796 {
4797 Message("Reference value error.");
4798 Message("Notify Met.Applications Section.");
4799 Message("ZTEMP = ", ztemp);
4800 Message("PREF = ", pref);
4801 }
4802 *pref = ztemp;
4803 }
4804 }
4805
4806 return;
4807 } /* ref2ibm */
4808 #include <math.h>
4809 #include <string.h>
4810
4811
correct_bdslen(unsigned bdslen,long recsize,long gribpos)4812 unsigned correct_bdslen(unsigned bdslen, long recsize, long gribpos)
4813 {
4814 /*
4815 If a very large product, the section 4 length field holds
4816 the number of bytes in the product after section 4 upto
4817 the end of the padding bytes.
4818 This is a fixup to get round the restriction on product lengths
4819 due to the count being only 24 bits. It is only possible because
4820 the (default) rounding for GRIB products is 120 bytes.
4821 */
4822 if ( recsize > JP23SET && bdslen <= 120 ) bdslen = (unsigned)(recsize - gribpos - bdslen);
4823 return bdslen;
4824 }
4825
4826
grib1Sections(unsigned char * gribbuffer,long gribbufsize,unsigned char ** pdsp,unsigned char ** gdsp,unsigned char ** bmsp,unsigned char ** bdsp,long * gribrecsize)4827 int grib1Sections(unsigned char *gribbuffer, long gribbufsize, unsigned char **pdsp,
4828 unsigned char **gdsp, unsigned char **bmsp, unsigned char **bdsp, long *gribrecsize)
4829 {
4830 *gribrecsize = 0;
4831 *pdsp = NULL;
4832 *gdsp = NULL;
4833 *bmsp = NULL;
4834 *bdsp = NULL;
4835
4836 unsigned char *section = gribbuffer;
4837 unsigned char *is = gribbuffer;
4838 if ( ! GRIB_START(section) )
4839 {
4840 fprintf(stderr, "Wrong GRIB indicator section: found >%c%c%c%c<\n",
4841 section[0], section[1], section[2], section[3]);
4842 return -1;
4843 }
4844
4845 unsigned recsize = GET_UINT3(section[4], section[5], section[6]);
4846
4847 int gribversion = GRIB_EDITION(section);
4848 if ( gribversion != 0 && gribversion != 1 )
4849 {
4850 fprintf(stderr, "Error while decoding GRIB1 sections: GRIB edition %d records not supported!\n", gribversion);
4851 return -1;
4852 }
4853
4854 unsigned grib1offset = (gribversion == 1) ? 4 : 0;
4855
4856 unsigned char *pds = is + 4 + grib1offset;
4857 unsigned char *bufpointer = pds + PDS_Len;
4858 unsigned gribsize = 4 + grib1offset + PDS_Len;
4859
4860 unsigned char *gds = NULL;
4861 if ( PDS_HAS_GDS )
4862 {
4863 gds = bufpointer;
4864 bufpointer += GDS_Len;
4865 gribsize += GDS_Len;
4866 }
4867
4868 unsigned char *bms = NULL;
4869 if ( PDS_HAS_BMS )
4870 {
4871 bms = bufpointer;
4872 bufpointer += BMS_Len;
4873 gribsize += BMS_Len;
4874 }
4875
4876 unsigned char *bds = bufpointer;
4877 unsigned bdslen = BDS_Len;
4878 if ( recsize > JP23SET && bdslen <= 120 )
4879 {
4880 recsize &= JP23SET;
4881 recsize *= 120;
4882 bdslen = correct_bdslen(bdslen, recsize, gribsize);
4883 }
4884 bufpointer += bdslen;
4885 gribsize += bdslen;
4886 gribsize += 4;
4887
4888 *pdsp = pds;
4889 *gdsp = gds;
4890 *bmsp = bms;
4891 *bdsp = bds;
4892
4893 *gribrecsize = gribsize;
4894 if ( gribbufsize < gribsize )
4895 {
4896 fprintf(stderr, "Inconsistent length of GRIB message (grib_buffer_size=%ld < grib_record_size=%u)!\n", gribbufsize, gribsize);
4897 return 1;
4898 }
4899
4900 if ( !GRIB_FIN(bufpointer) ) // end section - "7777" in ASCII
4901 {
4902 fprintf(stderr, "Missing GRIB end section: found >%c%c%c%c<\n",
4903 bufpointer[0], bufpointer[1], bufpointer[2], bufpointer[3]);
4904 return -2;
4905 }
4906
4907 return 0;
4908 }
4909
4910
grib2Sections(unsigned char * gribbuffer,long gribbufsize,unsigned char ** idsp,unsigned char ** lusp,unsigned char ** gdsp,unsigned char ** pdsp,unsigned char ** drsp,unsigned char ** bmsp,unsigned char ** bdsp)4911 int grib2Sections(unsigned char *gribbuffer, long gribbufsize, unsigned char **idsp,
4912 unsigned char **lusp, unsigned char **gdsp, unsigned char **pdsp,
4913 unsigned char **drsp, unsigned char **bmsp, unsigned char **bdsp)
4914 {
4915 UNUSED(gribbufsize);
4916
4917 *idsp = NULL;
4918 *lusp = NULL;
4919 *gdsp = NULL;
4920 *pdsp = NULL;
4921 *drsp = NULL;
4922 *bmsp = NULL;
4923 *bdsp = NULL;
4924
4925 unsigned char *section = gribbuffer;
4926 unsigned sec_len = 16;
4927
4928 if ( !GRIB_START(section) )
4929 {
4930 fprintf(stderr, "wrong indicator section >%c%c%c%c<\n",
4931 section[0], section[1], section[2], section[3]);
4932 return -1;
4933 }
4934
4935 int gribversion = GRIB_EDITION(section);
4936 if ( gribversion != 2 )
4937 {
4938 fprintf(stderr, "wrong GRIB version %d\n", gribversion);
4939 return -1;
4940 }
4941
4942 unsigned gribsize = 0;
4943 for ( int i = 0; i < 8; i++ ) gribsize = (gribsize << 8) | section[8+i];
4944
4945 unsigned grib_len = sec_len;
4946 section += sec_len;
4947
4948 /* section 1 */
4949 sec_len = GRIB2_SECLEN(section);
4950 int sec_num = GRIB2_SECNUM(section);
4951 //fprintf(stderr, "ids %d %ld\n", sec_num, sec_len);
4952
4953 if ( sec_num != 1 )
4954 {
4955 fprintf(stderr, "Unexpected section1 number %d\n", sec_num);
4956 return -1;
4957 }
4958
4959 *idsp = section;
4960
4961 grib_len += sec_len;
4962 section += sec_len;
4963
4964 /* section 2 and 3 */
4965 sec_len = GRIB2_SECLEN(section);
4966 sec_num = GRIB2_SECNUM(section);
4967 //fprintf(stderr, "lus %d %ld\n", sec_num, sec_len);
4968
4969 if ( sec_num == 2 )
4970 {
4971 *lusp = section;
4972
4973 grib_len += sec_len;
4974 section += sec_len;
4975
4976 /* section 3 */
4977 sec_len = GRIB2_SECLEN(section);
4978 //sec_num = GRIB2_SECNUM(section);
4979 //fprintf(stderr, "gds %d %ld\n", sec_num, sec_len);
4980
4981 *gdsp = section;
4982 }
4983 else if ( sec_num == 3 )
4984 {
4985 *gdsp = section;
4986 }
4987 else
4988 {
4989 fprintf(stderr, "Unexpected section3 number %d\n", sec_num);
4990 return -1;
4991 }
4992
4993 grib_len += sec_len;
4994 section += sec_len;
4995
4996 /* section 4 */
4997 sec_len = GRIB2_SECLEN(section);
4998 sec_num = GRIB2_SECNUM(section);
4999 //fprintf(stderr, "pds %d %ld\n", sec_num, sec_len);
5000
5001 if ( sec_num != 4 )
5002 {
5003 fprintf(stderr, "Unexpected section4 number %d\n", sec_num);
5004 return -1;
5005 }
5006
5007 *pdsp = section;
5008
5009 grib_len += sec_len;
5010 section += sec_len;
5011
5012 /* section 5 */
5013 sec_len = GRIB2_SECLEN(section);
5014 sec_num = GRIB2_SECNUM(section);
5015 //fprintf(stderr, "drs %d %ld\n", sec_num, sec_len);
5016
5017 if ( sec_num != 5 )
5018 {
5019 fprintf(stderr, "Unexpected section5 number %d\n", sec_num);
5020 return -1;
5021 }
5022
5023 *drsp = section;
5024
5025 grib_len += sec_len;
5026 section += sec_len;
5027
5028 /* section 6 */
5029 sec_len = GRIB2_SECLEN(section);
5030 sec_num = GRIB2_SECNUM(section);
5031 //fprintf(stderr, "bms %d %ld\n", sec_num, sec_len);
5032
5033 if ( sec_num != 6 )
5034 {
5035 fprintf(stderr, "Unexpected section6 number %d\n", sec_num);
5036 return -1;
5037 }
5038
5039 *bmsp = section;
5040
5041 grib_len += sec_len;
5042 section += sec_len;
5043
5044 /* section 7 */
5045 sec_len = GRIB2_SECLEN(section);
5046 sec_num = GRIB2_SECNUM(section);
5047 //fprintf(stderr, "bds %d %ld\n", sec_num, sec_len);
5048
5049 if ( sec_num != 7 )
5050 {
5051 fprintf(stderr, "Unexpected section7 number %d\n", sec_num);
5052 return -1;
5053 }
5054
5055 *bdsp = section;
5056
5057 grib_len += sec_len;
5058 section += sec_len;
5059
5060 /* skip multi GRIB sections */
5061 int msec = 1;
5062 while ( !GRIB_FIN(section) )
5063 {
5064 sec_len = GRIB2_SECLEN(section);
5065 sec_num = GRIB2_SECNUM(section);
5066
5067 if ( sec_num < 1 || sec_num > 7 ) break;
5068
5069 if ( sec_num == 7 )
5070 fprintf(stderr, "Skipped unsupported multi GRIB section %d!\n", ++msec);
5071
5072 if ( (grib_len + sec_len) > gribsize ) break;
5073
5074 grib_len += sec_len;
5075 section += sec_len;
5076 }
5077
5078 /* end section - "7777" in ASCII */
5079 if ( !GRIB_FIN(section) )
5080 {
5081 fprintf(stderr, "Missing end section >%2x %2x %2x %2x<\n",
5082 section[0], section[1], section[2], section[3]);
5083 return -2;
5084 }
5085
5086 return 0;
5087 }
5088
5089
grib_info_for_grads(off_t recpos,long recsize,unsigned char * gribbuffer,int * intnum,float * fltnum,off_t * bignum)5090 int grib_info_for_grads(off_t recpos, long recsize, unsigned char *gribbuffer,
5091 int *intnum, float *fltnum, off_t *bignum)
5092 {
5093 long gribsize = 0;
5094 off_t bpos = 0;
5095
5096 unsigned char *section = gribbuffer;
5097 unsigned char *is = gribbuffer;
5098 if ( ! GRIB_START(section) )
5099 {
5100 fprintf(stderr, "wrong indicator section >%c%c%c%c<\n",
5101 section[0], section[1], section[2], section[3]);
5102 return -1;
5103 }
5104
5105 int gribversion = GRIB_EDITION(section);
5106 if ( recsize == 24 && gribversion == 0 ) gribversion = 0;
5107
5108 unsigned grib1offset = (gribversion == 1) ? 4 : 0;
5109
5110 unsigned char *pds = is + 4 + grib1offset;
5111 unsigned char *bufpointer = pds + PDS_Len;
5112 gribsize += 4 + grib1offset + PDS_Len;
5113
5114 unsigned char *gds = NULL;
5115 if ( PDS_HAS_GDS )
5116 {
5117 gds = bufpointer;
5118 bufpointer += GDS_Len;
5119 gribsize += GDS_Len;
5120 }
5121
5122 unsigned char *bms = NULL;
5123 if ( PDS_HAS_BMS )
5124 {
5125 bms = bufpointer;
5126 bufpointer += BMS_Len;
5127 bpos = recpos + gribsize + 6;
5128 gribsize += BMS_Len;
5129 }
5130
5131 unsigned char *bds = bufpointer;
5132
5133 off_t dpos = recpos + gribsize + 11;
5134
5135 unsigned bdslen = BDS_Len;
5136 bdslen = correct_bdslen(bdslen, recsize, bds-gribbuffer);
5137 bufpointer += bdslen;
5138 gribsize += bdslen;
5139 gribsize += 4;
5140
5141 if ( gribsize > recsize )
5142 {
5143 fprintf(stderr, "GRIB buffer size %ld too small! Min size = %ld\n", recsize, gribsize);
5144 return 1;
5145 }
5146
5147 /* end section - "7777" in ascii */
5148 if ( !GRIB_FIN(bufpointer) )
5149 {
5150 fprintf(stderr, "Missing end section >%2x %2x %2x %2x<\n",
5151 bufpointer[0], bufpointer[1], bufpointer[2], bufpointer[3]);
5152 }
5153
5154 int bs = BDS_BinScale;
5155 if ( bs > 32767 ) bs = 32768-bs;
5156 float bsf = ldexpf(1.0f, bs);
5157
5158 bignum[0] = dpos;
5159 bignum[1] = bms ? bpos : -999;
5160 intnum[0] = BDS_NumBits;
5161
5162 /* fltnum[0] = 1.0; */
5163 fltnum[0] = powf(10.0f, (float)PDS_DecimalScale);
5164 fltnum[1] = bsf;
5165 fltnum[2] = (float)BDS_RefValue;
5166 /*
5167 printf("intnum %d %d %d\n", intnum[0], intnum[1], intnum[2]);
5168 printf("fltnum %g %g %g\n", fltnum[0], fltnum[1], fltnum[2]);
5169 */
5170 return 0;
5171 }
5172
5173 static
get_level(unsigned char * pds)5174 int get_level(unsigned char *pds)
5175 {
5176 int level = 0;
5177
5178 if ( PDS_LevelType == 100 )
5179 level = PDS_Level * 100;
5180 else if ( PDS_LevelType == 99 )
5181 level = PDS_Level;
5182 else if ( PDS_LevelType == 109 )
5183 level = PDS_Level;
5184 else
5185 level = PDS_Level1;
5186
5187 return level;
5188 }
5189
5190 static
get_cr(unsigned char * w1,unsigned char * w2)5191 double get_cr(unsigned char *w1, unsigned char *w2)
5192 {
5193 unsigned s1 = GET_UINT3(w1[0], w1[1], w1[2]);
5194 unsigned s2 = GET_UINT3(w2[0], w2[1], w2[2]);
5195 return ((double)s1)/s2;
5196 }
5197
5198
grib1PrintALL(int nrec,long offset,long recpos,long recsize,unsigned char * gribbuffer)5199 static void grib1PrintALL(int nrec, long offset, long recpos, long recsize, unsigned char *gribbuffer)
5200 {
5201 static bool header = true;
5202 unsigned char *is = NULL, *pds = NULL, *gds = NULL, *bms = NULL, *bds = NULL;
5203
5204 if ( header )
5205 {
5206 fprintf(stdout,
5207 " Rec : Off Position Size : V PDS GDS BMS BDS : Code Level : LType GType: CR LL\n");
5208 /* ----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+ */
5209 header = false;
5210 }
5211
5212 is = gribbuffer;
5213
5214 unsigned gribsize = GET_UINT3(is[4], is[5], is[6]);
5215
5216 long gribrecsize;
5217 int nerr = grib1Sections(gribbuffer, recsize, &pds, &gds, &bms, &bds, &gribrecsize);
5218 if ( nerr < 0 )
5219 {
5220 fprintf(stdout, "%5d :%4ld %8ld %6ld : GRIB message error\n", nrec, offset, recpos, recsize);
5221 return;
5222 }
5223
5224 int GridType = (gds == NULL) ? -1 : (int)GDS_GridType;
5225
5226 int level = get_level(pds);
5227
5228 unsigned bdslen = BDS_Len;
5229
5230 bool llarge = (gribsize > JP23SET && bdslen <= 120);
5231
5232 bdslen = correct_bdslen(bdslen, recsize, bds-gribbuffer);
5233
5234 double cr = (((BDS_Flag >> 4)&1) && (BDS_Z == 128 || BDS_Z == 130)) ? get_cr(&bds[14], &gribbuffer[4]) : 1;
5235
5236 fprintf(stdout, "%5d :%4ld %8ld %6ld :%2d%4d%5d %6d %6d : %3d %6d : %5d %5d %6.4g %c",
5237 nrec, offset, recpos, recsize, GRIB_EDITION(is),
5238 PDS_Len, GDS_Len, BMS_Len, bdslen,
5239 PDS_Parameter, level, PDS_LevelType, GridType, cr, llarge?'T':'F');
5240
5241 if ( nerr > 0 ) fprintf(stdout, " <-- GRIB data corrupted!");
5242 fprintf(stdout, "\n");
5243 }
5244
5245
grib2PrintALL(int nrec,long offset,long recpos,long recsize,unsigned char * gribbuffer)5246 static void grib2PrintALL(int nrec, long offset, long recpos, long recsize, unsigned char *gribbuffer)
5247 {
5248 static bool header = true;
5249 unsigned char *is = NULL, *pds = NULL, *gds = NULL, *bms = NULL, *bds = NULL;
5250 unsigned char *ids = NULL, *lus = NULL, *drs = NULL;
5251 long ids_len = 0, lus_len = 0, gds_len = 0, pds_len = 0, drs_len = 0, bms_len = 0, bds_len = 0;
5252 double cr = 1;
5253
5254 if ( header )
5255 {
5256 fprintf(stdout,
5257 " Rec : Off Position Size : V IDS LUS GDS PDS DRS BMS BDS : Parameter Level : LType GType: CR\n");
5258 /* ----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+ */
5259 header = false;
5260 }
5261
5262 is = gribbuffer;
5263
5264 int nerr = grib2Sections(gribbuffer, recsize, &ids, &lus, &gds, &pds, &drs, &bms, &bds);
5265 if ( nerr )
5266 {
5267 fprintf(stdout, "%5d :%4ld %8ld %6ld : error\n", nrec, offset, recpos, recsize);
5268 return;
5269 }
5270
5271 if ( ids ) ids_len = GRIB2_SECLEN(ids);
5272 if ( lus ) lus_len = GRIB2_SECLEN(lus);
5273 if ( gds ) gds_len = GRIB2_SECLEN(gds);
5274 if ( pds ) pds_len = GRIB2_SECLEN(pds);
5275 if ( drs ) drs_len = GRIB2_SECLEN(drs);
5276 if ( bms ) bms_len = GRIB2_SECLEN(bms);
5277 if ( bds ) bds_len = GRIB2_SECLEN(bds);
5278
5279 // double cr = (((BDS_Flag >> 4)&1) && (BDS_Z == 128 || BDS_Z == 130)) ? get_cr(&bds[14], &gribbuffer[4]) : 1;
5280
5281 int dis = GET_UINT1(is[6]);
5282 int gridtype = GET_UINT2(gds[12],gds[13]);
5283 int paramcat = GET_UINT1(pds[9]);
5284 int paramnum = GET_UINT1(pds[10]);
5285 int level1type = GET_UINT1(pds[22]);
5286 /* level1sf = GET_UINT1(pds[23]); */
5287 int level1 = GET_UINT4(pds[24],pds[25],pds[26],pds[27]);
5288 /* level2type = GET_UINT1(pds[28]); */
5289 /* level2sf = GET_UINT1(pds[29]); */
5290 /* level2 = GET_UINT4(pds[30],pds[31],pds[32],pds[33]); */
5291 /*
5292 printf("level %d %d %d %d %d %d %d\n", level1type, level1sf, level1, level1*level1sf, level2sf, level2, level2*level2sf);
5293 */
5294 char paramstr[16];
5295 sprintf(paramstr, "%d.%d.%d", paramnum, paramcat, dis);
5296 fprintf(stdout, "%5d :%4ld %8ld %6ld :%2d %3ld %3ld %3ld %3ld %4ld %6ld %6ld : %-9s %7d : %5d %5d %6.4g\n",
5297 nrec, offset, recpos, recsize, GRIB_EDITION(is),
5298 ids_len, lus_len, gds_len, pds_len, drs_len, bms_len, bds_len,
5299 paramstr, level1, level1type, gridtype, cr);
5300 }
5301
5302
gribPrintALL(int nrec,long offset,long recpos,long recsize,unsigned char * gribbuffer)5303 void gribPrintALL(int nrec, long offset, long recpos, long recsize, unsigned char *gribbuffer)
5304 {
5305 int gribversion = gribVersion(gribbuffer, (size_t)recsize);
5306
5307 if ( gribversion == 0 || gribversion == 1 )
5308 grib1PrintALL(nrec, offset, recpos, recsize, gribbuffer);
5309 else if ( gribversion == 2 )
5310 grib2PrintALL(nrec, offset, recpos, recsize, gribbuffer);
5311 else
5312 {
5313 fprintf(stdout, "%5d :%4ld%9ld%7ld : GRIB version %d unsupported\n",
5314 nrec, offset, recpos, recsize, gribversion);
5315 }
5316 }
5317
5318
grib1PrintPDS(int nrec,long recpos,long recsize,unsigned char * gribbuffer)5319 static void grib1PrintPDS(int nrec, long recpos, long recsize, unsigned char *gribbuffer)
5320 {
5321 static int header = 1;
5322 unsigned char *is = NULL, *pds = NULL, *gds = NULL, *bms = NULL, *bds = NULL;
5323 int century, subcenter, decimalscale;
5324 int fc_num = 0;
5325 int year = 0, date;
5326
5327 UNUSED(recpos);
5328
5329 if ( header )
5330 {
5331 fprintf(stdout,
5332 " Rec : PDS Tab Cen Sub Ver Grid Code LTyp Level1 Level2 Date Time P1 P2 TU TR NAVE Scale FCnum CT\n");
5333 /* ----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+ */
5334 header = 0;
5335 }
5336
5337 is = gribbuffer;
5338
5339 long gribrecsize;
5340 int nerr = grib1Sections(gribbuffer, recsize, &pds, &gds, &bms, &bds, &gribrecsize);
5341 if ( nerr < 0 )
5342 {
5343 fprintf(stdout, "%5d : GRIB message error\n", nrec);
5344 return;
5345 }
5346
5347 switch(GRIB_EDITION(is))
5348 {
5349 case 0:
5350 year = GET_UINT1(pds[12]);
5351 century = 1;
5352 subcenter = 0;
5353 decimalscale = 0;
5354 break;
5355 case 1:
5356 year = PDS_Year;
5357 century = PDS_Century;
5358 subcenter = PDS_Subcenter;
5359 decimalscale = PDS_DecimalScale;
5360 break;
5361 default:
5362 fprintf(stderr, "Grib version %d not supported!", GRIB_EDITION(is));
5363 exit(EXIT_FAILURE);
5364 }
5365
5366 if ( PDS_Len > 28 )
5367 if ( PDS_CenterID == 98 || PDS_Subcenter == 98 ||
5368 (PDS_CenterID == 7 && PDS_Subcenter == 98) )
5369 if ( pds[40] == 1 )
5370 fc_num = GET_UINT1(pds[49]);
5371
5372 if ( year < 0 )
5373 {
5374 date = (-year)*10000+PDS_Month*100+PDS_Day;
5375 century = -century;
5376 }
5377 else
5378 {
5379 date = year*10000+PDS_Month*100+PDS_Day;
5380 }
5381
5382 fprintf(stdout, "%5d :%4d%4d%4d%4d%4d %4d %4d%4d%7d%7d %8d%6d%3d%3d%3d%3d%5d%6d%5d%4d", nrec,
5383 PDS_Len, PDS_CodeTable, PDS_CenterID, subcenter, PDS_ModelID,
5384 PDS_GridDefinition, PDS_Parameter, PDS_LevelType, PDS_Level1, PDS_Level2,
5385 date, PDS_Time, PDS_TimePeriod1, PDS_TimePeriod2, PDS_TimeUnit, PDS_TimeRange,
5386 PDS_AvgNum, decimalscale, fc_num, century);
5387
5388 if ( nerr > 0 ) fprintf(stdout, " <-- GRIB data corrupted!");
5389 fprintf(stdout, "\n");
5390 }
5391
5392
gribPrintPDS(int nrec,long recpos,long recsize,unsigned char * gribbuffer)5393 void gribPrintPDS(int nrec, long recpos, long recsize, unsigned char *gribbuffer)
5394 {
5395 int gribversion = gribVersion(gribbuffer, (size_t)recsize);
5396
5397 if ( gribversion == 0 || gribversion == 1 )
5398 grib1PrintPDS(nrec, recpos, recsize, gribbuffer);
5399 /*
5400 else if ( gribversion == 2 )
5401 grib2PrintPDS(nrec, recpos, recsize, gribbuffer);
5402 */
5403 else
5404 {
5405 fprintf(stdout, "%5d :%4ld%9ld%7ld : GRIB version %d unsupported\n",
5406 nrec, 0L, recpos, recsize, gribversion);
5407 }
5408 }
5409
5410
grib1PrintGDS(int nrec,long recpos,long recsize,unsigned char * gribbuffer)5411 static void grib1PrintGDS(int nrec, long recpos, long recsize, unsigned char *gribbuffer)
5412 {
5413 static int header = 1;
5414 unsigned char *pds = NULL, *gds = NULL, *bms = NULL, *bds = NULL;
5415
5416 UNUSED(recpos);
5417
5418 if ( header )
5419 {
5420 fprintf(stdout,
5421 " Rec : GDS NV PVPL Typ : xsize ysize Lat1 Lon1 Lat2 Lon2 dx dy\n");
5422 /* ----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+ */
5423 header = 0;
5424 }
5425
5426 long gribrecsize;
5427 int nerr = grib1Sections(gribbuffer, recsize, &pds, &gds, &bms, &bds, &gribrecsize);
5428 if ( nerr < 0 )
5429 {
5430 fprintf(stdout, "%5d : GRIB message error\n", nrec);
5431 return;
5432 }
5433
5434 fprintf(stdout, "%5d :", nrec);
5435
5436 if ( gds )
5437 fprintf(stdout, "%4d%4d%4d %4d :%6d%6d%7d%7d%7d%7d%6d%6d",
5438 GDS_Len, GDS_NV, GDS_PVPL, GDS_GridType,
5439 GDS_NumLon, GDS_NumLat,
5440 GDS_FirstLat, GDS_FirstLon,
5441 GDS_LastLat, GDS_LastLon,
5442 GDS_LonIncr, GDS_LatIncr);
5443 else
5444 fprintf(stdout, " Grid Description Section not defined");
5445
5446 if ( nerr > 0 ) fprintf(stdout, " <-- GRIB data corrupted!");
5447 fprintf(stdout, "\n");
5448 }
5449
5450
gribPrintGDS(int nrec,long recpos,long recsize,unsigned char * gribbuffer)5451 void gribPrintGDS(int nrec, long recpos, long recsize, unsigned char *gribbuffer)
5452 {
5453 int gribversion = gribVersion(gribbuffer, (size_t)recsize);
5454
5455 if ( gribversion == 0 || gribversion == 1 )
5456 grib1PrintGDS(nrec, recpos, recsize, gribbuffer);
5457 /*
5458 else if ( gribversion == 2 )
5459 grib2PrintGDS(nrec, recpos, recsize, gribbuffer);
5460 */
5461 else
5462 {
5463 fprintf(stdout, "%5d :%4ld%9ld%7ld : GRIB version %d unsupported\n",
5464 nrec, 0L, recpos, recsize, gribversion);
5465 }
5466 }
5467
5468
grib1PrintBMS(int nrec,long recpos,long recsize,unsigned char * gribbuffer)5469 static void grib1PrintBMS(int nrec, long recpos, long recsize, unsigned char *gribbuffer)
5470 {
5471 static int header = 1;
5472 unsigned char *pds = NULL, *gds = NULL, *bms = NULL, *bds = NULL;
5473
5474 UNUSED(recpos);
5475
5476 if ( header )
5477 {
5478 fprintf(stdout,
5479 " Rec : Code Level BMS Size\n");
5480 /* ----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+ */
5481 header = 0;
5482 }
5483
5484 long gribrecsize;
5485 int nerr = grib1Sections(gribbuffer, recsize, &pds, &gds, &bms, &bds, &gribrecsize);
5486 if ( nerr < 0 )
5487 {
5488 fprintf(stdout, "%5d : GRIB message error\n", nrec);
5489 return;
5490 }
5491
5492 int level = get_level(pds);
5493
5494 fprintf(stdout, "%5d :", nrec);
5495
5496 if ( bms )
5497 fprintf(stdout, "%4d%7d %7d %7d",
5498 PDS_Parameter, level, BMS_Len, BMS_BitmapSize);
5499 else
5500 fprintf(stdout, "%4d%7d Bit Map Section not defined", PDS_Parameter, level);
5501
5502 if ( nerr > 0 ) fprintf(stdout, " <-- GRIB data corrupted!");
5503 fprintf(stdout, "\n");
5504 }
5505
5506
gribPrintBMS(int nrec,long recpos,long recsize,unsigned char * gribbuffer)5507 void gribPrintBMS(int nrec, long recpos, long recsize, unsigned char *gribbuffer)
5508 {
5509 int gribversion = gribVersion(gribbuffer, (size_t)recsize);
5510
5511 if ( gribversion == 0 || gribversion == 1 )
5512 grib1PrintBMS(nrec, recpos, recsize, gribbuffer);
5513 /*
5514 else if ( gribversion == 2 )
5515 grib2PrintBMS(nrec, recpos, recsize, gribbuffer);
5516 */
5517 else
5518 {
5519 fprintf(stdout, "%5d :%4ld%9ld%7ld : GRIB version %d unsupported\n",
5520 nrec, 0L, recpos, recsize, gribversion);
5521 }
5522 }
5523
5524
grib1PrintBDS(int nrec,long recpos,long recsize,unsigned char * gribbuffer)5525 static void grib1PrintBDS(int nrec, long recpos, long recsize, unsigned char *gribbuffer)
5526 {
5527 static int header = 1;
5528 unsigned char *pds = NULL, *gds = NULL, *bms = NULL, *bds = NULL;
5529 double scale;
5530
5531 UNUSED(recpos);
5532
5533 if ( header )
5534 {
5535 fprintf(stdout,
5536 " Rec : Code Level BDS Flag Scale RefValue Bits CR\n");
5537 /* ----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+ */
5538 header = 0;
5539 }
5540
5541 long gribrecsize;
5542 int nerr = grib1Sections(gribbuffer, recsize, &pds, &gds, &bms, &bds, &gribrecsize);
5543 if ( nerr < 0 )
5544 {
5545 fprintf(stdout, "%5d : GRIB message error\n", nrec);
5546 return;
5547 }
5548
5549 int level = get_level(pds);
5550
5551 double cr = (((BDS_Flag >> 4)&1) && BDS_Z == 128) ? get_cr(&bds[17], &bds[20]) : 1;
5552
5553 double refval = BDS_RefValue;
5554
5555 if ( BDS_BinScale < 0 )
5556 scale = 1.0/pow(2.0, (double) -BDS_BinScale);
5557 else
5558 scale = pow(2.0, (double) BDS_BinScale);
5559
5560 if ( PDS_DecimalScale )
5561 {
5562 double decscale = pow(10.0, (double)-PDS_DecimalScale);
5563 refval *= decscale;
5564 scale *= decscale;
5565 }
5566
5567 fprintf(stdout, "%5d :", nrec);
5568
5569 if ( bds )
5570 fprintf(stdout, "%4d%7d %7d %4d %8.5g %11.5g%4d %6.4g",
5571 PDS_Parameter, level,
5572 BDS_Len, BDS_Flag, scale, refval, BDS_NumBits, cr);
5573 else
5574 fprintf(stdout, " Binary Data Section not defined");
5575
5576 if ( nerr > 0 ) fprintf(stdout, " <-- GRIB data corrupted!");
5577 fprintf(stdout, "\n");
5578 }
5579
5580
gribPrintBDS(int nrec,long recpos,long recsize,unsigned char * gribbuffer)5581 void gribPrintBDS(int nrec, long recpos, long recsize, unsigned char *gribbuffer)
5582 {
5583 int gribversion = gribVersion(gribbuffer, (size_t)recsize);
5584
5585 if ( gribversion == 0 || gribversion == 1 )
5586 grib1PrintBDS(nrec, recpos, recsize, gribbuffer);
5587 /*
5588 else if ( gribversion == 2 )
5589 grib2PrintBDS(nrec, recpos, recsize, gribbuffer);
5590 */
5591 else
5592 {
5593 fprintf(stdout, "%5d :%4ld%9ld%7ld : GRIB version %d unsupported\n",
5594 nrec, 0L, recpos, recsize, gribversion);
5595 }
5596 }
5597
5598
gribCheck1(int nrec,long recpos,long recsize,unsigned char * gribbuffer)5599 void gribCheck1(int nrec, long recpos, long recsize, unsigned char *gribbuffer)
5600 {
5601 unsigned char *pds = NULL, *gds = NULL, *bms = NULL, *bds = NULL;
5602
5603 UNUSED(recpos);
5604
5605 long gribrecsize;
5606 int nerr = grib1Sections(gribbuffer, recsize, &pds, &gds, &bms, &bds, &gribrecsize);
5607 if ( nerr < 0 )
5608 {
5609 fprintf(stdout, "%5d : GRIB message error\n", nrec);
5610 return;
5611 }
5612
5613 if ( nerr > 0 )
5614 {
5615 fprintf(stdout, "%5d : <-- GRIB data corrupted!\n", nrec);
5616 return;
5617 }
5618
5619 int level = get_level(pds);
5620
5621 double cr = (((BDS_Flag >> 4)&1) && BDS_Z == 128) ? get_cr(&bds[17], &bds[20]) : 1;
5622
5623 if ( IS_EQUAL(cr, 1) && BDS_NumBits == 24 )
5624 fprintf(stdout, "GRIB record %5d : code = %4d level = %7d\n", nrec, PDS_Parameter, level);
5625 }
5626
5627
5628 static
repair1(unsigned char * gbuf,long gbufsize)5629 void repair1(unsigned char *gbuf, long gbufsize)
5630 {
5631 unsigned char *pds = NULL, *gds = NULL, *bms = NULL, *bds = NULL;
5632 /* int recLen; */
5633 unsigned char *source;
5634 size_t sourceLen;
5635 int bds_nbits, bds_flag, lspherc, lcomplex /*, lcompress */;
5636 int bds_head = 11;
5637 int bds_ext = 0, bds_ubits;
5638 int datstart = 0;
5639
5640 long gribrecsize;
5641 int nerr = grib1Sections(gbuf, gbufsize, &pds, &gds, &bms, &bds, &gribrecsize);
5642 if ( nerr < 0 )
5643 {
5644 fprintf(stdout, "GRIB message error\n");
5645 return;
5646 }
5647
5648 if ( nerr > 0 )
5649 {
5650 fprintf(stdout, "GRIB data corrupted!\n");
5651 return;
5652 }
5653
5654 unsigned bds_len = BDS_Len;
5655 bds_nbits = BDS_NumBits;
5656 bds_flag = BDS_Flag;
5657 bds_ubits = bds_flag & 15;
5658 lspherc = bds_flag >> 7;
5659 lcomplex = (bds_flag >> 6)&1;
5660 /* lcompress = (bds_flag >> 4)&1; */
5661
5662 if ( lspherc )
5663 {
5664 if ( lcomplex )
5665 {
5666 int jup, ioff;
5667 jup = bds[15];
5668 ioff = (jup+1)*(jup+2);
5669 bds_ext = 4 + 3 + 4*ioff;
5670 }
5671 else
5672 {
5673 bds_ext = 4;
5674 }
5675 }
5676
5677 datstart = bds_head + bds_ext;
5678
5679 source = bds + datstart;
5680
5681 sourceLen = (size_t)(((((bds_len - datstart)*8-bds_ubits)/bds_nbits)*bds_nbits)/8);
5682
5683 if ( bds_nbits == 24 )
5684 {
5685 unsigned char *pbuf = (unsigned char*) Malloc(sourceLen);;
5686 size_t nelem = sourceLen/3;
5687 for ( size_t i = 0; i < nelem; i++ )
5688 {
5689 pbuf[3*i ] = source[ i];
5690 pbuf[3*i+1] = source[ nelem+i];
5691 pbuf[3*i+2] = source[2*nelem+i];
5692 }
5693 memcpy(source, pbuf, sourceLen);
5694 Free(pbuf);
5695 }
5696 }
5697
5698
gribRepair1(int nrec,long recsize,unsigned char * gribbuffer)5699 void gribRepair1(int nrec, long recsize, unsigned char *gribbuffer)
5700 {
5701 unsigned char *pds = NULL, *gds = NULL, *bms = NULL, *bds = NULL;
5702
5703 long gribrecsize;
5704 int nerr = grib1Sections(gribbuffer, recsize, &pds, &gds, &bms, &bds, &gribrecsize);
5705 if ( nerr < 0 )
5706 {
5707 fprintf(stdout, "%5d : GRIB message error\n", nrec);
5708 return;
5709 }
5710
5711 if ( nerr > 0 )
5712 {
5713 fprintf(stdout, "%5d : <-- GRIB data corrupted!\n", nrec);
5714 return;
5715 }
5716
5717 int level = get_level(pds);
5718
5719 double cr = (((BDS_Flag >> 4)&1) && BDS_Z == 128) ? get_cr(&bds[17], &bds[20]) : 1;
5720
5721 if ( IS_EQUAL(cr, 1) && BDS_NumBits == 24 )
5722 {
5723 fprintf(stdout, "Repair GRIB record %5d : code = %4d level = %7d\n", nrec, PDS_Parameter, level);
5724 repair1(gribbuffer, recsize);
5725 }
5726 }
5727 #include <stdio.h>
5728 #include <string.h>
5729
5730 #if defined (HAVE_CONFIG_H)
5731 #endif
5732
5733 #if defined (HAVE_LIBSZ)
5734 #if defined(__cplusplus)
5735 extern "C" {
5736 #endif
5737 #include <szlib.h>
5738 #ifdef __cplusplus
5739 }
5740 #endif
5741
5742 #define OPTIONS_MASK (SZ_RAW_OPTION_MASK | SZ_MSB_OPTION_MASK | SZ_NN_OPTION_MASK)
5743
5744 #define PIXELS_PER_BLOCK (8)
5745 #define PIXELS_PER_SCANLINE (PIXELS_PER_BLOCK*128)
5746
5747 #define MIN_COMPRESS (0.95)
5748 #define MIN_SIZE (256)
5749 #endif
5750
5751 #define Z_SZIP 128
5752
5753 #if defined (HAVE_LIBSZ) || defined (HAVE_LIBAEC)
5754 #define SetLen3(var, offset, value) ((var[offset+0] = 0xFF & (value >> 16)), \
5755 (var[offset+1] = 0xFF & (value >> 8)), \
5756 (var[offset+2] = 0xFF & (value )))
5757 #define SetLen4(var, offset, value) ((var[offset+0] = 0xFF & (value >> 24)), \
5758 (var[offset+1] = 0xFF & (value >> 16)), \
5759 (var[offset+2] = 0xFF & (value >> 8)), \
5760 (var[offset+3] = 0xFF & (value )))
5761 #endif
5762
gribGetZip(size_t recsize,unsigned char * gribbuffer,size_t * urecsize)5763 int gribGetZip(size_t recsize, unsigned char *gribbuffer, size_t *urecsize)
5764 {
5765 int compress = 0;
5766 unsigned char *pds = NULL, *gds = NULL, *bms = NULL, *bds = NULL;
5767
5768 int gribversion = gribVersion(gribbuffer, recsize);
5769
5770 if ( gribversion == 2 ) return compress;
5771
5772 long gribrecsize;
5773 int nerr = grib1Sections(gribbuffer, (long)recsize, &pds, &gds, &bms, &bds, &gribrecsize);
5774 if ( nerr < 0 )
5775 {
5776 fprintf(stdout, "GRIB message error\n");
5777 return compress;
5778 }
5779
5780 if ( nerr > 0 )
5781 {
5782 fprintf(stdout, "GRIB data corrupted!\n");
5783 return compress;
5784 }
5785
5786 /* bds_len = BDS_Len; */
5787 /* bds_nbits = BDS_NumBits; */
5788 int bds_flag = BDS_Flag;
5789 /* lspherc = bds_flag >> 7; */
5790 /* lcomplex = (bds_flag >> 6)&1; */
5791 int lcompress = (bds_flag >> 4)&1;
5792
5793 size_t gribsize = 0;
5794 if ( lcompress )
5795 {
5796 compress = BDS_Z;
5797 if ( compress == Z_SZIP ) gribsize = (size_t) GET_UINT3(bds[14], bds[15], bds[16]);
5798 }
5799
5800 *urecsize = gribsize;
5801
5802 return compress;
5803 }
5804
5805
gribZip(unsigned char * dbuf,long dbufsize,unsigned char * sbuf,long sbufsize)5806 int gribZip(unsigned char *dbuf, long dbufsize, unsigned char *sbuf, long sbufsize)
5807 {
5808 #if ! defined(HAVE_LIBSZ)
5809 static int libszwarn = 1;
5810 #endif
5811 unsigned char *pds = NULL, *gds = NULL, *bms = NULL, *bds = NULL;
5812 bool llarge = false;
5813
5814 unsigned gribLen = GET_UINT3(dbuf[4], dbuf[5], dbuf[6]);
5815
5816 int rec_len = gribLen;
5817
5818 long gribrecsize;
5819 int nerr = grib1Sections(dbuf, dbufsize, &pds, &gds, &bms, &bds, &gribrecsize);
5820 if ( nerr < 0 )
5821 {
5822 fprintf(stdout, "GRIB message error\n");
5823 return gribrecsize;
5824 }
5825
5826 if ( nerr > 0 )
5827 {
5828 fprintf(stdout, "GRIB data corrupted!\n");
5829 return gribrecsize;
5830 }
5831
5832 int bds_zoffset = 12;
5833
5834 int bds_len = BDS_Len;
5835 if ( gribLen > JP23SET && bds_len <= 120 )
5836 {
5837 gribLen &= JP23SET;
5838 gribLen *= 120;
5839 bds_len = correct_bdslen(bds_len, gribLen, bds-dbuf);
5840 llarge = true;
5841 bds_zoffset += 2;
5842 }
5843
5844 if ( gribLen > JP24SET || llarge ) return gribLen;
5845
5846 #if defined(HAVE_LIBSZ)
5847 {
5848 int bds_zstart = 14;
5849 unsigned gribLenOld = 0;
5850 int bds_head = 11;
5851 int bds_ext = 0;
5852 unsigned char *pbuf = NULL;
5853
5854 int bds_nbits = BDS_NumBits;
5855 int bds_flag = BDS_Flag;
5856 int bds_ubits = bds_flag & 15;
5857 int lspherc = bds_flag >> 7;
5858 int lcomplex = (bds_flag >> 6)&1;
5859 /* lcompress = (bds_flag >> 4)&1; */
5860
5861 if ( bds_nbits != 8 && bds_nbits != 16 && bds_nbits != 24 && bds_nbits != 32 )
5862 {
5863 static bool linfo = true;
5864 if ( linfo && bds_nbits != 0 )
5865 {
5866 linfo = false;
5867 fprintf(stderr, "GRIB szip supports only 8, 16, 24 and 32 bit data!\n");
5868 }
5869 return rec_len;
5870 }
5871
5872 int bits_per_sample = (bds_nbits == 24) ? 8 : bds_nbits;
5873
5874 SZ_com_t sz_param; /* szip parameter block */
5875 sz_param.options_mask = OPTIONS_MASK;
5876 sz_param.bits_per_pixel = bits_per_sample;
5877 sz_param.pixels_per_block = PIXELS_PER_BLOCK;
5878 sz_param.pixels_per_scanline = PIXELS_PER_SCANLINE;
5879
5880 if ( lspherc )
5881 {
5882 bds_ext = 4;
5883 if ( lcomplex )
5884 {
5885 int jup = bds[15];
5886 int ioff = (jup+1)*(jup+2);
5887 bds_ext += 3 + 4*ioff;
5888 }
5889 }
5890
5891 size_t datstart = bds_head + bds_ext;
5892
5893 size_t datsize = ((((bds_len - datstart)*8-bds_ubits)/bds_nbits)*bds_nbits)/8;
5894
5895 if ( datsize < MIN_SIZE ) return rec_len;
5896 /*
5897 fprintf(stderr, "%d %d %d %d\n", bds_len, datstart, bds_len - datstart, datsize);
5898 */
5899 size_t sourceLen = datsize;
5900 size_t destLen = sbufsize;
5901
5902 unsigned char *source = bds + datstart;
5903 unsigned char *dest = sbuf;
5904
5905 if ( bds_nbits == 24 )
5906 {
5907 long nelem = sourceLen/3;
5908 pbuf = (unsigned char*) Malloc(sourceLen);
5909 for ( long i = 0; i < nelem; i++ )
5910 {
5911 pbuf[ i] = source[3*i ];
5912 pbuf[ nelem+i] = source[3*i+1];
5913 pbuf[2*nelem+i] = source[3*i+2];
5914 }
5915 source = pbuf;
5916 }
5917
5918 int status = SZ_BufftoBuffCompress(dest, &destLen, source, sourceLen, &sz_param);
5919 if ( status != SZ_OK )
5920 {
5921 if ( status == SZ_NO_ENCODER_ERROR )
5922 Warning("SZ_NO_ENCODER_ERROR code %3d level %3d", PDS_Parameter, PDS_Level2);
5923 else if ( status == SZ_PARAM_ERROR )
5924 Warning("SZ_PARAM_ERROR code %3d level %3d", PDS_Parameter, PDS_Level2);
5925 else if ( status == SZ_MEM_ERROR )
5926 Warning("SZ_MEM_ERROR code %3d level %3d", PDS_Parameter, PDS_Level2);
5927 else if ( status == SZ_OUTBUFF_FULL )
5928 /*Warning("SZ_OUTBUFF_FULL code %3d level %3d", PDS_Parameter, PDS_Level2)*/;
5929 else
5930 Warning("SZ ERROR: %d code %3d level %3d", status, PDS_Parameter, PDS_Level2);
5931 }
5932
5933 if ( pbuf ) Free(pbuf);
5934 /*
5935 fprintf(stderr, "sourceLen, destLen %d %d\n", sourceLen, destLen);
5936 */
5937 if ( destLen < MIN_COMPRESS*sourceLen )
5938 {
5939 source = bds + datstart + bds_zoffset;
5940 memcpy(source, dest, destLen);
5941
5942 /* ----++++ number of unused bits at end of section) */
5943
5944 BDS_Flag -= bds_ubits;
5945
5946 gribLenOld = gribLen;
5947
5948 if ( bds_ext )
5949 for ( long i = bds_ext-1; i >= 0; --i )
5950 bds[bds_zoffset+bds_head+i] = bds[bds_head+i];
5951
5952 /*
5953 fprintf(stderr, "destLen, datsize, datstart %d %d %d\n", destLen, datsize, datstart);
5954 */
5955 /* memcpy(bds + datstart + bds_zoffset, source, destLen); */
5956 /*
5957 fprintf(stderr, "z>>> %d %d %d %d <<<\n", (int) bds[0+datstart+bds_zoffset],
5958 (int)bds[1+datstart+bds_zoffset], (int)bds[2+datstart+bds_zoffset], (int)bds[3+datstart+bds_zoffset]);
5959 */
5960 if ( llarge )
5961 {
5962 if ( gribLenOld%120 )
5963 {
5964 fprintf(stderr, "Internal problem, record length not multiple of 120!");
5965 while ( gribLenOld%120 ) gribLenOld++;
5966 }
5967 // gribLenOld = gribLenOld / (-120);
5968 // gribLenOld = JP23SET - gribLenOld + 1;
5969
5970 SetLen3(bds, bds_zstart, gribLenOld);
5971 SetLen4(bds, bds_zstart+3, sourceLen);
5972 SetLen4(bds, bds_zstart+7, destLen);
5973 }
5974 else
5975 {
5976 SetLen3(bds, bds_zstart, gribLenOld);
5977 SetLen3(bds, bds_zstart+3, sourceLen);
5978 SetLen3(bds, bds_zstart+6, destLen);
5979 }
5980
5981 int bdsLen = datstart + bds_zoffset + destLen;
5982
5983 bds[11] = 0;
5984 bds[12] = 0;
5985
5986 BDS_Z = Z_SZIP;
5987
5988 BDS_Flag += 16;
5989 if ( (bdsLen%2) == 1 )
5990 {
5991 BDS_Flag += 8;
5992 bds[bdsLen++] = 0;
5993 }
5994
5995 SetLen3(bds, 0, bdsLen);
5996
5997 gribLen = (bds - dbuf) + bdsLen;
5998
5999 dbuf[gribLen++] = '7';
6000 dbuf[gribLen++] = '7';
6001 dbuf[gribLen++] = '7';
6002 dbuf[gribLen++] = '7';
6003
6004 if ( llarge )
6005 {
6006 long bdslen = gribLen - 4;
6007
6008 /*
6009 If a very large product, the section 4 length field holds
6010 the number of bytes in the product after section 4 upto
6011 the end of the padding bytes.
6012 This is a fixup to get round the restriction on product lengths
6013 due to the count being only 24 bits. It is only possible because
6014 the (default) rounding for GRIB products is 120 bytes.
6015 */
6016 while ( gribLen%120 ) dbuf[gribLen++] = 0;
6017
6018 long itemp = gribLen / (-120);
6019 itemp = JP23SET - itemp + 1;
6020
6021 SetLen3(dbuf, 4, itemp);
6022
6023 bdslen = gribLen - bdslen;
6024
6025 SetLen3(bds, 0, bdslen);
6026 }
6027 else
6028 {
6029 SetLen3(dbuf, 4, gribLen);
6030 }
6031 }
6032 else
6033 {
6034 }
6035 /*
6036 fprintf(stderr, "%3d %3d griblen in %6d out %6d CR %g slen %6d dlen %6d CR %g\n",
6037 PDS_Parameter, PDS_Level1, gribLenOld, gribLen,
6038 ((double)gribLenOld)/gribLen, sourceLen, destLen,
6039 ((double)sourceLen)/destLen);
6040 */
6041 }
6042
6043 #else
6044
6045 UNUSED(sbuf);
6046 UNUSED(sbufsize);
6047
6048 if ( libszwarn )
6049 {
6050 Warning("Compression disabled, szlib not available!");
6051 libszwarn = 0;
6052 }
6053 #endif
6054
6055 if ( llarge )
6056 while ( gribLen%120 ) dbuf[gribLen++] = 0;
6057 else
6058 while ( gribLen & 7 ) dbuf[gribLen++] = 0;
6059
6060 rec_len = gribLen;
6061
6062 return rec_len;
6063 }
6064
6065
gribUnzip(unsigned char * dbuf,long dbufsize,unsigned char * sbuf,long sbufsize)6066 int gribUnzip(unsigned char *dbuf, long dbufsize, unsigned char *sbuf, long sbufsize)
6067 {
6068 #if ! defined(HAVE_LIBSZ)
6069 static int libszwarn = 1;
6070 #endif
6071 unsigned char *pds = NULL, *gds = NULL, *bms = NULL, *bds = NULL;
6072 size_t gribLen = 0;
6073 size_t destLen, sourceLen;
6074 enum { bds_head = 11 };
6075 int bds_ext = 0;
6076
6077 UNUSED(dbufsize);
6078
6079 long gribrecsize;
6080 int nerr = grib1Sections(sbuf, sbufsize, &pds, &gds, &bms, &bds, &gribrecsize);
6081 if ( nerr < 0 )
6082 {
6083 fprintf(stdout, "GRIB message error\n");
6084 return 0;
6085 }
6086
6087 if ( nerr > 0 )
6088 {
6089 fprintf(stdout, "GRIB data corrupted!\n");
6090 return 0;
6091 }
6092
6093 //unsigned bds_len = BDS_Len;
6094 bool llarge = false;
6095
6096 int bds_zoffset = 12;
6097 if ( llarge ) bds_zoffset += 2;
6098
6099 int bds_nbits = BDS_NumBits;
6100 int bds_flag = BDS_Flag;
6101 int lspherc = bds_flag >> 7;
6102 int lcomplex = (bds_flag >> 6)&1;
6103 /* lcompress = (bds_flag >> 4)&1; */
6104
6105 if ( lspherc )
6106 {
6107 if ( lcomplex )
6108 {
6109 int jup = bds[bds_zoffset+15];
6110 int ioff = (jup+1)*(jup+2);
6111 bds_ext = 4 + 3 + 4*ioff;
6112 }
6113 else
6114 {
6115 bds_ext = 4;
6116 }
6117 }
6118
6119 size_t datstart = bds_head + (size_t)bds_ext;
6120
6121 unsigned char *source = bds + datstart + bds_zoffset;
6122 if ( llarge )
6123 sourceLen = ((size_t) ((bds[21]<<24)+(bds[22]<<16)+(bds[23]<<8)+bds[24]));
6124 else
6125 sourceLen = ((size_t) ((bds[20]<<16)+(bds[21]<<8)+bds[22]));
6126
6127 nerr = grib1Sections(dbuf, sbufsize, &pds, &gds, &bms, &bds, &gribrecsize);
6128 if ( nerr < 0 )
6129 {
6130 fprintf(stdout, "GRIB message error\n");
6131 return 0;
6132 }
6133
6134 if ( nerr > 0 )
6135 {
6136 fprintf(stdout, "GRIB data corrupted!\n");
6137 return 0;
6138 }
6139
6140 unsigned char *dest = bds + datstart;
6141 if ( llarge )
6142 destLen = ((size_t) ((bds[17]<<24)+(bds[18]<<16)+(bds[19]<<8)+bds[20]));
6143 else
6144 destLen = ((size_t) ((bds[17]<<16)+(bds[18]<<8)+bds[19]));
6145
6146 BDS_Flag = (unsigned char)(BDS_Flag - 16);
6147
6148 size_t bdsLen = datstart + destLen;
6149
6150 #if defined(HAVE_LIBSZ)
6151 {
6152 int bds_zstart = 14;
6153 unsigned recLen = GET_UINT3(bds[bds_zstart], bds[bds_zstart+1], bds[bds_zstart+2]);
6154
6155 int bits_per_sample = (bds_nbits == 24) ? 8 : bds_nbits;
6156
6157 SZ_com_t sz_param; /* szip parameter block */
6158 sz_param.options_mask = OPTIONS_MASK;
6159 sz_param.bits_per_pixel = bits_per_sample;
6160 sz_param.pixels_per_block = PIXELS_PER_BLOCK;
6161 sz_param.pixels_per_scanline = PIXELS_PER_SCANLINE;
6162
6163 if ( bds_ext )
6164 for ( long i = 0; i < bds_ext; ++i )
6165 bds[bds_head+i] = bds[bds_zoffset+bds_head+i];
6166
6167 /* fprintf(stderr, "gribUnzip: sourceLen %ld; destLen %ld\n", (long)sourceLen, (long)destLen);
6168 fprintf(stderr, "gribUnzip: sourceOff %d; destOff %d\n", bds[12], bds[11]);
6169 fprintf(stderr, "gribUnzip: reclen %d; bdslen %d\n", recLen, bdsLen);
6170 */
6171
6172 size_t tmpLen = destLen;
6173
6174 int status = SZ_BufftoBuffDecompress(dest, &tmpLen, source, sourceLen, &sz_param);
6175 if ( status != SZ_OK )
6176 {
6177 if ( status == SZ_NO_ENCODER_ERROR )
6178 Warning("SZ_NO_ENCODER_ERROR code %3d level %3d", PDS_Parameter, PDS_Level2);
6179 else if ( status == SZ_PARAM_ERROR )
6180 Warning("SZ_PARAM_ERROR code %3d level %3d", PDS_Parameter, PDS_Level2);
6181 else if ( status == SZ_MEM_ERROR )
6182 Warning("SZ_MEM_ERROR code %3d level %3d", PDS_Parameter, PDS_Level2);
6183 else if ( status == SZ_OUTBUFF_FULL )
6184 Warning("SZ_OUTBUFF_FULL code %3d level %3d", PDS_Parameter, PDS_Level2);
6185 else
6186 Warning("SZ ERROR: %d code %3d level %3d", status, PDS_Parameter, PDS_Level2);
6187 }
6188 /*
6189 fprintf(stderr, "gribUnzip: sl = %ld dl = %ld tl = %ld\n",
6190 (long)sourceLen, (long)destLen,(long) tmpLen);
6191 */
6192 if ( tmpLen != destLen )
6193 Warning("unzip size differ: code %3d level %3d ibuflen %ld ubuflen %ld",
6194 PDS_Parameter, PDS_Level2, (long) destLen, (long) tmpLen);
6195
6196 if ( bds_nbits == 24 )
6197 {
6198 long nelem = tmpLen/3;
6199 unsigned char *pbuf = (unsigned char*) Malloc(tmpLen);
6200 for ( long i = 0; i < nelem; i++ )
6201 {
6202 pbuf[3*i ] = dest[ i];
6203 pbuf[3*i+1] = dest[ nelem+i];
6204 pbuf[3*i+2] = dest[2*nelem+i];
6205 }
6206 memcpy(dest, pbuf, tmpLen);
6207 Free(pbuf);
6208 }
6209
6210 int bds_ubits = BDS_Flag & 15;
6211 BDS_Flag -= bds_ubits;
6212
6213 if ( (bdsLen%2) == 1 )
6214 {
6215 BDS_Flag += 8;
6216 bds[bdsLen++] = 0;
6217 }
6218
6219 SetLen3(bds, 0, bdsLen);
6220
6221 gribLen = (bds - dbuf) + bdsLen;
6222
6223 dbuf[gribLen++] = '7';
6224 dbuf[gribLen++] = '7';
6225 dbuf[gribLen++] = '7';
6226 dbuf[gribLen++] = '7';
6227
6228 if ( llarge )
6229 {
6230 long itemp;
6231 bdsLen = gribLen - 4;
6232 /*
6233 If a very large product, the section 4 length field holds
6234 the number of bytes in the product after section 4 upto
6235 the end of the padding bytes.
6236 This is a fixup to get round the restriction on product lengths
6237 due to the count being only 24 bits. It is only possible because
6238 the (default) rounding for GRIB products is 120 bytes.
6239 */
6240 while ( gribLen%120 ) dbuf[gribLen++] = 0;
6241
6242 if ( gribLen != (size_t)recLen )
6243 fprintf(stderr, "Internal problem, recLen and gribLen differ!\n");
6244
6245 itemp = gribLen / (-120);
6246 itemp = JP23SET - itemp + 1;
6247
6248 SetLen3(dbuf, 4, itemp);
6249
6250 bdsLen = gribLen - bdsLen;
6251
6252 SetLen3(bds, 0, bdsLen);
6253 }
6254 else
6255 {
6256 SetLen3(dbuf, 4, recLen);
6257 }
6258 /*
6259 fprintf(stderr, "recLen, gribLen, bdsLen %d %d %d\n", recLen, gribLen, bdsLen);
6260 */
6261 if ( llarge )
6262 while ( gribLen%120 ) dbuf[gribLen++] = 0;
6263 else
6264 while ( gribLen & 7 ) dbuf[gribLen++] = 0;
6265 /*
6266 fprintf(stderr, "recLen, gribLen, bdsLen %d %d %d\n", recLen, gribLen, bdsLen);
6267 */
6268 }
6269 #else
6270 UNUSED(bds_nbits);
6271 UNUSED(sourceLen);
6272 UNUSED(source);
6273 UNUSED(bdsLen);
6274 UNUSED(dest);
6275
6276 if ( libszwarn )
6277 {
6278 Warning("Decompression disabled, szlib not available!");
6279 libszwarn = 0;
6280 }
6281 #endif
6282
6283 return (int)gribLen;
6284 }
6285 #include <stdio.h>
6286 #include <math.h>
6287
6288
6289 static void
6290 scm0_double(double *pdl, double *pdr, double *pfl, double *pfr, int klg);
6291
6292
6293 static
rowina2(double * p,int ko,int ki,double * pw,int kcode,double msval,int * kret)6294 int rowina2(double *p, int ko, int ki, double *pw,
6295 int kcode, double msval, int *kret)
6296 {
6297 /* System generated locals */
6298 int pw_dim1, pw_offset, i_1;
6299
6300 /* Local variables */
6301 double zwt1, zrdi, zpos;
6302 int jl, ip;
6303 double zdo, zwt;
6304
6305 /* Parameter adjustments */
6306 --p;
6307 pw_dim1 = ko + 3;
6308 pw_offset = pw_dim1;
6309 pw -= pw_offset;
6310
6311 /* **** ROWINA2 - Interpolation of row of values. */
6312 /* Input Parameters. */
6313 /* ----------------- */
6314 /* P - Row of values to be interpolated. */
6315 /* Dimension must be at least KO. */
6316 /* KO - Number of values required. */
6317 /* KI - Number of values in P on input. */
6318 /* PW - Working array. */
6319 /* Dimension must be at least (0:KO+2,3). */
6320 /* KCODE - Interpolation required. */
6321 /* 1 , linear. */
6322 /* 3 , cubic. */
6323 /* PMSVAL - Value used for missing data indicator. */
6324
6325 /* Output Parameters. */
6326 /* ------------------ */
6327 /* P - Now contains KO values. */
6328 /* KRET - Return code */
6329 /* 0, OK */
6330 /* Non-zero, error */
6331
6332 /* Author. */
6333 /* ------- */
6334 /* J.D.Chambers ECMWF 22.07.94 */
6335
6336 /* ******************************** */
6337 /* Section 1. Linear interpolation .. */
6338 /* ******************************** */
6339
6340 *kret = 0;
6341
6342 if ( kcode == 1 )
6343 {
6344 /* Move input values to work array */
6345 for ( jl = 1; jl <= ki; ++jl )
6346 pw[jl + pw_dim1] = p[jl];
6347
6348 /* Arrange wrap-around value in work array */
6349 pw[ki + 1 + pw_dim1] = p[1];
6350
6351 /* Set up constants to be used to figure out weighting for */
6352 /* values in interpolation. */
6353 zrdi = (double) ki;
6354 zdo = 1.0 / (double) ko;
6355
6356 /* Loop through the output points */
6357 for ( jl = 1; jl <= ko; ++jl )
6358 {
6359
6360 /* Calculate weight from the start of row */
6361 zpos = (jl - 1) * zdo;
6362 zwt = zpos * zrdi;
6363
6364 /* Get the current array position(minus 1) from the weight - */
6365 /* note the implicit truncation. */
6366 ip = (int) zwt;
6367
6368 /* If the left value is missing, use the right value */
6369 if ( IS_EQUAL(pw[ip + 1 + pw_dim1], msval) )
6370 {
6371 p[jl] = pw[ip + 2 + pw_dim1];
6372 }
6373 /* If the right value is missing, use the left value */
6374 else if ( IS_EQUAL(pw[ip + 2 + pw_dim1], msval) )
6375 {
6376 p[jl] = pw[ip + 1 + pw_dim1];
6377 }
6378 /* If neither missing, interpolate ... */
6379 else
6380 {
6381
6382 /* Adjust the weight to range (0.0 to 1.0) */
6383 zwt -= ip;
6384
6385 /* Interpolate using the weighted values on either side */
6386 /* of the output point position */
6387 p[jl] = (1.0 - zwt) * pw[ip + 1 + pw_dim1] +
6388 zwt * pw[ip + 2 + pw_dim1];
6389 }
6390 }
6391
6392 /* ******************************* */
6393 /* Section 2. Cubic interpolation .. */
6394 /* ******************************* */
6395
6396 }
6397 else if ( kcode == 3 )
6398 {
6399 i_1 = ki;
6400 for ( jl = 1; jl <= i_1; ++jl )
6401 {
6402 if ( IS_EQUAL(p[jl], msval) )
6403 {
6404 fprintf(stderr," ROWINA2: ");
6405 fprintf(stderr," Cubic interpolation not supported");
6406 fprintf(stderr," for fields containing missing data.\n");
6407 *kret = 1;
6408 goto L900;
6409 }
6410 pw[jl + pw_dim1] = p[jl];
6411 }
6412 pw[pw_dim1] = p[ki];
6413 pw[ki + 1 + pw_dim1] = p[1];
6414 pw[ki + 2 + pw_dim1] = p[2];
6415 i_1 = ki;
6416 for ( jl = 1; jl <= i_1; ++jl )
6417 {
6418 pw[jl + (pw_dim1 << 1)] =
6419 - pw[jl - 1 + pw_dim1] / 3.0 -
6420 pw[jl + pw_dim1] * 0.5 +
6421 pw[jl + 1 + pw_dim1] - pw[jl + 2 + pw_dim1] / 6.0;
6422 pw[jl + 1 + pw_dim1 * 3] =
6423 pw[jl - 1 + pw_dim1] / 6.0 -
6424 pw[jl + pw_dim1] +
6425 pw[jl + 1 + pw_dim1] * 0.5 +
6426 pw[jl + 2 + pw_dim1] / 3.0;
6427 }
6428
6429 scm0_double(&pw[(pw_dim1 << 1) + 1], &pw[pw_dim1 * 3 + 2],
6430 &pw[pw_dim1 + 1], &pw[pw_dim1 + 2], ki);
6431
6432 zrdi = (double) ki;
6433 zdo = 1.0 / (double) ko;
6434 for ( jl = 1; jl <= ko; ++jl )
6435 {
6436 zpos = (jl - 1) * zdo;
6437 zwt = zpos * zrdi;
6438 ip = (int) zwt + 1;
6439 zwt = zwt + 1.0 - ip;
6440 zwt1 = 1.0 - zwt;
6441 p[jl] = ((3.0 - zwt1 * 2.0) * pw[ip + pw_dim1] +
6442 zwt * pw[ip + (pw_dim1 << 1)]) * zwt1 * zwt1 +
6443 ((3.0 - zwt * 2.0) * pw[ip + 1 + pw_dim1] -
6444 zwt1 * pw[ip + 1 + pw_dim1 * 3]) * zwt * zwt;
6445 }
6446
6447 }
6448 else
6449 {
6450 /* ************************************** */
6451 /* Section 3. Invalid interpolation code .. */
6452 /* ************************************** */
6453 fprintf(stderr," ROWINA2:");
6454 fprintf(stderr," Invalid interpolation code = %2d\n",kcode);
6455 *kret = 2;
6456 }
6457
6458 L900:
6459 return 0;
6460 } /* rowina2 */
6461
6462
6463
qu2reg2(double * pfield,int * kpoint,int klat,int klon,double * ztemp,double msval,int * kret)6464 int qu2reg2(double *pfield, int *kpoint, int klat, int klon,
6465 double *ztemp, double msval, int *kret)
6466 {
6467 /* System generated locals */
6468 int i_1, i_2;
6469 int kcode = 1;
6470
6471 /* Local variables */
6472 int ilii, ilio, icode;
6473 double *zline = NULL;
6474 double *zwork = NULL;
6475 int iregno, iquano, j210, j220, j230, j240, j225;
6476
6477
6478 zline = (double*) Malloc(2*(size_t)klon*sizeof(double));
6479 if ( zline == NULL ) SysError("No Memory!");
6480
6481 zwork = (double*) Malloc(3*(2*(size_t)klon+3)*sizeof(double));
6482 if ( zwork == NULL ) SysError("No Memory!");
6483
6484 /* Parameter adjustments */
6485 --pfield;
6486 --kpoint;
6487
6488 /* **** QU2REG - Convert quasi-regular grid data to regular. */
6489 /* Input Parameters. */
6490 /* ----------------- */
6491 /* PFIELD - Array containing quasi-regular grid */
6492 /* data. */
6493 /* KPOINT - Array containing list of the number of */
6494 /* points on each latitude (or longitude) of */
6495 /* the quasi-regular grid. */
6496 /* KLAT - Number of latitude lines */
6497 /* KLON - Number of longitude lines */
6498 /* KCODE - Interpolation required. */
6499 /* 1 , linear - data quasi-regular on */
6500 /* latitude lines. */
6501 /* 3 , cubic - data quasi-regular on */
6502 /* latitude lines. */
6503 /* 11, linear - data quasi-regular on */
6504 /* longitude lines. */
6505 /* 13, cubic - data quasi-regular on */
6506 /* longitude lines. */
6507 /* PMSVAL - Value used for missing data indicator. */
6508 /* Output Parameters. */
6509 /* ------------------ */
6510 /* KRET - return code */
6511 /* 0 = OK */
6512 /* non-zero indicates fatal error */
6513 /* PFIELD - Array containing regular grid data. */
6514 /* Author. */
6515 /* ------- */
6516 /* J.D.Chambers ECMWF 22.07.94 */
6517 /* J.D.Chambers ECMWF 13.09.94 */
6518 /* Add return code KRET and remove calls to ABORT. */
6519
6520
6521 /* ------------------------------ */
6522 /* Section 1. Set initial values. */
6523 /* ------------------------------ */
6524
6525 *kret = 0;
6526
6527 /* Check input parameters. */
6528
6529 if (kcode != 1 && kcode != 3 && kcode != 11 && kcode != 13) {
6530 fprintf(stderr," QU2REG :");
6531 fprintf(stderr," Invalid interpolation type code = %2d\n",kcode);
6532 *kret = 1;
6533 goto L900;
6534 }
6535
6536 /* Set array indices to 0. */
6537
6538 ilii = 0;
6539 ilio = 0;
6540
6541 /* Establish values of loop parameters. */
6542
6543 if (kcode > 10) {
6544
6545 /* Quasi-regular along longitude lines. */
6546
6547 iquano = klon;
6548 iregno = klat;
6549 icode = kcode - 10;
6550 } else {
6551
6552 /* Quasi-regular along latitude lines. */
6553
6554 iquano = klat;
6555 iregno = klon;
6556 icode = kcode;
6557 }
6558
6559 /* -------------------------------------------------------- */
6560 /** Section 2. Interpolate field from quasi to regular grid. */
6561 /* -------------------------------------------------------- */
6562
6563 i_1 = iquano;
6564 for (j230 = 1; j230 <= i_1; ++j230) {
6565
6566 if (iregno != kpoint[j230]) {
6567
6568 /* Line contains less values than required,so */
6569 /* extract quasi-regular grid values for a line */
6570
6571 i_2 = kpoint[j230];
6572 for (j210 = 1; j210 <= i_2; ++j210) {
6573 ++ilii;
6574 zline[j210 - 1] = pfield[ilii];
6575 }
6576
6577 /* and interpolate this line. */
6578
6579 rowina2(zline, iregno, kpoint[j230], zwork, icode, msval, kret);
6580 if (*kret != 0) goto L900;
6581
6582 /* Add regular grid values for this line to the
6583 temporary array. */
6584
6585 i_2 = iregno;
6586 for (j220 = 1; j220 <= i_2; ++j220) {
6587 ++ilio;
6588 ztemp[ilio - 1] = zline[j220 - 1];
6589 }
6590
6591 } else {
6592
6593 /* Line contains the required number of values, so add */
6594 /* this line to the temporary array. */
6595
6596 i_2 = iregno;
6597 for (j225 = 1; j225 <= i_2; ++j225) {
6598 ++ilio;
6599 ++ilii;
6600 ztemp[ilio - 1] = pfield[ilii];
6601 }
6602 }
6603 }
6604
6605 /* Copy temporary array to user array. */
6606
6607 i_1 = klon * klat;
6608 for (j240 = 1; j240 <= i_1; ++j240) {
6609 pfield[j240] = ztemp[j240 - 1];
6610 }
6611
6612 /* -------------------------------------------------------- */
6613 /* Section 9. Return to calling routine. Format statements. */
6614 /* -------------------------------------------------------- */
6615
6616 L900:
6617
6618 Free(zline);
6619 Free(zwork);
6620
6621 return 0;
6622 } /* qu2reg2 */
6623
6624
6625
6626 #ifdef T
6627 #undef T
6628 #endif
6629 #define T double
6630 #ifdef T
6631
6632 /* calculate_pfactor: source code from grib_api-1.8.0 */
TEMPLATE(calculate_pfactor,T)6633 double TEMPLATE(calculate_pfactor,T)(const T *spectralField, long fieldTruncation, long subsetTruncation)
6634 {
6635 /*long n_vals = ((fieldTruncation+1)*(fieldTruncation+2));*/
6636 long loop, index, m, n = 0;
6637 double zeps = 1.0e-15;
6638 long ismin = (subsetTruncation+1), ismax = (fieldTruncation+1);
6639 double weightedSumOverX = 0.0, weightedSumOverY = 0.0, sumOfWeights = 0.0;
6640 double numerator = 0.0, denominator = 0.0;
6641
6642 // Setup the weights
6643
6644 double range = (double) (ismax - ismin +1);
6645
6646 double *weights = (double*) Malloc(((size_t)ismax+1)*sizeof(double));
6647 for( loop = ismin; loop <= ismax; loop++ )
6648 weights[loop] = range / (double) (loop-ismin+1);
6649
6650 // Compute norms
6651 // Handle values 2 at a time (real and imaginary parts).
6652 double *norms = (double*) Malloc(((size_t)ismax+1)*sizeof(double));
6653
6654 for( loop = 0; loop < ismax+1; loop++ ) norms[loop] = 0.0;
6655
6656 // Form norms for the rows which contain part of the unscaled subset.
6657
6658 index = -2;
6659 for( m = 0; m < subsetTruncation; m++ )
6660 for( n = m; n <= fieldTruncation; n++ ) {
6661 index += 2;
6662 if( n >= subsetTruncation ) {
6663 double tval = spectralField[index];
6664 tval=tval<0?-tval:tval;
6665 norms[n] = norms[n] > tval ? norms[n] : tval;
6666 tval = spectralField[index+1];
6667 tval=tval<0?-tval:tval;
6668 norms[n] = norms[n] > tval ? norms[n] : tval;
6669 }
6670 }
6671
6672 // Form norms for the rows which do not contain part of the unscaled subset.
6673
6674 for( m = subsetTruncation; m <= fieldTruncation; m++ )
6675 for( n = m; n <= fieldTruncation; n++ ) {
6676 double tval = spectralField[index];
6677 index += 2;
6678 tval=tval<0?-tval:tval;
6679 norms[n] = norms[n] > tval ? norms[n] : tval;
6680 tval = spectralField[index+1];
6681 tval=tval<0?-tval:tval;
6682 norms[n] = norms[n] > tval ? norms[n] : tval;
6683 }
6684
6685 // Ensure the norms have a value which is not too small in case of problems with math functions (e.g. LOG).
6686
6687 for( loop = ismin; loop <= ismax; loop++ ) {
6688 norms[n] = norms[n] > zeps ? norms[n] : zeps;
6689 if( IS_EQUAL(norms[n], zeps) ) weights[n] = 100.0 * zeps;
6690 }
6691
6692 // Do linear fit to find the slope
6693
6694 for( loop = ismin; loop <= ismax; loop++ ) {
6695 double x = log( (double) (loop*(loop+1)) );
6696 double y = log( norms[loop] );
6697 weightedSumOverX += x * weights[loop];
6698 weightedSumOverY += y * weights[loop];
6699 sumOfWeights = sumOfWeights + weights[loop];
6700 }
6701 weightedSumOverX /= sumOfWeights;
6702 weightedSumOverY /= sumOfWeights;
6703
6704 // Perform a least square fit for the equation
6705
6706 for( loop = ismin; loop <= ismax; loop++ ) {
6707
6708 double x = log( (double)(loop*(loop+1)) );
6709 double y = log( norms[loop] );
6710 numerator += weights[loop] * (y-weightedSumOverY) * (x-weightedSumOverX);
6711 denominator += weights[loop] * ((x-weightedSumOverX) * (x-weightedSumOverX));
6712 }
6713 double slope = numerator / denominator;
6714
6715 Free(weights);
6716 Free(norms);
6717
6718 double pFactor = -slope;
6719 if( pFactor < -9999.9 ) pFactor = -9999.9;
6720 if( pFactor > 9999.9 ) pFactor = 9999.9;
6721
6722 return pFactor;
6723 }
6724
TEMPLATE(scale_complex,T)6725 void TEMPLATE(scale_complex,T)(T *fpdata, int pcStart, int pcScale, int trunc, int inv)
6726 {
6727
6728 if ( pcScale < -10000 || pcScale > 10000 )
6729 {
6730 fprintf(stderr, " %s: Invalid power given %6d\n", __func__, pcScale);
6731 return;
6732 }
6733
6734 /* Setup scaling factors = n(n+1)^^p for n = 1 to truncation */
6735
6736 if ( pcScale != 0 )
6737 {
6738 double *scale = (double*) Malloc(((size_t)trunc+1)*sizeof(double));
6739 const double power = (double) pcScale / 1000.;
6740 scale[0] = 1.0;
6741
6742 if (pcScale != 1000)
6743 for ( int n = 1; n <= trunc; n++ )
6744 scale[n] = pow((double) (n*(n+1)), power);
6745 else
6746 for ( int n = 1; n <= trunc; n++ )
6747 scale[n] = (double) (n*(n+1));
6748
6749 if ( inv )
6750 for ( int n = 1; n <= trunc; n++ ) scale[n] = 1.0 / scale[n];
6751
6752 /* Scale the values */
6753
6754 size_t index = 0;
6755
6756 for ( int m = 0; m < pcStart; m++ )
6757 for ( int n = m; n <= trunc; n++, index += 2 )
6758 if ( n >= pcStart )
6759 {
6760 fpdata[index ] = (T)(fpdata[index ] * scale[n]);
6761 fpdata[index+1] = (T)(fpdata[index+1] * scale[n]);
6762 }
6763
6764 for ( int m = pcStart; m <= trunc; m++ )
6765 for ( int n = m; n <= trunc; n++, index += 2 )
6766 {
6767 fpdata[index ] = (T)(fpdata[index ] * scale[n]);
6768 fpdata[index+1] = (T)(fpdata[index+1] * scale[n]);
6769 }
6770 Free(scale);
6771 }
6772 }
6773
6774
TEMPLATE(scatter_complex,T)6775 void TEMPLATE(scatter_complex,T)(T *fpdata, int pcStart, int trunc, int nsp)
6776 {
6777 T *fphelp = (T*) Malloc((size_t)nsp*sizeof(T));
6778 size_t inext = 0;
6779 size_t pcStart_ = pcStart >= 0 ? (size_t)pcStart : 0U;
6780 size_t trunc_ = trunc >= 0 ? (size_t)trunc : 0U;
6781 for ( size_t m = 0, index = 0; m <= pcStart_; m++ )
6782 {
6783 size_t n_copies = pcStart_ <= trunc_ ? (pcStart_ + 1 - m) * 2 : 0;
6784 for ( size_t i = 0; i < n_copies; ++i )
6785 fphelp[index + i] = fpdata[inext + i];
6786 inext += n_copies;
6787 index += m <= trunc_ ? (trunc_ - m + 1) * 2 : 0;
6788 }
6789 for ( size_t m = 0, index = 0; m <= trunc_; m++ )
6790 {
6791 size_t advIdx = m <= pcStart_ ? (pcStart_ - m + 1) * 2 : 0;
6792 index += advIdx;
6793 size_t copyStart = m > pcStart_ ? m : pcStart_ + 1;
6794 size_t n_copies = copyStart <= trunc_ ? (trunc_ - copyStart + 1) * 2 : 0;
6795 for ( size_t i = 0; i < n_copies; ++i )
6796 fphelp[index + i] = fpdata[inext + i];
6797 inext += n_copies;
6798 index += n_copies;
6799 }
6800 for ( size_t m = 0; m < (size_t)nsp; m++ ) fpdata[m] = fphelp[m];
6801
6802 Free(fphelp);
6803 }
6804
6805
TEMPLATE(gather_complex,T)6806 void TEMPLATE(gather_complex,T)(T *fpdata, size_t pcStart, size_t trunc, size_t nsp)
6807 {
6808 T *restrict fphelp = (T*) Malloc(nsp*sizeof(T));
6809 size_t inext = 0;
6810
6811 for ( size_t m = 0, index = 0; m <= pcStart; m++ )
6812 for ( size_t n = m; n <= trunc; n++ )
6813 {
6814 if ( pcStart >= n )
6815 {
6816 fphelp[inext++] = fpdata[index];
6817 fphelp[inext++] = fpdata[index+1];
6818 }
6819 index += 2;
6820 }
6821
6822 for ( size_t m = 0, index = 0; m <= trunc; m++ )
6823 for ( size_t n = m; n <= trunc; n++ )
6824 {
6825 if ( n > pcStart )
6826 {
6827 fphelp[inext++] = fpdata[index];
6828 fphelp[inext++] = fpdata[index+1];
6829 }
6830 index += 2;
6831 }
6832
6833 for ( size_t m = 0; m < nsp; m++ ) fpdata[m] = fphelp[m];
6834
6835 Free(fphelp);
6836 }
6837
6838
TEMPLATE(scm0,T)6839 static void TEMPLATE(scm0,T)(T *pdl, T *pdr, T *pfl, T *pfr, int klg)
6840 {
6841 /* **** SCM0 - Apply SCM0 limiter to derivative estimates. */
6842 /* output: */
6843 /* pdl = the limited derivative at the left edge of the interval */
6844 /* pdr = the limited derivative at the right edge of the interval */
6845 /* inputs */
6846 /* pdl = the original derivative at the left edge */
6847 /* pdr = the original derivative at the right edge */
6848 /* pfl = function value at the left edge of the interval */
6849 /* pfr = function value at the right edge of the interval */
6850 /* klg = number of intervals where the derivatives are limited */
6851
6852 /* define constants */
6853
6854 double zeps = 1.0e-12;
6855 double zfac = (1.0 - zeps) * 3.0;
6856
6857 for ( int jl = 0; jl < klg; ++jl )
6858 {
6859 double r_1;
6860 if ( (r_1 = pfr[jl] - pfl[jl], fabs(r_1)) > zeps )
6861 {
6862 double zalpha = pdl[jl] / (pfr[jl] - pfl[jl]);
6863 double zbeta = pdr[jl] / (pfr[jl] - pfl[jl]);
6864 if ( zalpha <= 0.0 ) pdl[jl] = 0.0;
6865 if ( zbeta <= 0.0 ) pdr[jl] = 0.0;
6866 if ( zalpha > zfac ) pdl[jl] = (T)(zfac * (pfr[jl] - pfl[jl]));
6867 if ( zbeta > zfac ) pdr[jl] = (T)(zfac * (pfr[jl] - pfl[jl]));
6868 }
6869 else
6870 {
6871 pdl[jl] = 0.0;
6872 pdr[jl] = 0.0;
6873 }
6874 }
6875 } /* scm0 */
6876
6877 static
TEMPLATE(rowina3,T)6878 int TEMPLATE(rowina3,T)(T *p, int ko, int ki, T *pw,
6879 int kcode, T msval, int *kret, int omisng, int operio, int oveggy)
6880 {
6881 /*
6882 C---->
6883 C**** ROWINA3 - Interpolation of row of values.
6884 C
6885 C Purpose.
6886 C --------
6887 C
6888 C Interpolate a row of values.
6889 C
6890 C
6891 C** Interface.
6892 C ----------
6893 C
6894 C CALL ROWINA3( P, KO, KI, PW, KCODE, PMSVAL, KRET, OMISNG, OPERIO)
6895 C
6896 C
6897 C Input Parameters.
6898 C -----------------
6899 C
6900 C P - Row of values to be interpolated.
6901 C Dimension must be at least KO.
6902 C
6903 C KO - Number of values required.
6904 C
6905 C KI - Number of values in P on input.
6906 C
6907 C PW - Working array.
6908 C Dimension must be at least (0:KO+2,3).
6909 C
6910 C KCODE - Interpolation required.
6911 C 1 , linear.
6912 C 3 , cubic.
6913 C
6914 C PMSVAL - Value used for missing data indicator.
6915 C
6916 C OMISNG - True if missing values are present in field.
6917 C
6918 C OPERIO - True if input field is periodic.
6919 C
6920 C OVEGGY - True if 'nearest neighbour' processing must be used
6921 C for interpolation
6922 C
6923 C Output Parameters.
6924 C ------------------
6925 C
6926 C P - Now contains KO values.
6927 C KRET - Return code
6928 C 0, OK
6929 C Non-zero, error
6930 C
6931 C
6932 C Method.
6933 C -------
6934 C
6935 C Linear or cubic interpolation performed as required.
6936 C
6937 C Comments.
6938 C ---------
6939 C
6940 C This is a version of ROWINA which allows for missing data
6941 C values and hence for bitmapped fields.
6942 C
6943 C
6944 C Author.
6945 C -------
6946 C
6947 C J.D.Chambers ECMWF 22.07.94
6948 C
6949 C
6950 C Modifications.
6951 C --------------
6952 C
6953 C J.D.Chambers ECMWF 13.09.94
6954 C Add return code KRET and remove calls to ABORT.
6955 C
6956 C J. Clochard, Meteo France, for ECMWF - January 1998.
6957 C Addition of OMISNG and OPERIO arguments.
6958 C
6959 C
6960 C -----------------------------------------------------------------
6961 */
6962 /* System generated locals */
6963 int pw_dim1, pw_offset, i_1;
6964
6965 /* Local variables */
6966 int jl, ip;
6967 double zwt1, zrdi, zpos;
6968 double zdo, zwt;
6969
6970 UNUSED(omisng);
6971
6972 /* Parameter adjustments */
6973 --p;
6974 pw_dim1 = ko + 3;
6975 pw_offset = pw_dim1;
6976 pw -= pw_offset;
6977
6978 *kret = 0;
6979
6980 if ( kcode == 1 )
6981 {
6982 /* Move input values to work array */
6983 for ( jl = 1; jl <= ki; ++jl )
6984 pw[jl + pw_dim1] = p[jl];
6985
6986 if ( operio )
6987 {
6988 /* Arrange wrap-around value in work array */
6989 pw[ki + 1 + pw_dim1] = p[1];
6990
6991 /* Set up constants to be used to figure out weighting for */
6992 /* values in interpolation. */
6993 zrdi = (double) ki;
6994 zdo = 1.0 / (double) ko;
6995 }
6996 else
6997 {
6998 /* Repeat last value, to cope with "implicit truncation" below */
6999 pw[ki + 1 + pw_dim1] = p[ki];
7000
7001 /* Set up constants to be used to figure out weighting for */
7002 /* values in interpolation. */
7003 zrdi = (double) (ki-1);
7004 zdo = 1.0 / (double) (ko-1);
7005 }
7006
7007 /* Loop through the output points */
7008 for ( jl = 1; jl <= ko; ++jl )
7009 {
7010
7011 /* Calculate weight from the start of row */
7012 zpos = (jl - 1) * zdo;
7013 zwt = zpos * zrdi;
7014
7015 /* Get the current array position(minus 1) from the weight - */
7016 /* note the implicit truncation. */
7017 ip = (int) zwt;
7018
7019 /* Adjust the weight to range (0.0 to 1.0) */
7020 zwt -= ip;
7021
7022 /* If 'nearest neighbour' processing must be used */
7023 if ( oveggy )
7024 {
7025 if ( zwt < 0.5 )
7026 p[jl] = pw[ip + 1 + pw_dim1];
7027 else
7028 p[jl] = pw[ip + 2 + pw_dim1];
7029 }
7030 else
7031 {
7032 /* If the left value is missing, use the right value */
7033 if ( IS_EQUAL(pw[ip + 1 + pw_dim1], msval) )
7034 {
7035 p[jl] = pw[ip + 2 + pw_dim1];
7036 }
7037 /* If the right value is missing, use the left value */
7038 else if ( IS_EQUAL(pw[ip + 2 + pw_dim1], msval) )
7039 {
7040 p[jl] = pw[ip + 1 + pw_dim1];
7041 }
7042 /* If neither missing, interpolate ... */
7043 else
7044 {
7045 /* Interpolate using the weighted values on either side */
7046 /* of the output point position */
7047 p[jl] = (T)((1.0 - zwt) * pw[ip+1 + pw_dim1]
7048 + zwt * pw[ip+2 + pw_dim1]);
7049 }
7050 }
7051 }
7052 }
7053 else if ( kcode == 3 )
7054 {
7055 /* ******************************* */
7056 /* Section 2. Cubic interpolation .. */
7057 /* ******************************* */
7058 i_1 = ki;
7059 for ( jl = 1; jl <= i_1; ++jl )
7060 {
7061 if ( IS_EQUAL(p[jl], msval) )
7062 {
7063 fprintf(stderr," ROWINA3: ");
7064 fprintf(stderr," Cubic interpolation not supported");
7065 fprintf(stderr," for fields containing missing data.\n");
7066 *kret = 1;
7067 goto L900;
7068 }
7069 pw[jl + pw_dim1] = p[jl];
7070 }
7071 pw[pw_dim1] = p[ki];
7072 pw[ki + 1 + pw_dim1] = p[1];
7073 pw[ki + 2 + pw_dim1] = p[2];
7074 i_1 = ki;
7075 for ( jl = 1; jl <= i_1; ++jl )
7076 {
7077 pw[jl + (pw_dim1 << 1)] =
7078 (T)(- pw[jl - 1 + pw_dim1] / 3.0 -
7079 pw[jl + pw_dim1] * 0.5 +
7080 pw[jl + 1 + pw_dim1] - pw[jl + 2 + pw_dim1] / 6.0);
7081 pw[jl + 1 + pw_dim1 * 3] =
7082 (T)(pw[jl - 1 + pw_dim1] / 6.0 -
7083 pw[jl + pw_dim1] +
7084 pw[jl + 1 + pw_dim1] * 0.5 +
7085 pw[jl + 2 + pw_dim1] / 3.0);
7086 }
7087
7088 TEMPLATE(scm0,T)(&pw[(pw_dim1 << 1) + 1], &pw[pw_dim1 * 3 + 2],
7089 &pw[pw_dim1 + 1], &pw[pw_dim1 + 2], ki);
7090
7091 zrdi = (double) ki;
7092 zdo = 1.0 / (double) ko;
7093 for ( jl = 1; jl <= ko; ++jl )
7094 {
7095 zpos = (jl - 1) * zdo;
7096 zwt = zpos * zrdi;
7097 ip = (int) zwt + 1;
7098 zwt = zwt + 1.0 - ip;
7099 zwt1 = 1.0 - zwt;
7100 p[jl] = (T)(((3.0 - zwt1 * 2.0) * pw[ip + pw_dim1] +
7101 zwt * pw[ip + (pw_dim1 << 1)]) * zwt1 * zwt1 +
7102 ((3.0 - zwt * 2.0) * pw[ip + 1 + pw_dim1] -
7103 zwt1 * pw[ip + 1 + pw_dim1 * 3]) * zwt * zwt);
7104 }
7105
7106 }
7107 else
7108 {
7109 /* ************************************** */
7110 /* Section 3. Invalid interpolation code .. */
7111 /* ************************************** */
7112 fprintf(stderr," ROWINA3:");
7113 fprintf(stderr," Invalid interpolation code = %2d\n",kcode);
7114 *kret = 2;
7115 }
7116
7117 L900:
7118 return 0;
7119 } /* rowina3 */
7120
7121
TEMPLATE(qu2reg3,T)7122 int TEMPLATE(qu2reg3,T)(T *pfield, int *kpoint, int klat, int klon,
7123 T msval, int *kret, int omisng, int operio, int oveggy)
7124 {
7125 /*
7126 C**** QU2REG3 - Convert quasi-regular grid data to regular.
7127 C
7128 C Purpose.
7129 C --------
7130 C
7131 C Convert quasi-regular grid data to regular,
7132 C using either a linear or cubic interpolation.
7133 C
7134 C
7135 C** Interface.
7136 C ----------
7137 C
7138 C CALL QU2REG3(PFIELD,KPOINT,KLAT,KLON,KCODE,PMSVAL,OMISNG,OPERIO,
7139 C X OVEGGY)
7140 C
7141 C
7142 C Input Parameters.
7143 C -----------------
7144 C
7145 C PFIELD - Array containing quasi-regular grid data.
7146 C
7147 C KPOINT - Array containing list of the number of
7148 C points on each latitude (or longitude) of
7149 C the quasi-regular grid.
7150 C
7151 C KLAT - Number of latitude lines
7152 C
7153 C KLON - Number of longitude lines
7154 C
7155 C KCODE - Interpolation required.
7156 C 1 , linear - data quasi-regular on latitude lines.
7157 C 3 , cubic - data quasi-regular on latitude lines.
7158 C 11, linear - data quasi-regular on longitude lines.
7159 C 13, cubic - data quasi-regular on longitude lines.
7160 C
7161 C PMSVAL - Value used for missing data indicator.
7162 C
7163 C OMISNG - True if missing values are present in field.
7164 C
7165 C OPERIO - True if input field is periodic.
7166 C
7167 C OVEGGY - True if 'nearest neighbour' processing must be used
7168 C for interpolation
7169 C
7170 C
7171 C Output Parameters.
7172 C ------------------
7173 C
7174 C KRET - return code
7175 C 0 = OK
7176 C non-zero indicates fatal error
7177 C
7178 C
7179 C Output Parameters.
7180 C ------------------
7181 C
7182 C PFIELD - Array containing regular grid data.
7183 C
7184 C
7185 C Method.
7186 C -------
7187 C
7188 C Data is interpolated and expanded into a temporary array,
7189 C which is then copied back into the user's array.
7190 C Returns an error code if an invalid interpolation is requested
7191 C or field size exceeds array dimensions.
7192 C
7193 C Comments.
7194 C ---------
7195 C
7196 C This routine is an adaptation of QU2REG to allow missing data
7197 C values, and hence bit mapped fields.
7198 C
7199 C
7200 C Author.
7201 C -------
7202 C
7203 C J.D.Chambers ECMWF 22.07.94
7204 C
7205 C
7206 C Modifications.
7207 C --------------
7208 C
7209 C J.D.Chambers ECMWF 13.09.94
7210 C Add return code KRET and remove calls to ABORT.
7211 C
7212 C J.D.Chambers ECMWF Feb 1997
7213 C Allow for 64-bit pointers
7214 C
7215 C J. Clochard, Meteo France, for ECMWF - January 1998.
7216 C Addition of OMISNG and OPERIO arguments.
7217 C Fix message for longitude number out of bounds, and routine
7218 C name in title and formats.
7219 C
7220 */
7221 /* System generated locals */
7222 int i_1, i_2;
7223 int kcode = 1;
7224
7225 /* Local variables */
7226 int ilii, ilio, icode;
7227 int iregno, iquano, j210, j220, j230, j240, j225;
7228
7229 T *ztemp = (T*) Malloc((size_t)klon*(size_t)klat*sizeof(T));
7230 T *zline = (T*) Malloc(2*(size_t)klon*sizeof(T));
7231 T *zwork = (T*) Malloc(3*(2*(size_t)klon+3)*sizeof(T));
7232
7233 /* Parameter adjustments */
7234 --pfield;
7235 --kpoint;
7236
7237 /* ------------------------------ */
7238 /* Section 1. Set initial values. */
7239 /* ------------------------------ */
7240
7241 *kret = 0;
7242
7243 /* Check input parameters. */
7244
7245 if (kcode != 1 && kcode != 3 && kcode != 11 && kcode != 13) {
7246 fprintf(stderr," QU2REG :");
7247 fprintf(stderr," Invalid interpolation type code = %2d\n",kcode);
7248 *kret = 1;
7249 goto L900;
7250 }
7251
7252 /* Set array indices to 0. */
7253
7254 ilii = 0;
7255 ilio = 0;
7256
7257 /* Establish values of loop parameters. */
7258
7259 if (kcode > 10) {
7260
7261 /* Quasi-regular along longitude lines. */
7262
7263 iquano = klon;
7264 iregno = klat;
7265 icode = kcode - 10;
7266 } else {
7267
7268 /* Quasi-regular along latitude lines. */
7269
7270 iquano = klat;
7271 iregno = klon;
7272 icode = kcode;
7273 }
7274
7275 /* -------------------------------------------------------- */
7276 /** Section 2. Interpolate field from quasi to regular grid. */
7277 /* -------------------------------------------------------- */
7278
7279 i_1 = iquano;
7280 for (j230 = 1; j230 <= i_1; ++j230) {
7281
7282 if (iregno != kpoint[j230]) {
7283
7284 /* Line contains less values than required,so */
7285 /* extract quasi-regular grid values for a line */
7286
7287 i_2 = kpoint[j230];
7288 for (j210 = 1; j210 <= i_2; ++j210) {
7289 ++ilii;
7290 zline[j210 - 1] = pfield[ilii];
7291 }
7292
7293 /* and interpolate this line. */
7294
7295 TEMPLATE(rowina3,T)(zline, iregno, kpoint[j230], zwork, icode, msval, kret, omisng, operio , oveggy);
7296 if (*kret != 0) goto L900;
7297
7298 /* Add regular grid values for this line to the
7299 temporary array. */
7300
7301 i_2 = iregno;
7302 for (j220 = 1; j220 <= i_2; ++j220) {
7303 ++ilio;
7304 ztemp[ilio - 1] = zline[j220 - 1];
7305 }
7306
7307 } else {
7308
7309 /* Line contains the required number of values, so add */
7310 /* this line to the temporary array. */
7311
7312 i_2 = iregno;
7313 for (j225 = 1; j225 <= i_2; ++j225) {
7314 ++ilio;
7315 ++ilii;
7316 ztemp[ilio - 1] = pfield[ilii];
7317 }
7318 }
7319 }
7320
7321 /* Copy temporary array to user array. */
7322
7323 i_1 = klon * klat;
7324 for (j240 = 1; j240 <= i_1; ++j240) {
7325 pfield[j240] = ztemp[j240 - 1];
7326 }
7327
7328 /* -------------------------------------------------------- */
7329 /* Section 9. Return to calling routine. Format statements. */
7330 /* -------------------------------------------------------- */
7331
7332 L900:
7333
7334 Free(zwork);
7335 Free(zline);
7336 Free(ztemp);
7337
7338 return 0;
7339 } /* qu2reg3 */
7340
7341 #endif /* T */
7342
7343 /*
7344 * Local Variables:
7345 * mode: c
7346 * c-file-style: "Java"
7347 * c-basic-offset: 2
7348 * indent-tabs-mode: nil
7349 * show-trailing-whitespace: t
7350 * require-trailing-newline: t
7351 * End:
7352 */
7353
7354 #ifdef T
7355 #undef T
7356 #endif
7357 #define T float
7358 #ifdef T
7359
7360 /* calculate_pfactor: source code from grib_api-1.8.0 */
TEMPLATE(calculate_pfactor,T)7361 double TEMPLATE(calculate_pfactor,T)(const T *spectralField, long fieldTruncation, long subsetTruncation)
7362 {
7363 /*long n_vals = ((fieldTruncation+1)*(fieldTruncation+2));*/
7364 long loop, index, m, n = 0;
7365 double zeps = 1.0e-15;
7366 long ismin = (subsetTruncation+1), ismax = (fieldTruncation+1);
7367 double weightedSumOverX = 0.0, weightedSumOverY = 0.0, sumOfWeights = 0.0;
7368 double numerator = 0.0, denominator = 0.0;
7369
7370 // Setup the weights
7371
7372 double range = (double) (ismax - ismin +1);
7373
7374 double *weights = (double*) Malloc(((size_t)ismax+1)*sizeof(double));
7375 for( loop = ismin; loop <= ismax; loop++ )
7376 weights[loop] = range / (double) (loop-ismin+1);
7377
7378 // Compute norms
7379 // Handle values 2 at a time (real and imaginary parts).
7380 double *norms = (double*) Malloc(((size_t)ismax+1)*sizeof(double));
7381
7382 for( loop = 0; loop < ismax+1; loop++ ) norms[loop] = 0.0;
7383
7384 // Form norms for the rows which contain part of the unscaled subset.
7385
7386 index = -2;
7387 for( m = 0; m < subsetTruncation; m++ )
7388 for( n = m; n <= fieldTruncation; n++ ) {
7389 index += 2;
7390 if( n >= subsetTruncation ) {
7391 double tval = spectralField[index];
7392 tval=tval<0?-tval:tval;
7393 norms[n] = norms[n] > tval ? norms[n] : tval;
7394 tval = spectralField[index+1];
7395 tval=tval<0?-tval:tval;
7396 norms[n] = norms[n] > tval ? norms[n] : tval;
7397 }
7398 }
7399
7400 // Form norms for the rows which do not contain part of the unscaled subset.
7401
7402 for( m = subsetTruncation; m <= fieldTruncation; m++ )
7403 for( n = m; n <= fieldTruncation; n++ ) {
7404 double tval = spectralField[index];
7405 index += 2;
7406 tval=tval<0?-tval:tval;
7407 norms[n] = norms[n] > tval ? norms[n] : tval;
7408 tval = spectralField[index+1];
7409 tval=tval<0?-tval:tval;
7410 norms[n] = norms[n] > tval ? norms[n] : tval;
7411 }
7412
7413 // Ensure the norms have a value which is not too small in case of problems with math functions (e.g. LOG).
7414
7415 for( loop = ismin; loop <= ismax; loop++ ) {
7416 norms[n] = norms[n] > zeps ? norms[n] : zeps;
7417 if( IS_EQUAL(norms[n], zeps) ) weights[n] = 100.0 * zeps;
7418 }
7419
7420 // Do linear fit to find the slope
7421
7422 for( loop = ismin; loop <= ismax; loop++ ) {
7423 double x = log( (double) (loop*(loop+1)) );
7424 double y = log( norms[loop] );
7425 weightedSumOverX += x * weights[loop];
7426 weightedSumOverY += y * weights[loop];
7427 sumOfWeights = sumOfWeights + weights[loop];
7428 }
7429 weightedSumOverX /= sumOfWeights;
7430 weightedSumOverY /= sumOfWeights;
7431
7432 // Perform a least square fit for the equation
7433
7434 for( loop = ismin; loop <= ismax; loop++ ) {
7435
7436 double x = log( (double)(loop*(loop+1)) );
7437 double y = log( norms[loop] );
7438 numerator += weights[loop] * (y-weightedSumOverY) * (x-weightedSumOverX);
7439 denominator += weights[loop] * ((x-weightedSumOverX) * (x-weightedSumOverX));
7440 }
7441 double slope = numerator / denominator;
7442
7443 Free(weights);
7444 Free(norms);
7445
7446 double pFactor = -slope;
7447 if( pFactor < -9999.9 ) pFactor = -9999.9;
7448 if( pFactor > 9999.9 ) pFactor = 9999.9;
7449
7450 return pFactor;
7451 }
7452
TEMPLATE(scale_complex,T)7453 void TEMPLATE(scale_complex,T)(T *fpdata, int pcStart, int pcScale, int trunc, int inv)
7454 {
7455
7456 if ( pcScale < -10000 || pcScale > 10000 )
7457 {
7458 fprintf(stderr, " %s: Invalid power given %6d\n", __func__, pcScale);
7459 return;
7460 }
7461
7462 /* Setup scaling factors = n(n+1)^^p for n = 1 to truncation */
7463
7464 if ( pcScale != 0 )
7465 {
7466 double *scale = (double*) Malloc(((size_t)trunc+1)*sizeof(double));
7467 const double power = (double) pcScale / 1000.;
7468 scale[0] = 1.0;
7469
7470 if (pcScale != 1000)
7471 for ( int n = 1; n <= trunc; n++ )
7472 scale[n] = pow((double) (n*(n+1)), power);
7473 else
7474 for ( int n = 1; n <= trunc; n++ )
7475 scale[n] = (double) (n*(n+1));
7476
7477 if ( inv )
7478 for ( int n = 1; n <= trunc; n++ ) scale[n] = 1.0 / scale[n];
7479
7480 /* Scale the values */
7481
7482 size_t index = 0;
7483
7484 for ( int m = 0; m < pcStart; m++ )
7485 for ( int n = m; n <= trunc; n++, index += 2 )
7486 if ( n >= pcStart )
7487 {
7488 fpdata[index ] = (T)(fpdata[index ] * scale[n]);
7489 fpdata[index+1] = (T)(fpdata[index+1] * scale[n]);
7490 }
7491
7492 for ( int m = pcStart; m <= trunc; m++ )
7493 for ( int n = m; n <= trunc; n++, index += 2 )
7494 {
7495 fpdata[index ] = (T)(fpdata[index ] * scale[n]);
7496 fpdata[index+1] = (T)(fpdata[index+1] * scale[n]);
7497 }
7498 Free(scale);
7499 }
7500 }
7501
7502
TEMPLATE(scatter_complex,T)7503 void TEMPLATE(scatter_complex,T)(T *fpdata, int pcStart, int trunc, int nsp)
7504 {
7505 T *fphelp = (T*) Malloc((size_t)nsp*sizeof(T));
7506 size_t inext = 0;
7507 size_t pcStart_ = pcStart >= 0 ? (size_t)pcStart : 0U;
7508 size_t trunc_ = trunc >= 0 ? (size_t)trunc : 0U;
7509 for ( size_t m = 0, index = 0; m <= pcStart_; m++ )
7510 {
7511 size_t n_copies = pcStart_ <= trunc_ ? (pcStart_ + 1 - m) * 2 : 0;
7512 for ( size_t i = 0; i < n_copies; ++i )
7513 fphelp[index + i] = fpdata[inext + i];
7514 inext += n_copies;
7515 index += m <= trunc_ ? (trunc_ - m + 1) * 2 : 0;
7516 }
7517 for ( size_t m = 0, index = 0; m <= trunc_; m++ )
7518 {
7519 size_t advIdx = m <= pcStart_ ? (pcStart_ - m + 1) * 2 : 0;
7520 index += advIdx;
7521 size_t copyStart = m > pcStart_ ? m : pcStart_ + 1;
7522 size_t n_copies = copyStart <= trunc_ ? (trunc_ - copyStart + 1) * 2 : 0;
7523 for ( size_t i = 0; i < n_copies; ++i )
7524 fphelp[index + i] = fpdata[inext + i];
7525 inext += n_copies;
7526 index += n_copies;
7527 }
7528 for ( size_t m = 0; m < (size_t)nsp; m++ ) fpdata[m] = fphelp[m];
7529
7530 Free(fphelp);
7531 }
7532
7533
TEMPLATE(gather_complex,T)7534 void TEMPLATE(gather_complex,T)(T *fpdata, size_t pcStart, size_t trunc, size_t nsp)
7535 {
7536 T *restrict fphelp = (T*) Malloc(nsp*sizeof(T));
7537 size_t inext = 0;
7538
7539 for ( size_t m = 0, index = 0; m <= pcStart; m++ )
7540 for ( size_t n = m; n <= trunc; n++ )
7541 {
7542 if ( pcStart >= n )
7543 {
7544 fphelp[inext++] = fpdata[index];
7545 fphelp[inext++] = fpdata[index+1];
7546 }
7547 index += 2;
7548 }
7549
7550 for ( size_t m = 0, index = 0; m <= trunc; m++ )
7551 for ( size_t n = m; n <= trunc; n++ )
7552 {
7553 if ( n > pcStart )
7554 {
7555 fphelp[inext++] = fpdata[index];
7556 fphelp[inext++] = fpdata[index+1];
7557 }
7558 index += 2;
7559 }
7560
7561 for ( size_t m = 0; m < nsp; m++ ) fpdata[m] = fphelp[m];
7562
7563 Free(fphelp);
7564 }
7565
7566
TEMPLATE(scm0,T)7567 static void TEMPLATE(scm0,T)(T *pdl, T *pdr, T *pfl, T *pfr, int klg)
7568 {
7569 /* **** SCM0 - Apply SCM0 limiter to derivative estimates. */
7570 /* output: */
7571 /* pdl = the limited derivative at the left edge of the interval */
7572 /* pdr = the limited derivative at the right edge of the interval */
7573 /* inputs */
7574 /* pdl = the original derivative at the left edge */
7575 /* pdr = the original derivative at the right edge */
7576 /* pfl = function value at the left edge of the interval */
7577 /* pfr = function value at the right edge of the interval */
7578 /* klg = number of intervals where the derivatives are limited */
7579
7580 /* define constants */
7581
7582 double zeps = 1.0e-12;
7583 double zfac = (1.0 - zeps) * 3.0;
7584
7585 for ( int jl = 0; jl < klg; ++jl )
7586 {
7587 double r_1;
7588 if ( (r_1 = pfr[jl] - pfl[jl], fabs(r_1)) > zeps )
7589 {
7590 double zalpha = pdl[jl] / (pfr[jl] - pfl[jl]);
7591 double zbeta = pdr[jl] / (pfr[jl] - pfl[jl]);
7592 if ( zalpha <= 0.0 ) pdl[jl] = 0.0;
7593 if ( zbeta <= 0.0 ) pdr[jl] = 0.0;
7594 if ( zalpha > zfac ) pdl[jl] = (T)(zfac * (pfr[jl] - pfl[jl]));
7595 if ( zbeta > zfac ) pdr[jl] = (T)(zfac * (pfr[jl] - pfl[jl]));
7596 }
7597 else
7598 {
7599 pdl[jl] = 0.0;
7600 pdr[jl] = 0.0;
7601 }
7602 }
7603 } /* scm0 */
7604
7605 static
TEMPLATE(rowina3,T)7606 int TEMPLATE(rowina3,T)(T *p, int ko, int ki, T *pw,
7607 int kcode, T msval, int *kret, int omisng, int operio, int oveggy)
7608 {
7609 /*
7610 C---->
7611 C**** ROWINA3 - Interpolation of row of values.
7612 C
7613 C Purpose.
7614 C --------
7615 C
7616 C Interpolate a row of values.
7617 C
7618 C
7619 C** Interface.
7620 C ----------
7621 C
7622 C CALL ROWINA3( P, KO, KI, PW, KCODE, PMSVAL, KRET, OMISNG, OPERIO)
7623 C
7624 C
7625 C Input Parameters.
7626 C -----------------
7627 C
7628 C P - Row of values to be interpolated.
7629 C Dimension must be at least KO.
7630 C
7631 C KO - Number of values required.
7632 C
7633 C KI - Number of values in P on input.
7634 C
7635 C PW - Working array.
7636 C Dimension must be at least (0:KO+2,3).
7637 C
7638 C KCODE - Interpolation required.
7639 C 1 , linear.
7640 C 3 , cubic.
7641 C
7642 C PMSVAL - Value used for missing data indicator.
7643 C
7644 C OMISNG - True if missing values are present in field.
7645 C
7646 C OPERIO - True if input field is periodic.
7647 C
7648 C OVEGGY - True if 'nearest neighbour' processing must be used
7649 C for interpolation
7650 C
7651 C Output Parameters.
7652 C ------------------
7653 C
7654 C P - Now contains KO values.
7655 C KRET - Return code
7656 C 0, OK
7657 C Non-zero, error
7658 C
7659 C
7660 C Method.
7661 C -------
7662 C
7663 C Linear or cubic interpolation performed as required.
7664 C
7665 C Comments.
7666 C ---------
7667 C
7668 C This is a version of ROWINA which allows for missing data
7669 C values and hence for bitmapped fields.
7670 C
7671 C
7672 C Author.
7673 C -------
7674 C
7675 C J.D.Chambers ECMWF 22.07.94
7676 C
7677 C
7678 C Modifications.
7679 C --------------
7680 C
7681 C J.D.Chambers ECMWF 13.09.94
7682 C Add return code KRET and remove calls to ABORT.
7683 C
7684 C J. Clochard, Meteo France, for ECMWF - January 1998.
7685 C Addition of OMISNG and OPERIO arguments.
7686 C
7687 C
7688 C -----------------------------------------------------------------
7689 */
7690 /* System generated locals */
7691 int pw_dim1, pw_offset, i_1;
7692
7693 /* Local variables */
7694 int jl, ip;
7695 double zwt1, zrdi, zpos;
7696 double zdo, zwt;
7697
7698 UNUSED(omisng);
7699
7700 /* Parameter adjustments */
7701 --p;
7702 pw_dim1 = ko + 3;
7703 pw_offset = pw_dim1;
7704 pw -= pw_offset;
7705
7706 *kret = 0;
7707
7708 if ( kcode == 1 )
7709 {
7710 /* Move input values to work array */
7711 for ( jl = 1; jl <= ki; ++jl )
7712 pw[jl + pw_dim1] = p[jl];
7713
7714 if ( operio )
7715 {
7716 /* Arrange wrap-around value in work array */
7717 pw[ki + 1 + pw_dim1] = p[1];
7718
7719 /* Set up constants to be used to figure out weighting for */
7720 /* values in interpolation. */
7721 zrdi = (double) ki;
7722 zdo = 1.0 / (double) ko;
7723 }
7724 else
7725 {
7726 /* Repeat last value, to cope with "implicit truncation" below */
7727 pw[ki + 1 + pw_dim1] = p[ki];
7728
7729 /* Set up constants to be used to figure out weighting for */
7730 /* values in interpolation. */
7731 zrdi = (double) (ki-1);
7732 zdo = 1.0 / (double) (ko-1);
7733 }
7734
7735 /* Loop through the output points */
7736 for ( jl = 1; jl <= ko; ++jl )
7737 {
7738
7739 /* Calculate weight from the start of row */
7740 zpos = (jl - 1) * zdo;
7741 zwt = zpos * zrdi;
7742
7743 /* Get the current array position(minus 1) from the weight - */
7744 /* note the implicit truncation. */
7745 ip = (int) zwt;
7746
7747 /* Adjust the weight to range (0.0 to 1.0) */
7748 zwt -= ip;
7749
7750 /* If 'nearest neighbour' processing must be used */
7751 if ( oveggy )
7752 {
7753 if ( zwt < 0.5 )
7754 p[jl] = pw[ip + 1 + pw_dim1];
7755 else
7756 p[jl] = pw[ip + 2 + pw_dim1];
7757 }
7758 else
7759 {
7760 /* If the left value is missing, use the right value */
7761 if ( IS_EQUAL(pw[ip + 1 + pw_dim1], msval) )
7762 {
7763 p[jl] = pw[ip + 2 + pw_dim1];
7764 }
7765 /* If the right value is missing, use the left value */
7766 else if ( IS_EQUAL(pw[ip + 2 + pw_dim1], msval) )
7767 {
7768 p[jl] = pw[ip + 1 + pw_dim1];
7769 }
7770 /* If neither missing, interpolate ... */
7771 else
7772 {
7773 /* Interpolate using the weighted values on either side */
7774 /* of the output point position */
7775 p[jl] = (T)((1.0 - zwt) * pw[ip+1 + pw_dim1]
7776 + zwt * pw[ip+2 + pw_dim1]);
7777 }
7778 }
7779 }
7780 }
7781 else if ( kcode == 3 )
7782 {
7783 /* ******************************* */
7784 /* Section 2. Cubic interpolation .. */
7785 /* ******************************* */
7786 i_1 = ki;
7787 for ( jl = 1; jl <= i_1; ++jl )
7788 {
7789 if ( IS_EQUAL(p[jl], msval) )
7790 {
7791 fprintf(stderr," ROWINA3: ");
7792 fprintf(stderr," Cubic interpolation not supported");
7793 fprintf(stderr," for fields containing missing data.\n");
7794 *kret = 1;
7795 goto L900;
7796 }
7797 pw[jl + pw_dim1] = p[jl];
7798 }
7799 pw[pw_dim1] = p[ki];
7800 pw[ki + 1 + pw_dim1] = p[1];
7801 pw[ki + 2 + pw_dim1] = p[2];
7802 i_1 = ki;
7803 for ( jl = 1; jl <= i_1; ++jl )
7804 {
7805 pw[jl + (pw_dim1 << 1)] =
7806 (T)(- pw[jl - 1 + pw_dim1] / 3.0 -
7807 pw[jl + pw_dim1] * 0.5 +
7808 pw[jl + 1 + pw_dim1] - pw[jl + 2 + pw_dim1] / 6.0);
7809 pw[jl + 1 + pw_dim1 * 3] =
7810 (T)(pw[jl - 1 + pw_dim1] / 6.0 -
7811 pw[jl + pw_dim1] +
7812 pw[jl + 1 + pw_dim1] * 0.5 +
7813 pw[jl + 2 + pw_dim1] / 3.0);
7814 }
7815
7816 TEMPLATE(scm0,T)(&pw[(pw_dim1 << 1) + 1], &pw[pw_dim1 * 3 + 2],
7817 &pw[pw_dim1 + 1], &pw[pw_dim1 + 2], ki);
7818
7819 zrdi = (double) ki;
7820 zdo = 1.0 / (double) ko;
7821 for ( jl = 1; jl <= ko; ++jl )
7822 {
7823 zpos = (jl - 1) * zdo;
7824 zwt = zpos * zrdi;
7825 ip = (int) zwt + 1;
7826 zwt = zwt + 1.0 - ip;
7827 zwt1 = 1.0 - zwt;
7828 p[jl] = (T)(((3.0 - zwt1 * 2.0) * pw[ip + pw_dim1] +
7829 zwt * pw[ip + (pw_dim1 << 1)]) * zwt1 * zwt1 +
7830 ((3.0 - zwt * 2.0) * pw[ip + 1 + pw_dim1] -
7831 zwt1 * pw[ip + 1 + pw_dim1 * 3]) * zwt * zwt);
7832 }
7833
7834 }
7835 else
7836 {
7837 /* ************************************** */
7838 /* Section 3. Invalid interpolation code .. */
7839 /* ************************************** */
7840 fprintf(stderr," ROWINA3:");
7841 fprintf(stderr," Invalid interpolation code = %2d\n",kcode);
7842 *kret = 2;
7843 }
7844
7845 L900:
7846 return 0;
7847 } /* rowina3 */
7848
7849
TEMPLATE(qu2reg3,T)7850 int TEMPLATE(qu2reg3,T)(T *pfield, int *kpoint, int klat, int klon,
7851 T msval, int *kret, int omisng, int operio, int oveggy)
7852 {
7853 /*
7854 C**** QU2REG3 - Convert quasi-regular grid data to regular.
7855 C
7856 C Purpose.
7857 C --------
7858 C
7859 C Convert quasi-regular grid data to regular,
7860 C using either a linear or cubic interpolation.
7861 C
7862 C
7863 C** Interface.
7864 C ----------
7865 C
7866 C CALL QU2REG3(PFIELD,KPOINT,KLAT,KLON,KCODE,PMSVAL,OMISNG,OPERIO,
7867 C X OVEGGY)
7868 C
7869 C
7870 C Input Parameters.
7871 C -----------------
7872 C
7873 C PFIELD - Array containing quasi-regular grid data.
7874 C
7875 C KPOINT - Array containing list of the number of
7876 C points on each latitude (or longitude) of
7877 C the quasi-regular grid.
7878 C
7879 C KLAT - Number of latitude lines
7880 C
7881 C KLON - Number of longitude lines
7882 C
7883 C KCODE - Interpolation required.
7884 C 1 , linear - data quasi-regular on latitude lines.
7885 C 3 , cubic - data quasi-regular on latitude lines.
7886 C 11, linear - data quasi-regular on longitude lines.
7887 C 13, cubic - data quasi-regular on longitude lines.
7888 C
7889 C PMSVAL - Value used for missing data indicator.
7890 C
7891 C OMISNG - True if missing values are present in field.
7892 C
7893 C OPERIO - True if input field is periodic.
7894 C
7895 C OVEGGY - True if 'nearest neighbour' processing must be used
7896 C for interpolation
7897 C
7898 C
7899 C Output Parameters.
7900 C ------------------
7901 C
7902 C KRET - return code
7903 C 0 = OK
7904 C non-zero indicates fatal error
7905 C
7906 C
7907 C Output Parameters.
7908 C ------------------
7909 C
7910 C PFIELD - Array containing regular grid data.
7911 C
7912 C
7913 C Method.
7914 C -------
7915 C
7916 C Data is interpolated and expanded into a temporary array,
7917 C which is then copied back into the user's array.
7918 C Returns an error code if an invalid interpolation is requested
7919 C or field size exceeds array dimensions.
7920 C
7921 C Comments.
7922 C ---------
7923 C
7924 C This routine is an adaptation of QU2REG to allow missing data
7925 C values, and hence bit mapped fields.
7926 C
7927 C
7928 C Author.
7929 C -------
7930 C
7931 C J.D.Chambers ECMWF 22.07.94
7932 C
7933 C
7934 C Modifications.
7935 C --------------
7936 C
7937 C J.D.Chambers ECMWF 13.09.94
7938 C Add return code KRET and remove calls to ABORT.
7939 C
7940 C J.D.Chambers ECMWF Feb 1997
7941 C Allow for 64-bit pointers
7942 C
7943 C J. Clochard, Meteo France, for ECMWF - January 1998.
7944 C Addition of OMISNG and OPERIO arguments.
7945 C Fix message for longitude number out of bounds, and routine
7946 C name in title and formats.
7947 C
7948 */
7949 /* System generated locals */
7950 int i_1, i_2;
7951 int kcode = 1;
7952
7953 /* Local variables */
7954 int ilii, ilio, icode;
7955 int iregno, iquano, j210, j220, j230, j240, j225;
7956
7957 T *ztemp = (T*) Malloc((size_t)klon*(size_t)klat*sizeof(T));
7958 T *zline = (T*) Malloc(2*(size_t)klon*sizeof(T));
7959 T *zwork = (T*) Malloc(3*(2*(size_t)klon+3)*sizeof(T));
7960
7961 /* Parameter adjustments */
7962 --pfield;
7963 --kpoint;
7964
7965 /* ------------------------------ */
7966 /* Section 1. Set initial values. */
7967 /* ------------------------------ */
7968
7969 *kret = 0;
7970
7971 /* Check input parameters. */
7972
7973 if (kcode != 1 && kcode != 3 && kcode != 11 && kcode != 13) {
7974 fprintf(stderr," QU2REG :");
7975 fprintf(stderr," Invalid interpolation type code = %2d\n",kcode);
7976 *kret = 1;
7977 goto L900;
7978 }
7979
7980 /* Set array indices to 0. */
7981
7982 ilii = 0;
7983 ilio = 0;
7984
7985 /* Establish values of loop parameters. */
7986
7987 if (kcode > 10) {
7988
7989 /* Quasi-regular along longitude lines. */
7990
7991 iquano = klon;
7992 iregno = klat;
7993 icode = kcode - 10;
7994 } else {
7995
7996 /* Quasi-regular along latitude lines. */
7997
7998 iquano = klat;
7999 iregno = klon;
8000 icode = kcode;
8001 }
8002
8003 /* -------------------------------------------------------- */
8004 /** Section 2. Interpolate field from quasi to regular grid. */
8005 /* -------------------------------------------------------- */
8006
8007 i_1 = iquano;
8008 for (j230 = 1; j230 <= i_1; ++j230) {
8009
8010 if (iregno != kpoint[j230]) {
8011
8012 /* Line contains less values than required,so */
8013 /* extract quasi-regular grid values for a line */
8014
8015 i_2 = kpoint[j230];
8016 for (j210 = 1; j210 <= i_2; ++j210) {
8017 ++ilii;
8018 zline[j210 - 1] = pfield[ilii];
8019 }
8020
8021 /* and interpolate this line. */
8022
8023 TEMPLATE(rowina3,T)(zline, iregno, kpoint[j230], zwork, icode, msval, kret, omisng, operio , oveggy);
8024 if (*kret != 0) goto L900;
8025
8026 /* Add regular grid values for this line to the
8027 temporary array. */
8028
8029 i_2 = iregno;
8030 for (j220 = 1; j220 <= i_2; ++j220) {
8031 ++ilio;
8032 ztemp[ilio - 1] = zline[j220 - 1];
8033 }
8034
8035 } else {
8036
8037 /* Line contains the required number of values, so add */
8038 /* this line to the temporary array. */
8039
8040 i_2 = iregno;
8041 for (j225 = 1; j225 <= i_2; ++j225) {
8042 ++ilio;
8043 ++ilii;
8044 ztemp[ilio - 1] = pfield[ilii];
8045 }
8046 }
8047 }
8048
8049 /* Copy temporary array to user array. */
8050
8051 i_1 = klon * klat;
8052 for (j240 = 1; j240 <= i_1; ++j240) {
8053 pfield[j240] = ztemp[j240 - 1];
8054 }
8055
8056 /* -------------------------------------------------------- */
8057 /* Section 9. Return to calling routine. Format statements. */
8058 /* -------------------------------------------------------- */
8059
8060 L900:
8061
8062 Free(zwork);
8063 Free(zline);
8064 Free(ztemp);
8065
8066 return 0;
8067 } /* qu2reg3 */
8068
8069 #endif /* T */
8070
8071 /*
8072 * Local Variables:
8073 * mode: c
8074 * c-file-style: "Java"
8075 * c-basic-offset: 2
8076 * indent-tabs-mode: nil
8077 * show-trailing-whitespace: t
8078 * require-trailing-newline: t
8079 * End:
8080 */
8081 #include <string.h>
8082
8083
8084
gribVersion(unsigned char * is,size_t buffersize)8085 int gribVersion(unsigned char *is, size_t buffersize)
8086 {
8087 if ( buffersize < 8 )
8088 Error("Buffer too small (current size %d)!", (int) buffersize);
8089
8090 return GRIB_EDITION(is);
8091 }
8092
8093 static
GET_Real(unsigned char * grib)8094 double GET_Real(unsigned char *grib)
8095 {
8096 int iexp = GET_UINT1(grib[0]);
8097 int imant = GET_UINT3(grib[1], grib[2], grib[3]);
8098
8099 return decfp2(iexp, imant);
8100 }
8101
8102 static
decodeIS(unsigned char * is,int * isec0,int * iret)8103 int decodeIS(unsigned char *is, int *isec0, int *iret)
8104 {
8105 // Octets 1 - 4 : The letters G R I B. Four 8 bit fields.
8106
8107 // Check letters -> GRIB, BUDG or TIDE.
8108
8109 // Check that 'GRIB' is found where expected.
8110 bool lgrib = GRIB_START(is);
8111
8112 // ECMWF pseudo-grib data uses 'BUDG' and 'TIDE'.
8113 bool lbudg = BUDG_START(is);
8114 bool ltide = TIDE_START(is);
8115
8116 // Data is not GRIB or pseudo-grib.
8117 if ( lgrib == false && lbudg == false && ltide == false )
8118 {
8119 *iret = 305;
8120 gprintf(__func__, "Input data is not GRIB or pseudo-grib.");
8121 gprintf(__func__, "Return code = %d", *iret);
8122 }
8123 if ( lbudg || ltide )
8124 {
8125 *iret = 305;
8126 gprintf(__func__, "Pseudo-grib data unsupported.");
8127 gprintf(__func__, "Return code = %d", *iret);
8128 }
8129
8130 // Octets 5 - 7 : Length of message. One 24 bit field.
8131 ISEC0_GRIB_Len = GRIB1_SECLEN(is);
8132
8133 // Octet 8 : GRIB Edition Number. One 8 bit field.
8134 ISEC0_GRIB_Version = GRIB_EDITION(is);
8135
8136 if ( ISEC0_GRIB_Version > 1 )
8137 Error("GRIB version %d unsupported!", ISEC0_GRIB_Version);
8138
8139 int grib1offset = ISEC0_GRIB_Version * 4;
8140
8141 int isLen = 4 + grib1offset;
8142
8143 return isLen;
8144 }
8145
8146 static
decodePDS_ECMWF_local_Extension_1(unsigned char * pds,int * isec1)8147 void decodePDS_ECMWF_local_Extension_1(unsigned char *pds, int *isec1)
8148 {
8149 isec1[36] = GET_UINT1(pds[40]); /* extension identifier */
8150 isec1[37] = GET_UINT1(pds[41]); /* Class */
8151 isec1[38] = GET_UINT1(pds[42]); /* Type */
8152 isec1[39] = GET_UINT2(pds[43],pds[44]); /* Stream */
8153 /* isec1[40] = GET_UINT4(pds[45],pds[46],pds[47],pds[48]); */
8154 memcpy((char*) &isec1[40], &pds[45], 4);
8155 isec1[41] = GET_UINT1(pds[49]); /* Forecast number */
8156 isec1[42] = GET_UINT1(pds[50]); /* Total number of forecasts */
8157 }
8158
8159 static
decodePDS_DWD_local_Extension_254(unsigned char * pds,int * isec1)8160 void decodePDS_DWD_local_Extension_254(unsigned char *pds, int *isec1)
8161 {
8162 isec1[36] = GET_UINT1(pds[40]); /* extension identifier */
8163 for ( int i = 0; i < 11; i++ )
8164 isec1[37+i] = GET_UINT1(pds[41+i]);
8165
8166 int isvn = GET_UINT2(pds[52],pds[53]);
8167
8168 isec1[48] = isvn % 0x8000; /* DWD experiment identifier */
8169 isec1[49] = isvn >> 15; /* DWD run type (0=main, 2=ass, 3=test) */
8170 }
8171
8172 static
decodePDS_DWD_local_Extension_253(unsigned char * pds,int * isec1)8173 void decodePDS_DWD_local_Extension_253(unsigned char *pds, int *isec1)
8174 {
8175 isec1[36] = GET_UINT1(pds[40]); /* extension identifier */
8176 for ( int i = 0; i < 11; i++ )
8177 isec1[37+i] = GET_UINT1(pds[41+i]);
8178
8179 int isvn = GET_UINT2(pds[52],pds[53]);
8180
8181 isec1[48] = isvn % 0x8000; /* DWD experiment identifier */
8182 isec1[49] = isvn >> 15; /* DWD run type (0=main, 2=ass, 3=test) */
8183 isec1[50] = GET_UINT1(pds[54]); /* User id, specified by table */
8184 isec1[51] = GET_UINT2(pds[55],pds[56]); /* Experiment identifier */
8185 isec1[52] = GET_UINT2(pds[57],pds[58]); /* Ensemble identification by table */
8186 isec1[53] = GET_UINT2(pds[59],pds[60]); /* Number of ensemble members */
8187 isec1[54] = GET_UINT2(pds[61],pds[62]); /* Actual number of ensemble member */
8188 isec1[55] = GET_UINT1(pds[63]); /* Model major version number */
8189 isec1[56] = GET_UINT1(pds[64]); /* Model minor version number */
8190 }
8191
8192 static
decodePDS_MPIM_local_Extension_1(unsigned char * pds,int * isec1)8193 void decodePDS_MPIM_local_Extension_1(unsigned char *pds, int *isec1)
8194 {
8195 isec1[36] = GET_UINT1(pds[40]); /* extension identifier */
8196 isec1[37] = GET_UINT1(pds[41]); /* type of ensemble forecast */
8197 isec1[38] = GET_UINT2(pds[42],pds[43]); /* individual ensemble member */
8198 isec1[39] = GET_UINT2(pds[44],pds[45]); /* number of forecasts in ensemble */
8199 }
8200
8201 static
decodePDS(unsigned char * pds,int * isec0,int * isec1)8202 int decodePDS(unsigned char *pds, int *isec0, int *isec1)
8203 {
8204 int pdsLen = PDS_Len;
8205
8206 ISEC1_CodeTable = PDS_CodeTable;
8207 ISEC1_CenterID = PDS_CenterID;
8208 ISEC1_ModelID = PDS_ModelID;
8209 ISEC1_GridDefinition = PDS_GridDefinition;
8210 ISEC1_Sec2Or3Flag = PDS_Sec2Or3Flag;
8211 ISEC1_Parameter = PDS_Parameter;
8212 ISEC1_LevelType = PDS_LevelType;
8213
8214 if ( (ISEC1_LevelType != 20) &&
8215 (ISEC1_LevelType != GRIB1_LTYPE_99) &&
8216 (ISEC1_LevelType != GRIB1_LTYPE_ISOBARIC) &&
8217 (ISEC1_LevelType != GRIB1_LTYPE_ISOBARIC_PA) &&
8218 (ISEC1_LevelType != GRIB1_LTYPE_ALTITUDE) &&
8219 (ISEC1_LevelType != GRIB1_LTYPE_HEIGHT) &&
8220 (ISEC1_LevelType != GRIB1_LTYPE_SIGMA) &&
8221 (ISEC1_LevelType != GRIB1_LTYPE_HYBRID) &&
8222 (ISEC1_LevelType != GRIB1_LTYPE_LANDDEPTH) &&
8223 (ISEC1_LevelType != GRIB1_LTYPE_ISENTROPIC) &&
8224 (ISEC1_LevelType != 115) &&
8225 (ISEC1_LevelType != 117) &&
8226 (ISEC1_LevelType != 125) &&
8227 (ISEC1_LevelType != 127) &&
8228 (ISEC1_LevelType != GRIB1_LTYPE_SEADEPTH) &&
8229 (ISEC1_LevelType != 210) )
8230 {
8231 ISEC1_Level1 = PDS_Level1;
8232 ISEC1_Level2 = PDS_Level2;
8233 }
8234 else
8235 {
8236 ISEC1_Level1 = PDS_Level;
8237 ISEC1_Level2 = 0;
8238 }
8239
8240 /* ISEC1_Year = PDS_Year; */
8241 ISEC1_Month = PDS_Month;
8242 ISEC1_Day = PDS_Day;
8243 ISEC1_Hour = PDS_Hour;
8244 ISEC1_Minute = PDS_Minute;
8245 ISEC1_TimeUnit = PDS_TimeUnit;
8246 ISEC1_TimePeriod1 = PDS_TimePeriod1;
8247 ISEC1_TimePeriod2 = PDS_TimePeriod2;
8248 ISEC1_TimeRange = PDS_TimeRange;
8249 ISEC1_AvgNum = PDS_AvgNum;
8250 ISEC1_AvgMiss = PDS_AvgMiss;
8251
8252 if ( ISEC0_GRIB_Version == 1 )
8253 {
8254 ISEC1_Year = PDS_Year;
8255 ISEC1_Century = PDS_Century;
8256 ISEC1_SubCenterID = PDS_Subcenter;
8257 ISEC1_DecScaleFactor = PDS_DecimalScale;
8258 }
8259 else
8260 {
8261 int year = GET_UINT1(pds[12]);
8262 if ( year <= 100 )
8263 {
8264 ISEC1_Year = year;
8265 ISEC1_Century = 1;
8266 }
8267 else
8268 {
8269 ISEC1_Year = year%100;
8270 ISEC1_Century = 1 + (year-ISEC1_Year)/100;
8271 }
8272 ISEC1_SubCenterID = 0;
8273 ISEC1_DecScaleFactor = 0;
8274 }
8275
8276 if ( ISEC1_Year < 0 )
8277 {
8278 ISEC1_Year = -ISEC1_Year;
8279 ISEC1_Century = -ISEC1_Century;
8280 }
8281
8282 ISEC1_LocalFLag = 0;
8283 if ( pdsLen > 28 )
8284 {
8285 int localextlen = pdsLen-28;
8286
8287 if ( localextlen > 4000 )
8288 {
8289 Warning("PDS larger than 4000 bytes not supported!");
8290 }
8291 else
8292 {
8293 ISEC1_LocalFLag = 1;
8294
8295 if ( ISEC1_CenterID == 78 || ISEC1_CenterID == 215 || ISEC1_CenterID == 250 )
8296 {
8297 if ( pds[40] == 254 )
8298 decodePDS_DWD_local_Extension_254(pds, isec1);
8299 else if ( pds[40] == 253 )
8300 decodePDS_DWD_local_Extension_253(pds, isec1);
8301 }
8302 else if ( (ISEC1_CenterID == 98 && ISEC1_LocalFLag == 1) ||
8303 (ISEC1_SubCenterID == 98 && ISEC1_LocalFLag == 1) ||
8304 (ISEC1_CenterID == 7 && ISEC1_SubCenterID == 98) )
8305 {
8306 if ( pds[40] == 1 )
8307 decodePDS_ECMWF_local_Extension_1(pds, isec1);
8308 }
8309 else if ( ISEC1_CenterID == 252 && ISEC1_LocalFLag == 1 )
8310 {
8311 if ( pds[40] == 1 )
8312 decodePDS_MPIM_local_Extension_1(pds, isec1);
8313 }
8314 else
8315 {
8316 for ( int i = 0; i < localextlen; i++ )
8317 isec1[24+i] = pds[28+i];
8318 }
8319 }
8320 }
8321
8322 return pdsLen;
8323 }
8324
8325
gribPrintSec2_double(int * isec0,int * isec2,double * fsec2)8326 static void gribPrintSec2_double(int *isec0, int *isec2, double *fsec2) {gribPrintSec2DP(isec0, isec2, fsec2);}
gribPrintSec3_double(int * isec0,int * isec3,double * fsec3)8327 static void gribPrintSec3_double(int *isec0, int *isec3, double *fsec3) {gribPrintSec3DP(isec0, isec3, fsec3);}
gribPrintSec4_double(int * isec0,int * isec4,double * fsec4)8328 static void gribPrintSec4_double(int *isec0, int *isec4, double *fsec4) {gribPrintSec4DP(isec0, isec4, fsec4);}
gribPrintSec2_float(int * isec0,int * isec2,float * fsec2)8329 static void gribPrintSec2_float(int *isec0, int *isec2, float *fsec2) {gribPrintSec2SP(isec0, isec2, fsec2);}
gribPrintSec3_float(int * isec0,int * isec3,float * fsec3)8330 static void gribPrintSec3_float(int *isec0, int *isec3, float *fsec3) {gribPrintSec3SP(isec0, isec3, fsec3);}
gribPrintSec4_float(int * isec0,int * isec4,float * fsec4)8331 static void gribPrintSec4_float(int *isec0, int *isec4, float *fsec4) {gribPrintSec4SP(isec0, isec4, fsec4);}
8332
8333
8334 #ifdef T
8335 #undef T
8336 #endif
8337 #define T double
8338 #ifdef T
8339
8340 #include <inttypes.h>
8341
8342 static
TEMPLATE(decode_array_common,T)8343 void TEMPLATE(decode_array_common,T)(const unsigned char *restrict igrib, long jlend, int NumBits,
8344 T fmin, T zscale, T *restrict fpdata)
8345 {
8346 /* code from wgrib routine BDS_unpack */
8347 const unsigned char *bits = igrib;
8348 unsigned int tbits = 0;
8349 int n_bits = NumBits;
8350 int t_bits = 0;
8351
8352 const unsigned jmask = (1U << n_bits) - 1U;
8353 for (long i = 0; i < jlend; i++)
8354 {
8355 if (n_bits - t_bits > 8)
8356 {
8357 tbits = (tbits << 16) | ((unsigned)bits[0] << 8) | ((unsigned)bits[1]);
8358 bits += 2;
8359 t_bits += 16;
8360 }
8361
8362 while ( t_bits < n_bits )
8363 {
8364 tbits = (tbits * 256) + *bits++;
8365 t_bits += 8;
8366 }
8367 t_bits -= n_bits;
8368 fpdata[i] = (float)((tbits >> t_bits) & jmask);
8369 }
8370 /* at least this vectorizes :) */
8371 for (long i = 0; i < jlend; i++)
8372 fpdata[i] = fmin + zscale*fpdata[i];
8373 }
8374
8375 static
TEMPLATE(decode_array_common2,T)8376 void TEMPLATE(decode_array_common2,T)(const unsigned char *restrict igrib, long jlend, int NumBits,
8377 T fmin, T zscale, T *restrict fpdata)
8378 {
8379 static const unsigned mask[] = {0,1,3,7,15,31,63,127,255};
8380 static const double shift[9] = {1.0, 2.0, 4.0, 8.0, 16.0, 32.0, 64.0, 128.0, 256.0};
8381
8382 /* code from wgrib routine BDS_unpack */
8383 const unsigned char *bits = igrib;
8384 int n_bits = NumBits;
8385 int c_bits, j_bits;
8386
8387 /* older unoptimized code, not often used */
8388 c_bits = 8;
8389 for (long i = 0; i < jlend; i++)
8390 {
8391 double jj = 0.0;
8392 j_bits = n_bits;
8393 while (c_bits <= j_bits)
8394 {
8395 if (c_bits == 8)
8396 {
8397 jj = jj * 256.0 + (double) (*bits++);
8398 j_bits -= 8;
8399 }
8400 else
8401 {
8402 jj = (jj * shift[c_bits]) + (double) (*bits & mask[c_bits]);
8403 bits++;
8404 j_bits -= c_bits;
8405 c_bits = 8;
8406 }
8407 }
8408
8409 if (j_bits)
8410 {
8411 c_bits -= j_bits;
8412 jj = (jj * shift[j_bits]) + (double) (((unsigned)*bits >> c_bits) & mask[j_bits]);
8413 }
8414 fpdata[i] = (T)(fmin + zscale*jj);
8415 }
8416 }
8417
8418 static
TEMPLATE(decode_array_2byte,T)8419 void TEMPLATE(decode_array_2byte,T)(size_t jlend, const unsigned char *restrict igrib,
8420 T *fpdata, T fmin, T zscale)
8421 {
8422 U_BYTEORDER;
8423 const uint16_t *restrict sgrib = (const uint16_t *)(const void *)(igrib);
8424
8425 if ( IS_BIGENDIAN() )
8426 {
8427 for ( size_t i = 0; i < jlend; i++ )
8428 {
8429 fpdata[i] = fmin + zscale * sgrib[i];
8430 }
8431 }
8432 else
8433 {
8434 for ( size_t i = 0; i < jlend; i++ )
8435 {
8436 uint16_t ui16 = gribSwapByteOrder_uint16(sgrib[i]);
8437 fpdata[i] = fmin + zscale * ui16;
8438 }
8439 }
8440 }
8441
8442 static
TEMPLATE(decode_array,T)8443 void TEMPLATE(decode_array,T)(const unsigned char *restrict igrib, long jlend, int numBits,
8444 T fmin, T zscale, T *restrict fpdata)
8445 {
8446 #if defined _GET_X86_COUNTER || defined _GET_MACH_COUNTER
8447 uint64_t start_decode, end_decode;
8448 #endif
8449
8450 long i;
8451 #ifdef VECTORCODE
8452 GRIBPACK *lgrib = NULL;
8453
8454 if ( numBits%8 == 0 )
8455 {
8456 long jlenc = jlend * numBits / 8;
8457 if ( jlenc > 0 )
8458 {
8459 lgrib = (GRIBPACK*) Malloc(jlenc*sizeof(GRIBPACK));
8460 if ( lgrib == NULL ) SysError("No Memory!");
8461
8462 (void) UNPACK_GRIB(igrib, lgrib, jlenc, -1L);
8463 }
8464 }
8465
8466 if ( numBits == 0 )
8467 {
8468 for ( i = 0; i < jlend; i++ )
8469 fpdata[i] = fmin;
8470 }
8471 else if ( numBits == 8 )
8472 for ( i = 0; i < jlend; i++ )
8473 {
8474 T dval = (int)lgrib[i];
8475 fpdata[i] = fmin + zscale * dval;
8476 }
8477 else if ( numBits == 16 )
8478 for ( i = 0; i < jlend; i++ )
8479 {
8480 T dval = (((int)lgrib[2*i ] << 8) + (int)lgrib[2*i+1]);
8481 fpdata[i] = fmin + zscale * dval;
8482 }
8483 else if ( numBits == 24 )
8484 for ( i = 0; i < jlend; i++ )
8485 {
8486 T dval = (((int)lgrib[3*i ] << 16) + ((int)lgrib[3*i+1] << 8) +
8487 (int)lgrib[3*i+2]);
8488 fpdata[i] = fmin + zscale * dval;
8489 }
8490 else if ( numBits == 32 )
8491 for ( i = 0; i < jlend; i++ )
8492 {
8493 T dval = (((unsigned int)lgrib[4*i ] << 24) + ((unsigned int)lgrib[4*i+1] << 16) +
8494 ((unsigned int)lgrib[4*i+2] << 8) + (unsigned int)lgrib[4*i+3]);
8495 fpdata[i] = fmin + zscale * dval;
8496 }
8497 else if ( numBits <= 25 )
8498 {
8499 TEMPLATE(decode_array_common,T)(igrib, jlend, numBits, fmin, zscale, fpdata);
8500 }
8501 else if ( numBits > 25 && numBits < 32 )
8502 {
8503 TEMPLATE(decode_array_common2,T)(igrib, jlend, numBits, fmin, zscale, fpdata);
8504 }
8505 else
8506 {
8507 Error("Unimplemented packing factor %d!", numBits);
8508 }
8509
8510 if ( lgrib ) Free(lgrib);
8511
8512 #else
8513 if ( numBits == 0 )
8514 {
8515 for ( i = 0; i < jlend; i++ )
8516 fpdata[i] = fmin;
8517 }
8518 else if ( numBits == 8 )
8519 for ( i = 0; i < jlend; i++ )
8520 {
8521 T dval = (int)igrib[i];
8522 fpdata[i] = fmin + zscale * dval;
8523 }
8524 else if ( numBits == 16 )
8525 {
8526 TEMPLATE(decode_array_2byte,T)((size_t) jlend, igrib, fpdata, fmin, zscale);
8527 }
8528 else if ( numBits == 24 )
8529 for ( i = 0; i < jlend; i++ )
8530 {
8531 T dval = (T)(((int)igrib[3*i ] << 16) + ((int)igrib[3*i+1] << 8) +
8532 (int)igrib[3*i+2]);
8533 fpdata[i] = fmin + zscale * dval;
8534 }
8535 else if ( numBits == 32 )
8536 for ( i = 0; i < jlend; i++ )
8537 {
8538 T dval = (T)(((unsigned int)igrib[4*i ] << 24) + ((unsigned int)igrib[4*i+1] << 16) +
8539 ((unsigned int)igrib[4*i+2] << 8) + (unsigned int)igrib[4*i+3]);
8540 fpdata[i] = fmin + zscale * dval;
8541 }
8542 else if ( numBits <= 25 )
8543 {
8544 TEMPLATE(decode_array_common,T)(igrib, jlend, numBits, fmin, zscale, fpdata);
8545 }
8546 else if ( numBits > 25 && numBits < 32 )
8547 {
8548 TEMPLATE(decode_array_common2,T)(igrib, jlend, numBits, fmin, zscale, fpdata);
8549 }
8550 else
8551 {
8552 Error("Unimplemented packing factor %d!", numBits);
8553 }
8554 #endif
8555 }
8556
8557 #endif /* T */
8558
8559 /*
8560 * Local Variables:
8561 * mode: c
8562 * End:
8563 */
8564
8565 #ifdef T
8566 #undef T
8567 #endif
8568 #define T float
8569 #ifdef T
8570
8571 #include <inttypes.h>
8572
8573 static
TEMPLATE(decode_array_common,T)8574 void TEMPLATE(decode_array_common,T)(const unsigned char *restrict igrib, long jlend, int NumBits,
8575 T fmin, T zscale, T *restrict fpdata)
8576 {
8577 /* code from wgrib routine BDS_unpack */
8578 const unsigned char *bits = igrib;
8579 unsigned int tbits = 0;
8580 int n_bits = NumBits;
8581 int t_bits = 0;
8582
8583 const unsigned jmask = (1U << n_bits) - 1U;
8584 for (long i = 0; i < jlend; i++)
8585 {
8586 if (n_bits - t_bits > 8)
8587 {
8588 tbits = (tbits << 16) | ((unsigned)bits[0] << 8) | ((unsigned)bits[1]);
8589 bits += 2;
8590 t_bits += 16;
8591 }
8592
8593 while ( t_bits < n_bits )
8594 {
8595 tbits = (tbits * 256) + *bits++;
8596 t_bits += 8;
8597 }
8598 t_bits -= n_bits;
8599 fpdata[i] = (float)((tbits >> t_bits) & jmask);
8600 }
8601 /* at least this vectorizes :) */
8602 for (long i = 0; i < jlend; i++)
8603 fpdata[i] = fmin + zscale*fpdata[i];
8604 }
8605
8606 static
TEMPLATE(decode_array_common2,T)8607 void TEMPLATE(decode_array_common2,T)(const unsigned char *restrict igrib, long jlend, int NumBits,
8608 T fmin, T zscale, T *restrict fpdata)
8609 {
8610 static const unsigned mask[] = {0,1,3,7,15,31,63,127,255};
8611 static const double shift[9] = {1.0, 2.0, 4.0, 8.0, 16.0, 32.0, 64.0, 128.0, 256.0};
8612
8613 /* code from wgrib routine BDS_unpack */
8614 const unsigned char *bits = igrib;
8615 int n_bits = NumBits;
8616 int c_bits, j_bits;
8617
8618 /* older unoptimized code, not often used */
8619 c_bits = 8;
8620 for (long i = 0; i < jlend; i++)
8621 {
8622 double jj = 0.0;
8623 j_bits = n_bits;
8624 while (c_bits <= j_bits)
8625 {
8626 if (c_bits == 8)
8627 {
8628 jj = jj * 256.0 + (double) (*bits++);
8629 j_bits -= 8;
8630 }
8631 else
8632 {
8633 jj = (jj * shift[c_bits]) + (double) (*bits & mask[c_bits]);
8634 bits++;
8635 j_bits -= c_bits;
8636 c_bits = 8;
8637 }
8638 }
8639
8640 if (j_bits)
8641 {
8642 c_bits -= j_bits;
8643 jj = (jj * shift[j_bits]) + (double) (((unsigned)*bits >> c_bits) & mask[j_bits]);
8644 }
8645 fpdata[i] = (T)(fmin + zscale*jj);
8646 }
8647 }
8648
8649 static
TEMPLATE(decode_array_2byte,T)8650 void TEMPLATE(decode_array_2byte,T)(size_t jlend, const unsigned char *restrict igrib,
8651 T *fpdata, T fmin, T zscale)
8652 {
8653 U_BYTEORDER;
8654 const uint16_t *restrict sgrib = (const uint16_t *)(const void *)(igrib);
8655
8656 if ( IS_BIGENDIAN() )
8657 {
8658 for ( size_t i = 0; i < jlend; i++ )
8659 {
8660 fpdata[i] = fmin + zscale * sgrib[i];
8661 }
8662 }
8663 else
8664 {
8665 for ( size_t i = 0; i < jlend; i++ )
8666 {
8667 uint16_t ui16 = gribSwapByteOrder_uint16(sgrib[i]);
8668 fpdata[i] = fmin + zscale * ui16;
8669 }
8670 }
8671 }
8672
8673 static
TEMPLATE(decode_array,T)8674 void TEMPLATE(decode_array,T)(const unsigned char *restrict igrib, long jlend, int numBits,
8675 T fmin, T zscale, T *restrict fpdata)
8676 {
8677 #if defined _GET_X86_COUNTER || defined _GET_MACH_COUNTER
8678 uint64_t start_decode, end_decode;
8679 #endif
8680
8681 long i;
8682 #ifdef VECTORCODE
8683 GRIBPACK *lgrib = NULL;
8684
8685 if ( numBits%8 == 0 )
8686 {
8687 long jlenc = jlend * numBits / 8;
8688 if ( jlenc > 0 )
8689 {
8690 lgrib = (GRIBPACK*) Malloc(jlenc*sizeof(GRIBPACK));
8691 if ( lgrib == NULL ) SysError("No Memory!");
8692
8693 (void) UNPACK_GRIB(igrib, lgrib, jlenc, -1L);
8694 }
8695 }
8696
8697 if ( numBits == 0 )
8698 {
8699 for ( i = 0; i < jlend; i++ )
8700 fpdata[i] = fmin;
8701 }
8702 else if ( numBits == 8 )
8703 for ( i = 0; i < jlend; i++ )
8704 {
8705 T dval = (int)lgrib[i];
8706 fpdata[i] = fmin + zscale * dval;
8707 }
8708 else if ( numBits == 16 )
8709 for ( i = 0; i < jlend; i++ )
8710 {
8711 T dval = (((int)lgrib[2*i ] << 8) + (int)lgrib[2*i+1]);
8712 fpdata[i] = fmin + zscale * dval;
8713 }
8714 else if ( numBits == 24 )
8715 for ( i = 0; i < jlend; i++ )
8716 {
8717 T dval = (((int)lgrib[3*i ] << 16) + ((int)lgrib[3*i+1] << 8) +
8718 (int)lgrib[3*i+2]);
8719 fpdata[i] = fmin + zscale * dval;
8720 }
8721 else if ( numBits == 32 )
8722 for ( i = 0; i < jlend; i++ )
8723 {
8724 T dval = (((unsigned int)lgrib[4*i ] << 24) + ((unsigned int)lgrib[4*i+1] << 16) +
8725 ((unsigned int)lgrib[4*i+2] << 8) + (unsigned int)lgrib[4*i+3]);
8726 fpdata[i] = fmin + zscale * dval;
8727 }
8728 else if ( numBits <= 25 )
8729 {
8730 TEMPLATE(decode_array_common,T)(igrib, jlend, numBits, fmin, zscale, fpdata);
8731 }
8732 else if ( numBits > 25 && numBits < 32 )
8733 {
8734 TEMPLATE(decode_array_common2,T)(igrib, jlend, numBits, fmin, zscale, fpdata);
8735 }
8736 else
8737 {
8738 Error("Unimplemented packing factor %d!", numBits);
8739 }
8740
8741 if ( lgrib ) Free(lgrib);
8742
8743 #else
8744 if ( numBits == 0 )
8745 {
8746 for ( i = 0; i < jlend; i++ )
8747 fpdata[i] = fmin;
8748 }
8749 else if ( numBits == 8 )
8750 for ( i = 0; i < jlend; i++ )
8751 {
8752 T dval = (int)igrib[i];
8753 fpdata[i] = fmin + zscale * dval;
8754 }
8755 else if ( numBits == 16 )
8756 {
8757 TEMPLATE(decode_array_2byte,T)((size_t) jlend, igrib, fpdata, fmin, zscale);
8758 }
8759 else if ( numBits == 24 )
8760 for ( i = 0; i < jlend; i++ )
8761 {
8762 T dval = (T)(((int)igrib[3*i ] << 16) + ((int)igrib[3*i+1] << 8) +
8763 (int)igrib[3*i+2]);
8764 fpdata[i] = fmin + zscale * dval;
8765 }
8766 else if ( numBits == 32 )
8767 for ( i = 0; i < jlend; i++ )
8768 {
8769 T dval = (T)(((unsigned int)igrib[4*i ] << 24) + ((unsigned int)igrib[4*i+1] << 16) +
8770 ((unsigned int)igrib[4*i+2] << 8) + (unsigned int)igrib[4*i+3]);
8771 fpdata[i] = fmin + zscale * dval;
8772 }
8773 else if ( numBits <= 25 )
8774 {
8775 TEMPLATE(decode_array_common,T)(igrib, jlend, numBits, fmin, zscale, fpdata);
8776 }
8777 else if ( numBits > 25 && numBits < 32 )
8778 {
8779 TEMPLATE(decode_array_common2,T)(igrib, jlend, numBits, fmin, zscale, fpdata);
8780 }
8781 else
8782 {
8783 Error("Unimplemented packing factor %d!", numBits);
8784 }
8785 #endif
8786 }
8787
8788 #endif /* T */
8789
8790 /*
8791 * Local Variables:
8792 * mode: c
8793 * End:
8794 */
8795
8796
8797 #ifdef T
8798 #undef T
8799 #endif
8800 #define T double
8801 #ifdef T
8802
8803 static
TEMPLATE(decodeGDS,T)8804 int TEMPLATE(decodeGDS,T)(unsigned char *gds, int *isec0, int *isec2, T *fsec2, int *numGridVals)
8805 {
8806 // int imisng = 0;
8807 bool ReducedGrid = false, VertCoorTab = false;
8808 #ifdef VECTORCODE
8809 unsigned char *igrib;
8810 GRIBPACK *lgrib = NULL;
8811 size_t lGribLen = 0;
8812 #endif
8813
8814 *numGridVals = 0;
8815
8816 memset(isec2, 0, 22*sizeof(int));
8817
8818 const unsigned gdsLen = GDS_Len;
8819
8820 unsigned ipvpl = GDS_PVPL;
8821 if ( ipvpl == 0 ) ipvpl = 0xFF;
8822
8823 if ( ipvpl != 0xFF )
8824 { // Either vct or reduced grid
8825 if ( GDS_NV != 0 )
8826 { // we have vct
8827 VertCoorTab = true;
8828 const unsigned ipl = 4*GDS_NV + ipvpl - 1;
8829 if ( ipl < gdsLen ) ReducedGrid = true;
8830 }
8831 else
8832 {
8833 VertCoorTab = false;
8834 ReducedGrid = true;
8835 }
8836 // ReducedGrid = (gdsLen - 32 - 4*GDS_NV);
8837 }
8838
8839 if ( ISEC0_GRIB_Version == 0 ) VertCoorTab = ((gdsLen - 32) > 0);
8840
8841 if ( ReducedGrid )
8842 {
8843 const unsigned locnl = GDS_PVPL - 1 + (VertCoorTab * 4 * GDS_NV);
8844 const unsigned jlenl = (gdsLen - locnl) >> 1;
8845 if ( jlenl == GDS_NumLat )
8846 {
8847 *numGridVals = 0;
8848 ISEC2_Reduced = true;
8849 for ( unsigned i = 0; i < jlenl; i++ )
8850 {
8851 ISEC2_ReducedPoints(i) = GET_UINT2(gds[locnl+2*i], gds[locnl+2*i+1]);
8852 *numGridVals += ISEC2_ReducedPoints(i);
8853 }
8854 }
8855 else
8856 {
8857 ReducedGrid = false;
8858 }
8859 }
8860
8861 ISEC2_GridType = GDS_GridType;
8862
8863 // Gaussian grid definition.
8864
8865 if ( ISEC2_GridType == GRIB1_GTYPE_LATLON ||
8866 ISEC2_GridType == GRIB1_GTYPE_GAUSSIAN ||
8867 ISEC2_GridType == GRIB1_GTYPE_LATLON_ROT )
8868 {
8869 ISEC2_NumLat = GDS_NumLat;
8870 if ( ! ReducedGrid )
8871 {
8872 ISEC2_NumLon = GDS_NumLon;
8873 *numGridVals = ISEC2_NumLon*ISEC2_NumLat;
8874 }
8875 ISEC2_FirstLat = GDS_FirstLat;
8876 ISEC2_FirstLon = GDS_FirstLon;
8877 ISEC2_ResFlag = GDS_ResFlag;
8878 ISEC2_LastLat = GDS_LastLat;
8879 ISEC2_LastLon = GDS_LastLon;
8880 ISEC2_LonIncr = GDS_LonIncr;
8881
8882 ISEC2_NumPar = GDS_NumPar;
8883 ISEC2_ScanFlag = GDS_ScanFlag;
8884 if ( ISEC2_GridType == GRIB1_GTYPE_LATLON_ROT )
8885 {
8886 ISEC2_LatSP = GDS_LatSP;
8887 ISEC2_LonSP = GDS_LonSP;
8888 FSEC2_RotAngle = (T)GDS_RotAngle;
8889 }
8890 // if ( Lons != Longitudes || Lats != Latitudes ) Error("Latitude/Longitude Conflict");
8891 }
8892 else if ( ISEC2_GridType == GRIB1_GTYPE_GAUSSIAN ||
8893 ISEC2_GridType == GRIB1_GTYPE_GAUSSIAN_ROT ||
8894 ISEC2_GridType == GRIB1_GTYPE_GAUSSIAN_STR ||
8895 ISEC2_GridType == GRIB1_GTYPE_GAUSSIAN_ROTSTR )
8896 {
8897 // iret = decodeGDS_GG(gds, gdspos, isec0, isec2, imisng);
8898 }
8899 else if ( ISEC2_GridType == GRIB1_GTYPE_LATLON ||
8900 ISEC2_GridType == GRIB1_GTYPE_LATLON_ROT ||
8901 ISEC2_GridType == GRIB1_GTYPE_LATLON_STR ||
8902 ISEC2_GridType == GRIB1_GTYPE_LATLON_ROTSTR )
8903 {
8904 // iret = decodeGDS_LL(gds, gdspos, isec0, isec2, imisng);
8905 }
8906 else if ( ISEC2_GridType == GRIB1_GTYPE_LCC )
8907 {
8908 ISEC2_NumLon = GDS_NumLon;
8909 ISEC2_NumLat = GDS_NumLat;
8910 *numGridVals = ISEC2_NumLon*ISEC2_NumLat;
8911 ISEC2_FirstLat = GDS_FirstLat;
8912 ISEC2_FirstLon = GDS_FirstLon;
8913 ISEC2_ResFlag = GDS_ResFlag;
8914 ISEC2_Lambert_Lov = GDS_Lambert_Lov;
8915 ISEC2_Lambert_dx = GDS_Lambert_dx;
8916 ISEC2_Lambert_dy = GDS_Lambert_dy;
8917 ISEC2_Lambert_LatS1 = GDS_Lambert_LatS1;
8918 ISEC2_Lambert_LatS2 = GDS_Lambert_LatS2;
8919 ISEC2_Lambert_LatSP = GDS_Lambert_LatSP;
8920 ISEC2_Lambert_LonSP = GDS_Lambert_LonSP;
8921 ISEC2_Lambert_ProjFlag = GDS_Lambert_ProjFlag;
8922 ISEC2_ScanFlag = GDS_ScanFlag;
8923 }
8924 else if ( ISEC2_GridType == GRIB1_GTYPE_SPECTRAL )
8925 {
8926 ISEC2_PentaJ = GDS_PentaJ; // Truncation
8927 ISEC2_PentaK = GDS_PentaK;
8928 ISEC2_PentaM = GDS_PentaM;
8929 ISEC2_RepType = GDS_RepType;
8930 ISEC2_RepMode = GDS_RepMode;
8931 *numGridVals = (ISEC2_PentaJ+1)*(ISEC2_PentaJ+2);
8932 isec2[ 6] = 0;
8933 isec2[ 7] = 0;
8934 isec2[ 8] = 0;
8935 isec2[ 9] = 0;
8936 isec2[10] = 0;
8937 // iret = decodeGDS_SH(gds, gdspos, isec0, isec2, imisng);
8938 }
8939 else if ( ISEC2_GridType == GRIB1_GTYPE_GME )
8940 {
8941 ISEC2_GME_NI2 = GDS_GME_NI2;
8942 ISEC2_GME_NI3 = GDS_GME_NI3;
8943 ISEC2_GME_ND = GDS_GME_ND;
8944 ISEC2_GME_NI = GDS_GME_NI;
8945 ISEC2_GME_AFlag = GDS_GME_AFlag;
8946 ISEC2_GME_LatPP = GDS_GME_LatPP;
8947 ISEC2_GME_LonPP = GDS_GME_LonPP;
8948 ISEC2_GME_LonMPL = GDS_GME_LonMPL;
8949 ISEC2_GME_BFlag = GDS_GME_BFlag;
8950 *numGridVals = (ISEC2_GME_NI+1)*(ISEC2_GME_NI+1)*10;
8951 // iret = decodeGDS_TR(gds, gdspos, isec0, isec2, imisng);
8952 }
8953 else
8954 {
8955 static bool lwarn = true;
8956 ISEC2_NumLon = GDS_NumLon;
8957 ISEC2_NumLat = GDS_NumLat;
8958 *numGridVals = ISEC2_NumLon*ISEC2_NumLat;
8959 if ( lwarn )
8960 {
8961 lwarn = false;
8962 Message("GRIB gridtype %d unsupported", ISEC2_GridType);
8963 }
8964 }
8965
8966 // Vertical coordinate parameters for hybrid levels.
8967 // Get number of vertical coordinate parameters, if any.
8968
8969 ISEC2_NumVCP = 0;
8970
8971 isec2[17] = 0;
8972 isec2[18] = 0;
8973
8974 if ( VertCoorTab )
8975 {
8976 int locnv;
8977 if ( ISEC0_GRIB_Version == 0 )
8978 {
8979 locnv = 32;
8980 ISEC2_NumVCP = (gdsLen - 32) >> 2;
8981 }
8982 else
8983 {
8984 locnv = GDS_PVPL - 1;
8985 ISEC2_NumVCP = GDS_NV;
8986 }
8987 #if defined (SX)
8988 lGribLen = 4*ISEC2_NumVCP;
8989 lgrib = (GRIBPACK*) Malloc(lGribLen*sizeof(GRIBPACK));
8990
8991 igrib = &gds[locnv];
8992 if ( ISEC2_NumVCP > 0 ) (void) UNPACK_GRIB(igrib, lgrib, lGribLen, -1L);
8993 for ( int i = 0; i < ISEC2_NumVCP; i++ )
8994 {
8995 const int iexp = lgrib[4*i];
8996 const int imant = GET_UINT3(lgrib[4*i+1], lgrib[4*i+2], lgrib[4*i+3]);
8997 fsec2[10+i] = POW_2_M24 * imant * ldexp(1.0, 4 * (iexp - 64));
8998 }
8999
9000 Free(lgrib);
9001 #else
9002 for ( int i = 0; i < ISEC2_NumVCP; i++ )
9003 {
9004 const int iexp = gds[locnv+4*i];
9005 const int imant = GET_UINT3(gds[locnv+4*i+1], gds[locnv+4*i+2], gds[locnv+4*i+3]);
9006 fsec2[10+i] = (T)decfp2(iexp,imant);
9007 }
9008 #endif
9009 }
9010
9011 return gdsLen;
9012 }
9013
9014 #define ldexp_double ldexp
9015 #define ldexp_float ldexpf
9016 #define pow_double pow
9017 #define pow_float powf
9018
9019 static
TEMPLATE(decodeBDS,T)9020 void TEMPLATE(decodeBDS,T)(int decscale, unsigned char *bds, int *isec2, int *isec4,
9021 T *fsec4, int fsec4len, int dfunc, int bdsLen, int numGridVals, int *iret)
9022 {
9023 int ioff = 0;
9024 enum { bds_head = 11 };
9025 T zscale = 0.;
9026 T fmin = 0.;
9027 T *fpdata = fsec4;
9028
9029 *iret = 0;
9030 unsigned char *igrib = bds;
9031
9032 memset(isec4, 0, 42*sizeof(int));
9033
9034 // 4 bit flag / 4 bit count of unused bits at end of block octet.
9035
9036 const int bds_flag = BDS_Flag;
9037
9038 // 0------- grid point
9039 // 1------- spherical harmonics
9040
9041 const bool lspherc = (bds_flag >> 7)&1;
9042 if ( lspherc ) isec4[2] = 128;
9043 else isec4[2] = 0;
9044
9045 // -0------ simple packing
9046 // -1------ complex packing
9047
9048 const bool lcomplex = (bds_flag >> 6)&1;
9049 if ( lcomplex ) isec4[3] = 64;
9050 else isec4[3] = 0;
9051
9052 // ---0---- No additional flags
9053 // ---1---- No additional flags
9054
9055 const bool lcompress = (bds_flag >> 4)&1;
9056
9057 unsigned zoff;
9058 if ( lcompress )
9059 { isec4[5] = 16; isec4[6] = BDS_Z; zoff = 12; }
9060 else
9061 { isec4[5] = 0; isec4[6] = 0; zoff = 0; }
9062
9063 // ----++++ number of unused bits at end of section)
9064
9065 const int bds_ubits = bds_flag & 0xF;
9066
9067 // scale factor (2 bytes)
9068 const int jscale = BDS_BinScale;
9069
9070 // check for missing data indicators.
9071
9072 const int iexp = bds[ 6];
9073 const int imant = GET_UINT3(bds[ 7], bds[ 8], bds[ 9]);
9074
9075 const int imiss = (jscale == 0xFFFF && iexp == 0xFF && imant == 0xFFFFFF);
9076
9077 // convert reference value and scale factor.
9078
9079 if ( ! (dfunc == 'J') && imiss == 0 )
9080 {
9081 fmin = (T)BDS_RefValue;
9082 zscale = TEMPLATE(ldexp,T)((T)1.0, jscale);
9083 }
9084
9085 // get number of bits in each data value.
9086
9087 ISEC4_NumBits = BDS_NumBits;
9088
9089 // octet number of start of packed data calculated from start of block 4 - 1
9090
9091 unsigned locnd = zoff + bds_head;
9092
9093 // if data is in spherical harmonic form, distinguish between simple/complex packing (lcomplex = 0/1)
9094
9095 if ( lspherc )
9096 {
9097 if ( !lcomplex )
9098 {
9099 // no unpacked binary data present octet number of start of packed data
9100 // calculated from start of block 4 - 1
9101
9102 ioff = 1;
9103 locnd += 4*ioff; // RealCoef
9104
9105 // get real (0,0) coefficient in grib format and convert to floating point.
9106 if ( dfunc != 'J' )
9107 {
9108 if ( imiss ) *fpdata++ = 0.0;
9109 else *fpdata++ = (T)BDS_RealCoef;
9110 }
9111 }
9112 else // complex packed spherical harmonics
9113 {
9114 isec4[15] = BDS_PackData;
9115 // scaling factor
9116 isec4[16] = BDS_Power;
9117
9118 // pentagonal resolution parameters of the unpacked section of data field
9119
9120 const int jup = bds[zoff+15];
9121 const int kup = bds[zoff+16];
9122 const int mup = bds[zoff+17];
9123
9124 isec4[zoff+17] = jup;
9125 isec4[zoff+18] = kup;
9126 isec4[zoff+19] = mup;
9127
9128 // unpacked binary data
9129
9130 locnd += 4; // 2 + power
9131 locnd += 3; // j, k, m
9132 ioff = (jup+1)*(jup+2);
9133
9134 if ( dfunc != 'J' )
9135 for ( int i = 0; i < ioff; i++ )
9136 {
9137 if ( imiss )
9138 *fpdata++ = 0.0;
9139 else
9140 {
9141 const int iexp2 = (bds[locnd+4*i]);
9142 const int imant2 = GET_UINT3(bds[locnd+4*i+1], bds[locnd+4*i+2], bds[locnd+4*i+3]);
9143 *fpdata++ = (T)decfp2(iexp2,imant2);
9144 }
9145 }
9146
9147 locnd += 4*ioff; /* RealCoef */
9148 }
9149 }
9150 else
9151 {
9152 if ( lcomplex )
9153 {
9154 *iret = 1999;
9155 gprintf(__func__, " Second order packed grids unsupported!");
9156 gprintf(__func__, " Return code = %d", *iret);
9157 return;
9158 }
9159 }
9160
9161 // Decode data values to floating point and store in fsec4.
9162 // First calculate the number of data values.
9163 // Take into account that spherical harmonics can be packed
9164 // simple (lcomplex = 0) or complex (lcomplex = 1)
9165
9166 int jlend = bdsLen - locnd;
9167
9168 if ( ISEC4_NumBits == 0 )
9169 {
9170 if ( jlend > 1 )
9171 {
9172 *iret = 2001;
9173 gprintf(__func__, " Number of bits per data value = 0!");
9174 gprintf(__func__, " Return code = %d", *iret);
9175 return;
9176 }
9177
9178 if ( numGridVals == 0 )
9179 {
9180 *iret = 2002;
9181 gprintf(__func__, " Constant field unsupported for this grid type!");
9182 gprintf(__func__, " Return code = %d", *iret);
9183 return;
9184 }
9185
9186 jlend = numGridVals;
9187 jlend -= ioff;
9188 }
9189 else
9190 {
9191 jlend = (int) (((long)jlend*8 - bds_ubits) / ISEC4_NumBits);
9192 }
9193
9194 ISEC4_NumValues = jlend + ioff;
9195 ISEC4_NumNonMissValues = 0;
9196
9197 if ( lcompress )
9198 {
9199 const size_t len = ((size_t) ((bds[17]<<16)+(bds[18]<<8)+bds[19]));
9200
9201 ISEC4_NumValues = (int)(len*8/(size_t)ISEC4_NumBits);
9202
9203 if ( lspherc ) ISEC4_NumValues += lcomplex ? ioff : 1;
9204 }
9205
9206 if ( dfunc == 'J' ) return;
9207
9208 // check length of output array.
9209
9210 if ( ISEC4_NumValues > fsec4len )
9211 {
9212 *iret = 710;
9213 gprintf(__func__, " Output array too small. Length = %d", fsec4len);
9214 gprintf(__func__, " Number of values = %d", ISEC4_NumValues);
9215 gprintf(__func__, " Return code = %d", *iret);
9216 return;
9217 }
9218
9219 if ( imiss ) memset((char *)fpdata, 0, (size_t)jlend*sizeof(T));
9220 else
9221 {
9222 igrib += locnd;
9223
9224 TEMPLATE(decode_array,T)(igrib, jlend, ISEC4_NumBits, fmin, zscale, fpdata);
9225 }
9226
9227 if ( lspherc && lcomplex )
9228 {
9229 int pcStart = isec4[19], pcScale = isec4[16];
9230 TEMPLATE(scatter_complex,T)(fsec4, pcStart, ISEC2_PentaJ, ISEC4_NumValues);
9231 TEMPLATE(scale_complex,T)(fsec4, pcStart, pcScale, ISEC2_PentaJ, 1);
9232 }
9233
9234 if ( CGRIBEX_Fix_ZSE ) // Fix ZeroShiftError of simple packed spherical harmonics
9235 if ( lspherc && !lcomplex )
9236 {
9237 // 20100705: Fix ZeroShiftError - Edi Kirk
9238 if ( IS_NOT_EQUAL(fsec4[1], 0.0) )
9239 {
9240 const T zserr = fsec4[1];
9241 for ( int i = 1; i < ISEC4_NumValues; i++ ) fsec4[i] -= zserr;
9242 }
9243 }
9244
9245 if ( decscale )
9246 {
9247 const T scale = TEMPLATE(pow,T)((T)10.0, (T)-decscale);
9248 for ( int i = 0; i < ISEC4_NumValues; i++ ) fsec4[i] *= scale;
9249 }
9250 }
9251
9252
TEMPLATE(grib_decode,T)9253 void TEMPLATE(grib_decode,T)(int *isec0, int *isec1, int *isec2, T *fsec2, int *isec3,
9254 T *fsec3, int *isec4, T *fsec4, int fsec4len, int *kgrib,
9255 int kleng, int *kword, int dfunc, int *iret)
9256 {
9257 UCHAR *bms = NULL;
9258 bool lsect2 = false, lsect3 = false;
9259 static bool lmissvalinfo = true;
9260
9261 UNUSED(kleng);
9262
9263 *iret = 0;
9264
9265 grsdef();
9266
9267 ISEC2_Reduced = false;
9268
9269 // ----------------------------------------------------------------
9270 // IS Indicator Section (Section 0)
9271 // ----------------------------------------------------------------
9272 UCHAR *is = (UCHAR *) &kgrib[0];
9273 int isLen = decodeIS(is, isec0, iret);
9274
9275 int gribLen = ISEC0_GRIB_Len;
9276
9277 /*
9278 When decoding or calculating length, previous editions
9279 of the GRIB code must be taken into account.
9280
9281 In the table below, covering sections 0 and 1 of the GRIB
9282 code, octet numbering is from the beginning of the GRIB
9283 message;
9284 * indicates that the value is not available in the code edition;
9285 R indicates reserved, should be set to 0;
9286 Experimental edition is considered as edition -1.
9287
9288 GRIB code edition -1 has fixed length of 20 octets for
9289 section 1, the length not included in the message.
9290 GRIB code edition 0 has fixed length of 24 octets for
9291 section 1, the length being included in the message.
9292 GRIB code edition 1 can have different lengths for section
9293 1, the minimum being 28 octets, length being included in
9294 the message.
9295
9296 Octet numbers for code
9297 editions
9298
9299 Contents. -1 0 1
9300 --------- ----------------------
9301 Letters GRIB 1-4 1-4 1-4
9302 Total length of GRIB message. * * 5-7
9303 GRIB code edition number * * 8
9304 Length of Section 1. * 5-7 9-11
9305 Reserved octet (R). * 8(R) *
9306 Version no. of Code Table 2. * * 12
9307 Identification of centre. 5 9 13
9308 Generating process. 6 10 14
9309 Grid definition . 7 11 15
9310 Flag (Code Table 1). 8 12 16
9311 Indicator of parameter. 9 13 17
9312 Indicator of type of level. 10 14 18
9313 Height, pressure etc of levels. 11-12 15-16 19-20
9314 Year of century. 13 17 21
9315 Month. 14 18 22
9316 Day. 15 19 23
9317 Hour. 16 20 24
9318 Minute. 17 21 25
9319 Indicator of unit of time. 18 22 26
9320 P1 - Period of time. 19 23 27
9321 P2 - Period of time 20(R) 24 28
9322 or reserved octet (R).
9323 Time range indicator. 21(R) 25 29
9324 or reserved octet (R).
9325 Number included in average. 22-23(R) 26-27 30-31
9326 or reserved octet (R).
9327 Number missing from average. 24(R) 28(R) 32
9328 or reserved octet (R).
9329 Century of data. * * 33
9330 Designates sub-centre if not 0. * * 34
9331 Decimal scale factor. * * 35-36
9332 Reserved. Set to 0. * * 37-48
9333 (Need not be present)
9334 For originating centre use only. * * 49-nn
9335 (Need not be present)
9336
9337 Identify which GRIB code edition is being decoded.
9338
9339 In GRIB edition 1, the edition number is in octet 8.
9340 In GRIB edition 0, octet 8 is reserved and set to 0.
9341 In GRIB edition -1, octet 8 is a flag field and can have a
9342 a valid value of 0, 1, 2 or 3.
9343
9344 However, GRIB edition number 0 has a fixed
9345 length of 24, included in the message, for section 1, so
9346 if the value extracted from octets 5-7 is 24 and that from
9347 octet 8 is 0, it is safe to assume edition 0 of the code.
9348
9349 */
9350
9351 // Set length of GRIB message to missing data value.
9352 if ( ISEC0_GRIB_Len == 24 && ISEC0_GRIB_Version == 0 ) ISEC0_GRIB_Len = 0;
9353
9354 // ----------------------------------------------------------------
9355 // PDS Product Definition Section (Section 1)
9356 // ----------------------------------------------------------------
9357 UCHAR *pds = is + isLen;
9358 int pdsLen = decodePDS(pds, isec0, isec1);
9359
9360 // ----------------------------------------------------------------
9361 // GDS Grid Description Section (Section 2)
9362 // ----------------------------------------------------------------
9363 int numGridVals = 0;
9364 int gdsLen = 0;
9365 const bool gdsIncluded = ISEC1_Sec2Or3Flag & 128;
9366 if ( gdsIncluded )
9367 {
9368 UCHAR *gds = is + isLen + pdsLen;
9369 gdsLen = TEMPLATE(decodeGDS,T)(gds, isec0, isec2, fsec2, &numGridVals);
9370 }
9371
9372 // ----------------------------------------------------------------
9373 // BMS Bit-Map Section Section (Section 3)
9374 // ----------------------------------------------------------------
9375 isec3[0] = 0;
9376 int bmsLen = 0, bitmapSize = 0, imaskSize = 0;
9377 const bool bmsIncluded = ISEC1_Sec2Or3Flag & 64;
9378 if ( bmsIncluded )
9379 {
9380 bms = is + isLen + pdsLen + gdsLen;
9381 bmsLen = BMS_Len;
9382
9383 imaskSize = (bmsLen > 6) ? (bmsLen - 6)<<3 : 0;
9384 bitmapSize = imaskSize - BMS_UnusedBits;
9385 }
9386
9387 // ----------------------------------------------------------------
9388 // BDS Binary Data Section (Section 4)
9389 // ----------------------------------------------------------------
9390 UCHAR *bds = is + isLen + pdsLen + gdsLen + bmsLen;
9391 int bdsLen = BDS_Len;
9392 /*
9393 If a very large product, the section 4 length field holds
9394 the number of bytes in the product after section 4 upto
9395 the end of the padding bytes.
9396 This is a fixup to get round the restriction on product lengths
9397 due to the count being only 24 bits. It is only possible because
9398 the (default) rounding for GRIB products is 120 bytes.
9399 */
9400 const bool llarge = (gribLen > JP23SET && bdsLen <= 120);
9401 if ( llarge )
9402 {
9403 gribLen &= JP23SET;
9404 gribLen *= 120;
9405 ISEC0_GRIB_Len = gribLen;
9406 bdsLen = correct_bdslen(bdsLen, gribLen, isLen+pdsLen+gdsLen+bmsLen);
9407 }
9408
9409 TEMPLATE(decodeBDS,T)(ISEC1_DecScaleFactor, bds, isec2, isec4, fsec4, fsec4len, dfunc, bdsLen, numGridVals, iret);
9410
9411 if ( *iret != 0 ) return;
9412
9413 ISEC4_NumNonMissValues = ISEC4_NumValues;
9414
9415 if ( bitmapSize > 0 )
9416 {
9417 if ( dfunc != 'L' && dfunc != 'J' )
9418 if ( DBL_IS_NAN(FSEC3_MissVal) && lmissvalinfo )
9419 {
9420 lmissvalinfo = false;
9421 FSEC3_MissVal = (T)GRIB_MISSVAL;
9422 Message("Missing value = NaN is unsupported, set to %g!", GRIB_MISSVAL);
9423 }
9424
9425 // ISEC4_NumNonMissValues = ISEC4_NumValues;
9426 ISEC4_NumValues = bitmapSize;
9427
9428 if ( dfunc != 'J' || bitmapSize == ISEC4_NumNonMissValues )
9429 {
9430 GRIBPACK bitmap;
9431 /*
9432 unsigned char *bitmap;
9433 bitmap = BMS_Bitmap;
9434 int j = ISEC4_NumNonMissValues;
9435 for ( int i = ISEC4_NumValues-1; i >= 0; i-- )
9436 {
9437 fsec4[i] = ((bitmap[i/8]>>(7-(i&7)))&1) ? fsec4[--j] : FSEC3_MissVal;
9438 }
9439 */
9440
9441 GRIBPACK *imask = (GRIBPACK*) Malloc((size_t)imaskSize*sizeof(GRIBPACK));
9442
9443 #ifdef VECTORCODE
9444 (void) UNPACK_GRIB(BMS_Bitmap, imask, imaskSize/8, -1L);
9445 GRIBPACK *pbitmap = imask;
9446 #else
9447 GRIBPACK *pbitmap = BMS_Bitmap;
9448 #endif
9449
9450 #if defined (CRAY)
9451 #pragma _CRI ivdep
9452 #endif
9453 #if defined (SX)
9454 #pragma vdir nodep
9455 #endif
9456 #ifdef __uxpch__
9457 #pragma loop novrec
9458 #endif
9459 for ( int i = imaskSize/8-1; i >= 0; i-- )
9460 {
9461 bitmap = pbitmap[i];
9462 imask[i*8+0] = 1 & (bitmap >> 7);
9463 imask[i*8+1] = 1 & (bitmap >> 6);
9464 imask[i*8+2] = 1 & (bitmap >> 5);
9465 imask[i*8+3] = 1 & (bitmap >> 4);
9466 imask[i*8+4] = 1 & (bitmap >> 3);
9467 imask[i*8+5] = 1 & (bitmap >> 2);
9468 imask[i*8+6] = 1 & (bitmap >> 1);
9469 imask[i*8+7] = 1 & (bitmap);
9470 }
9471
9472 int j = 0;
9473 for ( int i = 0; i < ISEC4_NumValues; i++ )
9474 if ( imask[i] ) j++;
9475
9476 if ( ISEC4_NumNonMissValues != j )
9477 {
9478 if ( dfunc != 'J' && ISEC4_NumBits != 0 )
9479 Warning("Bitmap (%d) and data (%d) section differ, using bitmap section!", j, ISEC4_NumNonMissValues);
9480
9481 ISEC4_NumNonMissValues = j;
9482 }
9483
9484 if ( dfunc != 'J' )
9485 {
9486 #if defined (CRAY)
9487 #pragma _CRI ivdep
9488 #endif
9489 #if defined (SX)
9490 #pragma vdir nodep
9491 #endif
9492 #ifdef __uxpch__
9493 #pragma loop novrec
9494 #endif
9495 for ( int i = ISEC4_NumValues-1; i >= 0; i-- )
9496 fsec4[i] = imask[i] ? fsec4[--j] : FSEC3_MissVal;
9497 }
9498
9499 Free(imask);
9500 }
9501 }
9502
9503 if ( ISEC2_Reduced )
9504 {
9505 int nvalues = 0;
9506 int nlat = ISEC2_NumLat;
9507 int nlon = ISEC2_ReducedPointsPtr[0];
9508 for ( int ilat = 0; ilat < nlat; ++ilat ) nvalues += ISEC2_ReducedPoints(ilat);
9509 for ( int ilat = 1; ilat < nlat; ++ilat )
9510 if ( ISEC2_ReducedPoints(ilat) > nlon ) nlon = ISEC2_ReducedPoints(ilat);
9511
9512 // int dlon = ISEC2_LastLon-ISEC2_FirstLon;
9513 // if ( dlon < 0 ) dlon += 360000;
9514
9515 if ( nvalues != ISEC4_NumValues ) *iret = -801;
9516
9517 //printf("nlat %d nlon %d \n", nlat, nlon);
9518 //printf("nvalues %d %d\n", nvalues, ISEC4_NumValues);
9519
9520 if ( dfunc == 'R' && *iret == -801 )
9521 gprintf(__func__, "Number of values (%d) and sum of lons per row (%d) differ, abort conversion to regular Gaussian grid!",
9522 ISEC4_NumValues, nvalues);
9523
9524 if ( dfunc == 'R' && *iret != -801 )
9525 {
9526 ISEC2_Reduced = 0;
9527 ISEC2_NumLon = nlon;
9528 ISEC4_NumValues = nlon*nlat;
9529
9530 lsect3 = bitmapSize > 0;
9531 int lperio = 1;
9532 int lveggy = (ISEC1_CodeTable == 128) && (ISEC1_CenterID == 98) &&
9533 ((ISEC1_Parameter == 27) || (ISEC1_Parameter == 28) ||
9534 (ISEC1_Parameter == 29) || (ISEC1_Parameter == 30) ||
9535 (ISEC1_Parameter == 39) || (ISEC1_Parameter == 40) ||
9536 (ISEC1_Parameter == 41) || (ISEC1_Parameter == 42) ||
9537 (ISEC1_Parameter == 43));
9538
9539 (void) TEMPLATE(qu2reg3,T)(fsec4, ISEC2_ReducedPointsPtr, nlat, nlon, FSEC3_MissVal, iret, lsect3, lperio, lveggy);
9540
9541 if ( bitmapSize > 0 )
9542 {
9543 int j = 0;
9544 for ( int i = 0; i < ISEC4_NumValues; i++ )
9545 if ( IS_NOT_EQUAL(fsec4[i], FSEC3_MissVal) ) j++;
9546
9547 ISEC4_NumNonMissValues = j;
9548 }
9549 }
9550 }
9551
9552 if ( ISEC0_GRIB_Version == 1 ) isLen = 8;
9553 const int esLen = 4;
9554 gribLen = isLen + pdsLen + gdsLen + bmsLen + bdsLen + esLen;
9555
9556 if ( !llarge && ISEC0_GRIB_Len && ISEC0_GRIB_Len < gribLen )
9557 Warning("Inconsistent length of GRIB message (grib_message_size=%d < grib_record_size=%d)!", ISEC0_GRIB_Len, gribLen);
9558
9559 ISEC0_GRIB_Len = gribLen;
9560
9561 *kword = (int)(((size_t)gribLen + sizeof(int) - 1) / sizeof(int));
9562
9563 // ----------------------------------------------------------------
9564 // Section 9 . Abort/return to calling routine.
9565 // ----------------------------------------------------------------
9566 bool ldebug = false, l_iorj = false;
9567 if ( ldebug )
9568 {
9569 gprintf(__func__, "Section 9.");
9570 gprintf(__func__, "Output values set -");
9571
9572 gribPrintSec0(isec0);
9573 gribPrintSec1(isec0, isec1);
9574 // Print section 2 if present.
9575 if ( lsect2 ) TEMPLATE(gribPrintSec2,T)(isec0, isec2, fsec2);
9576
9577 if ( ! l_iorj )
9578 {
9579 // Print section 3 if present.
9580 if ( lsect3 ) TEMPLATE(gribPrintSec3,T)(isec0, isec3, fsec3);
9581
9582 TEMPLATE(gribPrintSec4,T)(isec0, isec4, fsec4);
9583 // Special print for 2D spectra wave field real values in section 4
9584 if ( (isec1[ 0] == 140) &&
9585 (isec1[ 1] == 98) &&
9586 (isec1[23] == 1) &&
9587 ((isec1[39] == 1045) || (isec1[39] == 1081)) &&
9588 ((isec1[ 5] == 250) || (isec1[ 5] == 251)) )
9589 gribPrintSec4Wave(isec4);
9590 }
9591 }
9592 }
9593
9594 #endif /* T */
9595
9596 /*
9597 * Local Variables:
9598 * mode: c
9599 * End:
9600 */
9601
9602 #ifdef T
9603 #undef T
9604 #endif
9605 #define T float
9606 #ifdef T
9607
9608 static
TEMPLATE(decodeGDS,T)9609 int TEMPLATE(decodeGDS,T)(unsigned char *gds, int *isec0, int *isec2, T *fsec2, int *numGridVals)
9610 {
9611 // int imisng = 0;
9612 bool ReducedGrid = false, VertCoorTab = false;
9613 #ifdef VECTORCODE
9614 unsigned char *igrib;
9615 GRIBPACK *lgrib = NULL;
9616 size_t lGribLen = 0;
9617 #endif
9618
9619 *numGridVals = 0;
9620
9621 memset(isec2, 0, 22*sizeof(int));
9622
9623 const unsigned gdsLen = GDS_Len;
9624
9625 unsigned ipvpl = GDS_PVPL;
9626 if ( ipvpl == 0 ) ipvpl = 0xFF;
9627
9628 if ( ipvpl != 0xFF )
9629 { // Either vct or reduced grid
9630 if ( GDS_NV != 0 )
9631 { // we have vct
9632 VertCoorTab = true;
9633 const unsigned ipl = 4*GDS_NV + ipvpl - 1;
9634 if ( ipl < gdsLen ) ReducedGrid = true;
9635 }
9636 else
9637 {
9638 VertCoorTab = false;
9639 ReducedGrid = true;
9640 }
9641 // ReducedGrid = (gdsLen - 32 - 4*GDS_NV);
9642 }
9643
9644 if ( ISEC0_GRIB_Version == 0 ) VertCoorTab = ((gdsLen - 32) > 0);
9645
9646 if ( ReducedGrid )
9647 {
9648 const unsigned locnl = GDS_PVPL - 1 + (VertCoorTab * 4 * GDS_NV);
9649 const unsigned jlenl = (gdsLen - locnl) >> 1;
9650 if ( jlenl == GDS_NumLat )
9651 {
9652 *numGridVals = 0;
9653 ISEC2_Reduced = true;
9654 for ( unsigned i = 0; i < jlenl; i++ )
9655 {
9656 ISEC2_ReducedPoints(i) = GET_UINT2(gds[locnl+2*i], gds[locnl+2*i+1]);
9657 *numGridVals += ISEC2_ReducedPoints(i);
9658 }
9659 }
9660 else
9661 {
9662 ReducedGrid = false;
9663 }
9664 }
9665
9666 ISEC2_GridType = GDS_GridType;
9667
9668 // Gaussian grid definition.
9669
9670 if ( ISEC2_GridType == GRIB1_GTYPE_LATLON ||
9671 ISEC2_GridType == GRIB1_GTYPE_GAUSSIAN ||
9672 ISEC2_GridType == GRIB1_GTYPE_LATLON_ROT )
9673 {
9674 ISEC2_NumLat = GDS_NumLat;
9675 if ( ! ReducedGrid )
9676 {
9677 ISEC2_NumLon = GDS_NumLon;
9678 *numGridVals = ISEC2_NumLon*ISEC2_NumLat;
9679 }
9680 ISEC2_FirstLat = GDS_FirstLat;
9681 ISEC2_FirstLon = GDS_FirstLon;
9682 ISEC2_ResFlag = GDS_ResFlag;
9683 ISEC2_LastLat = GDS_LastLat;
9684 ISEC2_LastLon = GDS_LastLon;
9685 ISEC2_LonIncr = GDS_LonIncr;
9686
9687 ISEC2_NumPar = GDS_NumPar;
9688 ISEC2_ScanFlag = GDS_ScanFlag;
9689 if ( ISEC2_GridType == GRIB1_GTYPE_LATLON_ROT )
9690 {
9691 ISEC2_LatSP = GDS_LatSP;
9692 ISEC2_LonSP = GDS_LonSP;
9693 FSEC2_RotAngle = (T)GDS_RotAngle;
9694 }
9695 // if ( Lons != Longitudes || Lats != Latitudes ) Error("Latitude/Longitude Conflict");
9696 }
9697 else if ( ISEC2_GridType == GRIB1_GTYPE_GAUSSIAN ||
9698 ISEC2_GridType == GRIB1_GTYPE_GAUSSIAN_ROT ||
9699 ISEC2_GridType == GRIB1_GTYPE_GAUSSIAN_STR ||
9700 ISEC2_GridType == GRIB1_GTYPE_GAUSSIAN_ROTSTR )
9701 {
9702 // iret = decodeGDS_GG(gds, gdspos, isec0, isec2, imisng);
9703 }
9704 else if ( ISEC2_GridType == GRIB1_GTYPE_LATLON ||
9705 ISEC2_GridType == GRIB1_GTYPE_LATLON_ROT ||
9706 ISEC2_GridType == GRIB1_GTYPE_LATLON_STR ||
9707 ISEC2_GridType == GRIB1_GTYPE_LATLON_ROTSTR )
9708 {
9709 // iret = decodeGDS_LL(gds, gdspos, isec0, isec2, imisng);
9710 }
9711 else if ( ISEC2_GridType == GRIB1_GTYPE_LCC )
9712 {
9713 ISEC2_NumLon = GDS_NumLon;
9714 ISEC2_NumLat = GDS_NumLat;
9715 *numGridVals = ISEC2_NumLon*ISEC2_NumLat;
9716 ISEC2_FirstLat = GDS_FirstLat;
9717 ISEC2_FirstLon = GDS_FirstLon;
9718 ISEC2_ResFlag = GDS_ResFlag;
9719 ISEC2_Lambert_Lov = GDS_Lambert_Lov;
9720 ISEC2_Lambert_dx = GDS_Lambert_dx;
9721 ISEC2_Lambert_dy = GDS_Lambert_dy;
9722 ISEC2_Lambert_LatS1 = GDS_Lambert_LatS1;
9723 ISEC2_Lambert_LatS2 = GDS_Lambert_LatS2;
9724 ISEC2_Lambert_LatSP = GDS_Lambert_LatSP;
9725 ISEC2_Lambert_LonSP = GDS_Lambert_LonSP;
9726 ISEC2_Lambert_ProjFlag = GDS_Lambert_ProjFlag;
9727 ISEC2_ScanFlag = GDS_ScanFlag;
9728 }
9729 else if ( ISEC2_GridType == GRIB1_GTYPE_SPECTRAL )
9730 {
9731 ISEC2_PentaJ = GDS_PentaJ; // Truncation
9732 ISEC2_PentaK = GDS_PentaK;
9733 ISEC2_PentaM = GDS_PentaM;
9734 ISEC2_RepType = GDS_RepType;
9735 ISEC2_RepMode = GDS_RepMode;
9736 *numGridVals = (ISEC2_PentaJ+1)*(ISEC2_PentaJ+2);
9737 isec2[ 6] = 0;
9738 isec2[ 7] = 0;
9739 isec2[ 8] = 0;
9740 isec2[ 9] = 0;
9741 isec2[10] = 0;
9742 // iret = decodeGDS_SH(gds, gdspos, isec0, isec2, imisng);
9743 }
9744 else if ( ISEC2_GridType == GRIB1_GTYPE_GME )
9745 {
9746 ISEC2_GME_NI2 = GDS_GME_NI2;
9747 ISEC2_GME_NI3 = GDS_GME_NI3;
9748 ISEC2_GME_ND = GDS_GME_ND;
9749 ISEC2_GME_NI = GDS_GME_NI;
9750 ISEC2_GME_AFlag = GDS_GME_AFlag;
9751 ISEC2_GME_LatPP = GDS_GME_LatPP;
9752 ISEC2_GME_LonPP = GDS_GME_LonPP;
9753 ISEC2_GME_LonMPL = GDS_GME_LonMPL;
9754 ISEC2_GME_BFlag = GDS_GME_BFlag;
9755 *numGridVals = (ISEC2_GME_NI+1)*(ISEC2_GME_NI+1)*10;
9756 // iret = decodeGDS_TR(gds, gdspos, isec0, isec2, imisng);
9757 }
9758 else
9759 {
9760 static bool lwarn = true;
9761 ISEC2_NumLon = GDS_NumLon;
9762 ISEC2_NumLat = GDS_NumLat;
9763 *numGridVals = ISEC2_NumLon*ISEC2_NumLat;
9764 if ( lwarn )
9765 {
9766 lwarn = false;
9767 Message("GRIB gridtype %d unsupported", ISEC2_GridType);
9768 }
9769 }
9770
9771 // Vertical coordinate parameters for hybrid levels.
9772 // Get number of vertical coordinate parameters, if any.
9773
9774 ISEC2_NumVCP = 0;
9775
9776 isec2[17] = 0;
9777 isec2[18] = 0;
9778
9779 if ( VertCoorTab )
9780 {
9781 int locnv;
9782 if ( ISEC0_GRIB_Version == 0 )
9783 {
9784 locnv = 32;
9785 ISEC2_NumVCP = (gdsLen - 32) >> 2;
9786 }
9787 else
9788 {
9789 locnv = GDS_PVPL - 1;
9790 ISEC2_NumVCP = GDS_NV;
9791 }
9792 #if defined (SX)
9793 lGribLen = 4*ISEC2_NumVCP;
9794 lgrib = (GRIBPACK*) Malloc(lGribLen*sizeof(GRIBPACK));
9795
9796 igrib = &gds[locnv];
9797 if ( ISEC2_NumVCP > 0 ) (void) UNPACK_GRIB(igrib, lgrib, lGribLen, -1L);
9798 for ( int i = 0; i < ISEC2_NumVCP; i++ )
9799 {
9800 const int iexp = lgrib[4*i];
9801 const int imant = GET_UINT3(lgrib[4*i+1], lgrib[4*i+2], lgrib[4*i+3]);
9802 fsec2[10+i] = POW_2_M24 * imant * ldexp(1.0, 4 * (iexp - 64));
9803 }
9804
9805 Free(lgrib);
9806 #else
9807 for ( int i = 0; i < ISEC2_NumVCP; i++ )
9808 {
9809 const int iexp = gds[locnv+4*i];
9810 const int imant = GET_UINT3(gds[locnv+4*i+1], gds[locnv+4*i+2], gds[locnv+4*i+3]);
9811 fsec2[10+i] = (T)decfp2(iexp,imant);
9812 }
9813 #endif
9814 }
9815
9816 return gdsLen;
9817 }
9818
9819 #define ldexp_double ldexp
9820 #define ldexp_float ldexpf
9821 #define pow_double pow
9822 #define pow_float powf
9823
9824 static
TEMPLATE(decodeBDS,T)9825 void TEMPLATE(decodeBDS,T)(int decscale, unsigned char *bds, int *isec2, int *isec4,
9826 T *fsec4, int fsec4len, int dfunc, int bdsLen, int numGridVals, int *iret)
9827 {
9828 int ioff = 0;
9829 enum { bds_head = 11 };
9830 T zscale = 0.;
9831 T fmin = 0.;
9832 T *fpdata = fsec4;
9833
9834 *iret = 0;
9835 unsigned char *igrib = bds;
9836
9837 memset(isec4, 0, 42*sizeof(int));
9838
9839 // 4 bit flag / 4 bit count of unused bits at end of block octet.
9840
9841 const int bds_flag = BDS_Flag;
9842
9843 // 0------- grid point
9844 // 1------- spherical harmonics
9845
9846 const bool lspherc = (bds_flag >> 7)&1;
9847 if ( lspherc ) isec4[2] = 128;
9848 else isec4[2] = 0;
9849
9850 // -0------ simple packing
9851 // -1------ complex packing
9852
9853 const bool lcomplex = (bds_flag >> 6)&1;
9854 if ( lcomplex ) isec4[3] = 64;
9855 else isec4[3] = 0;
9856
9857 // ---0---- No additional flags
9858 // ---1---- No additional flags
9859
9860 const bool lcompress = (bds_flag >> 4)&1;
9861
9862 unsigned zoff;
9863 if ( lcompress )
9864 { isec4[5] = 16; isec4[6] = BDS_Z; zoff = 12; }
9865 else
9866 { isec4[5] = 0; isec4[6] = 0; zoff = 0; }
9867
9868 // ----++++ number of unused bits at end of section)
9869
9870 const int bds_ubits = bds_flag & 0xF;
9871
9872 // scale factor (2 bytes)
9873 const int jscale = BDS_BinScale;
9874
9875 // check for missing data indicators.
9876
9877 const int iexp = bds[ 6];
9878 const int imant = GET_UINT3(bds[ 7], bds[ 8], bds[ 9]);
9879
9880 const int imiss = (jscale == 0xFFFF && iexp == 0xFF && imant == 0xFFFFFF);
9881
9882 // convert reference value and scale factor.
9883
9884 if ( ! (dfunc == 'J') && imiss == 0 )
9885 {
9886 fmin = (T)BDS_RefValue;
9887 zscale = TEMPLATE(ldexp,T)((T)1.0, jscale);
9888 }
9889
9890 // get number of bits in each data value.
9891
9892 ISEC4_NumBits = BDS_NumBits;
9893
9894 // octet number of start of packed data calculated from start of block 4 - 1
9895
9896 unsigned locnd = zoff + bds_head;
9897
9898 // if data is in spherical harmonic form, distinguish between simple/complex packing (lcomplex = 0/1)
9899
9900 if ( lspherc )
9901 {
9902 if ( !lcomplex )
9903 {
9904 // no unpacked binary data present octet number of start of packed data
9905 // calculated from start of block 4 - 1
9906
9907 ioff = 1;
9908 locnd += 4*ioff; // RealCoef
9909
9910 // get real (0,0) coefficient in grib format and convert to floating point.
9911 if ( dfunc != 'J' )
9912 {
9913 if ( imiss ) *fpdata++ = 0.0;
9914 else *fpdata++ = (T)BDS_RealCoef;
9915 }
9916 }
9917 else // complex packed spherical harmonics
9918 {
9919 isec4[15] = BDS_PackData;
9920 // scaling factor
9921 isec4[16] = BDS_Power;
9922
9923 // pentagonal resolution parameters of the unpacked section of data field
9924
9925 const int jup = bds[zoff+15];
9926 const int kup = bds[zoff+16];
9927 const int mup = bds[zoff+17];
9928
9929 isec4[zoff+17] = jup;
9930 isec4[zoff+18] = kup;
9931 isec4[zoff+19] = mup;
9932
9933 // unpacked binary data
9934
9935 locnd += 4; // 2 + power
9936 locnd += 3; // j, k, m
9937 ioff = (jup+1)*(jup+2);
9938
9939 if ( dfunc != 'J' )
9940 for ( int i = 0; i < ioff; i++ )
9941 {
9942 if ( imiss )
9943 *fpdata++ = 0.0;
9944 else
9945 {
9946 const int iexp2 = (bds[locnd+4*i]);
9947 const int imant2 = GET_UINT3(bds[locnd+4*i+1], bds[locnd+4*i+2], bds[locnd+4*i+3]);
9948 *fpdata++ = (T)decfp2(iexp2,imant2);
9949 }
9950 }
9951
9952 locnd += 4*ioff; /* RealCoef */
9953 }
9954 }
9955 else
9956 {
9957 if ( lcomplex )
9958 {
9959 *iret = 1999;
9960 gprintf(__func__, " Second order packed grids unsupported!");
9961 gprintf(__func__, " Return code = %d", *iret);
9962 return;
9963 }
9964 }
9965
9966 // Decode data values to floating point and store in fsec4.
9967 // First calculate the number of data values.
9968 // Take into account that spherical harmonics can be packed
9969 // simple (lcomplex = 0) or complex (lcomplex = 1)
9970
9971 int jlend = bdsLen - locnd;
9972
9973 if ( ISEC4_NumBits == 0 )
9974 {
9975 if ( jlend > 1 )
9976 {
9977 *iret = 2001;
9978 gprintf(__func__, " Number of bits per data value = 0!");
9979 gprintf(__func__, " Return code = %d", *iret);
9980 return;
9981 }
9982
9983 if ( numGridVals == 0 )
9984 {
9985 *iret = 2002;
9986 gprintf(__func__, " Constant field unsupported for this grid type!");
9987 gprintf(__func__, " Return code = %d", *iret);
9988 return;
9989 }
9990
9991 jlend = numGridVals;
9992 jlend -= ioff;
9993 }
9994 else
9995 {
9996 jlend = (int) (((long)jlend*8 - bds_ubits) / ISEC4_NumBits);
9997 }
9998
9999 ISEC4_NumValues = jlend + ioff;
10000 ISEC4_NumNonMissValues = 0;
10001
10002 if ( lcompress )
10003 {
10004 const size_t len = ((size_t) ((bds[17]<<16)+(bds[18]<<8)+bds[19]));
10005
10006 ISEC4_NumValues = (int)(len*8/(size_t)ISEC4_NumBits);
10007
10008 if ( lspherc ) ISEC4_NumValues += lcomplex ? ioff : 1;
10009 }
10010
10011 if ( dfunc == 'J' ) return;
10012
10013 // check length of output array.
10014
10015 if ( ISEC4_NumValues > fsec4len )
10016 {
10017 *iret = 710;
10018 gprintf(__func__, " Output array too small. Length = %d", fsec4len);
10019 gprintf(__func__, " Number of values = %d", ISEC4_NumValues);
10020 gprintf(__func__, " Return code = %d", *iret);
10021 return;
10022 }
10023
10024 if ( imiss ) memset((char *)fpdata, 0, (size_t)jlend*sizeof(T));
10025 else
10026 {
10027 igrib += locnd;
10028
10029 TEMPLATE(decode_array,T)(igrib, jlend, ISEC4_NumBits, fmin, zscale, fpdata);
10030 }
10031
10032 if ( lspherc && lcomplex )
10033 {
10034 int pcStart = isec4[19], pcScale = isec4[16];
10035 TEMPLATE(scatter_complex,T)(fsec4, pcStart, ISEC2_PentaJ, ISEC4_NumValues);
10036 TEMPLATE(scale_complex,T)(fsec4, pcStart, pcScale, ISEC2_PentaJ, 1);
10037 }
10038
10039 if ( CGRIBEX_Fix_ZSE ) // Fix ZeroShiftError of simple packed spherical harmonics
10040 if ( lspherc && !lcomplex )
10041 {
10042 // 20100705: Fix ZeroShiftError - Edi Kirk
10043 if ( IS_NOT_EQUAL(fsec4[1], 0.0) )
10044 {
10045 const T zserr = fsec4[1];
10046 for ( int i = 1; i < ISEC4_NumValues; i++ ) fsec4[i] -= zserr;
10047 }
10048 }
10049
10050 if ( decscale )
10051 {
10052 const T scale = TEMPLATE(pow,T)((T)10.0, (T)-decscale);
10053 for ( int i = 0; i < ISEC4_NumValues; i++ ) fsec4[i] *= scale;
10054 }
10055 }
10056
10057
TEMPLATE(grib_decode,T)10058 void TEMPLATE(grib_decode,T)(int *isec0, int *isec1, int *isec2, T *fsec2, int *isec3,
10059 T *fsec3, int *isec4, T *fsec4, int fsec4len, int *kgrib,
10060 int kleng, int *kword, int dfunc, int *iret)
10061 {
10062 UCHAR *bms = NULL;
10063 bool lsect2 = false, lsect3 = false;
10064 static bool lmissvalinfo = true;
10065
10066 UNUSED(kleng);
10067
10068 *iret = 0;
10069
10070 grsdef();
10071
10072 ISEC2_Reduced = false;
10073
10074 // ----------------------------------------------------------------
10075 // IS Indicator Section (Section 0)
10076 // ----------------------------------------------------------------
10077 UCHAR *is = (UCHAR *) &kgrib[0];
10078 int isLen = decodeIS(is, isec0, iret);
10079
10080 int gribLen = ISEC0_GRIB_Len;
10081
10082 /*
10083 When decoding or calculating length, previous editions
10084 of the GRIB code must be taken into account.
10085
10086 In the table below, covering sections 0 and 1 of the GRIB
10087 code, octet numbering is from the beginning of the GRIB
10088 message;
10089 * indicates that the value is not available in the code edition;
10090 R indicates reserved, should be set to 0;
10091 Experimental edition is considered as edition -1.
10092
10093 GRIB code edition -1 has fixed length of 20 octets for
10094 section 1, the length not included in the message.
10095 GRIB code edition 0 has fixed length of 24 octets for
10096 section 1, the length being included in the message.
10097 GRIB code edition 1 can have different lengths for section
10098 1, the minimum being 28 octets, length being included in
10099 the message.
10100
10101 Octet numbers for code
10102 editions
10103
10104 Contents. -1 0 1
10105 --------- ----------------------
10106 Letters GRIB 1-4 1-4 1-4
10107 Total length of GRIB message. * * 5-7
10108 GRIB code edition number * * 8
10109 Length of Section 1. * 5-7 9-11
10110 Reserved octet (R). * 8(R) *
10111 Version no. of Code Table 2. * * 12
10112 Identification of centre. 5 9 13
10113 Generating process. 6 10 14
10114 Grid definition . 7 11 15
10115 Flag (Code Table 1). 8 12 16
10116 Indicator of parameter. 9 13 17
10117 Indicator of type of level. 10 14 18
10118 Height, pressure etc of levels. 11-12 15-16 19-20
10119 Year of century. 13 17 21
10120 Month. 14 18 22
10121 Day. 15 19 23
10122 Hour. 16 20 24
10123 Minute. 17 21 25
10124 Indicator of unit of time. 18 22 26
10125 P1 - Period of time. 19 23 27
10126 P2 - Period of time 20(R) 24 28
10127 or reserved octet (R).
10128 Time range indicator. 21(R) 25 29
10129 or reserved octet (R).
10130 Number included in average. 22-23(R) 26-27 30-31
10131 or reserved octet (R).
10132 Number missing from average. 24(R) 28(R) 32
10133 or reserved octet (R).
10134 Century of data. * * 33
10135 Designates sub-centre if not 0. * * 34
10136 Decimal scale factor. * * 35-36
10137 Reserved. Set to 0. * * 37-48
10138 (Need not be present)
10139 For originating centre use only. * * 49-nn
10140 (Need not be present)
10141
10142 Identify which GRIB code edition is being decoded.
10143
10144 In GRIB edition 1, the edition number is in octet 8.
10145 In GRIB edition 0, octet 8 is reserved and set to 0.
10146 In GRIB edition -1, octet 8 is a flag field and can have a
10147 a valid value of 0, 1, 2 or 3.
10148
10149 However, GRIB edition number 0 has a fixed
10150 length of 24, included in the message, for section 1, so
10151 if the value extracted from octets 5-7 is 24 and that from
10152 octet 8 is 0, it is safe to assume edition 0 of the code.
10153
10154 */
10155
10156 // Set length of GRIB message to missing data value.
10157 if ( ISEC0_GRIB_Len == 24 && ISEC0_GRIB_Version == 0 ) ISEC0_GRIB_Len = 0;
10158
10159 // ----------------------------------------------------------------
10160 // PDS Product Definition Section (Section 1)
10161 // ----------------------------------------------------------------
10162 UCHAR *pds = is + isLen;
10163 int pdsLen = decodePDS(pds, isec0, isec1);
10164
10165 // ----------------------------------------------------------------
10166 // GDS Grid Description Section (Section 2)
10167 // ----------------------------------------------------------------
10168 int numGridVals = 0;
10169 int gdsLen = 0;
10170 const bool gdsIncluded = ISEC1_Sec2Or3Flag & 128;
10171 if ( gdsIncluded )
10172 {
10173 UCHAR *gds = is + isLen + pdsLen;
10174 gdsLen = TEMPLATE(decodeGDS,T)(gds, isec0, isec2, fsec2, &numGridVals);
10175 }
10176
10177 // ----------------------------------------------------------------
10178 // BMS Bit-Map Section Section (Section 3)
10179 // ----------------------------------------------------------------
10180 isec3[0] = 0;
10181 int bmsLen = 0, bitmapSize = 0, imaskSize = 0;
10182 const bool bmsIncluded = ISEC1_Sec2Or3Flag & 64;
10183 if ( bmsIncluded )
10184 {
10185 bms = is + isLen + pdsLen + gdsLen;
10186 bmsLen = BMS_Len;
10187
10188 imaskSize = (bmsLen > 6) ? (bmsLen - 6)<<3 : 0;
10189 bitmapSize = imaskSize - BMS_UnusedBits;
10190 }
10191
10192 // ----------------------------------------------------------------
10193 // BDS Binary Data Section (Section 4)
10194 // ----------------------------------------------------------------
10195 UCHAR *bds = is + isLen + pdsLen + gdsLen + bmsLen;
10196 int bdsLen = BDS_Len;
10197 /*
10198 If a very large product, the section 4 length field holds
10199 the number of bytes in the product after section 4 upto
10200 the end of the padding bytes.
10201 This is a fixup to get round the restriction on product lengths
10202 due to the count being only 24 bits. It is only possible because
10203 the (default) rounding for GRIB products is 120 bytes.
10204 */
10205 const bool llarge = (gribLen > JP23SET && bdsLen <= 120);
10206 if ( llarge )
10207 {
10208 gribLen &= JP23SET;
10209 gribLen *= 120;
10210 ISEC0_GRIB_Len = gribLen;
10211 bdsLen = correct_bdslen(bdsLen, gribLen, isLen+pdsLen+gdsLen+bmsLen);
10212 }
10213
10214 TEMPLATE(decodeBDS,T)(ISEC1_DecScaleFactor, bds, isec2, isec4, fsec4, fsec4len, dfunc, bdsLen, numGridVals, iret);
10215
10216 if ( *iret != 0 ) return;
10217
10218 ISEC4_NumNonMissValues = ISEC4_NumValues;
10219
10220 if ( bitmapSize > 0 )
10221 {
10222 if ( dfunc != 'L' && dfunc != 'J' )
10223 if ( DBL_IS_NAN(FSEC3_MissVal) && lmissvalinfo )
10224 {
10225 lmissvalinfo = false;
10226 FSEC3_MissVal = (T)GRIB_MISSVAL;
10227 Message("Missing value = NaN is unsupported, set to %g!", GRIB_MISSVAL);
10228 }
10229
10230 // ISEC4_NumNonMissValues = ISEC4_NumValues;
10231 ISEC4_NumValues = bitmapSize;
10232
10233 if ( dfunc != 'J' || bitmapSize == ISEC4_NumNonMissValues )
10234 {
10235 GRIBPACK bitmap;
10236 /*
10237 unsigned char *bitmap;
10238 bitmap = BMS_Bitmap;
10239 int j = ISEC4_NumNonMissValues;
10240 for ( int i = ISEC4_NumValues-1; i >= 0; i-- )
10241 {
10242 fsec4[i] = ((bitmap[i/8]>>(7-(i&7)))&1) ? fsec4[--j] : FSEC3_MissVal;
10243 }
10244 */
10245
10246 GRIBPACK *imask = (GRIBPACK*) Malloc((size_t)imaskSize*sizeof(GRIBPACK));
10247
10248 #ifdef VECTORCODE
10249 (void) UNPACK_GRIB(BMS_Bitmap, imask, imaskSize/8, -1L);
10250 GRIBPACK *pbitmap = imask;
10251 #else
10252 GRIBPACK *pbitmap = BMS_Bitmap;
10253 #endif
10254
10255 #if defined (CRAY)
10256 #pragma _CRI ivdep
10257 #endif
10258 #if defined (SX)
10259 #pragma vdir nodep
10260 #endif
10261 #ifdef __uxpch__
10262 #pragma loop novrec
10263 #endif
10264 for ( int i = imaskSize/8-1; i >= 0; i-- )
10265 {
10266 bitmap = pbitmap[i];
10267 imask[i*8+0] = 1 & (bitmap >> 7);
10268 imask[i*8+1] = 1 & (bitmap >> 6);
10269 imask[i*8+2] = 1 & (bitmap >> 5);
10270 imask[i*8+3] = 1 & (bitmap >> 4);
10271 imask[i*8+4] = 1 & (bitmap >> 3);
10272 imask[i*8+5] = 1 & (bitmap >> 2);
10273 imask[i*8+6] = 1 & (bitmap >> 1);
10274 imask[i*8+7] = 1 & (bitmap);
10275 }
10276
10277 int j = 0;
10278 for ( int i = 0; i < ISEC4_NumValues; i++ )
10279 if ( imask[i] ) j++;
10280
10281 if ( ISEC4_NumNonMissValues != j )
10282 {
10283 if ( dfunc != 'J' && ISEC4_NumBits != 0 )
10284 Warning("Bitmap (%d) and data (%d) section differ, using bitmap section!", j, ISEC4_NumNonMissValues);
10285
10286 ISEC4_NumNonMissValues = j;
10287 }
10288
10289 if ( dfunc != 'J' )
10290 {
10291 #if defined (CRAY)
10292 #pragma _CRI ivdep
10293 #endif
10294 #if defined (SX)
10295 #pragma vdir nodep
10296 #endif
10297 #ifdef __uxpch__
10298 #pragma loop novrec
10299 #endif
10300 for ( int i = ISEC4_NumValues-1; i >= 0; i-- )
10301 fsec4[i] = imask[i] ? fsec4[--j] : FSEC3_MissVal;
10302 }
10303
10304 Free(imask);
10305 }
10306 }
10307
10308 if ( ISEC2_Reduced )
10309 {
10310 int nvalues = 0;
10311 int nlat = ISEC2_NumLat;
10312 int nlon = ISEC2_ReducedPointsPtr[0];
10313 for ( int ilat = 0; ilat < nlat; ++ilat ) nvalues += ISEC2_ReducedPoints(ilat);
10314 for ( int ilat = 1; ilat < nlat; ++ilat )
10315 if ( ISEC2_ReducedPoints(ilat) > nlon ) nlon = ISEC2_ReducedPoints(ilat);
10316
10317 // int dlon = ISEC2_LastLon-ISEC2_FirstLon;
10318 // if ( dlon < 0 ) dlon += 360000;
10319
10320 if ( nvalues != ISEC4_NumValues ) *iret = -801;
10321
10322 //printf("nlat %d nlon %d \n", nlat, nlon);
10323 //printf("nvalues %d %d\n", nvalues, ISEC4_NumValues);
10324
10325 if ( dfunc == 'R' && *iret == -801 )
10326 gprintf(__func__, "Number of values (%d) and sum of lons per row (%d) differ, abort conversion to regular Gaussian grid!",
10327 ISEC4_NumValues, nvalues);
10328
10329 if ( dfunc == 'R' && *iret != -801 )
10330 {
10331 ISEC2_Reduced = 0;
10332 ISEC2_NumLon = nlon;
10333 ISEC4_NumValues = nlon*nlat;
10334
10335 lsect3 = bitmapSize > 0;
10336 int lperio = 1;
10337 int lveggy = (ISEC1_CodeTable == 128) && (ISEC1_CenterID == 98) &&
10338 ((ISEC1_Parameter == 27) || (ISEC1_Parameter == 28) ||
10339 (ISEC1_Parameter == 29) || (ISEC1_Parameter == 30) ||
10340 (ISEC1_Parameter == 39) || (ISEC1_Parameter == 40) ||
10341 (ISEC1_Parameter == 41) || (ISEC1_Parameter == 42) ||
10342 (ISEC1_Parameter == 43));
10343
10344 (void) TEMPLATE(qu2reg3,T)(fsec4, ISEC2_ReducedPointsPtr, nlat, nlon, FSEC3_MissVal, iret, lsect3, lperio, lveggy);
10345
10346 if ( bitmapSize > 0 )
10347 {
10348 int j = 0;
10349 for ( int i = 0; i < ISEC4_NumValues; i++ )
10350 if ( IS_NOT_EQUAL(fsec4[i], FSEC3_MissVal) ) j++;
10351
10352 ISEC4_NumNonMissValues = j;
10353 }
10354 }
10355 }
10356
10357 if ( ISEC0_GRIB_Version == 1 ) isLen = 8;
10358 const int esLen = 4;
10359 gribLen = isLen + pdsLen + gdsLen + bmsLen + bdsLen + esLen;
10360
10361 if ( !llarge && ISEC0_GRIB_Len && ISEC0_GRIB_Len < gribLen )
10362 Warning("Inconsistent length of GRIB message (grib_message_size=%d < grib_record_size=%d)!", ISEC0_GRIB_Len, gribLen);
10363
10364 ISEC0_GRIB_Len = gribLen;
10365
10366 *kword = (int)(((size_t)gribLen + sizeof(int) - 1) / sizeof(int));
10367
10368 // ----------------------------------------------------------------
10369 // Section 9 . Abort/return to calling routine.
10370 // ----------------------------------------------------------------
10371 bool ldebug = false, l_iorj = false;
10372 if ( ldebug )
10373 {
10374 gprintf(__func__, "Section 9.");
10375 gprintf(__func__, "Output values set -");
10376
10377 gribPrintSec0(isec0);
10378 gribPrintSec1(isec0, isec1);
10379 // Print section 2 if present.
10380 if ( lsect2 ) TEMPLATE(gribPrintSec2,T)(isec0, isec2, fsec2);
10381
10382 if ( ! l_iorj )
10383 {
10384 // Print section 3 if present.
10385 if ( lsect3 ) TEMPLATE(gribPrintSec3,T)(isec0, isec3, fsec3);
10386
10387 TEMPLATE(gribPrintSec4,T)(isec0, isec4, fsec4);
10388 // Special print for 2D spectra wave field real values in section 4
10389 if ( (isec1[ 0] == 140) &&
10390 (isec1[ 1] == 98) &&
10391 (isec1[23] == 1) &&
10392 ((isec1[39] == 1045) || (isec1[39] == 1081)) &&
10393 ((isec1[ 5] == 250) || (isec1[ 5] == 251)) )
10394 gribPrintSec4Wave(isec4);
10395 }
10396 }
10397 }
10398
10399 #endif /* T */
10400
10401 /*
10402 * Local Variables:
10403 * mode: c
10404 * End:
10405 */
10406
10407 /* GRIB block 0 - indicator block */
10408 static
encodeIS(GRIBPACK * lGrib,long * gribLen)10409 void encodeIS(GRIBPACK *lGrib, long *gribLen)
10410 {
10411 long z;
10412 // z = *gribLen;
10413
10414 lGrib[0] = 'G';
10415 lGrib[1] = 'R';
10416 lGrib[2] = 'I';
10417 lGrib[3] = 'B';
10418
10419 // lGrib[4]-lGrib[6] contains full length of grib record.
10420 // included before finished CODEGB
10421
10422 z = 7;
10423 Put1Byte(1); /* grib version */
10424 z = 8;
10425
10426 *gribLen = z;
10427 }
10428
10429 /* GRIB block 5 - end block */
10430 static
encodeES(GRIBPACK * lGrib,long * gribLen,long bdsstart)10431 void encodeES(GRIBPACK *lGrib, long *gribLen, long bdsstart)
10432 {
10433 long z = *gribLen;
10434
10435 lGrib[z++] = '7';
10436 lGrib[z++] = '7';
10437 lGrib[z++] = '7';
10438 lGrib[z++] = '7';
10439
10440 if ( z > JP24SET )
10441 {
10442 long bdslen = z - 4;
10443 // fprintf(stderr, "Abort: GRIB record too large (max = %d)!\n", JP23SET);
10444 // exit(1);
10445 /*
10446 If a very large product, the section 4 length field holds
10447 the number of bytes in the product after section 4 upto
10448 the end of the padding bytes.
10449 This is a fixup to get round the restriction on product lengths
10450 due to the count being only 24 bits. It is only possible because
10451 the (default) rounding for GRIB products is 120 bytes.
10452 */
10453 while ( z%120 ) lGrib[z++] = 0;
10454
10455 if ( z > JP23SET*120 )
10456 {
10457 fprintf(stderr, "Abort: GRIB1 record too large (size = %ld; max = %d)!\n", z, JP23SET*120);
10458 exit(1);
10459 }
10460
10461 long itemp = z / (-120);
10462 itemp = JP23SET - itemp + 1;
10463
10464 lGrib[4] = (GRIBPACK)(itemp >> 16);
10465 lGrib[5] = (GRIBPACK)(itemp >> 8);
10466 lGrib[6] = (GRIBPACK)itemp;
10467
10468 bdslen = z - bdslen;
10469 lGrib[bdsstart ] = (GRIBPACK)(bdslen >> 16);
10470 lGrib[bdsstart+1] = (GRIBPACK)(bdslen >> 8);
10471 lGrib[bdsstart+2] = (GRIBPACK)bdslen;
10472 }
10473 else
10474 {
10475 lGrib[4] = (GRIBPACK)(z >> 16);
10476 lGrib[5] = (GRIBPACK)(z >> 8);
10477 lGrib[6] = (GRIBPACK)z;
10478
10479 while ( z%8 ) lGrib[z++] = 0;
10480 }
10481
10482 *gribLen = z;
10483 }
10484
10485 /* GRIB block 1 - product definition block. */
10486
10487 #define DWD_extension_253_len 38
10488 #define DWD_extension_254_len 26
10489 #define ECMWF_extension_1_len 24
10490 #define MPIM_extension_1_len 18
10491
10492 static
getLocalExtLen(int * isec1)10493 long getLocalExtLen(int *isec1)
10494 {
10495 long extlen = 0;
10496
10497 if ( ISEC1_LocalFLag )
10498 {
10499 if ( ISEC1_CenterID == 78 || ISEC1_CenterID == 215 || ISEC1_CenterID == 250 )
10500 {
10501 if ( isec1[36] == 254 ) extlen = DWD_extension_254_len;
10502 else if ( isec1[36] == 253 ) extlen = DWD_extension_253_len;
10503 }
10504 else if ( ISEC1_CenterID == 98 )
10505 {
10506 if ( isec1[36] == 1 ) extlen = ECMWF_extension_1_len;
10507 }
10508 else if ( ISEC1_CenterID == 252 )
10509 {
10510 if ( isec1[36] == 1 ) extlen = MPIM_extension_1_len;
10511 }
10512 }
10513
10514 return extlen;
10515 }
10516
10517 static
getPdsLen(int * isec1)10518 long getPdsLen(int *isec1)
10519 {
10520 long pdslen = 28;
10521
10522 pdslen += getLocalExtLen(isec1);
10523
10524 return pdslen;
10525 }
10526
10527 static
encodePDS_DWD_local_Extension_254(GRIBPACK * lGrib,long * zs,int * isec1)10528 void encodePDS_DWD_local_Extension_254(GRIBPACK *lGrib, long *zs, int *isec1)
10529 {
10530 long z = *zs;
10531
10532 long localextlen = getLocalExtLen(isec1);
10533 for ( long i = 0; i < localextlen-2; i++ ) Put1Byte(isec1[24+i]);
10534
10535 int isvn = isec1[49] << 15 | isec1[48]; /* DWD experiment identifier */
10536 Put2Byte(isvn); /* DWD run type (0=main, 2=ass, 3=test) */
10537
10538 *zs = z;
10539 }
10540
10541 static
encodePDS_DWD_local_Extension_253(GRIBPACK * lGrib,long * zs,int * isec1)10542 void encodePDS_DWD_local_Extension_253(GRIBPACK *lGrib, long *zs, int *isec1)
10543 {
10544 long z = *zs;
10545
10546 long localextlen = DWD_extension_254_len;
10547 for ( long i = 0; i < localextlen-2; i++ ) Put1Byte(isec1[24+i]);
10548
10549 int isvn = isec1[49] << 15 | isec1[48]; /* DWD experiment identifier */
10550 Put2Byte(isvn); /* DWD run type (0=main, 2=ass, 3=test) */
10551 Put1Byte(isec1[50]); /* 55 User id, specified by table */
10552 Put2Byte(isec1[51]); /* 56 Experiment identifier */
10553 Put2Byte(isec1[52]); /* 58 Ensemble identification by table */
10554 Put2Byte(isec1[53]); /* 60 Number of ensemble members */
10555 Put2Byte(isec1[54]); /* 62 Actual number of ensemble member */
10556 Put1Byte(isec1[55]); /* 64 Model major version number */
10557 Put1Byte(isec1[56]); /* 65 Model minor version number */
10558 Put1Byte(0); /* 66 Blank for even buffer length */
10559
10560 *zs = z;
10561 }
10562
10563 static
encodePDS_ECMWF_local_Extension_1(GRIBPACK * lGrib,long * zs,int * isec1)10564 void encodePDS_ECMWF_local_Extension_1(GRIBPACK *lGrib, long *zs, int *isec1)
10565 {
10566 long z = *zs;
10567
10568 long localextlen = getLocalExtLen(isec1);
10569 for ( long i = 0; i < localextlen-12; i++ ) Put1Byte(isec1[24+i]);
10570 /* 12 bytes explicitly encoded below: */
10571 Put1Byte(isec1[36]); /* ECMWF local GRIB use definition identifier */
10572 /* 1=MARS labelling or ensemble fcst. data */
10573 Put1Byte(isec1[37]); /* Class */
10574 Put1Byte(isec1[38]); /* Type */
10575 Put2Byte(isec1[39]); /* Stream */
10576
10577 /* Version number or experiment identifier */
10578 Put1Byte(((unsigned char*) &isec1[40])[0]);
10579 Put1Byte(((unsigned char*) &isec1[40])[1]);
10580 Put1Byte(((unsigned char*) &isec1[40])[2]);
10581 Put1Byte(((unsigned char*) &isec1[40])[3]);
10582
10583 Put1Byte(isec1[41]); /* Ensemble forecast number */
10584 Put1Byte(isec1[42]); /* Total number of forecasts in ensemble */
10585 Put1Byte(0); /* (Spare) */
10586
10587 *zs = z;
10588 }
10589
10590 static
encodePDS_MPIM_local_Extension_1(GRIBPACK * lGrib,long * zs,int * isec1)10591 void encodePDS_MPIM_local_Extension_1(GRIBPACK *lGrib, long *zs, int *isec1)
10592 {
10593 long z = *zs;
10594
10595 long localextlen = getLocalExtLen(isec1);
10596 for ( long i = 0; i < localextlen-6; i++ ) Put1Byte(isec1[24+i]);
10597 /* 6 bytes explicitly encoded below: */
10598 Put1Byte(isec1[36]); /* MPIM local GRIB use definition identifier */
10599 /* (extension identifier) */
10600 Put1Byte(isec1[37]); /* type of ensemble forecast */
10601 Put2Byte(isec1[38]); /* individual ensemble member */
10602 Put2Byte(isec1[39]); /* number of forecasts in ensemble */
10603
10604 *zs = z;
10605 }
10606
10607 /* GRIB BLOCK 1 - PRODUCT DESCRIPTION SECTION */
10608 static
encodePDS(GRIBPACK * lpds,long pdsLen,int * isec1)10609 void encodePDS(GRIBPACK *lpds, long pdsLen, int *isec1)
10610 {
10611 GRIBPACK *lGrib = lpds;
10612 long z = 0;
10613 int ival;
10614
10615 int century = ISEC1_Century;
10616 int year = ISEC1_Year;
10617
10618 if ( century < 0 )
10619 {
10620 century = -century;
10621 year = -year;
10622 }
10623
10624 Put3Byte(pdsLen); /* 0 Length of Block 1 */
10625 Put1Byte(ISEC1_CodeTable); /* 3 Local table number */
10626 Put1Byte(ISEC1_CenterID); /* 4 Identification of centre */
10627 Put1Byte(ISEC1_ModelID); /* 5 Identification of model */
10628 Put1Byte(ISEC1_GridDefinition); /* 6 Grid definition */
10629 Put1Byte(ISEC1_Sec2Or3Flag); /* 7 Block 2 included */
10630 Put1Byte(ISEC1_Parameter); /* 8 Parameter Code */
10631 Put1Byte(ISEC1_LevelType); /* 9 Type of level */
10632 if ( (ISEC1_LevelType != 20) &&
10633 (ISEC1_LevelType != GRIB1_LTYPE_99) &&
10634 (ISEC1_LevelType != GRIB1_LTYPE_ISOBARIC) &&
10635 (ISEC1_LevelType != GRIB1_LTYPE_ISOBARIC_PA) &&
10636 (ISEC1_LevelType != GRIB1_LTYPE_ALTITUDE) &&
10637 (ISEC1_LevelType != GRIB1_LTYPE_HEIGHT) &&
10638 (ISEC1_LevelType != GRIB1_LTYPE_SIGMA) &&
10639 (ISEC1_LevelType != GRIB1_LTYPE_HYBRID) &&
10640 (ISEC1_LevelType != GRIB1_LTYPE_LANDDEPTH) &&
10641 (ISEC1_LevelType != GRIB1_LTYPE_ISENTROPIC) &&
10642 (ISEC1_LevelType != 115) &&
10643 (ISEC1_LevelType != 117) &&
10644 (ISEC1_LevelType != 125) &&
10645 (ISEC1_LevelType != 127) &&
10646 (ISEC1_LevelType != 160) &&
10647 (ISEC1_LevelType != 210) )
10648 {
10649 Put1Byte(ISEC1_Level1);
10650 Put1Byte(ISEC1_Level2);
10651 }
10652 else
10653 {
10654 Put2Byte(ISEC1_Level1); /* 10 Level */
10655 }
10656
10657 Put1Int(year); /* 12 Year of Century */
10658 Put1Byte(ISEC1_Month); /* 13 Month */
10659 Put1Byte(ISEC1_Day); /* 14 Day */
10660 Put1Byte(ISEC1_Hour); /* 15 Hour */
10661 Put1Byte(ISEC1_Minute); /* 16 Minute */
10662
10663 Put1Byte(ISEC1_TimeUnit); /* 17 Time unit */
10664 if ( ISEC1_TimeRange == 10 )
10665 {
10666 Put1Byte(ISEC1_TimePeriod1);
10667 Put1Byte(ISEC1_TimePeriod2);
10668 }
10669 else if ( ISEC1_TimeRange == 113 || ISEC1_TimeRange == 0 )
10670 {
10671 Put1Byte(ISEC1_TimePeriod1);
10672 Put1Byte(0);
10673 }
10674 else if ( ISEC1_TimeRange == 5 || ISEC1_TimeRange == 4 ||
10675 ISEC1_TimeRange == 3 || ISEC1_TimeRange == 2 )
10676 {
10677 Put1Byte(ISEC1_TimePeriod1);
10678 Put1Byte(ISEC1_TimePeriod2);
10679 }
10680 else
10681 {
10682 Put1Byte(0);
10683 Put1Byte(0);
10684 }
10685 Put1Byte(ISEC1_TimeRange); /* 20 Timerange flag */
10686 Put2Byte(ISEC1_AvgNum); /* 21 Average */
10687
10688 Put1Byte(ISEC1_AvgMiss); /* 23 Missing from averages */
10689 Put1Byte(century); /* 24 Century */
10690 Put1Byte(ISEC1_SubCenterID); /* 25 Subcenter */
10691 Put2Int(ISEC1_DecScaleFactor); /* 26 Decimal scale factor */
10692
10693 if ( ISEC1_LocalFLag )
10694 {
10695 if ( ISEC1_CenterID == 78 || ISEC1_CenterID == 215 || ISEC1_CenterID == 250 )
10696 {
10697 if ( isec1[36] == 254 ) encodePDS_DWD_local_Extension_254(lGrib, &z, isec1);
10698 else if ( isec1[36] == 253 ) encodePDS_DWD_local_Extension_253(lGrib, &z, isec1);
10699 }
10700 else if ( ISEC1_CenterID == 98 )
10701 {
10702 if ( isec1[36] == 1 ) encodePDS_ECMWF_local_Extension_1(lGrib, &z, isec1);
10703 }
10704 else if ( ISEC1_CenterID == 252 )
10705 {
10706 if ( isec1[36] == 1 ) encodePDS_MPIM_local_Extension_1(lGrib, &z, isec1);
10707 }
10708 else
10709 {
10710 long i, localextlen;
10711 localextlen = getLocalExtLen(isec1);
10712 for ( i = 0; i < localextlen; i++ )
10713 {
10714 Put1Byte(isec1[24+i]);
10715 }
10716 }
10717 }
10718 }
10719
10720
10721
10722
10723 #ifdef T
10724 #undef T
10725 #endif
10726 #define T double
10727 #ifdef T
10728
10729
10730 #define round_float roundf
10731 #define round_double round
10732
10733 #if 0
10734 #define CGRIBEX_FPSCALE(data) (TEMPLATE(round,T)(((data) - zref) * factor))
10735 #else
10736 #define CGRIBEX_FPSCALE(data) (((data) - zref) * factor + (T)0.5)
10737 #endif
10738
10739 static
TEMPLATE(encode_array_common,T)10740 void TEMPLATE(encode_array_common,T)(int numBits, size_t packStart, size_t datasize, GRIBPACK *lGrib,
10741 const T *data, T zref, T factor, size_t *gz)
10742 {
10743 size_t z = *gz;
10744 unsigned int ival;
10745 int cbits, jbits;
10746 unsigned int c;
10747
10748 /* code from gribw routine flist2bitstream */
10749
10750 cbits = 8;
10751 c = 0;
10752 for (size_t i = packStart; i < datasize; i++)
10753 {
10754 /* note float -> unsigned int .. truncate */
10755 ival = (unsigned int)(CGRIBEX_FPSCALE(data[i]));
10756 /*
10757 if ( ival > max_nbpv_pow2 ) ival = max_nbpv_pow2;
10758 if ( ival < 0 ) ival = 0;
10759 */
10760 jbits = numBits;
10761 while ( cbits <= jbits )
10762 {
10763 if ( cbits == 8 )
10764 {
10765 jbits -= 8;
10766 lGrib[z++] = (ival >> jbits) & 0xFF;
10767 }
10768 else
10769 {
10770 jbits -= cbits;
10771 lGrib[z++] = (GRIBPACK)((c << cbits)
10772 + ((ival >> jbits) & ((1U << cbits) - 1)));
10773 cbits = 8;
10774 c = 0;
10775 }
10776 }
10777 /* now jbits < cbits */
10778 if ( jbits )
10779 {
10780 c = (c << jbits) + (ival & ((1U << jbits)-1));
10781 cbits -= jbits;
10782 }
10783 }
10784 if ( cbits != 8 ) lGrib[z++] = (GRIBPACK)(c << cbits);
10785
10786 *gz = z;
10787 }
10788
10789
10790 static
TEMPLATE(encode_array_2byte,T)10791 void TEMPLATE(encode_array_2byte,T)(size_t datasize, GRIBPACK *restrict lGrib,
10792 const T *restrict data, T zref, T factor, size_t *gz)
10793 {
10794 U_BYTEORDER;
10795 uint16_t *restrict sgrib = (uint16_t *)(void *)(lGrib+*gz);
10796
10797 if ( IS_BIGENDIAN() )
10798 {
10799 for ( size_t i = 0; i < datasize; i++ )
10800 sgrib[i] = (uint16_t)(CGRIBEX_FPSCALE(data[i]));
10801 }
10802 else
10803 {
10804 uint16_t ui16;
10805 for ( size_t i = 0; i < datasize; i++ )
10806 {
10807 ui16 = (uint16_t)(CGRIBEX_FPSCALE(data[i]));
10808 sgrib[i] = gribSwapByteOrder_uint16(ui16);
10809 }
10810 }
10811
10812 *gz += 2*datasize;
10813 }
10814 /*
10815 static
10816 void TEMPLATE(encode_array_2byte,T)(size_t datasize, GRIBPACK *restrict lGrib,
10817 const T *restrict data, T zref, T factor, size_t *gz)
10818 {
10819 size_t i, z = *gz;
10820 uint16_t ui16;
10821 T tmp;
10822
10823 #if defined (CRAY)
10824 #pragma _CRI ivdep
10825 #elif defined (SX)
10826 #pragma vdir nodep
10827 #elif defined (__uxp__)
10828 #pragma loop novrec
10829 #elif defined (__ICC)
10830 #pragma ivdep
10831 #endif
10832 for ( i = 0; i < datasize; i++ )
10833 {
10834 tmp = CGRIBEX_FPSCALE(data[i]);
10835 ui16 = (uint16_t) tmp;
10836 lGrib[z ] = ui16 >> 8;
10837 lGrib[z+1] = ui16;
10838 z += 2;
10839 }
10840
10841 *gz = z;
10842 }
10843 */
10844 static
TEMPLATE(encode_array,T)10845 void TEMPLATE(encode_array,T)(int numBits, size_t packStart, size_t datasize,
10846 GRIBPACK *restrict lGrib,
10847 const T *restrict data,
10848 T zref, T factor, size_t *gz)
10849 {
10850 #if defined _GET_X86_COUNTER || defined _GET_MACH_COUNTER
10851 uint64_t start_minmax, end_minmax;
10852 #endif
10853 uint32_t ui32;
10854 size_t i, z = *gz;
10855 T tmp;
10856
10857 data += packStart;
10858 datasize -= packStart;
10859
10860 if ( numBits == 8 )
10861 {
10862 #ifdef _GET_IBM_COUNTER
10863 hpmStart(2, "pack 8 bit base");
10864 #endif
10865
10866 #if defined (CRAY)
10867 #pragma _CRI ivdep
10868 #elif defined (SX)
10869 #pragma vdir nodep
10870 #elif defined (__uxp__)
10871 #pragma loop novrec
10872 #elif defined (__ICC)
10873 #pragma ivdep
10874 #endif
10875 for ( i = 0; i < datasize; i++ )
10876 {
10877 tmp = CGRIBEX_FPSCALE(data[i]);
10878 lGrib[z ] = (GRIBPACK)tmp;
10879 z++;
10880 }
10881
10882 #ifdef _GET_IBM_COUNTER
10883 hpmStop(2);
10884 #endif
10885 }
10886 else if ( numBits == 16 )
10887 {
10888 #ifdef _GET_IBM_COUNTER
10889 hpmStart(3, "pack 16 bit base");
10890 #elif defined _GET_X86_COUNTER
10891 start_minmax = _rdtsc();
10892 #elif defined _GET_MACH_COUNTER
10893 start_minmax = mach_absolute_time();
10894 #endif
10895 if ( sizeof(T) == sizeof(double) )
10896 {
10897 grib_encode_array_2byte_double(datasize, lGrib, (const double *)(const void *)data, zref, factor, &z);
10898 }
10899 else
10900 {
10901 TEMPLATE(encode_array_2byte,T)(datasize, lGrib, data, zref, factor, &z);
10902 }
10903
10904 #if defined _GET_X86_COUNTER || defined _GET_MACH_COUNTER
10905 #if defined _GET_X86_COUNTER
10906 end_minmax = _rdtsc();
10907 #elif defined _GET_MACH_COUNTER
10908 end_minmax = mach_absolute_time();
10909 #endif
10910 #if defined _ENABLE_AVX
10911 printf("AVX encoding cycles:: %" PRIu64 "\n", end_minmax-start_minmax);
10912 #elif defined _ENABLE_SSE4_1
10913 printf("SSE 4.1 encoding cycles:: %" PRIu64 "\n", end_minmax-start_minmax);
10914 #else
10915 printf("loop encoding cycles:: %" PRIu64 "\n", end_minmax-start_minmax);
10916 #endif
10917 #endif
10918
10919 #ifdef _GET_IBM_COUNTER
10920 hpmStop(3);
10921 #endif
10922 }
10923 else if ( numBits == 24 )
10924 {
10925 #ifdef _GET_IBM_COUNTER
10926 hpmStart(4, "pack 24 bit base");
10927 #endif
10928
10929 #if defined (CRAY)
10930 #pragma _CRI ivdep
10931 #elif defined (SX)
10932 #pragma vdir nodep
10933 #elif defined (__uxp__)
10934 #pragma loop novrec
10935 #elif defined (__ICC)
10936 #pragma ivdep
10937 #endif
10938 for ( i = 0; i < datasize; i++ )
10939 {
10940 tmp = CGRIBEX_FPSCALE(data[i]);
10941 ui32 = (uint32_t) tmp;
10942 lGrib[z ] = (GRIBPACK)(ui32 >> 16);
10943 lGrib[z+1] = (GRIBPACK)(ui32 >> 8);
10944 lGrib[z+2] = (GRIBPACK)ui32;
10945 z += 3;
10946 }
10947
10948 #ifdef _GET_IBM_COUNTER
10949 hpmStop(4);
10950 #endif
10951 }
10952 else if ( numBits == 32 )
10953 {
10954 #ifdef _GET_IBM_COUNTER
10955 hpmStart(5, "pack 32 bit base");
10956 #endif
10957
10958 #if defined (CRAY)
10959 #pragma _CRI ivdep
10960 #elif defined (SX)
10961 #pragma vdir nodep
10962 #elif defined (__uxp__)
10963 #pragma loop novrec
10964 #elif defined (__ICC)
10965 #pragma ivdep
10966 #endif
10967 for ( i = 0; i < datasize; i++ )
10968 {
10969 tmp = CGRIBEX_FPSCALE(data[i]);
10970 ui32 = (uint32_t) tmp;
10971 lGrib[z ] = (GRIBPACK)(ui32 >> 24);
10972 lGrib[z+1] = (GRIBPACK)(ui32 >> 16);
10973 lGrib[z+2] = (GRIBPACK)(ui32 >> 8);
10974 lGrib[z+3] = (GRIBPACK)ui32;
10975 z += 4;
10976 }
10977
10978 #ifdef _GET_IBM_COUNTER
10979 hpmStop(5);
10980 #endif
10981 }
10982 else if ( numBits > 0 && numBits <= 32 )
10983 {
10984 TEMPLATE(encode_array_common,T)(numBits, 0, datasize, lGrib, data, zref, factor, &z);
10985 }
10986 else if ( numBits == 0 )
10987 {
10988 }
10989 else
10990 {
10991 Error("Unimplemented packing factor %d!", numBits);
10992 }
10993
10994 *gz = z;
10995 }
10996
10997 static
TEMPLATE(encode_array_unrolled,T)10998 void TEMPLATE(encode_array_unrolled,T)(int numBits, size_t packStart, size_t datasize,
10999 GRIBPACK *restrict lGrib,
11000 const T *restrict data,
11001 T zref, T factor, size_t *gz)
11002 {
11003 U_BYTEORDER;
11004 size_t i, j, z = *gz;
11005 #ifdef _ARCH_PWR6
11006 enum { CGRIBEX__UNROLL_DEPTH_2 = 8 };
11007 #else
11008 enum { CGRIBEX__UNROLL_DEPTH_2 = 128 };
11009 #endif
11010 size_t residual;
11011 size_t ofs;
11012 T dval[CGRIBEX__UNROLL_DEPTH_2];
11013
11014 data += packStart;
11015 datasize -= packStart;
11016 residual = datasize % CGRIBEX__UNROLL_DEPTH_2;
11017 ofs = datasize - residual;
11018
11019 // reducing FP operations to single FMA is slowing down on pwr6 ...
11020
11021 if ( numBits == 8 )
11022 {
11023 #ifdef _GET_IBM_COUNTER
11024 hpmStart(2, "pack 8 bit unrolled");
11025 #endif
11026 unsigned char *cgrib = (unsigned char *) (lGrib + z);
11027 for ( i = 0; i < datasize - residual; i += CGRIBEX__UNROLL_DEPTH_2 )
11028 {
11029 for (j = 0; j < CGRIBEX__UNROLL_DEPTH_2; j++)
11030 {
11031 dval[j] = CGRIBEX_FPSCALE(data[i+j]);
11032 }
11033 for (j = 0; j < CGRIBEX__UNROLL_DEPTH_2; j++)
11034 {
11035 #ifdef _ARCH_PWR6
11036 *cgrib++ = (unsigned long) dval[j];
11037 #else
11038 *cgrib++ = (unsigned char) dval[j];
11039 #endif
11040 }
11041 z += CGRIBEX__UNROLL_DEPTH_2;
11042 }
11043 for (j = 0; j < residual; j++)
11044 {
11045 dval[j] = CGRIBEX_FPSCALE(data[i+j]);
11046 }
11047 for (j = 0; j < residual; j++)
11048 {
11049 #ifdef _ARCH_PWR6
11050 *cgrib++ = (unsigned long) dval[j];
11051 #else
11052 *cgrib++ = (unsigned char) dval[j];
11053 #endif
11054 }
11055 z += residual;
11056
11057 #ifdef _GET_IBM_COUNTER
11058 hpmStop(2);
11059 #endif
11060 }
11061 else if ( numBits == 16 )
11062 {
11063 #ifdef _GET_IBM_COUNTER
11064 hpmStart(3, "pack 16 bit unrolled");
11065 #endif
11066 #ifdef _ARCH_PWR6
11067 unsigned long ival;
11068 #else
11069 uint16_t ival;
11070 #endif
11071 uint16_t *sgrib = (uint16_t *)(void *)(lGrib+z);
11072
11073 for ( i = 0; i < datasize - residual; i += CGRIBEX__UNROLL_DEPTH_2 )
11074 {
11075 for (j = 0; j < CGRIBEX__UNROLL_DEPTH_2; j++)
11076 dval[j] = CGRIBEX_FPSCALE(data[j]);
11077 if ( IS_BIGENDIAN() )
11078 {
11079 for (j = 0; j < CGRIBEX__UNROLL_DEPTH_2; j++)
11080 {
11081 #ifdef _ARCH_PWR6
11082 *sgrib++ = (unsigned long) dval[j];
11083 #else
11084 *sgrib++ = (uint16_t) dval[j];
11085 #endif
11086 }
11087 z += 2*CGRIBEX__UNROLL_DEPTH_2;
11088 }
11089 else
11090 {
11091 for (j = 0; j < CGRIBEX__UNROLL_DEPTH_2; j++)
11092 {
11093 ival = (uint16_t) dval[j];
11094 *sgrib++ = gribSwapByteOrder_uint16(ival);
11095 }
11096 z += 2*CGRIBEX__UNROLL_DEPTH_2;
11097 }
11098 }
11099 for (j = 0; j < residual; j++)
11100 {
11101 dval[j] = CGRIBEX_FPSCALE(data[j]);
11102 }
11103 if ( IS_BIGENDIAN() )
11104 {
11105 for (j = 0; j < residual; j++)
11106 {
11107 #ifdef _ARCH_PWR6
11108 *sgrib++ = (unsigned long) dval[j];
11109 #else
11110 *sgrib++ = (uint16_t) dval[j];
11111 #endif
11112 }
11113 z += 2*residual;
11114 }
11115 else
11116 {
11117 for (j = 0; j < residual; j++)
11118 {
11119 ival = (uint16_t) dval[j];
11120 lGrib[z ] = (GRIBPACK)(ival >> 8);
11121 lGrib[z+1] = (GRIBPACK)ival;
11122 z += 2;
11123 }
11124 }
11125 #ifdef _GET_IBM_COUNTER
11126 hpmStop(3);
11127 #endif
11128 }
11129 else if ( numBits == 24 )
11130 {
11131 #ifdef _GET_IBM_COUNTER
11132 hpmStart(4, "pack 24 bit unrolled");
11133 #endif
11134 #ifdef _ARCH_PWR6
11135 unsigned long ival;
11136 #else
11137 uint32_t ival;
11138 #endif
11139 for ( i = 0; i < datasize - residual; i += CGRIBEX__UNROLL_DEPTH_2 )
11140 {
11141 for (j = 0; j < CGRIBEX__UNROLL_DEPTH_2; j++)
11142 {
11143 dval[j] = CGRIBEX_FPSCALE(data[j]);
11144 }
11145 for (j = 0; j < CGRIBEX__UNROLL_DEPTH_2; j++)
11146 {
11147 #ifdef _ARCH_PWR6
11148 ival = (unsigned long) dval[j];
11149 #else
11150 ival = (uint32_t) dval[j];
11151 #endif
11152 lGrib[z ] = (GRIBPACK)(ival >> 16);
11153 lGrib[z+1] = (GRIBPACK)(ival >> 8);
11154 lGrib[z+2] = (GRIBPACK)ival;
11155 z += 3;
11156 }
11157 }
11158 for (j = 0; j < residual; j++)
11159 {
11160 dval[j] = CGRIBEX_FPSCALE(data[j]);
11161 }
11162 for (j = 0; j < residual; j++)
11163 {
11164 ival = (uint32_t) dval[j];
11165 lGrib[z ] = (GRIBPACK)(ival >> 16);
11166 lGrib[z+1] = (GRIBPACK)(ival >> 8);
11167 lGrib[z+2] = (GRIBPACK)ival;
11168 z += 3;
11169 }
11170 #ifdef _GET_IBM_COUNTER
11171 hpmStop(4);
11172 #endif
11173 }
11174 else if ( numBits == 32 )
11175 {
11176 #ifdef _GET_IBM_COUNTER
11177 hpmStart(5, "pack 32 bit unrolled");
11178 #endif
11179 #ifdef _ARCH_PWR6
11180 unsigned long ival;
11181 #else
11182 uint32_t ival;
11183 #endif
11184 unsigned int *igrib = (unsigned int *)(void *)(lGrib + z);
11185 for ( i = 0; i < datasize - residual; i += CGRIBEX__UNROLL_DEPTH_2 )
11186 {
11187 for (j = 0; j < CGRIBEX__UNROLL_DEPTH_2; j++)
11188 dval[j] = CGRIBEX_FPSCALE(data[i+j]);
11189 if ( IS_BIGENDIAN() )
11190 {
11191 for (j = 0; j < CGRIBEX__UNROLL_DEPTH_2; j++)
11192 {
11193 #ifdef _ARCH_PWR6
11194 *igrib = (unsigned long) dval[j];
11195 #else
11196 *igrib = (uint32_t) dval[j];
11197 #endif
11198 igrib++;
11199 z += 4;
11200 }
11201 }
11202 else
11203 {
11204 for (j = 0; j < CGRIBEX__UNROLL_DEPTH_2; j++)
11205 {
11206 ival = (uint32_t) dval[j];
11207 lGrib[z ] = (GRIBPACK)(ival >> 24);
11208 lGrib[z+1] = (GRIBPACK)(ival >> 16);
11209 lGrib[z+2] = (GRIBPACK)(ival >> 8);
11210 lGrib[z+3] = (GRIBPACK)ival;
11211 z += 4;
11212 }
11213 }
11214 }
11215 for (j = 0; j < residual; j++)
11216 {
11217 dval[j] = CGRIBEX_FPSCALE(data[ofs+j]);
11218 }
11219 if ( IS_BIGENDIAN() )
11220 {
11221 for (j = 0; j < residual; j++)
11222 {
11223 #ifdef _ARCH_PWR6
11224 *igrib = (unsigned long) dval[j];
11225 #else
11226 *igrib = (uint32_t) dval[j];
11227 #endif
11228 igrib++;
11229 z += 4;
11230 }
11231 }
11232 else
11233 {
11234 for (j = 0; j < residual; j++)
11235 {
11236 ival = (uint32_t) dval[j];
11237 lGrib[z ] = (GRIBPACK)(ival >> 24);
11238 lGrib[z+1] = (GRIBPACK)(ival >> 16);
11239 lGrib[z+2] = (GRIBPACK)(ival >> 8);
11240 lGrib[z+3] = (GRIBPACK)ival;
11241 z += 4;
11242 }
11243 }
11244 #ifdef _GET_IBM_COUNTER
11245 hpmStop(5);
11246 #endif
11247 }
11248 else if ( numBits > 0 && numBits <= 32 )
11249 {
11250 TEMPLATE(encode_array_common,T)(numBits, 0, datasize, lGrib, data, zref, factor, &z);
11251 }
11252 else if ( numBits == 0 )
11253 {
11254 }
11255 else
11256 {
11257 Error("Unimplemented packing factor %d!", numBits);
11258 }
11259
11260 *gz = z;
11261 }
11262
11263 #endif /* T */
11264
11265 /*
11266 * Local Variables:
11267 * mode: c
11268 * End:
11269 */
11270
11271 #ifdef T
11272 #undef T
11273 #endif
11274 #define T float
11275 #ifdef T
11276
11277
11278 #define round_float roundf
11279 #define round_double round
11280
11281 #if 0
11282 #define CGRIBEX_FPSCALE(data) (TEMPLATE(round,T)(((data) - zref) * factor))
11283 #else
11284 #define CGRIBEX_FPSCALE(data) (((data) - zref) * factor + (T)0.5)
11285 #endif
11286
11287 static
TEMPLATE(encode_array_common,T)11288 void TEMPLATE(encode_array_common,T)(int numBits, size_t packStart, size_t datasize, GRIBPACK *lGrib,
11289 const T *data, T zref, T factor, size_t *gz)
11290 {
11291 size_t z = *gz;
11292 unsigned int ival;
11293 int cbits, jbits;
11294 unsigned int c;
11295
11296 /* code from gribw routine flist2bitstream */
11297
11298 cbits = 8;
11299 c = 0;
11300 for (size_t i = packStart; i < datasize; i++)
11301 {
11302 /* note float -> unsigned int .. truncate */
11303 ival = (unsigned int)(CGRIBEX_FPSCALE(data[i]));
11304 /*
11305 if ( ival > max_nbpv_pow2 ) ival = max_nbpv_pow2;
11306 if ( ival < 0 ) ival = 0;
11307 */
11308 jbits = numBits;
11309 while ( cbits <= jbits )
11310 {
11311 if ( cbits == 8 )
11312 {
11313 jbits -= 8;
11314 lGrib[z++] = (ival >> jbits) & 0xFF;
11315 }
11316 else
11317 {
11318 jbits -= cbits;
11319 lGrib[z++] = (GRIBPACK)((c << cbits)
11320 + ((ival >> jbits) & ((1U << cbits) - 1)));
11321 cbits = 8;
11322 c = 0;
11323 }
11324 }
11325 /* now jbits < cbits */
11326 if ( jbits )
11327 {
11328 c = (c << jbits) + (ival & ((1U << jbits)-1));
11329 cbits -= jbits;
11330 }
11331 }
11332 if ( cbits != 8 ) lGrib[z++] = (GRIBPACK)(c << cbits);
11333
11334 *gz = z;
11335 }
11336
11337
11338 static
TEMPLATE(encode_array_2byte,T)11339 void TEMPLATE(encode_array_2byte,T)(size_t datasize, GRIBPACK *restrict lGrib,
11340 const T *restrict data, T zref, T factor, size_t *gz)
11341 {
11342 U_BYTEORDER;
11343 uint16_t *restrict sgrib = (uint16_t *)(void *)(lGrib+*gz);
11344
11345 if ( IS_BIGENDIAN() )
11346 {
11347 for ( size_t i = 0; i < datasize; i++ )
11348 sgrib[i] = (uint16_t)(CGRIBEX_FPSCALE(data[i]));
11349 }
11350 else
11351 {
11352 uint16_t ui16;
11353 for ( size_t i = 0; i < datasize; i++ )
11354 {
11355 ui16 = (uint16_t)(CGRIBEX_FPSCALE(data[i]));
11356 sgrib[i] = gribSwapByteOrder_uint16(ui16);
11357 }
11358 }
11359
11360 *gz += 2*datasize;
11361 }
11362 /*
11363 static
11364 void TEMPLATE(encode_array_2byte,T)(size_t datasize, GRIBPACK *restrict lGrib,
11365 const T *restrict data, T zref, T factor, size_t *gz)
11366 {
11367 size_t i, z = *gz;
11368 uint16_t ui16;
11369 T tmp;
11370
11371 #if defined (CRAY)
11372 #pragma _CRI ivdep
11373 #elif defined (SX)
11374 #pragma vdir nodep
11375 #elif defined (__uxp__)
11376 #pragma loop novrec
11377 #elif defined (__ICC)
11378 #pragma ivdep
11379 #endif
11380 for ( i = 0; i < datasize; i++ )
11381 {
11382 tmp = CGRIBEX_FPSCALE(data[i]);
11383 ui16 = (uint16_t) tmp;
11384 lGrib[z ] = ui16 >> 8;
11385 lGrib[z+1] = ui16;
11386 z += 2;
11387 }
11388
11389 *gz = z;
11390 }
11391 */
11392 static
TEMPLATE(encode_array,T)11393 void TEMPLATE(encode_array,T)(int numBits, size_t packStart, size_t datasize,
11394 GRIBPACK *restrict lGrib,
11395 const T *restrict data,
11396 T zref, T factor, size_t *gz)
11397 {
11398 #if defined _GET_X86_COUNTER || defined _GET_MACH_COUNTER
11399 uint64_t start_minmax, end_minmax;
11400 #endif
11401 uint32_t ui32;
11402 size_t i, z = *gz;
11403 T tmp;
11404
11405 data += packStart;
11406 datasize -= packStart;
11407
11408 if ( numBits == 8 )
11409 {
11410 #ifdef _GET_IBM_COUNTER
11411 hpmStart(2, "pack 8 bit base");
11412 #endif
11413
11414 #if defined (CRAY)
11415 #pragma _CRI ivdep
11416 #elif defined (SX)
11417 #pragma vdir nodep
11418 #elif defined (__uxp__)
11419 #pragma loop novrec
11420 #elif defined (__ICC)
11421 #pragma ivdep
11422 #endif
11423 for ( i = 0; i < datasize; i++ )
11424 {
11425 tmp = CGRIBEX_FPSCALE(data[i]);
11426 lGrib[z ] = (GRIBPACK)tmp;
11427 z++;
11428 }
11429
11430 #ifdef _GET_IBM_COUNTER
11431 hpmStop(2);
11432 #endif
11433 }
11434 else if ( numBits == 16 )
11435 {
11436 #ifdef _GET_IBM_COUNTER
11437 hpmStart(3, "pack 16 bit base");
11438 #elif defined _GET_X86_COUNTER
11439 start_minmax = _rdtsc();
11440 #elif defined _GET_MACH_COUNTER
11441 start_minmax = mach_absolute_time();
11442 #endif
11443 if ( sizeof(T) == sizeof(double) )
11444 {
11445 grib_encode_array_2byte_double(datasize, lGrib, (const double *)(const void *)data, zref, factor, &z);
11446 }
11447 else
11448 {
11449 TEMPLATE(encode_array_2byte,T)(datasize, lGrib, data, zref, factor, &z);
11450 }
11451
11452 #if defined _GET_X86_COUNTER || defined _GET_MACH_COUNTER
11453 #if defined _GET_X86_COUNTER
11454 end_minmax = _rdtsc();
11455 #elif defined _GET_MACH_COUNTER
11456 end_minmax = mach_absolute_time();
11457 #endif
11458 #if defined _ENABLE_AVX
11459 printf("AVX encoding cycles:: %" PRIu64 "\n", end_minmax-start_minmax);
11460 #elif defined _ENABLE_SSE4_1
11461 printf("SSE 4.1 encoding cycles:: %" PRIu64 "\n", end_minmax-start_minmax);
11462 #else
11463 printf("loop encoding cycles:: %" PRIu64 "\n", end_minmax-start_minmax);
11464 #endif
11465 #endif
11466
11467 #ifdef _GET_IBM_COUNTER
11468 hpmStop(3);
11469 #endif
11470 }
11471 else if ( numBits == 24 )
11472 {
11473 #ifdef _GET_IBM_COUNTER
11474 hpmStart(4, "pack 24 bit base");
11475 #endif
11476
11477 #if defined (CRAY)
11478 #pragma _CRI ivdep
11479 #elif defined (SX)
11480 #pragma vdir nodep
11481 #elif defined (__uxp__)
11482 #pragma loop novrec
11483 #elif defined (__ICC)
11484 #pragma ivdep
11485 #endif
11486 for ( i = 0; i < datasize; i++ )
11487 {
11488 tmp = CGRIBEX_FPSCALE(data[i]);
11489 ui32 = (uint32_t) tmp;
11490 lGrib[z ] = (GRIBPACK)(ui32 >> 16);
11491 lGrib[z+1] = (GRIBPACK)(ui32 >> 8);
11492 lGrib[z+2] = (GRIBPACK)ui32;
11493 z += 3;
11494 }
11495
11496 #ifdef _GET_IBM_COUNTER
11497 hpmStop(4);
11498 #endif
11499 }
11500 else if ( numBits == 32 )
11501 {
11502 #ifdef _GET_IBM_COUNTER
11503 hpmStart(5, "pack 32 bit base");
11504 #endif
11505
11506 #if defined (CRAY)
11507 #pragma _CRI ivdep
11508 #elif defined (SX)
11509 #pragma vdir nodep
11510 #elif defined (__uxp__)
11511 #pragma loop novrec
11512 #elif defined (__ICC)
11513 #pragma ivdep
11514 #endif
11515 for ( i = 0; i < datasize; i++ )
11516 {
11517 tmp = CGRIBEX_FPSCALE(data[i]);
11518 ui32 = (uint32_t) tmp;
11519 lGrib[z ] = (GRIBPACK)(ui32 >> 24);
11520 lGrib[z+1] = (GRIBPACK)(ui32 >> 16);
11521 lGrib[z+2] = (GRIBPACK)(ui32 >> 8);
11522 lGrib[z+3] = (GRIBPACK)ui32;
11523 z += 4;
11524 }
11525
11526 #ifdef _GET_IBM_COUNTER
11527 hpmStop(5);
11528 #endif
11529 }
11530 else if ( numBits > 0 && numBits <= 32 )
11531 {
11532 TEMPLATE(encode_array_common,T)(numBits, 0, datasize, lGrib, data, zref, factor, &z);
11533 }
11534 else if ( numBits == 0 )
11535 {
11536 }
11537 else
11538 {
11539 Error("Unimplemented packing factor %d!", numBits);
11540 }
11541
11542 *gz = z;
11543 }
11544
11545 static
TEMPLATE(encode_array_unrolled,T)11546 void TEMPLATE(encode_array_unrolled,T)(int numBits, size_t packStart, size_t datasize,
11547 GRIBPACK *restrict lGrib,
11548 const T *restrict data,
11549 T zref, T factor, size_t *gz)
11550 {
11551 U_BYTEORDER;
11552 size_t i, j, z = *gz;
11553 #ifdef _ARCH_PWR6
11554 enum { CGRIBEX__UNROLL_DEPTH_2 = 8 };
11555 #else
11556 enum { CGRIBEX__UNROLL_DEPTH_2 = 128 };
11557 #endif
11558 size_t residual;
11559 size_t ofs;
11560 T dval[CGRIBEX__UNROLL_DEPTH_2];
11561
11562 data += packStart;
11563 datasize -= packStart;
11564 residual = datasize % CGRIBEX__UNROLL_DEPTH_2;
11565 ofs = datasize - residual;
11566
11567 // reducing FP operations to single FMA is slowing down on pwr6 ...
11568
11569 if ( numBits == 8 )
11570 {
11571 #ifdef _GET_IBM_COUNTER
11572 hpmStart(2, "pack 8 bit unrolled");
11573 #endif
11574 unsigned char *cgrib = (unsigned char *) (lGrib + z);
11575 for ( i = 0; i < datasize - residual; i += CGRIBEX__UNROLL_DEPTH_2 )
11576 {
11577 for (j = 0; j < CGRIBEX__UNROLL_DEPTH_2; j++)
11578 {
11579 dval[j] = CGRIBEX_FPSCALE(data[i+j]);
11580 }
11581 for (j = 0; j < CGRIBEX__UNROLL_DEPTH_2; j++)
11582 {
11583 #ifdef _ARCH_PWR6
11584 *cgrib++ = (unsigned long) dval[j];
11585 #else
11586 *cgrib++ = (unsigned char) dval[j];
11587 #endif
11588 }
11589 z += CGRIBEX__UNROLL_DEPTH_2;
11590 }
11591 for (j = 0; j < residual; j++)
11592 {
11593 dval[j] = CGRIBEX_FPSCALE(data[i+j]);
11594 }
11595 for (j = 0; j < residual; j++)
11596 {
11597 #ifdef _ARCH_PWR6
11598 *cgrib++ = (unsigned long) dval[j];
11599 #else
11600 *cgrib++ = (unsigned char) dval[j];
11601 #endif
11602 }
11603 z += residual;
11604
11605 #ifdef _GET_IBM_COUNTER
11606 hpmStop(2);
11607 #endif
11608 }
11609 else if ( numBits == 16 )
11610 {
11611 #ifdef _GET_IBM_COUNTER
11612 hpmStart(3, "pack 16 bit unrolled");
11613 #endif
11614 #ifdef _ARCH_PWR6
11615 unsigned long ival;
11616 #else
11617 uint16_t ival;
11618 #endif
11619 uint16_t *sgrib = (uint16_t *)(void *)(lGrib+z);
11620
11621 for ( i = 0; i < datasize - residual; i += CGRIBEX__UNROLL_DEPTH_2 )
11622 {
11623 for (j = 0; j < CGRIBEX__UNROLL_DEPTH_2; j++)
11624 dval[j] = CGRIBEX_FPSCALE(data[j]);
11625 if ( IS_BIGENDIAN() )
11626 {
11627 for (j = 0; j < CGRIBEX__UNROLL_DEPTH_2; j++)
11628 {
11629 #ifdef _ARCH_PWR6
11630 *sgrib++ = (unsigned long) dval[j];
11631 #else
11632 *sgrib++ = (uint16_t) dval[j];
11633 #endif
11634 }
11635 z += 2*CGRIBEX__UNROLL_DEPTH_2;
11636 }
11637 else
11638 {
11639 for (j = 0; j < CGRIBEX__UNROLL_DEPTH_2; j++)
11640 {
11641 ival = (uint16_t) dval[j];
11642 *sgrib++ = gribSwapByteOrder_uint16(ival);
11643 }
11644 z += 2*CGRIBEX__UNROLL_DEPTH_2;
11645 }
11646 }
11647 for (j = 0; j < residual; j++)
11648 {
11649 dval[j] = CGRIBEX_FPSCALE(data[j]);
11650 }
11651 if ( IS_BIGENDIAN() )
11652 {
11653 for (j = 0; j < residual; j++)
11654 {
11655 #ifdef _ARCH_PWR6
11656 *sgrib++ = (unsigned long) dval[j];
11657 #else
11658 *sgrib++ = (uint16_t) dval[j];
11659 #endif
11660 }
11661 z += 2*residual;
11662 }
11663 else
11664 {
11665 for (j = 0; j < residual; j++)
11666 {
11667 ival = (uint16_t) dval[j];
11668 lGrib[z ] = (GRIBPACK)(ival >> 8);
11669 lGrib[z+1] = (GRIBPACK)ival;
11670 z += 2;
11671 }
11672 }
11673 #ifdef _GET_IBM_COUNTER
11674 hpmStop(3);
11675 #endif
11676 }
11677 else if ( numBits == 24 )
11678 {
11679 #ifdef _GET_IBM_COUNTER
11680 hpmStart(4, "pack 24 bit unrolled");
11681 #endif
11682 #ifdef _ARCH_PWR6
11683 unsigned long ival;
11684 #else
11685 uint32_t ival;
11686 #endif
11687 for ( i = 0; i < datasize - residual; i += CGRIBEX__UNROLL_DEPTH_2 )
11688 {
11689 for (j = 0; j < CGRIBEX__UNROLL_DEPTH_2; j++)
11690 {
11691 dval[j] = CGRIBEX_FPSCALE(data[j]);
11692 }
11693 for (j = 0; j < CGRIBEX__UNROLL_DEPTH_2; j++)
11694 {
11695 #ifdef _ARCH_PWR6
11696 ival = (unsigned long) dval[j];
11697 #else
11698 ival = (uint32_t) dval[j];
11699 #endif
11700 lGrib[z ] = (GRIBPACK)(ival >> 16);
11701 lGrib[z+1] = (GRIBPACK)(ival >> 8);
11702 lGrib[z+2] = (GRIBPACK)ival;
11703 z += 3;
11704 }
11705 }
11706 for (j = 0; j < residual; j++)
11707 {
11708 dval[j] = CGRIBEX_FPSCALE(data[j]);
11709 }
11710 for (j = 0; j < residual; j++)
11711 {
11712 ival = (uint32_t) dval[j];
11713 lGrib[z ] = (GRIBPACK)(ival >> 16);
11714 lGrib[z+1] = (GRIBPACK)(ival >> 8);
11715 lGrib[z+2] = (GRIBPACK)ival;
11716 z += 3;
11717 }
11718 #ifdef _GET_IBM_COUNTER
11719 hpmStop(4);
11720 #endif
11721 }
11722 else if ( numBits == 32 )
11723 {
11724 #ifdef _GET_IBM_COUNTER
11725 hpmStart(5, "pack 32 bit unrolled");
11726 #endif
11727 #ifdef _ARCH_PWR6
11728 unsigned long ival;
11729 #else
11730 uint32_t ival;
11731 #endif
11732 unsigned int *igrib = (unsigned int *)(void *)(lGrib + z);
11733 for ( i = 0; i < datasize - residual; i += CGRIBEX__UNROLL_DEPTH_2 )
11734 {
11735 for (j = 0; j < CGRIBEX__UNROLL_DEPTH_2; j++)
11736 dval[j] = CGRIBEX_FPSCALE(data[i+j]);
11737 if ( IS_BIGENDIAN() )
11738 {
11739 for (j = 0; j < CGRIBEX__UNROLL_DEPTH_2; j++)
11740 {
11741 #ifdef _ARCH_PWR6
11742 *igrib = (unsigned long) dval[j];
11743 #else
11744 *igrib = (uint32_t) dval[j];
11745 #endif
11746 igrib++;
11747 z += 4;
11748 }
11749 }
11750 else
11751 {
11752 for (j = 0; j < CGRIBEX__UNROLL_DEPTH_2; j++)
11753 {
11754 ival = (uint32_t) dval[j];
11755 lGrib[z ] = (GRIBPACK)(ival >> 24);
11756 lGrib[z+1] = (GRIBPACK)(ival >> 16);
11757 lGrib[z+2] = (GRIBPACK)(ival >> 8);
11758 lGrib[z+3] = (GRIBPACK)ival;
11759 z += 4;
11760 }
11761 }
11762 }
11763 for (j = 0; j < residual; j++)
11764 {
11765 dval[j] = CGRIBEX_FPSCALE(data[ofs+j]);
11766 }
11767 if ( IS_BIGENDIAN() )
11768 {
11769 for (j = 0; j < residual; j++)
11770 {
11771 #ifdef _ARCH_PWR6
11772 *igrib = (unsigned long) dval[j];
11773 #else
11774 *igrib = (uint32_t) dval[j];
11775 #endif
11776 igrib++;
11777 z += 4;
11778 }
11779 }
11780 else
11781 {
11782 for (j = 0; j < residual; j++)
11783 {
11784 ival = (uint32_t) dval[j];
11785 lGrib[z ] = (GRIBPACK)(ival >> 24);
11786 lGrib[z+1] = (GRIBPACK)(ival >> 16);
11787 lGrib[z+2] = (GRIBPACK)(ival >> 8);
11788 lGrib[z+3] = (GRIBPACK)ival;
11789 z += 4;
11790 }
11791 }
11792 #ifdef _GET_IBM_COUNTER
11793 hpmStop(5);
11794 #endif
11795 }
11796 else if ( numBits > 0 && numBits <= 32 )
11797 {
11798 TEMPLATE(encode_array_common,T)(numBits, 0, datasize, lGrib, data, zref, factor, &z);
11799 }
11800 else if ( numBits == 0 )
11801 {
11802 }
11803 else
11804 {
11805 Error("Unimplemented packing factor %d!", numBits);
11806 }
11807
11808 *gz = z;
11809 }
11810
11811 #endif /* T */
11812
11813 /*
11814 * Local Variables:
11815 * mode: c
11816 * End:
11817 */
11818
11819
11820 #ifdef T
11821 #undef T
11822 #endif
11823 #define T double
11824 #ifdef T
11825
11826 // GRIB BLOCK 2 - GRID DESCRIPTION SECTION
11827 static
TEMPLATE(encodeGDS,T)11828 void TEMPLATE(encodeGDS,T)(GRIBPACK *lGrib, long *gribLen, int *isec2, T *fsec2)
11829 {
11830 long z = *gribLen;
11831 int exponent, mantissa;
11832 int ival;
11833 int gdslen = 32;
11834
11835 if ( ISEC2_GridType == GRIB1_GTYPE_LCC ) gdslen += 10;
11836
11837 if ( ISEC2_GridType == GRIB1_GTYPE_LATLON_ROT ) gdslen += 10;
11838
11839 const int pvoffset = (ISEC2_NumVCP || ISEC2_Reduced) ? gdslen + 1 : 0xFF;
11840
11841 if ( ISEC2_Reduced ) gdslen += 2 * ISEC2_NumLat;
11842
11843 gdslen += ISEC2_NumVCP * 4;
11844
11845 Put3Byte(gdslen); /* 0- 2 Length of Block 2 Byte 0 */
11846 Put1Byte(ISEC2_NumVCP); /* 3 NV */
11847 Put1Byte(pvoffset); /* 4 PV */
11848 Put1Byte(ISEC2_GridType); /* 5 LatLon=0 Gauss=4 Spectral=50 */
11849
11850 if ( ISEC2_GridType == GRIB1_GTYPE_SPECTRAL )
11851 {
11852 Put2Byte(ISEC2_PentaJ); /* 6- 7 Pentagonal resolution J */
11853 Put2Byte(ISEC2_PentaK); /* 8- 9 Pentagonal resolution K */
11854 Put2Byte(ISEC2_PentaM); /* 10-11 Pentagonal resolution M */
11855 Put1Byte(ISEC2_RepType); /* 12 Representation type */
11856 Put1Byte(ISEC2_RepMode); /* 13 Representation mode */
11857 PutnZero(18); /* 14-31 reserved */
11858 }
11859 else if ( ISEC2_GridType == GRIB1_GTYPE_GME )
11860 {
11861 Put2Byte(ISEC2_GME_NI2);
11862 Put2Byte(ISEC2_GME_NI3);
11863 Put3Byte(ISEC2_GME_ND);
11864 Put3Byte(ISEC2_GME_NI);
11865 Put1Byte(ISEC2_GME_AFlag);
11866 Put3Int(ISEC2_GME_LatPP);
11867 Put3Int(ISEC2_GME_LonPP);
11868 Put3Int(ISEC2_GME_LonMPL);
11869 Put1Byte(ISEC2_GME_BFlag);
11870 PutnZero(5);
11871 }
11872 else if ( ISEC2_GridType == GRIB1_GTYPE_LCC )
11873 {
11874 Put2Byte(ISEC2_NumLon); /* 6- 7 Longitudes */
11875
11876 Put2Byte(ISEC2_NumLat); /* 8- 9 Latitudes */
11877 Put3Int(ISEC2_FirstLat);
11878 Put3Int(ISEC2_FirstLon);
11879 Put1Byte(ISEC2_ResFlag); /* 16 Resolution flag */
11880 Put3Int(ISEC2_Lambert_Lov); /* 17-19 */
11881 Put3Int(ISEC2_Lambert_dx); /* 20-22 */
11882 Put3Int(ISEC2_Lambert_dy); /* 23-25 */
11883 Put1Byte(ISEC2_Lambert_ProjFlag);/* 26 Projection flag */
11884 Put1Byte(ISEC2_ScanFlag); /* 27 Scanning mode */
11885 Put3Int(ISEC2_Lambert_LatS1); /* 28-30 */
11886 Put3Int(ISEC2_Lambert_LatS2); /* 31-33 */
11887 Put3Int(ISEC2_Lambert_LatSP); /* 34-36 */
11888 Put3Int(ISEC2_Lambert_LonSP); /* 37-39 */
11889 PutnZero(2); /* 34-41 */
11890 }
11891 else if ( ISEC2_GridType == GRIB1_GTYPE_LATLON ||
11892 ISEC2_GridType == GRIB1_GTYPE_GAUSSIAN ||
11893 ISEC2_GridType == GRIB1_GTYPE_LATLON_ROT )
11894 {
11895 const int numlon = ISEC2_Reduced ? 0xFFFF : ISEC2_NumLon;
11896 Put2Byte(numlon); /* 6- 7 Number of Longitudes */
11897
11898 Put2Byte(ISEC2_NumLat); /* 8- 9 Number of Latitudes */
11899 Put3Int(ISEC2_FirstLat);
11900 Put3Int(ISEC2_FirstLon);
11901 Put1Byte(ISEC2_ResFlag); /* 16 Resolution flag */
11902 Put3Int(ISEC2_LastLat);
11903 Put3Int(ISEC2_LastLon);
11904 const unsigned lonIncr = (ISEC2_ResFlag == 0) ? 0xFFFF : (unsigned)ISEC2_LonIncr;
11905 const unsigned latIncr = (ISEC2_ResFlag == 0) ? 0xFFFF : (unsigned)ISEC2_LatIncr;
11906 Put2Byte(lonIncr); /* 23-24 i - direction increment */
11907 if ( ISEC2_GridType == GRIB1_GTYPE_GAUSSIAN )
11908 Put2Byte(ISEC2_NumPar); /* 25-26 Latitudes Pole->Equator */
11909 else
11910 Put2Byte(latIncr); /* 25-26 j - direction increment */
11911
11912 Put1Byte(ISEC2_ScanFlag); /* 27 Scanning mode */
11913 PutnZero(4); /* 28-31 reserved */
11914
11915 if ( ISEC2_GridType == GRIB1_GTYPE_LATLON_ROT )
11916 {
11917 Put3Int(ISEC2_LatSP);
11918 Put3Int(ISEC2_LonSP);
11919 Put1Real((double)(FSEC2_RotAngle));
11920 }
11921 }
11922 else
11923 {
11924 Error("Unsupported grid type %d", ISEC2_GridType);
11925 }
11926
11927 #if defined (SX)
11928 #pragma vdir novector /* vectorization gives wrong results on NEC */
11929 #endif
11930 for ( long i = 0; i < ISEC2_NumVCP; ++i )
11931 {
11932 Put1Real((double)(fsec2[10+i]));
11933 }
11934
11935 if ( ISEC2_Reduced )
11936 for ( long i = 0; i < ISEC2_NumLat; i++ ) Put2Byte(ISEC2_ReducedPoints(i));
11937
11938 *gribLen = z;
11939 }
11940
11941 // GRIB BLOCK 3 - BIT MAP SECTION
11942 static
TEMPLATE(encodeBMS,T)11943 void TEMPLATE(encodeBMS,T)(GRIBPACK *lGrib, long *gribLen, T *fsec3, int *isec4, T *data, long *datasize)
11944 {
11945 long z = *gribLen;
11946 static bool lmissvalinfo = true;
11947 // unsigned int c, imask;
11948
11949 if ( DBL_IS_NAN(FSEC3_MissVal) && lmissvalinfo)
11950 {
11951 lmissvalinfo = false;
11952 Message("Missing value = NaN is unsupported!");
11953 }
11954
11955 const long bitmapSize = ISEC4_NumValues;
11956 const long imaskSize = ((bitmapSize+7)>>3)<<3;
11957 GRIBPACK *bitmap = &lGrib[z+6];
11958 long fsec4size = 0;
11959
11960 #ifdef VECTORCODE
11961 unsigned int *imask = (unsigned int*) Malloc(imaskSize*sizeof(unsigned int));
11962 memset(imask, 0, imaskSize*sizeof(int));
11963
11964 #if defined (CRAY)
11965 #pragma _CRI ivdep
11966 #endif
11967 #if defined (SX)
11968 #pragma vdir nodep
11969 #endif
11970 #ifdef __uxpch__
11971 #pragma loop novrec
11972 #endif
11973 for ( long i = 0; i < bitmapSize; i++ )
11974 {
11975 if ( IS_NOT_EQUAL(data[i], FSEC3_MissVal) )
11976 {
11977 data[fsec4size++] = data[i];
11978 imask[i] = 1;
11979 }
11980 }
11981
11982 #if defined (CRAY)
11983 #pragma _CRI ivdep
11984 #endif
11985 #if defined (SX)
11986 #pragma vdir nodep
11987 #endif
11988 #ifdef __uxpch__
11989 #pragma loop novrec
11990 #endif
11991 for ( long i = 0; i < imaskSize/8; i++ )
11992 {
11993 bitmap[i] = (imask[i*8+0] << 7) | (imask[i*8+1] << 6) |
11994 (imask[i*8+2] << 5) | (imask[i*8+3] << 4) |
11995 (imask[i*8+4] << 3) | (imask[i*8+5] << 2) |
11996 (imask[i*8+6] << 1) | (imask[i*8+7]);
11997 }
11998
11999 Free(imask);
12000 #else
12001 for ( long i = 0; i < imaskSize/8; i++ ) bitmap[i] = 0;
12002
12003 for ( long i = 0; i < bitmapSize; i++ )
12004 {
12005 if ( IS_NOT_EQUAL(data[i], FSEC3_MissVal) )
12006 {
12007 data[fsec4size++] = data[i];
12008 bitmap[i/8] |= (GRIBPACK)(1<<(7-(i&7)));
12009 }
12010 }
12011 #endif
12012
12013 const long bmsLen = imaskSize/8 + 6;
12014 const long bmsUnusedBits = imaskSize - bitmapSize;
12015
12016 Put3Byte(bmsLen); /* 0- 2 Length of Block 3 Byte 0 */
12017 Put1Byte(bmsUnusedBits);
12018 Put2Byte(0);
12019
12020 *gribLen += bmsLen;
12021
12022 *datasize = fsec4size;
12023 }
12024
12025 #define pow_double pow
12026 #define pow_float powf
12027
12028 // GRIB BLOCK 4 - BINARY DATA SECTION
12029 static
TEMPLATE(encodeBDS,T)12030 int TEMPLATE(encodeBDS,T)(GRIBPACK *lGrib, long *gribLen, int decscale, int *isec2, int *isec4, long datasize, T *data,
12031 long *datstart, long *datsize, int code)
12032 {
12033 // Uwe Schulzweida, 11/04/2003 : Check that number of bits per value is not exceeded
12034 // Uwe Schulzweida, 6/05/2003 : Copy result to fpval to prevent integer overflow
12035
12036 size_t z = (size_t)*gribLen;
12037 int numBits;
12038 int ival;
12039 long PackStart = 0;
12040 int Flag = 0;
12041 int binscale = 0;
12042 int bds_head = 11;
12043 int bds_ext = 0;
12044 /* ibits = BitsPerInt; */
12045 int exponent, mantissa;
12046 bool lspherc = false;
12047 int isubset = 0, itemp = 0, itrunc = 0;
12048 T factor = 1, fmin, fmax;
12049 const double jpepsln = 1.0e-12; // -----> tolerance used to check equality
12050 // of floating point numbers - needed
12051 // on some platforms (eg vpp700, linux)
12052 extern int CGRIBEX_Const; // 1: Don't pack constant fields on regular grids
12053
12054 if ( isec2 )
12055 {
12056 /* If section 2 is present, it says if data is spherical harmonic */
12057
12058 lspherc = ( isec2[0] == 50 || isec2[0] == 60 ||
12059 isec2[0] == 70 || isec2[0] == 80 );
12060
12061 isec4[2] = lspherc ? 128 : 0;
12062 }
12063 else
12064 {
12065 /* Section 4 says if it's spherical harmonic data.. */
12066
12067 lspherc = ( isec4[2] == 128 );
12068 }
12069
12070 /* Complex packing supported for spherical harmonics. */
12071
12072 const bool lcomplex = ( lspherc && ( isec4[3] == 64 ) ) ||
12073 ( lspherc && isec2 && ( isec2[5] == 2 ) );
12074
12075 // Check input specification is consistent
12076
12077 if ( lcomplex && isec2 )
12078 {
12079 if ( ( isec4[3] != 64 ) && ( isec2[5] == 2 ) )
12080 {
12081 gprintf(__func__, " COMPLEX mismatch. isec4[3] = %d\n", isec4[3]);
12082 gprintf(__func__, " COMPLEX mismatch. isec2[5] = %d\n", isec2[5]);
12083 return (807);
12084 }
12085 else if ( ( isec4[3] == 64 ) && ( isec2[5] != 2 ) )
12086 {
12087 gprintf(__func__, " COMPLEX mismatch. isec4[3] = %d\n", isec4[3]);
12088 gprintf(__func__, " COMPLEX mismatch. isec2[5] = %d\n", isec2[5]);
12089 return (807);
12090 }
12091 else if ( lcomplex )
12092 {
12093 // Truncation of full spectrum, which is supposed triangular, has to be diagnosed. Define also sub-set truncation.
12094 isubset = isec4[17];
12095 // When encoding, use the total number of data.
12096 itemp = isec4[0];
12097 itrunc = (int) (sqrt(itemp*4 + 1.) - 3) / 2;
12098 }
12099 }
12100
12101 if ( decscale )
12102 {
12103 const T scale = TEMPLATE(pow,T)((T)10.0, (T)decscale);
12104 for ( long i = 0; i < datasize; ++i ) data[i] *= scale;
12105 }
12106
12107 if ( lspherc )
12108 {
12109 if ( lcomplex )
12110 {
12111 const int jup = isubset;
12112 const int ioff = (jup+1)*(jup+2);
12113 bds_ext = 4 + 3 + 4*ioff;
12114 PackStart = ioff;
12115 Flag = 192;
12116 }
12117 else
12118 {
12119 bds_ext = 4;
12120 PackStart = 1;
12121 Flag = 128;
12122 }
12123 }
12124
12125 *datstart = bds_head + bds_ext;
12126
12127 int nbpv = numBits = ISEC4_NumBits;
12128
12129 if ( lspherc && lcomplex )
12130 {
12131 const int pcStart = isubset;
12132 const int pcScale = isec4[16];
12133 TEMPLATE(scale_complex,T)(data, pcStart, pcScale, itrunc, 0);
12134 TEMPLATE(gather_complex,T)(data, (size_t)pcStart, (size_t)itrunc, (size_t)datasize);
12135 }
12136
12137 fmin = fmax = data[PackStart];
12138
12139 TEMPLATE(minmax_val,T)(data+PackStart, datasize-PackStart, &fmin, &fmax);
12140
12141 double zref = (double)fmin;
12142 if (!(zref < DBL_MAX && zref > -DBL_MAX))
12143 {
12144 gprintf(__func__, "Minimum value out of range: %g!", zref);
12145 return (707);
12146 }
12147
12148 if ( CGRIBEX_Const && !lspherc )
12149 {
12150 if ( IS_EQUAL(fmin, fmax) ) nbpv = 0;
12151 }
12152
12153 long blockLength = (*datstart) + (nbpv*(datasize - PackStart) + 7)/8;
12154 blockLength += blockLength & 1;
12155
12156 const long unused_bits = blockLength*8 - (*datstart)*8 - nbpv*(datasize - PackStart);
12157
12158 Flag += unused_bits;
12159
12160
12161 // Adjust number of bits per value if full integer length to avoid hitting most significant bit (sign bit).
12162 // if( nbpv == ibits ) nbpv = nbpv - 1;
12163 /*
12164 Calculate the binary scaling factor to spread the range of values over the number of bits per value.
12165 Limit scaling to 2**-126 to 2**127 (using IEEE 32-bit floatsas a guideline).
12166 */
12167 const double range = fabs(fmax - fmin);
12168
12169 if ( fabs(fmin) < FLT_MIN ) fmin = 0;
12170 /*
12171 Have to allow tolerance in comparisons on some platforms (eg vpp700 and linux),
12172 such as 0.9999999999999999 = 1.0, to avoid clipping ranges which are a power of 2.
12173 */
12174 if ( range <= jpepsln )
12175 {
12176 binscale = 0;
12177 }
12178 else if ( IS_NOT_EQUAL(fmin, 0.0) && (fabs(range/fmin) <= jpepsln) )
12179 {
12180 binscale = 0;
12181 }
12182 else if ( fabs(range-1.0) <= jpepsln )
12183 {
12184 binscale = 1 - nbpv;
12185 }
12186 else if ( range > 1.0 )
12187 {
12188 const double rangec = range + jpepsln;
12189 double p2 = 2.0;
12190 int jloop = 1;
12191 while ( jloop < 128 && p2 <= rangec )
12192 {
12193 p2 *= 2.0;
12194 ++jloop;
12195 }
12196 if (jloop < 128)
12197 binscale = jloop - nbpv;
12198 else
12199 {
12200 gprintf(__func__, "Problem calculating binary scale value for encode code %d!", code);
12201 gprintf(__func__, "> range %g rangec %g fmin %g fmax %g", range, rangec, fmin, fmax);
12202 return (707);
12203 }
12204 }
12205 else
12206 {
12207 const double rangec = range - jpepsln;
12208 double p05 = 0.5;
12209 int jloop = 1;
12210 while ( jloop < 127 && p05 >= rangec )
12211 {
12212 p05 *= 0.5;
12213 jloop++;
12214 }
12215 if ( jloop < 127 )
12216 {
12217 binscale = 1 - jloop - nbpv;
12218 }
12219 else
12220 {
12221 gprintf(__func__, "Problem calculating binary scale value for encode code %d!", code);
12222 gprintf(__func__, "< range %g rangec %g fmin %g fmax %g", range, rangec, fmin, fmax);
12223 return (707);
12224 }
12225 }
12226
12227 const uint64_t max_nbpv_pow2 = (uint64_t) ((1ULL << nbpv) - 1);
12228
12229 if ( binscale != 0 )
12230 {
12231 while ( (uint64_t)(ldexp(range, -binscale)+0.5) > max_nbpv_pow2 ) binscale++;
12232
12233 factor = (T)intpow2(-binscale);
12234 }
12235
12236 ref2ibm(&zref, BitsPerInt);
12237
12238 Put3Byte(blockLength); // 0-2 Length of Block 4
12239 Put1Byte(Flag); // 3 Flag & Unused bits
12240 if ( binscale < 0 ) binscale = 32768 - binscale;
12241 Put2Byte(binscale); // 4-5 Scale factor
12242 Put1Real(zref); // 6-9 Reference value
12243 Put1Byte(nbpv); // 10 Packing size
12244
12245 if ( lspherc )
12246 {
12247 if ( lcomplex )
12248 {
12249 const int jup = isubset;
12250 int ioff = (int)z + bds_ext;
12251 if ( ioff > 0xFFFF ) ioff = 0;
12252 Put2Byte(ioff);
12253 Put2Int(isec4[16]);
12254 Put1Byte(jup);
12255 Put1Byte(jup);
12256 Put1Byte(jup);
12257 for ( long i = 0; i < ((jup+1)*(jup+2)); i++ ) Put1Real((double)(data[i]));
12258 }
12259 else
12260 {
12261 Put1Real((double)(data[0]));
12262 }
12263 }
12264
12265 *datsize = ((datasize-PackStart)*nbpv + 7)/8;
12266
12267 #if defined (_ARCH_PWR6)
12268 TEMPLATE(encode_array_unrolled,T)(nbpv, (size_t)PackStart, (size_t)datasize, lGrib, data, (T)zref, factor, &z);
12269 #else
12270 TEMPLATE(encode_array,T)(nbpv, (size_t)PackStart, (size_t)datasize, lGrib, data, (T)zref, factor, &z);
12271 #endif
12272
12273 if ( unused_bits >= 8 ) Put1Byte(0); // Fillbyte
12274
12275 *gribLen = (long)z;
12276
12277 return 0;
12278 }
12279
12280
TEMPLATE(grib_encode,T)12281 void TEMPLATE(grib_encode,T)(int *isec0, int *isec1, int *isec2, T *fsec2, int *isec3,
12282 T *fsec3, int *isec4, T *fsec4, int klenp, int *kgrib,
12283 int kleng, int *kword, int efunc, int *kret)
12284 {
12285 long gribLen = 0; // Counter of GRIB length for output
12286 long fsec4size = 0;
12287 long datstart, datsize;
12288
12289 UNUSED(isec3);
12290 UNUSED(efunc);
12291
12292 grsdef();
12293
12294 unsigned char *CGrib = (unsigned char *) kgrib;
12295
12296 const bool gdsIncluded = ISEC1_Sec2Or3Flag & 128;
12297 const bool bmsIncluded = ISEC1_Sec2Or3Flag & 64;
12298
12299 // set max header len
12300 size_t len = 16384;
12301
12302 // add data len
12303 const size_t numBytes = (size_t)((ISEC4_NumBits+7)>>3);
12304
12305 len += numBytes*(size_t)klenp;
12306
12307 // add bitmap len
12308 if ( bmsIncluded ) len += (size_t)((klenp+7)>>3);
12309
12310 #ifdef VECTORCODE
12311 GRIBPACK *lGrib = (GRIBPACK*) Malloc(len*sizeof(GRIBPACK));
12312 if ( lGrib == NULL ) SysError("No Memory!");
12313 #else
12314 GRIBPACK *lGrib = CGrib;
12315 #endif
12316
12317 const long isLen = 8;
12318 encodeIS(lGrib, &gribLen);
12319 GRIBPACK *lpds = &lGrib[isLen];
12320 const long pdsLen = getPdsLen(isec1);
12321
12322 encodePDS(lpds, pdsLen, isec1);
12323 gribLen += pdsLen;
12324 /*
12325 if ( ( isec4[3] == 64 ) && ( isec2[5] == 2 ) )
12326 {
12327 static bool lwarn_cplx = true;
12328
12329 if ( lwarn_cplx )
12330 Message("Complex packing of spectral data unsupported, using simple packing!");
12331
12332 isec2[5] = 1;
12333 isec4[3] = 0;
12334
12335 lwarn_cplx = false;
12336 }
12337 */
12338 if ( gdsIncluded ) TEMPLATE(encodeGDS,T)(lGrib, &gribLen, isec2, fsec2);
12339 /*
12340 ----------------------------------------------------------------
12341 BMS Bit-Map Section Section (Section 3)
12342 ----------------------------------------------------------------
12343 */
12344 if ( bmsIncluded )
12345 {
12346 TEMPLATE(encodeBMS,T)(lGrib, &gribLen, fsec3, isec4, fsec4, &fsec4size);
12347 }
12348 else
12349 {
12350 fsec4size = ISEC4_NumValues;
12351 }
12352
12353 const long bdsstart = gribLen;
12354 int status = TEMPLATE(encodeBDS,T)(lGrib, &gribLen, ISEC1_DecScaleFactor, isec2,
12355 isec4, fsec4size, fsec4, &datstart, &datsize, ISEC1_Parameter);
12356 if ( status )
12357 {
12358 *kret = status;
12359 return;
12360 }
12361
12362 encodeES(lGrib, &gribLen, bdsstart);
12363
12364 if ( (size_t) gribLen > (size_t)kleng*sizeof(int) )
12365 Error("kgrib buffer too small! kleng = %d gribLen = %d", kleng, gribLen);
12366
12367 #ifdef VECTORCODE
12368 if ( (size_t) gribLen > len )
12369 Error("lGrib buffer too small! len = %d gribLen = %d", len, gribLen);
12370
12371 (void) PACK_GRIB(lGrib, (unsigned char *)CGrib, gribLen, -1L);
12372
12373 Free(lGrib);
12374 #endif
12375
12376 ISEC0_GRIB_Len = (int)gribLen;
12377 ISEC0_GRIB_Version = 1;
12378
12379 *kword = (int)((gribLen + (long)sizeof(int) - 1) / (long)sizeof(int));
12380
12381 *kret = status;
12382 }
12383
12384 #endif /* T */
12385
12386 /*
12387 * Local Variables:
12388 * mode: c
12389 * End:
12390 */
12391
12392 #ifdef T
12393 #undef T
12394 #endif
12395 #define T float
12396 #ifdef T
12397
12398 // GRIB BLOCK 2 - GRID DESCRIPTION SECTION
12399 static
TEMPLATE(encodeGDS,T)12400 void TEMPLATE(encodeGDS,T)(GRIBPACK *lGrib, long *gribLen, int *isec2, T *fsec2)
12401 {
12402 long z = *gribLen;
12403 int exponent, mantissa;
12404 int ival;
12405 int gdslen = 32;
12406
12407 if ( ISEC2_GridType == GRIB1_GTYPE_LCC ) gdslen += 10;
12408
12409 if ( ISEC2_GridType == GRIB1_GTYPE_LATLON_ROT ) gdslen += 10;
12410
12411 const int pvoffset = (ISEC2_NumVCP || ISEC2_Reduced) ? gdslen + 1 : 0xFF;
12412
12413 if ( ISEC2_Reduced ) gdslen += 2 * ISEC2_NumLat;
12414
12415 gdslen += ISEC2_NumVCP * 4;
12416
12417 Put3Byte(gdslen); /* 0- 2 Length of Block 2 Byte 0 */
12418 Put1Byte(ISEC2_NumVCP); /* 3 NV */
12419 Put1Byte(pvoffset); /* 4 PV */
12420 Put1Byte(ISEC2_GridType); /* 5 LatLon=0 Gauss=4 Spectral=50 */
12421
12422 if ( ISEC2_GridType == GRIB1_GTYPE_SPECTRAL )
12423 {
12424 Put2Byte(ISEC2_PentaJ); /* 6- 7 Pentagonal resolution J */
12425 Put2Byte(ISEC2_PentaK); /* 8- 9 Pentagonal resolution K */
12426 Put2Byte(ISEC2_PentaM); /* 10-11 Pentagonal resolution M */
12427 Put1Byte(ISEC2_RepType); /* 12 Representation type */
12428 Put1Byte(ISEC2_RepMode); /* 13 Representation mode */
12429 PutnZero(18); /* 14-31 reserved */
12430 }
12431 else if ( ISEC2_GridType == GRIB1_GTYPE_GME )
12432 {
12433 Put2Byte(ISEC2_GME_NI2);
12434 Put2Byte(ISEC2_GME_NI3);
12435 Put3Byte(ISEC2_GME_ND);
12436 Put3Byte(ISEC2_GME_NI);
12437 Put1Byte(ISEC2_GME_AFlag);
12438 Put3Int(ISEC2_GME_LatPP);
12439 Put3Int(ISEC2_GME_LonPP);
12440 Put3Int(ISEC2_GME_LonMPL);
12441 Put1Byte(ISEC2_GME_BFlag);
12442 PutnZero(5);
12443 }
12444 else if ( ISEC2_GridType == GRIB1_GTYPE_LCC )
12445 {
12446 Put2Byte(ISEC2_NumLon); /* 6- 7 Longitudes */
12447
12448 Put2Byte(ISEC2_NumLat); /* 8- 9 Latitudes */
12449 Put3Int(ISEC2_FirstLat);
12450 Put3Int(ISEC2_FirstLon);
12451 Put1Byte(ISEC2_ResFlag); /* 16 Resolution flag */
12452 Put3Int(ISEC2_Lambert_Lov); /* 17-19 */
12453 Put3Int(ISEC2_Lambert_dx); /* 20-22 */
12454 Put3Int(ISEC2_Lambert_dy); /* 23-25 */
12455 Put1Byte(ISEC2_Lambert_ProjFlag);/* 26 Projection flag */
12456 Put1Byte(ISEC2_ScanFlag); /* 27 Scanning mode */
12457 Put3Int(ISEC2_Lambert_LatS1); /* 28-30 */
12458 Put3Int(ISEC2_Lambert_LatS2); /* 31-33 */
12459 Put3Int(ISEC2_Lambert_LatSP); /* 34-36 */
12460 Put3Int(ISEC2_Lambert_LonSP); /* 37-39 */
12461 PutnZero(2); /* 34-41 */
12462 }
12463 else if ( ISEC2_GridType == GRIB1_GTYPE_LATLON ||
12464 ISEC2_GridType == GRIB1_GTYPE_GAUSSIAN ||
12465 ISEC2_GridType == GRIB1_GTYPE_LATLON_ROT )
12466 {
12467 const int numlon = ISEC2_Reduced ? 0xFFFF : ISEC2_NumLon;
12468 Put2Byte(numlon); /* 6- 7 Number of Longitudes */
12469
12470 Put2Byte(ISEC2_NumLat); /* 8- 9 Number of Latitudes */
12471 Put3Int(ISEC2_FirstLat);
12472 Put3Int(ISEC2_FirstLon);
12473 Put1Byte(ISEC2_ResFlag); /* 16 Resolution flag */
12474 Put3Int(ISEC2_LastLat);
12475 Put3Int(ISEC2_LastLon);
12476 const unsigned lonIncr = (ISEC2_ResFlag == 0) ? 0xFFFF : (unsigned)ISEC2_LonIncr;
12477 const unsigned latIncr = (ISEC2_ResFlag == 0) ? 0xFFFF : (unsigned)ISEC2_LatIncr;
12478 Put2Byte(lonIncr); /* 23-24 i - direction increment */
12479 if ( ISEC2_GridType == GRIB1_GTYPE_GAUSSIAN )
12480 Put2Byte(ISEC2_NumPar); /* 25-26 Latitudes Pole->Equator */
12481 else
12482 Put2Byte(latIncr); /* 25-26 j - direction increment */
12483
12484 Put1Byte(ISEC2_ScanFlag); /* 27 Scanning mode */
12485 PutnZero(4); /* 28-31 reserved */
12486
12487 if ( ISEC2_GridType == GRIB1_GTYPE_LATLON_ROT )
12488 {
12489 Put3Int(ISEC2_LatSP);
12490 Put3Int(ISEC2_LonSP);
12491 Put1Real((double)(FSEC2_RotAngle));
12492 }
12493 }
12494 else
12495 {
12496 Error("Unsupported grid type %d", ISEC2_GridType);
12497 }
12498
12499 #if defined (SX)
12500 #pragma vdir novector /* vectorization gives wrong results on NEC */
12501 #endif
12502 for ( long i = 0; i < ISEC2_NumVCP; ++i )
12503 {
12504 Put1Real((double)(fsec2[10+i]));
12505 }
12506
12507 if ( ISEC2_Reduced )
12508 for ( long i = 0; i < ISEC2_NumLat; i++ ) Put2Byte(ISEC2_ReducedPoints(i));
12509
12510 *gribLen = z;
12511 }
12512
12513 // GRIB BLOCK 3 - BIT MAP SECTION
12514 static
TEMPLATE(encodeBMS,T)12515 void TEMPLATE(encodeBMS,T)(GRIBPACK *lGrib, long *gribLen, T *fsec3, int *isec4, T *data, long *datasize)
12516 {
12517 long z = *gribLen;
12518 static bool lmissvalinfo = true;
12519 // unsigned int c, imask;
12520
12521 if ( DBL_IS_NAN(FSEC3_MissVal) && lmissvalinfo)
12522 {
12523 lmissvalinfo = false;
12524 Message("Missing value = NaN is unsupported!");
12525 }
12526
12527 const long bitmapSize = ISEC4_NumValues;
12528 const long imaskSize = ((bitmapSize+7)>>3)<<3;
12529 GRIBPACK *bitmap = &lGrib[z+6];
12530 long fsec4size = 0;
12531
12532 #ifdef VECTORCODE
12533 unsigned int *imask = (unsigned int*) Malloc(imaskSize*sizeof(unsigned int));
12534 memset(imask, 0, imaskSize*sizeof(int));
12535
12536 #if defined (CRAY)
12537 #pragma _CRI ivdep
12538 #endif
12539 #if defined (SX)
12540 #pragma vdir nodep
12541 #endif
12542 #ifdef __uxpch__
12543 #pragma loop novrec
12544 #endif
12545 for ( long i = 0; i < bitmapSize; i++ )
12546 {
12547 if ( IS_NOT_EQUAL(data[i], FSEC3_MissVal) )
12548 {
12549 data[fsec4size++] = data[i];
12550 imask[i] = 1;
12551 }
12552 }
12553
12554 #if defined (CRAY)
12555 #pragma _CRI ivdep
12556 #endif
12557 #if defined (SX)
12558 #pragma vdir nodep
12559 #endif
12560 #ifdef __uxpch__
12561 #pragma loop novrec
12562 #endif
12563 for ( long i = 0; i < imaskSize/8; i++ )
12564 {
12565 bitmap[i] = (imask[i*8+0] << 7) | (imask[i*8+1] << 6) |
12566 (imask[i*8+2] << 5) | (imask[i*8+3] << 4) |
12567 (imask[i*8+4] << 3) | (imask[i*8+5] << 2) |
12568 (imask[i*8+6] << 1) | (imask[i*8+7]);
12569 }
12570
12571 Free(imask);
12572 #else
12573 for ( long i = 0; i < imaskSize/8; i++ ) bitmap[i] = 0;
12574
12575 for ( long i = 0; i < bitmapSize; i++ )
12576 {
12577 if ( IS_NOT_EQUAL(data[i], FSEC3_MissVal) )
12578 {
12579 data[fsec4size++] = data[i];
12580 bitmap[i/8] |= (GRIBPACK)(1<<(7-(i&7)));
12581 }
12582 }
12583 #endif
12584
12585 const long bmsLen = imaskSize/8 + 6;
12586 const long bmsUnusedBits = imaskSize - bitmapSize;
12587
12588 Put3Byte(bmsLen); /* 0- 2 Length of Block 3 Byte 0 */
12589 Put1Byte(bmsUnusedBits);
12590 Put2Byte(0);
12591
12592 *gribLen += bmsLen;
12593
12594 *datasize = fsec4size;
12595 }
12596
12597 #define pow_double pow
12598 #define pow_float powf
12599
12600 // GRIB BLOCK 4 - BINARY DATA SECTION
12601 static
TEMPLATE(encodeBDS,T)12602 int TEMPLATE(encodeBDS,T)(GRIBPACK *lGrib, long *gribLen, int decscale, int *isec2, int *isec4, long datasize, T *data,
12603 long *datstart, long *datsize, int code)
12604 {
12605 // Uwe Schulzweida, 11/04/2003 : Check that number of bits per value is not exceeded
12606 // Uwe Schulzweida, 6/05/2003 : Copy result to fpval to prevent integer overflow
12607
12608 size_t z = (size_t)*gribLen;
12609 int numBits;
12610 int ival;
12611 long PackStart = 0;
12612 int Flag = 0;
12613 int binscale = 0;
12614 int bds_head = 11;
12615 int bds_ext = 0;
12616 /* ibits = BitsPerInt; */
12617 int exponent, mantissa;
12618 bool lspherc = false;
12619 int isubset = 0, itemp = 0, itrunc = 0;
12620 T factor = 1, fmin, fmax;
12621 const double jpepsln = 1.0e-12; // -----> tolerance used to check equality
12622 // of floating point numbers - needed
12623 // on some platforms (eg vpp700, linux)
12624 extern int CGRIBEX_Const; // 1: Don't pack constant fields on regular grids
12625
12626 if ( isec2 )
12627 {
12628 /* If section 2 is present, it says if data is spherical harmonic */
12629
12630 lspherc = ( isec2[0] == 50 || isec2[0] == 60 ||
12631 isec2[0] == 70 || isec2[0] == 80 );
12632
12633 isec4[2] = lspherc ? 128 : 0;
12634 }
12635 else
12636 {
12637 /* Section 4 says if it's spherical harmonic data.. */
12638
12639 lspherc = ( isec4[2] == 128 );
12640 }
12641
12642 /* Complex packing supported for spherical harmonics. */
12643
12644 const bool lcomplex = ( lspherc && ( isec4[3] == 64 ) ) ||
12645 ( lspherc && isec2 && ( isec2[5] == 2 ) );
12646
12647 // Check input specification is consistent
12648
12649 if ( lcomplex && isec2 )
12650 {
12651 if ( ( isec4[3] != 64 ) && ( isec2[5] == 2 ) )
12652 {
12653 gprintf(__func__, " COMPLEX mismatch. isec4[3] = %d\n", isec4[3]);
12654 gprintf(__func__, " COMPLEX mismatch. isec2[5] = %d\n", isec2[5]);
12655 return (807);
12656 }
12657 else if ( ( isec4[3] == 64 ) && ( isec2[5] != 2 ) )
12658 {
12659 gprintf(__func__, " COMPLEX mismatch. isec4[3] = %d\n", isec4[3]);
12660 gprintf(__func__, " COMPLEX mismatch. isec2[5] = %d\n", isec2[5]);
12661 return (807);
12662 }
12663 else if ( lcomplex )
12664 {
12665 // Truncation of full spectrum, which is supposed triangular, has to be diagnosed. Define also sub-set truncation.
12666 isubset = isec4[17];
12667 // When encoding, use the total number of data.
12668 itemp = isec4[0];
12669 itrunc = (int) (sqrt(itemp*4 + 1.) - 3) / 2;
12670 }
12671 }
12672
12673 if ( decscale )
12674 {
12675 const T scale = TEMPLATE(pow,T)((T)10.0, (T)decscale);
12676 for ( long i = 0; i < datasize; ++i ) data[i] *= scale;
12677 }
12678
12679 if ( lspherc )
12680 {
12681 if ( lcomplex )
12682 {
12683 const int jup = isubset;
12684 const int ioff = (jup+1)*(jup+2);
12685 bds_ext = 4 + 3 + 4*ioff;
12686 PackStart = ioff;
12687 Flag = 192;
12688 }
12689 else
12690 {
12691 bds_ext = 4;
12692 PackStart = 1;
12693 Flag = 128;
12694 }
12695 }
12696
12697 *datstart = bds_head + bds_ext;
12698
12699 int nbpv = numBits = ISEC4_NumBits;
12700
12701 if ( lspherc && lcomplex )
12702 {
12703 const int pcStart = isubset;
12704 const int pcScale = isec4[16];
12705 TEMPLATE(scale_complex,T)(data, pcStart, pcScale, itrunc, 0);
12706 TEMPLATE(gather_complex,T)(data, (size_t)pcStart, (size_t)itrunc, (size_t)datasize);
12707 }
12708
12709 fmin = fmax = data[PackStart];
12710
12711 TEMPLATE(minmax_val,T)(data+PackStart, datasize-PackStart, &fmin, &fmax);
12712
12713 double zref = (double)fmin;
12714 if (!(zref < DBL_MAX && zref > -DBL_MAX))
12715 {
12716 gprintf(__func__, "Minimum value out of range: %g!", zref);
12717 return (707);
12718 }
12719
12720 if ( CGRIBEX_Const && !lspherc )
12721 {
12722 if ( IS_EQUAL(fmin, fmax) ) nbpv = 0;
12723 }
12724
12725 long blockLength = (*datstart) + (nbpv*(datasize - PackStart) + 7)/8;
12726 blockLength += blockLength & 1;
12727
12728 const long unused_bits = blockLength*8 - (*datstart)*8 - nbpv*(datasize - PackStart);
12729
12730 Flag += unused_bits;
12731
12732
12733 // Adjust number of bits per value if full integer length to avoid hitting most significant bit (sign bit).
12734 // if( nbpv == ibits ) nbpv = nbpv - 1;
12735 /*
12736 Calculate the binary scaling factor to spread the range of values over the number of bits per value.
12737 Limit scaling to 2**-126 to 2**127 (using IEEE 32-bit floatsas a guideline).
12738 */
12739 const double range = fabs(fmax - fmin);
12740
12741 if ( fabs(fmin) < FLT_MIN ) fmin = 0;
12742 /*
12743 Have to allow tolerance in comparisons on some platforms (eg vpp700 and linux),
12744 such as 0.9999999999999999 = 1.0, to avoid clipping ranges which are a power of 2.
12745 */
12746 if ( range <= jpepsln )
12747 {
12748 binscale = 0;
12749 }
12750 else if ( IS_NOT_EQUAL(fmin, 0.0) && (fabs(range/fmin) <= jpepsln) )
12751 {
12752 binscale = 0;
12753 }
12754 else if ( fabs(range-1.0) <= jpepsln )
12755 {
12756 binscale = 1 - nbpv;
12757 }
12758 else if ( range > 1.0 )
12759 {
12760 const double rangec = range + jpepsln;
12761 double p2 = 2.0;
12762 int jloop = 1;
12763 while ( jloop < 128 && p2 <= rangec )
12764 {
12765 p2 *= 2.0;
12766 ++jloop;
12767 }
12768 if (jloop < 128)
12769 binscale = jloop - nbpv;
12770 else
12771 {
12772 gprintf(__func__, "Problem calculating binary scale value for encode code %d!", code);
12773 gprintf(__func__, "> range %g rangec %g fmin %g fmax %g", range, rangec, fmin, fmax);
12774 return (707);
12775 }
12776 }
12777 else
12778 {
12779 const double rangec = range - jpepsln;
12780 double p05 = 0.5;
12781 int jloop = 1;
12782 while ( jloop < 127 && p05 >= rangec )
12783 {
12784 p05 *= 0.5;
12785 jloop++;
12786 }
12787 if ( jloop < 127 )
12788 {
12789 binscale = 1 - jloop - nbpv;
12790 }
12791 else
12792 {
12793 gprintf(__func__, "Problem calculating binary scale value for encode code %d!", code);
12794 gprintf(__func__, "< range %g rangec %g fmin %g fmax %g", range, rangec, fmin, fmax);
12795 return (707);
12796 }
12797 }
12798
12799 const uint64_t max_nbpv_pow2 = (uint64_t) ((1ULL << nbpv) - 1);
12800
12801 if ( binscale != 0 )
12802 {
12803 while ( (uint64_t)(ldexp(range, -binscale)+0.5) > max_nbpv_pow2 ) binscale++;
12804
12805 factor = (T)intpow2(-binscale);
12806 }
12807
12808 ref2ibm(&zref, BitsPerInt);
12809
12810 Put3Byte(blockLength); // 0-2 Length of Block 4
12811 Put1Byte(Flag); // 3 Flag & Unused bits
12812 if ( binscale < 0 ) binscale = 32768 - binscale;
12813 Put2Byte(binscale); // 4-5 Scale factor
12814 Put1Real(zref); // 6-9 Reference value
12815 Put1Byte(nbpv); // 10 Packing size
12816
12817 if ( lspherc )
12818 {
12819 if ( lcomplex )
12820 {
12821 const int jup = isubset;
12822 int ioff = (int)z + bds_ext;
12823 if ( ioff > 0xFFFF ) ioff = 0;
12824 Put2Byte(ioff);
12825 Put2Int(isec4[16]);
12826 Put1Byte(jup);
12827 Put1Byte(jup);
12828 Put1Byte(jup);
12829 for ( long i = 0; i < ((jup+1)*(jup+2)); i++ ) Put1Real((double)(data[i]));
12830 }
12831 else
12832 {
12833 Put1Real((double)(data[0]));
12834 }
12835 }
12836
12837 *datsize = ((datasize-PackStart)*nbpv + 7)/8;
12838
12839 #if defined (_ARCH_PWR6)
12840 TEMPLATE(encode_array_unrolled,T)(nbpv, (size_t)PackStart, (size_t)datasize, lGrib, data, (T)zref, factor, &z);
12841 #else
12842 TEMPLATE(encode_array,T)(nbpv, (size_t)PackStart, (size_t)datasize, lGrib, data, (T)zref, factor, &z);
12843 #endif
12844
12845 if ( unused_bits >= 8 ) Put1Byte(0); // Fillbyte
12846
12847 *gribLen = (long)z;
12848
12849 return 0;
12850 }
12851
12852
TEMPLATE(grib_encode,T)12853 void TEMPLATE(grib_encode,T)(int *isec0, int *isec1, int *isec2, T *fsec2, int *isec3,
12854 T *fsec3, int *isec4, T *fsec4, int klenp, int *kgrib,
12855 int kleng, int *kword, int efunc, int *kret)
12856 {
12857 long gribLen = 0; // Counter of GRIB length for output
12858 long fsec4size = 0;
12859 long datstart, datsize;
12860
12861 UNUSED(isec3);
12862 UNUSED(efunc);
12863
12864 grsdef();
12865
12866 unsigned char *CGrib = (unsigned char *) kgrib;
12867
12868 const bool gdsIncluded = ISEC1_Sec2Or3Flag & 128;
12869 const bool bmsIncluded = ISEC1_Sec2Or3Flag & 64;
12870
12871 // set max header len
12872 size_t len = 16384;
12873
12874 // add data len
12875 const size_t numBytes = (size_t)((ISEC4_NumBits+7)>>3);
12876
12877 len += numBytes*(size_t)klenp;
12878
12879 // add bitmap len
12880 if ( bmsIncluded ) len += (size_t)((klenp+7)>>3);
12881
12882 #ifdef VECTORCODE
12883 GRIBPACK *lGrib = (GRIBPACK*) Malloc(len*sizeof(GRIBPACK));
12884 if ( lGrib == NULL ) SysError("No Memory!");
12885 #else
12886 GRIBPACK *lGrib = CGrib;
12887 #endif
12888
12889 const long isLen = 8;
12890 encodeIS(lGrib, &gribLen);
12891 GRIBPACK *lpds = &lGrib[isLen];
12892 const long pdsLen = getPdsLen(isec1);
12893
12894 encodePDS(lpds, pdsLen, isec1);
12895 gribLen += pdsLen;
12896 /*
12897 if ( ( isec4[3] == 64 ) && ( isec2[5] == 2 ) )
12898 {
12899 static bool lwarn_cplx = true;
12900
12901 if ( lwarn_cplx )
12902 Message("Complex packing of spectral data unsupported, using simple packing!");
12903
12904 isec2[5] = 1;
12905 isec4[3] = 0;
12906
12907 lwarn_cplx = false;
12908 }
12909 */
12910 if ( gdsIncluded ) TEMPLATE(encodeGDS,T)(lGrib, &gribLen, isec2, fsec2);
12911 /*
12912 ----------------------------------------------------------------
12913 BMS Bit-Map Section Section (Section 3)
12914 ----------------------------------------------------------------
12915 */
12916 if ( bmsIncluded )
12917 {
12918 TEMPLATE(encodeBMS,T)(lGrib, &gribLen, fsec3, isec4, fsec4, &fsec4size);
12919 }
12920 else
12921 {
12922 fsec4size = ISEC4_NumValues;
12923 }
12924
12925 const long bdsstart = gribLen;
12926 int status = TEMPLATE(encodeBDS,T)(lGrib, &gribLen, ISEC1_DecScaleFactor, isec2,
12927 isec4, fsec4size, fsec4, &datstart, &datsize, ISEC1_Parameter);
12928 if ( status )
12929 {
12930 *kret = status;
12931 return;
12932 }
12933
12934 encodeES(lGrib, &gribLen, bdsstart);
12935
12936 if ( (size_t) gribLen > (size_t)kleng*sizeof(int) )
12937 Error("kgrib buffer too small! kleng = %d gribLen = %d", kleng, gribLen);
12938
12939 #ifdef VECTORCODE
12940 if ( (size_t) gribLen > len )
12941 Error("lGrib buffer too small! len = %d gribLen = %d", len, gribLen);
12942
12943 (void) PACK_GRIB(lGrib, (unsigned char *)CGrib, gribLen, -1L);
12944
12945 Free(lGrib);
12946 #endif
12947
12948 ISEC0_GRIB_Len = (int)gribLen;
12949 ISEC0_GRIB_Version = 1;
12950
12951 *kword = (int)((gribLen + (long)sizeof(int) - 1) / (long)sizeof(int));
12952
12953 *kret = status;
12954 }
12955
12956 #endif /* T */
12957
12958 /*
12959 * Local Variables:
12960 * mode: c
12961 * End:
12962 */
12963
12964 void encode_dummy(void);
encode_dummy(void)12965 void encode_dummy(void)
12966 {
12967 (void) encode_array_unrolled_double(0, 0, 0, NULL, NULL, 0, 0, NULL);
12968 (void) encode_array_unrolled_float(0, 0, 0, NULL, NULL, 0, 0, NULL);
12969 }
12970 static const char grb_libvers[] = "2.0.0";
12971 const char *
cgribexLibraryVersion(void)12972 cgribexLibraryVersion(void)
12973 {
12974 return (grb_libvers);
12975 }
12976
12977 #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 5)
12978 #pragma GCC diagnostic pop
12979 #endif
12980
12981