diff --git a/src/builtins/compare.c b/src/builtins/compare.c index c757efee..03f88702 100644 --- a/src/builtins/compare.c +++ b/src/builtins/compare.c @@ -75,7 +75,7 @@ NOINLINE bool atomEqualF(B w, B x) { } bool atomEEqual(B w, B x) { // doesn't consume - if (isF64(w) & isF64(x)) return w.f==x.f; + if (isF64(w) & isF64(x)) return floatIndistinguishable(w.f, x.f); if (!isVal(w) || !isVal(x)) return false; if (TI(w,byRef) || TY(w)!=TY(x)) return false; diff --git a/src/core/stuff.h b/src/core/stuff.h index a30a40b1..f7ac76dd 100644 --- a/src/core/stuff.h +++ b/src/core/stuff.h @@ -315,8 +315,10 @@ void noop_visit(Value* x); #define VISIT_SHAPE(X) #endif + + #define ICMP(W,X) ({ AUTO wt = (W); AUTO xt = (X); (wt>xt?1:0)-(wtx) - !(w>=x); // slightly better codegen from being able to reuse the same compare instruction @@ -324,9 +326,13 @@ SHOULD_INLINE i32 compareFloat(f64 w, f64 x) { return (w>x) - (wx, 0 if w≡x - if (isNum(w) & isNum(x)) return compareFloat(o2fG(w), o2fG(x)); + if (isNum(w) & isNum(x)) return floatCompare(o2fG(w), o2fG(x)); if (isC32(w) & isC32(x)) return ICMP(o2cG(w), o2cG(x)); return compareF(w, x); } @@ -342,7 +348,7 @@ static bool compatible(B w, B x) { return eequal(w, x); } static bool compatibleFloats(f64 a, f64 b) { - return a==b || (a!=a && b!=b); + return floatIndistinguishable(a, b); } NOINLINE usz depthF(B x); diff --git a/test/cases/system.bqn b/test/cases/system.bqn index 8d29a23a..5f668fd9 100644 --- a/test/cases/system.bqn +++ b/test/cases/system.bqn @@ -2,6 +2,7 @@ %DEF var V←•internal.Variation ⋄ LV←•internal.ListVariations ⋄ CLR←•internal.ClearRefs %DEF tvar %USE var ⋄ _tvar ← {F _𝕣 x: (CLR@) ⊢ {F 𝕩 V x}¨ LV 𝕩; w F _𝕣 x: (CLR@) ⊢ (LV 𝕨) {(𝕨 V w) F 𝕩 V x}⌜ LV 𝕩} +%DEF eqvar %USE tvar ⋄ _eqvar ← {r ← 𝕨 𝔽 _tvar 𝕩 ⋄ !∘≡⟜(⊑r)¨ r ⋄ ⊑r} # standard system values @@ -280,6 +281,8 @@ a←3 ⋄ 12 {𝕊: a+↩𝕩}•_timed 10 ⋄ a %% 123 E←•internal.EEqual ⋄ a←(¯1⊸×≍⊢) (↕3)∾∞∾0÷0 ⋄ {𝕩!(a 𝕏 0)E a 𝕏 •ParseFloat"-0" ⋄ 𝕩!(0 𝕏 a)E(•ParseFloat"-0") 𝕏 a}¨ (⊢∾{𝕏¨}¨) ⟨+,-,×,÷,⋆,√,⌊,⌈,|,¬,∧,∨,<,>,≠,=,≤,≥, •math.Atan2,•math.Comb,•math.Hypot⟩ E←•internal.EEqual ⋄ {! (𝕏 4⥊0) E 𝕏 1↓¯1×π∾4⥊0}¨ (⊢∾{𝕏¨}¨) ⟨+,-,×,÷,⋆,√,⌊,⌈,|,¬, •math.Sin,•math.Cos,•math.Tan,•math.Asin,•math.Acos,•math.Atan,•math.Sinh,•math.Cosh,•math.Tanh,•math.Asinh,•math.Acosh,•math.Atanh,•math.Cbrt,•math.Log2,•math.Log10,•math.Log1p,•math.Expm1,•math.Fact,•math.LogFact,•math.Erf,•math.ErfC⟩ •internal.EEqual´¨ 1⊏˘¨{⟨•math.Atan2⟜2⁼𝕩, •math.Atan2⟜0⁼𝕩, 2⊸•math.Atan2⁼𝕩, 0⊸•math.Atan2⁼𝕩⟩} (¯1⊸×≍⊢) 1.2‿0 %% 1‿1‿1‿1 +(0÷0) •internal.EEqual -0÷0 %% 1 +%USE eqvar ⋄ •internal.EEqual _eqvar⟜- ⟨0÷0, 3⥊0⟩ %% 1 {15 𝕏 10}¨ ⟨•math.GCD,•math.LCM⟩ %% 5‿30 ⌊1e5×{0.1 𝕏 0.2}¨ ⟨•math.Atan2,•math.Comb,•math.Hypot,•math.Atan2⁼,•math.Atan2˜⁼⟩ %% 110714‿96959‿22360‿2027‿49331 diff --git a/test/cases/under.bqn b/test/cases/under.bqn index 264159f7..7c72320b 100644 --- a/test/cases/under.bqn +++ b/test/cases/under.bqn @@ -213,6 +213,7 @@ n←500 ⋄ a←↕n ⋄ i←(-n)+↕2×n ⋄ r←⌽(2×n)⥊a ⋄ ! (⌽a) ≡ ≍⌾(1‿2⊸⌽) 5‿5⥊↕25 %% 1‿5‿5⥊22‿23‿24‿20‿21‿2‿3‿4‿0‿1‿7‿8‿9‿5‿6‿12‿13‿14‿10‿11‿17‿18‿19‿15‿16 # NaN things +⟨@⋈0÷0, @⋈-0÷0⟩⌾(0‿0⊸⊏) ⋈3 %% ⋈@ ⋈ 0÷0 ( %USE eqvar _test_ ← { set Repl _𝕣_ different exp: