Search in sources :

Example 1 with KahanSummationForDouble

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)));
    }
}
Also used : ArrayList(java.util.ArrayList) KahanSummationForDouble(io.crate.execution.engine.aggregation.impl.util.KahanSummationForDouble) KahanSummationForDouble(io.crate.execution.engine.aggregation.impl.util.KahanSummationForDouble) BigDecimal(java.math.BigDecimal) ArrayType(io.crate.types.ArrayType) DataType(io.crate.types.DataType) Test(org.junit.Test)

Aggregations

KahanSummationForDouble (io.crate.execution.engine.aggregation.impl.util.KahanSummationForDouble)1 ArrayType (io.crate.types.ArrayType)1 DataType (io.crate.types.DataType)1 BigDecimal (java.math.BigDecimal)1 ArrayList (java.util.ArrayList)1 Test (org.junit.Test)1