Line data Source code
1 : #include <math.h>
2 : #include <float.h>
3 : #include <stdio.h>
4 : #include <stdlib.h>
5 : #include "grib2.h"
6 :
7 0 : static float DoubleToFloatClamp(double val) {
8 0 : if (val >= FLT_MAX) return FLT_MAX;
9 0 : if (val <= -FLT_MAX) return -FLT_MAX;
10 0 : return (float)val;
11 : }
12 :
13 0 : g2int specunpack(unsigned char *cpack,g2int *idrstmpl,g2int ndpts,g2int JJ,
14 : g2int KK, g2int MM, g2float *fld)
15 : //$$$ SUBPROGRAM DOCUMENTATION BLOCK
16 : // . . . .
17 : // SUBPROGRAM: specunpack
18 : // PRGMMR: Gilbert ORG: W/NP11 DATE: 2000-06-21
19 : //
20 : // ABSTRACT: This subroutine unpacks a spectral data field that was packed
21 : // using the complex packing algorithm for spherical harmonic data as
22 : // defined in the GRIB2 documentation,
23 : // using info from the GRIB2 Data Representation Template 5.51.
24 : //
25 : // PROGRAM HISTORY LOG:
26 : // 2000-06-21 Gilbert
27 : //
28 : // USAGE: int specunpack(unsigned char *cpack,g2int *idrstmpl,
29 : // g2int ndpts,g2int JJ,g2int KK,g2int MM,g2float *fld)
30 : // INPUT ARGUMENT LIST:
31 : // cpack - pointer to the packed data field.
32 : // idrstmpl - pointer to the array of values for Data Representation
33 : // Template 5.51
34 : // ndpts - The number of data values to unpack (real and imaginary parts)
35 : // JJ - J - pentagonal resolution parameter
36 : // KK - K - pentagonal resolution parameter
37 : // MM - M - pentagonal resolution parameter
38 : //
39 : // OUTPUT ARGUMENT LIST:
40 : // fld() - Contains the unpacked data values. fld must be allocated
41 : // with at least ndpts*sizeof(g2float) bytes before
42 : // calling this routine.
43 : //
44 : // REMARKS: None
45 : //
46 : // ATTRIBUTES:
47 : // LANGUAGE: C
48 : // MACHINE:
49 : //
50 : //$$$
51 : {
52 :
53 : g2int *ifld,j,iofst,nbits;
54 : g2float ref,bscale,dscale,*unpk;
55 : g2float *pscale,tscale;
56 : g2int Js,Ks,Ms,Ts,Ns,Nm,n,m;
57 : g2int inc,incu,incp;
58 :
59 0 : rdieee(idrstmpl+0,&ref,1);
60 0 : bscale = DoubleToFloatClamp(int_power(2.0,idrstmpl[1]));
61 0 : dscale = DoubleToFloatClamp(int_power(10.0,-idrstmpl[2]));
62 0 : nbits = idrstmpl[3];
63 0 : Js=idrstmpl[5];
64 0 : Ks=idrstmpl[6];
65 0 : Ms=idrstmpl[7];
66 0 : Ts=idrstmpl[8];
67 :
68 0 : if (idrstmpl[9] == 1) { // unpacked floats are 32-bit IEEE
69 :
70 0 : if (Ts > ndpts)
71 : {
72 0 : fprintf(stderr, "specunpack: invalid Ts=%d vs ndpts=%d.\n", Ts, ndpts);
73 0 : for (j=0;j<ndpts;j++) fld[j]=0.0;
74 0 : return -1;
75 : }
76 :
77 0 : unpk=(g2float *)malloc(ndpts*sizeof(g2float));
78 0 : ifld=(g2int *)malloc(ndpts*sizeof(g2int));
79 :
80 0 : gbits(cpack,G2_UNKNOWN_SIZE,ifld,0,32,0,Ts);
81 0 : iofst=32*Ts;
82 0 : rdieee(ifld,unpk,Ts); // read IEEE unpacked floats
83 0 : gbits(cpack,G2_UNKNOWN_SIZE,ifld,iofst,nbits,0,ndpts-Ts); // unpack scaled data
84 : //
85 : // Calculate Laplacian scaling factors for each possible wave number.
86 : //
87 0 : pscale=(g2float *)calloc((JJ+MM+1),sizeof(g2float));
88 0 : tscale=(g2float)(idrstmpl[4]*1E-6);
89 0 : for (n=Js;n<=JJ+MM;n++)
90 0 : pscale[n]=(float)pow((g2float)(n*(n+1)),-tscale);
91 : //
92 : // Assemble spectral coeffs back to original order.
93 : //
94 0 : inc=0;
95 0 : incu=0;
96 0 : incp=0;
97 0 : for (m=0;m<=MM;m++) {
98 0 : Nm=JJ; // triangular or trapezoidal
99 0 : if ( KK == JJ+MM ) Nm=JJ+m; // rhombodial
100 0 : Ns=Js; // triangular or trapezoidal
101 0 : if ( Ks == Js+Ms ) Ns=Js+m; // rhombodial
102 0 : for (n=m;n<=Nm;n++) {
103 0 : if (n<=Ns && m<=Ms) { // grab unpacked value
104 0 : fld[inc++]=unpk[incu++]; // real part
105 0 : fld[inc++]=unpk[incu++]; // imaginary part
106 : }
107 : else { // Calc coeff from packed value
108 0 : fld[inc++]=(((g2float)ifld[incp++]*bscale)+ref)*
109 0 : dscale*pscale[n]; // real part
110 0 : fld[inc++]=(((g2float)ifld[incp++]*bscale)+ref)*
111 0 : dscale*pscale[n]; // imaginary part
112 : }
113 : }
114 : }
115 :
116 0 : free(pscale);
117 0 : free(unpk);
118 0 : free(ifld);
119 :
120 : }
121 : else {
122 0 : printf("specunpack: Cannot handle 64 or 128-bit floats.\n");
123 0 : for (j=0;j<ndpts;j++) fld[j]=0.0;
124 0 : return -3;
125 : }
126 :
127 0 : return 0;
128 : }
|