fix eequal on different NaN patterns

+ rename compareFloat→floatCompare to be more consistent
This commit is contained in:
dzaima 2025-05-23 00:26:02 +03:00
parent a7897ddcde
commit 2a57cb30b8
4 changed files with 14 additions and 4 deletions

View File

@ -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;

View File

@ -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)-(wt<xt?1:0); })
SHOULD_INLINE i32 compareFloat(f64 w, f64 x) {
SHOULD_INLINE i32 floatCompare(f64 w, f64 x) { // w •Cmp x
if (RARE(w!=w || x!=x)) return (w!=w) - (x!=x);
#if __x86_64__
return (w>x) - !(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) - (w<x);
#endif
}
SHOULD_INLINE bool floatIndistinguishable(f64 a, f64 b) { // whether the floats are indistinguishable by BQN semantics
return a==b || (a!=a && b!=b);
}
NOINLINE i32 compareF(B w, B x);
static i32 compare(B w, B x) { // doesn't consume; -1 if w<x, 1 if w>x, 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);

View File

@ -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 {! (𝕏 40) E 𝕏 1¯1×π40}¨ ({𝕏¨}¨) +,-,×,÷,,,,,|,¬, •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.Atan22𝕩, •math.Atan20𝕩, 2•math.Atan2𝕩, 0•math.Atan2𝕩} (¯1×) 1.20 %% 1111
(0÷0) •internal.EEqual -0÷0 %% 1
%USE eqvar •internal.EEqual _eqvar- 0÷0, 30 %% 1
{15 𝕏 10}¨ •math.GCD,•math.LCM %% 530
1e5×{0.1 𝕏 0.2}¨ •math.Atan2,•math.Comb,•math.Hypot,•math.Atan2,•math.Atan2˜ %% 1107149695922360202749331

View File

@ -213,6 +213,7 @@ n←500 ⋄ a←↕n ⋄ i←(-n)+↕2×n ⋄ r←⌽(2×n)⥊a ⋄ ! (⌽a) ≡
(12) 5525 %% 1552223242021234017895612131410111718191516
# NaN things
@0÷0, @-0÷0(00) 3 %% @ 0÷0
(
%USE eqvar
_test_ { set Repl _𝕣_ different exp: