private static boolean doMultiply()

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


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

    // Set signum before; if result is zero, fastMultiply will set signum to 0.
    fastResult.fastSignum = (leftSignum == rightSignum ? 1 : -1);
    int resultScale = leftScale + rightScale;

    /*
     * For multiplicands with scale 0, trim trailing zeroes.
     */
    if (leftScale == 0) {

      // Pretend like it has fractional digits so we can get the trailing zero count.
      final int leftTrailingZeroCount =
          fastTrailingDecimalZeroCount(leftFast0, leftFast1, leftFast2, 0, leftIntegerDigitCount);
      if (leftTrailingZeroCount > 0) {
        doFastScaleDown(leftFast0, leftFast1, leftFast2, leftTrailingZeroCount, fastResult);
        resultScale -= leftTrailingZeroCount;
        leftFast0 = fastResult.fast0;
        leftFast1 = fastResult.fast1;
        leftFast2 = fastResult.fast2;
      }
    }
    if (rightScale == 0) {

      // Pretend like it has fractional digits so we can get the trailing zero count.
      final int rightTrailingZeroCount =
          fastTrailingDecimalZeroCount(
              rightFast0, rightFast1, rightFast2, 0, rightIntegerDigitCount);
      if (rightTrailingZeroCount > 0) {
        doFastScaleDown(rightFast0, rightFast1, rightFast2, rightTrailingZeroCount, fastResult);
        resultScale -= rightTrailingZeroCount;
        rightFast0 = fastResult.fast0;
        rightFast1 = fastResult.fast1;
        rightFast2 = fastResult.fast2;
      }
    }

    boolean largeOverflow =
        !fastMultiply5x5HalfWords(
            leftFast0, leftFast1, leftFast2, rightFast0, rightFast1, rightFast2, fastResult);
    if (largeOverflow) {
      return false;
    }

    if (fastResult.fastSignum == 0) {
      fastResult.fastScale = 0;
      return true;
    }

    if (resultScale < 0) {
      if (-resultScale >= HiveDecimal.MAX_SCALE) {
        return false;
      }
      if (!fastScaleUp(
          fastResult.fast0, fastResult.fast1, fastResult.fast2, -resultScale, fastResult)) {
        return false;
      }
      resultScale = 0;
    }

    int precision;
    if (fastResult.fast2 != 0) {
      precision = TWO_X_LONGWORD_DECIMAL_DIGITS + fastLongWordPrecision(fastResult.fast2);
    } else if (fastResult.fast1 != 0) {
      precision = LONGWORD_DECIMAL_DIGITS + fastLongWordPrecision(fastResult.fast1);
    } else {
      precision = fastLongWordPrecision(fastResult.fast0);
    }

    int integerDigitCount = Math.max(0, precision - resultScale);
    if (integerDigitCount > HiveDecimal.MAX_PRECISION) {
      // Integer is too large -- cannot recover by trimming fractional digits.
      return false;
    }

    if (precision > HiveDecimal.MAX_PRECISION || resultScale > HiveDecimal.MAX_SCALE) {

      // Trim off lower fractional digits but with NO ROUNDING.

      final int maxScale = HiveDecimal.MAX_SCALE - integerDigitCount;
      final int scaleDown = resultScale - maxScale;
      if (!fastScaleDownNoRound(
          fastResult.fastSignum,
          fastResult.fast0,
          fastResult.fast1,
          fastResult.fast2,
          scaleDown,
          fastResult)) {
        // Round fractional must be 0.  Not allowed to throw away digits.
        return false;
      }
      resultScale -= scaleDown;
    }
    fastResult.fastScale = resultScale;

    // This assume no round up...
    fastResult.fastIntegerDigitCount = integerDigitCount;

    if (fastResult.fastScale > HiveDecimal.MAX_SCALE) {
      // We are not allowed to lose digits in multiply to be compatible with OldHiveDecimal
      // behavior, so overflow.
      // CONSIDER: Does it make sense to be so restrictive.  If we just did repeated addition,
      //           it would succeed...
      return false;
    }
    final int resultTrailingZeroCount =
        fastTrailingDecimalZeroCount(
            fastResult.fast0,
            fastResult.fast1,
            fastResult.fast2,
            fastResult.fastIntegerDigitCount,
            fastResult.fastScale);
    if (resultTrailingZeroCount > 0) {
      doFastScaleDown(fastResult, resultTrailingZeroCount, fastResult);
      if (fastResult.fastSignum == 0) {
        fastResult.fastScale = 0;
      } else {
        fastResult.fastScale -= resultTrailingZeroCount;
      }
    }

    return true;
  }