in src/main/java/org/apache/commons/jexl3/JexlArithmetic.java [1462:1512]
public Number narrowNumber(final Number original, final Class<?> narrow) {
if (original != null) {
final long value;
if (original instanceof BigDecimal) {
final BigDecimal big = (BigDecimal) original;
try {
// can it be represented as a long?
value = big.longValueExact();
// continue in sequence to try and further reduce
} catch (final ArithmeticException xa) {
// if it is bigger than a double, it cannot be narrowed
if (big.compareTo(BIGD_DOUBLE_MAX_VALUE) > 0
|| big.compareTo(BIGD_DOUBLE_MIN_VALUE) < 0) {
return original;
}
// represent as double
return narrow(narrow, original.doubleValue());
}
// this continues with value as long
} else {
if (isFloatingPoint(original)) {
final double doubleValue = original.doubleValue();
// if it is not equivalent to a Long...
if ((long) doubleValue != doubleValue) {
return narrow(narrow, doubleValue);
}
// else it can be represented as a long
} else if (original instanceof BigInteger) {
final BigInteger bigi = (BigInteger) original;
// if it is bigger than a Long, it cannot be narrowed
if (!BigInteger.valueOf(bigi.longValue()).equals(bigi)) {
return original;
}
// else it can be represented as a long
}
value = original.longValue();
}
// it can be represented as a long; determine the smallest possible numberable representation
if (narrowAccept(narrow, Byte.class) && (byte) value == value) {
// it will fit in a byte
return (byte) value;
}
if (narrowAccept(narrow, Short.class) && (short) value == value) {
return (short) value;
}
if (narrowAccept(narrow, Integer.class) && (int) value == value) {
return (int) value;
}
}
return original;
}