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]