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