Skip to content

feat: Support IEEE 754 negative zero semantics - #22835

Merged
comphead merged 5 commits into
apache:mainfrom
comphead:array_nan
Jun 9, 2026
Merged

feat: Support IEEE 754 negative zero semantics#22835
comphead merged 5 commits into
apache:mainfrom
comphead:array_nan

Conversation

@comphead

@compheadcomphead commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Which issue does this PR close?

Rationale for this change

SQL (per PG and IEEE 754) treats +0.0 and -0.0 as equal in =, IS DISTINCT FROM, DISTINCT, GROUP BY, UNION/INTERSECT/EXCEPT, equi-joins, and array_* set ops. DataFusion treated them as
distinct because:

  • Arrow's cmp::eq/gt/lt use IEEE 754 totalOrder for floats — arrow-ord-58.3.0/src/cmp.rs:71-75 explicitly says "please normalize zeros before calling this kernel".
  • Arrow's RowConverter row-encodes floats with totalOrder; ±0 produce different bytes.
  • DataFusion's primitive float hashing used raw to_bits() / to_ne_bytes(), so ±0 hashed to different buckets.

What changes are included in this PR?

Helper in datafusion/common/src/utils/mod.rs:

  • normalize_float_zero(&ArrayRef) -> ArrayRef — rewrites -0.0 → +0.0 for Float16/32/64 via PrimitiveArray::unary; Arc::clone for non-float. NaN payloads preserved (bits << 1 == 0 matches only
    ±0).
  • normalize_float_zero_scalar(ScalarValue) -> ScalarValue — symmetric for scalars.

Applied at six boundary sites where DataFusion hands float data to Arrow:

SiteFixes
physical-expr-common/src/datum.rs::apply_cmpBinaryExpr =, <, >, IS DISTINCT FROM
physical-plan/src/joins/utils.rs::eq_dyn_nullHashJoin row equality → INNER JOIN, INTERSECT, EXCEPT
physical-plan/src/aggregates/group_values/row.rs::internMulti-column row-encoded GROUP BY
functions-nested/src/set_ops.rs::general_array_distinctarray_distinct
functions-nested/src/set_ops.rs::generic_set_listsarray_union, array_intersect
functions-nested/src/except.rs::general_exceptarray_except

Float hash macros normalize for consistency:

  • datafusion/common/src/hash_utils.rs::hash_float_value!create_hashes, hash joins, shuffle.
  • datafusion/physical-plan/src/aggregates/group_values/single_group_by/primitive.rs::hash_float! — single-column primitive GROUP BY fast path.

Single-column primitive GROUP BY / DISTINCT (GroupValuesPrimitive::intern, PrimitiveGroupValueBuilder::{append_val,vectorized_append,equal_to,vectorized_equal_to_*}) canonicalize the input via
a new default-identity canonicalize method on the local HashValue trait (float override only). Trait visibility lifted to pub so the multi-column file can use it.

@github-actionsgithub-actionsBot added physical-expr Changes to the physical-expr crates sqllogictest SQL Logic Tests (.slt) common Related to common crate functions Changes to functions implementation physical-plan Changes to the physical-plan crate labels Jun 9, 2026
@comphead

Copy link
Copy Markdown
ContributorAuthor

run benchmark tpch tpcds

@adriangbot

Copy link
Copy Markdown

🤖 Benchmark running (GKE) | trigger
Instance:c4a-highmem-16 (12 vCPU / 65 GiB) | Linux bench-c4655326814-495-cz9fl 6.12.68+ #1 SMP Sat May 2 07:49:07 UTC 2026 aarch64 GNU/Linux

CPU Details (lscpu)
Architecture: aarch64
CPU op-mode(s): 64-bit
Byte Order: Little Endian
CPU(s): 16
On-line CPU(s) list: 0-15
Vendor ID: ARM
Model name: Neoverse-V2
Model: 1
Thread(s) per core: 1
Core(s) per cluster: 16
Socket(s): -
Cluster(s): 1
Stepping: r0p1
BogoMIPS: 2000.00
Flags: fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm jscvt fcma lrcpc dcpop sha3 sm3 sm4 asimddp sha512 sve asimdfhm dit uscat ilrcpc flagm sb paca pacg dcpodp sve2 sveaes svepmull svebitperm svesha3 svesm4 flagm2 frint svei8mm svebf16 i8mm bf16 dgh rng bti
L1d cache: 1 MiB (16 instances)
L1i cache: 1 MiB (16 instances)
L2 cache: 32 MiB (16 instances)
L3 cache: 80 MiB (1 instance)
NUMA node(s): 1
NUMA node0 CPU(s): 0-15
Vulnerability Gather data sampling: Not affected
Vulnerability Indirect target selection: Not affected
Vulnerability Itlb multihit: Not affected
Vulnerability L1tf: Not affected
Vulnerability Mds: Not affected
Vulnerability Meltdown: Not affected
Vulnerability Mmio stale data: Not affected
Vulnerability Reg file data sampling: Not affected
Vulnerability Retbleed: Not affected
Vulnerability Spec rstack overflow: Not affected
Vulnerability Spec store bypass: Mitigation; Speculative Store Bypass disabled via prctl
Vulnerability Spectre v1: Mitigation; __user pointer sanitization
Vulnerability Spectre v2: Mitigation; CSV2, BHB
Vulnerability Srbds: Not affected
Vulnerability Tsa: Not affected
Vulnerability Tsx async abort: Not affected
Vulnerability Vmscape: Not affected

Comparing array_nan (1a564ec) to 883c38e (merge-base) diff using: tpch
Results will be posted here when complete


File an issue against this benchmark runner

@adriangbot

Copy link
Copy Markdown

🤖 Benchmark running (GKE) | trigger
Instance:c4a-highmem-16 (12 vCPU / 65 GiB) | Linux bench-c4655326814-496-kmqln 6.12.68+ #1 SMP Sat May 2 07:49:07 UTC 2026 aarch64 GNU/Linux

CPU Details (lscpu)
Architecture: aarch64
CPU op-mode(s): 64-bit
Byte Order: Little Endian
CPU(s): 16
On-line CPU(s) list: 0-15
Vendor ID: ARM
Model name: Neoverse-V2
Model: 1
Thread(s) per core: 1
Core(s) per cluster: 16
Socket(s): -
Cluster(s): 1
Stepping: r0p1
BogoMIPS: 2000.00
Flags: fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm jscvt fcma lrcpc dcpop sha3 sm3 sm4 asimddp sha512 sve asimdfhm dit uscat ilrcpc flagm sb paca pacg dcpodp sve2 sveaes svepmull svebitperm svesha3 svesm4 flagm2 frint svei8mm svebf16 i8mm bf16 dgh rng bti
L1d cache: 1 MiB (16 instances)
L1i cache: 1 MiB (16 instances)
L2 cache: 32 MiB (16 instances)
L3 cache: 80 MiB (1 instance)
NUMA node(s): 1
NUMA node0 CPU(s): 0-15
Vulnerability Gather data sampling: Not affected
Vulnerability Indirect target selection: Not affected
Vulnerability Itlb multihit: Not affected
Vulnerability L1tf: Not affected
Vulnerability Mds: Not affected
Vulnerability Meltdown: Not affected
Vulnerability Mmio stale data: Not affected
Vulnerability Reg file data sampling: Not affected
Vulnerability Retbleed: Not affected
Vulnerability Spec rstack overflow: Not affected
Vulnerability Spec store bypass: Mitigation; Speculative Store Bypass disabled via prctl
Vulnerability Spectre v1: Mitigation; __user pointer sanitization
Vulnerability Spectre v2: Mitigation; CSV2, BHB
Vulnerability Srbds: Not affected
Vulnerability Tsa: Not affected
Vulnerability Tsx async abort: Not affected
Vulnerability Vmscape: Not affected

Comparing array_nan (1a564ec) to 883c38e (merge-base) diff using: tpcds
Results will be posted here when complete


File an issue against this benchmark runner

@adriangbot

Copy link
Copy Markdown

🤖 Benchmark completed (GKE) | trigger

Instance:c4a-highmem-16 (12 vCPU / 65 GiB)

CPU Details (lscpu)
Architecture: aarch64
CPU op-mode(s): 64-bit
Byte Order: Little Endian
CPU(s): 16
On-line CPU(s) list: 0-15
Vendor ID: ARM
Model name: Neoverse-V2
Model: 1
Thread(s) per core: 1
Core(s) per cluster: 16
Socket(s): -
Cluster(s): 1
Stepping: r0p1
BogoMIPS: 2000.00
Flags: fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm jscvt fcma lrcpc dcpop sha3 sm3 sm4 asimddp sha512 sve asimdfhm dit uscat ilrcpc flagm sb paca pacg dcpodp sve2 sveaes svepmull svebitperm svesha3 svesm4 flagm2 frint svei8mm svebf16 i8mm bf16 dgh rng bti
L1d cache: 1 MiB (16 instances)
L1i cache: 1 MiB (16 instances)
L2 cache: 32 MiB (16 instances)
L3 cache: 80 MiB (1 instance)
NUMA node(s): 1
NUMA node0 CPU(s): 0-15
Vulnerability Gather data sampling: Not affected
Vulnerability Indirect target selection: Not affected
Vulnerability Itlb multihit: Not affected
Vulnerability L1tf: Not affected
Vulnerability Mds: Not affected
Vulnerability Meltdown: Not affected
Vulnerability Mmio stale data: Not affected
Vulnerability Reg file data sampling: Not affected
Vulnerability Retbleed: Not affected
Vulnerability Spec rstack overflow: Not affected
Vulnerability Spec store bypass: Mitigation; Speculative Store Bypass disabled via prctl
Vulnerability Spectre v1: Mitigation; __user pointer sanitization
Vulnerability Spectre v2: Mitigation; CSV2, BHB
Vulnerability Srbds: Not affected
Vulnerability Tsa: Not affected
Vulnerability Tsx async abort: Not affected
Vulnerability Vmscape: Not affected
Details

