grib/src/main/java/ucar/nc2/grib/grib2/Grib2DataReader.java
private float[] getData2(RandomAccessFile raf, Grib2Drs.Type2 gdrs) throws IOException {
    int mvm = gdrs.missingValueManagement;
    float mv = getMissingValue(gdrs);

    float DD = (float) java.lang.Math.pow((double) 10, (double) gdrs.decimalScaleFactor);
    float R = gdrs.referenceValue;
    float EE = (float) java.lang.Math.pow(2.0, (double) gdrs.binaryScaleFactor);
    float ref_val = R / DD;

    int NG = gdrs.numberOfGroups;
    if (NG == 0) {
      return nGroups0(bitmapIndicator, ref_val, mv);
    }

    BitReader reader = new BitReader(raf, startPos + 5);

    // 6-xx  Get reference values for groups (X1's)
    int[] X1 = new int[NG];
    int nb = gdrs.numberOfBits;
    if (nb != 0) {
      for (int i = 0; i < NG; i++) {
        X1[i] = (int) reader.bits2UInt(nb);
      }
    }

    // [xx +1 ]-yy Get number of bits used to encode each group
    int[] NB = new int[NG];
    nb = gdrs.bitsGroupWidths;
    if (nb != 0) {
      reader.incrByte();
      for (int i = 0; i < NG; i++) {
        NB[i] = (int) reader.bits2UInt(nb);
      }
    }

    // [yy +1 ]-zz Get the scaled group lengths using formula
    //     Ln = ref + Kn * len_inc, where n = 1-NG,
    //          ref = referenceGroupLength, and  len_inc = lengthIncrement

    int[] L = new int[NG];
    int ref = gdrs.referenceGroupLength;
    int len_inc = gdrs.lengthIncrement;
    nb = gdrs.bitsScaledGroupLength;

    reader.incrByte();
    for (int i = 0; i < NG; i++) {
      L[i] = ref + (int) reader.bits2UInt(nb) * len_inc;
    }
    L[NG - 1] = gdrs.lengthLastGroup; // enter Length of Last Group

    float[] data = new float[totalNPoints];

    // [zz +1 ]-nn get X2 values and calculate the results Y using formula

//              Y = R + [(X1 + X2) * (2 ** E) * (10 ** D)]
//               WHERE:
//                     Y = THE VALUE WE ARE UNPACKING
//                     R = THE REFERENCE VALUE (FIRST ORDER MINIMA)
//                    X1 = THE PACKED VALUE
//                    X2 = THE SECOND ORDER MINIMA
//                     E = THE BINARY SCALE FACTOR
//                     D = THE DECIMAL SCALE FACTOR
    int count = 0;
    reader.incrByte();
    for (int i = 0; i < NG; i++) {
      for (int j = 0; j < L[i]; j++) {
        if (NB[i] == 0) {
          if (mvm == 0) {  // X2 = 0
            data[count++] = (R + X1[i] * EE) / DD;
          } else { //if (mvm == 1) || (mvm == 2 )
            data[count++] = mv;
          }
        } else {
          int X2 = (int) reader.bits2UInt(NB[i]);
          if (mvm == 0) {
            data[count++] = (R + (X1[i] + X2) * EE) / DD;
          } else { //if (mvm == 1) || (mvm == 2 )
            // X2 is also set to missing value if all bits set to 1's
            if (X2 == bitsmv1[NB[i]]) {
              data[count++] = mv;
            } else {
              data[count++] = (R + (X1[i] + X2) * EE) / DD;
            }
          }
        }
      }  // end for j
    }  // end for i

    if (bitmap != null) {
      int idx = 0;
      float[] tmp = new float[totalNPoints];
      for (int i = 0; i < totalNPoints; i++) {
        if (GribNumbers.testBitIsSet(bitmap[i / 8], i % 8)) {
          tmp[i] = data[idx++];
        } else {
          tmp[i] = mv;
        }
      }
      data = tmp;
    }

    return data;
  }
