source: trunk/WRF.COMMON/WRFV2/external/io_grib1/MEL_grib1/pack_spatial.c

Last change on this file was 11, checked in by aslmd, 14 years ago

spiga@svn-planeto:ajoute le modele meso-echelle martien

File size: 19.4 KB
Line 
1/* 20jun97/atn:  always scaling data up whether dsf is -/+;
2*/
3#include <stdio.h> 
4#include <stdlib.h>
5#include <string.h> 
6#include <math.h>
7#ifdef XT3_Catamount
8#include <features.h>
9#undef htonl
10#define htonl(x)     swap_byte4(x)
11#else
12#include <netinet/in.h>
13#endif
14#include "dprints.h"            /* for dprints */
15#include "gribfuncs.h"          /* prototypes */
16#include "isdb.h"               /* WORD_BIT_CNT defn */
17
18/*
19****************************************************************
20* A. FUNCTION:   pack_spatial
21*      pack gridded data values into a bitstream
22*
23*    INTERFACE:
24*      int     pack_spatial (pt_cnt, bit_cnt, pack_null, fbuff, ppbitstream,
25*                           dec_scl_fctr, BDSlength, errmsg)
26*
27*    ARGUMENTS (I=input, O=output, I&O=input and output):
28*     (I) long *pt_cnt;                count of points in grid
29*     (I) long *bit_cnt;               count of bits to pack value in. 
30*                                      will be calculated if set to zero
31*     (I) float *pack_null;            parameter value for null (huge number)
32*   (I&O) float *fbuff;                array containing grid values to pack
33*                                     returned scaled up by Decimal Scale Factor
34*     (O) unsigned long **ppbitstream; Null upon entry;
35*                                      returned pointing to new Storage
36*                                      holding packed bitstream;
37*     (I) short dec_scl_fctr;          decimal scale factor to apply to data
38*     (O) long  *BDSlength;            updated with #bytes in packed bitstream
39*     (O) char  *errmsg                returned filled if error occurred
40*
41*    RETURN CODE:
42*      0> success, ppbitstream contains packed values
43*   else> error: errmsg holds msg;
44****************************************************************
45*/
46#if PROTOTYPE_NEEDED
47int     pack_spatial ( long             *pt_cnt,
48                        unsigned short  *bit_cnt,
49                        float           *pack_null,
50                        float           *fbuff,
51                        unsigned long   **ppbitstream,
52                        short           dec_scl_fctr,
53                        long            *BDSlength,
54                        char            *errmsg)
55
56#else
57int     pack_spatial (  pt_cnt, bit_cnt, pack_null, fbuff, ppbitstream,
58                        dec_scl_fctr, BDSlength, errmsg)
59                        long            *pt_cnt;
60                        unsigned short  *bit_cnt;
61                        float           *pack_null;
62                        float           *fbuff;
63                        unsigned long   **ppbitstream;
64                        short           dec_scl_fctr;
65                        long            *BDSlength;
66                        char            *errmsg;
67#endif
68{
69    char *func="pack_spatial";
70    long ipt;                   /* index over points */
71    int null_flag;              /* flag indicating presence of null values */
72    int bit1;                   /* starting bit in current word */ 
73    int empty;                  /* number of empty bits in word */ 
74    int diff;                   /* difference of empty - bit1 */ 
75    long max_value;             /* max value storable in bit_cnt bits */
76    unsigned long itemp;        /* temporary unsigned integer */
77    unsigned long *bstr;        /* pointer running across bitstream */
78    int pack_bit_cnt;           /* count of bits to pack parameter values */ 
79    int unused_bit_cnt;         /* count of unused bits for i2 words */
80    /*long byte4_cnt;           /- count of bytes using i4 words */
81    long byte2_cnt;             /* count of bytes using i2 words */
82    short scl_fctr;             /* scaling factor for grid values */
83    double pow_scl;             /* 2 ** (-scl_fctr) */
84    double pwr10toD;            /* 10 ** (D) */
85    float reference;            /* reference = minimum value in grid */
86    float max_grid;             /* maximum value in grid */
87    float ftemp;                /* temporary float containing grid value */
88    unsigned long *pBitstream;
89    unsigned long grib_local_ibm();
90    int wordnum;
91    int zero_cnt;
92    int prec_too_high = 0;
93    unsigned char bdshdr[14];   /* Character array to temporarily hold bds
94                                 *   header */
95    int hdrwords;
96
97    DPRINT1 ( "Entering %s....\n", func );
98
99/*
100*
101* A.1       IF (no data in grid) THEN
102*              PRINT message
103*              RETURN Stat= -1
104*           ENDIF
105*/
106    if (*pt_cnt <= 0) {
107        DPRINT2 ("%s; invalid pt_cnt = %d\n", func,*pt_cnt);
108        sprintf(errmsg, "%s; invalid pt_cnt = %d\n", func,*pt_cnt);
109        return (-1);
110    }
111
112/*
113*
114* A.2       IF (number of bits to pack into is greater than 30) THEN
115*               PRINT message
116*               RETURN Stat= -1
117*           ENDIF
118*           SET pack_bit_cnt for local use
119*/
120    if ( *bit_cnt > 30 ) {
121        DPRINT2 ("%s; invalid bit_cnt = %d\n", func,*bit_cnt);
122        sprintf(errmsg, "%s; invalid bit_cnt = %d\n", func,*bit_cnt);
123        return (-1);
124    }
125    pack_bit_cnt        = (int) *bit_cnt; 
126    DPRINT1 ("  use Pack_bit_cnt= %d\n", pack_bit_cnt);
127
128/*
129*               
130* A.3      FOR (each data point) DO
131*              SCALE all values of data array  !multiply by 10**DSF
132*          ENDDO
133*/
134        pwr10toD=  pow ( 10., (double) dec_scl_fctr );
135        for (ipt=0; ipt < *pt_cnt; ipt++)  fbuff[ipt] *= pwr10toD;
136
137        DPRINT2 ("  Decimal Scale Fctr= %d, scale data by 10**dsf "\
138        "(Fbuff *= %lf)\n", dec_scl_fctr,  pwr10toD);
139/*
140*
141* A.4       INIT reference, max_grid, null_flag
142*/
143    reference   = 1.e30;
144    max_grid    = -1.e30;
145    null_flag   = 0;
146
147/*
148*
149* A.5       FOR (each data point) DO
150*              IF (value < reference) THEN
151*                  SET reference to this value   !smallest value
152*              ENDIF
153*              IF (value > max_grid AND not a missing value ) THEN
154*                  SET max_grid to this value    !largest value
155*              ENDIF
156*              IF (value >= missing value ) THEN
157*                  SET null_flag to 1            !grid contains nulls
158*              ENDIF
159*           ENDDO
160  Find reference (minimum) and maximum values of the grid points
161*/
162    for (ipt = 0; ipt < *pt_cnt; ipt++) {
163        ftemp   = *(fbuff+ipt);
164        if (ftemp < reference) reference = ftemp;    /* REF is SCALED UP */
165        if (ftemp > max_grid && ftemp < *pack_null) max_grid = ftemp;
166        if (ftemp >= *pack_null) null_flag = 1;
167    }
168
169    DPRINT2 ("  Max before taking out Ref =%.4lf\n  Null flag=%d\n",
170    max_grid, null_flag);
171
172/*  Compute maximum range of grid (max_grid - reference) */
173/*
174*
175* A.6       IF (max value is same as smallest value AND
176*               null_flag is zero) THEN
177*               CLEAR pack_bit_cnt  !constant values, no nulls
178*               CLEAR max_grid      !set grid range to 0
179*/
180    if (((max_grid - reference) < 1.0) && null_flag == 0) {   
181        pack_bit_cnt = 0;
182        max_grid =  0;
183
184/*
185* A.6.a     ELSE IF (max value is same as smallest value AND
186*                    null_flag is set) THEN
187*               SET max_grid to 1      !const values, some nulls
188*/
189    } else if (((max_grid - reference) < 1.0) && null_flag == 1) {
190        max_grid = 1.;
191
192/*
193* A.6.b     ELSE IF (max value <= -1.e29 AND null_flag is set) THEN
194*               PRINT message
195*               RETURN Stat= -1
196*/
197    } else if (max_grid <= -1.e29 && null_flag == 1) {
198        DPRINT1 ("%s; Grid contains all NULLS\n",func);
199        sprintf(errmsg, "%s; Grid contains all NULLS\n",func);
200        return (-1);
201
202/*
203* A.6.c     ELSE IF (max value not equal to reference) THEN
204*               SET max_grid (max_grid-reference) !non-constant values w/wo nulls
205*/
206    } else if (max_grid != reference) {
207        max_grid -= reference;
208
209/*
210* A.6       ENDIF
211*/
212    }
213
214/*
215*
216* A.7       DEBUG print grid range and reference value
217*/
218    DPRINT2 ( "  Reference = %f\n  Max_grid (range) = %f\n", 
219    reference, max_grid);
220
221/*  Find minimum number of bits to pack data */
222/*
223*
224* A.8.a     IF (grid range is not zero) THEN
225*/
226    if ( max_grid != 0 )   
227    {
228
229/*
230*
231* A.8.a.1      DEBUG print input bit width
232*              IF (input bit_num is zero) THEN
233*                 CALCULATE number of bits needed to store grid range
234*                 DEBUG print calculated bit count
235*              ENDIF
236*/
237       DPRINT1 ( "  Input bit cnt = %d\n", pack_bit_cnt );
238       if ( pack_bit_cnt == 0 )
239       {
240          pack_bit_cnt = (int)(floor(log10((double)max_grid) / log10(2.)) +1); 
241          DPRINT1 ( "  Calculated bit cnt = %d\n", pack_bit_cnt );
242       }
243       if ( (pack_bit_cnt < 0) || (pack_bit_cnt > 30) )
244       {
245          DPRINT1 ("%s: Calculated bit count OUT OF RANGE [0 - 30] !!\n", func);
246          sprintf (errmsg, "%s: Calculated bit count OUT OF RANGE!! bit_cnt: %d  max: %f\n", func,pack_bit_cnt,max_grid);
247          return (-1);
248       }
249/*
250*
251* A.8.a.2      CALCULATE various byte counters
252*              !itemp: #bits required for header + grid
253*              !Byte2_cnt: #bytes rounded up to next 2-byte bdry
254*              !Byte4_cnt: #bytes rounded up to next 4-byte bdry
255*              !Unused_bit_cnt: #unused bits at end using byte2_cnt
256*              DEBUG print expected length and unused bits
257*/
258       itemp = *pt_cnt * pack_bit_cnt + 11 * BYTE_BIT_CNT;
259       byte2_cnt = (long) ceil(((double) itemp / BYTE_BIT_CNT) / 2.) * 2;
260       /*byte4_cnt = (long) ceil(((double) itemp / BYTE_BIT_CNT) / 4.) * 4;*/
261       unused_bit_cnt = byte2_cnt * BYTE_BIT_CNT - itemp;
262       DPRINT1 ( "  Calculated length = %ld bytes (Rnd2)\n", byte2_cnt);
263       DPRINT1 ( "  Bitstream padding = %ld bits\n",unused_bit_cnt);
264
265/*
266*
267* A.8.a.3      CALCULATE maximum storable value
268*              CALCULATE scl_fctr required to fit grid range
269*                        into available bit width
270*/
271       max_value = (long) pow(2., (double) pack_bit_cnt) - 1;
272       if (max_value < 2) max_value = 2;
273       scl_fctr = -(short) floor(log10((double) (max_value-1) / 
274                          (double) max_grid) / log10(2.));
275       pow_scl  = pow(2., (double) -scl_fctr); 
276       DPRINT1 ( "  Calculated Binary scale = %d\n",scl_fctr);
277    }
278
279/*
280*
281* A.8.b     ELSE       !max_grid = 0, all zero data or constant values
282*              SET number of bits to pack to zero
283*              SET lengths to 12 bytes
284*              SET unused bits to 8 (1 byte of padding)
285*              SET scl_fctr to 0
286*              DEBUG print constant grid
287*           ENDIF
288*/
289    else
290    {
291       pack_bit_cnt = 0;
292       byte2_cnt = 12;
293       /*byte4_cnt = 12;*/
294       unused_bit_cnt   = 8;
295       scl_fctr = 0;
296       DPRINT0 ( "  Constant grid.  Using bit cnt = 0\n");
297    }
298
299/*
300*
301* A.9       MALLOC space for bitstream (Rnd2_cnt)
302*           IF (failed) THEN
303*              PRINT error mesg
304*              RETURN Stat= 999;
305*           ENDIF
306*/ 
307    pBitstream = ( unsigned long * ) malloc ( sizeof( unsigned long ) * 
308                                              byte2_cnt );
309    if ( !pBitstream )
310    {
311       DPRINT1 ("%s:  MAlloc failed pBitstream\n", func );
312       sprintf(errmsg, "%s:  MAlloc failed pBitstream\n", func );
313       return (999);
314    }
315
316/*
317*
318* A.10      SET ptr to bitstream
319*           UPDATE bit_cnt for input structure
320*/
321    *bit_cnt = (unsigned short) pack_bit_cnt;
322    DPRINT1 ("  Updated input bit cnt to %d\n", *bit_cnt);
323    bstr = pBitstream;
324 
325/*
326*
327* A.11      ZERO out entire bitstream
328*/
329   zero_cnt = ceil(byte2_cnt / (float)sizeof(long)) * sizeof(long);
330   memset ((void *)pBitstream, '\0', zero_cnt);
331
332/*
333*
334* A.12      PUT packing info into first 11 bytes:
335*           NOTE: The Table 11 Flag stored in the first
336*                 4 bits of Octet 4 is HARDCODED to 0000.
337*                 This implies Simple packing of float
338*                 grid point data with no additional flags.
339*           Octet 1-3  = Byte2_cnt
340*           Octet 4    = Table 11 Flag & unused_bit_cnt
341*           Octet 5-6  = Scl_fctr
342*           Octet 7-10 = Reference truncated to DSF precision
343*           Octet 11   = Pack_bit_cnt
344*           Octet 12   = Bitstream starts (bit 25 of word 3)
345*/
346
347
348   set_bytes_u(byte2_cnt, 3, bdshdr);
349
350   itemp = unused_bit_cnt;
351   set_bytes_u(itemp, 1, bdshdr+3);
352
353   set_bytes_u(scl_fctr, 2, bdshdr+4);
354
355   DPRINT1 ("  Reference (%f) ", reference);
356   reference   =  floor((double) reference + .5);
357   DPRINT1 ("truncated to DSF precision= %lf\n", reference);
358   itemp        = grib_local_ibm(reference);
359   DPRINT1 ("  Reference converted to local IBM format= 0x%x\n", itemp);
360
361   set_bytes_u(itemp, 4, bdshdr+6);
362
363   set_bytes_u(pack_bit_cnt, 1, bdshdr+10);
364
365   bit1 = 25;
366
367   memcpy(bstr,bdshdr,11);
368
369   /*
370    * For non-internet byte order machines (i.e., linux),
371    * We reverse the order of the last byte in the bds header, since
372    *   it will be reversed once again below.
373    */
374   hdrwords = 11/(WORD_BIT_CNT/BYTE_BIT_CNT);
375   set_bytes_u(bstr[hdrwords], WORD_BIT_CNT/BYTE_BIT_CNT,
376              (char *)(bstr+hdrwords) );
377
378   bstr += hdrwords;
379
380
381/*
382    itemp       = unused_bit_cnt;
383    *bstr       = (byte2_cnt << 8) | itemp;
384    bstr++;
385    *bstr       = scl_fctr;
386
387    DPRINT1 ("  Reference (%f) ", reference);
388    reference   =  floor((double) reference + .5);
389    DPRINT1 ("truncated to DSF precision= %lf\n", reference);
390    itemp       = grib_local_ibm(reference);
391    DPRINT1 ("  Reference converted to local IBM format= 0x%x\n", itemp);
392
393    *bstr       = (*bstr << 16) | (itemp >> 16);
394    bstr++;
395    *bstr       = (itemp << 16) | (pack_bit_cnt << 8);
396    bit1        = 25;   */       /* starting bit within current bstr word */
397
398/*
399*
400* A.13      IF (grid values are not constant) THEN
401*/ 
402    if (pack_bit_cnt > 0) {
403
404
405/*
406* A.13.1       SET empty value
407*/
408        empty = WORD_BIT_CNT - pack_bit_cnt + 1;
409
410        for (ipt=0; ipt < 5; ipt++) DPRINT4 (
411            " ITEMP= (*(fbuff+ipt) - reference) * pow_scl + .5=\n"\
412            "        (%lf -%lf) * %lf + .5 = %lf\n",
413            *(fbuff+ipt), reference, pow_scl, 
414            (*(fbuff+ipt) - reference) * pow_scl + .5);
415           
416/*
417* A.13.2       FOR (each point in bitstream) DO
418*/
419        for (ipt = 0; ipt < *pt_cnt; ipt++) {
420
421/*
422* A.13.2.1         IF ( data value < pack_null) THEN
423*                     SET itemp to (value - reference) * pow_scl + .5;
424*                  ELSE
425*                     SET itemp to max value;
426*                  ENDIF
427*/
428            if (*(fbuff+ipt) < *pack_null) {
429                itemp  = (*(fbuff+ipt) - reference) * pow_scl + .5;
430            } else {
431                itemp  = max_value; 
432                DPRINT1 ("%s: Setting to max_value: Precision may be too high !!\n", func);
433                sprintf (errmsg, "%s: Setting grid point to max value, precision may be too high", func);
434                /*              return (-1); */
435            }
436
437/*
438* A.13.2.2         COMPUTE if data point can fit in current word
439*/
440            diff        = empty - bit1;
441
442/*
443* A.13.2.3.a       IF (data point falls within word ) THEN
444*                      SHIFT value to the correct bit position
445*                      COMBINE it with data in current word of bitstream
446*                      CALCULATE starting bit in curr word for next time
447*/
448            if (diff > 0)
449            {
450                *bstr   |= itemp << diff;
451                bit1    += pack_bit_cnt;
452            }
453
454/*
455* A.13.2.3.b       ELSE IF (data point ends at word boundary) THEN
456*                      COMBINE value with data in current word of bitstream
457*                      SET starting bit to 1
458*                      BUMP word counter in bitstream up by 1 word
459*/
460            else if (diff == 0) 
461            {
462                *bstr |= itemp;
463                bit1   = 1;
464                bstr++;
465            }
466
467/*
468* A.13.2.3.c       ELSE     !point crosses word boundary
469*                      STORE "diff" bits of value in current word of bitstream
470*                      BUMP word counter in bitstream up by 1 word
471*                      STORE remaining bits of value in next word
472*                      CALCULATE starting bit in curr word for next time
473*                  ENDIF    !word location check
474*/
475            else                /* pixel crosses word boundary */
476            {
477                *bstr |= itemp >> -diff;
478                bstr++;
479                *bstr |= itemp << (WORD_BIT_CNT + diff);
480                bit1   = -diff + 1;
481            }
482
483/*
484* A.13.2        ENDFOR loop over grid points
485*/
486       }
487
488/*
489* A.13       ENDIF (pack_bit_cnt > 0)
490*/
491    }
492
493/* For little endian machines, swap the bytes in the bstr pointer */
494    /*    for (wordnum = 0; */
495    for (wordnum = hdrwords;
496         wordnum < ceil(byte2_cnt/(float)(WORD_BIT_CNT/BYTE_BIT_CNT)); 
497         wordnum++) {
498      set_bytes_u(pBitstream[wordnum], WORD_BIT_CNT/BYTE_BIT_CNT, 
499                  (char *)(pBitstream+wordnum) );
500    }
501
502/*
503*
504* A.14       ASSIGN bitstream block to ppbitstream pointer
505*            SET BDSlength (size rnded to next 2 byte boundary)
506*            RETURN Status 0  ! success
507*/
508    *ppbitstream = pBitstream;
509    *BDSlength = (long) byte2_cnt;
510
511    DPRINT1 ("Exiting pack_spatial, BDS len=%ld,  Status=0\n" , *BDSlength);
512
513    if (prec_too_high) {
514        fprintf(stderr,"pack_spatial: Warning: Precision for a parameter may be too high in gribmap.txt\n");
515    }
516    return (0);
517/*
518* END OF FUNCTION
519*
520*/
521}
522
523/*
524*
525**************************************************************
526* B. FUNCTION  grib_local_ibm
527*      convert local_float from local floating point to
528*      IBM floating point stored in a 4-byte integer.
529*
530*    INTERFACE:
531*      unsigned long grib_local_ibm (local_float)
532*
533*    ARGUMENTS (I=input, O=output, I&O=input and output):
534*      (I)  double local_float      float value in local format
535*
536*    RETURNS:
537*       the actual IBM floating point value
538**************************************************************
539*
540*/
541#if PROTOTYPE_NEEDED
542unsigned long grib_local_ibm (double local_float)
543#else
544unsigned long grib_local_ibm (local_float)
545double local_float;
546#endif
547{
548    long a, b; 
549    unsigned long ibm_float;
550/*
551*
552* B.1.a     IF (local float value is zero) THEN
553*               SET the ibm float to zero too
554*/
555    if (local_float == 0.) { 
556        ibm_float = 0;
557    } else {
558/*
559* B.1.b     ELSE
560*              CONVERT to IBM floating point
561*              ! IBM floating point is stored in 4 bytes as: 
562*              ! saaaaaaa bbbbbbbb bbbbbbbb bbbbbbbb
563*              ! where s is sign bit, 0 -> positive, 1 -> negative
564*              !       a is 7-bit characteristic
565*              !       b is 24-bit fraction
566*              ! s, a and b are obtained from local_float (local 32-bit float) as
567*              !       s = sign(local_float)
568*              !       a = ceil(log10(local_float) / log10(16.)) + 64
569*              !       b = local_float / 16**(a-64) * 2**24
570* B.1.b     ENDIF
571*/
572        a = ceil(log10(fabs(local_float)) / log10(16.)) + 64;
573        /* Added by Todd Hutchinson, 8/13/99 */
574        /* This fixes a problem when local_float == 256, etc. */
575        if ( fmod((log10(fabs(local_float))/log10(16.)),1.) == 0) {
576          a++;
577        }
578/*      Local_float == +/-1. is a special case because of log function */
579        if ( (local_float == 1.) || (local_float == -1.)) a = 65;
580        b = (long) (fabs(local_float) * pow(16.,(double) (70 - a)) +.5)
581            & 0x00ffffff; 
582        ibm_float = (((local_float > 0.) ? 0 : 1) << 31) | (a << 24) | b;
583    }
584/*
585*
586* B.2       RETURN the ibm float value
587*/
588    return ibm_float;
589/*
590*
591* END OF FUNCTION
592*
593*/ }
594
595/*
596*
597**************************************************************
598* C. FUNCTION:   grib_ibm_local
599*      convert local_float from IBM floating point to
600*      local floating point.
601*
602*    INTERFACE:
603*      float grib_ibm_local(ibm_float)
604*
605*    ARGUMENTS (I=input, O=output, I&O=input and output):
606*      (I)  double local_float      float value in local format
607*
608*     RETURNS:
609*        the actual local floating point
610**************************************************************
611*/
612#if PROTOTYPE_NEEDED
613float grib_ibm_local( unsigned long ibm_float)
614#else
615float grib_ibm_local( ibm_float)
616unsigned long ibm_float;
617#endif
618{
619/*
620  Convert ibm_float from IBM floating point stored in a 4-byte integer
621  to local floating point.
622*
623* C.1       DETERMINE local floating point
624*           ! IBM floating point is stored in 4 bytes as: 
625*           ! saaaaaaa bbbbbbbb bbbbbbbb bbbbbbbb
626*           ! where s is sign bit, 0 -> positive, 1 -> negative
627*           !       a is 7-bit characteristic
628*           !       b is 24-bit fraction
629*           ! local_float (local 32-bit float) is recovered from
630*           ! s, a and b as
631*           ! local_float = (-1)**s * 2**(-24) * b * 16**(a-64)
632*/
633
634    long a, b;
635    float local_float;
636
637    a = (ibm_float >> 24) & 0x0000007f;
638    b = ibm_float & 0x00ffffff;
639    local_float = (float) b * pow(16., (double) (a - 70));
640    if (ibm_float >> 31) local_float = -local_float;
641/*
642*
643* C.2       RETURN floating point
644*/
645    return local_float;
646/*
647* END OF FUNCTION
648*
649*/ 
650}
Note: See TracBrowser for help on using the repository browser.