Comparing HEAD and array_nan
--------------------
Benchmark tpch_sf1.json
--------------------
┏━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓
┃ Query ┃ HEAD ┃ array_nan ┃ Change ┃
┡━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩
│ QQuery 1 │ 38.72 / 41.03 ±2.85 / 46.43 ms │ 38.38 / 39.63 ±1.14 / 41.10 ms │ no change │
│ QQuery 2 │ 18.55 / 19.35 ±0.63 / 20.46 ms │ 18.58 / 19.20 ±0.73 / 20.60 ms │ no change │
│ QQuery 3 │ 31.16 / 34.84 ±3.23 / 39.72 ms │ 30.85 / 32.81 ±2.28 / 36.70 ms │ +1.06x faster │
│ QQuery 4 │ 17.52 / 17.93 ±0.58 / 19.08 ms │ 17.09 / 17.26 ±0.16 / 17.50 ms │ no change │
│ QQuery 5 │ 38.30 / 40.71 ±1.25 / 41.91 ms │ 39.53 / 40.19 ±0.44 / 40.78 ms │ no change │
│ QQuery 6 │ 16.47 / 16.56 ±0.10 / 16.71 ms │ 16.35 / 16.98 ±0.39 / 17.43 ms │ no change │
│ QQuery 7 │ 44.59 / 46.73 ±2.24 / 49.89 ms │ 43.45 / 45.16 ±1.39 / 46.89 ms │ no change │
│ QQuery 8 │ 43.35 / 43.72 ±0.32 / 44.23 ms │ 42.92 / 43.20 ±0.19 / 43.40 ms │ no change │
│ QQuery 9 │ 49.30 / 50.35 ±0.87 / 51.84 ms │ 49.12 / 50.19 ±0.91 / 51.75 ms │ no change │
│ QQuery 10 │ 42.29 / 42.74 ±0.31 / 43.15 ms │ 42.07 / 42.31 ±0.15 / 42.51 ms │ no change │
│ QQuery 11 │ 13.09 / 13.66 ±0.62 / 14.47 ms │ 13.24 / 13.51 ±0.32 / 14.02 ms │ no change │
│ QQuery 12 │ 23.56 / 24.29 ±0.39 / 24.70 ms │ 24.39 / 25.15 ±0.83 / 26.75 ms │ no change │
│ QQuery 13 │ 31.80 / 34.65 ±2.42 / 38.97 ms │ 31.94 / 33.95 ±1.63 / 36.88 ms │ no change │
│ QQuery 14 │ 23.80 / 23.92 ±0.10 / 24.08 ms │ 23.90 / 23.97 ±0.10 / 24.18 ms │ no change │
│ QQuery 15 │ 31.36 / 32.36 ±1.13 / 34.46 ms │ 31.46 / 31.65 ±0.19 / 31.96 ms │ no change │
│ QQuery 16 │ 13.90 / 14.13 ±0.16 / 14.27 ms │ 13.76 / 14.07 ±0.20 / 14.35 ms │ no change │
│ QQuery 17 │ 73.23 / 73.97 ±0.57 / 74.94 ms │ 73.18 / 74.28 ±0.99 / 75.87 ms │ no change │
│ QQuery 18 │ 57.16 / 59.53 ±1.50 / 61.70 ms │ 58.07 / 60.81 ±3.16 / 66.92 ms │ no change │
│ QQuery 19 │ 32.91 / 33.21 ±0.40 / 34.00 ms │ 32.88 / 33.21 ±0.34 / 33.76 ms │ no change │
│ QQuery 20 │ 32.14 / 32.83 ±0.46 / 33.58 ms │ 32.00 / 32.89 ±0.95 / 34.71 ms │ no change │
│ QQuery 21 │ 56.95 / 58.37 ±1.10 / 60.14 ms │ 55.91 / 58.41 ±2.28 / 61.88 ms │ no change │
│ QQuery 22 │ 14.07 / 14.20 ±0.10 / 14.37 ms │ 14.03 / 14.34 ±0.36 / 15.04 ms │ no change │
└───────────┴────────────────────────────────┴────────────────────────────────┴───────────────┘
┏━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━┓
┃ Benchmark Summary ┃ ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━┩
│ Total Time (HEAD) │ 769.08ms │
│ Total Time (array_nan) │ 763.21ms │
│ Average Time (HEAD) │ 34.96ms │
│ Average Time (array_nan) │ 34.69ms │
│ Queries Faster │ 1 │
│ Queries Slower │ 0 │
│ Queries with No Change │ 21 │
│ Queries with Failure │ 0 │
└──────────────────────────┴──────────┘

Resource Usage

tpch — base (merge-base)

MetricValue
Wall time5.0s
Peak memory4.6 GiB
Avg memory3.8 GiB
CPU user30.1s
CPU sys2.4s
Peak spill0 B

tpch — branch

MetricValue
Wall time5.0s
Peak memory4.6 GiB
Avg memory3.8 GiB
CPU user30.1s
CPU sys2.3s
Peak spill0 B

File an issue against this benchmark runner

@adriangbot

Copy link
Copy Markdown

🤖 Benchmark completed (GKE) | trigger

Instance:c4a-highmem-16 (12 vCPU / 65 GiB)

CPU Details (lscpu)
Architecture: aarch64
CPU op-mode(s): 64-bit
Byte Order: Little Endian
CPU(s): 16
On-line CPU(s) list: 0-15
Vendor ID: ARM
Model name: Neoverse-V2
Model: 1
Thread(s) per core: 1
Core(s) per cluster: 16
Socket(s): -
Cluster(s): 1
Stepping: r0p1
BogoMIPS: 2000.00
Flags: fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm jscvt fcma lrcpc dcpop sha3 sm3 sm4 asimddp sha512 sve asimdfhm dit uscat ilrcpc flagm sb paca pacg dcpodp sve2 sveaes svepmull svebitperm svesha3 svesm4 flagm2 frint svei8mm svebf16 i8mm bf16 dgh rng bti
L1d cache: 1 MiB (16 instances)
L1i cache: 1 MiB (16 instances)
L2 cache: 32 MiB (16 instances)
L3 cache: 80 MiB (1 instance)
NUMA node(s): 1
NUMA node0 CPU(s): 0-15
Vulnerability Gather data sampling: Not affected
Vulnerability Indirect target selection: Not affected
Vulnerability Itlb multihit: Not affected
Vulnerability L1tf: Not affected
Vulnerability Mds: Not affected
Vulnerability Meltdown: Not affected
Vulnerability Mmio stale data: Not affected
Vulnerability Reg file data sampling: Not affected
Vulnerability Retbleed: Not affected
Vulnerability Spec rstack overflow: Not affected
Vulnerability Spec store bypass: Mitigation; Speculative Store Bypass disabled via prctl
Vulnerability Spectre v1: Mitigation; __user pointer sanitization
Vulnerability Spectre v2: Mitigation; CSV2, BHB
Vulnerability Srbds: Not affected
Vulnerability Tsa: Not affected
Vulnerability Tsx async abort: Not affected
Vulnerability Vmscape: Not affected
Details

