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

zclllyybb 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 a2e76e080e7 [Fix](nereids) Preserve negative zero sign in SIGNBIT 
constant folding (#63954)
a2e76e080e7 is described below

commit a2e76e080e74759058406bb0e927160115bbd5e5
Author: linrrarity <[email protected]>
AuthorDate: Tue Jun 2 09:57:29 2026 +0800

    [Fix](nereids) Preserve negative zero sign in SIGNBIT constant folding 
(#63954)
    
    Problem Summary:
    
    `signbit` in Nereids FE constant folding used `value < 0` to determine
    the sign, which treats `-0.0` as non-negative and folds it to `false`.
    This is inconsistent with:
    - the runtime BE implementation, which uses `std::signbit`
    - the documented `signbit` behavior, which distinguishes `+0.0` and
    `-0.0`
    
    `+0.0` and `-0.0` compare equal numerically, so `value < 0` cannot
    distinguish them. Their difference is only recorded in the
    floating-point sign bit. Using raw bits makes FE constant folding
    consistent with BE runtime semantics.
    
    before:
    ```text
    Doris> set debug_skip_fold_constant=true;
    Query OK, 0 rows affected (0.024 sec)
    
    Doris> select signbit(cast('+0.0' as double)) , signbit(cast('-0.0' as 
double));
    +---------------------------------+---------------------------------+
    | signbit(cast('+0.0' as double)) | signbit(cast('-0.0' as double)) |
    +---------------------------------+---------------------------------+
    |                               0 |                               1 |
    +---------------------------------+---------------------------------+
    1 row in set (0.108 sec)
    
    Doris> set debug_skip_fold_constant=false;
    Query OK, 0 rows affected (0.002 sec)
    
    Doris> select signbit(cast('+0.0' as double)) , signbit(cast('-0.0' as 
double));
    +---------------------------------+---------------------------------+
    | signbit(cast('+0.0' as double)) | signbit(cast('-0.0' as double)) |
    +---------------------------------+---------------------------------+
    |                               0 |                               0 |
    +---------------------------------+---------------------------------+
    ```
    
    now:
    ```text
    Doris> set debug_skip_fold_constant=true;
    Query OK, 0 rows affected (0.012 sec)
    
    Doris> select signbit(cast('+0.0' as double)) , signbit(cast('-0.0' as 
double));
    +---------------------------------+---------------------------------+
    | signbit(cast('+0.0' as double)) | signbit(cast('-0.0' as double)) |
    +---------------------------------+---------------------------------+
    |                               0 |                               1 |
    +---------------------------------+---------------------------------+
    1 row in set (0.070 sec)
    
    Doris> set debug_skip_fold_constant=false;
    Query OK, 0 rows affected (0.002 sec)
    
    Doris> select signbit(cast('+0.0' as double)) , signbit(cast('-0.0' as 
double));
    +---------------------------------+---------------------------------+
    | signbit(cast('+0.0' as double)) | signbit(cast('-0.0' as double)) |
    +---------------------------------+---------------------------------+
    |                               0 |                               1 |
    +---------------------------------+---------------------------------+
    1 row in set (0.010 sec)
    ```
---
 .../expressions/functions/executable/NumericArithmetic.java    |  6 +-----
 .../functions/executable/NumericArithmeticTest.java            | 10 ++++++++++
 regression-test/data/nereids_function_p0/scalar_function/S.out |  3 +++
 .../suites/nereids_function_p0/scalar_function/S.groovy        |  2 ++
 4 files changed, 16 insertions(+), 5 deletions(-)

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 1fa7c4fe349..6f664e2fadf 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
@@ -730,11 +730,7 @@ public class NumericArithmetic {
      */
     @ExecFunction(name = "signbit")
     public static Expression signbit(DoubleLiteral first) {
-        if (first.getValue() < 0) {
-            return BooleanLiteral.of(true);
-        } else {
-            return BooleanLiteral.of(false);
-        }
+        return BooleanLiteral.of(Double.doubleToRawLongBits(first.getValue()) 
< 0);
     }
 
     /**
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/functions/executable/NumericArithmeticTest.java
 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/functions/executable/NumericArithmeticTest.java
index 5e2f70d91dd..749a57e8b5d 100644
--- 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/functions/executable/NumericArithmeticTest.java
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/functions/executable/NumericArithmeticTest.java
@@ -17,8 +17,10 @@
 
 package org.apache.doris.nereids.trees.expressions.functions.executable;
 
+import org.apache.doris.nereids.trees.expressions.literal.BooleanLiteral;
 import org.apache.doris.nereids.trees.expressions.literal.DecimalLiteral;
 import org.apache.doris.nereids.trees.expressions.literal.DecimalV3Literal;
+import org.apache.doris.nereids.trees.expressions.literal.DoubleLiteral;
 import org.apache.doris.nereids.types.DecimalV2Type;
 import org.apache.doris.nereids.types.DecimalV3Type;
 
@@ -44,4 +46,12 @@ public class NumericArithmeticTest {
         DecimalLiteral result = (DecimalLiteral) 
NumericArithmetic.abs(decimalV3Literal);
         Assertions.assertEquals(DecimalV2Type.createDecimalV2Type(10, 0), 
result.getDataType());
     }
+
+    @Test
+    public void testSignBit() {
+        Assertions.assertEquals(BooleanLiteral.FALSE, 
NumericArithmetic.signbit(new DoubleLiteral(0.0)));
+        Assertions.assertEquals(BooleanLiteral.TRUE, 
NumericArithmetic.signbit(new DoubleLiteral(-0.0)));
+        Assertions.assertEquals(BooleanLiteral.FALSE, 
NumericArithmetic.signbit(new DoubleLiteral(1.0)));
+        Assertions.assertEquals(BooleanLiteral.TRUE, 
NumericArithmetic.signbit(new DoubleLiteral(-1.0)));
+    }
 }
diff --git a/regression-test/data/nereids_function_p0/scalar_function/S.out 
b/regression-test/data/nereids_function_p0/scalar_function/S.out
index 2c4d7d2f14f..e339f13bd5e 100644
--- a/regression-test/data/nereids_function_p0/scalar_function/S.out
+++ b/regression-test/data/nereids_function_p0/scalar_function/S.out
@@ -994,6 +994,9 @@ false
 false
 false
 
+-- !sql_signbit_negative_zero --
+false  true
+
 -- !sql_sin_Double --
 \N
 0.09983341664682815
diff --git 
a/regression-test/suites/nereids_function_p0/scalar_function/S.groovy 
b/regression-test/suites/nereids_function_p0/scalar_function/S.groovy
index ef993f2775b..cce6d4ac83e 100644
--- a/regression-test/suites/nereids_function_p0/scalar_function/S.groovy
+++ b/regression-test/suites/nereids_function_p0/scalar_function/S.groovy
@@ -90,6 +90,8 @@ suite("nereids_scalar_fn_S") {
        qt_sql_sign_Double_notnull "select sign(kdbl) from fn_test_not_nullable 
order by kdbl"
        qt_sql_signbit_Double "select signbit(kdbl) from fn_test order by kdbl"
        qt_sql_signbit_Double_notnull "select signbit(kdbl) from 
fn_test_not_nullable order by kdbl"
+       qt_sql_signbit_negative_zero "select signbit(cast('+0.0' as double)), 
signbit(cast('-0.0' as double))"
+       testFoldConst("select signbit(cast('+0.0' as double)), 
signbit(cast('-0.0' as double))")
        qt_sql_sin_Double "select sin(kdbl) from fn_test order by kdbl"
        qt_sql_sin_Double_notnull "select sin(kdbl) from fn_test_not_nullable 
order by kdbl"
        qt_sql_sleep_Integer "select sleep(0.1) from fn_test order by kint"


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to