diff --git a/src/builtins/sfns.c b/src/builtins/sfns.c index 47304b97..7e2ea9c2 100644 --- a/src/builtins/sfns.c +++ b/src/builtins/sfns.c @@ -1216,23 +1216,7 @@ B reverse_c2(B t, B w, B x) { return withFill(mut_fcd(r, x), xf); } - -B pick_uc1(B t, B o, B x) { // TODO do in-place like pick_ucw; maybe just call it? - if (isAtm(x) || IA(x)==0) return def_fn_uc1(t, o, x); - usz ia = IA(x); - B arg = IGet(x, 0); - B rep = c1(o, arg); - MAKE_MUT_INIT(r, ia, el_or(TI(x,elType), selfElType(rep))); MUTG_INIT(r); - mut_setG(r, 0, rep); - mut_copyG(r, 1, x, 1, ia-1); - B xf = getFillR(x); - return qWithFill(mut_fcd(r, x), xf); -} - -B pick_ucw(B t, B o, B w, B x) { - if (isArr(w) || isAtm(x) || RNK(x)!=1) return def_fn_ucw(t, o, w, x); - usz xia = IA(x); - usz wi = WRAP(o2i64(w), xia, thrF("𝔽⌾(n⊸⊑)𝕩: reading out-of-bounds (n≡%R, %s≡≠𝕩)", w, xia)); +static B replaceOne(B fn, usz pos, B x, usz xia) { if (TI(x,elType)==el_B) { B* xp; if (TY(x)==t_harr || TY(x)==t_hslice) { @@ -1247,34 +1231,47 @@ B pick_ucw(B t, B o, B w, B x) { COPY_TO(xp, el_B, 0, x, 0, xia); NOGC_E; arr_shCopy(x2, x); - dec(x); + decG(x); x = taga(x2); } - B c = xp[wi]; - xp[wi] = m_f64(0); - xp[wi] = c1(o, c); + B c = xp[pos]; + xp[pos] = m_f64(0); + xp[pos] = c1(fn, c); return x; } - B arg = IGet(x, wi); - B rep = c1(o, arg); + B arg = IGet(x, pos); + B rep = c1(fn, arg); if (reusable(x) && TI(x,canStore)(rep)) { REUSE(x); u8 xt = TY(x); - if (xt==t_i8arr ) { i8* xp = i8any_ptr (x); xp[wi] = o2iG(rep); return x; } - else if (xt==t_i16arr) { i16* xp = i16any_ptr(x); xp[wi] = o2iG(rep); return x; } - else if (xt==t_i32arr) { i32* xp = i32any_ptr(x); xp[wi] = o2iG(rep); return x; } - else if (xt==t_f64arr) { f64* xp = f64any_ptr(x); xp[wi] = o2fG(rep); return x; } - else if (xt==t_c8arr ) { u8* xp = c8any_ptr (x); xp[wi] = o2cG(rep); return x; } - else if (xt==t_c16arr) { u16* xp = c16any_ptr(x); xp[wi] = o2cG(rep); return x; } - else if (xt==t_c32arr) { u32* xp = c32any_ptr(x); xp[wi] = o2cG(rep); return x; } + void* xp = tyany_ptr(x); + if (xt==t_i8arr ) { ((i8* )xp)[pos] = o2iG(rep); return x; } + else if (xt==t_i16arr) { ((i16*)xp)[pos] = o2iG(rep); return x; } + else if (xt==t_i32arr) { ((i32*)xp)[pos] = o2iG(rep); return x; } + else if (xt==t_f64arr) { ((f64*)xp)[pos] = o2fG(rep); return x; } + else if (xt==t_c8arr ) { ((u8* )xp)[pos] = o2cG(rep); return x; } + else if (xt==t_c16arr) { ((u16*)xp)[pos] = o2cG(rep); return x; } + else if (xt==t_c32arr) { ((u32*)xp)[pos] = o2cG(rep); return x; } } MAKE_MUT_INIT(r, xia, el_or(TI(x,elType), selfElType(rep))); MUTG_INIT(r); - mut_setG(r, wi, rep); - mut_copyG(r, 0, x, 0, wi); - mut_copyG(r, wi+1, x, wi+1, xia-wi-1); + mut_setG(r, pos, rep); + mut_copyG(r, 0, x, 0, pos); + mut_copyG(r, pos+1, x, pos+1, xia-pos-1); B xf = getFillR(x); return qWithFill(mut_fcd(r, x), xf); } +B pick_uc1(B t, B o, B x) { // TODO do in-place like pick_ucw; maybe just call it? + if (isAtm(x) || IA(x)==0) return def_fn_uc1(t, o, x); + return replaceOne(o, 0, x, IA(x)); +} + +B pick_ucw(B t, B o, B w, B x) { + if (isArr(w) || isAtm(x) || RNK(x)!=1) return def_fn_ucw(t, o, w, x); + usz xia = IA(x); + usz wi = WRAP(o2i64(w), xia, thrF("𝔽⌾(n⊸⊑)𝕩: reading out-of-bounds (n≡%R, %s≡≠𝕩)", w, xia)); + return replaceOne(o, wi, x, xia); +} + static B takedrop_ucw(i64 wi, B o, u64 am, B x, ux xr) { usz xia = IA(x); usz csz = arr_csz(x);