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

    // Arrange so result* has a longer digit tail and it lines up; we will shift the shift* digits
    // as we do our addition and them into the result.
    long result0;
    long result1;
    long result2;

    long shift0;
    long shift1;
    long shift2;

    int diffScale;
    int resultScale;

    // Since addition is commutative, we can add in any order.
    if (leftScale > rightScale) {

      result0 = leftFast0;
      result1 = leftFast1;
      result2 = leftFast2;

      shift0 = rightFast0;
      shift1 = rightFast1;
      shift2 = rightFast2;

      diffScale = leftScale - rightScale;
      resultScale = leftScale;
    } else {

      result0 = rightFast0;
      result1 = rightFast1;
      result2 = rightFast2;

      shift0 = leftFast0;
      shift1 = leftFast1;
      shift2 = leftFast2;

      diffScale = rightScale - leftScale;
      resultScale = rightScale;
    }

    long result3 = 0;
    long result4 = 0;

    if (diffScale < LONGWORD_DECIMAL_DIGITS) {

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

      final long r0 =
          result0
        + (shift0 % divideFactor) * multiplyFactor;
      result0 =
          r0 % MULTIPLER_LONGWORD_DECIMAL;
      final long r1 =
          result1
        + shift0 / divideFactor
        + (shift1 % divideFactor) * multiplyFactor
        + r0 / MULTIPLER_LONGWORD_DECIMAL;
      result1 =
          r1 % MULTIPLER_LONGWORD_DECIMAL;
      final long r2 =
          result2
        + shift1 / divideFactor
        + (shift2 % divideFactor) * multiplyFactor
        + r1 / MULTIPLER_LONGWORD_DECIMAL;
      result2 =
          r2 % MULTIPLER_LONGWORD_DECIMAL;
      final long r3 =
          shift2 / divideFactor
        + r2 / MULTIPLER_LONGWORD_DECIMAL;
      result3 =
          r3 % MULTIPLER_LONGWORD_DECIMAL;

    } else if (diffScale == LONGWORD_DECIMAL_DIGITS){

      final long r1 =
          result1
        + shift0;
      result1 =
          r1 % MULTIPLER_LONGWORD_DECIMAL;
      final long r2 =
          result2
        + shift1
        + r1 / MULTIPLER_LONGWORD_DECIMAL;
      result2 =
          r2 % MULTIPLER_LONGWORD_DECIMAL;
      final long r3 =
          shift2
        + r2 / MULTIPLER_LONGWORD_DECIMAL;
      result3 =
          r3 % MULTIPLER_LONGWORD_DECIMAL;
      result4 = r3 / MULTIPLER_LONGWORD_DECIMAL;

    } 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 r1 =
          result1
        + (shift0 % divideFactor) * multiplyFactor;
      result1 =
          r1 % MULTIPLER_LONGWORD_DECIMAL;
      final long r2 =
          result2
        + shift0 / divideFactor
        + (shift1 % divideFactor) * multiplyFactor
        + r1 / MULTIPLER_LONGWORD_DECIMAL;
      result2 =
          r2 % MULTIPLER_LONGWORD_DECIMAL;
      final long r3 =
          shift1 / divideFactor
        + (shift2 % divideFactor) * multiplyFactor
        + r2 / MULTIPLER_LONGWORD_DECIMAL;
      result3 =
          r3 % MULTIPLER_LONGWORD_DECIMAL;
      final long r4 =
          shift2 / divideFactor
        + r3 / MULTIPLER_LONGWORD_DECIMAL;
      result4 =
          r4 % MULTIPLER_LONGWORD_DECIMAL;

    } else if (diffScale == TWO_X_LONGWORD_DECIMAL_DIGITS) {

      final long r2 =
          result2
        + shift0;
      result2 =
          r2 % MULTIPLER_LONGWORD_DECIMAL;
      final long r3 =
          shift1
        + r2 / MULTIPLER_LONGWORD_DECIMAL;
      result3 =
          r3 % MULTIPLER_LONGWORD_DECIMAL;
      final long r4 =
          shift2
        + r3 / MULTIPLER_LONGWORD_DECIMAL;
      result4 =
          r4 % MULTIPLER_LONGWORD_DECIMAL;

    } else {

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

      final long r2 =
          result2
        + (shift0 % divideFactor) * multiplyFactor;
      result2 =
          r2 % MULTIPLER_LONGWORD_DECIMAL;
      final long r3 =
          shift0 / divideFactor
        + (shift1 % divideFactor) * multiplyFactor
        + r2 / MULTIPLER_LONGWORD_DECIMAL;
      result3 =
          r3 % MULTIPLER_LONGWORD_DECIMAL;
      final long r4 =
          shift1 / divideFactor
        + (shift2 % divideFactor) * multiplyFactor
        + r3 / MULTIPLER_LONGWORD_DECIMAL;
      result4 =
          r4 % MULTIPLER_LONGWORD_DECIMAL;
      if (shift2 / divideFactor != 0) {
        throw new RuntimeException("Unexpected overflow");
      }

    }

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