public static boolean fastScaleByPowerOfTen()

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


  public static boolean fastScaleByPowerOfTen(
      int fastSignum,
      long fast0,
      long fast1,
      long fast2,
      int fastIntegerDigitCount,
      int fastScale,
      int power,
      FastHiveDecimal fastResult) {

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

    final int absPower = Math.abs(power);

    if (power > 0) {

      int integerRoom;
      int fractionalRoom;
      if (fastIntegerDigitCount > 0) {

        // Is there integer room above?

        integerRoom = HiveDecimal.MAX_PRECISION - fastIntegerDigitCount;
        if (integerRoom < power) {
          return false;
        }
        fastResult.fastSignum = fastSignum;
        if (fastScale <= power) {

          // All fractional digits become integer digits.
          final int scaleUp = power - fastScale;
          if (scaleUp > 0) {
            if (!fastScaleUp(fast0, fast1, fast2, scaleUp, fastResult)) {
              throw new RuntimeException("Unexpected");
            }
          } else {
            fastResult.fast0 = fast0;
            fastResult.fast1 = fast1;
            fastResult.fast2 = fast2;
          }
          fastResult.fastIntegerDigitCount = fastIntegerDigitCount + fastScale + scaleUp;
          fastResult.fastScale = 0;

        } else {

          // Only a scale adjustment is needed.
          fastResult.fastSet(
              fastSignum, fast0, fast1, fast2, fastIntegerDigitCount + power, fastScale - power);
        }
      } else {

        // How much can the fraction be moved up?

        final int rawPrecision = fastRawPrecision(fastSignum, fast0, fast1, fast2);
        final int zeroesBelowDot = fastScale - rawPrecision;

        // Our limit is max precision integer digits + "leading" zeros below the dot.
        // E.g. 0.00021 has 3 zeroes below the dot.
        //
        if (power > HiveDecimal.MAX_PRECISION + zeroesBelowDot) {

          // Fractional part powered up too high.
          return false;
        }

        final int newIntegerDigitCount = Math.max(0, power - zeroesBelowDot);
        if (newIntegerDigitCount > rawPrecision) {

          fastResult.fastSignum = fastSignum;
          final int scaleUp = newIntegerDigitCount - rawPrecision;
          if (!fastScaleUp(fast0, fast1, fast2, scaleUp, fastResult)) {
            throw new RuntimeException("Unexpected");
          }
          fastResult.fastIntegerDigitCount = newIntegerDigitCount;
          fastResult.fastScale = 0;
        } else {
          final int newScale = Math.max(0, fastScale - power);
          fastResult.fastSet(fastSignum, fast0, fast1, fast2, newIntegerDigitCount, newScale);
        }
      }

    } else if (fastScale + absPower <= HiveDecimal.MAX_SCALE) {

      // Negative power with range -- adjust the scale.

      final int newScale = fastScale + absPower;
      final int newIntegerDigitCount = Math.max(0, fastIntegerDigitCount - absPower);

      final int trailingZeroCount =
          fastTrailingDecimalZeroCount(fast0, fast1, fast2, newIntegerDigitCount, newScale);
      if (trailingZeroCount > 0) {
        fastResult.fastSignum = fastSignum;
        doFastScaleDown(fast0, fast1, fast2, trailingZeroCount, fastResult);
        fastResult.fastScale = newScale - trailingZeroCount;
        fastResult.fastIntegerDigitCount = newIntegerDigitCount;
      } else {
        fastResult.fastSet(fastSignum, fast0, fast1, fast2, newIntegerDigitCount, newScale);
      }
    } else {

      // fastScale + absPower > HiveDecimal.MAX_SCALE

      // Look at getting rid of fractional digits that will now be below HiveDecimal.MAX_SCALE.

      final int scaleDown = fastScale + absPower - HiveDecimal.MAX_SCALE;

      if (scaleDown < HiveDecimal.MAX_SCALE) {
        if (!fastRoundFractionalHalfUp(fastSignum, fast0, fast1, fast2, scaleDown, fastResult)) {
          // Overflow.
          return false;
        }
        if (fastResult.fastSignum != 0) {

          fastResult.fastScale = HiveDecimal.MAX_SCALE;
          fastResult.fastIntegerDigitCount =
              Math.max(0, fastRawPrecision(fastResult) - fastResult.fastScale);

          final int trailingZeroCount =
              fastTrailingDecimalZeroCount(
                  fastResult.fast0,
                  fastResult.fast1,
                  fastResult.fast2,
                  fastResult.fastIntegerDigitCount,
                  fastResult.fastScale);
          if (trailingZeroCount > 0) {
            doFastScaleDown(fastResult, trailingZeroCount, fastResult);
            fastResult.fastScale -= trailingZeroCount;
          }
        }
      } else {
        // All precision has been lost -- result is 0.
        fastResult.fastReset();
      }
    }

    /*
    if (!fastResult.fastIsValid()) {
      fastResult.fastRaiseInvalidException();
    }
    */

    return true;
  }