Comparing HEAD and array_nan
--------------------
Benchmark tpcds_sf1.json
--------------------
┏━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓
┃ Query ┃ HEAD ┃ array_nan ┃ Change ┃
┡━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩
│ QQuery 1 │ 5.84 / 6.32 ±0.81 / 7.94 ms │ 5.75 / 6.24 ±0.89 / 8.02 ms │ no change │
│ QQuery 2 │ 79.90 / 80.25 ±0.25 / 80.66 ms │ 80.04 / 80.32 ±0.25 / 80.77 ms │ no change │
│ QQuery 3 │ 28.89 / 28.97 ±0.11 / 29.19 ms │ 28.50 / 28.67 ±0.14 / 28.89 ms │ no change │
│ QQuery 4 │ 488.11 / 495.30 ±4.79 / 500.60 ms │ 471.40 / 479.53 ±10.33 / 499.75 ms │ no change │
│ QQuery 5 │ 51.40 / 51.84 ±0.25 / 52.09 ms │ 51.22 / 52.12 ±0.59 / 53.03 ms │ no change │
│ QQuery 6 │ 36.88 / 37.10 ±0.27 / 37.53 ms │ 36.03 / 36.68 ±0.51 / 37.61 ms │ no change │
│ QQuery 7 │ 94.63 / 95.43 ±0.52 / 96.23 ms │ 95.55 / 96.16 ±0.44 / 96.82 ms │ no change │
│ QQuery 8 │ 37.16 / 38.32 ±1.98 / 42.27 ms │ 36.94 / 39.24 ±3.37 / 45.87 ms │ no change │
│ QQuery 9 │ 53.62 / 55.87 ±2.30 / 60.14 ms │ 52.03 / 53.47 ±1.12 / 55.36 ms │ no change │
│ QQuery 10 │ 62.38 / 62.90 ±0.32 / 63.37 ms │ 62.88 / 63.17 ±0.35 / 63.84 ms │ no change │
│ QQuery 11 │ 297.92 / 301.68 ±3.81 / 308.17 ms │ 288.80 / 296.23 ±7.71 / 307.70 ms │ no change │
│ QQuery 12 │ 28.85 / 29.12 ±0.20 / 29.44 ms │ 28.67 / 29.13 ±0.60 / 30.29 ms │ no change │
│ QQuery 13 │ 118.95 / 119.47 ±0.44 / 120.16 ms │ 119.00 / 120.23 ±0.86 / 121.55 ms │ no change │
│ QQuery 14 │ 407.55 / 413.73 ±5.50 / 421.95 ms │ 408.08 / 409.99 ±1.61 / 411.94 ms │ no change │
│ QQuery 15 │ 58.66 / 59.07 ±0.34 / 59.59 ms │ 57.88 / 58.76 ±0.56 / 59.64 ms │ no change │
│ QQuery 16 │ 6.75 / 6.94 ±0.20 / 7.32 ms │ 6.75 / 6.86 ±0.11 / 7.06 ms │ no change │
│ QQuery 17 │ 80.98 / 81.41 ±0.32 / 81.90 ms │ 80.70 / 81.72 ±1.26 / 84.17 ms │ no change │
│ QQuery 18 │ 124.64 / 126.34 ±1.38 / 128.49 ms │ 124.49 / 126.46 ±1.53 / 128.93 ms │ no change │
│ QQuery 19 │ 41.68 / 41.84 ±0.10 / 41.99 ms │ 41.36 / 41.51 ±0.20 / 41.89 ms │ no change │
│ QQuery 20 │ 35.26 / 35.53 ±0.32 / 36.14 ms │ 35.17 / 35.51 ±0.37 / 36.18 ms │ no change │
│ QQuery 21 │ 16.85 / 17.13 ±0.26 / 17.52 ms │ 16.72 / 17.09 ±0.29 / 17.54 ms │ no change │
│ QQuery 22 │ 61.96 / 63.70 ±2.54 / 68.75 ms │ 62.09 / 63.59 ±2.19 / 67.82 ms │ no change │
│ QQuery 23 │ 319.24 / 321.29 ±1.56 / 324.06 ms │ 314.88 / 317.74 ±1.74 / 319.82 ms │ no change │
│ QQuery 24 │ 221.77 / 224.34 ±2.00 / 227.72 ms │ 222.61 / 226.14 ±3.66 / 233.06 ms │ no change │
│ QQuery 25 │ 110.10 / 111.51 ±1.38 / 114.09 ms │ 111.02 / 114.34 ±4.83 / 123.96 ms │ no change │
│ QQuery 26 │ 57.61 / 58.15 ±0.37 / 58.67 ms │ 57.31 / 57.84 ±0.38 / 58.48 ms │ no change │
│ QQuery 27 │ 6.60 / 7.63 ±1.76 / 11.13 ms │ 6.60 / 6.76 ±0.13 / 6.98 ms │ +1.13x faster │
│ QQuery 28 │ 56.31 / 61.16 ±3.70 / 67.39 ms │ 56.43 / 59.76 ±2.33 / 61.92 ms │ no change │
│ QQuery 29 │ 97.85 / 98.54 ±0.70 / 99.80 ms │ 97.09 / 99.59 ±2.99 / 105.19 ms │ no change │
│ QQuery 30 │ 32.22 / 32.84 ±0.45 / 33.34 ms │ 32.10 / 32.47 ±0.25 / 32.76 ms │ no change │
│ QQuery 31 │ 111.56 / 113.78 ±2.72 / 119.01 ms │ 111.06 / 112.05 ±0.72 / 113.05 ms │ no change │
│ QQuery 32 │ 20.47 / 20.68 ±0.15 / 20.80 ms │ 19.84 / 20.24 ±0.39 / 20.82 ms │ no change │
│ QQuery 33 │ 38.38 / 38.80 ±0.22 / 39.02 ms │ 38.50 / 38.89 ±0.38 / 39.61 ms │ no change │
│ QQuery 34 │ 9.33 / 9.59 ±0.20 / 9.91 ms │ 9.34 / 9.72 ±0.29 / 10.11 ms │ no change │
│ QQuery 35 │ 70.88 / 72.01 ±0.93 / 73.26 ms │ 70.85 / 71.31 ±0.27 / 71.64 ms │ no change │
│ QQuery 36 │ 5.99 / 6.13 ±0.15 / 6.42 ms │ 5.83 / 5.94 ±0.15 / 6.24 ms │ no change │
│ QQuery 37 │ 6.82 / 7.18 ±0.20 / 7.42 ms │ 6.62 / 6.75 ±0.09 / 6.84 ms │ +1.06x faster │
│ QQuery 38 │ 63.62 / 63.99 ±0.30 / 64.38 ms │ 62.37 / 63.49 ±1.02 / 65.40 ms │ no change │
│ QQuery 39 │ 448.24 / 457.21 ±7.28 / 468.75 ms │ 448.60 / 452.43 ±1.98 / 453.99 ms │ no change │
│ QQuery 40 │ 22.62 / 23.80 ±1.80 / 27.38 ms │ 22.95 / 23.03 ±0.09 / 23.21 ms │ no change │
│ QQuery 41 │ 11.09 / 11.32 ±0.28 / 11.88 ms │ 11.01 / 11.19 ±0.21 / 11.60 ms │ no change │
│ QQuery 42 │ 23.50 / 23.91 ±0.23 / 24.15 ms │ 23.28 / 24.27 ±1.58 / 27.40 ms │ no change │
│ QQuery 43 │ 4.84 / 6.29 ±2.75 / 11.79 ms │ 4.71 / 4.80 ±0.11 / 5.02 ms │ +1.31x faster │
│ QQuery 44 │ 8.94 / 9.03 ±0.09 / 9.19 ms │ 8.63 / 8.69 ±0.06 / 8.81 ms │ no change │
│ QQuery 45 │ 38.01 / 39.34 ±1.04 / 40.65 ms │ 37.41 / 39.67 ±2.60 / 44.67 ms │ no change │
│ QQuery 46 │ 11.50 / 11.94 ±0.24 / 12.15 ms │ 11.85 / 12.16 ±0.40 / 12.94 ms │ no change │
│ QQuery 47 │ 224.77 / 229.22 ±2.79 / 233.36 ms │ 228.77 / 230.40 ±1.03 / 231.80 ms │ no change │
│ QQuery 48 │ 96.35 / 96.68 ±0.24 / 97.10 ms │ 96.64 / 97.16 ±0.60 / 98.31 ms │ no change │
│ QQuery 49 │ 76.97 / 77.99 ±0.68 / 78.66 ms │ 77.53 / 80.73 ±3.80 / 87.85 ms │ no change │
│ QQuery 50 │ 59.69 / 60.04 ±0.37 / 60.73 ms │ 59.60 / 60.05 ±0.26 / 60.29 ms │ no change │
│ QQuery 51 │ 90.97 / 95.53 ±4.44 / 103.55 ms │ 91.69 / 93.75 ±2.72 / 98.90 ms │ no change │
│ QQuery 52 │ 23.81 / 24.32 ±0.48 / 25.23 ms │ 24.12 / 26.18 ±2.73 / 31.47 ms │ 1.08x slower │
│ QQuery 53 │ 29.58 / 29.88 ±0.30 / 30.44 ms │ 29.01 / 29.62 ±0.53 / 30.23 ms │ no change │
│ QQuery 54 │ 54.76 / 55.32 ±0.49 / 56.00 ms │ 54.48 / 54.96 ±0.36 / 55.54 ms │ no change │
│ QQuery 55 │ 23.17 / 23.39 ±0.20 / 23.64 ms │ 23.01 / 23.40 ±0.29 / 23.73 ms │ no change │
│ QQuery 56 │ 38.31 / 38.58 ±0.34 / 39.24 ms │ 38.46 / 38.81 ±0.47 / 39.71 ms │ no change │
│ QQuery 57 │ 174.19 / 177.33 ±3.71 / 184.55 ms │ 174.09 / 177.25 ±2.92 / 182.69 ms │ no change │
│ QQuery 58 │ 114.75 / 116.40 ±2.13 / 120.60 ms │ 113.69 / 114.14 ±0.28 / 114.45 ms │ no change │
│ QQuery 59 │ 116.08 / 117.48 ±1.48 / 120.31 ms │ 116.31 / 117.31 ±0.80 / 118.42 ms │ no change │
│ QQuery 60 │ 39.00 / 40.27 ±0.93 / 41.27 ms │ 38.37 / 38.93 ±0.34 / 39.28 ms │ no change │
│ QQuery 61 │ 12.94 / 13.07 ±0.21 / 13.49 ms │ 13.22 / 13.36 ±0.21 / 13.77 ms │ no change │
│ QQuery 62 │ 45.53 / 46.00 ±0.35 / 46.47 ms │ 45.93 / 46.14 ±0.19 / 46.47 ms │ no change │
│ QQuery 63 │ 29.54 / 29.84 ±0.29 / 30.37 ms │ 29.02 / 29.54 ±0.41 / 30.07 ms │ no change │
│ QQuery 64 │ 393.38 / 399.14 ±5.83 / 409.98 ms │ 393.43 / 397.56 ±4.92 / 407.13 ms │ no change │
│ QQuery 65 │ 147.56 / 151.22 ±3.11 / 155.55 ms │ 144.85 / 150.67 ±4.97 / 159.38 ms │ no change │
│ QQuery 66 │ 78.69 / 79.56 ±0.65 / 80.30 ms │ 78.04 / 79.24 ±0.76 / 80.13 ms │ no change │
│ QQuery 67 │ 246.97 / 252.99 ±3.57 / 256.67 ms │ 241.84 / 245.79 ±4.07 / 253.05 ms │ no change │
│ QQuery 68 │ 11.68 / 11.98 ±0.20 / 12.29 ms │ 11.66 / 12.01 ±0.37 / 12.61 ms │ no change │
│ QQuery 69 │ 56.94 / 57.43 ±0.38 / 58.02 ms │ 57.04 / 59.26 ±3.58 / 66.40 ms │ no change │
│ QQuery 70 │ 103.84 / 104.96 ±0.64 / 105.70 ms │ 103.61 / 105.22 ±1.85 / 108.84 ms │ no change │
│ QQuery 71 │ 36.08 / 38.92 ±4.08 / 46.96 ms │ 35.25 / 36.52 ±1.74 / 39.93 ms │ +1.07x faster │
│ QQuery 72 │ 2098.49 / 2237.43 ±95.66 / 2396.76 ms │ 2069.10 / 2146.60 ±41.12 / 2186.24 ms │ no change │
│ QQuery 73 │ 9.16 / 9.59 ±0.22 / 9.76 ms │ 9.19 / 9.44 ±0.19 / 9.69 ms │ no change │
│ QQuery 74 │ 169.59 / 174.92 ±5.75 / 185.96 ms │ 168.32 / 175.00 ±6.54 / 184.02 ms │ no change │
│ QQuery 75 │ 147.85 / 148.89 ±1.14 / 150.34 ms │ 147.00 / 148.85 ±1.09 / 150.04 ms │ no change │
│ QQuery 76 │ 35.42 / 40.16 ±7.61 / 55.31 ms │ 34.91 / 35.24 ±0.26 / 35.60 ms │ +1.14x faster │
│ QQuery 77 │ 61.20 / 61.70 ±0.44 / 62.43 ms │ 60.16 / 61.11 ±0.51 / 61.58 ms │ no change │
│ QQuery 78 │ 185.12 / 188.59 ±1.86 / 190.53 ms │ 184.42 / 189.65 ±4.63 / 196.55 ms │ no change │
│ QQuery 79 │ 66.86 / 67.46 ±0.51 / 68.18 ms │ 66.54 / 69.14 ±3.61 / 76.08 ms │ no change │
│ QQuery 80 │ 101.22 / 105.58 ±6.20 / 117.69 ms │ 100.48 / 101.55 ±0.92 / 102.65 ms │ no change │
│ QQuery 81 │ 25.29 / 25.55 ±0.21 / 25.80 ms │ 25.10 / 25.55 ±0.30 / 26.04 ms │ no change │
│ QQuery 82 │ 16.01 / 16.25 ±0.21 / 16.62 ms │ 15.91 / 16.21 ±0.26 / 16.68 ms │ no change │
│ QQuery 83 │ 38.70 / 39.08 ±0.34 / 39.60 ms │ 38.94 / 41.26 ±3.86 / 48.97 ms │ 1.06x slower │
│ QQuery 84 │ 34.13 / 34.64 ±0.26 / 34.85 ms │ 34.62 / 37.23 ±3.55 / 44.25 ms │ 1.07x slower │
│ QQuery 85 │ 106.23 / 111.53 ±4.61 / 117.75 ms │ 108.05 / 108.52 ±0.38 / 109.07 ms │ no change │
│ QQuery 86 │ 24.78 / 25.05 ±0.27 / 25.51 ms │ 24.70 / 26.68 ±3.58 / 33.82 ms │ 1.07x slower │
│ QQuery 87 │ 63.66 / 64.08 ±0.22 / 64.26 ms │ 63.93 / 66.22 ±1.97 / 69.33 ms │ no change │
│ QQuery 88 │ 61.56 / 64.87 ±6.07 / 77.00 ms │ 62.02 / 62.51 ±0.68 / 63.85 ms │ no change │
│ QQuery 89 │ 35.80 / 36.10 ±0.28 / 36.60 ms │ 35.50 / 35.98 ±0.42 / 36.74 ms │ no change │
│ QQuery 90 │ 16.74 / 16.87 ±0.10 / 17.03 ms │ 16.62 / 16.96 ±0.26 / 17.31 ms │ no change │
│ QQuery 91 │ 44.38 / 44.97 ±0.37 / 45.43 ms │ 44.17 / 44.56 ±0.34 / 45.11 ms │ no change │
│ QQuery 92 │ 28.89 / 29.37 ±0.41 / 30.07 ms │ 29.02 / 31.19 ±3.04 / 37.20 ms │ 1.06x slower │
│ QQuery 93 │ 50.04 / 51.68 ±1.60 / 54.59 ms │ 49.87 / 51.21 ±1.05 / 53.00 ms │ no change │
│ QQuery 94 │ 38.21 / 40.12 ±2.69 / 45.42 ms │ 37.98 / 38.67 ±0.67 / 39.80 ms │ no change │
│ QQuery 95 │ 83.19 / 85.12 ±1.37 / 86.91 ms │ 83.58 / 85.24 ±2.17 / 89.51 ms │ no change │
│ QQuery 96 │ 23.86 / 24.08 ±0.24 / 24.49 ms │ 23.95 / 25.09 ±1.81 / 28.67 ms │ no change │
│ QQuery 97 │ 45.61 / 46.53 ±1.01 / 48.41 ms │ 46.06 / 46.48 ±0.44 / 47.20 ms │ no change │
│ QQuery 98 │ 42.98 / 44.11 ±1.00 / 45.64 ms │ 42.83 / 43.47 ±0.43 / 44.15 ms │ no change │
│ QQuery 99 │ 68.80 / 69.31 ±0.31 / 69.71 ms │ 69.36 / 70.96 ±2.65 / 76.23 ms │ no change │
└───────────┴───────────────────────────────────────┴───────────────────────────────────────┴───────────────┘
┏━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┓
┃ Benchmark Summary ┃ ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━┩
│ Total Time (HEAD) │ 10349.86ms │
│ Total Time (array_nan) │ 10210.53ms │
│ Average Time (HEAD) │ 104.54ms │
│ Average Time (array_nan) │ 103.14ms │
│ Queries Faster │ 5 │
│ Queries Slower │ 5 │
│ Queries with No Change │ 89 │
│ Queries with Failure │ 0 │
└──────────────────────────┴────────────┘

