Coverage Report

Created: 2026-09-26 08:22

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