From ee47921b4357c5c7260b74b42213e5fb7c803fcf Mon Sep 17 00:00:00 2001 From: dzaima Date: Fri, 14 Apr 2023 14:45:50 +0300 Subject: [PATCH] =?UTF-8?q?normalize=20=C2=AF0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/builtins/search.c | 1 - src/builtins/selfsearch.c | 3 +-- src/utils/hash.c | 5 ++++- src/utils/hash.h | 17 +++++++++++++++-- 4 files changed, 20 insertions(+), 6 deletions(-) diff --git a/src/builtins/search.c b/src/builtins/search.c index 56bdb1e9..6965c8e2 100644 --- a/src/builtins/search.c +++ b/src/builtins/search.c @@ -18,7 +18,6 @@ // Otherwise, generic hashtable // SHOULD handle up to 64 bit cells via proper typed hash tables // SHOULD have fast path when cell sizes or element types doesn't match -// SHOULD properly handle ¯0 #include "../core.h" #include "../utils/hash.h" diff --git a/src/builtins/selfsearch.c b/src/builtins/selfsearch.c index 7c551f5f..557ec974 100644 --- a/src/builtins/selfsearch.c +++ b/src/builtins/selfsearch.c @@ -82,11 +82,10 @@ static bool canCompare64_norm(B x, usz n) { if (e == el_B) return 0; if (e == el_f64) { f64* pf = f64any_ptr(x); - u64* pu = (u64*)pf; for (usz i = 0; i < n; i++) { f64 f = pf[i]; if (f!=f) return 0; - if (pu[i] == m_f64(-0.0).u) return 0; + pf[i] = f==0? 0 : f; } } return 1; diff --git a/src/utils/hash.c b/src/utils/hash.c index 0912997b..6fab47aa 100644 --- a/src/utils/hash.c +++ b/src/utils/hash.c @@ -3,6 +3,7 @@ #include "hash.h" #include "time.h" + NOINLINE u64 bqn_hashObj(B x, const u64 secret[4]) { // TODO manual separation of atom & arr probably won't be worth it when there are actually sane typed array hashing things if (isArr(x)) { usz xia = IA(x); @@ -21,7 +22,9 @@ NOINLINE u64 bqn_hashObj(B x, const u64 secret[4]) { // TODO manual separation o case el_i8: case el_c8: data = tyany_ptr(x); bytes = xia*1; break; case el_i16: case el_c16: data = tyany_ptr(x); bytes = xia*2; break; case el_i32: case el_c32: data = tyany_ptr(x); bytes = xia*4; break; - case el_f64: data = f64any_ptr(x); bytes = xia*8; break; + case el_f64: data = f64any_ptr(x); bytes = xia*8; + for (ux i = 0; i < xia; i++) ((f64*)data)[i] = normalizeFloat(((f64*)data)[i]); + break; case el_B:; data = TALLOCP(u64, xia); isTemp = true; diff --git a/src/utils/hash.h b/src/utils/hash.h index 25beed1b..05c15d49 100644 --- a/src/utils/hash.h +++ b/src/utils/hash.h @@ -11,10 +11,23 @@ static void bcl(B x, usz ia) { // clean up bitarr tail bits to zero } } +static inline f64 normalizeFloat(f64 v) { + v = v+0; + return v==v? v+0 : 0.0/0.0; +} u64 bqn_hashObj(B x, const u64 secret[4]); static u64 bqn_hash(B x, const u64 secret[4]) { // doesn't consume - if (isVal(x)) return bqn_hashObj(x, secret); - return wyhash64(secret[0], x.u); + u64 h; + if (LIKELY(x.f==x.f)) { + h = m_f64(x.f+0).u; + } else if (isVal(x)) { + return bqn_hashObj(x, secret); + } else if ((x.u<<1) == (0x7FF8000000000000<<1)) { + h = secret[1]; + } else { + h = x.u; + } + return wyhash64(secret[0], h); } static u64 bqn_hashP(B x, const u64 secret[4]) { // bqn_hash but never zero