normalize ¯0

This commit is contained in:
dzaima 2023-04-14 14:45:50 +03:00
parent 2fd390ebf8
commit ee47921b43
4 changed files with 20 additions and 6 deletions

View File

@ -18,7 +18,6 @@
// Otherwise, generic hashtable // Otherwise, generic hashtable
// SHOULD handle up to 64 bit cells via proper typed hash tables // 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 have fast path when cell sizes or element types doesn't match
// SHOULD properly handle ¯0
#include "../core.h" #include "../core.h"
#include "../utils/hash.h" #include "../utils/hash.h"

View File

@ -82,11 +82,10 @@ static bool canCompare64_norm(B x, usz n) {
if (e == el_B) return 0; if (e == el_B) return 0;
if (e == el_f64) { if (e == el_f64) {
f64* pf = f64any_ptr(x); f64* pf = f64any_ptr(x);
u64* pu = (u64*)pf;
for (usz i = 0; i < n; i++) { for (usz i = 0; i < n; i++) {
f64 f = pf[i]; f64 f = pf[i];
if (f!=f) return 0; if (f!=f) return 0;
if (pu[i] == m_f64(-0.0).u) return 0; pf[i] = f==0? 0 : f;
} }
} }
return 1; return 1;

View File

@ -3,6 +3,7 @@
#include "hash.h" #include "hash.h"
#include "time.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 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)) { if (isArr(x)) {
usz xia = IA(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_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_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_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:; case el_B:;
data = TALLOCP(u64, xia); data = TALLOCP(u64, xia);
isTemp = true; isTemp = true;

View File

@ -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]); u64 bqn_hashObj(B x, const u64 secret[4]);
static u64 bqn_hash(B x, const u64 secret[4]) { // doesn't consume static u64 bqn_hash(B x, const u64 secret[4]) { // doesn't consume
if (isVal(x)) return bqn_hashObj(x, secret); u64 h;
return wyhash64(secret[0], x.u); 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 static u64 bqn_hashP(B x, const u64 secret[4]) { // bqn_hash but never zero