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

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


The following commit(s) were added to refs/heads/master by this push:
     new dffbd5108db [Enhancement] Support some math functions (#48476)
dffbd5108db is described below

commit dffbd5108db7ab022f01a8a619091857e442005c
Author: Nya~ <chenmiao...@gmail.com>
AuthorDate: Tue Mar 25 17:34:51 2025 +0800

    [Enhancement] Support some math functions (#48476)
    
    ### What problem does this PR solve?
    
    Related PR: #48203
    
    Problem Summary: support simple sql function for sinh(from Trino),
    asinh, atanh, acosh
---
 be/src/vec/functions/math.cpp                      |  28 +++++++++
 be/test/vec/function/function_math_test.cpp        |  60 ++++++++++++++++++
 fe/fe-core/pom.xml                                 |   4 ++
 .../doris/catalog/BuiltinScalarFunctions.java      |   8 +++
 .../functions/executable/NumericArithmetic.java    |  50 +++++++++++++++
 .../trees/expressions/functions/scalar/Acosh.java  |  68 +++++++++++++++++++++
 .../trees/expressions/functions/scalar/Asinh.java  |  67 ++++++++++++++++++++
 .../trees/expressions/functions/scalar/Atanh.java  |  68 +++++++++++++++++++++
 .../trees/expressions/functions/scalar/Sinh.java   |  68 +++++++++++++++++++++
 .../expressions/visitor/ScalarFunctionVisitor.java |  20 ++++++
 fe/pom.xml                                         |   7 +++
 .../test_math_unary_always_nullable.out            | Bin 1032 -> 1769 bytes
 .../fold_constant_numeric_arithmatic.groovy        |  48 ++++++++++++++-
 .../test_math_unary_always_nullable.groovy         |  30 ++++++++-
 14 files changed, 524 insertions(+), 2 deletions(-)

diff --git a/be/src/vec/functions/math.cpp b/be/src/vec/functions/math.cpp
index 6e8222bae4b..c4d5f8ed6aa 100644
--- a/be/src/vec/functions/math.cpp
+++ b/be/src/vec/functions/math.cpp
@@ -60,6 +60,13 @@ struct AcosName {
 using FunctionAcos =
         
FunctionMathUnaryAlwayNullable<UnaryFunctionPlainAlwayNullable<AcosName, 
std::acos>>;
 
+struct AcoshName {
+    static constexpr auto name = "acosh";
+    static constexpr bool is_invalid_input(Float64 x) { return x < 1; }
+};
+using FunctionAcosh =
+        
FunctionMathUnaryAlwayNullable<UnaryFunctionPlainAlwayNullable<AcoshName, 
std::acosh>>;
+
 struct AsinName {
     static constexpr auto name = "asin";
     // 
https://dev.mysql.com/doc/refman/8.4/en/mathematical-functions.html#function_asin
@@ -68,11 +75,23 @@ struct AsinName {
 using FunctionAsin =
         
FunctionMathUnaryAlwayNullable<UnaryFunctionPlainAlwayNullable<AsinName, 
std::asin>>;
 
+struct AsinhName {
+    static constexpr auto name = "asinh";
+};
+using FunctionAsinh = FunctionMathUnary<UnaryFunctionPlain<AsinhName, 
std::asinh>>;
+
 struct AtanName {
     static constexpr auto name = "atan";
 };
 using FunctionAtan = FunctionMathUnary<UnaryFunctionPlain<AtanName, 
std::atan>>;
 
+struct AtanhName {
+    static constexpr auto name = "atanh";
+    static constexpr bool is_invalid_input(Float64 x) { return x <= -1 || x >= 
1; }
+};
+using FunctionAtanh =
+        
FunctionMathUnaryAlwayNullable<UnaryFunctionPlainAlwayNullable<AtanhName, 
std::atanh>>;
+
 template <typename A, typename B>
 struct Atan2Impl {
     using ResultType = double;
@@ -247,6 +266,11 @@ struct UnaryFunctionPlainSin {
 
 using FunctionSin = FunctionMathUnary<UnaryFunctionPlainSin>;
 
+struct SinhName {
+    static constexpr auto name = "sinh";
+};
+using FunctionSinh = FunctionMathUnary<UnaryFunctionPlain<SinhName, 
std::sinh>>;
+
 struct SqrtName {
     static constexpr auto name = "sqrt";
     // 
https://dev.mysql.com/doc/refman/8.4/en/mathematical-functions.html#function_sqrt
@@ -427,8 +451,11 @@ public:
 // so mush. Split it to speed up compile time in the future
 void register_function_math(SimpleFunctionFactory& factory) {
     factory.register_function<FunctionAcos>();
+    factory.register_function<FunctionAcosh>();
     factory.register_function<FunctionAsin>();
+    factory.register_function<FunctionAsinh>();
     factory.register_function<FunctionAtan>();
+    factory.register_function<FunctionAtanh>();
     factory.register_function<FunctionAtan2>();
     factory.register_function<FunctionCos>();
     factory.register_function<FunctionCosh>();
@@ -445,6 +472,7 @@ void register_function_math(SimpleFunctionFactory& factory) 
{
     factory.register_function<FunctionNegative>();
     factory.register_function<FunctionPositive>();
     factory.register_function<FunctionSin>();
+    factory.register_function<FunctionSinh>();
     factory.register_function<FunctionSqrt>();
     factory.register_alias("sqrt", "dsqrt");
     factory.register_function<FunctionCbrt>();
diff --git a/be/test/vec/function/function_math_test.cpp 
b/be/test/vec/function/function_math_test.cpp
index bb24d141e4c..a0feec51753 100644
--- a/be/test/vec/function/function_math_test.cpp
+++ b/be/test/vec/function/function_math_test.cpp
@@ -43,6 +43,21 @@ TEST(MathFunctionTest, acos_test) {
     static_cast<void>(check_function<DataTypeFloat64, true>(func_name, 
input_types, data_set));
 }
 
+TEST(MathFunctionTest, acosh_test) {
+    std::string func_name = "acosh"; // acosh(x) = ln(x + sqrt(x^2 - 1)), x ∈ 
[1, +∞)
+
+    std::vector input_types = {TypeIndex::Float64};
+
+    DataSet data_set = {{{1.0}, 0.0},
+                        {{2.0}, 1.3169578969248168},
+                        {{3.0}, 1.7627471740390861},
+                        {{10.0}, 2.9932228461263808},
+                        {{100.0}, 5.2982923656104850}};
+
+    static_cast<void>(
+            check_function_all_arg_comb<DataTypeFloat64, true>(func_name, 
input_types, data_set));
+}
+
 TEST(MathFunctionTest, asin_test) {
     std::string func_name = "asin"; //[-1,1] -->[-pi_2, pi_2]
 
@@ -54,6 +69,21 @@ TEST(MathFunctionTest, asin_test) {
     static_cast<void>(check_function<DataTypeFloat64, true>(func_name, 
input_types, data_set));
 }
 
+TEST(MathFunctionTest, asinh_test) {
+    std::string func_name = "asinh"; // asinh(x) = ln(x + sqrt(x^2 + 1)), x ∈ 
(-∞, +∞)
+
+    std::vector input_types = {TypeIndex::Float64};
+
+    DataSet data_set = {{{0.0}, 0.0},
+                        {{1.0}, 0.8813735870195430},
+                        {{-1.0}, -0.8813735870195430},
+                        {{2.0}, 1.4436354751788103},
+                        {{-2.0}, -1.4436354751788103}};
+
+    static_cast<void>(
+            check_function_all_arg_comb<DataTypeFloat64, true>(func_name, 
input_types, data_set));
+}
+
 TEST(MathFunctionTest, atan_test) {
     std::string func_name = "atan"; //[-,+] -->(pi_2,pi_2)
 
@@ -67,6 +97,21 @@ TEST(MathFunctionTest, atan_test) {
     static_cast<void>(check_function<DataTypeFloat64, true>(func_name, 
input_types, data_set));
 }
 
+TEST(MathFunctionTest, atanh_test) {
+    std::string func_name = "atanh"; // atanh(x) = 0.5 * ln((1 + x) / (1 - 
x)), x ∈ (-1, 1)
+
+    std::vector input_types = {TypeIndex::Float64};
+
+    DataSet data_set = {{{0.0}, 0.0},
+                        {{0.5}, 0.5493061443340549},
+                        {{-0.5}, -0.5493061443340549},
+                        {{0.9}, 1.4722194895832204},
+                        {{-0.9}, -1.4722194895832204}};
+
+    static_cast<void>(
+            check_function_all_arg_comb<DataTypeFloat64, true>(func_name, 
input_types, data_set));
+}
+
 TEST(MathFunctionTest, cos_test) {
     std::string func_name = "cos";
 
@@ -95,6 +140,21 @@ TEST(MathFunctionTest, sin_test) {
     static_cast<void>(check_function<DataTypeFloat64, true>(func_name, 
input_types, data_set));
 }
 
+TEST(MathFunctionTest, sinh_test) {
+    std::string func_name = "sinh"; // sinh(x) = (e^x - e^(-x)) / 2, x ∈ (-∞, 
+∞)
+
+    std::vector input_types = {TypeIndex::Float64};
+
+    DataSet data_set = {{{0.0}, 0.0},
+                        {{1.0}, 1.1752011936438014},
+                        {{-1.0}, -1.1752011936438014},
+                        {{2.0}, 3.6268604078470186},
+                        {{-2.0}, -3.6268604078470186}};
+
+    static_cast<void>(
+            check_function_all_arg_comb<DataTypeFloat64, true>(func_name, 
input_types, data_set));
+}
+
 TEST(MathFunctionTest, sqrt_test) {
     std::string func_name = "sqrt"; //sqrt(x) x>=0
 
diff --git a/fe/fe-core/pom.xml b/fe/fe-core/pom.xml
index 52bb3ef7329..f7048b9f03d 100644
--- a/fe/fe-core/pom.xml
+++ b/fe/fe-core/pom.xml
@@ -131,6 +131,10 @@ under the License.
             <groupId>org.apache.commons</groupId>
             <artifactId>commons-lang3</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-math3</artifactId>
+        </dependency>
         <!-- 
https://mvnrepository.com/artifact/org.apache.commons/commons-pool2 -->
         <dependency>
             <groupId>org.apache.commons</groupId>
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/catalog/BuiltinScalarFunctions.java 
b/fe/fe-core/src/main/java/org/apache/doris/catalog/BuiltinScalarFunctions.java
index e6ce3de8c6f..ebf9f786ccf 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/catalog/BuiltinScalarFunctions.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/catalog/BuiltinScalarFunctions.java
@@ -21,6 +21,7 @@ import org.apache.doris.nereids.trees.expressions.Like;
 import org.apache.doris.nereids.trees.expressions.Regexp;
 import org.apache.doris.nereids.trees.expressions.functions.scalar.Abs;
 import org.apache.doris.nereids.trees.expressions.functions.scalar.Acos;
+import org.apache.doris.nereids.trees.expressions.functions.scalar.Acosh;
 import org.apache.doris.nereids.trees.expressions.functions.scalar.AesDecrypt;
 import org.apache.doris.nereids.trees.expressions.functions.scalar.AesEncrypt;
 import 
org.apache.doris.nereids.trees.expressions.functions.scalar.AppendTrailingCharIfAbsent;
@@ -75,9 +76,11 @@ import 
org.apache.doris.nereids.trees.expressions.functions.scalar.ArrayZip;
 import 
org.apache.doris.nereids.trees.expressions.functions.scalar.ArraysOverlap;
 import org.apache.doris.nereids.trees.expressions.functions.scalar.Ascii;
 import org.apache.doris.nereids.trees.expressions.functions.scalar.Asin;
+import org.apache.doris.nereids.trees.expressions.functions.scalar.Asinh;
 import org.apache.doris.nereids.trees.expressions.functions.scalar.AssertTrue;
 import org.apache.doris.nereids.trees.expressions.functions.scalar.Atan;
 import org.apache.doris.nereids.trees.expressions.functions.scalar.Atan2;
+import org.apache.doris.nereids.trees.expressions.functions.scalar.Atanh;
 import 
org.apache.doris.nereids.trees.expressions.functions.scalar.AutoPartitionName;
 import org.apache.doris.nereids.trees.expressions.functions.scalar.Bin;
 import org.apache.doris.nereids.trees.expressions.functions.scalar.BitCount;
@@ -381,6 +384,7 @@ import 
org.apache.doris.nereids.trees.expressions.functions.scalar.Sha1;
 import org.apache.doris.nereids.trees.expressions.functions.scalar.Sha2;
 import org.apache.doris.nereids.trees.expressions.functions.scalar.Sign;
 import org.apache.doris.nereids.trees.expressions.functions.scalar.Sin;
+import org.apache.doris.nereids.trees.expressions.functions.scalar.Sinh;
 import org.apache.doris.nereids.trees.expressions.functions.scalar.Sleep;
 import org.apache.doris.nereids.trees.expressions.functions.scalar.Sm3;
 import org.apache.doris.nereids.trees.expressions.functions.scalar.Sm3sum;
@@ -496,6 +500,7 @@ public class BuiltinScalarFunctions implements 
FunctionHelper {
     public final List<ScalarFunc> scalarFunctions = ImmutableList.of(
             scalar(Abs.class, "abs"),
             scalar(Acos.class, "acos"),
+            scalar(Acosh.class, "acosh"),
             scalar(AesDecrypt.class, "aes_decrypt"),
             scalar(AesEncrypt.class, "aes_encrypt"),
             scalar(AppendTrailingCharIfAbsent.class, 
"append_trailing_char_if_absent"),
@@ -550,8 +555,10 @@ public class BuiltinScalarFunctions implements 
FunctionHelper {
             scalar(ArraysOverlap.class, "arrays_overlap"),
             scalar(Ascii.class, "ascii"),
             scalar(Asin.class, "asin"),
+            scalar(Asinh.class, "asinh"),
             scalar(AssertTrue.class, "assert_true"),
             scalar(Atan.class, "atan"),
+            scalar(Atanh.class, "atanh"),
             scalar(Atan2.class, "atan2"),
             scalar(AutoPartitionName.class, "auto_partition_name"),
             scalar(Bin.class, "bin"),
@@ -874,6 +881,7 @@ public class BuiltinScalarFunctions implements 
FunctionHelper {
             scalar(Sha2.class, "sha2"),
             scalar(Sign.class, "sign"),
             scalar(Sin.class, "sin"),
+            scalar(Sinh.class, "sinh"),
             scalar(Sleep.class, "sleep"),
             scalar(StructElement.class, "struct_element"),
             scalar(Sm3.class, "sm3"),
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/executable/NumericArithmetic.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/executable/NumericArithmetic.java
index 57eda59ee7d..4859a61f950 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/executable/NumericArithmetic.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/executable/NumericArithmetic.java
@@ -36,6 +36,8 @@ import 
org.apache.doris.nereids.trees.expressions.literal.VarcharLiteral;
 import org.apache.doris.nereids.types.DecimalV3Type;
 import org.apache.doris.nereids.types.DoubleType;
 
+import org.apache.commons.math3.util.FastMath;
+
 import java.math.BigDecimal;
 import java.math.BigInteger;
 import java.nio.charset.StandardCharsets;
@@ -893,6 +895,17 @@ public class NumericArithmetic {
         return checkOutputBoundary(new 
DoubleLiteral(Math.sin(first.getValue())));
     }
 
+    /**
+     * sinh
+     */
+    @ExecFunction(name = "sinh")
+    public static Expression sinh(DoubleLiteral first) {
+        if (inputOutOfBound(first, Double.NEGATIVE_INFINITY, 
Double.POSITIVE_INFINITY, false, false)) {
+            return new NullLiteral(DoubleType.INSTANCE);
+        }
+        return checkOutputBoundary(new 
DoubleLiteral(Math.sinh(first.getValue())));
+    }
+
     /**
      * cos
      */
@@ -942,9 +955,46 @@ public class NumericArithmetic {
      */
     @ExecFunction(name = "atan")
     public static Expression atan(DoubleLiteral first) {
+        if (inputOutOfBound(first, Double.NEGATIVE_INFINITY, 
Double.POSITIVE_INFINITY, false, false)) {
+            return new NullLiteral(DoubleType.INSTANCE);
+        }
         return checkOutputBoundary(new 
DoubleLiteral(Math.atan(first.getValue())));
     }
 
+    /**
+     * asinh
+     */
+    @ExecFunction(name = "asinh")
+    public static Expression asinh(DoubleLiteral first) {
+        if (inputOutOfBound(first, Double.NEGATIVE_INFINITY, 
Double.POSITIVE_INFINITY, false, false)) {
+            return new NullLiteral(DoubleType.INSTANCE);
+        }
+        return checkOutputBoundary(new 
DoubleLiteral(FastMath.asinh(first.getValue())));
+    }
+
+    /**
+     * acosh
+     */
+    @ExecFunction(name = "acosh")
+    public static Expression acosh(DoubleLiteral first) {
+        if (inputOutOfBound(first, Double.NEGATIVE_INFINITY, 1.0, false, 
false)) {
+            return new NullLiteral(DoubleType.INSTANCE);
+        }
+        return checkOutputBoundary(new 
DoubleLiteral(FastMath.acosh(first.getValue())));
+    }
+
+    /**
+     * atanh
+     */
+    @ExecFunction(name = "atanh")
+    public static Expression atanh(DoubleLiteral first) {
+        if (inputOutOfBound(first, 1.0, Double.POSITIVE_INFINITY, true, false)
+                || inputOutOfBound(first, Double.NEGATIVE_INFINITY, -1.0, 
false, true)) {
+            return new NullLiteral(DoubleType.INSTANCE);
+        }
+        return checkOutputBoundary(new 
DoubleLiteral(FastMath.atanh(first.getValue())));
+    }
+
     /**
      * atan2
      */
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Acosh.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Acosh.java
new file mode 100644
index 00000000000..d7c80589524
--- /dev/null
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Acosh.java
@@ -0,0 +1,68 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.doris.nereids.trees.expressions.functions.scalar;
+
+import org.apache.doris.catalog.FunctionSignature;
+import org.apache.doris.nereids.trees.expressions.Expression;
+import org.apache.doris.nereids.trees.expressions.functions.AlwaysNullable;
+import 
org.apache.doris.nereids.trees.expressions.functions.ExplicitlyCastableSignature;
+import 
org.apache.doris.nereids.trees.expressions.functions.PropagateNullLiteral;
+import org.apache.doris.nereids.trees.expressions.shape.UnaryExpression;
+import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor;
+import org.apache.doris.nereids.types.DoubleType;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+
+import java.util.List;
+
+/**
+ * ScalarFunction Acosh
+ */
+public class Acosh extends ScalarFunction
+        implements UnaryExpression, ExplicitlyCastableSignature, 
AlwaysNullable, PropagateNullLiteral {
+    public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
+            
FunctionSignature.ret(DoubleType.INSTANCE).args(DoubleType.INSTANCE)
+    );
+
+    /**
+     * constructor with 1 argument.
+     */
+    public Acosh(Expression arg) {
+        super("acosh", arg);
+    }
+
+    /**
+     * withChildren.
+     */
+    @Override
+    public Acosh withChildren(List<Expression> children) {
+        Preconditions.checkArgument(children.size() == 1);
+        return new Acosh(children.get(0));
+    }
+
+    @Override
+    public List<FunctionSignature> getSignatures() {
+        return SIGNATURES;
+    }
+
+    @Override
+    public <R, C> R accept(ExpressionVisitor<R, C> visitor, C context) {
+        return visitor.visitAcosh(this, context);
+    }
+}
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Asinh.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Asinh.java
new file mode 100644
index 00000000000..d51b2de1ae1
--- /dev/null
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Asinh.java
@@ -0,0 +1,67 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.doris.nereids.trees.expressions.functions.scalar;
+
+import org.apache.doris.catalog.FunctionSignature;
+import org.apache.doris.nereids.trees.expressions.Expression;
+import 
org.apache.doris.nereids.trees.expressions.functions.ExplicitlyCastableSignature;
+import org.apache.doris.nereids.trees.expressions.functions.PropagateNullable;
+import org.apache.doris.nereids.trees.expressions.shape.UnaryExpression;
+import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor;
+import org.apache.doris.nereids.types.DoubleType;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+
+import java.util.List;
+
+/**
+ * ScalarFunction asinh
+ */
+public class Asinh extends ScalarFunction
+        implements UnaryExpression, ExplicitlyCastableSignature, 
PropagateNullable {
+    public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
+            
FunctionSignature.ret(DoubleType.INSTANCE).args(DoubleType.INSTANCE)
+    );
+
+    /**
+     * constructor with 1 argument.
+     */
+    public Asinh(Expression arg) {
+        super("asinh", arg);
+    }
+
+    /**
+     * withChildren.
+     */
+    @Override
+    public Asinh withChildren(List<Expression> children) {
+        Preconditions.checkArgument(children.size() == 1);
+        return new Asinh(children.get(0));
+    }
+
+    @Override
+    public List<FunctionSignature> getSignatures() {
+        return SIGNATURES;
+    }
+
+    @Override
+    public <R, C> R accept(ExpressionVisitor<R, C> visitor, C context) {
+        return visitor.visitAsinh(this, context);
+    }
+}
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Atanh.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Atanh.java
new file mode 100644
index 00000000000..4f0931caf12
--- /dev/null
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Atanh.java
@@ -0,0 +1,68 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.doris.nereids.trees.expressions.functions.scalar;
+
+import org.apache.doris.catalog.FunctionSignature;
+import org.apache.doris.nereids.trees.expressions.Expression;
+import org.apache.doris.nereids.trees.expressions.functions.AlwaysNullable;
+import 
org.apache.doris.nereids.trees.expressions.functions.ExplicitlyCastableSignature;
+import 
org.apache.doris.nereids.trees.expressions.functions.PropagateNullLiteral;
+import org.apache.doris.nereids.trees.expressions.shape.UnaryExpression;
+import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor;
+import org.apache.doris.nereids.types.DoubleType;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+
+import java.util.List;
+
+/**
+ * ScalarFunction atanh
+ */
+public class Atanh extends ScalarFunction
+        implements UnaryExpression, ExplicitlyCastableSignature, 
AlwaysNullable, PropagateNullLiteral {
+    public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
+            
FunctionSignature.ret(DoubleType.INSTANCE).args(DoubleType.INSTANCE)
+    );
+
+    /**
+     * constructor with 1 argument.
+     */
+    public Atanh(Expression arg) {
+        super("atanh", arg);
+    }
+
+    /**
+     * withChildren.
+     */
+    @Override
+    public Atanh withChildren(List<Expression> children) {
+        Preconditions.checkArgument(children.size() == 1);
+        return new Atanh(children.get(0));
+    }
+
+    @Override
+    public List<FunctionSignature> getSignatures() {
+        return SIGNATURES;
+    }
+
+    @Override
+    public <R, C> R accept(ExpressionVisitor<R, C> visitor, C context) {
+        return visitor.visitAtanh(this, context);
+    }
+}
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Sinh.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Sinh.java
new file mode 100644
index 00000000000..b1cdd188aa1
--- /dev/null
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Sinh.java
@@ -0,0 +1,68 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.doris.nereids.trees.expressions.functions.scalar;
+
+import org.apache.doris.catalog.FunctionSignature;
+import org.apache.doris.nereids.trees.expressions.Expression;
+import 
org.apache.doris.nereids.trees.expressions.functions.ExplicitlyCastableSignature;
+import org.apache.doris.nereids.trees.expressions.functions.PropagateNullable;
+import org.apache.doris.nereids.trees.expressions.shape.UnaryExpression;
+import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor;
+import org.apache.doris.nereids.types.DoubleType;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+
+import java.util.List;
+
+/**
+ * ScalarFunction Sinh
+ */
+public class Sinh extends ScalarFunction
+        implements UnaryExpression, ExplicitlyCastableSignature, 
PropagateNullable {
+
+    public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
+            
FunctionSignature.ret(DoubleType.INSTANCE).args(DoubleType.INSTANCE)
+    );
+
+    /**
+     * constructor with 1 argument.
+     */
+    public Sinh(Expression arg) {
+        super("sinh", arg);
+    }
+
+    /**
+     * withChildren.
+     */
+    @Override
+    public Sinh withChildren(List<Expression> children) {
+        Preconditions.checkArgument(children.size() == 1);
+        return new Sinh(children.get(0));
+    }
+
+    @Override
+    public List<FunctionSignature> getSignatures() {
+        return SIGNATURES;
+    }
+
+    @Override
+    public <R, C> R accept(ExpressionVisitor<R, C> visitor, C context) {
+        return visitor.visitSinh(this, context);
+    }
+}
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/visitor/ScalarFunctionVisitor.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/visitor/ScalarFunctionVisitor.java
index c4589cfe02c..f1737db8e59 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/visitor/ScalarFunctionVisitor.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/visitor/ScalarFunctionVisitor.java
@@ -23,6 +23,7 @@ import 
org.apache.doris.nereids.trees.expressions.StringRegexPredicate;
 import 
org.apache.doris.nereids.trees.expressions.functions.combinator.StateCombinator;
 import org.apache.doris.nereids.trees.expressions.functions.scalar.Abs;
 import org.apache.doris.nereids.trees.expressions.functions.scalar.Acos;
+import org.apache.doris.nereids.trees.expressions.functions.scalar.Acosh;
 import org.apache.doris.nereids.trees.expressions.functions.scalar.AesDecrypt;
 import org.apache.doris.nereids.trees.expressions.functions.scalar.AesEncrypt;
 import 
org.apache.doris.nereids.trees.expressions.functions.scalar.AppendTrailingCharIfAbsent;
@@ -82,9 +83,11 @@ import 
org.apache.doris.nereids.trees.expressions.functions.scalar.ArrayZip;
 import 
org.apache.doris.nereids.trees.expressions.functions.scalar.ArraysOverlap;
 import org.apache.doris.nereids.trees.expressions.functions.scalar.Ascii;
 import org.apache.doris.nereids.trees.expressions.functions.scalar.Asin;
+import org.apache.doris.nereids.trees.expressions.functions.scalar.Asinh;
 import org.apache.doris.nereids.trees.expressions.functions.scalar.AssertTrue;
 import org.apache.doris.nereids.trees.expressions.functions.scalar.Atan;
 import org.apache.doris.nereids.trees.expressions.functions.scalar.Atan2;
+import org.apache.doris.nereids.trees.expressions.functions.scalar.Atanh;
 import 
org.apache.doris.nereids.trees.expressions.functions.scalar.AutoPartitionName;
 import org.apache.doris.nereids.trees.expressions.functions.scalar.Bin;
 import org.apache.doris.nereids.trees.expressions.functions.scalar.BitCount;
@@ -379,6 +382,7 @@ import 
org.apache.doris.nereids.trees.expressions.functions.scalar.Sha1;
 import org.apache.doris.nereids.trees.expressions.functions.scalar.Sha2;
 import org.apache.doris.nereids.trees.expressions.functions.scalar.Sign;
 import org.apache.doris.nereids.trees.expressions.functions.scalar.Sin;
+import org.apache.doris.nereids.trees.expressions.functions.scalar.Sinh;
 import org.apache.doris.nereids.trees.expressions.functions.scalar.Sleep;
 import org.apache.doris.nereids.trees.expressions.functions.scalar.Sm3;
 import org.apache.doris.nereids.trees.expressions.functions.scalar.Sm3sum;
@@ -494,6 +498,10 @@ public interface ScalarFunctionVisitor<R, C> {
         return visitScalarFunction(acos, context);
     }
 
+    default R visitAcosh(Acosh acosh, C context) {
+        return visitScalarFunction(acosh, context);
+    }
+
     default R visitAesDecrypt(AesDecrypt aesDecrypt, C context) {
         return visitScalarFunction(aesDecrypt, context);
     }
@@ -730,6 +738,10 @@ public interface ScalarFunctionVisitor<R, C> {
         return visitScalarFunction(asin, context);
     }
 
+    default R visitAsinh(Asinh asinh, C context) {
+        return visitScalarFunction(asinh, context);
+    }
+
     default R visitAssertTrue(AssertTrue assertTrue, C context) {
         return visitScalarFunction(assertTrue, context);
     }
@@ -738,6 +750,10 @@ public interface ScalarFunctionVisitor<R, C> {
         return visitScalarFunction(atan, context);
     }
 
+    default R visitAtanh(Atanh atanh, C context) {
+        return visitScalarFunction(atanh, context);
+    }
+
     default R visitAtan2(Atan2 atan2, C context) {
         return visitScalarFunction(atan2, context);
     }
@@ -1891,6 +1907,10 @@ public interface ScalarFunctionVisitor<R, C> {
         return visitScalarFunction(sin, context);
     }
 
+    default R visitSinh(Sinh sinh, C context) {
+        return visitScalarFunction(sinh, context);
+    }
+
     default R visitSleep(Sleep sleep, C context) {
         return visitScalarFunction(sleep, context);
     }
diff --git a/fe/pom.xml b/fe/pom.xml
index 68cfff27e89..55d2763ac52 100644
--- a/fe/pom.xml
+++ b/fe/pom.xml
@@ -253,6 +253,7 @@ under the License.
         <commons-pool2.version>2.2</commons-pool2.version>
         <commons-pool.version>1.5.1</commons-pool.version>
         <commons-text.version>1.10.0</commons-text.version>
+        <commons-math3.version>3.6.1</commons-math3.version>
         <commons-validator.version>1.7</commons-validator.version>
         <gson.version>2.10.1</gson.version>
         <guava.version>33.2.1-jre</guava.version>
@@ -793,6 +794,12 @@ under the License.
                 <artifactId>commons-lang3</artifactId>
                 <version>${commons-lang3.version}</version>
             </dependency>
+            <!-- 
https://mvnrepository.com/artifact/org.apache.commons/commons-math3 -->
+            <dependency>
+                <groupId>org.apache.commons</groupId>
+                <artifactId>commons-math3</artifactId>
+                <version>${commons-math3.version}</version>
+            </dependency>
             <!-- 
https://mvnrepository.com/artifact/org.apache.commons/commons-pool2 -->
             <dependency>
                 <groupId>org.apache.commons</groupId>
diff --git 
a/regression-test/data/query_p0/sql_functions/math_functions/test_math_unary_always_nullable.out
 
b/regression-test/data/query_p0/sql_functions/math_functions/test_math_unary_always_nullable.out
index 0a190f0bd6b..ae2203c03d8 100644
Binary files 
a/regression-test/data/query_p0/sql_functions/math_functions/test_math_unary_always_nullable.out
 and 
b/regression-test/data/query_p0/sql_functions/math_functions/test_math_unary_always_nullable.out
 differ
diff --git 
a/regression-test/suites/nereids_p0/expression/fold_constant/fold_constant_numeric_arithmatic.groovy
 
b/regression-test/suites/nereids_p0/expression/fold_constant/fold_constant_numeric_arithmatic.groovy
index bc1cb91ca9d..fcf2d060886 100644
--- 
a/regression-test/suites/nereids_p0/expression/fold_constant/fold_constant_numeric_arithmatic.groovy
+++ 
b/regression-test/suites/nereids_p0/expression/fold_constant/fold_constant_numeric_arithmatic.groovy
@@ -51,6 +51,17 @@ suite("fold_constant_numeric_arithmatic") {
     testFoldConst("SELECT ACOS(1E308)")
     testFoldConst("SELECT ACOS(-1E308)")
 
+//Acosh function cases
+    testFoldConst("SELECT ACOSH(1) AS acosh_case_1"); // acosh(1) = 0
+    testFoldConst("SELECT ACOSH(2) AS acosh_case_2"); // acosh(2) ≈ 1.316957897
+    testFoldConst("SELECT ACOSH(10) AS acosh_case_3"); // acosh(10) ≈ 
2.993222846
+    testFoldConst("SELECT ACOSH(0.5)"); // Invalid input (x < 1)
+    testFoldConst("SELECT ACOSH(-1)"); // Invalid input (x < 1)
+    testFoldConst("SELECT ACOSH(NULL)"); // NULL handling
+    testFoldConst("SELECT ACOSH(1E308)"); // Large value
+    testFoldConst("SELECT ACOSH(-1E308)"); // Invalid input (x < 1)
+    testFoldConst("SELECT ACOSH(1), ACOSH(2), ACOSH(10)"); // Multiple values
+
 //Asin function cases
     testFoldConst("SELECT ASIN(1) AS asin_case_1") //asin(1) = π/2
     testFoldConst("SELECT ASIN(0) AS asin_case_2") //asin(0) = 0
@@ -65,6 +76,17 @@ suite("fold_constant_numeric_arithmatic") {
     testFoldConst("SELECT ASIN(1E308)")
     testFoldConst("SELECT ASIN(-1E308)")
 
+//Asinh function cases
+    testFoldConst("SELECT ASINH(0) AS asinh_case_1"); // asinh(0) = 0
+    testFoldConst("SELECT ASINH(1) AS asinh_case_2"); // asinh(1) ≈ 0.881373587
+    testFoldConst("SELECT ASINH(-1) AS asinh_case_3"); // asinh(-1) ≈ 
-0.881373587
+    testFoldConst("SELECT ASINH(0.5)"); // Common value
+    testFoldConst("SELECT ASINH(-0.5)"); // Negative common value
+    testFoldConst("SELECT ASINH(NULL)"); // NULL handling
+    testFoldConst("SELECT ASINH(1E308)"); // Large value
+    testFoldConst("SELECT ASINH(-1E308)"); // Large negative value
+    testFoldConst("SELECT ASINH(0), ASINH(1), ASINH(-1)"); // Multiple values
+
 //Atan function cases
     testFoldConst("SELECT ATAN(1) AS atan_case_1") //atan(1) = π/4
     testFoldConst("SELECT ATAN(0) AS atan_case_2") //atan(0) = 0
@@ -77,7 +99,22 @@ suite("fold_constant_numeric_arithmatic") {
     testFoldConst("SELECT ATAN(PI())") // PI input
     testFoldConst("SELECT ATAN(-PI())") // Negative PI input
     testFoldConst("SELECT ATAN(1E-308)") // Very small positive number
-    testFoldConst("SELECT ATAN(-1E-308)") // Very small negative number
+    testFoldConst("SELECT ATAN(-1E-308)") // Very small negative 
+    
+//Atanh function cases
+    testFoldConst("SELECT ATANH(0) AS atanh_case_1"); // atanh(0) = 0
+    testFoldConst("SELECT ATANH(0.5) AS atanh_case_2"); // atanh(0.5) ≈ 
0.549306144
+    testFoldConst("SELECT ATANH(-0.5) AS atanh_case_3"); // atanh(-0.5) ≈ 
-0.549306144
+    testFoldConst("SELECT ATANH(0.9)"); // Common value
+    testFoldConst("SELECT ATANH(-0.9)"); // Negative common value
+    testFoldConst("SELECT ATANH(NULL)"); // NULL handling
+    testFoldConst("SELECT ATANH(1)"); // Boundary value (invalid)
+    testFoldConst("SELECT ATANH(-1)"); // Boundary value (invalid)
+    testFoldConst("SELECT ATANH(1.5)"); // Invalid input (x > 1)
+    testFoldConst("SELECT ATANH(-1.5)"); // Invalid input (x < -1)
+    testFoldConst("SELECT ATANH(1E-308)"); // Very small positive number
+    testFoldConst("SELECT ATANH(-1E-308)"); // Very small negative number
+    testFoldConst("SELECT ATANH(0), ATANH(0.5), ATANH(-0.5)"); // Multiple 
values
 
 //Atan2 function cases
     testFoldConst("SELECT ATAN2(1, 1) AS atan2_case_1") //atan2(1, 1) = π/4
@@ -455,6 +492,15 @@ suite("fold_constant_numeric_arithmatic") {
     testFoldConst("SELECT SIN(1E308) AS sin_case_overflow")
     testFoldConst("SELECT sin(0), sin(pi()/2), sin(pi()), sin(3*pi()/2)")
 
+// Sinh function cases
+    testFoldConst("SELECT SINH(0) AS sinh_case_1"); // sinh(0) = 0
+    testFoldConst("SELECT SINH(1) AS sinh_case_2"); // sinh(1) ≈ 1.175201194
+    testFoldConst("SELECT SINH(-1) AS sinh_case_3"); // sinh(-1) ≈ -1.175201194
+    testFoldConst("SELECT SINH(2) AS sinh_case_4"); // sinh(2) ≈ 3.626860408
+    testFoldConst("SELECT SINH(NULL)"); // NULL handling
+    // testFoldConst("SELECT SINH(1E308) AS sinh_case_overflow"); // Error for 
input String "inf"
+    testFoldConst("SELECT SINH(0), SINH(1), SINH(-1), SINH(2)"); // Multi value
+
 //Sqrt function cases
     testFoldConst("SELECT SQRT(16) AS sqrt_case_1") //sqrt(16) = 4
     testFoldConst("SELECT SQRT(0) AS sqrt_case_2") //sqrt(0) = 0
diff --git 
a/regression-test/suites/query_p0/sql_functions/math_functions/test_math_unary_always_nullable.groovy
 
b/regression-test/suites/query_p0/sql_functions/math_functions/test_math_unary_always_nullable.groovy
index 282d4e3c575..64b9ddc01ef 100644
--- 
a/regression-test/suites/query_p0/sql_functions/math_functions/test_math_unary_always_nullable.groovy
+++ 
b/regression-test/suites/query_p0/sql_functions/math_functions/test_math_unary_always_nullable.groovy
@@ -30,6 +30,16 @@ suite("test_math_unary_alway_nullable") {
         select acos(-1.1), acos(-1.1) is NULL, number from 
numbers("number"="10")
     """
 
+    qt_acosh_1 """
+        select acosh(-1.1), acosh(-1.1) is null;
+    """
+    qt_acosh_2 """
+        select acosh(0.0), acosh(0.0) is null;
+    """
+    qt_acosh_3 """
+        select acosh(1.1), acosh(1.1) is NULL, number from 
numbers("number"="10")
+    """
+
     qt_asin_1 """
         select asin(1.1), asin(1.1) is null;
     """
@@ -40,6 +50,16 @@ suite("test_math_unary_alway_nullable") {
         select asin(-1.1), asin(-1.1) is NULL, number from 
numbers("number"="10")
     """
 
+    qt_atanh_1 """
+        select atanh(-1.0), atanh(-1.0) is null;
+    """
+    qt_atanh_2 """
+        select atanh(1.0), atanh(1.0) is null;
+    """
+    qt_atanh_3 """
+        select atanh(0.0), atanh(0.0) is NULL, number from 
numbers("number"="10")
+    """
+
     qt_sqrt_1 """
         select sqrt(-1), sqrt(-1) is null;
     """
@@ -70,10 +90,18 @@ suite("test_math_unary_alway_nullable") {
         select rowid, acos(val), acos(val) is null from 
test_math_unary_alway_nullable order by rowid;
     """
 
+    qt_acosh_tbl_1 """
+        select rowid, acosh(val), acosh(val) is null from 
test_math_unary_alway_nullable order by rowid;
+    """
+
     qt_asin_tbl_1 """
         select rowid, asin(val), asin(val) is null from 
test_math_unary_alway_nullable order by rowid;
     """
 
+    qt_atanh_tbl_1 """
+        select rowid, atanh(val), atanh(val) is null from 
test_math_unary_alway_nullable order by rowid;
+    """
+
     qt_sqrt_tbl_1 """
         select rowid, sqrt(val), sqrt(val) is null from 
test_math_unary_alway_nullable order by rowid;
     """
@@ -82,4 +110,4 @@ suite("test_math_unary_alway_nullable") {
         select rowid, dsqrt(val), dsqrt(val) is null from 
test_math_unary_alway_nullable order by rowid;
     """
 
-}
\ No newline at end of file
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org
For additional commands, e-mail: commits-h...@doris.apache.org


Reply via email to