You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@druid.apache.org by cw...@apache.org on 2020/09/27 06:30:34 UTC

[druid] branch master updated: vectorize remaining math expressions (#10429)

This is an automated email from the ASF dual-hosted git repository.

cwylie pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/druid.git


The following commit(s) were added to refs/heads/master by this push:
     new 3d700a5  vectorize remaining math expressions (#10429)
3d700a5 is described below

commit 3d700a5e31eaea131f1152e90b6c78a572edd7fc
Author: Clint Wylie <cw...@apache.org>
AuthorDate: Sat Sep 26 23:30:14 2020 -0700

    vectorize remaining math expressions (#10429)
    
    * vectorize remaining math expressions
    
    * fixes
    
    * remove cannotVectorize() where no longer true
    
    * disable vectorized groupby for numeric columns with nulls
    
    * fixes
---
 .../java/org/apache/druid/math/expr/ExprType.java  |   45 +-
 .../java/org/apache/druid/math/expr/Function.java  |  262 ++--
 .../LongOutDoubleInFunctionVectorProcessor.java    |   53 +
 ...LongOutDoubleLongInFunctionVectorProcessor.java |   58 +
 .../LongOutDoublesInFunctionVectorProcessor.java   |   58 +
 ...LongOutLongDoubleInFunctionVectorProcessor.java |   58 +
 .../math/expr/vector/VectorMathProcessors.java     | 1247 ++++++++++++++++++--
 .../org/apache/druid/math/expr/OutputTypeTest.java |   79 +-
 .../druid/math/expr/VectorExprSanityTest.java      |   43 +-
 .../epinephelinae/vector/VectorGroupByEngine.java  |    2 +-
 .../query/groupby/GroupByQueryRunnerTest.java      |    5 +
 .../virtual/VectorizedVirtualColumnTest.java       |   13 +
 .../builtin/ReductionOperatorConversionHelper.java |    2 +-
 .../apache/druid/sql/calcite/CalciteQueryTest.java |   59 +-
 .../calcite/SqlVectorizedExpressionSanityTest.java |   20 +-
 15 files changed, 1799 insertions(+), 205 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 05262ba..e11b8ace 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 enum ExprType
 
   /**
    * 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 enum ExprType
       return STRING;
     }
 
+    // otherwise a decimal or integer number
     return numericAutoTypeConversion(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
@@ -219,7 +229,40 @@ public enum ExprType
     return numericAutoTypeConversion(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;
+  }
+
+  /**
+   * Default best effort numeric type conversion. If both types are {@link #LONG}, returns {@link #LONG}, else
+   * {@link #DOUBLE}
+   */
   public static ExprType numericAutoTypeConversion(ExprType type, ExprType other)
   {
     // all numbers win over longs
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 4fde339..d812fa8 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 interface Function
     {
       return args.get(0).getOutputType(inputTypes);
     }
+
+    @Override
+    public boolean canVectorize(Expr.InputBindingTypes inputTypes, List<Expr> args)
+    {
+      return inputTypes.areNumeric(args) && inputTypes.canVectorize(args);
+    }
   }
 
   /**
@@ -273,7 +279,13 @@ public interface Function
     @Override
     public ExprType getOutputType(Expr.InputBindingTypes inputTypes, List<Expr> 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<Expr> args)
+    {
+      return inputTypes.areNumeric(args) && inputTypes.canVectorize(args);
     }
   }
 
@@ -432,7 +444,7 @@ public interface Function
     {
       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 interface Function
         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 @@ public interface Function
     {
       return ExprEval.of(Math.abs(param));
     }
+
+    @Override
+    public <T> ExprVectorProcessor<T> asVectorProcessor(Expr.VectorInputBindingTypes inputTypes, List<Expr> args)
+    {
+      return VectorMathProcessors.abs(inputTypes, args.get(0));
+    }
   }
 
   class Acos extends DoubleUnivariateMathFunction
@@ -646,6 +664,12 @@ public interface Function
     {
       return ExprEval.of(Math.acos(param));
     }
+
+    @Override
+    public <T> ExprVectorProcessor<T> asVectorProcessor(Expr.VectorInputBindingTypes inputTypes, List<Expr> args)
+    {
+      return VectorMathProcessors.acos(inputTypes, args.get(0));
+    }
   }
 
   class Asin extends DoubleUnivariateMathFunction
@@ -661,6 +685,12 @@ public interface Function
     {
       return ExprEval.of(Math.asin(param));
     }
+
+    @Override
+    public <T> ExprVectorProcessor<T> asVectorProcessor(Expr.VectorInputBindingTypes inputTypes, List<Expr> args)
+    {
+      return VectorMathProcessors.asin(inputTypes, args.get(0));
+    }
   }
 
   class Atan extends DoubleUnivariateMathFunction
@@ -678,12 +708,6 @@ public interface Function
     }
 
     @Override
-    public boolean canVectorize(Expr.InputBindingTypes inputTypes, List<Expr> args)
-    {
-      return inputTypes.areNumeric(args) && inputTypes.canVectorize(args);
-    }
-
-    @Override
     public <T> ExprVectorProcessor<T> asVectorProcessor(Expr.VectorInputBindingTypes inputTypes, List<Expr> args)
     {
       return VectorMathProcessors.atan(inputTypes, args.get(0));
@@ -703,6 +727,12 @@ public interface Function
     {
       return ExprEval.of(Math.cbrt(param));
     }
+
+    @Override
+    public <T> ExprVectorProcessor<T> asVectorProcessor(Expr.VectorInputBindingTypes inputTypes, List<Expr> args)
+    {
+      return VectorMathProcessors.cbrt(inputTypes, args.get(0));
+    }
   }
 
   class Ceil extends DoubleUnivariateMathFunction
@@ -718,6 +748,12 @@ public interface Function
     {
       return ExprEval.of(Math.ceil(param));
     }
+
+    @Override
+    public <T> ExprVectorProcessor<T> asVectorProcessor(Expr.VectorInputBindingTypes inputTypes, List<Expr> args)
+    {
+      return VectorMathProcessors.ceil(inputTypes, args.get(0));
+    }
   }
 
   class Cos extends DoubleUnivariateMathFunction
@@ -735,12 +771,6 @@ public interface Function
     }
 
     @Override
-    public boolean canVectorize(Expr.InputBindingTypes inputTypes, List<Expr> args)
-    {
-      return inputTypes.areNumeric(args) && inputTypes.canVectorize(args);
-    }
-
-    @Override
     public <T> ExprVectorProcessor<T> asVectorProcessor(Expr.VectorInputBindingTypes inputTypes, List<Expr> args)
     {
       return VectorMathProcessors.cos(inputTypes, args.get(0));
@@ -762,12 +792,6 @@ public interface Function
     }
 
     @Override
-    public boolean canVectorize(Expr.InputBindingTypes inputTypes, List<Expr> args)
-    {
-      return inputTypes.areNumeric(args) && inputTypes.canVectorize(args);
-    }
-
-    @Override
     public <T> ExprVectorProcessor<T> asVectorProcessor(Expr.VectorInputBindingTypes inputTypes, List<Expr> args)
     {
       return VectorMathProcessors.cosh(inputTypes, args.get(0));
@@ -789,12 +813,6 @@ public interface Function
     }
 
     @Override
-    public boolean canVectorize(Expr.InputBindingTypes inputTypes, List<Expr> args)
-    {
-      return inputTypes.areNumeric(args) && inputTypes.canVectorize(args);
-    }
-
-    @Override
     public <T> ExprVectorProcessor<T> asVectorProcessor(Expr.VectorInputBindingTypes inputTypes, List<Expr> args)
     {
       return VectorMathProcessors.cot(inputTypes, args.get(0));
@@ -821,16 +839,17 @@ public interface Function
       return ExprEval.of((long) (x / y));
     }
 
+    @Nullable
     @Override
-    public boolean canVectorize(Expr.InputBindingTypes inputTypes, List<Expr> args)
+    public ExprType getOutputType(Expr.InputBindingTypes inputTypes, List<Expr> args)
     {
-      return inputTypes.areNumeric(args) && inputTypes.canVectorize(args);
+      return ExprType.integerMathFunctionAutoTypeConversion(args.get(0).getOutputType(inputTypes), args.get(1).getOutputType(inputTypes));
     }
 
     @Override
     public <T> ExprVectorProcessor<T> asVectorProcessor(Expr.VectorInputBindingTypes inputTypes, List<Expr> 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 @@ public interface Function
     {
       return ExprEval.of(Math.exp(param));
     }
+
+    @Override
+    public <T> ExprVectorProcessor<T> asVectorProcessor(Expr.VectorInputBindingTypes inputTypes, List<Expr> args)
+    {
+      return VectorMathProcessors.exp(inputTypes, args.get(0));
+    }
   }
 
   class Expm1 extends DoubleUnivariateMathFunction
@@ -862,6 +887,12 @@ public interface Function
     {
       return ExprEval.of(Math.expm1(param));
     }
+
+    @Override
+    public <T> ExprVectorProcessor<T> asVectorProcessor(Expr.VectorInputBindingTypes inputTypes, List<Expr> args)
+    {
+      return VectorMathProcessors.expm1(inputTypes, args.get(0));
+    }
   }
 
   class Floor extends DoubleUnivariateMathFunction
@@ -877,6 +908,12 @@ public interface Function
     {
       return ExprEval.of(Math.floor(param));
     }
+
+    @Override
+    public <T> ExprVectorProcessor<T> asVectorProcessor(Expr.VectorInputBindingTypes inputTypes, List<Expr> args)
+    {
+      return VectorMathProcessors.floor(inputTypes, args.get(0));
+    }
   }
 
   class GetExponent extends UnivariateMathFunction
@@ -892,6 +929,19 @@ public interface Function
     {
       return ExprEval.of(Math.getExponent(param));
     }
+
+    @Nullable
+    @Override
+    public ExprType getOutputType(Expr.InputBindingTypes inputTypes, List<Expr> args)
+    {
+      return ExprType.LONG;
+    }
+
+    @Override
+    public <T> ExprVectorProcessor<T> asVectorProcessor(Expr.VectorInputBindingTypes inputTypes, List<Expr> args)
+    {
+      return VectorMathProcessors.getExponent(inputTypes, args.get(0));
+    }
   }
 
   class Log extends DoubleUnivariateMathFunction
@@ -907,6 +957,12 @@ public interface Function
     {
       return ExprEval.of(Math.log(param));
     }
+
+    @Override
+    public <T> ExprVectorProcessor<T> asVectorProcessor(Expr.VectorInputBindingTypes inputTypes, List<Expr> args)
+    {
+      return VectorMathProcessors.log(inputTypes, args.get(0));
+    }
   }
 
   class Log10 extends DoubleUnivariateMathFunction
@@ -922,6 +978,12 @@ public interface Function
     {
       return ExprEval.of(Math.log10(param));
     }
+
+    @Override
+    public <T> ExprVectorProcessor<T> asVectorProcessor(Expr.VectorInputBindingTypes inputTypes, List<Expr> args)
+    {
+      return VectorMathProcessors.log10(inputTypes, args.get(0));
+    }
   }
 
   class Log1p extends DoubleUnivariateMathFunction
@@ -937,6 +999,12 @@ public interface Function
     {
       return ExprEval.of(Math.log1p(param));
     }
+
+    @Override
+    public <T> ExprVectorProcessor<T> asVectorProcessor(Expr.VectorInputBindingTypes inputTypes, List<Expr> args)
+    {
+      return VectorMathProcessors.log1p(inputTypes, args.get(0));
+    }
   }
 
   class NextUp extends DoubleUnivariateMathFunction
@@ -952,6 +1020,12 @@ public interface Function
     {
       return ExprEval.of(Math.nextUp(param));
     }
+
+    @Override
+    public <T> ExprVectorProcessor<T> asVectorProcessor(Expr.VectorInputBindingTypes inputTypes, List<Expr> args)
+    {
+      return VectorMathProcessors.nextUp(inputTypes, args.get(0));
+    }
   }
 
   class Rint extends DoubleUnivariateMathFunction
@@ -967,6 +1041,12 @@ public interface Function
     {
       return ExprEval.of(Math.rint(param));
     }
+
+    @Override
+    public <T> ExprVectorProcessor<T> asVectorProcessor(Expr.VectorInputBindingTypes inputTypes, List<Expr> args)
+    {
+      return VectorMathProcessors.rint(inputTypes, args.get(0));
+    }
   }
 
   class Round implements Function
@@ -1070,6 +1150,12 @@ public interface Function
     {
       return ExprEval.of(Math.signum(param));
     }
+
+    @Override
+    public <T> ExprVectorProcessor<T> asVectorProcessor(Expr.VectorInputBindingTypes inputTypes, List<Expr> args)
+    {
+      return VectorMathProcessors.signum(inputTypes, args.get(0));
+    }
   }
 
   class Sin extends DoubleUnivariateMathFunction
@@ -1087,12 +1173,6 @@ public interface Function
     }
 
     @Override
-    public boolean canVectorize(Expr.InputBindingTypes inputTypes, List<Expr> args)
-    {
-      return inputTypes.areNumeric(args) && inputTypes.canVectorize(args);
-    }
-
-    @Override
     public <T> ExprVectorProcessor<T> asVectorProcessor(Expr.VectorInputBindingTypes inputTypes, List<Expr> args)
     {
       return VectorMathProcessors.sin(inputTypes, args.get(0));
@@ -1114,12 +1194,6 @@ public interface Function
     }
 
     @Override
-    public boolean canVectorize(Expr.InputBindingTypes inputTypes, List<Expr> args)
-    {
-      return inputTypes.areNumeric(args) && inputTypes.canVectorize(args);
-    }
-
-    @Override
     public <T> ExprVectorProcessor<T> asVectorProcessor(Expr.VectorInputBindingTypes inputTypes, List<Expr> args)
     {
       return VectorMathProcessors.sinh(inputTypes, args.get(0));
@@ -1139,6 +1213,12 @@ public interface Function
     {
       return ExprEval.of(Math.sqrt(param));
     }
+
+    @Override
+    public <T> ExprVectorProcessor<T> asVectorProcessor(Expr.VectorInputBindingTypes inputTypes, List<Expr> args)
+    {
+      return VectorMathProcessors.sqrt(inputTypes, args.get(0));
+    }
   }
 
   class Tan extends DoubleUnivariateMathFunction
@@ -1156,12 +1236,6 @@ public interface Function
     }
 
     @Override
-    public boolean canVectorize(Expr.InputBindingTypes inputTypes, List<Expr> args)
-    {
-      return inputTypes.areNumeric(args) && inputTypes.canVectorize(args);
-    }
-
-    @Override
     public <T> ExprVectorProcessor<T> asVectorProcessor(Expr.VectorInputBindingTypes inputTypes, List<Expr> args)
     {
       return VectorMathProcessors.tan(inputTypes, args.get(0));
@@ -1183,12 +1257,6 @@ public interface Function
     }
 
     @Override
-    public boolean canVectorize(Expr.InputBindingTypes inputTypes, List<Expr> args)
-    {
-      return inputTypes.areNumeric(args) && inputTypes.canVectorize(args);
-    }
-
-    @Override
     public <T> ExprVectorProcessor<T> asVectorProcessor(Expr.VectorInputBindingTypes inputTypes, List<Expr> args)
     {
       return VectorMathProcessors.tanh(inputTypes, args.get(0));
@@ -1208,6 +1276,12 @@ public interface Function
     {
       return ExprEval.of(Math.toDegrees(param));
     }
+
+    @Override
+    public <T> ExprVectorProcessor<T> asVectorProcessor(Expr.VectorInputBindingTypes inputTypes, List<Expr> args)
+    {
+      return VectorMathProcessors.toDegrees(inputTypes, args.get(0));
+    }
   }
 
   class ToRadians extends DoubleUnivariateMathFunction
@@ -1223,6 +1297,12 @@ public interface Function
     {
       return ExprEval.of(Math.toRadians(param));
     }
+
+    @Override
+    public <T> ExprVectorProcessor<T> asVectorProcessor(Expr.VectorInputBindingTypes inputTypes, List<Expr> args)
+    {
+      return VectorMathProcessors.toRadians(inputTypes, args.get(0));
+    }
   }
 
   class Ulp extends DoubleUnivariateMathFunction
@@ -1238,6 +1318,12 @@ public interface Function
     {
       return ExprEval.of(Math.ulp(param));
     }
+
+    @Override
+    public <T> ExprVectorProcessor<T> asVectorProcessor(Expr.VectorInputBindingTypes inputTypes, List<Expr> args)
+    {
+      return VectorMathProcessors.ulp(inputTypes, args.get(0));
+    }
   }
 
   class Atan2 extends DoubleBivariateMathFunction
@@ -1253,6 +1339,12 @@ public interface Function
     {
       return ExprEval.of(Math.atan2(y, x));
     }
+
+    @Override
+    public <T> ExprVectorProcessor<T> asVectorProcessor(Expr.VectorInputBindingTypes inputTypes, List<Expr> args)
+    {
+      return VectorMathProcessors.atan2(inputTypes, args.get(0), args.get(1));
+    }
   }
 
   class CopySign extends DoubleBivariateMathFunction
@@ -1268,6 +1360,12 @@ public interface Function
     {
       return ExprEval.of(Math.copySign(x, y));
     }
+
+    @Override
+    public <T> ExprVectorProcessor<T> asVectorProcessor(Expr.VectorInputBindingTypes inputTypes, List<Expr> args)
+    {
+      return VectorMathProcessors.copySign(inputTypes, args.get(0), args.get(1));
+    }
   }
 
   class Hypot extends DoubleBivariateMathFunction
@@ -1283,6 +1381,12 @@ public interface Function
     {
       return ExprEval.of(Math.hypot(x, y));
     }
+
+    @Override
+    public <T> ExprVectorProcessor<T> asVectorProcessor(Expr.VectorInputBindingTypes inputTypes, List<Expr> args)
+    {
+      return VectorMathProcessors.hypot(inputTypes, args.get(0), args.get(1));
+    }
   }
 
   class Remainder extends DoubleBivariateMathFunction
@@ -1298,6 +1402,12 @@ public interface Function
     {
       return ExprEval.of(Math.IEEEremainder(x, y));
     }
+
+    @Override
+    public <T> ExprVectorProcessor<T> asVectorProcessor(Expr.VectorInputBindingTypes inputTypes, List<Expr> args)
+    {
+      return VectorMathProcessors.remainder(inputTypes, args.get(0), args.get(1));
+    }
   }
 
   class Max extends BivariateMathFunction
@@ -1321,12 +1431,6 @@ public interface Function
     }
 
     @Override
-    public boolean canVectorize(Expr.InputBindingTypes inputTypes, List<Expr> args)
-    {
-      return inputTypes.areNumeric(args) && inputTypes.canVectorize(args);
-    }
-
-    @Override
     public <T> ExprVectorProcessor<T> asVectorProcessor(Expr.VectorInputBindingTypes inputTypes, List<Expr> args)
     {
       return VectorMathProcessors.max(inputTypes, args.get(0), args.get(1));
@@ -1354,12 +1458,6 @@ public interface Function
     }
 
     @Override
-    public boolean canVectorize(Expr.InputBindingTypes inputTypes, List<Expr> args)
-    {
-      return inputTypes.areNumeric(args) && inputTypes.canVectorize(args);
-    }
-
-    @Override
     public <T> ExprVectorProcessor<T> asVectorProcessor(Expr.VectorInputBindingTypes inputTypes, List<Expr> args)
     {
       return VectorMathProcessors.min(inputTypes, args.get(0), args.get(1));
@@ -1379,6 +1477,12 @@ public interface Function
     {
       return ExprEval.of(Math.nextAfter(x, y));
     }
+
+    @Override
+    public <T> ExprVectorProcessor<T> asVectorProcessor(Expr.VectorInputBindingTypes inputTypes, List<Expr> args)
+    {
+      return VectorMathProcessors.nextAfter(inputTypes, args.get(0), args.get(1));
+    }
   }
 
   class Pow extends DoubleBivariateMathFunction
@@ -1396,12 +1500,6 @@ public interface Function
     }
 
     @Override
-    public boolean canVectorize(Expr.InputBindingTypes inputTypes, List<Expr> args)
-    {
-      return inputTypes.areNumeric(args) && inputTypes.canVectorize(args);
-    }
-
-    @Override
     public <T> ExprVectorProcessor<T> asVectorProcessor(Expr.VectorInputBindingTypes inputTypes, List<Expr> args)
     {
       return VectorMathProcessors.doublePower(inputTypes, args.get(0), args.get(1));
@@ -1426,8 +1524,26 @@ public interface Function
     @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 boolean canVectorize(Expr.InputBindingTypes inputTypes, List<Expr> args)
+    {
+      return inputTypes.areNumeric(args) && inputTypes.canVectorize(args);
+    }
+
+    @Override
+    public <T> ExprVectorProcessor<T> asVectorProcessor(Expr.VectorInputBindingTypes inputTypes, List<Expr> args)
+    {
+      return VectorMathProcessors.scalb(inputTypes, args.get(0), args.get(1));
+    }
   }
 
   class CastFunc extends BivariateFunction
@@ -2503,7 +2619,7 @@ public interface Function
     {
       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 0000000..318e2df
--- /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<double[], long[]>
+{
+  public LongOutDoubleInFunctionVectorProcessor(ExprVectorProcessor<double[]> 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<long[]> 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 0000000..0e38d7c
--- /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<double[], long[], long[]>
+{
+  public LongOutDoubleLongInFunctionVectorProcessor(
+      ExprVectorProcessor<double[]> left,
+      ExprVectorProcessor<long[]> 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<long[]> 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 0000000..6cbbe9d
--- /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<double[], double[], long[]>
+{
+  public LongOutDoublesInFunctionVectorProcessor(
+      ExprVectorProcessor<double[]> left,
+      ExprVectorProcessor<double[]> 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<long[]> 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 0000000..dce8033
--- /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<long[], double[], long[]>
+{
+  public LongOutLongDoubleInFunctionVectorProcessor(
+      ExprVectorProcessor<long[]> left,
+      ExprVectorProcessor<double[]> 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<long[]> 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 ea6db8f..bd33e8d 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
@@ -82,6 +82,32 @@ public class VectorMathProcessors
   }
 
   /**
+   * Make a 1 argument math processor with the following type rules
+   *    long    -> long
+   *    double  -> long
+   */
+  public static <T> ExprVectorProcessor<T> makeLongMathProcessor(
+      Expr.VectorInputBindingTypes inputTypes,
+      Expr arg,
+      Supplier<LongOutLongInFunctionVectorProcessor> longOutLongInSupplier,
+      Supplier<LongOutDoubleInFunctionVectorProcessor> 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<T>) processor;
+  }
+
+  /**
    * Make a 2 argument, math processor with the following type rules
    *    long, long      -> long
    *    long, double    -> double
@@ -120,6 +146,84 @@ public class VectorMathProcessors
     return (ExprVectorProcessor<T>) 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 <T> ExprVectorProcessor<T> makeDoubleMathProcessor(
+      Expr.VectorInputBindingTypes inputTypes,
+      Expr left,
+      Expr right,
+      Supplier<DoubleOutLongsInFunctionVectorProcessor> doubleOutLongsInProcessor,
+      Supplier<DoubleOutLongDoubleInFunctionVectorProcessor> doubleOutLongDoubleInProcessor,
+      Supplier<DoubleOutDoubleLongInFunctionVectorProcessor> doubleOutDoubleLongInProcessor,
+      Supplier<DoubleOutDoublesInFunctionVectorProcessor> 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<T>) 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 <T> ExprVectorProcessor<T> makeLongMathProcessor(
+      Expr.VectorInputBindingTypes inputTypes,
+      Expr left,
+      Expr right,
+      Supplier<LongOutLongsInFunctionVectorProcessor> longOutLongsInProcessor,
+      Supplier<LongOutLongDoubleInFunctionVectorProcessor> longOutLongDoubleInProcessor,
+      Supplier<LongOutDoubleLongInFunctionVectorProcessor> longOutDoubleLongInProcessor,
+      Supplier<LongOutDoublesInFunctionVectorProcessor> 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<T>) processor;
+  }
+
   public static <T> ExprVectorProcessor<T> plus(Expr.VectorInputBindingTypes inputTypes, Expr left, Expr right)
   {
     return makeMathProcessor(
@@ -348,6 +452,63 @@ public class VectorMathProcessors
     );
   }
 
+  public static <T> ExprVectorProcessor<T> 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 <T> ExprVectorProcessor<T> modulo(Expr.VectorInputBindingTypes inputTypes, Expr left, Expr right)
   {
     return makeMathProcessor(
@@ -632,170 +793,812 @@ public class VectorMathProcessors
     );
   }
 
-  public static <T> ExprVectorProcessor<T> atan(Expr.VectorInputBindingTypes inputTypes, Expr arg)
+  public static <T> ExprVectorProcessor<T> 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 <T> ExprVectorProcessor<T> 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 <T> ExprVectorProcessor<T> cosh(Expr.VectorInputBindingTypes inputTypes, Expr arg)
+  public static <T> ExprVectorProcessor<T> 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 <T> ExprVectorProcessor<T> 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 <T> ExprVectorProcessor<T> sin(Expr.VectorInputBindingTypes inputTypes, Expr arg)
+  public static <T> ExprVectorProcessor<T> 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 <T> ExprVectorProcessor<T> 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 <T> ExprVectorProcessor<T> 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 <T> ExprVectorProcessor<T> 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 <T> ExprVectorProcessor<T> 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 <T> ExprVectorProcessor<T> 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 <T> ExprVectorProcessor<T> 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 <T> ExprVectorProcessor<T> 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 <T> ExprVectorProcessor<T> 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 <T> ExprVectorProcessor<T> 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 <T> ExprVectorProcessor<T> 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 <T> ExprVectorProcessor<T> 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 <T> ExprVectorProcessor<T> 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 <T> ExprVectorProcessor<T> 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 <T> ExprVectorProcessor<T> 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 <T> ExprVectorProcessor<T> 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 <T> ExprVectorProcessor<T> 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 <T> ExprVectorProcessor<T> 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 <T> ExprVectorProcessor<T> 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 <T> ExprVectorProcessor<T> 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 <T> ExprVectorProcessor<T> 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 class VectorMathProcessors
           @Override
           public double apply(double input)
           {
-            return Math.sinh(input);
+            return Math.expm1(input);
           }
         }
     );
   }
 
-  public static <T> ExprVectorProcessor<T> tan(Expr.VectorInputBindingTypes inputTypes, Expr arg)
+  public static <T> ExprVectorProcessor<T> 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 <T> ExprVectorProcessor<T> log(Expr.VectorInputBindingTypes inputTypes, Expr arg)
   {
     return makeDoubleMathProcessor(
         inputTypes,
@@ -825,7 +1658,7 @@ public class VectorMathProcessors
           @Override
           public double apply(long input)
           {
-            return Math.tan(input);
+            return Math.log(input);
           }
         },
         () -> new DoubleOutDoubleInFunctionVectorProcessor(
@@ -836,13 +1669,13 @@ public class VectorMathProcessors
           @Override
           public double apply(double input)
           {
-            return Math.tan(input);
+            return Math.log(input);
           }
         }
     );
   }
 
-  public static <T> ExprVectorProcessor<T> tanh(Expr.VectorInputBindingTypes inputTypes, Expr arg)
+  public static <T> ExprVectorProcessor<T> log10(Expr.VectorInputBindingTypes inputTypes, Expr arg)
   {
     return makeDoubleMathProcessor(
         inputTypes,
@@ -855,7 +1688,7 @@ public class VectorMathProcessors
           @Override
           public double apply(long input)
           {
-            return Math.tanh(input);
+            return Math.log10(input);
           }
         },
         () -> new DoubleOutDoubleInFunctionVectorProcessor(
@@ -866,12 +1699,254 @@ public class VectorMathProcessors
           @Override
           public double apply(double input)
           {
-            return Math.tanh(input);
+            return Math.log10(input);
+          }
+        }
+    );
+  }
+
+  public static <T> ExprVectorProcessor<T> 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 <T> ExprVectorProcessor<T> 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 <T> ExprVectorProcessor<T> 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 <T> ExprVectorProcessor<T> 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 <T> ExprVectorProcessor<T> 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 <T> ExprVectorProcessor<T> 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 <T> ExprVectorProcessor<T> 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 <T> ExprVectorProcessor<T> 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 7b977d3..c28fdb8 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 class OutputTypeTest extends InitializedNullHandlingTest
   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);
@@ -399,33 +399,66 @@ public class OutputTypeTest extends InitializedNullHandlingTest
   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)
+    );
+  }
+
+  @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)
     );
   }
 
@@ -433,21 +466,21 @@ public class OutputTypeTest extends InitializedNullHandlingTest
   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 cc4ecd0..09740e1 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 class VectorExprSanityTest extends InitializedNullHandlingTest
   @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 class VectorExprSanityTest extends InitializedNullHandlingTest
   @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/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 e2f2e75..ff982c7 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 class VectorGroupByEngine
                        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 c34e1fd..0f8b690 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 class GroupByQueryRunnerTest extends InitializedNullHandlingTest
       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/processing/src/test/java/org/apache/druid/segment/virtual/VectorizedVirtualColumnTest.java b/processing/src/test/java/org/apache/druid/segment/virtual/VectorizedVirtualColumnTest.java
index ed6d1b4..ed1a573 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 @@ package org.apache.druid.segment.virtual;
 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 class VectorizedVirtualColumnTest
   @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/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 5aa9a9e..1356de9 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 @@ class 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 -> {
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 f077566..d1c75ee 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 class CalciteQueryTest extends BaseCalciteQueryTest
   @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,10 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
   @Test
   public void testExpressionFilteringAndGrouping() throws Exception
   {
-    // Cannot vectorize due to virtual columns.
-    cannotVectorize();
-
+    // cannot vectorize due to unknown nulls in numeric column
+    if (NullHandling.sqlCompatible()) {
+      cannotVectorize();
+    }
     testQuery(
         "SELECT\n"
         + "  FLOOR(m1 / 2) * 2,\n"
@@ -5895,6 +5893,10 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
   @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"
@@ -5943,9 +5945,10 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
   @Test
   public void testExpressionFilteringAndGroupingOnStringCastToNumber() throws Exception
   {
-    // Cannot vectorize due to virtual columns.
-    cannotVectorize();
-
+    // cannot vectorize due to unknown nulls in numeric column
+    if (NullHandling.sqlCompatible()) {
+      cannotVectorize();
+    }
     testQuery(
         "SELECT\n"
         + "  FLOOR(CAST(dim1 AS FLOAT) / 2) * 2,\n"
@@ -6690,6 +6693,10 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
   @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"
@@ -9081,9 +9088,10 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
   @Test
   public void testGroupByFloor() throws Exception
   {
-    // Cannot vectorize due to virtual columns.
-    cannotVectorize();
-
+    // 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(
@@ -9111,9 +9119,10 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
   @Test
   public void testGroupByFloorWithOrderBy() throws Exception
   {
-    // Cannot vectorize due to virtual columns.
-    cannotVectorize();
-
+    // 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(
@@ -9165,6 +9174,10 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
   @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"
@@ -11403,6 +11416,10 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
   @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"
@@ -11913,6 +11930,10 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
   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"
@@ -11977,6 +11998,10 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
   @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"
@@ -15900,6 +15925,10 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
   @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 10d630b..aae98c2 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.schema.SchemaPlus;
 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,6 +42,7 @@ import org.apache.druid.server.QueryStackTests;
 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;
@@ -68,7 +70,18 @@ public class SqlVectorizedExpressionSanityTest extends InitializedNullHandlingTe
 {
   private static final Logger log = new Logger(SqlVectorizedExpressionSanityTest.class);
 
-  private static final List<String> QUERIES = ImmutableList.of(
+  // cannot vectorize grouping on numeric expressions in group by v2 in sql compatible null handling mode
+  private static final List<String> 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 InitializedNullHandlingTe
   @BeforeClass
   public static void setupClass()
   {
+    Calcites.setSystemProperties();
     CLOSER = Closer.create();
 
     final GeneratorSchemaInfo schemaInfo = GeneratorBasicSchemas.SCHEMA_MAP.get("expression-testbench");
@@ -165,8 +179,8 @@ public class SqlVectorizedExpressionSanityTest extends InitializedNullHandlingTe
   public static void sanityTestVectorizedSqlQueries(PlannerFactory plannerFactory, String query)
       throws ValidationException, RelConversionException, SqlParseException
   {
-    final Map<String, Object> vector = ImmutableMap.of("vectorize", true);
-    final Map<String, Object> nonvector = ImmutableMap.of("vectorize", false);
+    final Map<String, Object> vector = ImmutableMap.of("vectorize", "force");
+    final Map<String, Object> nonvector = ImmutableMap.of("vectorize", "false");
     final AuthenticationResult authenticationResult = NoopEscalator.getInstance()
                                                                    .createEscalatedAuthenticationResult();
 


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@druid.apache.org
For additional commands, e-mail: commits-help@druid.apache.org