|
| 1 | +#include <stdio.h> |
| 2 | +#include <stdlib.h> |
| 3 | +#include <stddef.h> |
| 4 | +#include <limits.h> |
| 5 | +#include "grib.h" |
| 6 | +#include "pds4.h" |
| 7 | +#include "bms.h" |
| 8 | +#include "bds.h" |
| 9 | + |
| 10 | +/* 1996 wesley ebisuzaki |
| 11 | + * |
| 12 | + * Unpack BDS section |
| 13 | + * |
| 14 | + * input: *bits, pointer to packed integer data |
| 15 | + * *bitmap, pointer to bitmap (undefined data), NULL if none |
| 16 | + * n_bits, number of bits per packed integer |
| 17 | + * n, number of data points (includes undefined data) |
| 18 | + * ref, scale: flt[] = ref + scale*packed_int |
| 19 | + * output: *flt, pointer to output array |
| 20 | + * undefined values filled with UNDEFINED |
| 21 | + * |
| 22 | + * note: code assumes an integer > 32 bits |
| 23 | + * |
| 24 | + * 7/98 v1.2.1 fix bug for bitmaps and nbit >= 25 found by Larry Brasfield |
| 25 | + * 2/01 v1.2.2 changed jj from long int to double |
| 26 | + * 3/02 v1.2.3 added unpacking extensions for spectral data |
| 27 | + * Luis Kornblueh, MPIfM |
| 28 | + * 7/06 v.1.2.4 fixed some bug complex packed data was not set to undefined |
| 29 | + */ |
| 30 | + |
| 31 | +static unsigned int mask[] = {0,1,3,7,15,31,63,127,255}; |
| 32 | +static unsigned int map_masks[8] = {128, 64, 32, 16, 8, 4, 2, 1}; |
| 33 | +static double shift[9] = {1.0, 2.0, 4.0, 8.0, 16.0, 32.0, 64.0, 128.0, 256.0}; |
| 34 | + |
| 35 | +void BDS_unpack(float *flt, unsigned char *bds, unsigned char *bitmap, |
| 36 | + int n_bits, int n, double ref, double scale) { |
| 37 | + |
| 38 | + unsigned char *bits; |
| 39 | + |
| 40 | + int i, mask_idx, t_bits, c_bits, j_bits; |
| 41 | + unsigned int j, map_mask, tbits, jmask, bbits; |
| 42 | + double jj; |
| 43 | + |
| 44 | + |
| 45 | + if (BDS_ComplexPacking(bds)) { |
| 46 | + fprintf(stderr,"*** Cannot decode complex packed fields n=%d***\n", n); |
| 47 | + exit(8); |
| 48 | + for (i = 0; i < n; i++) { |
| 49 | + *flt++ = UNDEFINED; |
| 50 | + } |
| 51 | + return; |
| 52 | + } |
| 53 | + |
| 54 | + if (BDS_Harmonic(bds)) { |
| 55 | + bits = bds + 15; |
| 56 | + /* fill in global mean */ |
| 57 | + *flt++ = BDS_Harmonic_RefValue(bds); |
| 58 | + n -= 1; |
| 59 | + } |
| 60 | + else { |
| 61 | + bits = bds + 11; |
| 62 | + } |
| 63 | + |
| 64 | + tbits = bbits = 0; |
| 65 | + |
| 66 | + /* assume integer has 32+ bits */ |
| 67 | + if (n_bits <= 25) { |
| 68 | + jmask = (1 << n_bits) - 1; |
| 69 | + t_bits = 0; |
| 70 | + |
| 71 | + if (bitmap) { |
| 72 | + for (i = 0; i < n; i++) { |
| 73 | + /* check bitmap */ |
| 74 | + mask_idx = i & 7; |
| 75 | + if (mask_idx == 0) bbits = *bitmap++; |
| 76 | + if ((bbits & map_masks[mask_idx]) == 0) { |
| 77 | + *flt++ = UNDEFINED; |
| 78 | + continue; |
| 79 | + } |
| 80 | + |
| 81 | + while (t_bits < n_bits) { |
| 82 | + tbits = (tbits * 256) + *bits++; |
| 83 | + t_bits += 8; |
| 84 | + } |
| 85 | + t_bits -= n_bits; |
| 86 | + j = (tbits >> t_bits) & jmask; |
| 87 | + *flt++ = ref + scale*j; |
| 88 | + } |
| 89 | + } |
| 90 | + else { |
| 91 | + for (i = 0; i < n; i++) { |
| 92 | + if (n_bits - t_bits > 8) { |
| 93 | + tbits = (tbits << 16) | (bits[0] << 8) | (bits[1]); |
| 94 | + bits += 2; |
| 95 | + t_bits += 16; |
| 96 | + } |
| 97 | + while (t_bits < n_bits) { |
| 98 | + tbits = (tbits * 256) + *bits++; |
| 99 | + t_bits += 8; |
| 100 | + } |
| 101 | + t_bits -= n_bits; |
| 102 | + flt[i] = (tbits >> t_bits) & jmask; |
| 103 | + } |
| 104 | + /* at least this vectorizes :) */ |
| 105 | + for (i = 0; i < n; i++) { |
| 106 | + flt[i] = ref + scale*flt[i]; |
| 107 | + } |
| 108 | + } |
| 109 | + } |
| 110 | + else { |
| 111 | + /* older unoptimized code, not often used */ |
| 112 | + c_bits = 8; |
| 113 | + map_mask = 128; |
| 114 | + while (n-- > 0) { |
| 115 | + if (bitmap) { |
| 116 | + j = (*bitmap & map_mask); |
| 117 | + if ((map_mask >>= 1) == 0) { |
| 118 | + map_mask = 128; |
| 119 | + bitmap++; |
| 120 | + } |
| 121 | + if (j == 0) { |
| 122 | + *flt++ = UNDEFINED; |
| 123 | + continue; |
| 124 | + } |
| 125 | + } |
| 126 | + |
| 127 | + jj = 0.0; |
| 128 | + j_bits = n_bits; |
| 129 | + while (c_bits <= j_bits) { |
| 130 | + if (c_bits == 8) { |
| 131 | + jj = jj * 256.0 + (double) (*bits++); |
| 132 | + j_bits -= 8; |
| 133 | + } |
| 134 | + else { |
| 135 | + jj = (jj * shift[c_bits]) + (double) (*bits & mask[c_bits]); |
| 136 | + bits++; |
| 137 | + j_bits -= c_bits; |
| 138 | + c_bits = 8; |
| 139 | + } |
| 140 | + } |
| 141 | + if (j_bits) { |
| 142 | + c_bits -= j_bits; |
| 143 | + jj = (jj * shift[j_bits]) + (double) ((*bits >> c_bits) & mask[j_bits]); |
| 144 | + } |
| 145 | + *flt++ = ref + scale*jj; |
| 146 | + } |
| 147 | + } |
| 148 | + return; |
| 149 | +} |
0 commit comments