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

rubenql pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/calcite.git


The following commit(s) were added to refs/heads/main by this push:
     new af2fb7f02b [CALCITE-5608] Implement ASINH, ACOSH, ATANH functions
af2fb7f02b is described below

commit af2fb7f02b30bf853cf9f4c384fbcfeafefcebdf
Author: zoudan <zou...@bytedance.com>
AuthorDate: Mon May 15 16:19:49 2023 +0800

    [CALCITE-5608] Implement ASINH, ACOSH, ATANH functions
---
 .../calcite/adapter/enumerable/RexImpTable.java    |  6 ++
 .../org/apache/calcite/runtime/SqlFunctions.java   | 56 ++++++++++++++++++
 .../calcite/sql/fun/SqlLibraryOperators.java       | 26 ++++++++
 site/_docs/reference.md                            |  3 +
 .../org/apache/calcite/test/SqlOperatorTest.java   | 69 ++++++++++++++++++++++
 5 files changed, 160 insertions(+)

diff --git 
a/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java 
b/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java
index 6bc1dd18e7..4d8e51bb15 100644
--- a/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java
+++ b/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java
@@ -112,6 +112,7 @@ import static 
org.apache.calcite.linq4j.tree.ExpressionType.NotEqual;
 import static org.apache.calcite.linq4j.tree.ExpressionType.Subtract;
 import static org.apache.calcite.linq4j.tree.ExpressionType.UnaryPlus;
 import static org.apache.calcite.sql.fun.SqlInternalOperators.THROW_UNLESS;
+import static org.apache.calcite.sql.fun.SqlLibraryOperators.ACOSH;
 import static org.apache.calcite.sql.fun.SqlLibraryOperators.ARRAY;
 import static org.apache.calcite.sql.fun.SqlLibraryOperators.ARRAY_AGG;
 import static org.apache.calcite.sql.fun.SqlLibraryOperators.ARRAY_CONCAT;
@@ -121,6 +122,8 @@ import static 
org.apache.calcite.sql.fun.SqlLibraryOperators.ARRAY_LENGTH;
 import static org.apache.calcite.sql.fun.SqlLibraryOperators.ARRAY_REPEAT;
 import static org.apache.calcite.sql.fun.SqlLibraryOperators.ARRAY_REVERSE;
 import static org.apache.calcite.sql.fun.SqlLibraryOperators.ARRAY_SIZE;
+import static org.apache.calcite.sql.fun.SqlLibraryOperators.ASINH;
+import static org.apache.calcite.sql.fun.SqlLibraryOperators.ATANH;
 import static org.apache.calcite.sql.fun.SqlLibraryOperators.BOOL_AND;
 import static org.apache.calcite.sql.fun.SqlLibraryOperators.BOOL_OR;
 import static org.apache.calcite.sql.fun.SqlLibraryOperators.CHAR;
