From 47392acc338440fb7612319ceecd5abe48881a28 Mon Sep 17 00:00:00 2001 From: Marshall Lochbaum Date: Mon, 21 Nov 2022 15:19:27 -0500 Subject: [PATCH] =?UTF-8?q?Implement=20=C3=97=C2=B4=20for=20all=20numeric?= =?UTF-8?q?=20cases,=20using=20f64=20product=20when=20i32=20fails?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/builtins/fold.c | 43 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 35 insertions(+), 8 deletions(-) diff --git a/src/builtins/fold.c b/src/builtins/fold.c index fcced21e..86c83ca3 100644 --- a/src/builtins/fold.c +++ b/src/builtins/fold.c @@ -55,6 +55,30 @@ static f64 sum_f64(void* xv, usz i, f64 r) { static i64 (*const sum_small_fns[])(void*, usz) = { sum_small_i8, sum_small_i16, sum_small_i32 }; static f64 (*const sum_fns[])(void*, usz, f64) = { sum_i8, sum_i16, sum_i32, sum_f64 }; +// Try to keep to i32 product, go to f64 on overflow or non-i32 initial +#define DEF_INT_PROD(T) \ + static f64 prod_##T(void* xv, usz i, f64 init) { \ + while (i--) init*=((T*)xv)[i]; return init; \ + } \ + static f64 prod_int_##T(void* xv, usz ia, i32 init) { \ + T* xp = xv; \ + while (ia--) { \ + i32 i0=init; \ + if (mulOn(init,xp[ia])) return prod_##T(xv, ia+1, i0); \ + } \ + return init; \ + } +DEF_INT_PROD(i8) +DEF_INT_PROD(i16) +DEF_INT_PROD(i32) +#undef DEF_PROD +static f64 prod_f64(void* xv, usz i, f64 r) { + while (i--) r *= ((f64*)xv)[i]; + return r; +} +static f64 (*const prod_int_fns[])(void*, usz, i32) = { prod_int_i8, prod_int_i16, prod_int_i32 }; +static f64 (*const prod_fns[])(void*, usz, f64) = { prod_i8, prod_i16, prod_i32, prod_f64 }; + #define MIN_MAX(T,C) \ T* xp = xv; T r = xp[0]; \ for (usz i=1; if; if (rtid==n_floor) { f64 r=min_fns[xe-el_i8](tyany_ptr(x), ia); decG(x); return m_f64(r); } // ⌊ if (rtid==n_ceil ) { f64 r=max_fns[xe-el_i8](tyany_ptr(x), ia); decG(x); return m_f64(r); } // ⌈ if (rtid==n_mul | rtid==n_and) { // ×/∧ - if (xe==el_i8 ) { i8* xp = i8any_ptr (x); i32 c=1; for (usz i=ia; i--; ) if (mulOn(c,xp[i]))goto base; decG(x); return m_f64(c); } - if (xe==el_i16) { i16* xp = i16any_ptr(x); i32 c=1; for (usz i=ia; i--; ) if (mulOn(c,xp[i]))goto base; decG(x); return m_i32(c); } - if (xe==el_i32) { i32* xp = i32any_ptr(x); i32 c=1; for (usz i=ia; i--; ) if (mulOn(c,xp[i]))goto base; decG(x); return m_i32(c); } - if (xe==el_f64) { f64* xp = f64any_ptr(x); f64 c=1; for (usz i=ia; i--; ) c*= xp[i]; decG(x); return m_f64(c); } + void *xv = tyany_ptr(x); + u8 sel = xe - el_i8; + f64 r = xe<=el_i32 ? prod_int_fns[sel](xv, ia, 1) + : prod_fns[sel](xv, ia, 1); + decG(x); return m_f64(r); } if (rtid==n_or) { // ∨ if (xe==el_i8 ) { i8* xp = i8any_ptr (x); bool r=0; for (usz i=0; if; if (rtid==n_ceil ) { f64 r=wf; if (ia>0) { f64 m=max_fns[xe-el_i8](tyany_ptr(x), ia); if (m>r) r=m; } decG(x); return m_f64(r); } // ⌈ i32 wi = wf; if (rtid==n_mul | rtid==n_and) { // ×/∧ - if (xe==el_i8 && wi==wf) { i8* xp = i8any_ptr (x); i32 c=wi; for (usz i=ia; i--; ) if (mulOn(c,xp[i]))goto base; decG(x); return m_i32(c); } - if (xe==el_i16 && wi==wf) { i16* xp = i16any_ptr(x); i32 c=wi; for (usz i=ia; i--; ) if (mulOn(c,xp[i]))goto base; decG(x); return m_i32(c); } - if (xe==el_i32 && wi==wf) { i32* xp = i32any_ptr(x); i32 c=wi; for (usz i=ia; i--; ) if (mulOn(c,xp[i]))goto base; decG(x); return m_i32(c); } - if (xe==el_f64 ) { f64* xp = f64any_ptr(x); f64 c=wf; for (usz i=ia; i--; ) c*= xp[i]; decG(x); return m_f64(c); } + void *xv = tyany_ptr(x); + bool isint = xe<=el_i32 && wi==wf; + u8 sel = xe - el_i8; + f64 r = isint ? prod_int_fns[sel](xv, ia, wi) + : prod_fns[sel](xv, ia, wf); + decG(x); return m_f64(r); } if (rtid==n_or && (wi&1)==wf) { // ∨ if (xe==el_i8 ) { i8* xp = i8any_ptr (x); bool q=wi; for (usz i=0; i