grib/src/main/java/ucar/nc2/grib/grib2/Grib2DataReader.java
private float[] getData50002(RandomAccessFile raf, Grib2Drs.Type50002 gdrs) throws IOException {

    BitReader reader;

    reader = new BitReader(raf, startPos + 5);
    int[] groupWidth = new int[gdrs.p1];
    for (int i = 0; i < gdrs.p1; i++) {
      groupWidth[i] = (int) reader.bits2UInt(gdrs.widthOfWidth);
    }

    reader = new BitReader(raf, raf.getFilePointer());
    int[] groupLength = new int[gdrs.p1];
    for (int i = 0; i < gdrs.p1; i++) {
      groupLength[i] = (int) reader.bits2UInt(gdrs.widthOfLength);
    }

    reader = new BitReader(raf, raf.getFilePointer());
    int[] firstOrderValues = new int[gdrs.p1];
    for (int i = 0; i < gdrs.p1; i++) {
      firstOrderValues[i] = (int) reader.bits2UInt(gdrs.widthOfFirstOrderValues);
    }

    int bias = 0;
    if (gdrs.orderOfSPD > 0) {
      bias = gdrs.spd[gdrs.orderOfSPD];
    }

    reader = new BitReader(raf, raf.getFilePointer());
    int cnt = gdrs.orderOfSPD;
    int[] data = new int[totalNPoints];
    for (int i = 0; i < gdrs.p1; i++) {
      if (groupWidth[i] > 0) {

        for (int j = 0; j < groupLength[i]; j++) {
          data[cnt] = (int) reader.bits2UInt(groupWidth[i]);
          data[cnt] += firstOrderValues[i];
          cnt++;
        }

      } else {

        for (int j = 0; j < groupLength[i]; j++) {
          data[cnt] = firstOrderValues[i];
          cnt++;
        }

      }

    }

    if (gdrs.orderOfSPD >= 0) {
      System.arraycopy(gdrs.spd, 0, data, 0, gdrs.orderOfSPD);
    }

    int y, z, w;
    switch (gdrs.orderOfSPD) {
      case 1:
        y = data[0];
        for (int i = 1; i < totalNPoints; i++) {
          y += data[i] + bias;
          data[i] = y;
        }

        break;
      case 2:
        y = data[1] - data[0];
        z = data[1];
        for (int i = 2; i < totalNPoints; i++) {
          y += data[i] + bias;
          z += y;
          data[i] = z;
        }

        break;
      case 3:
        y = data[2] - data[1];
        z = y - (data[1] - data[0]);
        w = data[2];
        for (int i = 3; i < totalNPoints; i++) {
          z += data[i] + bias;
          y += z;
          w += y;
          data[i] = w;
        }

        break;
    }

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

    float[] ret = new float[totalNPoints];
    for (int i = 0; i < totalNPoints; i++) {
      ret[i] = (((data[i] * EE) + R) * DD);
    }

    return ret;

  }
private float[] getData50002(RandomAccessFile raf, Grib2Drs.Type50002 gdrs) throws IOException {

    BitReader reader;

    reader = new BitReader(raf, startPos + 5);
    int[] groupWidth = new int[gdrs.p1];
    for (int i = 0; i < gdrs.p1; i++) {
      groupWidth[i] = (int) reader.bits2UInt(gdrs.widthOfWidth);
    }

    reader = new BitReader(raf, raf.getFilePointer());
    int[] groupLength = new int[gdrs.p1];
    for (int i = 0; i < gdrs.p1; i++) {
      groupLength[i] = (int) reader.bits2UInt(gdrs.widthOfLength);
    }

    reader = new BitReader(raf, raf.getFilePointer());
    int[] firstOrderValues = new int[gdrs.p1];
    for (int i = 0; i < gdrs.p1; i++) {
      firstOrderValues[i] = (int) reader.bits2UInt(gdrs.widthOfFirstOrderValues);
    }

    int bias = 0;
    if (gdrs.orderOfSPD > 0) {
      bias = gdrs.spd[gdrs.orderOfSPD];
    }

    reader = new BitReader(raf, raf.getFilePointer());
    int cnt = gdrs.orderOfSPD;
    int[] data = new int[totalNPoints];
    for (int i = 0; i < gdrs.p1; i++) {
      if (groupWidth[i] > 0) {

        for (int j = 0; j < groupLength[i]; j++) {
          data[cnt] = (int) reader.bits2UInt(groupWidth[i]);
          data[cnt] += firstOrderValues[i];
          cnt++;
        }

      } else {

        for (int j = 0; j < groupLength[i]; j++) {
          data[cnt] = firstOrderValues[i];
          cnt++;
        }

      }

    }

    if (gdrs.orderOfSPD >= 0) {
      System.arraycopy(gdrs.spd, 0, data, 0, gdrs.orderOfSPD);
    }

    int y, z, w;
    switch (gdrs.orderOfSPD) {
      case 1:
        y = data[0];
        for (int i = 1; i < totalNPoints; i++) {
          y += data[i] + bias;
          data[i] = y;
        }

        break;
      case 2:
        y = data[1] - data[0];
        z = data[1];
        for (int i = 2; i < totalNPoints; i++) {
          y += data[i] + bias;
          z += y;
          data[i] = z;
        }

        break;
      case 3:
        y = data[2] - data[1];
        z = y - (data[1] - data[0]);
        w = data[2];
        for (int i = 3; i < totalNPoints; i++) {
          z += data[i] + bias;
          y += z;
          w += y;
          data[i] = w;
        }

        break;
    }

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

    float[] ret = new float[totalNPoints];
    for (int i = 0; i < totalNPoints; i++) {
      ret[i] = (((data[i] * EE) + R) * DD);
    }

    return ret;

  }
ported from https://github.com/erdc-cm/grib_api/blob/master/src/grib_accessor_class_data_g1second_order_general_extended_packing.c