Resource Usage

tpcds — base (merge-base)

MetricValue
Wall time55.0s
Peak memory5.8 GiB
Avg memory5.1 GiB
CPU user237.7s
CPU sys6.4s
Peak spill0 B

tpcds — branch

MetricValue
Wall time55.0s
Peak memory5.7 GiB
Avg memory5.0 GiB
CPU user234.9s
CPU sys6.3s
Peak spill0 B

File an issue against this benchmark runner

@compheadcomphead changed the title feat: Support IEEE 754 for SQL opsfeat: Support IEEE 754 negative zero semanticsJun 9, 2026
@comphead

Copy link
Copy Markdown
ContributorAuthor

run benchmark tpch tpcds

@adriangbot

Copy link
Copy Markdown

🤖 Benchmark running (GKE) | trigger
Instance:c4a-highmem-16 (12 vCPU / 65 GiB) | Linux bench-c4655762895-497-bbtkh 6.12.68+ #1 SMP Sat May 2 07:49:07 UTC 2026 aarch64 GNU/Linux

CPU Details (lscpu)
Architecture: aarch64
CPU op-mode(s): 64-bit
Byte Order: Little Endian
CPU(s): 16
On-line CPU(s) list: 0-15
Vendor ID: ARM
Model name: Neoverse-V2
Model: 1
Thread(s) per core: 1
Core(s) per cluster: 16
Socket(s): -
Cluster(s): 1
Stepping: r0p1
BogoMIPS: 2000.00
Flags: fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm jscvt fcma lrcpc dcpop sha3 sm3 sm4 asimddp sha512 sve asimdfhm dit uscat ilrcpc flagm sb paca pacg dcpodp sve2 sveaes svepmull svebitperm svesha3 svesm4 flagm2 frint svei8mm svebf16 i8mm bf16 dgh rng bti
L1d cache: 1 MiB (16 instances)
L1i cache: 1 MiB (16 instances)
L2 cache: 32 MiB (16 instances)
L3 cache: 80 MiB (1 instance)
NUMA node(s): 1
NUMA node0 CPU(s): 0-15
Vulnerability Gather data sampling: Not affected
Vulnerability Indirect target selection: Not affected
Vulnerability Itlb multihit: Not affected
Vulnerability L1tf: Not affected
Vulnerability Mds: Not affected
Vulnerability Meltdown: Not affected
Vulnerability Mmio stale data: Not affected
Vulnerability Reg file data sampling: Not affected
Vulnerability Retbleed: Not affected
Vulnerability Spec rstack overflow: Not affected
Vulnerability Spec store bypass: Mitigation; Speculative Store Bypass disabled via prctl
Vulnerability Spectre v1: Mitigation; __user pointer sanitization
Vulnerability Spectre v2: Mitigation; CSV2, BHB
Vulnerability Srbds: Not affected
Vulnerability Tsa: Not affected
Vulnerability Tsx async abort: Not affected
Vulnerability Vmscape: Not affected

Comparing array_nan (beb8750) to 883c38e (merge-base) diff using: tpch
Results will be posted here when complete


File an issue against this benchmark runner

@adriangbot

Copy link
Copy Markdown

