private static boolean fastSubtractDifferentScale(
      long leftFast0, long leftFast1, long leftFast2,
      int leftIntegerDigitCount, int leftScale,
      long rightFast0, long rightFast1, long rightFast2,
      int rightIntegerDigitCount, int rightScale,
      FastHiveDecimal fastResult) {

    int diffScale;
    int resultScale;

    long result0 = 0;
    long result1 = 0;
    long result2 = 0;
    long result3 = 0;
    long result4 = 0;

    // Since subtraction is not commutative, we can must subtract in the order passed in.
    if (leftScale > rightScale) {

      // Since left has a longer digit tail and it doesn't move; we will shift the right digits
      // as we do our addition into the result.

      diffScale = leftScale - rightScale;
      resultScale = leftScale;

      if (diffScale < LONGWORD_DECIMAL_DIGITS) {

        final long divideFactor = powerOfTenTable[LONGWORD_DECIMAL_DIGITS - diffScale];
        final long multiplyFactor = powerOfTenTable[diffScale];

        final long r0 =
            leftFast0
          - (rightFast0 % divideFactor) * multiplyFactor;
        long r1;
        if (r0 < 0) {
          result0 = r0 + MULTIPLER_LONGWORD_DECIMAL;
          r1 =
              leftFast1
            - rightFast0 / divideFactor
            - (rightFast1 % divideFactor) * multiplyFactor
            - 1;
        } else {
          result0 = r0;
          r1 =
              leftFast1
            - rightFast0 / divideFactor
            - (rightFast1 % divideFactor) * multiplyFactor;
        }
        long r2;
        if (r1 < 0) {
          result1 = r1 + MULTIPLER_LONGWORD_DECIMAL;
          r2 =
              leftFast2
            - rightFast1 / divideFactor
            - (rightFast2 % divideFactor) * multiplyFactor
            - 1;
        } else {
          result1 = r1;
          r2 =
              leftFast2
            - rightFast1 / divideFactor
            - (rightFast2 % divideFactor) * multiplyFactor;
        }
        long r3;
        if (r2 < 0) {
          result2 = r2 + MULTIPLER_LONGWORD_DECIMAL;
          r3 =
             -(rightFast2 / divideFactor)
            - 1;
        } else {
          result2 = r2;
          r3 =
             -(rightFast2 / divideFactor);
        }
        long r4;
        if (r3 < 0) {
          result3 = r3 + MULTIPLER_LONGWORD_DECIMAL;
          r4 =  - 1;
        } else {
          result3 = r3;
          r4 = 0;
        }
        if (r4 != 0) {
          throw new RuntimeException("Unexpected underflow");
        }

      } else if (diffScale == LONGWORD_DECIMAL_DIGITS){

        result0 = leftFast0;
        final long r1 =
            leftFast1
          - rightFast0;
        long r2;
        if (r1 < 0) {
          result1 = r1 + MULTIPLER_LONGWORD_DECIMAL;
          r2 =
              leftFast2
            - rightFast1
            - 1;
        } else {
          result1 = r1;
          r2 =
              leftFast2
            - rightFast1;
        }
        long r3;
        if (r2 < 0) {
          result2 = r2 + MULTIPLER_LONGWORD_DECIMAL;
          r3 =
             -rightFast2
            - 1;
        } else {
          result2 = r2;
          r3 =
             -rightFast2;
        }
        if (r3 != 0) {
          throw new RuntimeException("Unexpected underflow");
        }


      } else if (diffScale < TWO_X_LONGWORD_DECIMAL_DIGITS) {

        final long divideFactor = powerOfTenTable[TWO_X_LONGWORD_DECIMAL_DIGITS - diffScale];
        final long multiplyFactor = powerOfTenTable[diffScale - LONGWORD_DECIMAL_DIGITS];

        result0 = leftFast0;
        final long r1 =
            leftFast1
           -(rightFast0 % divideFactor) * multiplyFactor;
        long r2;
        if (r1 < 0) {
          result1 = r1 + MULTIPLER_LONGWORD_DECIMAL;
          r2 =
              leftFast2
            - rightFast0 / divideFactor
            - (rightFast1 % divideFactor) * multiplyFactor
            - 1;
        } else {
          result1 = r1;
          r2 =
              leftFast2
            - rightFast0 / divideFactor
            - (rightFast1 % divideFactor) * multiplyFactor;
        }
        long r3;
        if (r2 < 0) {
          result2 = r2 + MULTIPLER_LONGWORD_DECIMAL;
          r3 =
            - rightFast1 / divideFactor
            - (rightFast2 % divideFactor) * multiplyFactor
            - 1;
        } else {
          result2 = r2;
          r3 =
            - rightFast1 / divideFactor
            - (rightFast2 % divideFactor) * multiplyFactor;
        }
        long r4;
        if (r3 < 0) {
          result3 = r3 + MULTIPLER_LONGWORD_DECIMAL;
          r4 =
            - rightFast2 / divideFactor
            - 1;
        } else {
          result3 = r3;
          r4 =
            - rightFast2 / divideFactor;
        }
        long r5;
        if (r4 < 0) {
          result4 = r4 + MULTIPLER_LONGWORD_DECIMAL;
          r5 = - 1;
        } else {
          result4 = r4;
          r5 = 0;
        }
        if (r5 != 0) {
         throw new RuntimeException("Unexpected underflow");
        }

      } else if (diffScale == TWO_X_LONGWORD_DECIMAL_DIGITS) {

        result0 = leftFast0;
        result1 = leftFast1;
        final long r2 =
            leftFast2
          - rightFast0;
        long r3;
        if (r2 < 0) {
          result2 = r2 + MULTIPLER_LONGWORD_DECIMAL;
          r3 =
            - rightFast1
            - 1;
        } else {
          result2 = r2;
          r3 =
            - rightFast1;
        }
        long r4;
        if (r3 < 0) {
          result3 = r3 + MULTIPLER_LONGWORD_DECIMAL;
          r4 =
             -rightFast2
            - 1;
        } else {
          result3 = r3;
          r4 =
             -rightFast2;
        }
        long r5;
        if (r4 < 0) {
          result4 = r4 + MULTIPLER_LONGWORD_DECIMAL;
          r5 = - 1;
        } else {
          result4 = r4;
          r5 = 0;
        }
        if (r5 != 0) {
          throw new RuntimeException("Unexpected underflow");
        }

      } else {

        final long divideFactor = powerOfTenTable[THREE_X_LONGWORD_DECIMAL_DIGITS - diffScale];
        final long multiplyFactor = powerOfTenTable[diffScale - TWO_X_LONGWORD_DECIMAL_DIGITS];

        result0 = leftFast0;
        result1 = leftFast1;
        final long r2 =
            leftFast2
          - (rightFast0 % divideFactor) * multiplyFactor;
        long r3;
        if (r2 < 0) {
          result2 = r2 + MULTIPLER_LONGWORD_DECIMAL;
          r3 =
            - (rightFast0 / divideFactor)
            - (rightFast1 % divideFactor) * multiplyFactor
            - 1;
        } else {
          result2 = r2;
          r3 =
            - (rightFast0 / divideFactor)
            - (rightFast1 % divideFactor) * multiplyFactor;
        }
        long r4;
        if (r3 < 0) {
          result3 = r3 + MULTIPLER_LONGWORD_DECIMAL;
          r4 =
              - (rightFast1 / divideFactor)
              - (rightFast2 % divideFactor) * multiplyFactor
              - 1;
        } else {
          result3 = r3;
          r4 =
              - (rightFast1 / divideFactor)
              - (rightFast2 % divideFactor) * multiplyFactor;
        }
        long r5;
        if (r4 < 0) {
          result4 = r4 + MULTIPLER_LONGWORD_DECIMAL;
          r5 =
              - (rightFast2 / divideFactor)
              - 1;
        } else {
          result4 = r4;
          r5 =
              - (rightFast2 / divideFactor);
        }
        if (r5 != 0) {
          throw new RuntimeException("Unexpected underflow");
        }
      }
    } else {

      // Since right has a longer digit tail and it doesn't move; we will shift the left digits
      // as we do our addition into the result.

      diffScale = rightScale - leftScale;
      resultScale = rightScale;

      if (diffScale < LONGWORD_DECIMAL_DIGITS) {

        final long divideFactor = powerOfTenTable[LONGWORD_DECIMAL_DIGITS - diffScale];
        final long multiplyFactor = powerOfTenTable[diffScale];

        final long r0 =
            (leftFast0 % divideFactor) * multiplyFactor
          - rightFast0;
        long r1;
        if (r0 < 0) {
          result0 = r0 + MULTIPLER_LONGWORD_DECIMAL;
          r1 =
              leftFast0 / divideFactor
            + (leftFast1 % divideFactor) * multiplyFactor
            - rightFast1
            - 1;
        } else {
          result0 = r0;
          r1 =
              leftFast0 / divideFactor
            + (leftFast1 % divideFactor) * multiplyFactor
            - rightFast1;
        }
        long r2;
        if (r1 < 0) {
          result1 = r1 + MULTIPLER_LONGWORD_DECIMAL;
          r2 =
              leftFast1 / divideFactor
            + (leftFast2 % divideFactor) * multiplyFactor
            - rightFast2
            - 1;
        } else {
          result1 = r1;
          r2 =
              leftFast1 / divideFactor
            + (leftFast2 % divideFactor) * multiplyFactor
            - rightFast2;
        }
        long r3;
        if (r2 < 0) {
          result2 = r2 + MULTIPLER_LONGWORD_DECIMAL;
          r3 =
              leftFast2 / divideFactor
            - 1;
        } else {
          result2 = r2;
          r3 =
              leftFast2 / divideFactor;
        }
        long r4;
        if (r3 < 0) {
          result3 = r3 + MULTIPLER_LONGWORD_DECIMAL;
          r4 = - 1;
        } else {
          result3 = r3;
          r4 = 0;
        }
        if (r4 != 0) {
          throw new RuntimeException("Unexpected underflow");
        }

      } else if (diffScale == LONGWORD_DECIMAL_DIGITS){

        final long r0 =
          - rightFast0;
        long r1;
        if (r0 < 0) {
          result0 = r0 + MULTIPLER_LONGWORD_DECIMAL;
          r1 =
              leftFast0
            - rightFast1
            - 1;
        } else {
          result0 = r0;
          r1 =
              leftFast0
            - rightFast1;
        }
        long r2;
        if (r1 < 0) {
          result1 = r1 + MULTIPLER_LONGWORD_DECIMAL;
          r2 =
              leftFast1
            - rightFast2
            - 1;
        } else {
          result1 = r1;
          r2 =
              leftFast1
            - rightFast2;
        }
        long r3;
        if (r2 < 0) {
          result2 = r2 + MULTIPLER_LONGWORD_DECIMAL;
          r3 =
              leftFast2
            - 1;
        } else {
          result2 = r2;
          r3 =
              leftFast2;
        }
        long r4;
        if (r3 < 0) {
          result3 = r3 + MULTIPLER_LONGWORD_DECIMAL;
          r4 = - 1;
        } else {
          result3 = r3;
          r4 = 0;
        }
        if (r4 != 0) {
          throw new RuntimeException("Unexpected underflow");
        }

      } else if (diffScale < TWO_X_LONGWORD_DECIMAL_DIGITS) {

        final long divideFactor = powerOfTenTable[TWO_X_LONGWORD_DECIMAL_DIGITS - diffScale];
        final long multiplyFactor = powerOfTenTable[diffScale - LONGWORD_DECIMAL_DIGITS];

        final long r0 =
          - rightFast0;
        long r1;
        if (r0 < 0) {
          result0 = r0 + MULTIPLER_LONGWORD_DECIMAL;
          r1 =
              (leftFast0 % divideFactor) * multiplyFactor
            - rightFast1
            - 1;
        } else {
          result0 = r0;
          r1 =
              (leftFast0 % divideFactor) * multiplyFactor
            - rightFast1;
        }
        long r2;
        if (r1 < 0) {
          result1 = r1 + MULTIPLER_LONGWORD_DECIMAL;
          r2 =
              leftFast0 / divideFactor
            + (leftFast1 % divideFactor) * multiplyFactor
            - rightFast2
            - 1;
        } else {
          result1 = r1;
          r2 =
              leftFast0 / divideFactor
            + (leftFast1 % divideFactor) * multiplyFactor
            - rightFast2;
        }
        long r3;
        if (r2 < 0) {
          result2 = r2 + MULTIPLER_LONGWORD_DECIMAL;
          r3 =
              leftFast1 / divideFactor
            + (leftFast2 % divideFactor) * multiplyFactor
            - 1;
        } else {
          result2 = r2;
          r3 =
              leftFast1 / divideFactor
            + (leftFast2 % divideFactor) * multiplyFactor;
        }
        long r4;
        if (r3 < 0) {
          result3 = r3 + MULTIPLER_LONGWORD_DECIMAL;
          r4 =
              leftFast2 / divideFactor
            - 1;
        } else {
          result3 = r3;
          r4 =
              leftFast2 / divideFactor;
        }
        if (r4 < 0) {
          result4 = r4 + MULTIPLER_LONGWORD_DECIMAL;
        } else {
          result4 = r4;
        }

      } else if (diffScale == TWO_X_LONGWORD_DECIMAL_DIGITS) {

        final long r0 =
            - rightFast0;
        long r1;
        if (r0 < 0) {
          result0 = r0 + MULTIPLER_LONGWORD_DECIMAL;
          r1 =
            - rightFast1
            - 1;
        } else {
          result0 = r0;
          r1 =
            - rightFast1;
        }
        long r2;
        if (r1 < 0) {
          result1 = r1 + MULTIPLER_LONGWORD_DECIMAL;
          r2 =
              leftFast0
            - rightFast2
            - 1;
        } else {
          result1 = r1;
          r2 =
              leftFast0
            - rightFast2;
        }
        long r3;
        if (r2 < 0) {
          result2 = r2 + MULTIPLER_LONGWORD_DECIMAL;
          r3 =
              leftFast1
            - 1;
        } else {
          result2 = r2;
          r3 =
              leftFast1;
        }
        long r4;
        if (r3 < 0) {
          result3 = r3 + MULTIPLER_LONGWORD_DECIMAL;
          r4 =
              leftFast2
            - 1;
        } else {
          result3 = r3;
          r4 =
              leftFast2;
        }
        long r5;
        if (r4 < 0) {
          result4 = r4 + MULTIPLER_LONGWORD_DECIMAL;
          r5 = - 1;
        } else {
          result4 = r4;
          r5 = 0;
        }
        if (r5 != 0) {
          throw new RuntimeException("Unexpected underflow");
        }

      } else {

        final long divideFactor = powerOfTenTable[THREE_X_LONGWORD_DECIMAL_DIGITS - diffScale];
        final long multiplyFactor = powerOfTenTable[diffScale - TWO_X_LONGWORD_DECIMAL_DIGITS];

        final long r0 =
            - rightFast0;
        long r1;
        if (r0 < 0) {
          result0 = r0 + MULTIPLER_LONGWORD_DECIMAL;
          r1 =
            - rightFast1
            - 1;
        } else {
          result0 = r0;
          r1 =
            - rightFast1;
        }
        long r2;
        if (r1 < 0) {
          result1 = r1 + MULTIPLER_LONGWORD_DECIMAL;
          r2 =
              (leftFast0 % divideFactor) * multiplyFactor
            - rightFast2
            - 1;
        } else {
          result1 = r1;
          r2 =
              (leftFast0 % divideFactor) * multiplyFactor
            - rightFast2;
        }
        long r3;
        if (r2 < 0) {
          result2 = r2 + MULTIPLER_LONGWORD_DECIMAL;
          r3 =
              leftFast0 / divideFactor
            + (leftFast1 % divideFactor) * multiplyFactor
            - 1;
        } else {
          result2 = r2;
          r3 =
              leftFast0 / divideFactor
            + (leftFast1 % divideFactor) * multiplyFactor;
        }
        long r4;
        if (r3 < 0) {
          result3 = r3 + MULTIPLER_LONGWORD_DECIMAL;
          r4 =
              leftFast1 / divideFactor
            + (leftFast2 % divideFactor) * multiplyFactor
            - 1;
        } else {
          result3 = r3;
          r4 =
              leftFast1 / divideFactor
            + (leftFast2 % divideFactor) * multiplyFactor;
        }
        long r5;
        if (r4 < 0) {
          result4 = r4 + MULTIPLER_LONGWORD_DECIMAL;
          r5 =
              leftFast2 / divideFactor
            - 1;
        } else {
          result4 = r4;
          r5 =
              leftFast2 / divideFactor;
        }
        if (r5 != 0) {
          throw new RuntimeException("Unexpected underflow");
        }
      }
    }

    return
        doFinishAddSubtractDifferentScale(
            result0, result1, result2, result3, result4,
            resultScale,
            fastResult);
  }
Handle decimal subtraction when the values have different scales.
storage-api/src/java/org/apache/hadoop/hive/common/type/FastHiveDecimalImpl.java