private float[] getData2(RandomAccessFile raf, Grib2Drs.Type2 gdrs) throws IOException {
    int mvm = gdrs.missingValueManagement;
    float mv = getMissingValue(gdrs);

    float DD = (float) java.lang.Math.pow((double) 10, (double) gdrs.decimalScaleFactor);
    float R = gdrs.referenceValue;
    float EE = (float) java.lang.Math.pow(2.0, (double) gdrs.binaryScaleFactor);
    float ref_val = R / DD;

    int NG = gdrs.numberOfGroups;
    if (NG == 0) {
      return nGroups0(bitmapIndicator, ref_val, mv);
    }

    BitReader reader = new BitReader(raf, startPos + 5);

    // 6-xx  Get reference values for groups (X1's)
    int[] X1 = new int[NG];
    int nb = gdrs.numberOfBits;
    if (nb != 0) {
      for (int i = 0; i < NG; i++) {
        X1[i] = (int) reader.bits2UInt(nb);
      }
    }

    // [xx +1 ]-yy Get number of bits used to encode each group
    int[] NB = new int[NG];
    nb = gdrs.bitsGroupWidths;
    if (nb != 0) {
      reader.incrByte();
      for (int i = 0; i < NG; i++) {
        NB[i] = (int) reader.bits2UInt(nb);
      }
    }

    // [yy +1 ]-zz Get the scaled group lengths using formula
    //     Ln = ref + Kn * len_inc, where n = 1-NG,
    //          ref = referenceGroupLength, and  len_inc = lengthIncrement

    int[] L = new int[NG];
    int ref = gdrs.referenceGroupLength;
    int len_inc = gdrs.lengthIncrement;
    nb = gdrs.bitsScaledGroupLength;

    reader.incrByte();
    for (int i = 0; i < NG; i++) {
      L[i] = ref + (int) reader.bits2UInt(nb) * len_inc;
    }
    L[NG - 1] = gdrs.lengthLastGroup; // enter Length of Last Group

    float[] data = new float[totalNPoints];

    // [zz +1 ]-nn get X2 values and calculate the results Y using formula

//              Y = R + [(X1 + X2) * (2 ** E) * (10 ** D)]
//               WHERE:
//                     Y = THE VALUE WE ARE UNPACKING
//                     R = THE REFERENCE VALUE (FIRST ORDER MINIMA)
//                    X1 = THE PACKED VALUE
//                    X2 = THE SECOND ORDER MINIMA
//                     E = THE BINARY SCALE FACTOR
//                     D = THE DECIMAL SCALE FACTOR
    int count = 0;
    reader.incrByte();
    for (int i = 0; i < NG; i++) {
      for (int j = 0; j < L[i]; j++) {
        if (NB[i] == 0) {
          if (mvm == 0) {  // X2 = 0
            data[count++] = (R + X1[i] * EE) / DD;
          } else { //if (mvm == 1) || (mvm == 2 )
            data[count++] = mv;
          }
        } else {
          int X2 = (int) reader.bits2UInt(NB[i]);
          if (mvm == 0) {
            data[count++] = (R + (X1[i] + X2) * EE) / DD;
          } else { //if (mvm == 1) || (mvm == 2 )
            // X2 is also set to missing value if all bits set to 1's
            if (X2 == bitsmv1[NB[i]]) {
              data[count++] = mv;
            } else {
              data[count++] = (R + (X1[i] + X2) * EE) / DD;
            }
          }
        }
      }  // end for j
    }  // end for i

    if (bitmap != null) {
      int idx = 0;
      float[] tmp = new float[totalNPoints];
      for (int i = 0; i < totalNPoints; i++) {
        if (GribNumbers.testBitIsSet(bitmap[i / 8], i % 8)) {
          tmp[i] = data[idx++];
        } else {
          tmp[i] = mv;
        }
      }
      data = tmp;
    }

    return data;
  }
/*
Data template 7.2 – Grid point data – complex packing
Note: For most templates, details of the packing process are described in Regulation 92.9.4.
Octet No. Contents
6–xx    NG group reference values (X1 in the decoding formula), each of which is encoded using
the number of bits specified in octet 20 of data representation template 5.0. Bits set to zero
shall be appended as necessary to ensure this sequence of numbers ends on an octet boundary
[xx+1]–yy NG group widths, each of which is encoded using the number of bits specified in octet 37
of data representation template 5.2. Bits set to zero shall be appended as necessary to
ensure this sequence of numbers ends on an octet boundary
[yy+1]–zz NG scaled group lengths, each of which is encoded using the number of bits specified in
octet 47 of data representation template 5.2. Bits set to zero shall be appended as necessary
to ensure this sequence of numbers ends on an octet boundary (see Note 14 of data
representation template 5.2)
[zz+1]–nn Packed values (X2 in the decoding formula), where each value is a deviation from its respective
group reference value

Notes:
(1) Group descriptors mentioned above may not be physically present; if associated field width is 0.
(2) Group lengths have no meaning for row by row packing; for consistency, associated field width should then be
encoded as 0. So no specific test for row by row case is mandatory at decoding software level to handle
encoding/decoding of group descriptors.
(3) Scaled group lengths, if present, are encoded for each group. But the true last group length (unscaled) should be taken
from data representation template.
(4) For groups with a constant value, associated field width is 0, and no incremental data are physically present.