DRILL-247: Math Functions List of math functions : rand,cbrt, exp, log(a), log(a,base), pi, degrees, radians Code formatting Review Comments: Removed rand function, Moved pi away from codegen Implemented Decimal9 & Decimal18 support for math functions Drill:247: Code Cleanup
Project: http://git-wip-us.apache.org/repos/asf/incubator-drill/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-drill/commit/6b9a1c53 Tree: http://git-wip-us.apache.org/repos/asf/incubator-drill/tree/6b9a1c53 Diff: http://git-wip-us.apache.org/repos/asf/incubator-drill/diff/6b9a1c53 Branch: refs/heads/master Commit: 6b9a1c53ea60ac1896fa6224ddacde73bb830dfd Parents: c022b40 Author: Yash Sharma <[email protected]> Authored: Sun May 18 12:45:21 2014 +0530 Committer: Jacques Nadeau <[email protected]> Committed: Mon Jun 16 12:44:36 2014 -0700 ---------------------------------------------------------------------- .../src/main/codegen/data/MathFunc.tdd | 109 +++++++++++++++++- .../main/codegen/templates/MathFunctions.java | 110 +++++++++++++++++++ .../drill/exec/expr/fn/impl/MathFunctions.java | 14 +++ .../exec/fn/impl/TestNewMathFunctions.java | 13 +++ .../functions/testExtendedMathFunctions.json | 44 ++++++++ 5 files changed, 285 insertions(+), 5 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/6b9a1c53/exec/java-exec/src/main/codegen/data/MathFunc.tdd ---------------------------------------------------------------------- diff --git a/exec/java-exec/src/main/codegen/data/MathFunc.tdd b/exec/java-exec/src/main/codegen/data/MathFunc.tdd index e287122..8180141 100644 --- a/exec/java-exec/src/main/codegen/data/MathFunc.tdd +++ b/exec/java-exec/src/main/codegen/data/MathFunc.tdd @@ -14,8 +14,9 @@ # See the License for the specific language governing permissions and # limitations under the License. -{ - unaryMathFunctions : [ +{ + +unaryMathFunctions : [ {className: "Abs", funcName: "abs", javaFunc : "java.lang.Math.abs", types: [ {input: "Int", outputType: "Int", castType: "int"}, {input: "BigInt", outputType: "BigInt", castType: "long"}, @@ -106,7 +107,7 @@ {input: "UInt4", outputType: "Int", castType: "int"}, {input: "UInt8", outputType: "Int", castType: "int"} ] - } + } ], binaryMathFunctions : [ {className: "Div", funcName: "div", javaFunc : " / ", types: [ @@ -133,11 +134,109 @@ {input: "UInt2", outputType: "UInt2", castType: "char"}, {input: "UInt4", outputType: "UInt4", castType: "int"}, {input: "UInt8", outputType: "UInt8", castType: "long"} - ] + ] } - ], +logBaseMathFunction : [ + {className: "LogBase", funcName: "log", javaFunc : "java.lang.Math.log", outputType: "Float8", types: [ + {input: "Int"}, + {input: "BigInt"}, + {input: "Float4"}, + {input: "Float8"}, + {input: "SmallInt"}, + {input: "TinyInt"}, + {input: "UInt1"}, + {input: "UInt2"}, + {input: "UInt4"}, + {input: "UInt8"}, + {input: "Decimal9"}, + {input: "Decimal18"} + ] + } +], +extendedUnaryMathFunctions : [ + {className: "Cbrt", funcName: "cbrt", javaFunc : "java.lang.Math.cbrt", outputType: "Float8", types: [ + {input: "Int"}, + {input: "BigInt"}, + {input: "Float4"}, + {input: "Float8"}, + {input: "SmallInt"}, + {input: "TinyInt"}, + {input: "UInt1"}, + {input: "UInt2"}, + {input: "UInt4"}, + {input: "UInt8"}, + {input: "Decimal9"}, + {input: "Decimal18"} + ] + }, + + {className: "Exp", funcName: "exp", javaFunc : "java.lang.Math.exp", outputType: "Float8", types: [ + {input: "Int"}, + {input: "BigInt"}, + {input: "Float4"}, + {input: "Float8"}, + {input: "SmallInt"}, + {input: "TinyInt"}, + {input: "UInt1"}, + {input: "UInt2"}, + {input: "UInt4"}, + {input: "UInt8"}, + {input: "Decimal9"}, + {input: "Decimal18"} + ] + }, + + {className: "Log", funcName: "log", javaFunc : "java.lang.Math.log", outputType: "Float8", types: [ + {input: "Int"}, + {input: "BigInt"}, + {input: "Float4"}, + {input: "Float8"}, + {input: "SmallInt"}, + {input: "TinyInt"}, + {input: "UInt1"}, + {input: "UInt2"}, + {input: "UInt4"}, + {input: "UInt8"}, + {input: "Decimal9"}, + {input: "Decimal18"} + ] + }, + +{className: "Degrees", funcName: "degrees", javaFunc : "java.lang.Math.toDegrees", outputType: "Float8", types: [ + {input: "Int"}, + {input: "BigInt"}, + {input: "Float4"}, + {input: "Float8"}, + {input: "SmallInt"}, + {input: "TinyInt"}, + {input: "UInt1"}, + {input: "UInt2"}, + {input: "UInt4"}, + {input: "UInt8"}, + {input: "Decimal9"}, + {input: "Decimal18"} + ] + }, + +{className: "Radians", funcName: "radians", javaFunc : "java.lang.Math.toRadians", outputType: "Float8", types: [ + {input: "Int"}, + {input: "BigInt"}, + {input: "Float4"}, + {input: "Float8"}, + {input: "SmallInt"}, + {input: "TinyInt"}, + {input: "UInt1"}, + {input: "UInt2"}, + {input: "UInt4"}, + {input: "UInt8"}, + {input: "Decimal9"}, + {input: "Decimal18"} + ] + } +], + trigoMathFunctions : [ {className: "Sin", funcName: "sin", javaFunc : "java.lang.Math.sin", outputType: "Float8", types: [ {input: "Int"}, http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/6b9a1c53/exec/java-exec/src/main/codegen/templates/MathFunctions.java ---------------------------------------------------------------------- diff --git a/exec/java-exec/src/main/codegen/templates/MathFunctions.java b/exec/java-exec/src/main/codegen/templates/MathFunctions.java index ac7cedb..d1ba6e8 100644 --- a/exec/java-exec/src/main/codegen/templates/MathFunctions.java +++ b/exec/java-exec/src/main/codegen/templates/MathFunctions.java @@ -29,6 +29,8 @@ package org.apache.drill.exec.expr.fn.impl; +import java.math.BigDecimal; + import org.apache.drill.common.types.TypeProtos; import org.apache.drill.common.types.Types; import org.apache.drill.common.types.TypeProtos.MinorType; @@ -98,10 +100,118 @@ public class GMathFunctions{ </#list> } + + ////////////////////////////////////////////////////////////////////////////////////////////////// //End of GMath Functions ////////////////////////////////////////////////////////////////////////////////////////////////// + + + +<@pp.changeOutputFile name="/org/apache/drill/exec/expr/fn/impl/ExtendedMathFunctions.java" /> +<#include "/@includes/license.ftl" /> + +////////////////////////////////////////////////////////////////////////////////////////////////// +//Functions for Extended Math Functions +////////////////////////////////////////////////////////////////////////////////////////////////// + + +package org.apache.drill.exec.expr.fn.impl; + +import org.apache.drill.common.types.TypeProtos; +import org.apache.drill.common.types.Types; +import org.apache.drill.common.types.TypeProtos.MinorType; +import org.apache.drill.exec.expr.DrillSimpleFunc; +import org.apache.drill.exec.expr.annotations.FunctionTemplate; +import org.apache.drill.exec.expr.annotations.FunctionTemplate.FunctionScope; +import org.apache.drill.exec.expr.annotations.FunctionTemplate.FunctionScope; +import org.apache.drill.exec.expr.annotations.FunctionTemplate.NullHandling; +import org.apache.drill.exec.expr.annotations.Output; +import org.apache.drill.exec.expr.annotations.Param; +import org.apache.drill.exec.expr.annotations.Workspace; +import org.apache.drill.exec.expr.fn.impl.StringFunctions; +import org.apache.drill.exec.expr.holders.*; +import org.apache.drill.exec.record.RecordBatch; +import java.math.BigDecimal; +/* + * This class is automatically generated from MathFunc.tdd using FreeMarker. + */ + +@SuppressWarnings("unused") + +public class ExtendedMathFunctions{ + static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(ExtendedMathFunctions.class); + + private ExtendedMathFunctions(){} + +////////////////////////////////////////////////////////////////////////////////////////////////// +//Unary Math functions with 1 parameter. +////////////////////////////////////////////////////////////////////////////////////////////////// + +<#list mathFunc.extendedUnaryMathFunctions as func> + +<#list func.types as type> + +@FunctionTemplate(name = "${func.funcName}", scope = FunctionScope.SIMPLE, nulls = NullHandling.NULL_IF_NULL) +public static class ${func.className}${type.input} implements DrillSimpleFunc { + + @Param ${type.input}Holder in; + @Output ${func.outputType}Holder out; + + public void setup(RecordBatch b) { + } + + public void eval() { + <#if type.input?matches("^Decimal[1-9]*")> + double dblval = new BigDecimal(in.value).setScale(in.scale).doubleValue(); + out.value = ${func.javaFunc}(dblval); + <#else> + out.value = ${func.javaFunc}(in.value); + </#if> + } +} + +</#list> +</#list> + + +////////////////////////////////////////////////////////////////////////////////////////////////// +//Function to handle Log with base. +////////////////////////////////////////////////////////////////////////////////////////////////// +<#list mathFunc.logBaseMathFunction as func> +<#list func.types as type> + +@FunctionTemplate(name = "${func.funcName}", scope = FunctionScope.SIMPLE, nulls = NullHandling.NULL_IF_NULL) +public static class ${func.className}${type.input} implements DrillSimpleFunc { + + @Param ${type.input}Holder base; + @Param ${type.input}Holder val; + @Output ${func.outputType}Holder out; + + public void setup(RecordBatch b) { + } + + public void eval() { + <#if type.input?matches("^Decimal[1-9]*")> + double dblval = new BigDecimal(val.value).setScale(val.scale).doubleValue(); + out.value = ${func.javaFunc}(dblval)/ ${func.javaFunc}(base.value); + <#else> + out.value = ${func.javaFunc}(val.value)/ ${func.javaFunc}(base.value); + </#if> + } +} +</#list> +</#list> + + +} + +////////////////////////////////////////////////////////////////////////////////////////////////// +//End of Extended Math Functions +////////////////////////////////////////////////////////////////////////////////////////////////// + + <@pp.changeOutputFile name="/org/apache/drill/exec/expr/fn/impl/TrigoMathFunctions.java" /> <#include "/@includes/license.ftl" /> http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/6b9a1c53/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/MathFunctions.java ---------------------------------------------------------------------- diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/MathFunctions.java b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/MathFunctions.java index 7d5a3a6..0492a6e 100644 --- a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/MathFunctions.java +++ b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/MathFunctions.java @@ -112,4 +112,18 @@ public class MathFunctions{ out.value = (roundedValue.setScale(decimalDigits, java.math.BigDecimal.ROUND_HALF_UP)).doubleValue(); } } + + @FunctionTemplate(name = "pi", scope = FunctionScope.SIMPLE, nulls = NullHandling.NULL_IF_NULL) + public static class Pi implements DrillSimpleFunc { + + @Output Float8Holder out; + + public void setup(RecordBatch b) { + } + + public void eval() { + out.value = java.lang.Math.PI; + } + } + } http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/6b9a1c53/exec/java-exec/src/test/java/org/apache/drill/exec/fn/impl/TestNewMathFunctions.java ---------------------------------------------------------------------- diff --git a/exec/java-exec/src/test/java/org/apache/drill/exec/fn/impl/TestNewMathFunctions.java b/exec/java-exec/src/test/java/org/apache/drill/exec/fn/impl/TestNewMathFunctions.java index 3a67d31..3289601 100644 --- a/exec/java-exec/src/test/java/org/apache/drill/exec/fn/impl/TestNewMathFunctions.java +++ b/exec/java-exec/src/test/java/org/apache/drill/exec/fn/impl/TestNewMathFunctions.java @@ -20,6 +20,9 @@ package org.apache.drill.exec.fn.impl; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; + +import java.math.BigDecimal; + import mockit.Injectable; import mockit.NonStrictExpectations; @@ -116,4 +119,14 @@ public class TestNewMathFunctions { Object [] expected = new Object[] {Math.sin(45), Math.cos(45), Math.tan(45),Math.asin(45), Math.acos(45), Math.atan(45),Math.sinh(45), Math.cosh(45), Math.tanh(45)}; runTest(bitContext, connection, expected, "functions/testTrigoMathFunctions.json"); } + + @Test + public void testExtendedMathFunc(@Injectable final DrillbitContext bitContext, + @Injectable UserServer.UserClientConnection connection) throws Throwable{ + BigDecimal d = new BigDecimal("100111111111111111111111111111111111.00000000000000000000000000000000000000000000000000001"); + + Object [] expected = new Object[] {Math.cbrt(1000), Math.log(10), (Math.log(64.0)/Math.log(2.0)), Math.exp(10), Math.toDegrees(0.5), Math.toRadians(45.0), Math.PI, Math.cbrt(d.doubleValue()), Math.log(d.doubleValue()), (Math.log(d.doubleValue())/Math.log(2)), Math.exp(d.doubleValue()), Math.toDegrees(d.doubleValue()), Math.toRadians(d.doubleValue())}; + + runTest(bitContext, connection, expected, "functions/testExtendedMathFunctions.json"); + } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/6b9a1c53/exec/java-exec/src/test/resources/functions/testExtendedMathFunctions.json ---------------------------------------------------------------------- diff --git a/exec/java-exec/src/test/resources/functions/testExtendedMathFunctions.json b/exec/java-exec/src/test/resources/functions/testExtendedMathFunctions.json new file mode 100644 index 0000000..9814cf6 --- /dev/null +++ b/exec/java-exec/src/test/resources/functions/testExtendedMathFunctions.json @@ -0,0 +1,44 @@ +{ + head : { + version : 1, + generator : { + type : "optiq", + info : "na" + }, + type : "APACHE_DRILL_PHYSICAL" + }, + graph:[ + { + @id:1, + pop:"mock-sub-scan", + url: "http://apache.org", + entries:[ + {records: 1, types: [ + {name: "blue", type: "BIGINT", mode: "REQUIRED"} + ]} + ] + }, { + pop : "project", + @id : 2, + exprs : [ + { ref : "CBRTVAL", expr : " cbrt(1000) "}, + { ref : "LOGVAL", expr : " log(10) "}, + { ref : "LOGVALBASE", expr : " log(2.0, 64.0) "}, + { ref : "EXP", expr : " exp(10) "}, + { ref : "DEGREES", expr : " degrees(0.5) "}, + { ref : "RADIANS", expr : " radians(45.0) "}, + { ref : "PIVAL", expr : " pi() " }, + { ref : "CBRTVAL", expr : " cbrt(100111111111111111111111111111111111.00000000000000000000000000000000000000000000000000001) "}, + { ref : "LOGVAL", expr : " log(100111111111111111111111111111111111.00000000000000000000000000000000000000000000000000001) "}, + { ref : "LOGVALBASE", expr : " log(2, 100111111111111111111111111111111111.00000000000000000000000000000000000000000000000000001) "}, + { ref : "EXP", expr : " exp(100111111111111111111111111111111111.00000000000000000000000000000000000000000000000000001) "}, + { ref : "DEGREES", expr : " degrees(100111111111111111111111111111111111.00000000000000000000000000000000000000000000000000001) "}, + { ref : "RADIANS", expr : " radians(100111111111111111111111111111111111.00000000000000000000000000000000000000000000000000001) "} + ], + child : 1 + }, { + pop : "screen", + @id : 3, + child : 2 + } ] +} \ No newline at end of file
