diff --git a/core/trino-main/src/main/java/io/trino/operator/scalar/MathFunctions.java b/core/trino-main/src/main/java/io/trino/operator/scalar/MathFunctions.java index 921bd3bd7514..aaea7d5d4570 100644 --- a/core/trino-main/src/main/java/io/trino/operator/scalar/MathFunctions.java +++ b/core/trino-main/src/main/java/io/trino/operator/scalar/MathFunctions.java @@ -84,6 +84,15 @@ public final class MathFunctions private static final Int128[] DECIMAL_HALF_UNSCALED_FOR_SCALE; private static final Int128[] DECIMAL_ALMOST_HALF_UNSCALED_FOR_SCALE; + // Lookup table of 10^n as double for small non-negative n. Values are bit-exact matches of Math.pow(10, n) + // for n in [0, 18]; see Pow10 verification in the session notes. Hot-path round(double, long) and + // roundReal(long, long) use this to avoid calling Math.pow for the typical decimals range. + private static final double[] POWERS_OF_TEN_DOUBLE = new double[] { + 1.0, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, 10000000.0, 100000000.0, 1000000000.0, + 10000000000.0, 100000000000.0, 1000000000000.0, 10000000000000.0, 100000000000000.0, + 1000000000000000.0, 10000000000000000.0, 100000000000000000.0, 1000000000000000000.0 + }; + static { DECIMAL_HALF_UNSCALED_FOR_SCALE = new Int128[Decimals.MAX_PRECISION]; DECIMAL_ALMOST_HALF_UNSCALED_FOR_SCALE = new Int128[Decimals.MAX_PRECISION]; @@ -102,6 +111,14 @@ public final class MathFunctions } } + private static double powerOfTen(long decimals) + { + if (decimals >= 0 && decimals < POWERS_OF_TEN_DOUBLE.length) { + return POWERS_OF_TEN_DOUBLE[(int) decimals]; + } + return Math.pow(10, decimals); + } + private MathFunctions() {} @Description("Absolute value") @@ -899,7 +916,7 @@ public static double round(@SqlType(StandardTypes.DOUBLE) double num, @SqlType(S return num; } - double factor = Math.pow(10, decimals); + double factor = powerOfTen(decimals); int sign = (num < 0) ? -1 : 1; double rescaled = sign * num * factor; long rescaledRound = Math.round(rescaled); @@ -926,7 +943,7 @@ public static long roundReal(@SqlType(StandardTypes.REAL) long num, @SqlType(Sta return num; } - double factor = Math.pow(10, decimals); + double factor = powerOfTen(decimals); int sign = (numInFloat < 0) ? -1 : 1; double result; double rescaled = sign * numInFloat * factor;