@@ -529,9 +532,12 @@ public class RexImpTable {
       map.put(RAND_INTEGER, new RandIntegerImplementor());
 
       defineMethod(ACOS, "acos", NullPolicy.STRICT);
+      defineMethod(ACOSH, "acosh", NullPolicy.STRICT);
       defineMethod(ASIN, "asin", NullPolicy.STRICT);
+      defineMethod(ASINH, "asinh", NullPolicy.STRICT);
       defineMethod(ATAN, "atan", NullPolicy.STRICT);
       defineMethod(ATAN2, "atan2", NullPolicy.STRICT);
+      defineMethod(ATANH, "atanh", NullPolicy.STRICT);
       defineMethod(CBRT, "cbrt", NullPolicy.STRICT);
       defineMethod(COS, "cos", NullPolicy.STRICT);
       defineMethod(COSH, "cosh", NullPolicy.STRICT);
diff --git a/core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java 
b/core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java
index 1fc339fc07..d9621c5c1b 100644
--- a/core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java
+++ b/core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java
@@ -1854,6 +1854,20 @@ public class SqlFunctions {
     return Math.acos(b0);
   }
 
+  // ACOSH
+  /** SQL <code>ACOSH</code> operator applied to BigDecimal values. */
+  public static double acosh(BigDecimal b0) {
+    return acosh(b0.doubleValue());
+  }
+
+  /** SQL <code>ACOSH</code> operator applied to double values. */
+  public static double acosh(double b0) {
+    if (b0 < 1) {
+      throw new IllegalArgumentException("Input parameter of acosh cannot be 
less than 1!");
+    }
+    return Math.log(Math.sqrt(b0 * b0 - 1.0d) + b0);
+  }
+
   // ASIN
   /** SQL <code>ASIN</code> operator applied to BigDecimal values. */
   public static double asin(BigDecimal b0) {
@@ -1865,6 +1879,25 @@ public class SqlFunctions {
     return Math.asin(b0);
   }
 
+  // ASINH
+  /** SQL <code>ASINH</code> operator applied to BigDecimal values. */
+  public static double asinh(BigDecimal b0) {
+    return asinh(b0.doubleValue());
+  }
+
+  /** SQL <code>ASINH</code> operator applied to double values. */
+  public static double asinh(double b0) {
+    final double sign;
+    // check the sign bit of the raw representation to handle -0.
+    if (Double.doubleToRawLongBits(b0) < 0) {
+      b0 = Math.abs(b0);
+      sign = -1.0d;
+    } else {
+      sign = 1.0d;
+    }
+    return sign * Math.log(Math.sqrt(b0 * b0 + 1.0d) + b0);
+  }
+
   // ATAN
   /** SQL <code>ATAN</code> operator applied to BigDecimal values. */
   public static double atan(BigDecimal b0) {
@@ -1897,6 +1930,29 @@ public class SqlFunctions {
     return Math.atan2(b0, b1);
   }
 
+  // ATANH
+  /** SQL <code>ATANH</code> operator applied to BigDecimal values. */
+  public static double atanh(BigDecimal b) {
+    return atanh(b.doubleValue());
+  }
+
+  /** SQL <code>ATANH</code> operator applied to double values. */
+  public static double atanh(double b) {
+    if (Math.abs(b) >= 1) {
+      throw new IllegalArgumentException("Input parameter of atanh cannot be 
out of the "
+          + "range (-1, 1)!");
+    }
+    final double mult;
+    // check the sign bit of the raw representation to handle -0.
+    if (Double.doubleToRawLongBits(b) < 0) {
+      b = Math.abs(b);
+      mult = -0.5d;
+    } else {
+      mult = 0.5d;
+    }
+    return mult * Math.log((1.0d + b) / (1.0d - b));
+  }
+
   // CBRT
   /** SQL <code>CBRT</code> operator applied to BigDecimal values. */
   public static double cbrt(BigDecimal b) {
diff --git 
a/core/src/main/java/org/apache/calcite/sql/fun/SqlLibraryOperators.java 
b/core/src/main/java/org/apache/calcite/sql/fun/SqlLibraryOperators.java
index a1952900eb..01c16396c3 100644
--- a/core/src/main/java/org/apache/calcite/sql/fun/SqlLibraryOperators.java
+++ b/core/src/main/java/org/apache/calcite/sql/fun/SqlLibraryOperators.java
@@ -1277,6 +1277,32 @@ public abstract class SqlLibraryOperators {
           OperandTypes.NUMERIC,
           SqlFunctionCategory.NUMERIC);
 
+  /** The {@code ACOSH(numeric)} function; returns the inverse hyperbolic 
cosine
+   * of {@code value}. */
+  @LibraryOperator(libraries = {ALL})
+  public static final SqlFunction ACOSH =
+      SqlBasicFunction.create("ACOSH",
+          ReturnTypes.DOUBLE_NULLABLE,
+          OperandTypes.NUMERIC,
+          SqlFunctionCategory.NUMERIC);
+
+  /** The {@code ASINH(numeric)} function; returns the inverse hyperbolic sine 
of {@code value}. */
+  @LibraryOperator(libraries = {ALL})
+  public static final SqlFunction ASINH =
+      SqlBasicFunction.create("ASINH",
+          ReturnTypes.DOUBLE_NULLABLE,
+          OperandTypes.NUMERIC,
+          SqlFunctionCategory.NUMERIC);
+
+  /** The {@code ATANH(numeric)} function; returns the inverse hyperbolic 
tangent
+   * of {@code value}. */
+  @LibraryOperator(libraries = {ALL})
+  public static final SqlFunction ATANH =
+      SqlBasicFunction.create("ATANH",
+          ReturnTypes.DOUBLE_NULLABLE,
+          OperandTypes.NUMERIC,
+          SqlFunctionCategory.NUMERIC);
+
   /** The "COTH(value)" function; returns the hyperbolic secant
    * of {@code value}. */
   @LibraryOperator(libraries = {ALL})
diff --git a/site/_docs/reference.md b/site/_docs/reference.md
index 077ecb75c3..7baa3d64df 100644
--- a/site/_docs/reference.md
+++ b/site/_docs/reference.md
@@ -2650,6 +2650,7 @@ BigQuery's type system uses confusingly different names 
for types and functions:
 |:- |:-----------------------------------------------|:-----------
 | p | expr :: type                                   | Casts *expr* to *type*
 | m | expr1 <=> expr2                                | Whether two values are 
equal, treating null values as the same, and it's similar to `IS NOT DISTINCT 
FROM`
+| * | ACOSH(numeric)                                 | Returns the inverse 
hyperbolic cosine of *numeric*
 | s | ARRAY(expr [, expr ]*)                         | Construct an array in 
Apache Spark
 | b | ARRAY_CONCAT(array [, array ]*)                | Concatenates one or 
more arrays. If any input argument is `NULL` the function returns `NULL`
 | s | ARRAY_DISTINCT(array)                          | Returns unique elements 
of *array*. Keeps ordering of elements.
@@ -2657,6 +2658,8 @@ BigQuery's type system uses confusingly different names 
for types and functions:
 | s | ARRAY_REPEAT(element, count)                   | Returns the array 
containing element count times.
 | b | ARRAY_REVERSE(array)                           | Reverses elements of 
*array*
 | s | ARRAY_SIZE(array)                              | Synonym for 
`CARDINALITY`
+| * | ASINH(numeric)                                 | Returns the inverse 
hyperbolic sine of *numeric*
+| * | ATANH(numeric)                                 | Returns the inverse 
hyperbolic tangent of *numeric*
 | m s | CHAR(integer)                                | Returns the character 
whose ASCII code is *integer* % 256, or null if *integer* &lt; 0
 | b o p | CHR(integer)                               | Returns the character 
whose UTF-8 code is *integer*
 | o | CONCAT(string, string)                         | Concatenates two strings
diff --git a/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java 
b/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java
index 57585050b4..bf9412efb6 100644
--- a/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java
+++ b/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java
@@ -5587,6 +5587,75 @@ public class SqlOperatorTest {
     f.checkNull("atan2(1, cast(null as double))");
   }
 
+  @Test void testAcoshFunc() {
+    final SqlOperatorFixture f0 = fixture().setFor(SqlLibraryOperators.ACOSH);
+    f0.checkFails("^acosh(1)^",
+        "No match found for function signature ACOSH\\(<NUMERIC>\\)",
+        false);
+    final Consumer<SqlOperatorFixture> consumer = f -> {
+      f.checkType("acosh(1)", "DOUBLE NOT NULL");
+      f.checkType("acosh(cast(1 as Decimal))", "DOUBLE NOT NULL");
+      f.checkType("acosh(case when false then 1 else null end)", "DOUBLE");
+      f.checkType("acosh('abc')", "DOUBLE NOT NULL");
+      f.checkScalarApprox("acosh(1)", "DOUBLE NOT NULL",
+          isWithin(0d, 0.0001d));
+      f.checkScalarApprox("acosh(cast(10 as decimal))", "DOUBLE NOT NULL",
+          isWithin(2.9932d, 0.0001d));
+      f.checkNull("acosh(cast(null as integer))");
+      f.checkNull("acosh(cast(null as double))");
+      f.checkFails("acosh(0.1)",
+          "Input parameter of acosh cannot be less than 1!",
+          true);
+    };
+    f0.forEachLibrary(list(SqlLibrary.ALL), consumer);
+  }
+
+  @Test void testAsinhFunc() {
+    final SqlOperatorFixture f0 = fixture().setFor(SqlLibraryOperators.ASINH);
+    f0.checkFails("^asinh(1)^",
+        "No match found for function signature ASINH\\(<NUMERIC>\\)",
+        false);
+    final Consumer<SqlOperatorFixture> consumer = f -> {
+      f.checkType("asinh(1)", "DOUBLE NOT NULL");
+      f.checkType("asinh(cast(1 as Decimal))", "DOUBLE NOT NULL");
+      f.checkType("asinh(case when false then 1 else null end)", "DOUBLE");
+      f.checkType("asinh('abc')", "DOUBLE NOT NULL");
+      f.checkScalarApprox("asinh(-2.5)", "DOUBLE NOT NULL",
+          isWithin(-1.6472d, 0.0001d));
+      f.checkScalarApprox("asinh(cast(10 as decimal))", "DOUBLE NOT NULL",
+          isWithin(2.9982, 0.0001d));
+      f.checkNull("asinh(cast(null as integer))");
+      f.checkNull("asinh(cast(null as double))");
+    };
+    f0.forEachLibrary(list(SqlLibrary.ALL), consumer);
+  }
+
+  @Test void testAtanhFunc() {
+    final SqlOperatorFixture f0 = fixture().setFor(SqlLibraryOperators.ATANH);
+    f0.checkFails("^atanh(1)^",
+        "No match found for function signature ATANH\\(<NUMERIC>\\)",
+        false);
+    final Consumer<SqlOperatorFixture> consumer = f -> {
+      f.checkType("atanh(0.1)", "DOUBLE NOT NULL");
+      f.checkType("atanh(cast(0 as Decimal))", "DOUBLE NOT NULL");
+      f.checkType("atanh(case when false then 0 else null end)", "DOUBLE");
+      f.checkType("atanh('abc')", "DOUBLE NOT NULL");
+      f.checkScalarApprox("atanh(0.76159416)", "DOUBLE NOT NULL",
+          isWithin(1d, 0.0001d));
+      f.checkScalarApprox("atanh(cast(-0.1 as decimal))", "DOUBLE NOT NULL",
+          isWithin(-0.1003d, 0.0001d));
+      f.checkNull("atanh(cast(null as integer))");
+      f.checkNull("atanh(cast(null as double))");
+      f.checkFails("atanh(1)",
+          "Input parameter of atanh cannot be out of the range \\(-1, 1\\)!",
+          true);
+      f.checkFails("atanh(-1)",
+          "Input parameter of atanh cannot be out of the range \\(-1, 1\\)!",
+          true);
+    };
+    f0.forEachLibrary(list(SqlLibrary.ALL), consumer);
+  }
+
   @Test void testCbrtFunc() {
     final SqlOperatorFixture f = fixture();
     f.setFor(SqlStdOperatorTable.CBRT, VmName.EXPAND);

Reply via email to