From 53e23d64996d46241e00f712cd33f7f6c275b64d Mon Sep 17 00:00:00 2001 From: Clint Wylie Date: Wed, 23 Sep 2020 14:18:48 -0700 Subject: [PATCH 1/5] vectorize remaining math expressions --- .../org/apache/druid/math/expr/ExprType.java | 51 +- .../org/apache/druid/math/expr/Function.java | 256 +++- ...ongOutDoubleInFunctionVectorProcessor.java | 53 + ...utDoubleLongInFunctionVectorProcessor.java | 58 + ...ngOutDoublesInFunctionVectorProcessor.java | 58 + ...utLongDoubleInFunctionVectorProcessor.java | 58 + .../expr/vector/VectorMathProcessors.java | 1247 +++++++++++++++-- .../druid/math/expr/OutputTypeTest.java | 42 +- .../druid/math/expr/VectorExprSanityTest.java | 43 +- .../ReductionOperatorConversionHelper.java | 2 +- 10 files changed, 1681 insertions(+), 187 deletions(-) create mode 100644 core/src/main/java/org/apache/druid/math/expr/vector/LongOutDoubleInFunctionVectorProcessor.java create mode 100644 core/src/main/java/org/apache/druid/math/expr/vector/LongOutDoubleLongInFunctionVectorProcessor.java create mode 100644 core/src/main/java/org/apache/druid/math/expr/vector/LongOutDoublesInFunctionVectorProcessor.java create mode 100644 core/src/main/java/org/apache/druid/math/expr/vector/LongOutLongDoubleInFunctionVectorProcessor.java diff --git a/core/src/main/java/org/apache/druid/math/expr/ExprType.java b/core/src/main/java/org/apache/druid/math/expr/ExprType.java index 05262baf04f5..140edde7062b 100644 --- a/core/src/main/java/org/apache/druid/math/expr/ExprType.java +++ b/core/src/main/java/org/apache/druid/math/expr/ExprType.java @@ -171,6 +171,11 @@ public static ExprType asArrayType(@Nullable ExprType elementType) /** * Given 2 'input' types, choose the most appropriate combined type, if possible + * + * arrays must be the same type + * if both types are {@link #STRING}, the output type will be preserved as string + * if both types are {@link #LONG}, the output type will be preserved as long + * */ @Nullable public static ExprType operatorAutoTypeConversion(@Nullable ExprType type, @Nullable ExprType other) @@ -191,14 +196,19 @@ public static ExprType operatorAutoTypeConversion(@Nullable ExprType type, @Null return STRING; } - return numericAutoTypeConversion(type, other); + // otherwise a decimal or integer number + return doubleNumericAutoTypeConversion(type, other); } /** * Given 2 'input' types, choose the most appropriate combined type, if possible + * + * arrays must be the same type + * if either type is {@link #STRING}, the output type will be preserved as string + * if both types are {@link #LONG}, the output type will be preserved as long, otherwise {@link #DOUBLE} */ @Nullable - public static ExprType functionAutoTypeConversion(@Nullable ExprType type, @Nullable ExprType other) + public static ExprType doubleMathFunctionAutoTypeConversion(@Nullable ExprType type, @Nullable ExprType other) { if (type == null || other == null) { // cannot auto conversion unknown types @@ -216,11 +226,44 @@ public static ExprType functionAutoTypeConversion(@Nullable ExprType type, @Null return STRING; } - return numericAutoTypeConversion(type, other); + return doubleNumericAutoTypeConversion(type, other); } + /** + * Given 2 'input' types, choose the most appropriate combined type, if possible + * + * arrays must be the same type + * if either type is {@link #STRING}, the output type will be preserved as string + * any number will be coerced to {@link #LONG} + */ + @Nullable + public static ExprType integerMathFunctionAutoTypeConversion(@Nullable ExprType type, @Nullable ExprType other) + { + if (type == null || other == null) { + // cannot auto conversion unknown types + return null; + } + // arrays cannot be auto converted + if (isArray(type) || isArray(other)) { + if (!type.equals(other)) { + throw new IAE("Cannot implicitly cast %s to %s", type, other); + } + return type; + } + // if either argument is a string, type becomes a string + if (STRING.equals(type) || STRING.equals(other)) { + return STRING; + } + + // any number is long + return LONG; + } + + /** + * If both types are {@link #LONG}, returns {@link #LONG}, else {@link #DOUBLE} + */ @Nullable - public static ExprType numericAutoTypeConversion(ExprType type, ExprType other) + public static ExprType doubleNumericAutoTypeConversion(ExprType type, ExprType other) { // all numbers win over longs if (LONG.equals(type) && LONG.equals(other)) { diff --git a/core/src/main/java/org/apache/druid/math/expr/Function.java b/core/src/main/java/org/apache/druid/math/expr/Function.java index 4fde3398d501..779e9bf92f59 100644 --- a/core/src/main/java/org/apache/druid/math/expr/Function.java +++ b/core/src/main/java/org/apache/druid/math/expr/Function.java @@ -225,6 +225,12 @@ public ExprType getOutputType(Expr.InputBindingTypes inputTypes, List args { return args.get(0).getOutputType(inputTypes); } + + @Override + public boolean canVectorize(Expr.InputBindingTypes inputTypes, List args) + { + return inputTypes.areNumeric(args) && inputTypes.canVectorize(args); + } } /** @@ -273,7 +279,13 @@ protected ExprEval eval(double x, double y) @Override public ExprType getOutputType(Expr.InputBindingTypes inputTypes, List args) { - return ExprType.functionAutoTypeConversion(args.get(0).getOutputType(inputTypes), args.get(1).getOutputType(inputTypes)); + return ExprType.doubleMathFunctionAutoTypeConversion(args.get(0).getOutputType(inputTypes), args.get(1).getOutputType(inputTypes)); + } + + @Override + public boolean canVectorize(Expr.InputBindingTypes inputTypes, List args) + { + return inputTypes.areNumeric(args) && inputTypes.canVectorize(args); } } @@ -432,7 +444,7 @@ public ExprType getOutputType(Expr.InputBindingTypes inputTypes, List args { ExprType outputType = ExprType.LONG; for (Expr expr : args) { - outputType = ExprType.functionAutoTypeConversion(outputType, expr.getOutputType(inputTypes)); + outputType = ExprType.doubleMathFunctionAutoTypeConversion(outputType, expr.getOutputType(inputTypes)); } return outputType; } @@ -453,7 +465,7 @@ public ExprEval apply(List args, Expr.ObjectBinding bindings) ExprType exprType = exprEval.type(); if (isValidType(exprType)) { - outputType = ExprType.functionAutoTypeConversion(outputType, exprType); + outputType = ExprType.doubleMathFunctionAutoTypeConversion(outputType, exprType); } if (exprEval.value() != null) { @@ -631,6 +643,12 @@ protected ExprEval eval(double param) { return ExprEval.of(Math.abs(param)); } + + @Override + public ExprVectorProcessor asVectorProcessor(Expr.VectorInputBindingTypes inputTypes, List args) + { + return VectorMathProcessors.abs(inputTypes, args.get(0)); + } } class Acos extends DoubleUnivariateMathFunction @@ -646,6 +664,12 @@ protected ExprEval eval(double param) { return ExprEval.of(Math.acos(param)); } + + @Override + public ExprVectorProcessor asVectorProcessor(Expr.VectorInputBindingTypes inputTypes, List args) + { + return VectorMathProcessors.acos(inputTypes, args.get(0)); + } } class Asin extends DoubleUnivariateMathFunction @@ -661,6 +685,12 @@ protected ExprEval eval(double param) { return ExprEval.of(Math.asin(param)); } + + @Override + public ExprVectorProcessor asVectorProcessor(Expr.VectorInputBindingTypes inputTypes, List args) + { + return VectorMathProcessors.asin(inputTypes, args.get(0)); + } } class Atan extends DoubleUnivariateMathFunction @@ -677,12 +707,6 @@ protected ExprEval eval(double param) return ExprEval.of(Math.atan(param)); } - @Override - public boolean canVectorize(Expr.InputBindingTypes inputTypes, List args) - { - return inputTypes.areNumeric(args) && inputTypes.canVectorize(args); - } - @Override public ExprVectorProcessor asVectorProcessor(Expr.VectorInputBindingTypes inputTypes, List args) { @@ -703,6 +727,12 @@ protected ExprEval eval(double param) { return ExprEval.of(Math.cbrt(param)); } + + @Override + public ExprVectorProcessor asVectorProcessor(Expr.VectorInputBindingTypes inputTypes, List args) + { + return VectorMathProcessors.cbrt(inputTypes, args.get(0)); + } } class Ceil extends DoubleUnivariateMathFunction @@ -718,6 +748,12 @@ protected ExprEval eval(double param) { return ExprEval.of(Math.ceil(param)); } + + @Override + public ExprVectorProcessor asVectorProcessor(Expr.VectorInputBindingTypes inputTypes, List args) + { + return VectorMathProcessors.ceil(inputTypes, args.get(0)); + } } class Cos extends DoubleUnivariateMathFunction @@ -734,12 +770,6 @@ protected ExprEval eval(double param) return ExprEval.of(Math.cos(param)); } - @Override - public boolean canVectorize(Expr.InputBindingTypes inputTypes, List args) - { - return inputTypes.areNumeric(args) && inputTypes.canVectorize(args); - } - @Override public ExprVectorProcessor asVectorProcessor(Expr.VectorInputBindingTypes inputTypes, List args) { @@ -761,12 +791,6 @@ protected ExprEval eval(double param) return ExprEval.of(Math.cosh(param)); } - @Override - public boolean canVectorize(Expr.InputBindingTypes inputTypes, List args) - { - return inputTypes.areNumeric(args) && inputTypes.canVectorize(args); - } - @Override public ExprVectorProcessor asVectorProcessor(Expr.VectorInputBindingTypes inputTypes, List args) { @@ -788,12 +812,6 @@ protected ExprEval eval(double param) return ExprEval.of(Math.cos(param) / Math.sin(param)); } - @Override - public boolean canVectorize(Expr.InputBindingTypes inputTypes, List args) - { - return inputTypes.areNumeric(args) && inputTypes.canVectorize(args); - } - @Override public ExprVectorProcessor asVectorProcessor(Expr.VectorInputBindingTypes inputTypes, List args) { @@ -821,16 +839,17 @@ protected ExprEval eval(final double x, final double y) return ExprEval.of((long) (x / y)); } + @Nullable @Override - public boolean canVectorize(Expr.InputBindingTypes inputTypes, List args) + public ExprType getOutputType(Expr.InputBindingTypes inputTypes, List args) { - return inputTypes.areNumeric(args) && inputTypes.canVectorize(args); + return ExprType.integerMathFunctionAutoTypeConversion(args.get(0).getOutputType(inputTypes), args.get(1).getOutputType(inputTypes)); } @Override public ExprVectorProcessor asVectorProcessor(Expr.VectorInputBindingTypes inputTypes, List args) { - return VectorMathProcessors.divide(inputTypes, args.get(0), args.get(1)); + return VectorMathProcessors.longDivide(inputTypes, args.get(0), args.get(1)); } } @@ -847,6 +866,12 @@ protected ExprEval eval(double param) { return ExprEval.of(Math.exp(param)); } + + @Override + public ExprVectorProcessor asVectorProcessor(Expr.VectorInputBindingTypes inputTypes, List args) + { + return VectorMathProcessors.exp(inputTypes, args.get(0)); + } } class Expm1 extends DoubleUnivariateMathFunction @@ -862,6 +887,12 @@ protected ExprEval eval(double param) { return ExprEval.of(Math.expm1(param)); } + + @Override + public ExprVectorProcessor asVectorProcessor(Expr.VectorInputBindingTypes inputTypes, List args) + { + return VectorMathProcessors.expm1(inputTypes, args.get(0)); + } } class Floor extends DoubleUnivariateMathFunction @@ -877,6 +908,12 @@ protected ExprEval eval(double param) { return ExprEval.of(Math.floor(param)); } + + @Override + public ExprVectorProcessor asVectorProcessor(Expr.VectorInputBindingTypes inputTypes, List args) + { + return VectorMathProcessors.floor(inputTypes, args.get(0)); + } } class GetExponent extends UnivariateMathFunction @@ -892,6 +929,19 @@ protected ExprEval eval(double param) { return ExprEval.of(Math.getExponent(param)); } + + @Nullable + @Override + public ExprType getOutputType(Expr.InputBindingTypes inputTypes, List args) + { + return ExprType.LONG; + } + + @Override + public ExprVectorProcessor asVectorProcessor(Expr.VectorInputBindingTypes inputTypes, List args) + { + return VectorMathProcessors.getExponent(inputTypes, args.get(0)); + } } class Log extends DoubleUnivariateMathFunction @@ -907,6 +957,12 @@ protected ExprEval eval(double param) { return ExprEval.of(Math.log(param)); } + + @Override + public ExprVectorProcessor asVectorProcessor(Expr.VectorInputBindingTypes inputTypes, List args) + { + return VectorMathProcessors.log(inputTypes, args.get(0)); + } } class Log10 extends DoubleUnivariateMathFunction @@ -922,6 +978,12 @@ protected ExprEval eval(double param) { return ExprEval.of(Math.log10(param)); } + + @Override + public ExprVectorProcessor asVectorProcessor(Expr.VectorInputBindingTypes inputTypes, List args) + { + return VectorMathProcessors.log10(inputTypes, args.get(0)); + } } class Log1p extends DoubleUnivariateMathFunction @@ -937,6 +999,12 @@ protected ExprEval eval(double param) { return ExprEval.of(Math.log1p(param)); } + + @Override + public ExprVectorProcessor asVectorProcessor(Expr.VectorInputBindingTypes inputTypes, List args) + { + return VectorMathProcessors.log1p(inputTypes, args.get(0)); + } } class NextUp extends DoubleUnivariateMathFunction @@ -952,6 +1020,12 @@ protected ExprEval eval(double param) { return ExprEval.of(Math.nextUp(param)); } + + @Override + public ExprVectorProcessor asVectorProcessor(Expr.VectorInputBindingTypes inputTypes, List args) + { + return VectorMathProcessors.nextUp(inputTypes, args.get(0)); + } } class Rint extends DoubleUnivariateMathFunction @@ -967,6 +1041,12 @@ protected ExprEval eval(double param) { return ExprEval.of(Math.rint(param)); } + + @Override + public ExprVectorProcessor asVectorProcessor(Expr.VectorInputBindingTypes inputTypes, List args) + { + return VectorMathProcessors.rint(inputTypes, args.get(0)); + } } class Round implements Function @@ -1070,6 +1150,12 @@ protected ExprEval eval(double param) { return ExprEval.of(Math.signum(param)); } + + @Override + public ExprVectorProcessor asVectorProcessor(Expr.VectorInputBindingTypes inputTypes, List args) + { + return VectorMathProcessors.signum(inputTypes, args.get(0)); + } } class Sin extends DoubleUnivariateMathFunction @@ -1086,12 +1172,6 @@ protected ExprEval eval(double param) return ExprEval.of(Math.sin(param)); } - @Override - public boolean canVectorize(Expr.InputBindingTypes inputTypes, List args) - { - return inputTypes.areNumeric(args) && inputTypes.canVectorize(args); - } - @Override public ExprVectorProcessor asVectorProcessor(Expr.VectorInputBindingTypes inputTypes, List args) { @@ -1113,12 +1193,6 @@ protected ExprEval eval(double param) return ExprEval.of(Math.sinh(param)); } - @Override - public boolean canVectorize(Expr.InputBindingTypes inputTypes, List args) - { - return inputTypes.areNumeric(args) && inputTypes.canVectorize(args); - } - @Override public ExprVectorProcessor asVectorProcessor(Expr.VectorInputBindingTypes inputTypes, List args) { @@ -1139,6 +1213,12 @@ protected ExprEval eval(double param) { return ExprEval.of(Math.sqrt(param)); } + + @Override + public ExprVectorProcessor asVectorProcessor(Expr.VectorInputBindingTypes inputTypes, List args) + { + return VectorMathProcessors.sqrt(inputTypes, args.get(0)); + } } class Tan extends DoubleUnivariateMathFunction @@ -1155,12 +1235,6 @@ protected ExprEval eval(double param) return ExprEval.of(Math.tan(param)); } - @Override - public boolean canVectorize(Expr.InputBindingTypes inputTypes, List args) - { - return inputTypes.areNumeric(args) && inputTypes.canVectorize(args); - } - @Override public ExprVectorProcessor asVectorProcessor(Expr.VectorInputBindingTypes inputTypes, List args) { @@ -1182,12 +1256,6 @@ protected ExprEval eval(double param) return ExprEval.of(Math.tanh(param)); } - @Override - public boolean canVectorize(Expr.InputBindingTypes inputTypes, List args) - { - return inputTypes.areNumeric(args) && inputTypes.canVectorize(args); - } - @Override public ExprVectorProcessor asVectorProcessor(Expr.VectorInputBindingTypes inputTypes, List args) { @@ -1208,6 +1276,12 @@ protected ExprEval eval(double param) { return ExprEval.of(Math.toDegrees(param)); } + + @Override + public ExprVectorProcessor asVectorProcessor(Expr.VectorInputBindingTypes inputTypes, List args) + { + return VectorMathProcessors.toDegrees(inputTypes, args.get(0)); + } } class ToRadians extends DoubleUnivariateMathFunction @@ -1223,6 +1297,12 @@ protected ExprEval eval(double param) { return ExprEval.of(Math.toRadians(param)); } + + @Override + public ExprVectorProcessor asVectorProcessor(Expr.VectorInputBindingTypes inputTypes, List args) + { + return VectorMathProcessors.toRadians(inputTypes, args.get(0)); + } } class Ulp extends DoubleUnivariateMathFunction @@ -1238,6 +1318,12 @@ protected ExprEval eval(double param) { return ExprEval.of(Math.ulp(param)); } + + @Override + public ExprVectorProcessor asVectorProcessor(Expr.VectorInputBindingTypes inputTypes, List args) + { + return VectorMathProcessors.ulp(inputTypes, args.get(0)); + } } class Atan2 extends DoubleBivariateMathFunction @@ -1253,6 +1339,12 @@ protected ExprEval eval(double y, double x) { return ExprEval.of(Math.atan2(y, x)); } + + @Override + public ExprVectorProcessor asVectorProcessor(Expr.VectorInputBindingTypes inputTypes, List args) + { + return VectorMathProcessors.atan2(inputTypes, args.get(0), args.get(1)); + } } class CopySign extends DoubleBivariateMathFunction @@ -1268,6 +1360,12 @@ protected ExprEval eval(double x, double y) { return ExprEval.of(Math.copySign(x, y)); } + + @Override + public ExprVectorProcessor asVectorProcessor(Expr.VectorInputBindingTypes inputTypes, List args) + { + return VectorMathProcessors.copySign(inputTypes, args.get(0), args.get(1)); + } } class Hypot extends DoubleBivariateMathFunction @@ -1283,6 +1381,12 @@ protected ExprEval eval(double x, double y) { return ExprEval.of(Math.hypot(x, y)); } + + @Override + public ExprVectorProcessor asVectorProcessor(Expr.VectorInputBindingTypes inputTypes, List args) + { + return VectorMathProcessors.hypot(inputTypes, args.get(0), args.get(1)); + } } class Remainder extends DoubleBivariateMathFunction @@ -1298,6 +1402,12 @@ protected ExprEval eval(double x, double y) { return ExprEval.of(Math.IEEEremainder(x, y)); } + + @Override + public ExprVectorProcessor asVectorProcessor(Expr.VectorInputBindingTypes inputTypes, List args) + { + return VectorMathProcessors.remainder(inputTypes, args.get(0), args.get(1)); + } } class Max extends BivariateMathFunction @@ -1320,12 +1430,6 @@ protected ExprEval eval(double x, double y) return ExprEval.of(Math.max(x, y)); } - @Override - public boolean canVectorize(Expr.InputBindingTypes inputTypes, List args) - { - return inputTypes.areNumeric(args) && inputTypes.canVectorize(args); - } - @Override public ExprVectorProcessor asVectorProcessor(Expr.VectorInputBindingTypes inputTypes, List args) { @@ -1353,12 +1457,6 @@ protected ExprEval eval(double x, double y) return ExprEval.of(Math.min(x, y)); } - @Override - public boolean canVectorize(Expr.InputBindingTypes inputTypes, List args) - { - return inputTypes.areNumeric(args) && inputTypes.canVectorize(args); - } - @Override public ExprVectorProcessor asVectorProcessor(Expr.VectorInputBindingTypes inputTypes, List args) { @@ -1379,6 +1477,12 @@ protected ExprEval eval(double x, double y) { return ExprEval.of(Math.nextAfter(x, y)); } + + @Override + public ExprVectorProcessor asVectorProcessor(Expr.VectorInputBindingTypes inputTypes, List args) + { + return VectorMathProcessors.nextAfter(inputTypes, args.get(0), args.get(1)); + } } class Pow extends DoubleBivariateMathFunction @@ -1395,12 +1499,6 @@ protected ExprEval eval(double x, double y) return ExprEval.of(Math.pow(x, y)); } - @Override - public boolean canVectorize(Expr.InputBindingTypes inputTypes, List args) - { - return inputTypes.areNumeric(args) && inputTypes.canVectorize(args); - } - @Override public ExprVectorProcessor asVectorProcessor(Expr.VectorInputBindingTypes inputTypes, List args) { @@ -1426,8 +1524,20 @@ public ExprType getOutputType(Expr.InputBindingTypes inputTypes, List args @Override protected ExprEval eval(ExprEval x, ExprEval y) { + if (x.type() == ExprType.STRING || y.type() == ExprType.STRING) { + return ExprEval.of(null); + } + if (NullHandling.sqlCompatible() && x.isNumericNull() || y.isNumericNull()) { + return ExprEval.of(null); + } return ExprEval.of(Math.scalb(x.asDouble(), y.asInt())); } + + @Override + public ExprVectorProcessor asVectorProcessor(Expr.VectorInputBindingTypes inputTypes, List args) + { + return VectorMathProcessors.scalb(inputTypes, args.get(0), args.get(1)); + } } class CastFunc extends BivariateFunction @@ -2503,7 +2613,7 @@ public ExprType getOutputType(Expr.InputBindingTypes inputTypes, List args { ExprType type = ExprType.LONG; for (Expr arg : args) { - type = ExprType.functionAutoTypeConversion(type, arg.getOutputType(inputTypes)); + type = ExprType.doubleMathFunctionAutoTypeConversion(type, arg.getOutputType(inputTypes)); } return ExprType.asArrayType(type); } diff --git a/core/src/main/java/org/apache/druid/math/expr/vector/LongOutDoubleInFunctionVectorProcessor.java b/core/src/main/java/org/apache/druid/math/expr/vector/LongOutDoubleInFunctionVectorProcessor.java new file mode 100644 index 000000000000..318e2dff9cf2 --- /dev/null +++ b/core/src/main/java/org/apache/druid/math/expr/vector/LongOutDoubleInFunctionVectorProcessor.java @@ -0,0 +1,53 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.druid.math.expr.vector; + +import org.apache.druid.math.expr.ExprType; + +/** + * specialized {@link UnivariateFunctionVectorProcessor} for processing (long[]) -> long[] + */ +public abstract class LongOutDoubleInFunctionVectorProcessor extends UnivariateFunctionVectorProcessor +{ + public LongOutDoubleInFunctionVectorProcessor(ExprVectorProcessor processor, int maxVectorSize) + { + super(processor, maxVectorSize, new long[maxVectorSize]); + } + + public abstract long apply(double input); + + @Override + public ExprType getOutputType() + { + return ExprType.LONG; + } + + @Override + final void processIndex(double[] input, int i) + { + outValues[i] = apply(input[i]); + } + + @Override + final ExprEvalVector asEval() + { + return new ExprEvalLongVector(outValues, outNulls); + } +} diff --git a/core/src/main/java/org/apache/druid/math/expr/vector/LongOutDoubleLongInFunctionVectorProcessor.java b/core/src/main/java/org/apache/druid/math/expr/vector/LongOutDoubleLongInFunctionVectorProcessor.java new file mode 100644 index 000000000000..0e38d7c81a47 --- /dev/null +++ b/core/src/main/java/org/apache/druid/math/expr/vector/LongOutDoubleLongInFunctionVectorProcessor.java @@ -0,0 +1,58 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.druid.math.expr.vector; + +import org.apache.druid.math.expr.ExprType; + +/** + * specialized {@link BivariateFunctionVectorProcessor} for processing (double[], long[]) -> long[] + */ +public abstract class LongOutDoubleLongInFunctionVectorProcessor + extends BivariateFunctionVectorProcessor +{ + public LongOutDoubleLongInFunctionVectorProcessor( + ExprVectorProcessor left, + ExprVectorProcessor right, + int maxVectorSize + ) + { + super(left, right, maxVectorSize, new long[maxVectorSize]); + } + + public abstract long apply(double left, long right); + + @Override + public ExprType getOutputType() + { + return ExprType.LONG; + } + + @Override + final void processIndex(double[] leftInput, long[] rightInput, int i) + { + outValues[i] = apply(leftInput[i], rightInput[i]); + } + + @Override + final ExprEvalVector asEval() + { + return new ExprEvalLongVector(outValues, outNulls); + } +} diff --git a/core/src/main/java/org/apache/druid/math/expr/vector/LongOutDoublesInFunctionVectorProcessor.java b/core/src/main/java/org/apache/druid/math/expr/vector/LongOutDoublesInFunctionVectorProcessor.java new file mode 100644 index 000000000000..6cbbe9d6e2c5 --- /dev/null +++ b/core/src/main/java/org/apache/druid/math/expr/vector/LongOutDoublesInFunctionVectorProcessor.java @@ -0,0 +1,58 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.druid.math.expr.vector; + +import org.apache.druid.math.expr.ExprType; + +/** + * specialized {@link BivariateFunctionVectorProcessor} for processing (double[], double[]) -> long[] + */ +public abstract class LongOutDoublesInFunctionVectorProcessor + extends BivariateFunctionVectorProcessor +{ + public LongOutDoublesInFunctionVectorProcessor( + ExprVectorProcessor left, + ExprVectorProcessor right, + int maxVectorSize + ) + { + super(left, right, maxVectorSize, new long[maxVectorSize]); + } + + public abstract long apply(double left, double right); + + @Override + public ExprType getOutputType() + { + return ExprType.LONG; + } + + @Override + final void processIndex(double[] leftInput, double[] rightInput, int i) + { + outValues[i] = apply(leftInput[i], rightInput[i]); + } + + @Override + final ExprEvalVector asEval() + { + return new ExprEvalLongVector(outValues, outNulls); + } +} diff --git a/core/src/main/java/org/apache/druid/math/expr/vector/LongOutLongDoubleInFunctionVectorProcessor.java b/core/src/main/java/org/apache/druid/math/expr/vector/LongOutLongDoubleInFunctionVectorProcessor.java new file mode 100644 index 000000000000..dce8033da2f5 --- /dev/null +++ b/core/src/main/java/org/apache/druid/math/expr/vector/LongOutLongDoubleInFunctionVectorProcessor.java @@ -0,0 +1,58 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.druid.math.expr.vector; + +import org.apache.druid.math.expr.ExprType; + +/** + * specialized {@link BivariateFunctionVectorProcessor} for processing (long[], double[]) -> long[] + */ +public abstract class LongOutLongDoubleInFunctionVectorProcessor + extends BivariateFunctionVectorProcessor +{ + public LongOutLongDoubleInFunctionVectorProcessor( + ExprVectorProcessor left, + ExprVectorProcessor right, + int maxVectorSize + ) + { + super(left, right, maxVectorSize, new long[maxVectorSize]); + } + + public abstract long apply(long left, double right); + + @Override + public ExprType getOutputType() + { + return ExprType.LONG; + } + + @Override + final void processIndex(long[] leftInput, double[] rightInput, int i) + { + outValues[i] = apply(leftInput[i], rightInput[i]); + } + + @Override + final ExprEvalVector asEval() + { + return new ExprEvalLongVector(outValues, outNulls); + } +} diff --git a/core/src/main/java/org/apache/druid/math/expr/vector/VectorMathProcessors.java b/core/src/main/java/org/apache/druid/math/expr/vector/VectorMathProcessors.java index ea6db8f7a634..bd33e8d2f25d 100644 --- a/core/src/main/java/org/apache/druid/math/expr/vector/VectorMathProcessors.java +++ b/core/src/main/java/org/apache/druid/math/expr/vector/VectorMathProcessors.java @@ -81,6 +81,32 @@ public static ExprVectorProcessor makeDoubleMathProcessor( return (ExprVectorProcessor) processor; } + /** + * Make a 1 argument math processor with the following type rules + * long -> long + * double -> long + */ + public static ExprVectorProcessor makeLongMathProcessor( + Expr.VectorInputBindingTypes inputTypes, + Expr arg, + Supplier longOutLongInSupplier, + Supplier longOutDoubleInSupplier + ) + { + final ExprType inputType = arg.getOutputType(inputTypes); + + ExprVectorProcessor processor = null; + if (ExprType.LONG.equals(inputType)) { + processor = longOutLongInSupplier.get(); + } else if (ExprType.DOUBLE.equals(inputType)) { + processor = longOutDoubleInSupplier.get(); + } + if (processor == null) { + throw Exprs.cannotVectorize(); + } + return (ExprVectorProcessor) processor; + } + /** * Make a 2 argument, math processor with the following type rules * long, long -> long @@ -120,6 +146,84 @@ public static ExprVectorProcessor makeMathProcessor( return (ExprVectorProcessor) processor; } + /** + * Make a 2 argument, math processor with the following type rules + * long, long -> double + * long, double -> double + * double, long -> double + * double, double -> double + */ + public static ExprVectorProcessor makeDoubleMathProcessor( + Expr.VectorInputBindingTypes inputTypes, + Expr left, + Expr right, + Supplier doubleOutLongsInProcessor, + Supplier doubleOutLongDoubleInProcessor, + Supplier doubleOutDoubleLongInProcessor, + Supplier doubleOutDoublesInProcessor + ) + { + final ExprType leftType = left.getOutputType(inputTypes); + final ExprType rightType = right.getOutputType(inputTypes); + ExprVectorProcessor processor = null; + if (ExprType.LONG.equals(leftType)) { + if (ExprType.LONG.equals(rightType)) { + processor = doubleOutLongsInProcessor.get(); + } else if (ExprType.DOUBLE.equals(rightType)) { + processor = doubleOutLongDoubleInProcessor.get(); + } + } else if (ExprType.DOUBLE.equals(leftType)) { + if (ExprType.LONG.equals(rightType)) { + processor = doubleOutDoubleLongInProcessor.get(); + } else if (ExprType.DOUBLE.equals(rightType)) { + processor = doubleOutDoublesInProcessor.get(); + } + } + if (processor == null) { + throw Exprs.cannotVectorize(); + } + return (ExprVectorProcessor) processor; + } + + /** + * Make a 2 argument, math processor with the following type rules + * long, long -> long + * long, double -> long + * double, long -> long + * double, double -> long + */ + public static ExprVectorProcessor makeLongMathProcessor( + Expr.VectorInputBindingTypes inputTypes, + Expr left, + Expr right, + Supplier longOutLongsInProcessor, + Supplier longOutLongDoubleInProcessor, + Supplier longOutDoubleLongInProcessor, + Supplier longOutDoublesInProcessor + ) + { + final ExprType leftType = left.getOutputType(inputTypes); + final ExprType rightType = right.getOutputType(inputTypes); + ExprVectorProcessor processor = null; + if (ExprType.LONG.equals(leftType)) { + if (ExprType.LONG.equals(rightType)) { + processor = longOutLongsInProcessor.get(); + } else if (ExprType.DOUBLE.equals(rightType)) { + processor = longOutLongDoubleInProcessor.get(); + } + } else if (ExprType.DOUBLE.equals(leftType)) { + if (ExprType.LONG.equals(rightType)) { + processor = longOutDoubleLongInProcessor.get(); + } else if (ExprType.DOUBLE.equals(rightType)) { + processor = longOutDoublesInProcessor.get(); + } + } + if (processor == null) { + throw Exprs.cannotVectorize(); + } + return (ExprVectorProcessor) processor; + } + public static ExprVectorProcessor plus(Expr.VectorInputBindingTypes inputTypes, Expr left, Expr right) { return makeMathProcessor( @@ -348,6 +452,63 @@ public double apply(double left, double right) ); } + public static ExprVectorProcessor longDivide(Expr.VectorInputBindingTypes inputTypes, Expr left, Expr right) + { + return makeLongMathProcessor( + inputTypes, + left, + right, + () -> new LongOutLongsInFunctionVectorProcessor( + left.buildVectorized(inputTypes), + right.buildVectorized(inputTypes), + inputTypes.getMaxVectorSize() + ) + { + @Override + public long apply(long left, long right) + { + return left / right; + } + }, + () -> new LongOutLongDoubleInFunctionVectorProcessor( + left.buildVectorized(inputTypes), + right.buildVectorized(inputTypes), + inputTypes.getMaxVectorSize() + ) + { + @Override + public long apply(long left, double right) + { + return (long) (left / right); + } + }, + () -> new LongOutDoubleLongInFunctionVectorProcessor( + left.buildVectorized(inputTypes), + right.buildVectorized(inputTypes), + inputTypes.getMaxVectorSize() + ) + { + @Override + public long apply(double left, long right) + { + return (long) (left / right); + } + }, + () -> new LongOutDoublesInFunctionVectorProcessor( + left.buildVectorized(inputTypes), + right.buildVectorized(inputTypes), + inputTypes.getMaxVectorSize() + ) + { + @Override + public long apply(double left, double right) + { + return (long) (left / right); + } + } + ); + } + public static ExprVectorProcessor modulo(Expr.VectorInputBindingTypes inputTypes, Expr left, Expr right) { return makeMathProcessor( @@ -632,170 +793,812 @@ public double apply(double left, double right) ); } - public static ExprVectorProcessor atan(Expr.VectorInputBindingTypes inputTypes, Expr arg) + public static ExprVectorProcessor atan2(Expr.VectorInputBindingTypes inputTypes, Expr left, Expr right) { return makeDoubleMathProcessor( inputTypes, - arg, - () -> new DoubleOutLongInFunctionVectorProcessor( - arg.buildVectorized(inputTypes), + left, + right, + () -> new DoubleOutLongsInFunctionVectorProcessor( + left.buildVectorized(inputTypes), + right.buildVectorized(inputTypes), inputTypes.getMaxVectorSize() ) { @Override - public double apply(long input) + public double apply(long left, long right) { - return Math.atan(input); + return Math.atan2(left, right); } }, - () -> new DoubleOutDoubleInFunctionVectorProcessor( - arg.buildVectorized(inputTypes), + () -> new DoubleOutLongDoubleInFunctionVectorProcessor( + left.buildVectorized(inputTypes), + right.buildVectorized(inputTypes), inputTypes.getMaxVectorSize() ) { @Override - public double apply(double input) + public double apply(long left, double right) { - return Math.atan(input); + return Math.atan2(left, right); } - } - ); - } - - public static ExprVectorProcessor cos(Expr.VectorInputBindingTypes inputTypes, Expr arg) - { - return makeDoubleMathProcessor( - inputTypes, - arg, - () -> new DoubleOutLongInFunctionVectorProcessor( - arg.buildVectorized(inputTypes), + }, + () -> new DoubleOutDoubleLongInFunctionVectorProcessor( + left.buildVectorized(inputTypes), + right.buildVectorized(inputTypes), inputTypes.getMaxVectorSize() ) { @Override - public double apply(long input) + public double apply(double left, long right) { - return Math.cos(input); + return Math.atan2(left, right); } }, - () -> new DoubleOutDoubleInFunctionVectorProcessor( - arg.buildVectorized(inputTypes), + () -> new DoubleOutDoublesInFunctionVectorProcessor( + left.buildVectorized(inputTypes), + right.buildVectorized(inputTypes), inputTypes.getMaxVectorSize() ) { @Override - public double apply(double input) + public double apply(double left, double right) { - return Math.cos(input); + return Math.atan2(left, right); } } ); } - public static ExprVectorProcessor cosh(Expr.VectorInputBindingTypes inputTypes, Expr arg) + public static ExprVectorProcessor copySign(Expr.VectorInputBindingTypes inputTypes, Expr left, Expr right) { return makeDoubleMathProcessor( inputTypes, - arg, - () -> new DoubleOutLongInFunctionVectorProcessor( - arg.buildVectorized(inputTypes), + left, + right, + () -> new DoubleOutLongsInFunctionVectorProcessor( + left.buildVectorized(inputTypes), + right.buildVectorized(inputTypes), inputTypes.getMaxVectorSize() ) { @Override - public double apply(long input) + public double apply(long left, long right) { - return Math.cosh(input); + return Math.copySign((double) left, (double) right); } }, - () -> new DoubleOutDoubleInFunctionVectorProcessor( - arg.buildVectorized(inputTypes), + () -> new DoubleOutLongDoubleInFunctionVectorProcessor( + left.buildVectorized(inputTypes), + right.buildVectorized(inputTypes), inputTypes.getMaxVectorSize() ) { @Override - public double apply(double input) + public double apply(long left, double right) { - return Math.cosh(input); + return Math.copySign((double) left, right); } - } - ); - } - - public static ExprVectorProcessor cot(Expr.VectorInputBindingTypes inputTypes, Expr arg) - { - return makeDoubleMathProcessor( - inputTypes, - arg, - () -> new DoubleOutLongInFunctionVectorProcessor( - arg.buildVectorized(inputTypes), + }, + () -> new DoubleOutDoubleLongInFunctionVectorProcessor( + left.buildVectorized(inputTypes), + right.buildVectorized(inputTypes), inputTypes.getMaxVectorSize() ) { @Override - public double apply(long input) + public double apply(double left, long right) { - return Math.cos(input) / Math.sin(input); + return Math.copySign(left, (double) right); } }, - () -> new DoubleOutDoubleInFunctionVectorProcessor( - arg.buildVectorized(inputTypes), + () -> new DoubleOutDoublesInFunctionVectorProcessor( + left.buildVectorized(inputTypes), + right.buildVectorized(inputTypes), inputTypes.getMaxVectorSize() ) { @Override - public double apply(double input) + public double apply(double left, double right) { - return Math.cos(input) / Math.sin(input); + return Math.copySign(left, right); } } ); } - public static ExprVectorProcessor sin(Expr.VectorInputBindingTypes inputTypes, Expr arg) + public static ExprVectorProcessor hypot(Expr.VectorInputBindingTypes inputTypes, Expr left, Expr right) { return makeDoubleMathProcessor( inputTypes, - arg, - () -> new DoubleOutLongInFunctionVectorProcessor( - arg.buildVectorized(inputTypes), + left, + right, + () -> new DoubleOutLongsInFunctionVectorProcessor( + left.buildVectorized(inputTypes), + right.buildVectorized(inputTypes), inputTypes.getMaxVectorSize() ) { @Override - public double apply(long input) + public double apply(long left, long right) { - return Math.sin(input); + return Math.hypot(left, right); } }, - () -> new DoubleOutDoubleInFunctionVectorProcessor( - arg.buildVectorized(inputTypes), + () -> new DoubleOutLongDoubleInFunctionVectorProcessor( + left.buildVectorized(inputTypes), + right.buildVectorized(inputTypes), inputTypes.getMaxVectorSize() ) { @Override - public double apply(double input) + public double apply(long left, double right) { - return Math.sin(input); + return Math.hypot(left, right); } - } - ); - } - - public static ExprVectorProcessor sinh(Expr.VectorInputBindingTypes inputTypes, Expr arg) - { - return makeDoubleMathProcessor( - inputTypes, - arg, - () -> new DoubleOutLongInFunctionVectorProcessor( - arg.buildVectorized(inputTypes), - inputTypes.getMaxVectorSize() - ) - { + }, + () -> new DoubleOutDoubleLongInFunctionVectorProcessor( + left.buildVectorized(inputTypes), + right.buildVectorized(inputTypes), + inputTypes.getMaxVectorSize() + ) + { + @Override + public double apply(double left, long right) + { + return Math.hypot(left, right); + } + }, + () -> new DoubleOutDoublesInFunctionVectorProcessor( + left.buildVectorized(inputTypes), + right.buildVectorized(inputTypes), + inputTypes.getMaxVectorSize() + ) + { + @Override + public double apply(double left, double right) + { + return Math.hypot(left, right); + } + } + ); + } + + public static ExprVectorProcessor remainder(Expr.VectorInputBindingTypes inputTypes, Expr left, Expr right) + { + return makeDoubleMathProcessor( + inputTypes, + left, + right, + () -> new DoubleOutLongsInFunctionVectorProcessor( + left.buildVectorized(inputTypes), + right.buildVectorized(inputTypes), + inputTypes.getMaxVectorSize() + ) + { + @Override + public double apply(long left, long right) + { + return Math.IEEEremainder(left, right); + } + }, + () -> new DoubleOutLongDoubleInFunctionVectorProcessor( + left.buildVectorized(inputTypes), + right.buildVectorized(inputTypes), + inputTypes.getMaxVectorSize() + ) + { + @Override + public double apply(long left, double right) + { + return Math.IEEEremainder(left, right); + } + }, + () -> new DoubleOutDoubleLongInFunctionVectorProcessor( + left.buildVectorized(inputTypes), + right.buildVectorized(inputTypes), + inputTypes.getMaxVectorSize() + ) + { + @Override + public double apply(double left, long right) + { + return Math.IEEEremainder(left, right); + } + }, + () -> new DoubleOutDoublesInFunctionVectorProcessor( + left.buildVectorized(inputTypes), + right.buildVectorized(inputTypes), + inputTypes.getMaxVectorSize() + ) + { + @Override + public double apply(double left, double right) + { + return Math.IEEEremainder(left, right); + } + } + ); + } + + public static ExprVectorProcessor nextAfter(Expr.VectorInputBindingTypes inputTypes, Expr left, Expr right) + { + return makeDoubleMathProcessor( + inputTypes, + left, + right, + () -> new DoubleOutLongsInFunctionVectorProcessor( + left.buildVectorized(inputTypes), + right.buildVectorized(inputTypes), + inputTypes.getMaxVectorSize() + ) + { + @Override + public double apply(long left, long right) + { + return Math.nextAfter((double) left, (double) right); + } + }, + () -> new DoubleOutLongDoubleInFunctionVectorProcessor( + left.buildVectorized(inputTypes), + right.buildVectorized(inputTypes), + inputTypes.getMaxVectorSize() + ) + { + @Override + public double apply(long left, double right) + { + return Math.nextAfter((double) left, right); + } + }, + () -> new DoubleOutDoubleLongInFunctionVectorProcessor( + left.buildVectorized(inputTypes), + right.buildVectorized(inputTypes), + inputTypes.getMaxVectorSize() + ) + { + @Override + public double apply(double left, long right) + { + return Math.nextAfter(left, (double) right); + } + }, + () -> new DoubleOutDoublesInFunctionVectorProcessor( + left.buildVectorized(inputTypes), + right.buildVectorized(inputTypes), + inputTypes.getMaxVectorSize() + ) + { + @Override + public double apply(double left, double right) + { + return Math.nextAfter(left, right); + } + } + ); + } + + public static ExprVectorProcessor scalb(Expr.VectorInputBindingTypes inputTypes, Expr left, Expr right) + { + return makeDoubleMathProcessor( + inputTypes, + left, + right, + () -> new DoubleOutLongsInFunctionVectorProcessor( + left.buildVectorized(inputTypes), + right.buildVectorized(inputTypes), + inputTypes.getMaxVectorSize() + ) + { + @Override + public double apply(long left, long right) + { + return Math.scalb((double) left, (int) right); + } + }, + () -> new DoubleOutLongDoubleInFunctionVectorProcessor( + left.buildVectorized(inputTypes), + right.buildVectorized(inputTypes), + inputTypes.getMaxVectorSize() + ) + { + @Override + public double apply(long left, double right) + { + return Math.scalb((double) left, (int) right); + } + }, + () -> new DoubleOutDoubleLongInFunctionVectorProcessor( + left.buildVectorized(inputTypes), + right.buildVectorized(inputTypes), + inputTypes.getMaxVectorSize() + ) + { + @Override + public double apply(double left, long right) + { + return Math.scalb(left, (int) right); + } + }, + () -> new DoubleOutDoublesInFunctionVectorProcessor( + left.buildVectorized(inputTypes), + right.buildVectorized(inputTypes), + inputTypes.getMaxVectorSize() + ) + { + @Override + public double apply(double left, double right) + { + return Math.scalb(left, (int) right); + } + } + ); + } + + public static ExprVectorProcessor acos(Expr.VectorInputBindingTypes inputTypes, Expr arg) + { + return makeDoubleMathProcessor( + inputTypes, + arg, + () -> new DoubleOutLongInFunctionVectorProcessor( + arg.buildVectorized(inputTypes), + inputTypes.getMaxVectorSize() + ) + { + @Override + public double apply(long input) + { + return Math.acos(input); + } + }, + () -> new DoubleOutDoubleInFunctionVectorProcessor( + arg.buildVectorized(inputTypes), + inputTypes.getMaxVectorSize() + ) + { + @Override + public double apply(double input) + { + return Math.acos(input); + } + } + ); + } + + public static ExprVectorProcessor asin(Expr.VectorInputBindingTypes inputTypes, Expr arg) + { + return makeDoubleMathProcessor( + inputTypes, + arg, + () -> new DoubleOutLongInFunctionVectorProcessor( + arg.buildVectorized(inputTypes), + inputTypes.getMaxVectorSize() + ) + { + @Override + public double apply(long input) + { + return Math.asin(input); + } + }, + () -> new DoubleOutDoubleInFunctionVectorProcessor( + arg.buildVectorized(inputTypes), + inputTypes.getMaxVectorSize() + ) + { + @Override + public double apply(double input) + { + return Math.asin(input); + } + } + ); + } + + public static ExprVectorProcessor atan(Expr.VectorInputBindingTypes inputTypes, Expr arg) + { + return makeDoubleMathProcessor( + inputTypes, + arg, + () -> new DoubleOutLongInFunctionVectorProcessor( + arg.buildVectorized(inputTypes), + inputTypes.getMaxVectorSize() + ) + { + @Override + public double apply(long input) + { + return Math.atan(input); + } + }, + () -> new DoubleOutDoubleInFunctionVectorProcessor( + arg.buildVectorized(inputTypes), + inputTypes.getMaxVectorSize() + ) + { + @Override + public double apply(double input) + { + return Math.atan(input); + } + } + ); + } + + public static ExprVectorProcessor cos(Expr.VectorInputBindingTypes inputTypes, Expr arg) + { + return makeDoubleMathProcessor( + inputTypes, + arg, + () -> new DoubleOutLongInFunctionVectorProcessor( + arg.buildVectorized(inputTypes), + inputTypes.getMaxVectorSize() + ) + { + @Override + public double apply(long input) + { + return Math.cos(input); + } + }, + () -> new DoubleOutDoubleInFunctionVectorProcessor( + arg.buildVectorized(inputTypes), + inputTypes.getMaxVectorSize() + ) + { + @Override + public double apply(double input) + { + return Math.cos(input); + } + } + ); + } + + public static ExprVectorProcessor cosh(Expr.VectorInputBindingTypes inputTypes, Expr arg) + { + return makeDoubleMathProcessor( + inputTypes, + arg, + () -> new DoubleOutLongInFunctionVectorProcessor( + arg.buildVectorized(inputTypes), + inputTypes.getMaxVectorSize() + ) + { + @Override + public double apply(long input) + { + return Math.cosh(input); + } + }, + () -> new DoubleOutDoubleInFunctionVectorProcessor( + arg.buildVectorized(inputTypes), + inputTypes.getMaxVectorSize() + ) + { + @Override + public double apply(double input) + { + return Math.cosh(input); + } + } + ); + } + + public static ExprVectorProcessor cot(Expr.VectorInputBindingTypes inputTypes, Expr arg) + { + return makeDoubleMathProcessor( + inputTypes, + arg, + () -> new DoubleOutLongInFunctionVectorProcessor( + arg.buildVectorized(inputTypes), + inputTypes.getMaxVectorSize() + ) + { + @Override + public double apply(long input) + { + return Math.cos(input) / Math.sin(input); + } + }, + () -> new DoubleOutDoubleInFunctionVectorProcessor( + arg.buildVectorized(inputTypes), + inputTypes.getMaxVectorSize() + ) + { + @Override + public double apply(double input) + { + return Math.cos(input) / Math.sin(input); + } + } + ); + } + + public static ExprVectorProcessor sin(Expr.VectorInputBindingTypes inputTypes, Expr arg) + { + return makeDoubleMathProcessor( + inputTypes, + arg, + () -> new DoubleOutLongInFunctionVectorProcessor( + arg.buildVectorized(inputTypes), + inputTypes.getMaxVectorSize() + ) + { + @Override + public double apply(long input) + { + return Math.sin(input); + } + }, + () -> new DoubleOutDoubleInFunctionVectorProcessor( + arg.buildVectorized(inputTypes), + inputTypes.getMaxVectorSize() + ) + { + @Override + public double apply(double input) + { + return Math.sin(input); + } + } + ); + } + + public static ExprVectorProcessor sinh(Expr.VectorInputBindingTypes inputTypes, Expr arg) + { + return makeDoubleMathProcessor( + inputTypes, + arg, + () -> new DoubleOutLongInFunctionVectorProcessor( + arg.buildVectorized(inputTypes), + inputTypes.getMaxVectorSize() + ) + { + @Override + public double apply(long input) + { + return Math.sinh(input); + } + }, + () -> new DoubleOutDoubleInFunctionVectorProcessor( + arg.buildVectorized(inputTypes), + inputTypes.getMaxVectorSize() + ) + { + @Override + public double apply(double input) + { + return Math.sinh(input); + } + } + ); + } + + public static ExprVectorProcessor tan(Expr.VectorInputBindingTypes inputTypes, Expr arg) + { + return makeDoubleMathProcessor( + inputTypes, + arg, + () -> new DoubleOutLongInFunctionVectorProcessor( + arg.buildVectorized(inputTypes), + inputTypes.getMaxVectorSize() + ) + { + @Override + public double apply(long input) + { + return Math.tan(input); + } + }, + () -> new DoubleOutDoubleInFunctionVectorProcessor( + arg.buildVectorized(inputTypes), + inputTypes.getMaxVectorSize() + ) + { + @Override + public double apply(double input) + { + return Math.tan(input); + } + } + ); + } + + public static ExprVectorProcessor tanh(Expr.VectorInputBindingTypes inputTypes, Expr arg) + { + return makeDoubleMathProcessor( + inputTypes, + arg, + () -> new DoubleOutLongInFunctionVectorProcessor( + arg.buildVectorized(inputTypes), + inputTypes.getMaxVectorSize() + ) + { + @Override + public double apply(long input) + { + return Math.tanh(input); + } + }, + () -> new DoubleOutDoubleInFunctionVectorProcessor( + arg.buildVectorized(inputTypes), + inputTypes.getMaxVectorSize() + ) + { + @Override + public double apply(double input) + { + return Math.tanh(input); + } + } + ); + } + + public static ExprVectorProcessor abs(Expr.VectorInputBindingTypes inputTypes, Expr arg) + { + return makeMathProcessor( + inputTypes, + arg, + () -> new LongOutLongInFunctionVectorProcessor( + arg.buildVectorized(inputTypes), + inputTypes.getMaxVectorSize() + ) + { + @Override + public long apply(long input) + { + return Math.abs(input); + } + }, + () -> new DoubleOutDoubleInFunctionVectorProcessor( + arg.buildVectorized(inputTypes), + inputTypes.getMaxVectorSize() + ) + { + @Override + public double apply(double input) + { + return Math.abs(input); + } + } + ); + } + + public static ExprVectorProcessor cbrt(Expr.VectorInputBindingTypes inputTypes, Expr arg) + { + return makeDoubleMathProcessor( + inputTypes, + arg, + () -> new DoubleOutLongInFunctionVectorProcessor( + arg.buildVectorized(inputTypes), + inputTypes.getMaxVectorSize() + ) + { + @Override + public double apply(long input) + { + return Math.cbrt(input); + } + }, + () -> new DoubleOutDoubleInFunctionVectorProcessor( + arg.buildVectorized(inputTypes), + inputTypes.getMaxVectorSize() + ) + { + @Override + public double apply(double input) + { + return Math.cbrt(input); + } + } + ); + } + + public static ExprVectorProcessor ceil(Expr.VectorInputBindingTypes inputTypes, Expr arg) + { + return makeDoubleMathProcessor( + inputTypes, + arg, + () -> new DoubleOutLongInFunctionVectorProcessor( + arg.buildVectorized(inputTypes), + inputTypes.getMaxVectorSize() + ) + { + @Override + public double apply(long input) + { + return Math.ceil(input); + } + }, + () -> new DoubleOutDoubleInFunctionVectorProcessor( + arg.buildVectorized(inputTypes), + inputTypes.getMaxVectorSize() + ) + { + @Override + public double apply(double input) + { + return Math.ceil(input); + } + } + ); + } + + public static ExprVectorProcessor floor(Expr.VectorInputBindingTypes inputTypes, Expr arg) + { + return makeDoubleMathProcessor( + inputTypes, + arg, + () -> new DoubleOutLongInFunctionVectorProcessor( + arg.buildVectorized(inputTypes), + inputTypes.getMaxVectorSize() + ) + { + @Override + public double apply(long input) + { + return Math.floor(input); + } + }, + () -> new DoubleOutDoubleInFunctionVectorProcessor( + arg.buildVectorized(inputTypes), + inputTypes.getMaxVectorSize() + ) + { + @Override + public double apply(double input) + { + return Math.floor(input); + } + } + ); + } + + public static ExprVectorProcessor exp(Expr.VectorInputBindingTypes inputTypes, Expr arg) + { + return makeDoubleMathProcessor( + inputTypes, + arg, + () -> new DoubleOutLongInFunctionVectorProcessor( + arg.buildVectorized(inputTypes), + inputTypes.getMaxVectorSize() + ) + { + @Override + public double apply(long input) + { + return Math.exp(input); + } + }, + () -> new DoubleOutDoubleInFunctionVectorProcessor( + arg.buildVectorized(inputTypes), + inputTypes.getMaxVectorSize() + ) + { + @Override + public double apply(double input) + { + return Math.exp(input); + } + } + ); + } + + public static ExprVectorProcessor expm1(Expr.VectorInputBindingTypes inputTypes, Expr arg) + { + return makeDoubleMathProcessor( + inputTypes, + arg, + () -> new DoubleOutLongInFunctionVectorProcessor( + arg.buildVectorized(inputTypes), + inputTypes.getMaxVectorSize() + ) + { @Override public double apply(long input) { - return Math.sinh(input); + return Math.expm1(input); } }, () -> new DoubleOutDoubleInFunctionVectorProcessor( @@ -806,13 +1609,43 @@ public double apply(long input) @Override public double apply(double input) { - return Math.sinh(input); + return Math.expm1(input); } } ); } - public static ExprVectorProcessor tan(Expr.VectorInputBindingTypes inputTypes, Expr arg) + public static ExprVectorProcessor getExponent(Expr.VectorInputBindingTypes inputTypes, Expr arg) + { + return makeLongMathProcessor( + inputTypes, + arg, + () -> new LongOutLongInFunctionVectorProcessor( + arg.buildVectorized(inputTypes), + inputTypes.getMaxVectorSize() + ) + { + @Override + public long apply(long input) + { + return Math.getExponent((double) input); + } + }, + () -> new LongOutDoubleInFunctionVectorProcessor( + arg.buildVectorized(inputTypes), + inputTypes.getMaxVectorSize() + ) + { + @Override + public long apply(double input) + { + return Math.getExponent(input); + } + } + ); + } + + public static ExprVectorProcessor log(Expr.VectorInputBindingTypes inputTypes, Expr arg) { return makeDoubleMathProcessor( inputTypes, @@ -825,7 +1658,7 @@ public static ExprVectorProcessor tan(Expr.VectorInputBindingTypes inputT @Override public double apply(long input) { - return Math.tan(input); + return Math.log(input); } }, () -> new DoubleOutDoubleInFunctionVectorProcessor( @@ -836,13 +1669,13 @@ public double apply(long input) @Override public double apply(double input) { - return Math.tan(input); + return Math.log(input); } } ); } - public static ExprVectorProcessor tanh(Expr.VectorInputBindingTypes inputTypes, Expr arg) + public static ExprVectorProcessor log10(Expr.VectorInputBindingTypes inputTypes, Expr arg) { return makeDoubleMathProcessor( inputTypes, @@ -855,7 +1688,7 @@ public static ExprVectorProcessor tanh(Expr.VectorInputBindingTypes input @Override public double apply(long input) { - return Math.tanh(input); + return Math.log10(input); } }, () -> new DoubleOutDoubleInFunctionVectorProcessor( @@ -866,12 +1699,254 @@ public double apply(long input) @Override public double apply(double input) { - return Math.tanh(input); + return Math.log10(input); + } + } + ); + } + + public static ExprVectorProcessor log1p(Expr.VectorInputBindingTypes inputTypes, Expr arg) + { + return makeDoubleMathProcessor( + inputTypes, + arg, + () -> new DoubleOutLongInFunctionVectorProcessor( + arg.buildVectorized(inputTypes), + inputTypes.getMaxVectorSize() + ) + { + @Override + public double apply(long input) + { + return Math.log1p(input); + } + }, + () -> new DoubleOutDoubleInFunctionVectorProcessor( + arg.buildVectorized(inputTypes), + inputTypes.getMaxVectorSize() + ) + { + @Override + public double apply(double input) + { + return Math.log1p(input); + } + } + ); + } + + public static ExprVectorProcessor nextUp(Expr.VectorInputBindingTypes inputTypes, Expr arg) + { + return makeDoubleMathProcessor( + inputTypes, + arg, + () -> new DoubleOutLongInFunctionVectorProcessor( + arg.buildVectorized(inputTypes), + inputTypes.getMaxVectorSize() + ) + { + @Override + public double apply(long input) + { + return Math.nextUp((double) input); + } + }, + () -> new DoubleOutDoubleInFunctionVectorProcessor( + arg.buildVectorized(inputTypes), + inputTypes.getMaxVectorSize() + ) + { + @Override + public double apply(double input) + { + return Math.nextUp(input); + } + } + ); + } + + public static ExprVectorProcessor rint(Expr.VectorInputBindingTypes inputTypes, Expr arg) + { + return makeDoubleMathProcessor( + inputTypes, + arg, + () -> new DoubleOutLongInFunctionVectorProcessor( + arg.buildVectorized(inputTypes), + inputTypes.getMaxVectorSize() + ) + { + @Override + public double apply(long input) + { + return Math.rint(input); + } + }, + () -> new DoubleOutDoubleInFunctionVectorProcessor( + arg.buildVectorized(inputTypes), + inputTypes.getMaxVectorSize() + ) + { + @Override + public double apply(double input) + { + return Math.rint(input); + } + } + ); + } + + public static ExprVectorProcessor signum(Expr.VectorInputBindingTypes inputTypes, Expr arg) + { + return makeDoubleMathProcessor( + inputTypes, + arg, + () -> new DoubleOutLongInFunctionVectorProcessor( + arg.buildVectorized(inputTypes), + inputTypes.getMaxVectorSize() + ) + { + @Override + public double apply(long input) + { + return Math.signum(input); + } + }, + () -> new DoubleOutDoubleInFunctionVectorProcessor( + arg.buildVectorized(inputTypes), + inputTypes.getMaxVectorSize() + ) + { + @Override + public double apply(double input) + { + return Math.signum(input); + } + } + ); + } + + public static ExprVectorProcessor sqrt(Expr.VectorInputBindingTypes inputTypes, Expr arg) + { + return makeDoubleMathProcessor( + inputTypes, + arg, + () -> new DoubleOutLongInFunctionVectorProcessor( + arg.buildVectorized(inputTypes), + inputTypes.getMaxVectorSize() + ) + { + @Override + public double apply(long input) + { + return Math.sqrt(input); + } + }, + () -> new DoubleOutDoubleInFunctionVectorProcessor( + arg.buildVectorized(inputTypes), + inputTypes.getMaxVectorSize() + ) + { + @Override + public double apply(double input) + { + return Math.sqrt(input); + } + } + ); + } + + public static ExprVectorProcessor toDegrees(Expr.VectorInputBindingTypes inputTypes, Expr arg) + { + return makeDoubleMathProcessor( + inputTypes, + arg, + () -> new DoubleOutLongInFunctionVectorProcessor( + arg.buildVectorized(inputTypes), + inputTypes.getMaxVectorSize() + ) + { + @Override + public double apply(long input) + { + return Math.toDegrees(input); + } + }, + () -> new DoubleOutDoubleInFunctionVectorProcessor( + arg.buildVectorized(inputTypes), + inputTypes.getMaxVectorSize() + ) + { + @Override + public double apply(double input) + { + return Math.toDegrees(input); + } + } + ); + } + + public static ExprVectorProcessor toRadians(Expr.VectorInputBindingTypes inputTypes, Expr arg) + { + return makeDoubleMathProcessor( + inputTypes, + arg, + () -> new DoubleOutLongInFunctionVectorProcessor( + arg.buildVectorized(inputTypes), + inputTypes.getMaxVectorSize() + ) + { + @Override + public double apply(long input) + { + return Math.toRadians(input); + } + }, + () -> new DoubleOutDoubleInFunctionVectorProcessor( + arg.buildVectorized(inputTypes), + inputTypes.getMaxVectorSize() + ) + { + @Override + public double apply(double input) + { + return Math.toRadians(input); + } + } + ); + } + + public static ExprVectorProcessor ulp(Expr.VectorInputBindingTypes inputTypes, Expr arg) + { + return makeDoubleMathProcessor( + inputTypes, + arg, + () -> new DoubleOutLongInFunctionVectorProcessor( + arg.buildVectorized(inputTypes), + inputTypes.getMaxVectorSize() + ) + { + @Override + public double apply(long input) + { + return Math.ulp((double) input); + } + }, + () -> new DoubleOutDoubleInFunctionVectorProcessor( + arg.buildVectorized(inputTypes), + inputTypes.getMaxVectorSize() + ) + { + @Override + public double apply(double input) + { + return Math.ulp(input); } } ); } + + private VectorMathProcessors() { // No instantiation diff --git a/core/src/test/java/org/apache/druid/math/expr/OutputTypeTest.java b/core/src/test/java/org/apache/druid/math/expr/OutputTypeTest.java index 7b977d3b9ac2..5369352597d8 100644 --- a/core/src/test/java/org/apache/druid/math/expr/OutputTypeTest.java +++ b/core/src/test/java/org/apache/druid/math/expr/OutputTypeTest.java @@ -399,33 +399,33 @@ public void testOperatorAutoConversion() public void testFunctionAutoConversion() { // nulls output nulls - Assert.assertNull(ExprType.functionAutoTypeConversion(ExprType.LONG, null)); - Assert.assertNull(ExprType.functionAutoTypeConversion(null, ExprType.LONG)); - Assert.assertNull(ExprType.functionAutoTypeConversion(ExprType.DOUBLE, null)); - Assert.assertNull(ExprType.functionAutoTypeConversion(null, ExprType.DOUBLE)); - Assert.assertNull(ExprType.functionAutoTypeConversion(ExprType.STRING, null)); - Assert.assertNull(ExprType.functionAutoTypeConversion(null, ExprType.STRING)); + Assert.assertNull(ExprType.doubleMathFunctionAutoTypeConversion(ExprType.LONG, null)); + Assert.assertNull(ExprType.doubleMathFunctionAutoTypeConversion(null, ExprType.LONG)); + Assert.assertNull(ExprType.doubleMathFunctionAutoTypeConversion(ExprType.DOUBLE, null)); + Assert.assertNull(ExprType.doubleMathFunctionAutoTypeConversion(null, ExprType.DOUBLE)); + Assert.assertNull(ExprType.doubleMathFunctionAutoTypeConversion(ExprType.STRING, null)); + Assert.assertNull(ExprType.doubleMathFunctionAutoTypeConversion(null, ExprType.STRING)); // only long stays long - Assert.assertEquals(ExprType.LONG, ExprType.functionAutoTypeConversion(ExprType.LONG, ExprType.LONG)); + Assert.assertEquals(ExprType.LONG, ExprType.doubleMathFunctionAutoTypeConversion(ExprType.LONG, ExprType.LONG)); // any double makes all doubles - Assert.assertEquals(ExprType.DOUBLE, ExprType.functionAutoTypeConversion(ExprType.LONG, ExprType.DOUBLE)); - Assert.assertEquals(ExprType.DOUBLE, ExprType.functionAutoTypeConversion(ExprType.DOUBLE, ExprType.LONG)); - Assert.assertEquals(ExprType.DOUBLE, ExprType.functionAutoTypeConversion(ExprType.DOUBLE, ExprType.DOUBLE)); + Assert.assertEquals(ExprType.DOUBLE, ExprType.doubleMathFunctionAutoTypeConversion(ExprType.LONG, ExprType.DOUBLE)); + Assert.assertEquals(ExprType.DOUBLE, ExprType.doubleMathFunctionAutoTypeConversion(ExprType.DOUBLE, ExprType.LONG)); + Assert.assertEquals(ExprType.DOUBLE, ExprType.doubleMathFunctionAutoTypeConversion(ExprType.DOUBLE, ExprType.DOUBLE)); // any string makes become string - Assert.assertEquals(ExprType.STRING, ExprType.functionAutoTypeConversion(ExprType.LONG, ExprType.STRING)); - Assert.assertEquals(ExprType.STRING, ExprType.functionAutoTypeConversion(ExprType.STRING, ExprType.LONG)); - Assert.assertEquals(ExprType.STRING, ExprType.functionAutoTypeConversion(ExprType.DOUBLE, ExprType.STRING)); - Assert.assertEquals(ExprType.STRING, ExprType.functionAutoTypeConversion(ExprType.STRING, ExprType.DOUBLE)); - Assert.assertEquals(ExprType.STRING, ExprType.functionAutoTypeConversion(ExprType.STRING, ExprType.STRING)); + Assert.assertEquals(ExprType.STRING, ExprType.doubleMathFunctionAutoTypeConversion(ExprType.LONG, ExprType.STRING)); + Assert.assertEquals(ExprType.STRING, ExprType.doubleMathFunctionAutoTypeConversion(ExprType.STRING, ExprType.LONG)); + Assert.assertEquals(ExprType.STRING, ExprType.doubleMathFunctionAutoTypeConversion(ExprType.DOUBLE, ExprType.STRING)); + Assert.assertEquals(ExprType.STRING, ExprType.doubleMathFunctionAutoTypeConversion(ExprType.STRING, ExprType.DOUBLE)); + Assert.assertEquals(ExprType.STRING, ExprType.doubleMathFunctionAutoTypeConversion(ExprType.STRING, ExprType.STRING)); // unless it is an array, and those have to be the same - Assert.assertEquals(ExprType.LONG_ARRAY, ExprType.functionAutoTypeConversion(ExprType.LONG_ARRAY, ExprType.LONG_ARRAY)); + Assert.assertEquals(ExprType.LONG_ARRAY, ExprType.doubleMathFunctionAutoTypeConversion(ExprType.LONG_ARRAY, ExprType.LONG_ARRAY)); Assert.assertEquals( ExprType.DOUBLE_ARRAY, - ExprType.functionAutoTypeConversion(ExprType.DOUBLE_ARRAY, ExprType.DOUBLE_ARRAY) + ExprType.doubleMathFunctionAutoTypeConversion(ExprType.DOUBLE_ARRAY, ExprType.DOUBLE_ARRAY) ); Assert.assertEquals( ExprType.STRING_ARRAY, - ExprType.functionAutoTypeConversion(ExprType.STRING_ARRAY, ExprType.STRING_ARRAY) + ExprType.doubleMathFunctionAutoTypeConversion(ExprType.STRING_ARRAY, ExprType.STRING_ARRAY) ); } @@ -433,21 +433,21 @@ public void testFunctionAutoConversion() public void testAutoConversionArrayMismatchArrays() { expectedException.expect(IAE.class); - ExprType.functionAutoTypeConversion(ExprType.DOUBLE_ARRAY, ExprType.LONG_ARRAY); + ExprType.doubleMathFunctionAutoTypeConversion(ExprType.DOUBLE_ARRAY, ExprType.LONG_ARRAY); } @Test public void testAutoConversionArrayMismatchArrayScalar() { expectedException.expect(IAE.class); - ExprType.functionAutoTypeConversion(ExprType.DOUBLE_ARRAY, ExprType.LONG); + ExprType.doubleMathFunctionAutoTypeConversion(ExprType.DOUBLE_ARRAY, ExprType.LONG); } @Test public void testAutoConversionArrayMismatchScalarArray() { expectedException.expect(IAE.class); - ExprType.functionAutoTypeConversion(ExprType.STRING, ExprType.LONG_ARRAY); + ExprType.doubleMathFunctionAutoTypeConversion(ExprType.STRING, ExprType.LONG_ARRAY); } private void assertOutputType(String expression, Expr.InputBindingTypes inputTypes, ExprType outputType) diff --git a/core/src/test/java/org/apache/druid/math/expr/VectorExprSanityTest.java b/core/src/test/java/org/apache/druid/math/expr/VectorExprSanityTest.java index cc4ecd0415f0..09740e1d64a7 100644 --- a/core/src/test/java/org/apache/druid/math/expr/VectorExprSanityTest.java +++ b/core/src/test/java/org/apache/druid/math/expr/VectorExprSanityTest.java @@ -109,7 +109,35 @@ public void testUnivariateFunctions() @Test public void testUnivariateMathFunctions() { - final String[] functions = new String[]{"atan", "cos", "cosh", "cot", "sin", "sinh", "tan", "tanh"}; + final String[] functions = new String[]{ + "abs", + "acos", + "asin", + "atan", + "cbrt", + "ceil", + "cos", + "cosh", + "cot", + "exp", + "expm1", + "floor", + "getExponent", + "log", + "log10", + "log1p", + "nextUp", + "rint", + "signum", + "sin", + "sinh", + "sqrt", + "tan", + "tanh", + "toDegrees", + "toRadians", + "ulp" + }; final String[] templates = new String[]{"%s(l1)", "%s(d1)", "%s(pi())"}; testFunctions(types, templates, functions); } @@ -117,7 +145,18 @@ public void testUnivariateMathFunctions() @Test public void testBivariateMathFunctions() { - final String[] functions = new String[]{"max", "min", "pow"}; + final String[] functions = new String[]{ + "atan2", + "copySign", + "div", + "hypot", + "remainder", + "max", + "min", + "nextAfter", + "scalb", + "pow" + }; final String[] templates = new String[]{"%s(d1, d2)", "%s(d1, l1)", "%s(l1, d1)", "%s(l1, l2)"}; testFunctions(types, templates, functions); } diff --git a/sql/src/main/java/org/apache/druid/sql/calcite/expression/builtin/ReductionOperatorConversionHelper.java b/sql/src/main/java/org/apache/druid/sql/calcite/expression/builtin/ReductionOperatorConversionHelper.java index 5aa9a9e3645f..1356de9abb19 100644 --- a/sql/src/main/java/org/apache/druid/sql/calcite/expression/builtin/ReductionOperatorConversionHelper.java +++ b/sql/src/main/java/org/apache/druid/sql/calcite/expression/builtin/ReductionOperatorConversionHelper.java @@ -38,7 +38,7 @@ private ReductionOperatorConversionHelper() * https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#function_least * * @see org.apache.druid.math.expr.Function.ReduceFunction#apply - * @see org.apache.druid.math.expr.ExprType#functionAutoTypeConversion + * @see org.apache.druid.math.expr.ExprType#doubleMathFunctionAutoTypeConversion */ static final SqlReturnTypeInference TYPE_INFERENCE = opBinding -> { From b27fca67d6bc793aaec438138b4d7e6eb2382e83 Mon Sep 17 00:00:00 2001 From: Clint Wylie Date: Thu, 24 Sep 2020 04:59:01 -0700 Subject: [PATCH 2/5] fixes --- .../org/apache/druid/math/expr/Function.java | 6 +++ .../druid/math/expr/OutputTypeTest.java | 37 ++++++++++++++++++- 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/org/apache/druid/math/expr/Function.java b/core/src/main/java/org/apache/druid/math/expr/Function.java index 779e9bf92f59..d812fa830b18 100644 --- a/core/src/main/java/org/apache/druid/math/expr/Function.java +++ b/core/src/main/java/org/apache/druid/math/expr/Function.java @@ -1533,6 +1533,12 @@ protected ExprEval eval(ExprEval x, ExprEval y) return ExprEval.of(Math.scalb(x.asDouble(), y.asInt())); } + @Override + public boolean canVectorize(Expr.InputBindingTypes inputTypes, List args) + { + return inputTypes.areNumeric(args) && inputTypes.canVectorize(args); + } + @Override public ExprVectorProcessor asVectorProcessor(Expr.VectorInputBindingTypes inputTypes, List args) { diff --git a/core/src/test/java/org/apache/druid/math/expr/OutputTypeTest.java b/core/src/test/java/org/apache/druid/math/expr/OutputTypeTest.java index 5369352597d8..c28fdb85d9e7 100644 --- a/core/src/test/java/org/apache/druid/math/expr/OutputTypeTest.java +++ b/core/src/test/java/org/apache/druid/math/expr/OutputTypeTest.java @@ -159,8 +159,8 @@ public void testUnivariateMathFunctions() public void testBivariateMathFunctions() { assertOutputType("div(y,y_)", inputTypes, ExprType.LONG); - assertOutputType("div(y,z_)", inputTypes, ExprType.DOUBLE); - assertOutputType("div(z,z_)", inputTypes, ExprType.DOUBLE); + assertOutputType("div(y,z_)", inputTypes, ExprType.LONG); + assertOutputType("div(z,z_)", inputTypes, ExprType.LONG); assertOutputType("max(y,y_)", inputTypes, ExprType.LONG); assertOutputType("max(y,z_)", inputTypes, ExprType.DOUBLE); @@ -429,6 +429,39 @@ public void testFunctionAutoConversion() ); } + @Test + public void testIntegerFunctionAutoConversion() + { + // nulls output nulls + Assert.assertNull(ExprType.integerMathFunctionAutoTypeConversion(ExprType.LONG, null)); + Assert.assertNull(ExprType.integerMathFunctionAutoTypeConversion(null, ExprType.LONG)); + Assert.assertNull(ExprType.integerMathFunctionAutoTypeConversion(ExprType.DOUBLE, null)); + Assert.assertNull(ExprType.integerMathFunctionAutoTypeConversion(null, ExprType.DOUBLE)); + Assert.assertNull(ExprType.integerMathFunctionAutoTypeConversion(ExprType.STRING, null)); + Assert.assertNull(ExprType.integerMathFunctionAutoTypeConversion(null, ExprType.STRING)); + // all numbers are longs + Assert.assertEquals(ExprType.LONG, ExprType.integerMathFunctionAutoTypeConversion(ExprType.LONG, ExprType.LONG)); + Assert.assertEquals(ExprType.LONG, ExprType.integerMathFunctionAutoTypeConversion(ExprType.LONG, ExprType.DOUBLE)); + Assert.assertEquals(ExprType.LONG, ExprType.integerMathFunctionAutoTypeConversion(ExprType.DOUBLE, ExprType.LONG)); + Assert.assertEquals(ExprType.LONG, ExprType.integerMathFunctionAutoTypeConversion(ExprType.DOUBLE, ExprType.DOUBLE)); + // any string makes become string + Assert.assertEquals(ExprType.STRING, ExprType.integerMathFunctionAutoTypeConversion(ExprType.LONG, ExprType.STRING)); + Assert.assertEquals(ExprType.STRING, ExprType.integerMathFunctionAutoTypeConversion(ExprType.STRING, ExprType.LONG)); + Assert.assertEquals(ExprType.STRING, ExprType.integerMathFunctionAutoTypeConversion(ExprType.DOUBLE, ExprType.STRING)); + Assert.assertEquals(ExprType.STRING, ExprType.integerMathFunctionAutoTypeConversion(ExprType.STRING, ExprType.DOUBLE)); + Assert.assertEquals(ExprType.STRING, ExprType.integerMathFunctionAutoTypeConversion(ExprType.STRING, ExprType.STRING)); + // unless it is an array + Assert.assertEquals(ExprType.LONG_ARRAY, ExprType.integerMathFunctionAutoTypeConversion(ExprType.LONG_ARRAY, ExprType.LONG_ARRAY)); + Assert.assertEquals( + ExprType.DOUBLE_ARRAY, + ExprType.integerMathFunctionAutoTypeConversion(ExprType.DOUBLE_ARRAY, ExprType.DOUBLE_ARRAY) + ); + Assert.assertEquals( + ExprType.STRING_ARRAY, + ExprType.integerMathFunctionAutoTypeConversion(ExprType.STRING_ARRAY, ExprType.STRING_ARRAY) + ); + } + @Test public void testAutoConversionArrayMismatchArrays() { From f132d71b1e26ce3a2089b27b2f2f8dcaee68166c Mon Sep 17 00:00:00 2001 From: Clint Wylie Date: Thu, 24 Sep 2020 11:45:33 -0700 Subject: [PATCH 3/5] remove cannotVectorize() where no longer true --- .../druid/sql/calcite/CalciteQueryTest.java | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/sql/src/test/java/org/apache/druid/sql/calcite/CalciteQueryTest.java b/sql/src/test/java/org/apache/druid/sql/calcite/CalciteQueryTest.java index f077566fd8e7..9e5db9521db9 100644 --- a/sql/src/test/java/org/apache/druid/sql/calcite/CalciteQueryTest.java +++ b/sql/src/test/java/org/apache/druid/sql/calcite/CalciteQueryTest.java @@ -5297,9 +5297,6 @@ public void testCountStarWithLongColumnFiltersOnTwoPoints() throws Exception @Test public void testFilterOnStringAsNumber() throws Exception { - // Cannot vectorize due to usage of expressions. - cannotVectorize(); - testQuery( "SELECT distinct dim1 FROM druid.foo WHERE " + "dim1 = 10 OR " @@ -5846,9 +5843,6 @@ public void testExpressionAggregations() throws Exception @Test public void testExpressionFilteringAndGrouping() throws Exception { - // Cannot vectorize due to virtual columns. - cannotVectorize(); - testQuery( "SELECT\n" + " FLOOR(m1 / 2) * 2,\n" @@ -5943,9 +5937,6 @@ public void testExpressionFilteringAndGroupingUsingCastToLong() throws Exception @Test public void testExpressionFilteringAndGroupingOnStringCastToNumber() throws Exception { - // Cannot vectorize due to virtual columns. - cannotVectorize(); - testQuery( "SELECT\n" + " FLOOR(CAST(dim1 AS FLOAT) / 2) * 2,\n" @@ -9081,9 +9072,6 @@ public void testFilterOnTimeFloorMisaligned() throws Exception @Test public void testGroupByFloor() throws Exception { - // Cannot vectorize due to virtual columns. - cannotVectorize(); - testQuery( "SELECT floor(CAST(dim1 AS float)), COUNT(*) FROM druid.foo GROUP BY floor(CAST(dim1 AS float))", ImmutableList.of( @@ -9111,9 +9099,6 @@ public void testGroupByFloor() throws Exception @Test public void testGroupByFloorWithOrderBy() throws Exception { - // Cannot vectorize due to virtual columns. - cannotVectorize(); - testQuery( "SELECT floor(CAST(dim1 AS float)) AS fl, COUNT(*) FROM druid.foo GROUP BY floor(CAST(dim1 AS float)) ORDER BY fl DESC", ImmutableList.of( From 3d6a279977c90a4057e3b48340812f16bef3dc97 Mon Sep 17 00:00:00 2001 From: Clint Wylie Date: Thu, 24 Sep 2020 18:48:00 -0700 Subject: [PATCH 4/5] disable vectorized groupby for numeric columns with nulls --- .../vector/VectorGroupByEngine.java | 2 +- .../query/groupby/GroupByQueryRunnerTest.java | 5 +++ .../druid/sql/calcite/CalciteQueryTest.java | 44 +++++++++++++++++++ .../SqlVectorizedExpressionSanityTest.java | 8 ++-- 4 files changed, 54 insertions(+), 5 deletions(-) diff --git a/processing/src/main/java/org/apache/druid/query/groupby/epinephelinae/vector/VectorGroupByEngine.java b/processing/src/main/java/org/apache/druid/query/groupby/epinephelinae/vector/VectorGroupByEngine.java index e2f2e756be96..ff982c73477e 100644 --- a/processing/src/main/java/org/apache/druid/query/groupby/epinephelinae/vector/VectorGroupByEngine.java +++ b/processing/src/main/java/org/apache/druid/query/groupby/epinephelinae/vector/VectorGroupByEngine.java @@ -110,7 +110,7 @@ public static boolean canVectorizeDimensions( columnCapabilities.isDictionaryEncoded().isTrue() && columnCapabilities.areDictionaryValuesUnique().isTrue(); } - return columnCapabilities.hasMultipleValues().isFalse(); + return columnCapabilities.hasMultipleValues().isFalse() && columnCapabilities.hasNulls().isFalse(); }); } diff --git a/processing/src/test/java/org/apache/druid/query/groupby/GroupByQueryRunnerTest.java b/processing/src/test/java/org/apache/druid/query/groupby/GroupByQueryRunnerTest.java index c34e1fd4abbe..0f8b69033982 100644 --- a/processing/src/test/java/org/apache/druid/query/groupby/GroupByQueryRunnerTest.java +++ b/processing/src/test/java/org/apache/druid/query/groupby/GroupByQueryRunnerTest.java @@ -10651,6 +10651,11 @@ public void testGroupByOnVirtualColumn() expectedException.expect(UnsupportedOperationException.class); } + // cannot vectorize due to unknown nulls in numeric column + if (NullHandling.sqlCompatible()) { + cannotVectorize(); + } + GroupByQuery query = makeQueryBuilder() .setDataSource(QueryRunnerTestHelper.DATA_SOURCE) .setQuerySegmentSpec(QueryRunnerTestHelper.FIRST_TO_THIRD) diff --git a/sql/src/test/java/org/apache/druid/sql/calcite/CalciteQueryTest.java b/sql/src/test/java/org/apache/druid/sql/calcite/CalciteQueryTest.java index 9e5db9521db9..d1c75ee8ce55 100644 --- a/sql/src/test/java/org/apache/druid/sql/calcite/CalciteQueryTest.java +++ b/sql/src/test/java/org/apache/druid/sql/calcite/CalciteQueryTest.java @@ -5843,6 +5843,10 @@ public void testExpressionAggregations() throws Exception @Test public void testExpressionFilteringAndGrouping() throws Exception { + // cannot vectorize due to unknown nulls in numeric column + if (NullHandling.sqlCompatible()) { + cannotVectorize(); + } testQuery( "SELECT\n" + " FLOOR(m1 / 2) * 2,\n" @@ -5889,6 +5893,10 @@ public void testExpressionFilteringAndGrouping() throws Exception @Test public void testExpressionFilteringAndGroupingUsingCastToLong() throws Exception { + // cannot vectorize due to unknown nulls in numeric column + if (NullHandling.sqlCompatible()) { + cannotVectorize(); + } testQuery( "SELECT\n" + " CAST(m1 AS BIGINT) / 2 * 2,\n" @@ -5937,6 +5945,10 @@ public void testExpressionFilteringAndGroupingUsingCastToLong() throws Exception @Test public void testExpressionFilteringAndGroupingOnStringCastToNumber() throws Exception { + // cannot vectorize due to unknown nulls in numeric column + if (NullHandling.sqlCompatible()) { + cannotVectorize(); + } testQuery( "SELECT\n" + " FLOOR(CAST(dim1 AS FLOAT) / 2) * 2,\n" @@ -6681,6 +6693,10 @@ public void testSumOfExtractionFn() throws Exception @Test public void testTimeseriesWithTimeFilterOnLongColumnUsingMillisToTimestamp() throws Exception { + // cannot vectorize due to unknown nulls in numeric column + if (NullHandling.sqlCompatible()) { + cannotVectorize(); + } testQuery( "SELECT\n" + " FLOOR(MILLIS_TO_TIMESTAMP(cnt) TO YEAR),\n" @@ -9072,6 +9088,10 @@ public void testFilterOnTimeFloorMisaligned() throws Exception @Test public void testGroupByFloor() throws Exception { + // grouping on numeric columns with null values is not yet supported + if (NullHandling.sqlCompatible()) { + cannotVectorize(); + } testQuery( "SELECT floor(CAST(dim1 AS float)), COUNT(*) FROM druid.foo GROUP BY floor(CAST(dim1 AS float))", ImmutableList.of( @@ -9099,6 +9119,10 @@ public void testGroupByFloor() throws Exception @Test public void testGroupByFloorWithOrderBy() throws Exception { + // grouping on numeric columns with null values is not yet supported + if (NullHandling.sqlCompatible()) { + cannotVectorize(); + } testQuery( "SELECT floor(CAST(dim1 AS float)) AS fl, COUNT(*) FROM druid.foo GROUP BY floor(CAST(dim1 AS float)) ORDER BY fl DESC", ImmutableList.of( @@ -9150,6 +9174,10 @@ public void testGroupByFloorWithOrderBy() throws Exception @Test public void testGroupByFloorTimeAndOneOtherDimensionWithOrderBy() throws Exception { + // cannot vectorize due to unknown nulls in numeric column + if (NullHandling.sqlCompatible()) { + cannotVectorize(); + } testQuery( "SELECT floor(__time TO year), dim2, COUNT(*)" + " FROM druid.foo" @@ -11388,6 +11416,10 @@ public void testTimeseriesUsingTimeFloorWithTimeShift() throws Exception @Test public void testTimeseriesUsingTimeFloorWithTimestampAdd() throws Exception { + // cannot vectorize due to unknown nulls in numeric column + if (NullHandling.sqlCompatible()) { + cannotVectorize(); + } testQuery( "SELECT SUM(cnt), gran FROM (\n" + " SELECT TIME_FLOOR(TIMESTAMPADD(DAY, -1, __time), 'P1M') AS gran,\n" @@ -11898,6 +11930,10 @@ public void testTimeseriesWithLimit() throws Exception public void testTimeseriesWithLimitAndOffset() throws Exception { // Timeseries cannot handle offsets, so the query morphs into a groupBy. + // cannot vectorize due to unknown nulls in numeric column + if (NullHandling.sqlCompatible()) { + cannotVectorize(); + } testQuery( "SELECT gran, SUM(cnt)\n" + "FROM (\n" @@ -11962,6 +11998,10 @@ public void testTimeseriesWithOrderByAndLimit() throws Exception @Test public void testGroupByTimeAndOtherDimension() throws Exception { + // cannot vectorize due to unknown nulls in numeric column + if (NullHandling.sqlCompatible()) { + cannotVectorize(); + } testQuery( "SELECT dim2, gran, SUM(cnt)\n" + "FROM (SELECT FLOOR(__time TO MONTH) AS gran, dim2, cnt FROM druid.foo) AS x\n" @@ -15885,6 +15925,10 @@ public void testJoinOnConstantShouldFail(Map queryContext) throw @Test public void testRepeatedIdenticalVirtualExpressionGrouping() throws Exception { + // cannot vectorize due to unknown nulls in numeric column + if (NullHandling.sqlCompatible()) { + cannotVectorize(); + } final String query = "SELECT \n" + "\tCASE dim1 WHEN NULL THEN FALSE ELSE TRUE END AS col_a,\n" + "\tCASE dim2 WHEN NULL THEN FALSE ELSE TRUE END AS col_b\n" diff --git a/sql/src/test/java/org/apache/druid/sql/calcite/SqlVectorizedExpressionSanityTest.java b/sql/src/test/java/org/apache/druid/sql/calcite/SqlVectorizedExpressionSanityTest.java index 10d630bff3c2..9898ff5283a3 100644 --- a/sql/src/test/java/org/apache/druid/sql/calcite/SqlVectorizedExpressionSanityTest.java +++ b/sql/src/test/java/org/apache/druid/sql/calcite/SqlVectorizedExpressionSanityTest.java @@ -45,9 +45,9 @@ import org.apache.druid.sql.calcite.planner.PlannerConfig; import org.apache.druid.sql.calcite.planner.PlannerFactory; import org.apache.druid.sql.calcite.planner.PlannerResult; +import org.apache.druid.sql.calcite.util.CalciteTestBase; import org.apache.druid.sql.calcite.util.CalciteTests; import org.apache.druid.sql.calcite.util.SpecificSegmentsQuerySegmentWalker; -import org.apache.druid.testing.InitializedNullHandlingTest; import org.apache.druid.timeline.DataSegment; import org.apache.druid.timeline.partition.LinearShardSpec; import org.junit.AfterClass; @@ -64,7 +64,7 @@ import java.util.stream.Collectors; @RunWith(Parameterized.class) -public class SqlVectorizedExpressionSanityTest extends InitializedNullHandlingTest +public class SqlVectorizedExpressionSanityTest extends CalciteTestBase { private static final Logger log = new Logger(SqlVectorizedExpressionSanityTest.class); @@ -165,8 +165,8 @@ public void testQuery() throws SqlParseException, RelConversionException, Valida public static void sanityTestVectorizedSqlQueries(PlannerFactory plannerFactory, String query) throws ValidationException, RelConversionException, SqlParseException { - final Map vector = ImmutableMap.of("vectorize", true); - final Map nonvector = ImmutableMap.of("vectorize", false); + final Map vector = ImmutableMap.of("vectorize", "force"); + final Map nonvector = ImmutableMap.of("vectorize", "false"); final AuthenticationResult authenticationResult = NoopEscalator.getInstance() .createEscalatedAuthenticationResult(); From 2fc940bd69f8cd97c81297aabdc999a314f936ec Mon Sep 17 00:00:00 2001 From: Clint Wylie Date: Thu, 24 Sep 2020 22:07:50 -0700 Subject: [PATCH 5/5] fixes --- .../org/apache/druid/math/expr/ExprType.java | 10 +++++----- .../virtual/VectorizedVirtualColumnTest.java | 13 ++++++++++++ .../SqlVectorizedExpressionSanityTest.java | 20 ++++++++++++++++--- 3 files changed, 35 insertions(+), 8 deletions(-) diff --git a/core/src/main/java/org/apache/druid/math/expr/ExprType.java b/core/src/main/java/org/apache/druid/math/expr/ExprType.java index 140edde7062b..e11b8acec74c 100644 --- a/core/src/main/java/org/apache/druid/math/expr/ExprType.java +++ b/core/src/main/java/org/apache/druid/math/expr/ExprType.java @@ -197,7 +197,7 @@ public static ExprType operatorAutoTypeConversion(@Nullable ExprType type, @Null } // otherwise a decimal or integer number - return doubleNumericAutoTypeConversion(type, other); + return numericAutoTypeConversion(type, other); } /** @@ -226,7 +226,7 @@ public static ExprType doubleMathFunctionAutoTypeConversion(@Nullable ExprType t return STRING; } - return doubleNumericAutoTypeConversion(type, other); + return numericAutoTypeConversion(type, other); } /** @@ -260,10 +260,10 @@ public static ExprType integerMathFunctionAutoTypeConversion(@Nullable ExprType } /** - * If both types are {@link #LONG}, returns {@link #LONG}, else {@link #DOUBLE} + * Default best effort numeric type conversion. If both types are {@link #LONG}, returns {@link #LONG}, else + * {@link #DOUBLE} */ - @Nullable - public static ExprType doubleNumericAutoTypeConversion(ExprType type, ExprType other) + public static ExprType numericAutoTypeConversion(ExprType type, ExprType other) { // all numbers win over longs if (LONG.equals(type) && LONG.equals(other)) { diff --git a/processing/src/test/java/org/apache/druid/segment/virtual/VectorizedVirtualColumnTest.java b/processing/src/test/java/org/apache/druid/segment/virtual/VectorizedVirtualColumnTest.java index ed6d1b4fe8ae..ed1a5737558f 100644 --- a/processing/src/test/java/org/apache/druid/segment/virtual/VectorizedVirtualColumnTest.java +++ b/processing/src/test/java/org/apache/druid/segment/virtual/VectorizedVirtualColumnTest.java @@ -22,6 +22,7 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Lists; +import org.apache.druid.common.config.NullHandling; import org.apache.druid.java.util.common.DateTimes; import org.apache.druid.java.util.common.granularity.Granularities; import org.apache.druid.java.util.common.guava.Sequence; @@ -156,18 +157,30 @@ public void testGroupByMultiValueStringNotDictionaryEncoded() @Test public void testGroupByLong() { + // vectorized group by does not work for null numeric columns + if (NullHandling.sqlCompatible()) { + cannotVectorize(); + } testGroupBy(ColumnCapabilitiesImpl.createSimpleNumericColumnCapabilities(ValueType.LONG)); } @Test public void testGroupByDouble() { + // vectorized group by does not work for null numeric columns + if (NullHandling.sqlCompatible()) { + cannotVectorize(); + } testGroupBy(ColumnCapabilitiesImpl.createSimpleNumericColumnCapabilities(ValueType.DOUBLE)); } @Test public void testGroupByFloat() { + // vectorized group by does not work for null numeric columns + if (NullHandling.sqlCompatible()) { + cannotVectorize(); + } testGroupBy(ColumnCapabilitiesImpl.createSimpleNumericColumnCapabilities(ValueType.FLOAT)); } diff --git a/sql/src/test/java/org/apache/druid/sql/calcite/SqlVectorizedExpressionSanityTest.java b/sql/src/test/java/org/apache/druid/sql/calcite/SqlVectorizedExpressionSanityTest.java index 9898ff5283a3..aae98c206063 100644 --- a/sql/src/test/java/org/apache/druid/sql/calcite/SqlVectorizedExpressionSanityTest.java +++ b/sql/src/test/java/org/apache/druid/sql/calcite/SqlVectorizedExpressionSanityTest.java @@ -25,6 +25,7 @@ import org.apache.calcite.sql.parser.SqlParseException; import org.apache.calcite.tools.RelConversionException; import org.apache.calcite.tools.ValidationException; +import org.apache.druid.common.config.NullHandling; import org.apache.druid.java.util.common.StringUtils; import org.apache.druid.java.util.common.granularity.Granularities; import org.apache.druid.java.util.common.guava.Sequence; @@ -41,13 +42,14 @@ import org.apache.druid.server.security.AuthTestUtils; import org.apache.druid.server.security.AuthenticationResult; import org.apache.druid.server.security.NoopEscalator; +import org.apache.druid.sql.calcite.planner.Calcites; import org.apache.druid.sql.calcite.planner.DruidPlanner; import org.apache.druid.sql.calcite.planner.PlannerConfig; import org.apache.druid.sql.calcite.planner.PlannerFactory; import org.apache.druid.sql.calcite.planner.PlannerResult; -import org.apache.druid.sql.calcite.util.CalciteTestBase; import org.apache.druid.sql.calcite.util.CalciteTests; import org.apache.druid.sql.calcite.util.SpecificSegmentsQuerySegmentWalker; +import org.apache.druid.testing.InitializedNullHandlingTest; import org.apache.druid.timeline.DataSegment; import org.apache.druid.timeline.partition.LinearShardSpec; import org.junit.AfterClass; @@ -64,11 +66,22 @@ import java.util.stream.Collectors; @RunWith(Parameterized.class) -public class SqlVectorizedExpressionSanityTest extends CalciteTestBase +public class SqlVectorizedExpressionSanityTest extends InitializedNullHandlingTest { private static final Logger log = new Logger(SqlVectorizedExpressionSanityTest.class); - private static final List QUERIES = ImmutableList.of( + // cannot vectorize grouping on numeric expressions in group by v2 in sql compatible null handling mode + private static final List QUERIES = NullHandling.sqlCompatible() ? ImmutableList.of( + "SELECT SUM(long1 * long2) FROM foo", + "SELECT SUM((long1 * long2) / double1) FROM foo", + "SELECT SUM(float3 + ((long1 * long4)/double1)) FROM foo", + "SELECT SUM(long5 - (float3 + ((long1 * long4)/double1))) FROM foo", + "SELECT cos(double2) FROM foo", + "SELECT SUM(-long4) FROM foo", + "SELECT SUM(PARSE_LONG(string1)) FROM foo", + "SELECT SUM(PARSE_LONG(string3)) FROM foo", + "SELECT string2, SUM(long1 * long4) FROM foo GROUP BY 1 ORDER BY 2" + ) : ImmutableList.of( "SELECT SUM(long1 * long2) FROM foo", "SELECT SUM((long1 * long2) / double1) FROM foo", "SELECT SUM(float3 + ((long1 * long4)/double1)) FROM foo", @@ -97,6 +110,7 @@ public class SqlVectorizedExpressionSanityTest extends CalciteTestBase @BeforeClass public static void setupClass() { + Calcites.setSystemProperties(); CLOSER = Closer.create(); final GeneratorSchemaInfo schemaInfo = GeneratorBasicSchemas.SCHEMA_MAP.get("expression-testbench");