From cec962fb8ce317bafe19a386426d1e3c2730c884 Mon Sep 17 00:00:00 2001 From: dzaima Date: Sun, 5 Sep 2021 21:51:00 +0300 Subject: [PATCH] usz multiplication --- src/builtins/md1.c | 6 +++--- src/builtins/sfns.c | 29 ++++++++++++++--------------- src/core/stuff.h | 8 ++++++++ src/h.h | 12 ++++++------ 4 files changed, 31 insertions(+), 24 deletions(-) diff --git a/src/builtins/md1.c b/src/builtins/md1.c index bd08ebcb..195a1837 100644 --- a/src/builtins/md1.c +++ b/src/builtins/md1.c @@ -46,9 +46,9 @@ B tbl_c2(B d, B w, B x) { B f = c(Md1D,d)->f; if (EACH_FILLS) xf = getFillQ(x); if (isAtm(w)) w = m_atomUnit(w); if (isAtm(x)) x = m_atomUnit(x); - usz wia = a(w)->ia; ur wr = rnk(w); - usz xia = a(x)->ia; ur xr = rnk(x); - usz ria = wia*xia; ur rr = wr+xr; + ur wr = rnk(w); usz wia = a(w)->ia; + ur xr = rnk(x); usz xia = a(x)->ia; + ur rr = wr+xr; usz ria = uszMulT(wia, xia); if (rria : 1; - usz nia; + usz nia = 1; ur nr; ShArr* sh; if (isF64(w)) { @@ -76,25 +76,25 @@ B shape_c2(B t, B w, B x) { if (TI(w,elType)==el_i32) { i32* wi = i32any_ptr(w); if (nr>1) for (i32 i = 0; i < nr; i++) sh->a[i] = wi[i]; - i64 tot = 1; + bool bad=false, good=false; for (i32 i = 0; i < nr; i++) { if (wi[i]<0) thrF("ℊ: š•Ø contained %i", wi[i]); - tot*= wi[i]; - if (tot > USZ_MAX) thrM("ℊ: Result too large"); // TODO this (& below) doesn't detect overflows for usz==u64 + bad|= uszMul(&nia, wi[i]); + good|= wi[i]==0; } - nia = (usz)tot; + if (bad && !good) thrM("ℊ: š•Ø too large"); } else { BS2B getU = TI(w,getU); i32 unkPos = -1; i32 unkInd; - i64 tot = 1; + bool bad=false, good=false; for (i32 i = 0; i < nr; i++) { B c = getU(w, i); if (isF64(c)) { usz v = o2s(c); if (sh) sh->a[i] = v; - tot*= v; - if (tot > USZ_MAX) thrM("ℊ: Result too large"); + bad|= uszMul(&nia, v); + good|= v==0; } else { if (isArr(c) || !isVal(c)) thrM("ℊ: š•Ø must consist of natural numbers or ∘ ⌊ ⌽ ↑"); if (unkPos!=-1) thrM("ℊ: š•Ø contained multiple computed axes"); @@ -102,11 +102,12 @@ B shape_c2(B t, B w, B x) { unkInd = ((i32)v(c)->flags) - 1; } } + if (bad && !good) thrM("ℊ: š•Ø too large"); if (unkPos!=-1) { if (unkInd!=52 & unkInd!=6 & unkInd!=30 & unkInd!=25) thrM("ℊ: š•Ø must consist of natural numbers or ∘ ⌊ ⌽ ↑"); - if (tot==0) thrM("ℊ: Can't compute axis when the rest of the shape is empty"); - i64 div = xia/tot; - i64 mod = xia%tot; + if (nia==0) thrM("ℊ: Can't compute axis when the rest of the shape is empty"); + i64 div = xia/nia; + i64 mod = xia%nia; usz item; bool fill = false; if (unkInd == 52) { @@ -121,9 +122,7 @@ B shape_c2(B t, B w, B x) { fill = true; } else UD; if (sh) sh->a[unkPos] = item; - tot*= item; - if (tot > USZ_MAX) thrM("ℊ: Result too large"); - nia = tot; + nia = uszMulT(nia, item); if (fill) { if (!isArr(x)) x = m_atomUnit(x); Arr* a = take_impl(nia, x); @@ -131,7 +130,7 @@ B shape_c2(B t, B w, B x) { x = taga(a); xia = nia; } - } else nia = tot; + } } } dec(w); diff --git a/src/core/stuff.h b/src/core/stuff.h index cdc83438..2c8c7687 100644 --- a/src/core/stuff.h +++ b/src/core/stuff.h @@ -93,6 +93,14 @@ static B m_v3(B a, B b, B c ); // consumes all static B m_v4(B a, B b, B c, B d); // consumes all static bool isNumEl(u8 elt) { return elt==el_i32 | elt==el_f64; } +static bool uszMul(usz* c, usz n) { + return __builtin_mul_overflow(*c, n, c); +} +static usz uszMulT(usz a, usz b) { + if (uszMul(&a, b)) thrM("Size too large"); + return a; +} + // string stuff B m_str8l(char* s); diff --git a/src/h.h b/src/h.h index 58010e48..9e780efe 100644 --- a/src/h.h +++ b/src/h.h @@ -100,12 +100,12 @@ #define i64 int64_t #define u64 uint64_t #define f64 double -#define I8_MAX 127 -#define I16_MAX 65535 -#define I8_MIN (-128) -#define I16_MIN (-65536) -#define I32_MAX ((i32)((1LL<<31)-1)) -#define I32_MIN ((i32)(-(1LL<<31))) +#define I8_MIN -128 +#define I8_MAX 127 +#define I16_MIN -65536 +#define I16_MAX 65535 +#define I32_MIN -2147483648 +#define I32_MAX 2147483647 #define I64_MIN ((i64)(1ULL<<63)) #define CHR_MAX 1114111 #define U16_MAX ((u16)~(u16)0)