diff --git a/src/fns.c b/src/fns.c index 3201d271..1be6685b 100644 --- a/src/fns.c +++ b/src/fns.c @@ -228,8 +228,7 @@ B indexOf_c1(B t, B x) { if (had) rp[i] = map->a[p].val; else rp[i] = map->a[p].val = ctr++; } - free_b2i(map); - dec(x); + free_b2i(map); dec(x); // u64 e = nsTime(); q1+= e-s; return r; } @@ -255,10 +254,31 @@ B memberOf_c2(B t, B w, B x) { for (usz i = 0; i < xia; i++) mk_Sb(&set, xgetU(x,i), &had); i32* rp; B r = m_i32arrv(&rp, wia); for (usz i = 0; i < wia; i++) rp[i] = has_Sb(set, wgetU(w,i)); - dec(w);dec(x); free_Sb(set); + free_Sb(set); dec(w);dec(x); return r; } +B rt_find; +B find_c1(B t, B x) { + if (isAtm(x) || rnk(x)==0) thrM("⍷: Argument cannot have rank 0"); + usz xia = a(x)->ia; + B xf = getFillQ(x); + if (rnk(x)!=1) return c1(rt_find, x); + + B r = inc(bi_emptyHVec); + H_Sb* set = m_Sb(64); + BS2B xgetU = TI(x).getU; + for (usz i = 0; i < xia; i++) { + B c = xgetU(x,i); + if (!ins_Sb(&set, c)) r = vec_add(r, inc(c)); + } + free_Sb(set); dec(x); + return withFill(r, xf); +} +B find_c2(B t, B w, B x) { + return c2(rt_find, w, x); +} + #define BI_A(N) { B t=bi_##N = mm_alloc(sizeof(BFn), t_funBI, ftag(FUN_TAG)); BFn*f=c(BFn,t); f->c2=N##_c2 ; f->c1=N##_c1 ; f->extra=pf_##N; f->ident=bi_N; f->uc1=def_fn_uc1; f->ucw=def_fn_ucw; gc_add(t); } #define BI_D(N) { B t=bi_##N = mm_alloc(sizeof(BFn), t_funBI, ftag(FUN_TAG)); BFn*f=c(BFn,t); f->c2=N##_c2 ; f->c1=c1_invalid; f->extra=pf_##N; f->ident=bi_N; f->uc1=def_fn_uc1; f->ucw=def_fn_ucw; gc_add(t); } @@ -268,7 +288,7 @@ B memberOf_c2(B t, B w, B x) { #define BI_FNS1(F) F(BI_A,BI_M,BI_D) -#define F(A,M,D) A(ud) A(fne) A(feq) A(ltack) A(rtack) M(fmtF) A(indexOf) A(memberOf) +#define F(A,M,D) A(ud) A(fne) A(feq) A(ltack) A(rtack) M(fmtF) A(indexOf) A(memberOf) A(find) BI_FNS0(F); static inline void fns_init() { BI_FNS1(F) ti[t_funBI].print = print_funBI; diff --git a/src/h.h b/src/h.h index 5e2b49d3..5458463c 100644 --- a/src/h.h +++ b/src/h.h @@ -114,7 +114,7 @@ char* format_type(u8 u) { case t_harr :return"harr" ; case t_i8arr :return"i8arr" ; case t_i32arr :return"i32arr" ; case t_fillarr :return"fillarr" ; case t_c32arr :return"c32arr" ; case t_f64arr :return"f64arr" ; case t_hslice:return"hslice"; case t_i8slice:return"i8slice"; case t_i32slice:return"i32slice"; case t_fillslice:return"fillslice"; case t_c32slice:return"c32slice"; case t_f64slice:return"f64slice"; case t_comp:return"comp"; case t_block:return"block"; case t_body:return"body"; case t_scope:return"scope"; - case t_ns:return"ns"; case t_nsDesc:return"nsDesc"; case t_fldAlias:return"alias"; + case t_ns:return"ns"; case t_nsDesc:return"nsDesc"; case t_fldAlias:return"alias"; case t_hashmap:return"hashmap"; case t_freed:return"(freed by GC)"; case t_harrPartial:return"partHarr"; #ifdef RT_PERF case t_funPerf:return"perf fn"; case t_md1Perf:return"perf m1"; case t_md2Perf:return "perf m2"; @@ -125,7 +125,7 @@ char* format_type(u8 u) { #define FOR_PF(F) F(none, "(unknown fn)") \ /*arith.c*/ F(add,"+") F(sub,"-") F(mul,"×") F(div,"÷") F(pow,"⋆") F(floor,"⌊") F(ceil,"⌈") F(stile,"|") F(eq,"=") \ /*arith.c*/ F(ne,"≠") F(le,"≤") F(ge,"≥") F(lt,"<") F(gt,">") F(and,"∧") F(or,"∨") F(not,"¬") F(log,"⋆⁼") \ - /*fns.c*/ F(ud,"↕") F(fne,"≢") F(feq,"≡") F(ltack,"⊣") F(rtack,"⊢") F(fmtF,"•FmtF") F(indexOf,"⊐") F(memberOf,"∊") \ + /*fns.c*/ F(ud,"↕") F(fne,"≢") F(feq,"≡") F(ltack,"⊣") F(rtack,"⊢") F(fmtF,"•FmtF") F(indexOf,"⊐") F(memberOf,"∊") F(find,"⍷") \ /*sfns.c*/ F(shape,"⥊") F(pick,"⊑") F(pair,"{𝕨‿𝕩}") F(select,"⊏") F(slash,"/") F(join,"∾") F(couple,"≍") F(shiftb,"»") F(shifta,"«") F(take,"↑") F(drop,"↓") F(group,"⊔") F(reverse,"⌽") \ /*derv.c*/ F(fork,"(fork)") F(atop,"(atop)") F(md1d,"(derived 1-modifier)") F(md2d,"(derived 2-modifier)") \ /*sort.c*/ F(gradeUp,"⍋") \ @@ -251,7 +251,8 @@ bool atomEqual(B w, B x); // doesn't consume B toCells(B x); // consumes B toKCells(B x, ur k); // consumes B withFill(B x, B f); // consumes both -B vec_join(B w, B x); // consumes both +B vec_join(B w, B x); // consumes both; w∾x for vectors +B vec_add(B w, B x); // consumes both; w∾pop++; return p; } -#ifdef VALS - static inline bool N(ins) (Map** mp, KT k, VT v) { // returns whether element was replaced - bool had; u64 p = N(mk)(mp, k, &had); - (*mp)->a[p].val = v; - return had; - } -#endif +static inline bool N(ins) (Map** mp, KT k IFVAL(, VT v)) { // returns whether element was replaced + bool had; + IFVAL(u64 p =) N(mk)(mp, k, &had); + IFVAL((*mp)->a[p].val = v); + return had; +} #undef IFKEY @@ -150,4 +149,4 @@ static inline u64 N(mk) (Map** mp, KT k, bool* had) { #ifdef VALS #undef VALS #undef VT -#endif \ No newline at end of file +#endif diff --git a/src/load.c b/src/load.c index 54b7299b..fbafe471 100644 --- a/src/load.c +++ b/src/load.c @@ -66,7 +66,7 @@ static inline void load_init() { /* ∧∨<>≠=≤≥≡≢ */ bi_and , bi_or , bi_lt , bi_gt , bi_ne , bi_eq , bi_le , bi_ge , bi_feq , bi_fne, /* ⊣⊢⥊∾≍↑↓↕«» */ bi_ltack , bi_rtack , bi_shape, bi_join , bi_couple, bi_take , bi_drop , bi_ud , bi_shifta, bi_shiftb, /* ⌽⍉/⍋⍒⊏⊑⊐⊒∊ */ bi_reverse, bi_N , bi_slash, bi_gradeUp, bi_N , bi_select, bi_pick , bi_indexOf, bi_N , bi_memberOf, - /* ⍷⊔!˙˜˘¨⌜⁼´ */ bi_N , bi_group , bi_asrt , bi_const , bi_swap , bi_cell , bi_each , bi_tbl , bi_N , bi_fold, + /* ⍷⊔!˙˜˘¨⌜⁼´ */ bi_find , bi_group , bi_asrt , bi_const , bi_swap , bi_cell , bi_each , bi_tbl , bi_N , bi_fold, /* ˝`∘○⊸⟜⌾⊘◶⎉ */ bi_N , bi_scan , bi_atop , bi_over , bi_before, bi_after , bi_under, bi_val , bi_cond , bi_N, /* ⚇⍟⎊ */ bi_N , bi_repeat, bi_catch }; @@ -75,7 +75,7 @@ static inline void load_init() { /* ∧∨<>≠=≤≥≡≢ */ 1,1,1,1,1,1,1,1,1,1, /* ⊣⊢⥊∾≍↑↓↕«» */ 1,1,0,1,1,1,1,1,1,1, /* ⌽⍉/⍋⍒⊏⊑⊐⊒∊ */ 1,0,1,1,0,1,1,1,0,1, - /* ⍷⊔!˙˜˘¨⌜⁼´ */ 0,1,1,1,1,1,1,1,0,1, + /* ⍷⊔!˙˜˘¨⌜⁼´ */ 1,1,1,1,1,1,1,1,0,1, /* ˝`∘○⊸⟜⌾⊘◶⎉ */ 0,1,1,1,1,1,1,1,0,0, /* ⚇⍟⎊ */ 0,1,1 }; @@ -129,6 +129,7 @@ static inline void load_init() { rt_reverse = rtObjGet(rtObjRaw, 30); gc_add(rt_reverse); rt_indexOf = rtObjGet(rtObjRaw, 37); gc_add(rt_indexOf); rt_memberOf= rtObjGet(rtObjRaw, 39); gc_add(rt_memberOf); + rt_find = rtObjGet(rtObjRaw, 40); gc_add(rt_find); rt_cell = rtObjGet(rtObjRaw, 45); gc_add(rt_cell); for (usz i = 0; i < runtimeLen; i++) { diff --git a/src/mut.c b/src/mut.c index 58cfe54b..5c13a447 100644 --- a/src/mut.c +++ b/src/mut.c @@ -82,7 +82,7 @@ void mut_pfree(Mut* m, usz n) { // free the first n elements else mm_free((Value*) m->val); } -void mut_set(Mut* m, usz ms, B x) { // consumes; sets m[ms] to x +void mut_set(Mut* m, usz ms, B x) { // consumes x; sets m[ms] to x again: #define AGAIN(T) { mut_to(m, T); goto again; } switch(m->type) { default: UD; @@ -296,3 +296,36 @@ B vec_join(B w, B x) { // consumes both dec(w); dec(x); return mut_fv(r); } +B vec_add(B w, B x) { // consumes both + usz wia = a(w)->ia; + usz ria = wia+1; + if (v(w)->refc==1) { + u64 wsz = mm_size(v(w)); + u8 wt = v(w)->type; + if (wt==t_i32arr && fsizeof(I32Arr,a,i32,ria)ia = ria; + i32arr_ptr(w)[wia] = o2iu(x); + return w; + } + if (wt==t_c32arr && fsizeof(C32Arr,a,u32,ria)ia = ria; + c32arr_ptr(w)[wia] = o2cu(x); + return w; + } + if (wt==t_f64arr && fsizeof(F64Arr,a,f64,ria)ia = ria; + f64arr_ptr(w)[wia] = o2fu(x); + return w; + } + if (wt==t_harr && fsizeof(HArr,a,B,ria)ia = ria; + harr_ptr(w)[wia] = x; + return w; + } + } + MAKE_MUT(r, ria); mut_to(r, el_or(TI(w).elType, selfElType(x))); + mut_copy(r, 0, w, 0, wia); + mut_set(r, wia, x); + dec(w); + return mut_fv(r); +}