public static boolean doFastRound()

in kyuubi-hive-jdbc/src/main/java/org/apache/kyuubi/jdbc/hive/common/FastHiveDecimalImpl.java [4353:4622]


  public static boolean doFastRound(
      int fastSignum,
      long fast0,
      long fast1,
      long fast2,
      int fastIntegerDigitCount,
      int fastScale,
      int roundPower,
      int roundingMode,
      FastHiveDecimal fastResult) {

    if (fastSignum == 0) {

      // Zero result.
      fastResult.fastReset();
      return true;
    } else if (fastScale == roundPower) {

      // The roundPower same as scale means all zeroes below round point.

      fastResult.fastSet(fastSignum, fast0, fast1, fast2, fastIntegerDigitCount, fastScale);
      /*
      if (!fastResult.fastIsValid()) {
        fastResult.fastRaiseInvalidException();
      }
      */
      return true;
    }

    if (roundPower > fastScale) {

      // We pretend to add trailing zeroes, EVEN WHEN it would exceed the HiveDecimal.MAX_PRECISION.

      // Copy current value; do not change current scale.
      fastResult.fastSet(fastSignum, fast0, fast1, fast2, fastIntegerDigitCount, fastScale);
      /*
      if (!fastResult.fastIsValid()) {
        fastResult.fastRaiseInvalidException();
      }
      */
    } else if (roundPower < 0) {

      // roundPower < 0
      //
      // Negative scale means we start rounding integer digits.
      //
      // The result will integer result will have at least abs(roundPower) trailing digits.
      //
      // Examples where the 'r's show the rounding digits:
      //
      //      round(12500, -3) = 13000           // BigDecimal.ROUND_HALF_UP
      //              rrr
      //
      // Or,  ceiling(12400.8302, -2) = 12500     // BigDecimal.ROUND_CEILING
      //                 rr rrrr
      //
      // Notice that any fractional digits will be gone in the result.
      //
      switch (roundingMode) {
        case BigDecimal.ROUND_DOWN:
          if (!fastRoundIntegerDown(
              fastSignum,
              fast0,
              fast1,
              fast2,
              fastIntegerDigitCount,
              fastScale,
              roundPower,
              fastResult)) {
            return false;
          }
          break;
        case BigDecimal.ROUND_UP:
          if (!fastRoundIntegerUp(
              fastSignum,
              fast0,
              fast1,
              fast2,
              fastIntegerDigitCount,
              fastScale,
              roundPower,
              fastResult)) {
            return false;
          }
          break;
        case BigDecimal.ROUND_FLOOR:
          // Round towards negative infinity.
          if (fastSignum == 1) {
            if (!fastRoundIntegerDown(
                fastSignum,
                fast0,
                fast1,
                fast2,
                fastIntegerDigitCount,
                fastScale,
                roundPower,
                fastResult)) {
              return false;
            }
          } else {
            if (!fastRoundIntegerUp(
                fastSignum,
                fast0,
                fast1,
                fast2,
                fastIntegerDigitCount,
                fastScale,
                roundPower,
                fastResult)) {
              return false;
            }
            if (fastResult.fast2 > MAX_HIGHWORD_DECIMAL) {
              return false;
            }
          }
          break;
        case BigDecimal.ROUND_CEILING:
          // Round towards positive infinity.
          if (fastSignum == 1) {
            if (!fastRoundIntegerUp(
                fastSignum,
                fast0,
                fast1,
                fast2,
                fastIntegerDigitCount,
                fastScale,
                roundPower,
                fastResult)) {
              return false;
            }
            if (fastResult.fast2 > MAX_HIGHWORD_DECIMAL) {
              return false;
            }
          } else {
            if (!fastRoundIntegerDown(
                fastSignum,
                fast0,
                fast1,
                fast2,
                fastIntegerDigitCount,
                fastScale,
                roundPower,
                fastResult)) {
              return false;
            }
          }
          break;
        case BigDecimal.ROUND_HALF_UP:
          if (!fastRoundIntegerHalfUp(
              fastSignum,
              fast0,
              fast1,
              fast2,
              fastIntegerDigitCount,
              fastScale,
              roundPower,
              fastResult)) {
            return false;
          }
          if (fastResult.fast2 > MAX_HIGHWORD_DECIMAL) {
            return false;
          }
          break;
        case BigDecimal.ROUND_HALF_EVEN:
          if (!fastRoundIntegerHalfEven(
              fastSignum,
              fast0,
              fast1,
              fast2,
              fastIntegerDigitCount,
              fastScale,
              roundPower,
              fastResult)) {
            return false;
          }
          if (fastResult.fast2 > MAX_HIGHWORD_DECIMAL) {
            return false;
          }
          break;
        default:
          throw new RuntimeException("Unsupported rounding mode " + roundingMode);
      }

      // The fastRoundInteger* methods remove all fractional digits, set fastIntegerDigitCount, and
      // set fastScale to 0.
      return true;

    } else {

      // roundPower < fastScale

      // Do rounding of fractional digits.
      final int scaleDown = fastScale - roundPower;
      switch (roundingMode) {
        case BigDecimal.ROUND_DOWN:
          fastRoundFractionalDown(fastSignum, fast0, fast1, fast2, scaleDown, fastResult);
          break;
        case BigDecimal.ROUND_UP:
          if (!fastRoundFractionalUp(fastSignum, fast0, fast1, fast2, scaleDown, fastResult)) {
            return false;
          }
          break;
        case BigDecimal.ROUND_FLOOR:
          // Round towards negative infinity.
          if (fastSignum == 1) {
            fastRoundFractionalDown(fastSignum, fast0, fast1, fast2, scaleDown, fastResult);
          } else {
            if (!fastRoundFractionalUp(fastSignum, fast0, fast1, fast2, scaleDown, fastResult)) {
              return false;
            }
          }
          break;
        case BigDecimal.ROUND_CEILING:
          // Round towards positive infinity.
          if (fastSignum == 1) {
            if (!fastRoundFractionalUp(fastSignum, fast0, fast1, fast2, scaleDown, fastResult)) {
              return false;
            }
          } else {
            fastRoundFractionalDown(fastSignum, fast0, fast1, fast2, scaleDown, fastResult);
          }
          break;
        case BigDecimal.ROUND_HALF_UP:
          if (!fastRoundFractionalHalfUp(fastSignum, fast0, fast1, fast2, scaleDown, fastResult)) {
            return false;
          }
          break;
        case BigDecimal.ROUND_HALF_EVEN:
          if (!fastRoundFractionalHalfEven(
              fastSignum, fast0, fast1, fast2, scaleDown, fastResult)) {
            return false;
          }
          break;
        default:
          throw new RuntimeException("Unsupported rounding mode " + roundingMode);
      }
      if (fastResult.fastSignum == 0) {
        fastResult.fastScale = 0;
        /*
        if (!fastResult.fastIsValid()) {
          fastResult.fastRaiseInvalidException();
        }
        */
      } else {
        final int rawPrecision = fastRawPrecision(fastResult);
        fastResult.fastIntegerDigitCount = Math.max(0, rawPrecision - roundPower);
        fastResult.fastScale = roundPower;

        // Trim trailing zeroes and re-adjust scale.
        final int trailingZeroCount =
            fastTrailingDecimalZeroCount(
                fastResult.fast0,
                fastResult.fast1,
                fastResult.fast2,
                fastResult.fastIntegerDigitCount,
                fastResult.fastScale);
        if (trailingZeroCount > 0) {
          doFastScaleDown(fastResult, trailingZeroCount, fastResult);
          fastResult.fastScale -= trailingZeroCount;
          /*
          if (!fastResult.fastIsValid()) {
            fastResult.fastRaiseInvalidException();
          }
          */
        }
      }
    }

    return true;
  }