in kyuubi-hive-jdbc/src/main/java/org/apache/kyuubi/jdbc/hive/common/FastHiveDecimalImpl.java [7336:7478]
private static boolean fastAddDifferentScale(
long leftFast0,
long leftFast1,
long leftFast2,
int leftIntegerDigitCount,
int leftScale,
long rightFast0,
long rightFast1,
long rightFast2,
int rightIntegerDigitCount,
int rightScale,
FastHiveDecimal fastResult) {
// Arrange so result* has a longer digit tail and it lines up; we will shift the shift* digits
// as we do our addition and them into the result.
long result0;
long result1;
long result2;
long shift0;
long shift1;
long shift2;
int diffScale;
int resultScale;
// Since addition is commutative, we can add in any order.
if (leftScale > rightScale) {
result0 = leftFast0;
result1 = leftFast1;
result2 = leftFast2;
shift0 = rightFast0;
shift1 = rightFast1;
shift2 = rightFast2;
diffScale = leftScale - rightScale;
resultScale = leftScale;
} else {
result0 = rightFast0;
result1 = rightFast1;
result2 = rightFast2;
shift0 = leftFast0;
shift1 = leftFast1;
shift2 = leftFast2;
diffScale = rightScale - leftScale;
resultScale = rightScale;
}
long result3 = 0;
long result4 = 0;
if (diffScale < LONGWORD_DECIMAL_DIGITS) {
final long divideFactor = powerOfTenTable[LONGWORD_DECIMAL_DIGITS - diffScale];
final long multiplyFactor = powerOfTenTable[diffScale];
final long r0 = result0 + (shift0 % divideFactor) * multiplyFactor;
result0 = r0 % MULTIPLER_LONGWORD_DECIMAL;
final long r1 =
result1
+ shift0 / divideFactor
+ (shift1 % divideFactor) * multiplyFactor
+ r0 / MULTIPLER_LONGWORD_DECIMAL;
result1 = r1 % MULTIPLER_LONGWORD_DECIMAL;
final long r2 =
result2
+ shift1 / divideFactor
+ (shift2 % divideFactor) * multiplyFactor
+ r1 / MULTIPLER_LONGWORD_DECIMAL;
result2 = r2 % MULTIPLER_LONGWORD_DECIMAL;
final long r3 = shift2 / divideFactor + r2 / MULTIPLER_LONGWORD_DECIMAL;
result3 = r3 % MULTIPLER_LONGWORD_DECIMAL;
} else if (diffScale == LONGWORD_DECIMAL_DIGITS) {
final long r1 = result1 + shift0;
result1 = r1 % MULTIPLER_LONGWORD_DECIMAL;
final long r2 = result2 + shift1 + r1 / MULTIPLER_LONGWORD_DECIMAL;
result2 = r2 % MULTIPLER_LONGWORD_DECIMAL;
final long r3 = shift2 + r2 / MULTIPLER_LONGWORD_DECIMAL;
result3 = r3 % MULTIPLER_LONGWORD_DECIMAL;
result4 = r3 / MULTIPLER_LONGWORD_DECIMAL;
} else if (diffScale < TWO_X_LONGWORD_DECIMAL_DIGITS) {
final long divideFactor = powerOfTenTable[TWO_X_LONGWORD_DECIMAL_DIGITS - diffScale];
final long multiplyFactor = powerOfTenTable[diffScale - LONGWORD_DECIMAL_DIGITS];
final long r1 = result1 + (shift0 % divideFactor) * multiplyFactor;
result1 = r1 % MULTIPLER_LONGWORD_DECIMAL;
final long r2 =
result2
+ shift0 / divideFactor
+ (shift1 % divideFactor) * multiplyFactor
+ r1 / MULTIPLER_LONGWORD_DECIMAL;
result2 = r2 % MULTIPLER_LONGWORD_DECIMAL;
final long r3 =
shift1 / divideFactor
+ (shift2 % divideFactor) * multiplyFactor
+ r2 / MULTIPLER_LONGWORD_DECIMAL;
result3 = r3 % MULTIPLER_LONGWORD_DECIMAL;
final long r4 = shift2 / divideFactor + r3 / MULTIPLER_LONGWORD_DECIMAL;
result4 = r4 % MULTIPLER_LONGWORD_DECIMAL;
} else if (diffScale == TWO_X_LONGWORD_DECIMAL_DIGITS) {
final long r2 = result2 + shift0;
result2 = r2 % MULTIPLER_LONGWORD_DECIMAL;
final long r3 = shift1 + r2 / MULTIPLER_LONGWORD_DECIMAL;
result3 = r3 % MULTIPLER_LONGWORD_DECIMAL;
final long r4 = shift2 + r3 / MULTIPLER_LONGWORD_DECIMAL;
result4 = r4 % MULTIPLER_LONGWORD_DECIMAL;
} else {
final long divideFactor = powerOfTenTable[THREE_X_LONGWORD_DECIMAL_DIGITS - diffScale];
final long multiplyFactor = powerOfTenTable[diffScale - TWO_X_LONGWORD_DECIMAL_DIGITS];
final long r2 = result2 + (shift0 % divideFactor) * multiplyFactor;
result2 = r2 % MULTIPLER_LONGWORD_DECIMAL;
final long r3 =
shift0 / divideFactor
+ (shift1 % divideFactor) * multiplyFactor
+ r2 / MULTIPLER_LONGWORD_DECIMAL;
result3 = r3 % MULTIPLER_LONGWORD_DECIMAL;
final long r4 =
shift1 / divideFactor
+ (shift2 % divideFactor) * multiplyFactor
+ r3 / MULTIPLER_LONGWORD_DECIMAL;
result4 = r4 % MULTIPLER_LONGWORD_DECIMAL;
if (shift2 / divideFactor != 0) {
throw new RuntimeException("Unexpected overflow");
}
}
return doFinishAddSubtractDifferentScale(
result0, result1, result2, result3, result4, resultScale, fastResult);
}