🤖 Benchmark running (GKE) | trigger
Instance:c4a-highmem-16 (12 vCPU / 65 GiB) | Linux bench-c4655762895-498-4xr8g 6.12.68+ #1 SMP Sat May 2 07:49:07 UTC 2026 aarch64 GNU/Linux

CPU Details (lscpu)
Architecture: aarch64
CPU op-mode(s): 64-bit
Byte Order: Little Endian
CPU(s): 16
On-line CPU(s) list: 0-15
Vendor ID: ARM
Model name: Neoverse-V2
Model: 1
Thread(s) per core: 1
Core(s) per cluster: 16
Socket(s): -
Cluster(s): 1
Stepping: r0p1
BogoMIPS: 2000.00
Flags: fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm jscvt fcma lrcpc dcpop sha3 sm3 sm4 asimddp sha512 sve asimdfhm dit uscat ilrcpc flagm sb paca pacg dcpodp sve2 sveaes svepmull svebitperm svesha3 svesm4 flagm2 frint svei8mm svebf16 i8mm bf16 dgh rng bti
L1d cache: 1 MiB (16 instances)
L1i cache: 1 MiB (16 instances)
L2 cache: 32 MiB (16 instances)
L3 cache: 80 MiB (1 instance)
NUMA node(s): 1
NUMA node0 CPU(s): 0-15
Vulnerability Gather data sampling: Not affected
Vulnerability Indirect target selection: Not affected
Vulnerability Itlb multihit: Not affected
Vulnerability L1tf: Not affected
Vulnerability Mds: Not affected
Vulnerability Meltdown: Not affected
Vulnerability Mmio stale data: Not affected
Vulnerability Reg file data sampling: Not affected
Vulnerability Retbleed: Not affected
Vulnerability Spec rstack overflow: Not affected
Vulnerability Spec store bypass: Mitigation; Speculative Store Bypass disabled via prctl
Vulnerability Spectre v1: Mitigation; __user pointer sanitization
Vulnerability Spectre v2: Mitigation; CSV2, BHB
Vulnerability Srbds: Not affected
Vulnerability Tsa: Not affected
Vulnerability Tsx async abort: Not affected
Vulnerability Vmscape: Not affected

Comparing array_nan (beb8750) to 883c38e (merge-base) diff using: tpcds
Results will be posted here when complete


File an issue against this benchmark runner

@adriangbot

Copy link
Copy Markdown

🤖 Benchmark completed (GKE) | trigger

Instance:c4a-highmem-16 (12 vCPU / 65 GiB)

CPU Details (lscpu)
Architecture: aarch64
CPU op-mode(s): 64-bit
Byte Order: Little Endian
CPU(s): 16
On-line CPU(s) list: 0-15
Vendor ID: ARM
Model name: Neoverse-V2
Model: 1
Thread(s) per core: 1
Core(s) per cluster: 16
Socket(s): -
Cluster(s): 1
Stepping: r0p1
BogoMIPS: 2000.00
Flags: fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm jscvt fcma lrcpc dcpop sha3 sm3 sm4 asimddp sha512 sve asimdfhm dit uscat ilrcpc flagm sb paca pacg dcpodp sve2 sveaes svepmull svebitperm svesha3 svesm4 flagm2 frint svei8mm svebf16 i8mm bf16 dgh rng bti
L1d cache: 1 MiB (16 instances)
L1i cache: 1 MiB (16 instances)
L2 cache: 32 MiB (16 instances)
L3 cache: 80 MiB (1 instance)
NUMA node(s): 1
NUMA node0 CPU(s): 0-15
Vulnerability Gather data sampling: Not affected
Vulnerability Indirect target selection: Not affected
Vulnerability Itlb multihit: Not affected
Vulnerability L1tf: Not affected
Vulnerability Mds: Not affected
Vulnerability Meltdown: Not affected
Vulnerability Mmio stale data: Not affected
Vulnerability Reg file data sampling: Not affected
Vulnerability Retbleed: Not affected
Vulnerability Spec rstack overflow: Not affected
Vulnerability Spec store bypass: Mitigation; Speculative Store Bypass disabled via prctl
Vulnerability Spectre v1: Mitigation; __user pointer sanitization
Vulnerability Spectre v2: Mitigation; CSV2, BHB
Vulnerability Srbds: Not affected
Vulnerability Tsa: Not affected
Vulnerability Tsx async abort: Not affected
Vulnerability Vmscape: Not affected
Details

Comparing HEAD and array_nan
--------------------
Benchmark tpch_sf1.json
--------------------
┏━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━┓
┃ Query ┃ HEAD ┃ array_nan ┃ Change ┃
┡━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━┩
│ QQuery 1 │ 38.43 / 39.66 ±1.01 / 41.21 ms │ 38.32 / 39.16 ±1.08 / 41.20 ms │ no change │
│ QQuery 2 │ 18.48 / 18.78 ±0.16 / 18.94 ms │ 18.34 / 18.72 ±0.29 / 19.15 ms │ no change │
│ QQuery 3 │ 31.38 / 32.89 ±1.21 / 34.58 ms │ 30.72 / 34.40 ±2.29 / 37.02 ms │ no change │
│ QQuery 4 │ 16.96 / 17.34 ±0.45 / 18.21 ms │ 16.82 / 17.25 ±0.33 / 17.84 ms │ no change │
│ QQuery 5 │ 37.37 / 38.84 ±1.50 / 40.86 ms │ 37.77 / 39.92 ±1.19 / 40.99 ms │ no change │
│ QQuery 6 │ 16.21 / 16.42 ±0.15 / 16.61 ms │ 16.14 / 16.27 ±0.08 / 16.39 ms │ no change │
│ QQuery 7 │ 42.90 / 45.18 ±2.95 / 50.90 ms │ 44.95 / 46.12 ±1.16 / 47.94 ms │ no change │
│ QQuery 8 │ 42.79 / 43.18 ±0.28 / 43.57 ms │ 42.47 / 43.10 ±0.44 / 43.78 ms │ no change │
│ QQuery 9 │ 49.21 / 49.90 ±0.69 / 51.07 ms │ 48.42 / 49.79 ±0.90 / 50.80 ms │ no change │
│ QQuery 10 │ 42.15 / 43.00 ±1.06 / 45.07 ms │ 41.66 / 42.26 ±0.82 / 43.88 ms │ no change │
│ QQuery 11 │ 12.76 / 13.10 ±0.21 / 13.38 ms │ 12.95 / 13.03 ±0.10 / 13.24 ms │ no change │
│ QQuery 12 │ 24.17 / 24.48 ±0.21 / 24.77 ms │ 23.62 / 23.96 ±0.28 / 24.32 ms │ no change │
│ QQuery 13 │ 32.16 / 34.18 ±1.82 / 37.28 ms │ 32.98 / 34.63 ±2.86 / 40.32 ms │ no change │
│ QQuery 14 │ 23.97 / 24.07 ±0.09 / 24.19 ms │ 23.58 / 23.95 ±0.30 / 24.46 ms │ no change │
│ QQuery 15 │ 31.52 / 32.32 ±0.80 / 33.43 ms │ 31.16 / 31.72 ±0.74 / 33.15 ms │ no change │
│ QQuery 16 │ 13.99 / 14.08 ±0.10 / 14.28 ms │ 13.18 / 13.84 ±0.55 / 14.86 ms │ no change │
│ QQuery 17 │ 73.38 / 74.38 ±0.87 / 75.86 ms │ 72.74 / 73.80 ±0.75 / 74.62 ms │ no change │
│ QQuery 18 │ 57.65 / 59.00 ±0.85 / 60.06 ms │ 57.66 / 58.46 ±0.75 / 59.82 ms │ no change │
│ QQuery 19 │ 32.89 / 33.33 ±0.38 / 33.87 ms │ 32.66 / 32.99 ±0.35 / 33.64 ms │ no change │
│ QQuery 20 │ 31.81 / 32.28 ±0.26 / 32.50 ms │ 31.49 / 32.31 ±0.44 / 32.78 ms │ no change │
│ QQuery 21 │ 55.44 / 57.67 ±1.60 / 59.89 ms │ 55.43 / 57.74 ±1.62 / 59.73 ms │ no change │
│ QQuery 22 │ 13.63 / 13.96 ±0.23 / 14.24 ms │ 13.55 / 14.03 ±0.72 / 15.46 ms │ no change │
└───────────┴────────────────────────────────┴────────────────────────────────┴───────────┘
┏━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━┓
┃ Benchmark Summary ┃ ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━┩
│ Total Time (HEAD) │ 758.05ms │
│ Total Time (array_nan) │ 757.45ms │
│ Average Time (HEAD) │ 34.46ms │
│ Average Time (array_nan) │ 34.43ms │
│ Queries Faster │ 0 │
│ Queries Slower │ 0 │
│ Queries with No Change │ 22 │
│ Queries with Failure │ 0 │
└──────────────────────────┴──────────┘

Resource Usage

tpch — base (merge-base)

MetricValue
Wall time5.0s
Peak memory4.6 GiB
Avg memory3.8 GiB
CPU user30.0s
CPU sys2.4s
Peak spill0 B

tpch — branch

MetricValue
Wall time5.0s
Peak memory4.6 GiB
Avg memory3.8 GiB
CPU user29.9s
CPU sys2.3s
Peak spill0 B

File an issue against this benchmark runner

@adriangbot

Copy link
Copy Markdown

🤖 Benchmark completed (GKE) | trigger

Instance:c4a-highmem-16 (12 vCPU / 65 GiB)

