#include "../core.h" #include "../utils/calls.h" NOINLINE i32 compareF(B w, B x) { if (isNum(w) & isC32(x)) return -1; if (isC32(w) & isNum(x)) return 1; i32 atmNeg; if (isAtm(w)) { atmNeg = 0; atmW:; if (isAtm(x)) thrM("Invalid comparison"); if (IA(x)==0) return atmNeg? -1 : 1; i32 c = compare(w, IGetU(x,0)); return (c<=0)^atmNeg? -1 : 1; } if (isAtm(x)) { B t=w; w=x; x=t; atmNeg=1; goto atmW; } if (w.u==x.u && TI(w,arrD1)) return 0; ur wr=RNK(w); usz* wsh=SH(w); ur xr=RNK(x); usz* xsh=SH(x); i32 rc = ICMP(wr, xr); ur rr = wr0); u64* wp = w; u64* xp = x; usz q = l/64; for (usz i=0; i0); \ if (d!=0) { void* t=w; w=x; x=t; } \ u64* wp = w; T* xp = x; \ for (usz i=0; i0); INIT \ S* wp = w; T* xp = x; \ for (usz i=0; i0); return false; } INIT_GLOBAL EqFn eqFns[] = { F(1_1), F(1_8), F(1_16), F(1_32), F(1_f64), notEq, notEq, notEq, F(1_8), F(8_8), F(s8_16), F(s8_32), F(s8_f64), notEq, notEq, notEq, F(1_16), F(s8_16), F(8_8), F(s16_32), F(s16_f64), notEq, notEq, notEq, F(1_32), F(s8_32), F(s16_32), F(8_8), F(s32_f64), notEq, notEq, notEq, F(1_f64), F(s8_f64), F(s16_f64), F(s32_f64), F(f64_f64), notEq, notEq, notEq, notEq, notEq, notEq, notEq, notEq, F(8_8), F(u8_16), F(u8_32), notEq, notEq, notEq, notEq, notEq, F(u8_16), F(8_8), F(u16_32), notEq, notEq, notEq, notEq, notEq, F(u8_32), F(u16_32), F(8_8), }; #undef F FORCE_INLINE bool equalTyped(B w, B x, u8 we, u8 xe, usz ia) { usz idx = EQFN_INDEX(we, xe); return eqFns[idx](tyany_ptr(w), tyany_ptr(x), ia, eqFnData[idx]); } static NOINLINE bool equalSlow(B w, B x, usz ia) { SLOW2("equal", w, x); SGetU(x) SGetU(w) for (usz i = 0; i < ia; i++) if(!equal(GetU(w,i),GetU(x,i))) return false; return true; } static NOINLINE bool eequalSlow(B w, B x, usz ia) { SLOW2("eequal", w, x); SGetU(x) SGetU(w) for (usz i = 0; i < ia; i++) if(!eequal(GetU(w,i),GetU(x,i))) return false; return true; } static NOINLINE bool eequalFloat(f64* wp, f64* xp, usz ia) { u64 r = 1; for (usz i = 0; i < ia; i++) { #if NEEQUAL_NEGZERO r&= ((u64*)wp)[i] == ((u64*)xp)[i]; #else r&= (wp[i]==xp[i]) | (wp[i]!=wp[i] & xp[i]!=xp[i]); #endif } return r; } #define EQ_START(F) \ if (isAtm(w)) { \ if (!isAtm(x)) return false; \ return F(w, x); \ } \ if (isAtm(x)) return false; \ ur wr = RNK(w); \ if (wr!=RNK(x)) return false; \ usz ia = IA(x); \ if (LIKELY(wr==1)) { if (ia != IA(w)) return false; } \ else if (!eqShPart(SH(w), SH(x), wr)) return false; \ if (ia==0) return true; NOINLINE bool equal(B w, B x) { // doesn't consume EQ_START(atomEqual); u8 we = TI(w,elType); u8 xe = TI(x,elType); if (we!=el_B && xe!=el_B) return equalTyped(w, x, we, xe, ia); return equalSlow(w, x, ia); } bool eequal(B w, B x) { // doesn't consume if (w.u==x.u) return true; EQ_START(atomEEqual); u8 we = TI(w,elType); u8 xe = TI(x,elType); if (we==el_f64 && xe==el_f64) return eequalFloat(f64any_ptr(w), f64any_ptr(x), ia); if (RARE(we==el_B || xe==el_B)) return eequalSlow(w, x, ia); return equalTyped(w, x, we, xe, ia); }