use of io.crate.execution.engine.aggregation.impl.util.KahanSummationForDouble in project crate by crate.
the class ArraySumFunctionTest method test_array_returns_sum_of_elements.
@Test
public void test_array_returns_sum_of_elements() {
// This test picks up random numbers but controls that overflow will not happen (overflow case is checked in another test).
List<DataType> typesToTest = new ArrayList(DataTypes.NUMERIC_PRIMITIVE_TYPES);
typesToTest.add(DataTypes.NUMERIC);
for (DataType type : typesToTest) {
var valuesToTest = TestingHelpers.getRandomsOfType(1, 10, type);
DataType inputDependantOutputType = DataTypes.LONG;
if (type == DataTypes.FLOAT || type == DataTypes.DOUBLE || type == DataTypes.NUMERIC) {
inputDependantOutputType = type;
} else {
// check potential overflow and get rid of numbers causing overflow
long sum = 0;
for (int i = 0; i < valuesToTest.size(); i++) {
if (valuesToTest.get(i) != null) {
long nextNum = ((Number) valuesToTest.get(i)).longValue();
try {
sum = Math.addExact(sum, nextNum);
} catch (ArithmeticException e) {
// excluding i
valuesToTest = valuesToTest.subList(0, i);
break;
}
}
}
}
KahanSummationForDouble kahanSummationForDouble = new KahanSummationForDouble();
var optional = valuesToTest.stream().filter(Objects::nonNull).reduce((o1, o2) -> {
if (o1 instanceof BigDecimal) {
return ((BigDecimal) o1).add((BigDecimal) o2);
} else if (o1 instanceof Double || o1 instanceof Float) {
return kahanSummationForDouble.sum(((Number) o1).doubleValue(), ((Number) o2).doubleValue());
} else {
return DataTypes.LONG.implicitCast(o1) + DataTypes.LONG.implicitCast(o2);
}
});
var expected = inputDependantOutputType.implicitCast(optional.orElse(null));
String expression = String.format(Locale.ENGLISH, "array_sum(?::%s[])", type.getName());
assertEvaluate(expression, expected, Literal.of(valuesToTest, new ArrayType<>(type)));
}
}
Aggregations