CPU Details (lscpu)
Architecture: aarch64
CPU op-mode(s): 64-bit
Byte Order: Little Endian
CPU(s): 16
On-line CPU(s) list: 0-15
Vendor ID: ARM
Model name: Neoverse-V2
Model: 1
Thread(s) per core: 1
Core(s) per cluster: 16
Socket(s): -
Cluster(s): 1
Stepping: r0p1
BogoMIPS: 2000.00
Flags: fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm jscvt fcma lrcpc dcpop sha3 sm3 sm4 asimddp sha512 sve asimdfhm dit uscat ilrcpc flagm sb paca pacg dcpodp sve2 sveaes svepmull svebitperm svesha3 svesm4 flagm2 frint svei8mm svebf16 i8mm bf16 dgh rng bti
L1d cache: 1 MiB (16 instances)
L1i cache: 1 MiB (16 instances)
L2 cache: 32 MiB (16 instances)
L3 cache: 80 MiB (1 instance)
NUMA node(s): 1
NUMA node0 CPU(s): 0-15
Vulnerability Gather data sampling: Not affected
Vulnerability Indirect target selection: Not affected
Vulnerability Itlb multihit: Not affected
Vulnerability L1tf: Not affected
Vulnerability Mds: Not affected
Vulnerability Meltdown: Not affected
Vulnerability Mmio stale data: Not affected
Vulnerability Reg file data sampling: Not affected
Vulnerability Retbleed: Not affected
Vulnerability Spec rstack overflow: Not affected
Vulnerability Spec store bypass: Mitigation; Speculative Store Bypass disabled via prctl
Vulnerability Spectre v1: Mitigation; __user pointer sanitization
Vulnerability Spectre v2: Mitigation; CSV2, BHB
Vulnerability Srbds: Not affected
Vulnerability Tsa: Not affected
Vulnerability Tsx async abort: Not affected
Vulnerability Vmscape: Not affected
Details

