From cce52dd40e526ebe4f57b365b06680434e2f0cb2 Mon Sep 17 00:00:00 2001 From: dzaima Date: Wed, 7 Jul 2021 21:31:48 +0300 Subject: [PATCH] random deal & subset --- src/builtins/sysfn.c | 113 +++++++++++++++++++++++++++++++----- src/h.h | 2 +- src/utils/hashmapTemplate.h | 14 ++++- 3 files changed, 112 insertions(+), 17 deletions(-) diff --git a/src/builtins/sysfn.c b/src/builtins/sysfn.c index 1bc82857..b94f292d 100644 --- a/src/builtins/sysfn.c +++ b/src/builtins/sysfn.c @@ -199,24 +199,26 @@ B hash_c1(B t, B x) { static B rand_ns; -static B rand_rangeName; static i32 rand_a, rand_b; -static NFnDesc* rand_rangeDesc; +static B rand_rangeName; static NFnDesc* rand_rangeDesc; +static B rand_dealName; static NFnDesc* rand_dealDesc; +static B rand_subsetName; static NFnDesc* rand_subsetDesc; +#define RAND_START Scope* sc = c(NS,nfn_objU(t))->sc; \ + u64 seed = sc->vars[rand_a].u | sc->vars[rand_b].u<<32; +#define RAND_END sc->vars[rand_a].u = seed>>32; \ + sc->vars[rand_a].u = seed&0xFFFFFFFF; B rand_range_c1(B t, B x) { i64 xv = o2i64(x); if (xv<0) thrM("(rand).Range: 𝕩 cannot be negative"); - Scope* sc = c(NS,nfn_objU(t))->sc; - u64 seed = sc->vars[rand_a].u | sc->vars[rand_b].u<<32; + RAND_START; u64 rnd = wyrand(&seed); - sc->vars[rand_a].u = seed>>32; - sc->vars[rand_a].u = seed&0xFFFFFFFF; + RAND_END; return xv? m_f64(wy2u0k(rnd, xv)) : m_f64(wy2u01(rnd)); } B rand_range_c2(B t, B w, B x) { - Scope* sc = c(NS,nfn_objU(t))->sc; - u64 seed = sc->vars[rand_a].u | sc->vars[rand_b].u<<32; usz am = o2s(w); i64 max = o2i64(x); + RAND_START; B r; if (max<1) { if (max!=0) thrM("(rand).Range: 𝕩 cannot be negative"); @@ -230,15 +232,96 @@ B rand_range_c2(B t, B w, B x) { i32* rp; r = m_i32arrv(&rp, am); for (usz i = 0; i < am; i++) rp[i] = wy2u0k(wyrand(&seed), max); } - sc->vars[rand_a].u = seed>>32; - sc->vars[rand_a].u = seed&0xFFFFFFFF; + RAND_END; + return r; +} + +B rand_deal_c1(B t, B x) { + i32 xi = o2i(x); + if (RARE(xi<0)) thrM("(rand).Deal: Argument cannot be negative"); + if (xi==0) return emptyIVec(); + RAND_START; + i32* rp; B r = m_i32arrv(&rp, xi); + for (i64 i = 0; i < xi; i++) rp[i] = i; + for (i64 i = 0; i < xi; i++) { + i32 j = wy2u0k(wyrand(&seed), xi-i) + i; + i32 c = rp[j]; + rp[j] = rp[i]; + rp[i] = c; + } + RAND_END; + return r; +} + +B rand_deal_c2(B t, B w, B x) { + i32 wi = o2i(w); + i32 xi = o2i(x); + if (RARE(wi<0)) thrM("(rand).Deal: 𝕨 cannot be negative"); + if (RARE(xi<0)) thrM("(rand).Deal: 𝕩 cannot be negative"); + if (RARE(wi>xi)) thrM("(rand).Deal: 𝕨 cannot exceed 𝕩"); + if (wi==0) return emptyIVec(); + RAND_START; + TALLOC(i32,s,xi); + for (i64 i = 0; i < xi; i++) s[i] = i; + for (i64 i = 0; i < wi; i++) { + i32 j = wy2u0k(wyrand(&seed), xi-i) + i; + i32 c = s[j]; + s[j] = s[i]; + s[i] = c; + } + i32* rp; B r = m_i32arrv(&rp, wi); + memcpy(rp, s, wi*4); + TFREE(s); + RAND_END; + return r; +} + +#define N(X) X##_i2i +#define KT i32 +#define HT i32 +#define H1(K) K +#define H2(K,h1) h1 +#define H1R(K,h2) h2 +#define EMPTY(S,K) ((S)==0) +#define HDEF 0 +#define EQUAL(A,B) (A)==(B) +#define VALS +#define VT i32 +#include "../utils/hashmapTemplate.h" +B rand_subset_c2(B t, B w, B x) { + i32 wi = o2i(w); + i32 xi = o2i(x); + if (RARE(wi<0)) thrM("(rand).Subset: 𝕨 cannot be negative"); + if (RARE(xi<0)) thrM("(rand).Subset: 𝕩 cannot be negative"); + if (RARE(wi>xi)) thrM("(rand).Subset: 𝕨 cannot exceed 𝕩"); + if (wi==0) return emptyIVec(); + RAND_START; + i32* rp; B r = m_i32arrv(&rp, wi); + i64 sz = 1; + while (sz < wi*2) sz*= 2; + sz*= 2; + H_i2i* map = m_i2i(sz); + for (i64 i = 0; i < wi; i++) rp[i] = i; + for (i64 i = 0; i < wi; i++) { + i32 j = wy2u0k(wyrand(&seed), xi-i) + i; + if (j>32), b(x.u&0xFFFFFFFF)); - ns_set(r, rand_rangeName, m_nfn(rand_rangeDesc, inc(r))); + ns_set(r, rand_rangeName, m_nfn(rand_rangeDesc, inc(r))); + ns_set(r, rand_dealName, m_nfn(rand_dealDesc, inc(r))); + ns_set(r, rand_subsetName, m_nfn(rand_subsetDesc, inc(r))); return r; } diff --git a/src/h.h b/src/h.h index 901721cd..700c3568 100644 --- a/src/h.h +++ b/src/h.h @@ -190,7 +190,7 @@ typedef struct Value { i32 refc; // plain old reference count u8 mmInfo; // bucket size, mark&sweep bits when that's needed; currently unused u8 flags; // is sorted/a permutation/whatever in the future, currently primitive index for self-hosted runtime - u8 type; // access into TypeInfo among generally knowing what type of object this is + u8 type; // access into ti_*, among generally knowing what type of object this is ur extra; // whatever object-specific stuff. Rank for arrays, id for functions #ifdef OBJ_COUNTER u64 uid; diff --git a/src/utils/hashmapTemplate.h b/src/utils/hashmapTemplate.h index eeac886f..d2b0c810 100644 --- a/src/utils/hashmapTemplate.h +++ b/src/utils/hashmapTemplate.h @@ -91,7 +91,7 @@ static inline bool N(has) (Map* m, KT k) { #endif -static inline void N(qins) (Map* m, u64 h1, HT h2, KT k IFVAL(, VT v)) { // if guaranteed that k doesn't exist in the map yet and there's space for this +static inline void N(qins) (Map* m, u64 h1, HT h2 IFKEY(, KT k) IFVAL(, VT v)) { // if guaranteed that k doesn't exist in the map yet and there's space for this u64 mask = m->mask; u64 p = h1 & mask; while (true) { @@ -112,7 +112,7 @@ static void N(dbl) (Map** m) { Map* nm = N(m)(psz*2); for (u64 i = 0; i < psz; i++) { Ent e = pm->a[i]; - if(!EMPTY(e.hash, e.key)) N(qins)(nm, H1R(e.key, e.hash), e.hash, e.key IFVAL(, e.val)); + if(!EMPTY(e.hash, e.key)) N(qins)(nm, H1R(e.key, e.hash), e.hash IFKEY(, e.key) IFVAL(, e.val)); } mm_free((Value*)pm); *m = nm; @@ -136,6 +136,15 @@ static inline bool N(ins) (Map** mp, KT k IFVAL(, VT v)) { // returns whether el IFVAL((*mp)->a[p].val = v); return had; } +#ifdef VALS + static inline VT N(swap) (Map** mp, KT k, VT v, VT def) { // returns either previous element or def; sets new element to v + bool had; + u64 p = N(mk)(mp, k, &had); + VT prev = (*mp)->a[p].val; + (*mp)->a[p].val = v; + return had? prev : def; + } +#endif #undef IFKEY @@ -146,6 +155,7 @@ static inline bool N(ins) (Map** mp, KT k IFVAL(, VT v)) { // returns whether el #undef HT #undef KT #undef H1 +#undef H1R #undef H2 #undef EMPTY #undef HDEF