8000 Float constants in patterns match any float within f64::EPSILON · Issue #706 · project-minigraf/minigraf · GitHub
[go: up one dir, main page]

Skip to content

Float constants in patterns match any float within f64::EPSILON #706

Closed

Description

@adityamukho

Summary

A float constant in a pattern's value position, written or bound with $slot, matches every stored float within an absolute f64::EPSILON (about 2.2e-16), not only an equal one. The same comparison written as a predicate is exact, so two ways of asking the same question return different rows.

(transact [[:e1 :m/x 0.00000000000000001]])           ; 1e-17
(query [:find ?e :where [?e :m/x 0.0]])               ; => [[:e1]]  wrong
(query [:find ?e :where [?e :m/x ?v] [(= ?v 0.0)]])   ; => []       right

PreparedQuery with $v bound to BindValue::Val(Value::Float(0.0)) also returns :e1. Checked on main (v2.0.9) before and after a checkpoint.

Cause

(f - ff).abs() < f64::EPSILON where a constant float is compared with a stored one:

  • main: src/query/datalog/matcher.rs:217
  • v3: src/query/datalog/matcher.rs:241, src/query/engine/plan.rs:76 (documented as "floats within f64::EPSILON"), src/query/engine/scan.rs:107 and :379

An absolute epsilon does nothing useful at either end of the range. Above 1.0 it is smaller than the gap between adjacent floats, so the comparison is exact. Below that, values that differ by orders of magnitude compare equal: every float in (-2.2e-16, 2.2e-16) matches 0.0, and 1e-20 matches 5e-20. Joins on a variable (JoinKey, IEEE ==), predicates, and the indexes (encode_value / keys::float_bits, exact bytes) are all exact, so this one comparison disagrees with the rest of the engine.

Impact

Wrong rows from a pattern with a float constant when the stored floats include values smaller than about 2.2e-16 in magnitude: probabilities, scientific measurements, embedding components. Nothing is lost or changed on disk. Present on both branches; the v3 engine copied the executor's comparison so that the plan-independence oracle would agree.

Proposed fix

Compare with IEEE ==, as joins and = already do (-0.0 equals 0.0; NaN equals nothing, and NaN can't be stored, #688). Change every site above together so the engine and the executor still agree, and add a regression test for both pattern forms (literal and bound) and the predicate form. v3 first, then a backport to main, following the v2.x data-integrity policy.

🤖 Generated with Claude Code

Activity

  1. added this to the v3.0.0 milestone on Oct 23, 2026
  2. added
    bugSomething isn't working
    known-issueBug present in a published release and not yet fixed in one; listed in the pinned known-issues issue
    on Oct 23, 2026
  3. adityamukho commented on Oct 23, 2026

    @adityamukho
    CollaboratorAuthor

    Fixed in v2.0.10, released 2026-10-23 (crates.io, CHANGELOG). Also fixed on v3 for v3.0.0. Moved to "Fixed in v2.0.10" in #421.

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

    bugSomething isn't workingdata-integrityData integrity issueknown-issueBug present in a published release and not yet fixed in one; listed in the pinned known-issues issue

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions

      0