Comparing HEAD and array_nan
--------------------
Benchmark tpcds_sf1.json
--------------------
┏━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓
┃ Query ┃ HEAD ┃ array_nan ┃ Change ┃
┡━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩
│ QQuery 1 │ 5.70 / 6.24 ±0.84 / 7.91 ms │ 5.83 / 6.35 ±0.89 / 8.13 ms │ no change │
│ QQuery 2 │ 79.86 / 80.09 ±0.16 / 80.31 ms │ 80.73 / 81.21 ±0.34 / 81.78 ms │ no change │
│ QQuery 3 │ 28.68 / 28.84 ±0.15 / 29.11 ms │ 29.06 / 29.20 ±0.12 / 29.41 ms │ no change │
│ QQuery 4 │ 471.72 / 479.12 ±9.36 / 497.27 ms │ 476.94 / 479.72 ±3.38 / 486.18 ms │ no change │
│ QQuery 5 │ 51.11 / 52.58 ±1.00 / 54.21 ms │ 51.34 / 51.80 ±0.56 / 52.87 ms │ no change │
│ QQuery 6 │ 36.04 / 36.28 ±0.19 / 36.57 ms │ 35.78 / 36.43 ±0.51 / 37.35 ms │ no change │
│ QQuery 7 │ 94.82 / 95.08 ±0.17 / 95.30 ms │ 95.08 / 95.33 ±0.30 / 95.89 ms │ no change │
│ QQuery 8 │ 36.29 / 37.61 ±1.93 / 41.42 ms │ 36.74 / 38.15 ±1.78 / 41.57 ms │ no change │
│ QQuery 9 │ 51.69 / 54.13 ±2.89 / 59.77 ms │ 51.12 / 53.44 ±1.19 / 54.27 ms │ no change │
│ QQuery 10 │ 62.14 / 62.41 ±0.24 / 62.77 ms │ 62.28 / 62.85 ±0.43 / 63.40 ms │ no change │
│ QQuery 11 │ 290.59 / 293.90 ±2.89 / 298.78 ms │ 286.15 / 289.95 ±2.80 / 294.29 ms │ no change │
│ QQuery 12 │ 28.03 / 28.47 ±0.35 / 29.07 ms │ 27.95 / 28.51 ±0.36 / 29.07 ms │ no change │
│ QQuery 13 │ 118.26 / 119.32 ±0.57 / 119.95 ms │ 118.79 / 119.45 ±0.59 / 120.54 ms │ no change │
│ QQuery 14 │ 407.88 / 409.57 ±1.37 / 411.51 ms │ 407.39 / 409.55 ±1.93 / 412.97 ms │ no change │
│ QQuery 15 │ 57.98 / 59.80 ±2.93 / 65.64 ms │ 57.70 / 59.42 ±2.77 / 64.90 ms │ no change │
│ QQuery 16 │ 6.67 / 6.87 ±0.29 / 7.43 ms │ 6.73 / 6.83 ±0.14 / 7.11 ms │ no change │
│ QQuery 17 │ 80.27 / 81.17 ±0.90 / 82.83 ms │ 80.55 / 81.54 ±1.26 / 84.01 ms │ no change │
│ QQuery 18 │ 123.83 / 126.61 ±3.49 / 132.28 ms │ 125.80 / 127.61 ±2.97 / 133.53 ms │ no change │
│ QQuery 19 │ 41.48 / 41.77 ±0.27 / 42.14 ms │ 41.47 / 41.78 ±0.46 / 42.68 ms │ no change │
│ QQuery 20 │ 34.59 / 35.16 ±0.68 / 36.46 ms │ 34.73 / 35.18 ±0.40 / 35.80 ms │ no change │
│ QQuery 21 │ 16.52 / 17.47 ±0.92 / 19.08 ms │ 16.78 / 16.92 ±0.19 / 17.28 ms │ no change │
│ QQuery 22 │ 61.56 / 62.20 ±0.52 / 62.86 ms │ 61.69 / 62.34 ±0.56 / 63.05 ms │ no change │
│ QQuery 23 │ 314.59 / 317.15 ±2.99 / 322.57 ms │ 314.43 / 317.66 ±2.81 / 322.89 ms │ no change │
│ QQuery 24 │ 223.22 / 225.86 ±2.85 / 230.23 ms │ 222.85 / 225.41 ±2.63 / 229.70 ms │ no change │
│ QQuery 25 │ 110.59 / 112.29 ±2.02 / 116.17 ms │ 110.74 / 113.96 ±3.86 / 118.99 ms │ no change │
│ QQuery 26 │ 57.56 / 57.72 ±0.17 / 58.00 ms │ 57.62 / 57.95 ±0.31 / 58.54 ms │ no change │
│ QQuery 27 │ 6.77 / 6.84 ±0.12 / 7.08 ms │ 6.63 / 6.73 ±0.10 / 6.93 ms │ no change │
│ QQuery 28 │ 56.40 / 60.32 ±1.97 / 61.72 ms │ 60.92 / 62.28 ±2.01 / 66.25 ms │ no change │
│ QQuery 29 │ 97.95 / 100.07 ±2.28 / 104.44 ms │ 97.13 / 99.04 ±1.78 / 101.96 ms │ no change │
│ QQuery 30 │ 31.71 / 32.05 ±0.23 / 32.39 ms │ 31.86 / 32.30 ±0.37 / 32.84 ms │ no change │
│ QQuery 31 │ 110.33 / 112.13 ±1.76 / 115.18 ms │ 110.58 / 112.53 ±2.28 / 116.17 ms │ no change │
│ QQuery 32 │ 19.80 / 20.05 ±0.27 / 20.50 ms │ 19.70 / 20.08 ±0.35 / 20.72 ms │ no change │
│ QQuery 33 │ 38.16 / 38.51 ±0.23 / 38.73 ms │ 38.30 / 38.65 ±0.32 / 39.18 ms │ no change │
│ QQuery 34 │ 9.29 / 9.51 ±0.25 / 9.97 ms │ 9.30 / 9.79 ±0.46 / 10.52 ms │ no change │
│ QQuery 35 │ 70.45 / 71.53 ±0.94 / 73.25 ms │ 70.56 / 71.47 ±0.53 / 72.05 ms │ no change │
│ QQuery 36 │ 5.81 / 5.95 ±0.16 / 6.25 ms │ 5.75 / 5.91 ±0.22 / 6.35 ms │ no change │
│ QQuery 37 │ 6.71 / 6.80 ±0.10 / 6.96 ms │ 6.72 / 6.83 ±0.07 / 6.93 ms │ no change │
│ QQuery 38 │ 62.27 / 63.44 ±1.83 / 67.08 ms │ 62.12 / 63.18 ±0.67 / 63.93 ms │ no change │
│ QQuery 39 │ 443.42 / 452.66 ±6.02 / 460.43 ms │ 445.31 / 450.97 ±3.76 / 456.64 ms │ no change │
│ QQuery 40 │ 22.73 / 22.98 ±0.23 / 23.39 ms │ 22.62 / 22.89 ±0.24 / 23.33 ms │ no change │
│ QQuery 41 │ 11.20 / 11.33 ±0.20 / 11.72 ms │ 11.01 / 11.14 ±0.12 / 11.34 ms │ no change │
│ QQuery 42 │ 23.33 / 24.32 ±1.25 / 26.75 ms │ 23.36 / 24.82 ±2.02 / 28.82 ms │ no change │
│ QQuery 43 │ 4.85 / 4.93 ±0.06 / 5.04 ms │ 4.71 / 4.79 ±0.11 / 4.99 ms │ no change │
│ QQuery 44 │ 9.02 / 9.18 ±0.09 / 9.30 ms │ 8.58 / 8.71 ±0.12 / 8.91 ms │ +1.05x faster │
│ QQuery 45 │ 37.80 / 39.79 ±2.98 / 45.74 ms │ 37.48 / 40.17 ±4.30 / 48.74 ms │ no change │
│ QQuery 46 │ 11.57 / 11.96 ±0.38 / 12.69 ms │ 11.25 / 11.96 ±0.40 / 12.50 ms │ no change │
│ QQuery 47 │ 223.81 / 227.78 ±2.26 / 230.63 ms │ 224.39 / 228.24 ±3.10 / 232.32 ms │ no change │
│ QQuery 48 │ 95.88 / 96.34 ±0.25 / 96.63 ms │ 96.16 / 96.68 ±0.41 / 97.14 ms │ no change │
│ QQuery 49 │ 76.54 / 79.96 ±5.70 / 91.34 ms │ 77.06 / 78.64 ±1.43 / 81.05 ms │ no change │
│ QQuery 50 │ 59.67 / 59.85 ±0.15 / 60.03 ms │ 59.09 / 59.81 ±0.68 / 60.87 ms │ no change │
│ QQuery 51 │ 92.04 / 94.27 ±2.76 / 99.09 ms │ 90.38 / 92.62 ±1.25 / 93.95 ms │ no change │
│ QQuery 52 │ 23.80 / 24.04 ±0.24 / 24.37 ms │ 23.47 / 23.90 ±0.23 / 24.12 ms │ no change │
│ QQuery 53 │ 29.32 / 31.84 ±4.46 / 40.74 ms │ 29.13 / 32.03 ±4.47 / 40.94 ms │ no change │
│ QQuery 54 │ 55.15 / 55.72 ±0.37 / 56.14 ms │ 54.46 / 55.02 ±0.49 / 55.90 ms │ no change │
│ QQuery 55 │ 23.00 / 23.41 ±0.28 / 23.76 ms │ 23.17 / 23.61 ±0.61 / 24.81 ms │ no change │
│ QQuery 56 │ 38.38 / 39.33 ±1.20 / 41.68 ms │ 38.29 / 38.79 ±0.38 / 39.40 ms │ no change │
│ QQuery 57 │ 172.96 / 175.18 ±2.19 / 178.10 ms │ 173.47 / 175.19 ±1.54 / 178.00 ms │ no change │
│ QQuery 58 │ 113.21 / 114.25 ±1.33 / 116.84 ms │ 113.23 / 115.54 ±2.75 / 120.85 ms │ no change │
│ QQuery 59 │ 115.58 / 116.43 ±1.20 / 118.79 ms │ 116.04 / 116.54 ±0.32 / 116.88 ms │ no change │
│ QQuery 60 │ 39.02 / 39.64 ±0.51 / 40.51 ms │ 38.62 / 39.27 ±0.41 / 39.71 ms │ no change │
│ QQuery 61 │ 12.90 / 13.07 ±0.17 / 13.38 ms │ 12.53 / 14.10 ±2.60 / 19.28 ms │ 1.08x slower │
│ QQuery 62 │ 45.07 / 47.49 ±3.71 / 54.83 ms │ 45.57 / 46.06 ±0.32 / 46.36 ms │ no change │
│ QQuery 63 │ 28.97 / 29.54 ±0.36 / 30.05 ms │ 29.84 / 30.11 ±0.22 / 30.42 ms │ no change │
│ QQuery 64 │ 394.02 / 405.58 ±8.23 / 416.92 ms │ 393.93 / 404.78 ±8.85 / 415.30 ms │ no change │
│ QQuery 65 │ 145.69 / 148.71 ±3.88 / 156.07 ms │ 147.20 / 152.07 ±6.83 / 165.55 ms │ no change │
│ QQuery 66 │ 78.64 / 79.79 ±0.84 / 81.20 ms │ 78.94 / 79.59 ±0.44 / 80.22 ms │ no change │
│ QQuery 67 │ 241.67 / 245.91 ±3.61 / 251.85 ms │ 240.80 / 246.98 ±7.05 / 259.68 ms │ no change │
│ QQuery 68 │ 11.63 / 11.96 ±0.21 / 12.22 ms │ 11.55 / 11.75 ±0.22 / 12.17 ms │ no change │
│ QQuery 69 │ 56.86 / 59.21 ±3.71 / 66.60 ms │ 57.28 / 59.95 ±4.25 / 68.35 ms │ no change │
│ QQuery 70 │ 104.16 / 104.94 ±0.89 / 106.63 ms │ 103.50 / 107.13 ±5.79 / 118.66 ms │ no change │
│ QQuery 71 │ 34.95 / 37.48 ±3.80 / 45.05 ms │ 35.27 / 35.65 ±0.34 / 36.16 ms │ no change │
│ QQuery 72 │ 2088.19 / 2232.94 ±85.35 / 2354.36 ms │ 2116.43 / 2160.53 ±46.37 / 2227.43 ms │ no change │
│ QQuery 73 │ 9.26 / 9.82 ±0.47 / 10.66 ms │ 9.20 / 9.42 ±0.30 / 10.00 ms │ no change │
│ QQuery 74 │ 168.11 / 173.50 ±6.14 / 184.20 ms │ 167.05 / 169.92 ±2.65 / 174.76 ms │ no change │
│ QQuery 75 │ 147.58 / 150.85 ±4.64 / 160.00 ms │ 146.21 / 150.67 ±6.12 / 162.72 ms │ no change │
│ QQuery 76 │ 35.19 / 35.48 ±0.21 / 35.68 ms │ 34.90 / 35.49 ±0.48 / 36.27 ms │ no change │
│ QQuery 77 │ 60.54 / 63.85 ±4.07 / 71.86 ms │ 60.26 / 60.63 ±0.28 / 61.07 ms │ +1.05x faster │
│ QQuery 78 │ 181.44 / 187.53 ±4.19 / 194.06 ms │ 182.72 / 186.98 ±5.71 / 198.18 ms │ no change │
│ QQuery 79 │ 66.84 / 67.71 ±0.56 / 68.56 ms │ 66.46 / 68.57 ±2.60 / 72.74 ms │ no change │
│ QQuery 80 │ 101.33 / 102.06 ±0.38 / 102.42 ms │ 99.26 / 100.82 ±2.06 / 104.88 ms │ no change │
│ QQuery 81 │ 25.50 / 25.79 ±0.23 / 26.15 ms │ 25.14 / 25.38 ±0.19 / 25.56 ms │ no change │
│ QQuery 82 │ 16.44 / 19.16 ±4.93 / 29.02 ms │ 16.00 / 16.13 ±0.10 / 16.28 ms │ +1.19x faster │
│ QQuery 83 │ 39.68 / 40.30 ±0.45 / 41.02 ms │ 38.69 / 38.93 ±0.20 / 39.22 ms │ no change │
│ QQuery 84 │ 34.51 / 34.82 ±0.17 / 35.01 ms │ 35.06 / 38.14 ±4.35 / 46.52 ms │ 1.10x slower │
│ QQuery 85 │ 108.25 / 113.02 ±5.47 / 121.91 ms │ 106.99 / 108.47 ±0.93 / 109.84 ms │ no change │
│ QQuery 86 │ 25.00 / 25.43 ±0.36 / 25.88 ms │ 24.45 / 24.69 ±0.22 / 25.06 ms │ no change │
│ QQuery 87 │ 63.75 / 64.88 ±0.88 / 66.13 ms │ 63.03 / 64.31 ±1.36 / 66.77 ms │ no change │
│ QQuery 88 │ 61.71 / 63.19 ±1.57 / 66.13 ms │ 61.39 / 61.80 ±0.44 / 62.63 ms │ no change │
│ QQuery 89 │ 35.46 / 36.36 ±0.60 / 37.16 ms │ 35.23 / 35.79 ±0.51 / 36.71 ms │ no change │
│ QQuery 90 │ 16.97 / 18.58 ±3.02 / 24.61 ms │ 16.80 / 16.94 ±0.13 / 17.18 ms │ +1.10x faster │
│ QQuery 91 │ 44.53 / 45.73 ±0.68 / 46.49 ms │ 44.09 / 44.44 ±0.22 / 44.75 ms │ no change │
│ QQuery 92 │ 28.83 / 30.05 ±0.89 / 31.10 ms │ 28.61 / 32.45 ±3.86 / 38.44 ms │ 1.08x slower │
│ QQuery 93 │ 50.97 / 52.26 ±1.37 / 54.89 ms │ 50.06 / 50.89 ±0.79 / 52.30 ms │ no change │
│ QQuery 94 │ 38.56 / 39.16 ±0.49 / 39.74 ms │ 37.96 / 38.36 ±0.30 / 38.76 ms │ no change │
│ QQuery 95 │ 84.95 / 86.32 ±1.41 / 88.94 ms │ 82.76 / 83.57 ±0.55 / 84.28 ms │ no change │
│ QQuery 96 │ 24.15 / 24.36 ±0.23 / 24.80 ms │ 24.04 / 25.48 ±2.37 / 30.20 ms │ no change │
│ QQuery 97 │ 45.67 / 46.41 ±0.38 / 46.75 ms │ 45.67 / 46.87 ±1.68 / 50.12 ms │ no change │
│ QQuery 98 │ 42.05 / 43.54 ±0.83 / 44.42 ms │ 42.06 / 42.68 ±0.38 / 43.26 ms │ no change │
│ QQuery 99 │ 70.04 / 71.87 ±2.58 / 76.86 ms │ 68.76 / 69.40 ±0.55 / 70.35 ms │ no change │
└───────────┴───────────────────────────────────────┴───────────────────────────────────────┴───────────────┘
┏━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┓
┃ Benchmark Summary ┃ ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━┩
│ Total Time (HEAD) │ 10298.76ms │
│ Total Time (array_nan) │ 10204.60ms │
│ Average Time (HEAD) │ 104.03ms │
│ Average Time (array_nan) │ 103.08ms │
│ Queries Faster │ 4 │
│ Queries Slower │ 3 │
│ Queries with No Change │ 92 │
│ Queries with Failure │ 0 │
└──────────────────────────┴────────────┘

