From c9f96fbec2746ee8ec656c9c36d20c3c597dbb3d Mon Sep 17 00:00:00 2001 From: Matthew Wells Date: Tue, 14 Mar 2023 17:17:33 -0700 Subject: [PATCH] Added SINH function to V2 engine (#242) (#1434) * Updated SINH function to V2 engine, added documentation, unit/IT tests Signed-off-by: Matthew Wells --- .../org/opensearch/sql/expression/DSL.java | 4 ++ .../function/BuiltinFunctionName.java | 1 + .../arthmetic/MathematicalFunction.java | 12 ++++ .../arthmetic/MathematicalFunctionTest.java | 66 +++++++++++++++++++ docs/user/dql/functions.rst | 16 ++++- .../sql/sql/MathematicalFunctionIT.java | 15 +++++ sql/src/main/antlr/OpenSearchSQLParser.g4 | 2 +- 7 files changed, 113 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/org/opensearch/sql/expression/DSL.java b/core/src/main/java/org/opensearch/sql/expression/DSL.java index 616f431283..2f0c07a897 100644 --- a/core/src/main/java/org/opensearch/sql/expression/DSL.java +++ b/core/src/main/java/org/opensearch/sql/expression/DSL.java @@ -226,6 +226,10 @@ public static FunctionExpression sign(Expression... expressions) { return compile(FunctionProperties.None, BuiltinFunctionName.SIGN, expressions); } + public static FunctionExpression sinh(Expression... expressions) { + return compile(FunctionProperties.None, BuiltinFunctionName.SINH, expressions); + } + public static FunctionExpression sqrt(Expression... expressions) { return compile(FunctionProperties.None, BuiltinFunctionName.SQRT, expressions); } diff --git a/core/src/main/java/org/opensearch/sql/expression/function/BuiltinFunctionName.java b/core/src/main/java/org/opensearch/sql/expression/function/BuiltinFunctionName.java index ec4a7bc140..b64207bb09 100644 --- a/core/src/main/java/org/opensearch/sql/expression/function/BuiltinFunctionName.java +++ b/core/src/main/java/org/opensearch/sql/expression/function/BuiltinFunctionName.java @@ -41,6 +41,7 @@ public enum BuiltinFunctionName { RAND(FunctionName.of("rand")), ROUND(FunctionName.of("round")), SIGN(FunctionName.of("sign")), + SINH(FunctionName.of("sinh")), SQRT(FunctionName.of("sqrt")), CBRT(FunctionName.of("cbrt")), TRUNCATE(FunctionName.of("truncate")), diff --git a/core/src/main/java/org/opensearch/sql/expression/operator/arthmetic/MathematicalFunction.java b/core/src/main/java/org/opensearch/sql/expression/operator/arthmetic/MathematicalFunction.java index bb562ac07b..bb6c943208 100644 --- a/core/src/main/java/org/opensearch/sql/expression/operator/arthmetic/MathematicalFunction.java +++ b/core/src/main/java/org/opensearch/sql/expression/operator/arthmetic/MathematicalFunction.java @@ -71,6 +71,7 @@ public static void register(BuiltinFunctionRepository repository) { repository.register(power()); repository.register(round()); repository.register(sign()); + repository.register(sinh()); repository.register(sqrt()); repository.register(truncate()); repository.register(pi()); @@ -475,6 +476,17 @@ private static DefaultFunctionResolver sign() { v -> new ExprIntegerValue(Math.signum(v.doubleValue())), INTEGER); } + /** + * Definition of sinh(x) function. + * Returns the hyperbolix sine of x, defined as (((e^x) - (e^(-x))) / 2) + * The supported signature is + * BYTE/SHORT/INTEGER/LONG/FLOAT/DOUBLE -> DOUBLE + */ + private static DefaultFunctionResolver sinh() { + return baseMathFunction(BuiltinFunctionName.SINH.getName(), + v -> new ExprDoubleValue(Math.sinh(v.doubleValue())), DOUBLE); + } + /** * Definition of sqrt(x) function. * Calculate the square root of a non-negative number x diff --git a/core/src/test/java/org/opensearch/sql/expression/operator/arthmetic/MathematicalFunctionTest.java b/core/src/test/java/org/opensearch/sql/expression/operator/arthmetic/MathematicalFunctionTest.java index 47ea5057c9..6fdfdaf5c1 100644 --- a/core/src/test/java/org/opensearch/sql/expression/operator/arthmetic/MathematicalFunctionTest.java +++ b/core/src/test/java/org/opensearch/sql/expression/operator/arthmetic/MathematicalFunctionTest.java @@ -1804,6 +1804,72 @@ public void sign_missing_value() { assertTrue(sign.valueOf(valueEnv()).isMissing()); } + /** + * Test sinh with byte value. + */ + @ParameterizedTest(name = "sinh({0})") + @ValueSource(bytes = {-1, 1, 2, Byte.MAX_VALUE, Byte.MIN_VALUE}) + public void sinh_byte_value(Byte value) { + FunctionExpression sinh = DSL.sinh(DSL.literal(value)); + assertThat(sinh.valueOf(valueEnv()), allOf(hasType(DOUBLE), hasValue(Math.sinh(value)))); + assertEquals(String.format("sinh(%s)", value), sinh.toString()); + } + + /** + * Test sinh with short value. + */ + @ParameterizedTest(name = "sinh({0})") + @ValueSource(shorts = {-1, 1, 2, Short.MAX_VALUE, Short.MIN_VALUE}) + public void sinh_short_value(Short value) { + FunctionExpression sinh = DSL.sinh(DSL.literal(value)); + assertThat(sinh.valueOf(valueEnv()), allOf(hasType(DOUBLE), hasValue(Math.sinh(value)))); + assertEquals(String.format("sinh(%s)", value), sinh.toString()); + } + + /** + * Test sinh with integer value. + */ + @ParameterizedTest(name = "sinh({0})") + @ValueSource(ints = {-1, 1, 2, Integer.MAX_VALUE, Integer.MIN_VALUE}) + public void sinh_int_value(Integer value) { + FunctionExpression sinh = DSL.sinh(DSL.literal(value)); + assertThat(sinh.valueOf(valueEnv()), allOf(hasType(DOUBLE), hasValue(Math.sinh(value)))); + assertEquals(String.format("sinh(%s)", value), sinh.toString()); + } + + /** + * Test sinh with long value. + */ + @ParameterizedTest(name = "sinh({0})") + @ValueSource(longs = {-1L, 1L, 2L, Long.MAX_VALUE, Long.MIN_VALUE}) + public void sinh_long_value(Long value) { + FunctionExpression sinh = DSL.sinh(DSL.literal(value)); + assertThat(sinh.valueOf(valueEnv()), allOf(hasType(DOUBLE), hasValue(Math.sinh(value)))); + assertEquals(String.format("sinh(%s)", value), sinh.toString()); + } + + /** + * Test sinh with float value. + */ + @ParameterizedTest(name = "sinh({0})") + @ValueSource(floats = {-1.5F, -1F, 1F, 1.5F, 2F, 2.7F, Float.MAX_VALUE, Float.MIN_VALUE}) + public void sinh_float_value(Float value) { + FunctionExpression sinh = DSL.sinh(DSL.literal(value)); + assertThat(sinh.valueOf(valueEnv()), allOf(hasType(DOUBLE), hasValue(Math.sinh(value)))); + assertEquals(String.format("sinh(%s)", value), sinh.toString()); + } + + /** + * Test sinh with double value. + */ + @ParameterizedTest(name = "sinh({0})") + @ValueSource(doubles = {-1.5, -1D, 1D, 1.5D, 2D, 2.7D, Double.MAX_VALUE, Double.MIN_VALUE}) + public void sinh_double_value(Double value) { + FunctionExpression sinh = DSL.sinh(DSL.literal(value)); + assertThat(sinh.valueOf(valueEnv()), allOf(hasType(DOUBLE), hasValue(Math.sinh(value)))); + assertEquals(String.format("sinh(%s)", value), sinh.toString()); + } + /** * Test sqrt with int value. */ diff --git a/docs/user/dql/functions.rst b/docs/user/dql/functions.rst index 5d5a3e1f96..127f8044bf 100644 --- a/docs/user/dql/functions.rst +++ b/docs/user/dql/functions.rst @@ -794,9 +794,21 @@ SINH Description >>>>>>>>>>> -Specifications: +Usage: sinh(x) calculate the hyperbolic sine of x, defined as (((e^x) - (e^(-x))) / 2) + +Argument type: BYTE/SHORT/INTEGER/LONG/FLOAT/DOUBLE + +Return type: DOUBLE -1. SINH(NUMBER T) -> DOUBLE +Example:: + + os> SELECT SINH(2), SINH(1.5) + fetched rows / total rows = 1/1 + +-------------------+--------------------+ + | SINH(2) | SINH(1.5) | + |-------------------+--------------------| + | 3.626860407847019 | 2.1292794550948173 | + +-------------------+--------------------+ SQRT diff --git a/integ-test/src/test/java/org/opensearch/sql/sql/MathematicalFunctionIT.java b/integ-test/src/test/java/org/opensearch/sql/sql/MathematicalFunctionIT.java index 1bc9bd09b6..00da77e209 100644 --- a/integ-test/src/test/java/org/opensearch/sql/sql/MathematicalFunctionIT.java +++ b/integ-test/src/test/java/org/opensearch/sql/sql/MathematicalFunctionIT.java @@ -147,6 +147,21 @@ public void testSign() throws IOException { verifyDataRows(result, rows(-1)); } + @Test + public void testSinh() throws IOException { + JSONObject result = executeQuery("select sinh(1)"); + verifySchema(result, schema("sinh(1)", null, "double")); + verifyDataRows(result, rows(1.1752011936438014)); + + result = executeQuery("select sinh(-1)"); + verifySchema(result, schema("sinh(-1)", null, "double")); + verifyDataRows(result, rows(-1.1752011936438014)); + + result = executeQuery("select sinh(1.5)"); + verifySchema(result, schema("sinh(1.5)", null, "double")); + verifyDataRows(result, rows(2.1292794550948173)); + } + @Test public void testTruncate() throws IOException { JSONObject result = executeQuery("select truncate(56.78, 1)"); diff --git a/sql/src/main/antlr/OpenSearchSQLParser.g4 b/sql/src/main/antlr/OpenSearchSQLParser.g4 index e5efeabba0..76afbcc28c 100644 --- a/sql/src/main/antlr/OpenSearchSQLParser.g4 +++ b/sql/src/main/antlr/OpenSearchSQLParser.g4 @@ -424,7 +424,7 @@ mathematicalFunctionName ; trigonometricFunctionName - : ACOS | ASIN | ATAN | ATAN2 | COS | COT | DEGREES | RADIANS | SIN | TAN + : ACOS | ASIN | ATAN | ATAN2 | COS | COT | DEGREES | RADIANS | SIN | SINH | TAN ; dateTimeFunctionName