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;
}