Resource Usage

tpcds — base (merge-base)

MetricValue
Wall time55.0s
Peak memory5.6 GiB
Avg memory5.0 GiB
CPU user236.2s
CPU sys6.7s
Peak spill0 B

tpcds — branch

MetricValue
Wall time55.0s
Peak memory5.4 GiB
Avg memory4.8 GiB
CPU user235.5s
CPU sys6.3s
Peak spill0 B

File an issue against this benchmark runner

@comphead

Copy link
Copy Markdown
ContributorAuthor

@kosiew@Jefffrey FYI as you also reviewed the FP PR #22813

@mbutrovich
mbutrovich self-requested a review June 9, 2026 17:19

@mbutrovichmbutrovich left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for tackling this, @comphead!

One thing I wanted to ask about: optimizing for the common case where an array has no -0.0.

normalize_float_zero allocates unconditionally

PrimitiveArray::unary always allocates a fresh values buffer of length n, even when there's no -0.0 to fix — which is the overwhelmingly common case. This now sits on some hot paths:

  • apply_cmp — every float =/</>/<=/>=/IS [NOT] DISTINCT comparison, on both operands.
  • eq_dyn_null — float hash-join key verification.
  • GroupValuesRows::intern — a deep copy of each float column on every batch.

Would it be worth gating the copy behind a SIMD-reducible pre-scan, so we only allocate when a -0.0 is actually present?

// f64 case; sign-bit-only pattern == -0.0let needs = arr.values().iter().any(|v| v.to_bits() == 0x8000_0000_0000_0000);if !needs {returnArc::clone(array);}

.any() over a contiguous slice should vectorize to a read-only OR-reduction, so the common case drops from "allocate + write n" to just a scan, and we pay the unary cost only when there's something to normalize. The per-native-value canonicalize path in the primitive group-by builders already avoids allocation entirely — this would bring the array path closer to that.

Small question on coverage

The fix covers hash joins via eq_dyn_null + create_hashes, but JoinKeyComparator builds via make_comparator (arrow totalOrder), which isn't normalized. Is sort-merge join reachable for float equi-keys, and if so is it covered? The current tests look like they exercise the hash-join plan only.

Either way, this is a solid fix — mostly just wondering whether we can keep the no--0.0 path allocation-free.

Comment threaddatafusion/common/src/utils/mod.rs Outdated
/// (PostgreSQL / IEEE 754 equality) require them to compare equal, so
/// callers normalize before invoking those kernels.
///
/// The common case — no `-0.0` present — is allocation-free: a single

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Parenthetical in em dashes is awkward.

@mbutrovichmbutrovich left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor nit, thanks @comphead.

@comphead

Copy link
Copy Markdown
ContributorAuthor

Thanks @mbutrovich for the review

@comphead
comphead added this pull request to the merge queueJun 9, 2026
Merged via the queue into apache:main with commit 7dd1c6aJun 9, 2026
39 of 40 checks passed
@Jefffrey

Copy link
Copy Markdown
Contributor

ive only skimmed this, but i wonder how we'll enforce/ensure we remember to apply this normalization each time for different operation/functions/execution paths 🤔

for example, this fix isn't applied to array_replace (testing on main after this merged):

>select array_replace([0.0, -0.0], 0.0, 1.0);
+-------------------------------------------------------------------------+
| array_replace(make_array(Float64(0),Float64(-0)),Float64(0),Float64(1)) |
+-------------------------------------------------------------------------+
| [1.0, -0.0] |
+-------------------------------------------------------------------------+1 row(s) fetched.
Elapsed 0.003 seconds.

postgres for comparison:

postgres=# select array_replace(ARRAY[0.0, -0.0], 0.0, 1.0);
array_replace
---------------
{1.0,1.0}
(1 row)

AdamGS pushed a commit to AdamGS/arrow-datafusion that referenced this pull request Jun 11, 2026
## Which issue does this PR close?
<!--
We generally require a GitHub issue to be filed for all bug fixes and
enhancements and this helps us generate change logs for our releases.
You can link an issue to this PR using the GitHub syntax. For example
`Closesapache#123` indicates that this PR will close issue apache#123.
-->
- Closesapache#22826 .
- Closesapache#22490
- Closesapache#11108 ## Rationale for this change
SQL (per PG and IEEE 754) treats `+0.0` and `-0.0` as equal in `=`, `IS
DISTINCT FROM`, DISTINCT, GROUP BY, UNION/INTERSECT/EXCEPT, equi-joins,
and `array_*` set ops. DataFusion treated them as
distinct because:
- Arrow's `cmp::eq`/`gt`/`lt` use IEEE 754 totalOrder for floats —
`arrow-ord-58.3.0/src/cmp.rs:71-75` explicitly says *"please normalize
zeros before calling this kernel"*.
- Arrow's `RowConverter` row-encodes floats with totalOrder; ±0 produce
different bytes.
- DataFusion's primitive float hashing used raw `to_bits()` /
`to_ne_bytes()`, so ±0 hashed to different buckets.
## What changes are included in this PR?
**Helper** in `datafusion/common/src/utils/mod.rs`:
- `normalize_float_zero(&ArrayRef) -> ArrayRef` — rewrites `-0.0 → +0.0`
for Float16/32/64 via `PrimitiveArray::unary`; `Arc::clone` for
non-float. NaN payloads preserved (`bits << 1 == 0` matches only
±0).
- `normalize_float_zero_scalar(ScalarValue) -> ScalarValue` — symmetric
for scalars.
**Applied at six boundary sites** where DataFusion hands float data to
Arrow:
| Site | Fixes |
|---|---|
| `physical-expr-common/src/datum.rs::apply_cmp` | BinaryExpr `=`, `<`,
`>`, `IS DISTINCT FROM` |
| `physical-plan/src/joins/utils.rs::eq_dyn_null` | HashJoin row
equality → INNER JOIN, INTERSECT, EXCEPT |
| `physical-plan/src/aggregates/group_values/row.rs::intern` |
Multi-column row-encoded GROUP BY |
| `functions-nested/src/set_ops.rs::general_array_distinct` |
`array_distinct` |
| `functions-nested/src/set_ops.rs::generic_set_lists` | `array_union`,
`array_intersect` |
| `functions-nested/src/except.rs::general_except` | `array_except` |
**Float hash macros** normalize for consistency:
- `datafusion/common/src/hash_utils.rs::hash_float_value!` —
`create_hashes`, hash joins, shuffle.
-
`datafusion/physical-plan/src/aggregates/group_values/single_group_by/primitive.rs::hash_float!`
— single-column primitive GROUP BY fast path.
**Single-column primitive GROUP BY / DISTINCT**
(`GroupValuesPrimitive::intern`,
`PrimitiveGroupValueBuilder::{append_val,vectorized_append,equal_to,vectorized_equal_to_*}`)
canonicalize the input via
a new default-identity `canonicalize` method on the local `HashValue`
trait (float override only). Trait visibility lifted to `pub` so the
multi-column file can use it.
Rich-T-kid added a commit to DataDog/datafusion that referenced this pull request Aug 17, 2026
…22835)
Cherry-pick of upstream commit 7dd1c6a.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Rich-T-kid added a commit to DataDog/datafusion that referenced this pull request Aug 17, 2026
LuciferYang added a commit to LuciferYang/lance that referenced this pull request Aug 26, 2026
Scalar indices select candidates in arrow's total order, where -0.0 sorts
strictly below +0.0, and bloom filters hash the raw float bytes. Expression
evaluation follows IEEE 754, where the two compare equal. A query on one
encoding therefore prunes the rows stored under the other before any recheck
can look at them: a btree page or zone whose extremum is -0.0 is skipped for
`= +0.0`, a bitmap key lookup finds only one of the two keys, and a bloom
probe misses the other block.
Nothing is lost today because DataFusion 54 evaluates float comparisons in
total order too, so index and scan agree on the same wrong answer. It starts
losing rows the moment expression evaluation becomes IEEE-correct, which is
what the DataFusion 55 signed-zero normalization (apache/datafusion#22835)
does.
So widen the query, not the comparators: a query on a float zero offers both
encodings as candidates and reports AtMost, and the parser forces the matching
recheck so expression evaluation still decides which rows match. Candidate
sets only grow, never shrink, which keeps results identical on DataFusion 54
and makes them IEEE-correct on 55 without rebuilding any index.
Range bounds only need widening where an inclusive bound leaves the other
encoding out (`>= +0.0`, `<= -0.0`); exclusive bounds already admit every row
IEEE 754 matches, so `> 0.0` and `< 0.0` stay exact.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

commonRelated to common cratefunctionsChanges to functions implementationphysical-exprChanges to the physical-expr cratesphysical-planChanges to the physical-plan cratesqllogictestSQL Logic Tests (.slt)

Projects

None yet

4 participants

@comphead@adriangbot@Jefffrey@mbutrovich