diff --git a/src/builtins/sfns.c b/src/builtins/sfns.c index 3d20b67f..04b0acdc 100644 --- a/src/builtins/sfns.c +++ b/src/builtins/sfns.c @@ -1131,18 +1131,32 @@ static NOINLINE B rotate_highrank(bool inv, B w, B x) { goto decW_ret; } if (wia>xr) goto badlen; - if (wia==0 || IA(x)==0) { r=x; goto decW_ret; } + + if (wia==0) { r=x; goto decW_ret; } + if (!elNum(TI(w,elType))) { + w = num_squeeze(w); + if (!elNum(TI(w,elType))) thrF("⌽%U: 𝕨 contained non-number", INV); + } + bool origF64 = TI(w,elType)==el_f64; + w = toF64Any(w); + f64* wp = tyany_ptr(w); + if (origF64) for (ux i = 0; i < wia; i++) o2i64(m_f64(wp[i])); + + if (IA(x)==0) { r=x; goto decW_ret; } usz* xsh = SH(x); - SGetU(w) ur cr = wia-1; usz rot0, l0; usz csz = 1; while (1) { - usz xshc = xsh[cr]; if (cr==0) goto lastaxis; - i64 wv = WRAP_ROT(o2i64(GetU(w, cr)), xshc); - if (wv!=0) { rot0 = inv? xshc-wv : wv; l0 = xshc; break; } + usz xshc = xsh[cr]; + i64 wv = WRAP_ROT((i64)wp[cr], xshc); + if (wv != 0) { + rot0 = inv? xshc-wv : wv; + l0 = xshc; + break; + } csz*= xshc; cr--; } @@ -1158,7 +1172,7 @@ static NOINLINE B rotate_highrank(bool inv, B w, B x) { usz ccsz = rSkip; for (usz i = cr; i-->0; ) { usz xshc = xsh[i]; - i64 v = WRAP_ROT(o2i64(GetU(w, i)), xshc); + i64 v = WRAP_ROT((i64)wp[cr], xshc); if (inv && v!=0) v = xshc-v; pos[i] = rot[i] = v; xi+= v*ccsz; @@ -1198,7 +1212,7 @@ B reverse_c2(B t, B w, B x) { if (isArr(w)) return rotate_highrank(0, w, x); if (isAtm(x) || RNK(x)==0) thrM("⌽: 𝕩 must have rank at least 1 for atom 𝕨"); usz xia = IA(x); - if (xia==0) return x; + if (xia==0) { o2i64(w); return x; } usz cam = SH(x)[0]; usz csz = arr_csz(x); i64 am = WRAP_ROT(o2i64(w), cam); diff --git a/test/cases/prims.bqn b/test/cases/prims.bqn index 9027ba73..031bd741 100644 --- a/test/cases/prims.bqn +++ b/test/cases/prims.bqn @@ -2,6 +2,7 @@ %DEF tvar %USE var β‹„ _tvar ← {F _𝕣 x: (CLR@) ⊒ {F 𝕩 V x}Β¨ LV 𝕩; w F _𝕣 x: (CLR@) ⊒ (LV 𝕨) {(𝕨 V w) F 𝕩 V x}⌜ LV 𝕩} %DEF eqvar %USE tvar β‹„ _eqvar ← {r ← 𝕨 𝔽 _tvar 𝕩 β‹„ !βˆ˜β‰‘βŸœ(βŠ‘r)Β¨ r β‹„ βŠ‘r} %DEF evar %USE tvar β‹„ _evar ← {ok←{⇐} β‹„ r←β₯Šπ•¨ okβˆ˜π”½βŽŠ{π•Š: β€’CurrentError@} _tvar 𝕩 β‹„ {βŠ‘ok∊r? !"TEST FAIL: variation didn't error"; ("TEST FAIL: varying error messages"βŠΈβ‹ˆ ! 1=β‰ )⍷r β‹„ !βŠ‘r}} +%DEF eqerr %USE eqvar β‹„ _eqerr ← {ok←{⇐} β‹„ r←β₯Šπ•¨ okβˆ˜π”½βŽŠ{π•Š: β€’CurrentError@}⌜ 𝕩 β‹„ {βŠ‘ok∊r? !"TEST FAIL: case didn't error"; ("TEST FAIL: varying error messages"βŠΈβ‹ˆ ! 1=β‰ )⍷r β‹„ !βŠ‘r}} %DEF k _k ← {𝔽○‒internal.Keep} # batch checks @@ -237,6 +238,17 @@ w←1β€Ώ1β₯Š1 β‹„ x←2β₯Š1 β‹„ wβ€Ώx <¨↩ β‹„ {! (βˆΎβŸ¨β€’Repr𝕩,": Expe # βŒ½π•© %USE var β‹„ {{! 𝕩 ≑ ⌽"Ai8"VβŒ½π•©} 𝕩‒rand.Range 2}Β¨ ↕1000 +# π•¨βŒ½π•© +!"Integer out of range: 1e20" % %USE eqerr β‹„ ⟨1e20,⟨1e20⟩⟩ ⌽_eqerr βŸ¨β†•10, ↕0, 0β€Ώ0β₯Š0, ⟨⟩⟩ +!"Expected integer, got NaN" % %USE eqerr β‹„ ⟨0Γ·0, ⟨0Γ·0⟩⟩ ⌽_eqerr βŸ¨β†•10, ↕0, 0β€Ώ0β₯Š0, ⟨⟩⟩ +!"Integer out of range: ∞" % %USE eqerr β‹„ ⟨∞, ⟨∞⟩⟩ ⌽_eqerr βŸ¨β†•10, ↕0, 0β€Ώ0β₯Š0, ⟨⟩⟩ +!"Expected integer, got function" % %USE eqerr β‹„ βŸ¨βŠ‘ ⟩ ⌽_eqerr βŸ¨β†•10, ↕0, 0β€Ώ0β₯Š0, ⟨⟩⟩ +!"Expected integer, got character" % %USE eqerr β‹„ ⟨'a'⟩ ⌽_eqerr βŸ¨β†•10, ↕0, 0β€Ώ0β₯Š0, ⟨⟩⟩ +!"⌽: 𝕨 contained non-number" % %USE eqerr β‹„ ⟨3β€Ώ'a', 'a'β€Ώ3, 0β€Ώ'a', 'a'β€Ώ0⟩ ⌽_eqerr ⟨0β€Ώ0β₯Š0,0β€Ώ0β€Ώ0β₯Š0⟩ +!"Integer out of range: ∞" % %USE eqerr β‹„ ⟨3β€Ώβˆž, βˆžβ€Ώ3, 0β€Ώβˆž, βˆžβ€Ώ0⟩ ⌽_eqerr ⟨0β€Ώ0β₯Š0,0β€Ώ0β€Ώ0β₯Š0⟩ +(1+1e15) ⌽ ↕10 %% (1+↕9)∾0 +(-1+1e15) ⌽ ↕10 %% 9βˆΎβ†•9 + # ↑𝕩 & ↓𝕩 !"↑: Argument must have rank at least 1" % ↑0 !"↓: Argument must have rank at least 1" % ↓<0