EchoNullify commented on code in PR #3121: URL: https://github.com/apache/tinkerpop/pull/3121#discussion_r2107829818
########## gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/NumberHelper.java: ########## @@ -28,6 +28,50 @@ */ public final class NumberHelper { + static final class NumberInfo { + + int bits; + boolean fp; + + NumberInfo(int bits, boolean fp) { + this.bits = bits; + this.fp = fp; + } + } + + enum MathOperation { Review Comment: Updated ########## gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/NumberHelper.java: ########## @@ -312,43 +356,84 @@ private NumberHelper(final BiFunction<Number, Number, Number> add, this.cmp = cmp; } - public static Class<? extends Number> getHighestCommonNumberClass(final Number... numbers) { - return getHighestCommonNumberClass(false, numbers); - } - - public static Class<? extends Number> getHighestCommonNumberClass(final boolean forceFloatingPoint, final Number... numbers) { + static NumberInfo getHighestCommonNumberInfo(final boolean forceFloatingPoint, final Number... numbers) { int bits = 8; boolean fp = forceFloatingPoint; for (final Number number : numbers) { if (!isNumber(number)) continue; final Class<? extends Number> clazz = number.getClass(); if (clazz.equals(Byte.class)) continue; if (clazz.equals(Short.class)) { - bits = bits < 16 ? 16 : bits; + bits = Math.max(bits, 16); } else if (clazz.equals(Integer.class)) { - bits = bits < 32 ? 32 : bits; + bits = Math.max(bits, 32); } else if (clazz.equals(Long.class)) { - bits = bits < 64 ? 64 : bits; + bits = Math.max(bits, 64); } else if (clazz.equals(BigInteger.class)) { - bits = bits < 128 ? 128 : bits; + bits = 128; } else if (clazz.equals(Float.class)) { - bits = bits < 32 ? 32 : bits; + bits = Math.max(bits, 32); fp = true; } else if (clazz.equals(Double.class)) { - bits = bits < 64 ? 64 : bits; + bits = Math.max(bits, 64); fp = true; } else /*if (clazz.equals(BigDecimal.class))*/ { - bits = bits < 128 ? 128 : bits; + bits = 128; fp = true; break; // maxed out, no need to check remaining numbers } } - return determineNumberClass(bits, fp); + return new NumberInfo(bits, fp); + } + + public static Class<? extends Number> getHighestCommonNumberClass(final Number... numbers) { + return getHighestCommonNumberClass(false, numbers); + } + + public static Class<? extends Number> getHighestCommonNumberClass(final boolean forceFloatingPoint, final Number... numbers) { + NumberInfo numberInfo = getHighestCommonNumberInfo(forceFloatingPoint, numbers); + return determineNumberClass(numberInfo.bits, numberInfo.fp); + } + + private static Number mathOperationWithPromote(final MathOperation mathOperation, final boolean forceFloatingPoint, final Number a, final Number b) { + if (null == a || null == b) return a; + NumberInfo numberInfo = getHighestCommonNumberInfo(forceFloatingPoint, a, b); + Number result = 0; + while (true) { + try { + result = mathOperation.apply(numberInfo, a, b); + if (result.getClass() == BigInteger.class || result.getClass() == BigDecimal.class) + { + return result; + } + if (Double.isInfinite(result.doubleValue())) + { + throw new ArithmeticException("Floating point overflow detected"); + } + return result; + } catch (ArithmeticException exception) { + if (!numberInfo.fp && numberInfo.bits >= 64) { + throw exception; + } else if (numberInfo.fp && numberInfo.bits >= 64) { + return result; + } + numberInfo.bits <<= 1; + } + } } /** * Adds two numbers returning the highest common number class between them. * + * <p> + * This method returns a result using the highest common number class between the two inputs. + * If an overflow occurs (either integer or floating-point), the method promotes the precision + * by increasing the bit width or switching to floating-point arithmetic, until a suitable type is found. Review Comment: Done -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: commits-unsubscr...@tinkerpop.apache.org For queries about this service, please contact Infrastructure at: us...@infra.apache.org