Skip to content

Support Spark floating point semantics in bound comparisons #10064

Open

Description

@gatesn

Vortex’s existing total ordering distinguishes -0.0 from +0.0 and compares NaNs by their bit patterns. Spark treats signed zeros as equal and all NaNs as equal. Spark currently pushes float and double predicates using Vortex’s existing comparison functions, so a pushed filter can return different rows than Spark evaluation.

Add an explicit comparison mode or separate bound scalar functions for Spark-compatible floating point equality and ordering. Preserve Vortex’s current behavior as the default. Until Spark-compatible operations exist, the Spark connector should decline affected pushdown.

Regression cases should cover =, !=, ranges, and IN with signed zeros and NaNs, including distinct NaN payloads.

Activity

  1. jackylee-ch commented on Oct 14, 2026

    @jackylee-ch
    Contributor

    DuckDB has the same semantics (all NaNs are equal and greater than any other value, -0.0 = 0.0), and the DuckDB integration pushes float comparisons too; the stats side is #10479. With duckdb 1.5.6 and the released extension, x = 0.0 returns 1 of 2 rows, x > 100 drops a negative NaN, and a hash join with 0.0 on the build side returns 0 of 100,000 -0.0 probe rows, as the build key reaches the scan as x = 0.0. An explicit option, like the SQL semantics #10057 added to list_contains, can lower col op literal into existing expressions without losing pruning (float comparisons already prune only NaN-free zones): >/>= gain OR is_nan(x), </<= gain AND NOT is_nan(x), zero literals treat -0.0 and 0.0 alike, and NaN literals reduce to is_nan or a constant. It has to reach list_contains too, since DuckDB IN filters, small-build-side join filters included, go through it (x IN (0.0, 'nan') returns 2 of 4 rows) and #10052 probes floats by their bits. If that works for you, I can start with the comparisons in vortex-array (column-to-column float comparisons would be declined) and sequence list_contains and the DuckDB and Spark wiring behind #10052, #10054, #9141 and #9658.

    Investigated with AI assistance; the numbers are from local runs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugA bug issue

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions