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