From b940467023a895529f828f88f5208532bb77ef70 Mon Sep 17 00:00:00 2001 From: Max Kaplan Date: Sat, 1 Aug 2020 19:10:28 -0400 Subject: [PATCH 1/9] expressions: adding bitwise expressions --- .../org/apache/druid/math/expr/Function.java | 90 +++++++++++++++++++ docs/misc/math-expr.md | 6 ++ 2 files changed, 96 insertions(+) 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 a20863929875..420702fe136d 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 @@ -461,6 +461,96 @@ protected ExprEval eval(double param) } } + class BitwiseAnd extends BivariateMathFunction + { + @Override + public String name() + { + return "bitwiseAnd"; + } + + @Override + protected ExprEval eval(long x, long y) + { + return ExprEval.of(x & y); + } + } + + class BitwiseComplement extends UnivariateMathFunction + { + @Override + public String name() + { + return "bitwiseComplement"; + } + + @Override + protected ExprEval eval(long param) + { + return ExprEval.of(~param); + } + } + + class BitwiseOr extends BivariateMathFunction + { + @Override + public String name() + { + return "bitwiseOr"; + } + + @Override + protected ExprEval eval(long x, long y) + { + return ExprEval.of(x | y); + } + } + + class BitwiseShiftLeft extends BivariateMathFunction + { + @Override + public String name() + { + return "bitwiseShiftLeft"; + } + + @Override + protected ExprEval eval(long x, long y) + { + return ExprEval.of(x << y); + } + } + + class BitwiseShiftRight extends BivariateMathFunction + { + @Override + public String name() + { + return "bitwiseShiftRight"; + } + + @Override + protected ExprEval eval(long x, long y) + { + return ExprEval.of(x >> y); + } + } + + class BitwiseXor extends BivariateMathFunction + { + @Override + public String name() + { + return "bitwiseXor"; + } + + @Override + protected ExprEval eval(long x, long y) + { + return ExprEval.of(x ^ y); + } + } + class Cbrt extends UnivariateMathFunction { @Override diff --git a/docs/misc/math-expr.md b/docs/misc/math-expr.md index dc356479ad58..d16563722bb9 100644 --- a/docs/misc/math-expr.md +++ b/docs/misc/math-expr.md @@ -117,6 +117,12 @@ See javadoc of java.lang.Math for detailed explanation for each function. |acos|acos(x) would return the arc cosine of x| |asin|asin(x) would return the arc sine of x| |atan|atan(x) would return the arc tangent of x| +|bitwiseAnd|bitwiseAnd(x,y) would return the result of x & y| +|bitwiseComplement|bitwiseComplement(x) would return the result of ~x| +|bitwiseOr|bitwiseOr(x,y) would return the result of x [PIPE] y | +|bitwiseShiftLeft|bitwiseShiftLeft(x,y) would return the result of x << y| +|bitwiseShiftRight|bitwiseShiftRight(x,y) would return the result of x >> y| +|bitwiseXor|bitwiseXor(x,y) would return the result of x ^ y| |atan2|atan2(y, x) would return the angle theta from the conversion of rectangular coordinates (x, y) to polar * coordinates (r, theta)| |cbrt|cbrt(x) would return the cube root of x| |ceil|ceil(x) would return the smallest (closest to negative infinity) double value that is greater than or equal to x and is equal to a mathematical integer| From 88529c0b70997eae17089498fbe5326d39d2f924 Mon Sep 17 00:00:00 2001 From: Clint Wylie Date: Wed, 25 Nov 2020 01:58:03 -0800 Subject: [PATCH 2/9] double handling and vectorization --- .../org/apache/druid/math/expr/Function.java | 148 +++++++- .../expr/vector/VectorMathProcessors.java | 357 ++++++++++++++++++ .../apache/druid/math/expr/FunctionTest.java | 25 ++ .../druid/math/expr/VectorExprSanityTest.java | 11 +- docs/misc/math-expr.md | 15 +- website/.spelling | 7 + website/package-lock.json | 44 +-- 7 files changed, 555 insertions(+), 52 deletions(-) diff --git a/core/src/main/java/org/apache/druid/math/expr/Function.java b/core/src/main/java/org/apache/druid/math/expr/Function.java index ec6587662386..ab6d309278d8 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 @@ -312,6 +312,42 @@ public ExprType getOutputType(Expr.InputBindingInspector inspector, List a } } + abstract class BivariateBitwiseMathFunction extends BivariateFunction + { + @Override + protected final ExprEval eval(ExprEval x, ExprEval y) + { + // this is a copy of the logic of BivariateMathFunction for string handling, which itself is a + // remix of BinaryEvalOpExprBase.eval modified so that string inputs are always null outputs + if (NullHandling.sqlCompatible() && (x.value() == null || y.value() == null)) { + return ExprEval.of(null); + } + + ExprType type = ExprTypeConversion.autoDetect(x, y); + if (type == ExprType.STRING) { + return ExprEval.of(null); + } + final long xlong = ExprType.DOUBLE.equals(x.type()) ? Double.doubleToLongBits(x.asDouble()) : x.asLong(); + final long ylong = ExprType.DOUBLE.equals(y.type()) ? Double.doubleToLongBits(y.asDouble()) : y.asLong(); + return eval(xlong, ylong); + } + + protected abstract ExprEval eval(long x, long y); + + @Nullable + @Override + public ExprType getOutputType(Expr.InputBindingInspector inspector, List args) + { + return ExprType.LONG; + } + + @Override + public boolean canVectorize(Expr.InputBindingInspector inspector, List args) + { + return inspector.areNumeric(args) && inspector.canVectorize(args); + } + } + /** * Base class for a 2 variable input {@link Function} whose first argument is a {@link ExprType#STRING} and second * argument is {@link ExprType#LONG} @@ -724,37 +760,103 @@ public ExprVectorProcessor asVectorProcessor(Expr.VectorInputBindingInspe } } - class BitwiseAnd extends BivariateMathFunction + class BitwiseComplement extends UnivariateMathFunction { @Override public String name() { - return "bitwiseAnd"; + return "bitwiseComplement"; } + @Nullable @Override - protected ExprEval eval(long x, long y) + public ExprType getOutputType(Expr.InputBindingInspector inspector, List args) { - return ExprEval.of(x & y); + return ExprType.LONG; + } + + @Override + protected ExprEval eval(long param) + { + return ExprEval.of(~param); + } + + @Override + protected ExprEval eval(double param) + { + return ExprEval.of(~Double.doubleToLongBits(param)); + } + + @Override + public ExprVectorProcessor asVectorProcessor(Expr.VectorInputBindingInspector inspector, List args) + { + return VectorMathProcessors.bitwiseComplement(inspector, args.get(0)); } } - class BitwiseComplement extends UnivariateMathFunction + class BitwiseConvertDouble extends UnivariateMathFunction { @Override public String name() { - return "bitwiseComplement"; + return "bitwiseConvertDouble"; + } + + @Nullable + @Override + public ExprType getOutputType(Expr.InputBindingInspector inspector, List args) + { + ExprType type = args.get(0).getOutputType(inspector); + if (type == null) { + return null; + } + if (type == ExprType.LONG) { + return ExprType.DOUBLE; + } + return ExprType.LONG; } @Override protected ExprEval eval(long param) { - return ExprEval.of(~param); + return ExprEval.of(Double.longBitsToDouble(param)); + } + + @Override + protected ExprEval eval(double param) + { + return ExprEval.of(Double.doubleToLongBits(param)); + } + + @Override + public ExprVectorProcessor asVectorProcessor(Expr.VectorInputBindingInspector inspector, List args) + { + return VectorMathProcessors.bitwiseConvertDouble(inspector, args.get(0)); + } + } + + class BitwiseAnd extends BivariateBitwiseMathFunction + { + @Override + public String name() + { + return "bitwiseAnd"; + } + + @Override + protected ExprEval eval(long x, long y) + { + return ExprEval.of(x & y); + } + + @Override + public ExprVectorProcessor asVectorProcessor(Expr.VectorInputBindingInspector inspector, List args) + { + return VectorMathProcessors.bitwiseAnd(inspector, args.get(0), args.get(1)); } } - class BitwiseOr extends BivariateMathFunction + class BitwiseOr extends BivariateBitwiseMathFunction { @Override public String name() @@ -767,9 +869,15 @@ protected ExprEval eval(long x, long y) { return ExprEval.of(x | y); } + + @Override + public ExprVectorProcessor asVectorProcessor(Expr.VectorInputBindingInspector inspector, List args) + { + return VectorMathProcessors.bitwiseOr(inspector, args.get(0), args.get(1)); + } } - class BitwiseShiftLeft extends BivariateMathFunction + class BitwiseShiftLeft extends BivariateBitwiseMathFunction { @Override public String name() @@ -782,9 +890,15 @@ protected ExprEval eval(long x, long y) { return ExprEval.of(x << y); } + + @Override + public ExprVectorProcessor asVectorProcessor(Expr.VectorInputBindingInspector inspector, List args) + { + return VectorMathProcessors.bitwiseShiftLeft(inspector, args.get(0), args.get(1)); + } } - class BitwiseShiftRight extends BivariateMathFunction + class BitwiseShiftRight extends BivariateBitwiseMathFunction { @Override public String name() @@ -797,9 +911,15 @@ protected ExprEval eval(long x, long y) { return ExprEval.of(x >> y); } + + @Override + public ExprVectorProcessor asVectorProcessor(Expr.VectorInputBindingInspector inspector, List args) + { + return VectorMathProcessors.bitwiseShiftRight(inspector, args.get(0), args.get(1)); + } } - class BitwiseXor extends BivariateMathFunction + class BitwiseXor extends BivariateBitwiseMathFunction { @Override public String name() @@ -812,6 +932,12 @@ protected ExprEval eval(long x, long y) { return ExprEval.of(x ^ y); } + + @Override + public ExprVectorProcessor asVectorProcessor(Expr.VectorInputBindingInspector inspector, List args) + { + return VectorMathProcessors.bitwiseXor(inspector, args.get(0), args.get(1)); + } } class Cbrt extends DoubleUnivariateMathFunction 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 c1a9888466a0..3ff573c6727e 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 @@ -1968,7 +1968,364 @@ public double apply(double input) ); } + public static ExprVectorProcessor bitwiseComplement(Expr.VectorInputBindingInspector inspector, Expr arg) + { + return makeLongMathProcessor( + inspector, + arg, + () -> new LongOutLongInFunctionVectorProcessor( + arg.buildVectorized(inspector), + inspector.getMaxVectorSize() + ) + { + @Override + public long apply(long input) + { + return ~input; + } + }, + () -> new LongOutDoubleInFunctionVectorProcessor( + arg.buildVectorized(inspector), + inspector.getMaxVectorSize() + ) + { + @Override + public long apply(double input) + { + return ~Double.doubleToLongBits(input); + } + } + ); + } + + public static ExprVectorProcessor bitwiseConvertDouble(Expr.VectorInputBindingInspector inspector, Expr arg) + { + final ExprType inputType = arg.getOutputType(inspector); + + ExprVectorProcessor processor = null; + if (inputType == ExprType.LONG) { + processor = new DoubleOutLongInFunctionVectorProcessor( + arg.buildVectorized(inspector), + inspector.getMaxVectorSize() + ) + { + @Override + public double apply(long input) + { + return Double.longBitsToDouble(input); + } + }; + } else if (inputType == ExprType.DOUBLE) { + processor = new LongOutDoubleInFunctionVectorProcessor( + arg.buildVectorized(inspector), + inspector.getMaxVectorSize() + ) + { + @Override + public long apply(double input) + { + return Double.doubleToLongBits(input); + } + }; + } + if (processor == null) { + throw Exprs.cannotVectorize(); + } + return (ExprVectorProcessor) processor; + } + + public static ExprVectorProcessor bitwiseAnd(Expr.VectorInputBindingInspector inspector, Expr left, Expr right) + { + return makeLongMathProcessor( + inspector, + left, + right, + () -> new LongOutLongsInFunctionVectorProcessor( + left.buildVectorized(inspector), + right.buildVectorized(inspector), + inspector.getMaxVectorSize() + ) + { + @Override + public long apply(long left, long right) + { + return left & right; + } + }, + () -> new LongOutLongDoubleInFunctionVectorProcessor( + left.buildVectorized(inspector), + right.buildVectorized(inspector), + inspector.getMaxVectorSize() + ) + { + @Override + public long apply(long left, double right) + { + return left & Double.doubleToLongBits(right); + } + }, + () -> new LongOutDoubleLongInFunctionVectorProcessor( + left.buildVectorized(inspector), + right.buildVectorized(inspector), + inspector.getMaxVectorSize() + ) + { + @Override + public long apply(double left, long right) + { + return Double.doubleToLongBits(left) & right; + } + }, + () -> new LongOutDoublesInFunctionVectorProcessor( + left.buildVectorized(inspector), + right.buildVectorized(inspector), + inspector.getMaxVectorSize() + ) + { + @Override + public long apply(double left, double right) + { + return Double.doubleToLongBits(left) & Double.doubleToLongBits(right); + } + } + ); + } + + public static ExprVectorProcessor bitwiseOr(Expr.VectorInputBindingInspector inspector, Expr left, Expr right) + { + return makeLongMathProcessor( + inspector, + left, + right, + () -> new LongOutLongsInFunctionVectorProcessor( + left.buildVectorized(inspector), + right.buildVectorized(inspector), + inspector.getMaxVectorSize() + ) + { + @Override + public long apply(long left, long right) + { + return left | right; + } + }, + () -> new LongOutLongDoubleInFunctionVectorProcessor( + left.buildVectorized(inspector), + right.buildVectorized(inspector), + inspector.getMaxVectorSize() + ) + { + @Override + public long apply(long left, double right) + { + return left | Double.doubleToLongBits(right); + } + }, + () -> new LongOutDoubleLongInFunctionVectorProcessor( + left.buildVectorized(inspector), + right.buildVectorized(inspector), + inspector.getMaxVectorSize() + ) + { + @Override + public long apply(double left, long right) + { + return Double.doubleToLongBits(left) | right; + } + }, + () -> new LongOutDoublesInFunctionVectorProcessor( + left.buildVectorized(inspector), + right.buildVectorized(inspector), + inspector.getMaxVectorSize() + ) + { + @Override + public long apply(double left, double right) + { + return Double.doubleToLongBits(left) | Double.doubleToLongBits(right); + } + } + ); + } + + public static ExprVectorProcessor bitwiseXor(Expr.VectorInputBindingInspector inspector, Expr left, Expr right) + { + return makeLongMathProcessor( + inspector, + left, + right, + () -> new LongOutLongsInFunctionVectorProcessor( + left.buildVectorized(inspector), + right.buildVectorized(inspector), + inspector.getMaxVectorSize() + ) + { + @Override + public long apply(long left, long right) + { + return left ^ right; + } + }, + () -> new LongOutLongDoubleInFunctionVectorProcessor( + left.buildVectorized(inspector), + right.buildVectorized(inspector), + inspector.getMaxVectorSize() + ) + { + @Override + public long apply(long left, double right) + { + return left ^ Double.doubleToLongBits(right); + } + }, + () -> new LongOutDoubleLongInFunctionVectorProcessor( + left.buildVectorized(inspector), + right.buildVectorized(inspector), + inspector.getMaxVectorSize() + ) + { + @Override + public long apply(double left, long right) + { + return Double.doubleToLongBits(left) ^ right; + } + }, + () -> new LongOutDoublesInFunctionVectorProcessor( + left.buildVectorized(inspector), + right.buildVectorized(inspector), + inspector.getMaxVectorSize() + ) + { + @Override + public long apply(double left, double right) + { + return Double.doubleToLongBits(left) ^ Double.doubleToLongBits(right); + } + } + ); + } + + public static ExprVectorProcessor bitwiseShiftLeft( + Expr.VectorInputBindingInspector inspector, + Expr left, + Expr right + ) + { + return makeLongMathProcessor( + inspector, + left, + right, + () -> new LongOutLongsInFunctionVectorProcessor( + left.buildVectorized(inspector), + right.buildVectorized(inspector), + inspector.getMaxVectorSize() + ) + { + @Override + public long apply(long left, long right) + { + return left << right; + } + }, + () -> new LongOutLongDoubleInFunctionVectorProcessor( + left.buildVectorized(inspector), + right.buildVectorized(inspector), + inspector.getMaxVectorSize() + ) + { + @Override + public long apply(long left, double right) + { + return left << Double.doubleToLongBits(right); + } + }, + () -> new LongOutDoubleLongInFunctionVectorProcessor( + left.buildVectorized(inspector), + right.buildVectorized(inspector), + inspector.getMaxVectorSize() + ) + { + @Override + public long apply(double left, long right) + { + return Double.doubleToLongBits(left) << right; + } + }, + () -> new LongOutDoublesInFunctionVectorProcessor( + left.buildVectorized(inspector), + right.buildVectorized(inspector), + inspector.getMaxVectorSize() + ) + { + @Override + public long apply(double left, double right) + { + return Double.doubleToLongBits(left) << Double.doubleToLongBits(right); + } + } + ); + } + public static ExprVectorProcessor bitwiseShiftRight( + Expr.VectorInputBindingInspector inspector, + Expr left, + Expr right + ) + { + return makeLongMathProcessor( + inspector, + left, + right, + () -> new LongOutLongsInFunctionVectorProcessor( + left.buildVectorized(inspector), + right.buildVectorized(inspector), + inspector.getMaxVectorSize() + ) + { + @Override + public long apply(long left, long right) + { + return left >> right; + } + }, + () -> new LongOutLongDoubleInFunctionVectorProcessor( + left.buildVectorized(inspector), + right.buildVectorized(inspector), + inspector.getMaxVectorSize() + ) + { + @Override + public long apply(long left, double right) + { + return left >> Double.doubleToLongBits(right); + } + }, + () -> new LongOutDoubleLongInFunctionVectorProcessor( + left.buildVectorized(inspector), + right.buildVectorized(inspector), + inspector.getMaxVectorSize() + ) + { + @Override + public long apply(double left, long right) + { + return Double.doubleToLongBits(left) >> right; + } + }, + () -> new LongOutDoublesInFunctionVectorProcessor( + left.buildVectorized(inspector), + right.buildVectorized(inspector), + inspector.getMaxVectorSize() + ) + { + @Override + public long apply(double left, double right) + { + return Double.doubleToLongBits(left) >> Double.doubleToLongBits(right); + } + } + ); + } private VectorMathProcessors() { diff --git a/core/src/test/java/org/apache/druid/math/expr/FunctionTest.java b/core/src/test/java/org/apache/druid/math/expr/FunctionTest.java index 3c5c214de657..c50f4eb49975 100644 --- a/core/src/test/java/org/apache/druid/math/expr/FunctionTest.java +++ b/core/src/test/java/org/apache/druid/math/expr/FunctionTest.java @@ -519,6 +519,31 @@ public void testLeast() assertExpr("least(1, null, 'A')", "1"); } + @Test + public void testBitwise() + { + assertExpr("bitwiseAnd(3, 1)", 1L); + assertExpr("bitwiseAnd(2, 1)", 0L); + assertExpr("bitwiseOr(3, 1)", 3L); + assertExpr("bitwiseOr(2, 1)", 3L); + assertExpr("bitwiseXor(3, 1)", 2L); + assertExpr("bitwiseXor(2, 1)", 3L); + assertExpr("bitwiseShiftLeft(2, 1)", 4L); + assertExpr("bitwiseShiftRight(2, 1)", 1L); + assertExpr("bitwiseAnd(bitwiseComplement(1), 7)", 6L); + assertExpr("bitwiseAnd('2', '1')", null); + assertExpr("bitwiseAnd(2, '1')", 0L); + + assertExpr("bitwiseOr(2.345, 1)", 4612462889363109315L); + assertExpr("bitwiseAnd(2.345, 2.0)", 4611686018427387904L); + assertExpr( + "bitwiseAnd(bitwiseConvertDouble(2.345), bitwiseConvertDouble(2.0))", + 4611686018427387904L + ); + assertExpr("bitwiseConvertDouble(bitwiseAnd(2.345, 2.0))", 2.0); + assertExpr("bitwiseConvertDouble(2.0)", 4611686018427387904L); + } + private void assertExpr(final String expression, @Nullable final Object expectedResult) { final Expr expr = Parser.parse(expression, ExprMacroTable.nil()); 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 72bc0c89d821..4977a7ed225a 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 @@ -137,7 +137,9 @@ public void testUnivariateMathFunctions() "tanh", "toDegrees", "toRadians", - "ulp" + "ulp", + "bitwiseComplement", + "bitwiseConvertDouble" }; final String[] templates = new String[]{"%s(l1)", "%s(d1)", "%s(pi())"}; testFunctions(types, templates, functions); @@ -156,7 +158,12 @@ public void testBivariateMathFunctions() "min", "nextAfter", "scalb", - "pow" + "pow", + "bitwiseAnd", + "bitwiseOr", + "bitwiseXor", + "bitwiseShiftLeft", + "bitwiseShiftRight" }; final String[] templates = new String[]{ "%s(d1, d2)", diff --git a/docs/misc/math-expr.md b/docs/misc/math-expr.md index da4ad64dd81c..7873c9ba1a32 100644 --- a/docs/misc/math-expr.md +++ b/docs/misc/math-expr.md @@ -119,12 +119,13 @@ See javadoc of java.lang.Math for detailed explanation for each function. |acos|acos(x) would return the arc cosine of x| |asin|asin(x) would return the arc sine of x| |atan|atan(x) would return the arc tangent of x| -|bitwiseAnd|bitwiseAnd(x,y) would return the result of x & y| -|bitwiseComplement|bitwiseComplement(x) would return the result of ~x| -|bitwiseOr|bitwiseOr(x,y) would return the result of x [PIPE] y | -|bitwiseShiftLeft|bitwiseShiftLeft(x,y) would return the result of x << y| -|bitwiseShiftRight|bitwiseShiftRight(x,y) would return the result of x >> y| -|bitwiseXor|bitwiseXor(x,y) would return the result of x ^ y| +|bitwiseAnd|bitwiseAnd(x,y) would return the result of x & y. Double values will be converted to their bit representation| +|bitwiseComplement|bitwiseComplement(x) would return the result of ~x. Double values will be converted to their bit representation| +|bitwiseConvertDouble|bitwiseConvertDouble(x) would convert the IEEE 754 floating-point "double" bits stored in a long into a double value if the input is a long, or the copy bits of a double value into a long if the input is a double.| +|bitwiseOr|bitwiseOr(x,y) would return the result of x [PIPE] y. Double values will be converted to their bit representation | +|bitwiseShiftLeft|bitwiseShiftLeft(x,y) would return the result of x << y. Double values will be converted to their bit representation| +|bitwiseShiftRight|bitwiseShiftRight(x,y) would return the result of x >> y. Double values will be converted to their bit representation| +|bitwiseXor|bitwiseXor(x,y) would return the result of x ^ y. Double values will be converted to their bit representation| |atan2|atan2(y, x) would return the angle theta from the conversion of rectangular coordinates (x, y) to polar * coordinates (r, theta)| |cbrt|cbrt(x) would return the cube root of x| |ceil|ceil(x) would return the smallest (closest to negative infinity) double value that is greater than or equal to x and is equal to a mathematical integer| @@ -140,7 +141,7 @@ See javadoc of java.lang.Math for detailed explanation for each function. |hypot|hypot(x, y) would return sqrt(x^2+y^2) without intermediate overflow or underflow| |log|log(x) would return the natural logarithm of x| |log10|log10(x) would return the base 10 logarithm of x| -|log1p|log1p(x) would the natural logarithm of x + 1| +|log1p|log1p(x) would the natural logarithm of x + 1| |max|max(x, y) would return the greater of two values| |min|min(x, y) would return the smaller of two values| |nextafter|nextafter(x, y) would return the floating-point number adjacent to the x in the direction of the y| diff --git a/website/.spelling b/website/.spelling index a1e5dfdf3956..0823e8d86bce 100644 --- a/website/.spelling +++ b/website/.spelling @@ -1076,6 +1076,13 @@ array_to_string asin atan atan2 +bitwiseAnd +bitwiseComplement +bitwiseConvertDouble +bitwiseOr +bitwiseShiftLeft +bitwiseShiftRight +bitwiseXor bloom_filter_test cartesian_fold cartesian_map diff --git a/website/package-lock.json b/website/package-lock.json index 2d56db94b0cf..4421f38ce6af 100644 --- a/website/package-lock.json +++ b/website/package-lock.json @@ -4201,8 +4201,7 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "aproba": { "version": "1.2.0", @@ -4223,14 +4222,12 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, - "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -4245,20 +4242,17 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "core-util-is": { "version": "1.0.2", @@ -4375,8 +4369,7 @@ "inherits": { "version": "2.0.4", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "ini": { "version": "1.3.5", @@ -4388,7 +4381,6 @@ "version": "1.0.0", "bundled": true, "dev": true, - "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -4403,7 +4395,6 @@ "version": "3.0.4", "bundled": true, "dev": true, - "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -4411,14 +4402,12 @@ "minimist": { "version": "1.2.5", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "minipass": { "version": "2.9.0", "bundled": true, "dev": true, - "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -4437,7 +4426,6 @@ "version": "0.5.3", "bundled": true, "dev": true, - "optional": true, "requires": { "minimist": "^1.2.5" } @@ -4499,8 +4487,7 @@ "npm-normalize-package-bin": { "version": "1.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "npm-packlist": { "version": "1.4.8", @@ -4528,8 +4515,7 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "object-assign": { "version": "4.1.1", @@ -4541,7 +4527,6 @@ "version": "1.4.0", "bundled": true, "dev": true, - "optional": true, "requires": { "wrappy": "1" } @@ -4619,8 +4604,7 @@ "safe-buffer": { "version": "5.1.2", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "safer-buffer": { "version": "2.1.2", @@ -4656,7 +4640,6 @@ "version": "1.0.2", "bundled": true, "dev": true, - "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -4676,7 +4659,6 @@ "version": "3.0.1", "bundled": true, "dev": true, - "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -4720,14 +4702,12 @@ "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "yallist": { "version": "3.1.1", "bundled": true, - "dev": true, - "optional": true + "dev": true } } }, From ecc103ade747d4212f775777efb4c1e3a0e2fc19 Mon Sep 17 00:00:00 2001 From: Clint Wylie Date: Wed, 25 Nov 2020 02:13:06 -0800 Subject: [PATCH 3/9] move conversion to Evals --- .../org/apache/druid/math/expr/Evals.java | 10 +++++ .../org/apache/druid/math/expr/Function.java | 10 ++--- .../expr/vector/VectorMathProcessors.java | 37 ++++++++++--------- 3 files changed, 34 insertions(+), 23 deletions(-) diff --git a/core/src/main/java/org/apache/druid/math/expr/Evals.java b/core/src/main/java/org/apache/druid/math/expr/Evals.java index f6e3e4f74c85..0ac050a71a5e 100644 --- a/core/src/main/java/org/apache/druid/math/expr/Evals.java +++ b/core/src/main/java/org/apache/druid/math/expr/Evals.java @@ -71,4 +71,14 @@ public static boolean asBoolean(@Nullable String x) { return !NullHandling.isNullOrEquivalent(x) && Boolean.parseBoolean(x); } + + public static long doubleToLongBits(double x) + { + return Double.doubleToLongBits(x); + } + + public static double longBitsToDouble(long x) + { + return Double.longBitsToDouble(x); + } } 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 ab6d309278d8..0159edf51c38 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 @@ -327,8 +327,8 @@ protected final ExprEval eval(ExprEval x, ExprEval y) if (type == ExprType.STRING) { return ExprEval.of(null); } - final long xlong = ExprType.DOUBLE.equals(x.type()) ? Double.doubleToLongBits(x.asDouble()) : x.asLong(); - final long ylong = ExprType.DOUBLE.equals(y.type()) ? Double.doubleToLongBits(y.asDouble()) : y.asLong(); + final long xlong = ExprType.DOUBLE.equals(x.type()) ? Evals.doubleToLongBits(x.asDouble()) : x.asLong(); + final long ylong = ExprType.DOUBLE.equals(y.type()) ? Evals.doubleToLongBits(y.asDouble()) : y.asLong(); return eval(xlong, ylong); } @@ -784,7 +784,7 @@ protected ExprEval eval(long param) @Override protected ExprEval eval(double param) { - return ExprEval.of(~Double.doubleToLongBits(param)); + return ExprEval.of(~Evals.doubleToLongBits(param)); } @Override @@ -819,13 +819,13 @@ public ExprType getOutputType(Expr.InputBindingInspector inspector, List a @Override protected ExprEval eval(long param) { - return ExprEval.of(Double.longBitsToDouble(param)); + return ExprEval.of(Evals.longBitsToDouble(param)); } @Override protected ExprEval eval(double param) { - return ExprEval.of(Double.doubleToLongBits(param)); + return ExprEval.of(Evals.doubleToLongBits(param)); } @Override 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 3ff573c6727e..f976df7d9bb7 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 @@ -21,6 +21,7 @@ import com.google.common.math.LongMath; import com.google.common.primitives.Ints; +import org.apache.druid.math.expr.Evals; import org.apache.druid.math.expr.Expr; import org.apache.druid.math.expr.ExprType; import org.apache.druid.math.expr.Exprs; @@ -1992,7 +1993,7 @@ public long apply(long input) @Override public long apply(double input) { - return ~Double.doubleToLongBits(input); + return ~Evals.doubleToLongBits(input); } } ); @@ -2012,7 +2013,7 @@ public static ExprVectorProcessor bitwiseConvertDouble(Expr.VectorInputBi @Override public double apply(long input) { - return Double.longBitsToDouble(input); + return Evals.longBitsToDouble(input); } }; } else if (inputType == ExprType.DOUBLE) { @@ -2024,7 +2025,7 @@ public double apply(long input) @Override public long apply(double input) { - return Double.doubleToLongBits(input); + return Evals.doubleToLongBits(input); } }; } @@ -2061,7 +2062,7 @@ public long apply(long left, long right) @Override public long apply(long left, double right) { - return left & Double.doubleToLongBits(right); + return left & Evals.doubleToLongBits(right); } }, () -> new LongOutDoubleLongInFunctionVectorProcessor( @@ -2073,7 +2074,7 @@ public long apply(long left, double right) @Override public long apply(double left, long right) { - return Double.doubleToLongBits(left) & right; + return Evals.doubleToLongBits(left) & right; } }, () -> new LongOutDoublesInFunctionVectorProcessor( @@ -2085,7 +2086,7 @@ public long apply(double left, long right) @Override public long apply(double left, double right) { - return Double.doubleToLongBits(left) & Double.doubleToLongBits(right); + return Evals.doubleToLongBits(left) & Evals.doubleToLongBits(right); } } ); @@ -2118,7 +2119,7 @@ public long apply(long left, long right) @Override public long apply(long left, double right) { - return left | Double.doubleToLongBits(right); + return left | Evals.doubleToLongBits(right); } }, () -> new LongOutDoubleLongInFunctionVectorProcessor( @@ -2130,7 +2131,7 @@ public long apply(long left, double right) @Override public long apply(double left, long right) { - return Double.doubleToLongBits(left) | right; + return Evals.doubleToLongBits(left) | right; } }, () -> new LongOutDoublesInFunctionVectorProcessor( @@ -2142,7 +2143,7 @@ public long apply(double left, long right) @Override public long apply(double left, double right) { - return Double.doubleToLongBits(left) | Double.doubleToLongBits(right); + return Evals.doubleToLongBits(left) | Evals.doubleToLongBits(right); } } ); @@ -2175,7 +2176,7 @@ public long apply(long left, long right) @Override public long apply(long left, double right) { - return left ^ Double.doubleToLongBits(right); + return left ^ Evals.doubleToLongBits(right); } }, () -> new LongOutDoubleLongInFunctionVectorProcessor( @@ -2187,7 +2188,7 @@ public long apply(long left, double right) @Override public long apply(double left, long right) { - return Double.doubleToLongBits(left) ^ right; + return Evals.doubleToLongBits(left) ^ right; } }, () -> new LongOutDoublesInFunctionVectorProcessor( @@ -2199,7 +2200,7 @@ public long apply(double left, long right) @Override public long apply(double left, double right) { - return Double.doubleToLongBits(left) ^ Double.doubleToLongBits(right); + return Evals.doubleToLongBits(left) ^ Evals.doubleToLongBits(right); } } ); @@ -2236,7 +2237,7 @@ public long apply(long left, long right) @Override public long apply(long left, double right) { - return left << Double.doubleToLongBits(right); + return left << Evals.doubleToLongBits(right); } }, () -> new LongOutDoubleLongInFunctionVectorProcessor( @@ -2248,7 +2249,7 @@ public long apply(long left, double right) @Override public long apply(double left, long right) { - return Double.doubleToLongBits(left) << right; + return Evals.doubleToLongBits(left) << right; } }, () -> new LongOutDoublesInFunctionVectorProcessor( @@ -2260,7 +2261,7 @@ public long apply(double left, long right) @Override public long apply(double left, double right) { - return Double.doubleToLongBits(left) << Double.doubleToLongBits(right); + return Evals.doubleToLongBits(left) << Evals.doubleToLongBits(right); } } ); @@ -2297,7 +2298,7 @@ public long apply(long left, long right) @Override public long apply(long left, double right) { - return left >> Double.doubleToLongBits(right); + return left >> Evals.doubleToLongBits(right); } }, () -> new LongOutDoubleLongInFunctionVectorProcessor( @@ -2309,7 +2310,7 @@ public long apply(long left, double right) @Override public long apply(double left, long right) { - return Double.doubleToLongBits(left) >> right; + return Evals.doubleToLongBits(left) >> right; } }, () -> new LongOutDoublesInFunctionVectorProcessor( @@ -2321,7 +2322,7 @@ public long apply(double left, long right) @Override public long apply(double left, double right) { - return Double.doubleToLongBits(left) >> Double.doubleToLongBits(right); + return Evals.doubleToLongBits(left) >> Evals.doubleToLongBits(right); } } ); From 1b5269b3892105463d516855b535dc427adbc8d7 Mon Sep 17 00:00:00 2001 From: Clint Wylie Date: Wed, 25 Nov 2020 02:21:55 -0800 Subject: [PATCH 4/9] revert unintended changes --- docs/misc/math-expr.md | 2 +- website/package-lock.json | 44 ++++++++++++++++++++++++++++----------- 2 files changed, 33 insertions(+), 13 deletions(-) diff --git a/docs/misc/math-expr.md b/docs/misc/math-expr.md index 7873c9ba1a32..6ae44ff39dbc 100644 --- a/docs/misc/math-expr.md +++ b/docs/misc/math-expr.md @@ -141,7 +141,7 @@ See javadoc of java.lang.Math for detailed explanation for each function. |hypot|hypot(x, y) would return sqrt(x^2+y^2) without intermediate overflow or underflow| |log|log(x) would return the natural logarithm of x| |log10|log10(x) would return the base 10 logarithm of x| -|log1p|log1p(x) would the natural logarithm of x + 1| +|log1p|log1p(x) would the natural logarithm of x + 1| |max|max(x, y) would return the greater of two values| |min|min(x, y) would return the smaller of two values| |nextafter|nextafter(x, y) would return the floating-point number adjacent to the x in the direction of the y| diff --git a/website/package-lock.json b/website/package-lock.json index 4421f38ce6af..2d56db94b0cf 100644 --- a/website/package-lock.json +++ b/website/package-lock.json @@ -4201,7 +4201,8 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "aproba": { "version": "1.2.0", @@ -4222,12 +4223,14 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, + "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -4242,17 +4245,20 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "core-util-is": { "version": "1.0.2", @@ -4369,7 +4375,8 @@ "inherits": { "version": "2.0.4", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "ini": { "version": "1.3.5", @@ -4381,6 +4388,7 @@ "version": "1.0.0", "bundled": true, "dev": true, + "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -4395,6 +4403,7 @@ "version": "3.0.4", "bundled": true, "dev": true, + "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -4402,12 +4411,14 @@ "minimist": { "version": "1.2.5", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "minipass": { "version": "2.9.0", "bundled": true, "dev": true, + "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -4426,6 +4437,7 @@ "version": "0.5.3", "bundled": true, "dev": true, + "optional": true, "requires": { "minimist": "^1.2.5" } @@ -4487,7 +4499,8 @@ "npm-normalize-package-bin": { "version": "1.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "npm-packlist": { "version": "1.4.8", @@ -4515,7 +4528,8 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "object-assign": { "version": "4.1.1", @@ -4527,6 +4541,7 @@ "version": "1.4.0", "bundled": true, "dev": true, + "optional": true, "requires": { "wrappy": "1" } @@ -4604,7 +4619,8 @@ "safe-buffer": { "version": "5.1.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "safer-buffer": { "version": "2.1.2", @@ -4640,6 +4656,7 @@ "version": "1.0.2", "bundled": true, "dev": true, + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -4659,6 +4676,7 @@ "version": "3.0.1", "bundled": true, "dev": true, + "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -4702,12 +4720,14 @@ "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "yallist": { "version": "3.1.1", "bundled": true, - "dev": true + "dev": true, + "optional": true } } }, From 85e30745167b02585a00a378635102c42db49573 Mon Sep 17 00:00:00 2001 From: Clint Wylie Date: Fri, 8 Jan 2021 18:15:00 -0800 Subject: [PATCH 5/9] less magic, split convert functions, fix parser for funny exponent doubles --- .../org/apache/druid/math/expr/antlr/Expr.g4 | 7 +- .../org/apache/druid/math/expr/Evals.java | 10 --- .../org/apache/druid/math/expr/Function.java | 51 +++++++---- .../expr/vector/VectorMathProcessors.java | 85 ++++++++++++++----- .../apache/druid/math/expr/FunctionTest.java | 20 +++-- .../apache/druid/math/expr/ParserTest.java | 43 ++++++++++ .../druid/math/expr/VectorExprSanityTest.java | 3 +- docs/misc/math-expr.md | 15 ++-- 8 files changed, 169 insertions(+), 65 deletions(-) diff --git a/core/src/main/antlr4/org/apache/druid/math/expr/antlr/Expr.g4 b/core/src/main/antlr4/org/apache/druid/math/expr/antlr/Expr.g4 index db336a2d54e0..2d3441fce582 100644 --- a/core/src/main/antlr4/org/apache/druid/math/expr/antlr/Expr.g4 +++ b/core/src/main/antlr4/org/apache/druid/math/expr/antlr/Expr.g4 @@ -51,9 +51,12 @@ numericElement : (LONG | DOUBLE | NULL); literalElement : (STRING | LONG | DOUBLE | NULL); NULL : 'null'; +LONG : [0-9]+; +EXP: [eE] [-]? LONG; +// DOUBLE provides partial support for java double format +// see: https://docs.oracle.com/javase/8/docs/api/java/lang/Double.html#valueOf-java.lang.String- +DOUBLE : 'NaN' | 'Infinity' | (LONG '.' LONG) | (LONG EXP) | (LONG '.' LONG EXP); IDENTIFIER : [_$a-zA-Z][_$a-zA-Z0-9]* | '"' (ESC | ~ [\"\\])* '"'; -LONG : [0-9]+ ; -DOUBLE : [0-9]+ '.' [0-9]* ; WS : [ \t\r\n]+ -> skip ; STRING : '\'' (ESC | ~ [\'\\])* '\''; diff --git a/core/src/main/java/org/apache/druid/math/expr/Evals.java b/core/src/main/java/org/apache/druid/math/expr/Evals.java index 0ac050a71a5e..f6e3e4f74c85 100644 --- a/core/src/main/java/org/apache/druid/math/expr/Evals.java +++ b/core/src/main/java/org/apache/druid/math/expr/Evals.java @@ -71,14 +71,4 @@ public static boolean asBoolean(@Nullable String x) { return !NullHandling.isNullOrEquivalent(x) && Boolean.parseBoolean(x); } - - public static long doubleToLongBits(double x) - { - return Double.doubleToLongBits(x); - } - - public static double longBitsToDouble(long x) - { - return Double.longBitsToDouble(x); - } } 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 0159edf51c38..fef0776ecff3 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 @@ -327,9 +327,7 @@ protected final ExprEval eval(ExprEval x, ExprEval y) if (type == ExprType.STRING) { return ExprEval.of(null); } - final long xlong = ExprType.DOUBLE.equals(x.type()) ? Evals.doubleToLongBits(x.asDouble()) : x.asLong(); - final long ylong = ExprType.DOUBLE.equals(y.type()) ? Evals.doubleToLongBits(y.asDouble()) : y.asLong(); - return eval(xlong, ylong); + return eval(x.asLong(), y.asLong()); } protected abstract ExprEval eval(long x, long y); @@ -781,12 +779,6 @@ protected ExprEval eval(long param) return ExprEval.of(~param); } - @Override - protected ExprEval eval(double param) - { - return ExprEval.of(~Evals.doubleToLongBits(param)); - } - @Override public ExprVectorProcessor asVectorProcessor(Expr.VectorInputBindingInspector inspector, List args) { @@ -794,12 +786,12 @@ public ExprVectorProcessor asVectorProcessor(Expr.VectorInputBindingInspe } } - class BitwiseConvertDouble extends UnivariateMathFunction + class BitwiseConvertLongBitsToDouble extends UnivariateMathFunction { @Override public String name() { - return "bitwiseConvertDouble"; + return "bitwiseConvertLongBitsToDouble"; } @Nullable @@ -810,28 +802,51 @@ public ExprType getOutputType(Expr.InputBindingInspector inspector, List a if (type == null) { return null; } - if (type == ExprType.LONG) { - return ExprType.DOUBLE; - } - return ExprType.LONG; + return ExprType.DOUBLE; } @Override protected ExprEval eval(long param) { - return ExprEval.of(Evals.longBitsToDouble(param)); + return ExprEval.of(Double.longBitsToDouble(param)); + } + + @Override + public ExprVectorProcessor asVectorProcessor(Expr.VectorInputBindingInspector inspector, List args) + { + return VectorMathProcessors.bitwiseConvertLongBitsToDouble(inspector, args.get(0)); + } + } + + class BitwiseConvertDoubleToLongBits extends UnivariateMathFunction + { + @Override + public String name() + { + return "bitwiseConvertDoubleToLongBits"; + } + + @Nullable + @Override + public ExprType getOutputType(Expr.InputBindingInspector inspector, List args) + { + ExprType type = args.get(0).getOutputType(inspector); + if (type == null) { + return null; + } + return ExprType.LONG; } @Override protected ExprEval eval(double param) { - return ExprEval.of(Evals.doubleToLongBits(param)); + return ExprEval.of(Double.doubleToLongBits(param)); } @Override public ExprVectorProcessor asVectorProcessor(Expr.VectorInputBindingInspector inspector, List args) { - return VectorMathProcessors.bitwiseConvertDouble(inspector, args.get(0)); + return VectorMathProcessors.bitwiseConvertDoubleToLongBits(inspector, args.get(0)); } } 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 f976df7d9bb7..0a170ac24969 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 @@ -21,7 +21,6 @@ import com.google.common.math.LongMath; import com.google.common.primitives.Ints; -import org.apache.druid.math.expr.Evals; import org.apache.druid.math.expr.Expr; import org.apache.druid.math.expr.ExprType; import org.apache.druid.math.expr.Exprs; @@ -1993,27 +1992,30 @@ public long apply(long input) @Override public long apply(double input) { - return ~Evals.doubleToLongBits(input); + return ~((long) input); } } ); } - public static ExprVectorProcessor bitwiseConvertDouble(Expr.VectorInputBindingInspector inspector, Expr arg) + public static ExprVectorProcessor bitwiseConvertDoubleToLongBits( + Expr.VectorInputBindingInspector inspector, + Expr arg + ) { final ExprType inputType = arg.getOutputType(inspector); ExprVectorProcessor processor = null; if (inputType == ExprType.LONG) { - processor = new DoubleOutLongInFunctionVectorProcessor( + processor = new LongOutLongInFunctionVectorProcessor( arg.buildVectorized(inspector), inspector.getMaxVectorSize() ) { @Override - public double apply(long input) + public long apply(long input) { - return Evals.longBitsToDouble(input); + return Double.doubleToLongBits(input); } }; } else if (inputType == ExprType.DOUBLE) { @@ -2025,7 +2027,46 @@ public double apply(long input) @Override public long apply(double input) { - return Evals.doubleToLongBits(input); + return Double.doubleToLongBits(input); + } + }; + } + if (processor == null) { + throw Exprs.cannotVectorize(); + } + return (ExprVectorProcessor) processor; + } + + public static ExprVectorProcessor bitwiseConvertLongBitsToDouble( + Expr.VectorInputBindingInspector inspector, + Expr arg + ) + { + final ExprType inputType = arg.getOutputType(inspector); + + ExprVectorProcessor processor = null; + if (inputType == ExprType.LONG) { + processor = new DoubleOutLongInFunctionVectorProcessor( + arg.buildVectorized(inspector), + inspector.getMaxVectorSize() + ) + { + @Override + public double apply(long input) + { + return Double.longBitsToDouble(input); + } + }; + } else if (inputType == ExprType.DOUBLE) { + processor = new DoubleOutDoubleInFunctionVectorProcessor( + arg.buildVectorized(inspector), + inspector.getMaxVectorSize() + ) + { + @Override + public double apply(double input) + { + return Double.longBitsToDouble((long) input); } }; } @@ -2062,7 +2103,7 @@ public long apply(long left, long right) @Override public long apply(long left, double right) { - return left & Evals.doubleToLongBits(right); + return left & (long) right; } }, () -> new LongOutDoubleLongInFunctionVectorProcessor( @@ -2074,7 +2115,7 @@ public long apply(long left, double right) @Override public long apply(double left, long right) { - return Evals.doubleToLongBits(left) & right; + return (long) left & right; } }, () -> new LongOutDoublesInFunctionVectorProcessor( @@ -2086,7 +2127,7 @@ public long apply(double left, long right) @Override public long apply(double left, double right) { - return Evals.doubleToLongBits(left) & Evals.doubleToLongBits(right); + return (long) left & (long) right; } } ); @@ -2119,7 +2160,7 @@ public long apply(long left, long right) @Override public long apply(long left, double right) { - return left | Evals.doubleToLongBits(right); + return left | (long) right; } }, () -> new LongOutDoubleLongInFunctionVectorProcessor( @@ -2131,7 +2172,7 @@ public long apply(long left, double right) @Override public long apply(double left, long right) { - return Evals.doubleToLongBits(left) | right; + return (long) left | right; } }, () -> new LongOutDoublesInFunctionVectorProcessor( @@ -2143,7 +2184,7 @@ public long apply(double left, long right) @Override public long apply(double left, double right) { - return Evals.doubleToLongBits(left) | Evals.doubleToLongBits(right); + return (long) left | (long) right; } } ); @@ -2176,7 +2217,7 @@ public long apply(long left, long right) @Override public long apply(long left, double right) { - return left ^ Evals.doubleToLongBits(right); + return left ^ (long) right; } }, () -> new LongOutDoubleLongInFunctionVectorProcessor( @@ -2188,7 +2229,7 @@ public long apply(long left, double right) @Override public long apply(double left, long right) { - return Evals.doubleToLongBits(left) ^ right; + return (long) left ^ right; } }, () -> new LongOutDoublesInFunctionVectorProcessor( @@ -2200,7 +2241,7 @@ public long apply(double left, long right) @Override public long apply(double left, double right) { - return Evals.doubleToLongBits(left) ^ Evals.doubleToLongBits(right); + return (long) left ^ (long) right; } } ); @@ -2237,7 +2278,7 @@ public long apply(long left, long right) @Override public long apply(long left, double right) { - return left << Evals.doubleToLongBits(right); + return left << (long) right; } }, () -> new LongOutDoubleLongInFunctionVectorProcessor( @@ -2249,7 +2290,7 @@ public long apply(long left, double right) @Override public long apply(double left, long right) { - return Evals.doubleToLongBits(left) << right; + return (long) left << right; } }, () -> new LongOutDoublesInFunctionVectorProcessor( @@ -2261,7 +2302,7 @@ public long apply(double left, long right) @Override public long apply(double left, double right) { - return Evals.doubleToLongBits(left) << Evals.doubleToLongBits(right); + return (long) left << (long) right; } } ); @@ -2298,7 +2339,7 @@ public long apply(long left, long right) @Override public long apply(long left, double right) { - return left >> Evals.doubleToLongBits(right); + return left >> (long) right; } }, () -> new LongOutDoubleLongInFunctionVectorProcessor( @@ -2310,7 +2351,7 @@ public long apply(long left, double right) @Override public long apply(double left, long right) { - return Evals.doubleToLongBits(left) >> right; + return (long) left >> right; } }, () -> new LongOutDoublesInFunctionVectorProcessor( @@ -2322,7 +2363,7 @@ public long apply(double left, long right) @Override public long apply(double left, double right) { - return Evals.doubleToLongBits(left) >> Evals.doubleToLongBits(right); + return (long) left >> (long) right; } } ); diff --git a/core/src/test/java/org/apache/druid/math/expr/FunctionTest.java b/core/src/test/java/org/apache/druid/math/expr/FunctionTest.java index c50f4eb49975..96a22840eb04 100644 --- a/core/src/test/java/org/apache/druid/math/expr/FunctionTest.java +++ b/core/src/test/java/org/apache/druid/math/expr/FunctionTest.java @@ -534,14 +534,24 @@ public void testBitwise() assertExpr("bitwiseAnd('2', '1')", null); assertExpr("bitwiseAnd(2, '1')", 0L); - assertExpr("bitwiseOr(2.345, 1)", 4612462889363109315L); - assertExpr("bitwiseAnd(2.345, 2.0)", 4611686018427387904L); + // doubles are cast + assertExpr("bitwiseOr(2.345, 1)", 3L); + assertExpr("bitwiseOr(2, 1.3)", 3L); + assertExpr("bitwiseAnd(2.345, 2.0)", 2L); + + // but can be converted to be double-like assertExpr( - "bitwiseAnd(bitwiseConvertDouble(2.345), bitwiseConvertDouble(2.0))", + "bitwiseAnd(bitwiseConvertDoubleToLongBits(2.345), bitwiseConvertDoubleToLongBits(2.0))", 4611686018427387904L ); - assertExpr("bitwiseConvertDouble(bitwiseAnd(2.345, 2.0))", 2.0); - assertExpr("bitwiseConvertDouble(2.0)", 4611686018427387904L); + assertExpr( + "bitwiseConvertLongBitsToDouble(bitwiseAnd(bitwiseConvertDoubleToLongBits(2.345), bitwiseConvertDoubleToLongBits(2.0)))", + 2.0 + ); + assertExpr("bitwiseConvertDoubleToLongBits(2.0)", 4611686018427387904L); + assertExpr("bitwiseConvertDoubleToLongBits(bitwiseConvertDoubleToLongBits(2.0))", 4886405595696988160L); + assertExpr("bitwiseConvertLongBitsToDouble(4611686018427387904)", 2.0); + assertExpr("bitwiseConvertLongBitsToDouble(bitwiseConvertLongBitsToDouble(4611686018427387904))", 1.0E-323); } private void assertExpr(final String expression, @Nullable final Object expectedResult) diff --git a/core/src/test/java/org/apache/druid/math/expr/ParserTest.java b/core/src/test/java/org/apache/druid/math/expr/ParserTest.java index 1ebd71f1cc43..e8ebaa35ed1a 100644 --- a/core/src/test/java/org/apache/druid/math/expr/ParserTest.java +++ b/core/src/test/java/org/apache/druid/math/expr/ParserTest.java @@ -41,6 +41,8 @@ public class ParserTest extends InitializedNullHandlingTest @Rule public ExpectedException expectedException = ExpectedException.none(); + VectorExprSanityTest.SettableVectorInputBinding emptyBinding = new VectorExprSanityTest.SettableVectorInputBinding(8); + @Test public void testSimple() { @@ -49,6 +51,27 @@ public void testSimple() Assert.assertEquals(expected, actual); } + + @Test + public void testParseConstants() + { + validateLiteral("null", ExprType.STRING, null); + validateLiteral("'hello'", ExprType.STRING, "hello"); + validateLiteral("'hello \\uD83E\\uDD18'", ExprType.STRING, "hello \uD83E\uDD18"); + validateLiteral("1", ExprType.LONG, 1L); + validateLiteral("1.234", ExprType.DOUBLE, 1.234); + validateLiteral("1e10", ExprType.DOUBLE, 1.0E10, false); + validateLiteral("1e-10", ExprType.DOUBLE, 1.0E-10, false); + validateLiteral("1E10", ExprType.DOUBLE, 1.0E10, false); + validateLiteral("1E-10", ExprType.DOUBLE, 1.0E-10, false); + validateLiteral("1.1e10", ExprType.DOUBLE, 1.1E10, false); + validateLiteral("1.1e-10", ExprType.DOUBLE, 1.1E-10, false); + validateLiteral("1.1E10", ExprType.DOUBLE, 1.1E10); + validateLiteral("1.1E-10", ExprType.DOUBLE, 1.1E-10); + validateLiteral("Infinity", ExprType.DOUBLE, Double.POSITIVE_INFINITY); + validateLiteral("NaN", ExprType.DOUBLE, Double.NaN); + } + @Test public void testSimpleUnaryOps1() { @@ -542,6 +565,26 @@ public void testUniquify() ); } + private void validateLiteral(String expr, ExprType type, Object expected) + { + validateLiteral(expr, type, expected, true); + } + + private void validateLiteral(String expr, ExprType type, Object expected, boolean roundTrip) + { + Expr parsed = Parser.parse(expr, ExprMacroTable.nil(), false); + Expr parsedFlat = Parser.parse(expr, ExprMacroTable.nil(), true); + Assert.assertTrue(parsed.isLiteral()); + Assert.assertTrue(parsedFlat.isLiteral()); + Assert.assertEquals(type, parsed.getOutputType(emptyBinding)); + Assert.assertEquals(type, parsedFlat.getOutputType(emptyBinding)); + Assert.assertEquals(expected, parsed.getLiteralValue()); + Assert.assertEquals(expected, parsedFlat.getLiteralValue()); + if (roundTrip) { + Assert.assertEquals(expr, parsed.stringify()); + Assert.assertEquals(expr, parsedFlat.stringify()); + } + } private void validateFlatten(String expression, String withoutFlatten, String withFlatten) { 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 4977a7ed225a..8c6a46cfd382 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 @@ -139,7 +139,8 @@ public void testUnivariateMathFunctions() "toRadians", "ulp", "bitwiseComplement", - "bitwiseConvertDouble" + "bitwiseConvertDoubleToLongBits", + "bitwiseConvertLongBitsToDouble" }; final String[] templates = new String[]{"%s(l1)", "%s(d1)", "%s(pi())"}; testFunctions(types, templates, functions); diff --git a/docs/misc/math-expr.md b/docs/misc/math-expr.md index 69d2602cc621..d3598013601a 100644 --- a/docs/misc/math-expr.md +++ b/docs/misc/math-expr.md @@ -119,13 +119,14 @@ See javadoc of java.lang.Math for detailed explanation for each function. |acos|acos(x) would return the arc cosine of x| |asin|asin(x) would return the arc sine of x| |atan|atan(x) would return the arc tangent of x| -|bitwiseAnd|bitwiseAnd(x,y) would return the result of x & y. Double values will be converted to their bit representation| -|bitwiseComplement|bitwiseComplement(x) would return the result of ~x. Double values will be converted to their bit representation| -|bitwiseConvertDouble|bitwiseConvertDouble(x) would convert the IEEE 754 floating-point "double" bits stored in a long into a double value if the input is a long, or the copy bits of a double value into a long if the input is a double.| -|bitwiseOr|bitwiseOr(x,y) would return the result of x [PIPE] y. Double values will be converted to their bit representation | -|bitwiseShiftLeft|bitwiseShiftLeft(x,y) would return the result of x << y. Double values will be converted to their bit representation| -|bitwiseShiftRight|bitwiseShiftRight(x,y) would return the result of x >> y. Double values will be converted to their bit representation| -|bitwiseXor|bitwiseXor(x,y) would return the result of x ^ y. Double values will be converted to their bit representation| +|bitwiseAnd|bitwiseAnd(x,y) would return the result of x & y. Double values will be implicitly cast to longs, use `bitwiseConvertDoubleToLongBits` to perform bitwise operations directly with doubles| +|bitwiseComplement|bitwiseComplement(x) would return the result of ~x. Double values will be implicitly cast to longs, use `bitwiseConvertDoubleToLongBits` to perform bitwise operations directly with doubles| +|bitwiseConvertDoubleToLongBits|bitwiseConvertDoubleToLongBits(x) would convert the IEEE 754 floating-point "double" bits stored in a long into a double value if the input is a long, or implicitly cast the value to a long if the input is a double| +|bitwiseConvertLongBitsToDouble|bitwiseConvertLongBitsToDouble(x) would convert a long to the IEEE 754 floating-point "double" specified by the bits stored in the long. A double input will be implicitly cast to a long| +|bitwiseOr|bitwiseOr(x,y) would return the result of x [PIPE] y. Double values will be implicitly cast to longs, use `bitwiseConvertDoubleToLongBits` to perform bitwise operations directly with doubles| +|bitwiseShiftLeft|bitwiseShiftLeft(x,y) would return the result of x << y. Double values will be implicitly cast to longs, use `bitwiseConvertDoubleToLongBits` to perform bitwise operations directly with doubles| +|bitwiseShiftRight|bitwiseShiftRight(x,y) would return the result of x >> y. Double values will be implicitly cast to longs, use `bitwiseConvertDoubleToLongBits` to perform bitwise operations directly with doubles| +|bitwiseXor|bitwiseXor(x,y) would return the result of x ^ y. Double values will be implicitly cast to longs, use `bitwiseConvertDoubleToLongBits` to perform bitwise operations directly with doubles| |atan2|atan2(y, x) would return the angle theta from the conversion of rectangular coordinates (x, y) to polar * coordinates (r, theta)| |cbrt|cbrt(x) would return the cube root of x| |ceil|ceil(x) would return the smallest (closest to negative infinity) double value that is greater than or equal to x and is equal to a mathematical integer| From d988512555c145cff650a8325e4f7616b273dbae Mon Sep 17 00:00:00 2001 From: Clint Wylie Date: Mon, 11 Jan 2021 18:14:37 -0800 Subject: [PATCH 6/9] fix spelling exceptions list --- website/.spelling | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/website/.spelling b/website/.spelling index 952f68209420..c72368abf0c5 100644 --- a/website/.spelling +++ b/website/.spelling @@ -1092,7 +1092,8 @@ atan atan2 bitwiseAnd bitwiseComplement -bitwiseConvertDouble +bitwiseConvertDoubleToLongBits +bitwiseConvertLongBitsToDouble bitwiseOr bitwiseShiftLeft bitwiseShiftRight From 72a452a2a1884cd9cfad998a23723040b9eac70e Mon Sep 17 00:00:00 2001 From: Clint Wylie Date: Tue, 12 Jan 2021 12:36:25 -0800 Subject: [PATCH 7/9] more spelling --- website/.spelling | 1 + 1 file changed, 1 insertion(+) diff --git a/website/.spelling b/website/.spelling index c72368abf0c5..6f7a1ff6c1e4 100644 --- a/website/.spelling +++ b/website/.spelling @@ -1090,6 +1090,7 @@ array_to_string asin atan atan2 +bitwise bitwiseAnd bitwiseComplement bitwiseConvertDoubleToLongBits From 58fb61757ca7b24f5e09d61048771dc84545f473 Mon Sep 17 00:00:00 2001 From: Clint Wylie Date: Wed, 20 Jan 2021 04:45:02 -0800 Subject: [PATCH 8/9] fix grammar, add more test, fix docs --- .../org/apache/druid/math/expr/antlr/Expr.g4 | 2 +- .../apache/druid/math/expr/ParserTest.java | 5 ++ docs/misc/math-expr.md | 88 +++++++++---------- 3 files changed, 50 insertions(+), 45 deletions(-) diff --git a/core/src/main/antlr4/org/apache/druid/math/expr/antlr/Expr.g4 b/core/src/main/antlr4/org/apache/druid/math/expr/antlr/Expr.g4 index 2d3441fce582..9b9eda9dfded 100644 --- a/core/src/main/antlr4/org/apache/druid/math/expr/antlr/Expr.g4 +++ b/core/src/main/antlr4/org/apache/druid/math/expr/antlr/Expr.g4 @@ -55,7 +55,7 @@ LONG : [0-9]+; EXP: [eE] [-]? LONG; // DOUBLE provides partial support for java double format // see: https://docs.oracle.com/javase/8/docs/api/java/lang/Double.html#valueOf-java.lang.String- -DOUBLE : 'NaN' | 'Infinity' | (LONG '.' LONG) | (LONG EXP) | (LONG '.' LONG EXP); +DOUBLE : 'NaN' | 'Infinity' | (LONG '.' LONG?) | (LONG EXP) | (LONG '.' LONG? EXP); IDENTIFIER : [_$a-zA-Z][_$a-zA-Z0-9]* | '"' (ESC | ~ [\"\\])* '"'; WS : [ \t\r\n]+ -> skip ; diff --git a/core/src/test/java/org/apache/druid/math/expr/ParserTest.java b/core/src/test/java/org/apache/druid/math/expr/ParserTest.java index e8ebaa35ed1a..4fd7c13e9afc 100644 --- a/core/src/test/java/org/apache/druid/math/expr/ParserTest.java +++ b/core/src/test/java/org/apache/druid/math/expr/ParserTest.java @@ -59,11 +59,16 @@ public void testParseConstants() validateLiteral("'hello'", ExprType.STRING, "hello"); validateLiteral("'hello \\uD83E\\uDD18'", ExprType.STRING, "hello \uD83E\uDD18"); validateLiteral("1", ExprType.LONG, 1L); + validateLiteral("1.", ExprType.DOUBLE, 1.0, false); validateLiteral("1.234", ExprType.DOUBLE, 1.234); validateLiteral("1e10", ExprType.DOUBLE, 1.0E10, false); validateLiteral("1e-10", ExprType.DOUBLE, 1.0E-10, false); validateLiteral("1E10", ExprType.DOUBLE, 1.0E10, false); validateLiteral("1E-10", ExprType.DOUBLE, 1.0E-10, false); + validateLiteral("1.E10", ExprType.DOUBLE, 1.0E10, false); + validateLiteral("1.E-10", ExprType.DOUBLE, 1.0E-10, false); + validateLiteral("1.e10", ExprType.DOUBLE, 1.0E10, false); + validateLiteral("1.e-10", ExprType.DOUBLE, 1.0E-10, false); validateLiteral("1.1e10", ExprType.DOUBLE, 1.1E10, false); validateLiteral("1.1e-10", ExprType.DOUBLE, 1.1E-10, false); validateLiteral("1.1E10", ExprType.DOUBLE, 1.1E10); diff --git a/docs/misc/math-expr.md b/docs/misc/math-expr.md index d3598013601a..6d7aba734581 100644 --- a/docs/misc/math-expr.md +++ b/docs/misc/math-expr.md @@ -115,53 +115,53 @@ See javadoc of java.lang.Math for detailed explanation for each function. |name|description| |----|-----------| -|abs|abs(x) would return the absolute value of x| -|acos|acos(x) would return the arc cosine of x| -|asin|asin(x) would return the arc sine of x| -|atan|atan(x) would return the arc tangent of x| -|bitwiseAnd|bitwiseAnd(x,y) would return the result of x & y. Double values will be implicitly cast to longs, use `bitwiseConvertDoubleToLongBits` to perform bitwise operations directly with doubles| -|bitwiseComplement|bitwiseComplement(x) would return the result of ~x. Double values will be implicitly cast to longs, use `bitwiseConvertDoubleToLongBits` to perform bitwise operations directly with doubles| -|bitwiseConvertDoubleToLongBits|bitwiseConvertDoubleToLongBits(x) would convert the IEEE 754 floating-point "double" bits stored in a long into a double value if the input is a long, or implicitly cast the value to a long if the input is a double| -|bitwiseConvertLongBitsToDouble|bitwiseConvertLongBitsToDouble(x) would convert a long to the IEEE 754 floating-point "double" specified by the bits stored in the long. A double input will be implicitly cast to a long| -|bitwiseOr|bitwiseOr(x,y) would return the result of x [PIPE] y. Double values will be implicitly cast to longs, use `bitwiseConvertDoubleToLongBits` to perform bitwise operations directly with doubles| -|bitwiseShiftLeft|bitwiseShiftLeft(x,y) would return the result of x << y. Double values will be implicitly cast to longs, use `bitwiseConvertDoubleToLongBits` to perform bitwise operations directly with doubles| -|bitwiseShiftRight|bitwiseShiftRight(x,y) would return the result of x >> y. Double values will be implicitly cast to longs, use `bitwiseConvertDoubleToLongBits` to perform bitwise operations directly with doubles| -|bitwiseXor|bitwiseXor(x,y) would return the result of x ^ y. Double values will be implicitly cast to longs, use `bitwiseConvertDoubleToLongBits` to perform bitwise operations directly with doubles| -|atan2|atan2(y, x) would return the angle theta from the conversion of rectangular coordinates (x, y) to polar * coordinates (r, theta)| -|cbrt|cbrt(x) would return the cube root of x| -|ceil|ceil(x) would return the smallest (closest to negative infinity) double value that is greater than or equal to x and is equal to a mathematical integer| -|copysign|copysign(x) would return the first floating-point argument with the sign of the second floating-point argument| -|cos|cos(x) would return the trigonometric cosine of x| -|cosh|cosh(x) would return the hyperbolic cosine of x| -|cot|cot(x) would return the trigonometric cotangent of an angle x| +|abs|abs(x) returns the absolute value of x| +|acos|acos(x) returns the arc cosine of x| +|asin|asin(x) returns the arc sine of x| +|atan|atan(x) returns the arc tangent of x| +|bitwiseAnd|bitwiseAnd(x,y) returns the result of x & y. Double values will be implicitly cast to longs, use `bitwiseConvertDoubleToLongBits` to perform bitwise operations directly with doubles| +|bitwiseComplement|bitwiseComplement(x) returns the result of ~x. Double values will be implicitly cast to longs, use `bitwiseConvertDoubleToLongBits` to perform bitwise operations directly with doubles| +|bitwiseConvertDoubleToLongBits|bitwiseConvertDoubleToLongBits(x) will convert the IEEE 754 floating-point "double" bits of a double value into a long, or implicitly cast the value to a double if the input is a long.| +|bitwiseConvertLongBitsToDouble|bitwiseConvertLongBitsToDouble(x) will convert a long to the IEEE 754 floating-point "double" specified by the bits stored in the long. A double input will be implicitly cast to a long| +|bitwiseOr|bitwiseOr(x,y) returns the result of x [PIPE] y. Double values will be implicitly cast to longs, use `bitwiseConvertDoubleToLongBits` to perform bitwise operations directly with doubles| +|bitwiseShiftLeft|bitwiseShiftLeft(x,y) returns the result of x << y. Double values will be implicitly cast to longs, use `bitwiseConvertDoubleToLongBits` to perform bitwise operations directly with doubles| +|bitwiseShiftRight|bitwiseShiftRight(x,y) returns the result of x >> y. Double values will be implicitly cast to longs, use `bitwiseConvertDoubleToLongBits` to perform bitwise operations directly with doubles| +|bitwiseXor|bitwiseXor(x,y) returns the result of x ^ y. Double values will be implicitly cast to longs, use `bitwiseConvertDoubleToLongBits` to perform bitwise operations directly with doubles| +|atan2|atan2(y, x) returns the angle theta from the conversion of rectangular coordinates (x, y) to polar * coordinates (r, theta)| +|cbrt|cbrt(x) returns the cube root of x| +|ceil|ceil(x) returns the smallest (closest to negative infinity) double value that is greater than or equal to x and is equal to a mathematical integer| +|copysign|copysign(x) returns the first floating-point argument with the sign of the second floating-point argument| +|cos|cos(x) returns the trigonometric cosine of x| +|cosh|cosh(x) returns the hyperbolic cosine of x| +|cot|cot(x) returns the trigonometric cotangent of an angle x| |div|div(x,y) is integer division of x by y| -|exp|exp(x) would return Euler's number raised to the power of x| -|expm1|expm1(x) would return e^x-1| -|floor|floor(x) would return the largest (closest to positive infinity) double value that is less than or equal to x and is equal to a mathematical integer| -|getExponent|getExponent(x) would return the unbiased exponent used in the representation of x| -|hypot|hypot(x, y) would return sqrt(x^2+y^2) without intermediate overflow or underflow| -|log|log(x) would return the natural logarithm of x| -|log10|log10(x) would return the base 10 logarithm of x| -|log1p|log1p(x) would the natural logarithm of x + 1| -|max|max(x, y) would return the greater of two values| -|min|min(x, y) would return the smaller of two values| -|nextafter|nextafter(x, y) would return the floating-point number adjacent to the x in the direction of the y| -|nextUp|nextUp(x) would return the floating-point value adjacent to x in the direction of positive infinity| -|pi|pi would return the constant value of the π | -|pow|pow(x, y) would return the value of the x raised to the power of y| -|remainder|remainder(x, y) would return the remainder operation on two arguments as prescribed by the IEEE 754 standard| -|rint|rint(x) would return value that is closest in value to x and is equal to a mathematical integer| -|round|round(x, y) would return the value of the x rounded to the y decimal places. While x can be an integer or floating-point number, y must be an integer. The type of the return value is specified by that of x. y defaults to 0 if omitted. When y is negative, x is rounded on the left side of the y decimal points. If x is `NaN`, x will return 0. If x is infinity, x will be converted to the nearest finite double. | -|scalb|scalb(d, sf) would return d * 2^sf rounded as if performed by a single correctly rounded floating-point multiply to a member of the double value set| -|signum|signum(x) would return the signum function of the argument x| -|sin|sin(x) would return the trigonometric sine of an angle x| -|sinh|sinh(x) would return the hyperbolic sine of x| -|sqrt|sqrt(x) would return the correctly rounded positive square root of x| -|tan|tan(x) would return the trigonometric tangent of an angle x| -|tanh|tanh(x) would return the hyperbolic tangent of x| +|exp|exp(x) returns Euler's number raised to the power of x| +|expm1|expm1(x) returns e^x-1| +|floor|floor(x) returns the largest (closest to positive infinity) double value that is less than or equal to x and is equal to a mathematical integer| +|getExponent|getExponent(x) returns the unbiased exponent used in the representation of x| +|hypot|hypot(x, y) returns sqrt(x^2+y^2) without intermediate overflow or underflow| +|log|log(x) returns the natural logarithm of x| +|log10|log10(x) returns the base 10 logarithm of x| +|log1p|log1p(x) will the natural logarithm of x + 1| +|max|max(x, y) returns the greater of two values| +|min|min(x, y) returns the smaller of two values| +|nextafter|nextafter(x, y) returns the floating-point number adjacent to the x in the direction of the y| +|nextUp|nextUp(x) returns the floating-point value adjacent to x in the direction of positive infinity| +|pi|pi returns the constant value of the π | +|pow|pow(x, y) returns the value of the x raised to the power of y| +|remainder|remainder(x, y) returns the remainder operation on two arguments as prescribed by the IEEE 754 standard| +|rint|rint(x) returns value that is closest in value to x and is equal to a mathematical integer| +|round|round(x, y) returns the value of the x rounded to the y decimal places. While x can be an integer or floating-point number, y must be an integer. The type of the return value is specified by that of x. y defaults to 0 if omitted. When y is negative, x is rounded on the left side of the y decimal points. If x is `NaN`, x returns 0. If x is infinity, x will be converted to the nearest finite double. | +|scalb|scalb(d, sf) returns d * 2^sf rounded as if performed by a single correctly rounded floating-point multiply to a member of the double value set| +|signum|signum(x) returns the signum function of the argument x| +|sin|sin(x) returns the trigonometric sine of an angle x| +|sinh|sinh(x) returns the hyperbolic sine of x| +|sqrt|sqrt(x) returns the correctly rounded positive square root of x| +|tan|tan(x) returns the trigonometric tangent of an angle x| +|tanh|tanh(x) returns the hyperbolic tangent of x| |todegrees|todegrees(x) converts an angle measured in radians to an approximately equivalent angle measured in degrees| |toradians|toradians(x) converts an angle measured in degrees to an approximately equivalent angle measured in radians| -|ulp|ulp(x) would return the size of an ulp of the argument x| +|ulp|ulp(x) returns the size of an ulp of the argument x| ## Array functions From 623e0b78ff3779e4a4941886d3a5176bf9ff845d Mon Sep 17 00:00:00 2001 From: Clint Wylie Date: Wed, 20 Jan 2021 13:29:33 -0800 Subject: [PATCH 9/9] fix docs --- docs/misc/math-expr.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/misc/math-expr.md b/docs/misc/math-expr.md index 6d7aba734581..0e902b05bc43 100644 --- a/docs/misc/math-expr.md +++ b/docs/misc/math-expr.md @@ -121,8 +121,8 @@ See javadoc of java.lang.Math for detailed explanation for each function. |atan|atan(x) returns the arc tangent of x| |bitwiseAnd|bitwiseAnd(x,y) returns the result of x & y. Double values will be implicitly cast to longs, use `bitwiseConvertDoubleToLongBits` to perform bitwise operations directly with doubles| |bitwiseComplement|bitwiseComplement(x) returns the result of ~x. Double values will be implicitly cast to longs, use `bitwiseConvertDoubleToLongBits` to perform bitwise operations directly with doubles| -|bitwiseConvertDoubleToLongBits|bitwiseConvertDoubleToLongBits(x) will convert the IEEE 754 floating-point "double" bits of a double value into a long, or implicitly cast the value to a double if the input is a long.| -|bitwiseConvertLongBitsToDouble|bitwiseConvertLongBitsToDouble(x) will convert a long to the IEEE 754 floating-point "double" specified by the bits stored in the long. A double input will be implicitly cast to a long| +|bitwiseConvertDoubleToLongBits|bitwiseConvertDoubleToLongBits(x) converts the bits of an IEEE 754 floating-point double value to a long. If the input is not a double, it is implicitly cast to a double prior to conversion| +|bitwiseConvertLongBitsToDouble|bitwiseConvertLongBitsToDouble(x) converts a long to the IEEE 754 floating-point double specified by the bits stored in the long. If the input is not a long, it is implicitly cast to a long prior to conversion| |bitwiseOr|bitwiseOr(x,y) returns the result of x [PIPE] y. Double values will be implicitly cast to longs, use `bitwiseConvertDoubleToLongBits` to perform bitwise operations directly with doubles| |bitwiseShiftLeft|bitwiseShiftLeft(x,y) returns the result of x << y. Double values will be implicitly cast to longs, use `bitwiseConvertDoubleToLongBits` to perform bitwise operations directly with doubles| |bitwiseShiftRight|bitwiseShiftRight(x,y) returns the result of x >> y. Double values will be implicitly cast to longs, use `bitwiseConvertDoubleToLongBits` to perform bitwise operations directly with doubles|