public static boolean fastRoundFractionalHalfUp5Words(
      int fastSignum, long fast0, long fast1, long fast2, long fast3, long fast4,
      int scaleDown,
      FastHiveDecimal fastResult) {

    // Adjust all longs using power 10 division/remainder.
    long result0;
    long result1;
    long result2;
    long result3;
    long result4;
    if (scaleDown < LONGWORD_DECIMAL_DIGITS) {

      // Part of lowest word survives.

      // Divide down just before scaleDown to get round digit.
      final long withRoundDigit = fast0 / powerOfTenTable[scaleDown - 1];
      final long roundDigit = withRoundDigit % 10;

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

      if (roundDigit < 5) {
        result0 =
            withRoundDigit / 10
          + ((fast1 % divideFactor) * multiplyFactor);
        result1 =
            fast1 / divideFactor
          + ((fast2 % divideFactor) * multiplyFactor);
        result2 =
          + fast2 / divideFactor
          + ((fast3 % divideFactor) * multiplyFactor);
        result3 =
            fast3 / divideFactor
          + ((fast4 % divideFactor) * multiplyFactor);
        result4 =
            fast4 / divideFactor;
      } else {
        // Add rounding and handle carry.
        final long r0 =
            withRoundDigit / 10
          + ((fast1 % divideFactor) * multiplyFactor)
          + 1;
        result0 = r0 % MULTIPLER_LONGWORD_DECIMAL;
        final long r1 =
            fast1 / divideFactor
          + ((fast2 % divideFactor) * multiplyFactor)
          + r0 / MULTIPLER_LONGWORD_DECIMAL;
        result1 = r1 % MULTIPLER_LONGWORD_DECIMAL;
        final long r2 =
            fast2 / divideFactor +
          + ((fast3 % divideFactor) * multiplyFactor)
          + r1 / MULTIPLER_LONGWORD_DECIMAL;
        result2 = r2 % MULTIPLER_LONGWORD_DECIMAL;
        final long r3 =
            fast3 / divideFactor
          + ((fast4 % divideFactor) * multiplyFactor)
          + r2 / MULTIPLER_LONGWORD_DECIMAL;
        result3 = r3 % MULTIPLER_LONGWORD_DECIMAL;
        result4 =
            fast4 / divideFactor +
            r3 % MULTIPLER_LONGWORD_DECIMAL;
      }
    } else if (scaleDown < TWO_X_LONGWORD_DECIMAL_DIGITS) {

      // Throw away lowest word.

      final int adjustedScaleDown = scaleDown - LONGWORD_DECIMAL_DIGITS;

      long roundDigit;
      long fast1Scaled;
      if (adjustedScaleDown == 0) {
        // Grab round digit from lowest word.
        roundDigit = fast0 / (MULTIPLER_LONGWORD_DECIMAL / 10);
        fast1Scaled = fast1;
      } else {
        // Divide down just before scaleDown to get round digit.
        final long withRoundDigit = fast1 / powerOfTenTable[adjustedScaleDown - 1];
        roundDigit = withRoundDigit % 10;
        fast1Scaled = withRoundDigit / 10;
      }

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

      if (roundDigit < 5) {
        result0 =
            fast1Scaled
          + ((fast2 % divideFactor) * multiplyFactor);
        result1 =
            fast2 / divideFactor
          + ((fast3 % divideFactor) * multiplyFactor);
        result2 =
            fast3 / divideFactor
          + ((fast4 % divideFactor) * multiplyFactor);
        result3 =
            fast4 / divideFactor;
      } else {
        // Add rounding and handle carry.
        final long r0 =
            fast1Scaled
          + ((fast2 % divideFactor) * multiplyFactor)
          + 1;
        result0 = r0 % MULTIPLER_LONGWORD_DECIMAL;
        final long r1 =
            fast2 / divideFactor
          + ((fast3 % divideFactor) * multiplyFactor)
          + r0 / MULTIPLER_LONGWORD_DECIMAL;
        result1 = r1 % MULTIPLER_LONGWORD_DECIMAL;
        final long r2 =
            fast3 / divideFactor
          + ((fast4 % divideFactor) * multiplyFactor)
          + r1 / MULTIPLER_LONGWORD_DECIMAL;
        result2 = r2 % MULTIPLER_LONGWORD_DECIMAL;
        result3 =
            fast4 / divideFactor
          + r2 / MULTIPLER_LONGWORD_DECIMAL;
      }
      result4 = 0;
    } else {

      // Throw away middle and lowest words.

      final int adjustedScaleDown = scaleDown - 2*LONGWORD_DECIMAL_DIGITS;

      long roundDigit;
      long fast2Scaled;
      if (adjustedScaleDown == 0) {
        // Grab round digit from middle word.
        roundDigit = fast1 / (MULTIPLER_LONGWORD_DECIMAL / 10);
        fast2Scaled = fast2;
      } else {
        // Divide down just before scaleDown to get round digit.
        final long withRoundDigit = fast2 / powerOfTenTable[adjustedScaleDown - 1];
        roundDigit = withRoundDigit % 10;
        fast2Scaled = withRoundDigit / 10;
      }

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

      if (roundDigit < 5) {
        result0 =
            fast2Scaled
          + ((fast3 % divideFactor) * multiplyFactor);
        result1 =
            fast3 / divideFactor
          + ((fast4 % divideFactor) * multiplyFactor);
        result2 =
            fast4 / divideFactor;
      } else {
        // Add rounding.
        final long r0 =
            fast2Scaled
          + ((fast3 % divideFactor) * multiplyFactor)
          + 1;
        result0 = r0 % MULTIPLER_LONGWORD_DECIMAL;
        final long r1 =
            fast3 / divideFactor
          + ((fast4 % divideFactor) * multiplyFactor)
          + r0 / MULTIPLER_LONGWORD_DECIMAL;
        result1 = r1 % MULTIPLER_LONGWORD_DECIMAL;
        result2 =
            fast4 / divideFactor
          + r1 / MULTIPLER_LONGWORD_DECIMAL;
      }
      result3 = 0;
      result4 = 0;
    }

    if (result4 != 0 || result3 != 0) {
      throw new RuntimeException("Unexpected overflow into result3 or result4");
    }
    if (result0 == 0 && result1 == 0 && result2 == 0) {
      fastResult.fastReset();
    }
    fastResult.fastSignum = fastSignum;
    fastResult.fast0 = result0;
    fastResult.fast1 = result1;
    fastResult.fast2 = result2;

    return (result2 <= MAX_HIGHWORD_DECIMAL);
  }
Fast decimal scale down by factor of 10 with rounding ROUND_HALF_UP.

When the fraction being scaled away is &gt;= 0.5, the add 1.

@param fastSignum the sign (-1, 0, or +1)
@param fast0 word 0 of the internal representation
@param fast1 word 1
@param fast2 word 2
@param fast3 word 3
@param fast4 word 4
@param scaleDown the number of integer digits to scale
@param fastResult an object to reuse
@return was the operation successfule?
storage-api/src/java/org/apache/hadoop/hive/common/type/FastHiveDecimalImpl.java