more random

This commit is contained in:
dzaima 2021-06-01 02:12:30 +03:00
parent c35e885ea1
commit 75a6d1b307

View File

@ -170,35 +170,49 @@ B hash_c1(B t, B x) {
return r;
}
static B rand_ns;
static B rand_intsName;
static B rand_rangeName;
static i32 rand_a, rand_b;
static NFnDesc* rand_ints;
B rand_ints_c1(B t, B x) {
static NFnDesc* rand_range;
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;
u64 rnd = wyrand(&seed);
sc->vars[rand_a].u = seed>>32;
sc->vars[rand_a].u = seed&0xFFFFFFFF;
return m_f64(wy2u0k(rnd, o2i64(x)));
return xv? m_f64(wy2u0k(rnd, xv)) : m_f64(wy2u01(rnd));
}
B rand_ints_c2(B t, B w, B x) {
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);
if (max>I32_MAX | max<1) thrM("(rand).Ints: bad 𝕩");
i32* rp; B r = m_i32arrv(&rp, am);
for (usz i = 0; i < am; i++) rp[i] = wy2u0k(wyrand(&seed), max);
B r;
if (max<1) {
if (max!=0) thrM("(rand).Range: 𝕩 cannot be negative");
f64* rp; r = m_f64arrv(&rp, am);
for (usz i = 0; i < am; i++) rp[i] = wy2u01(wyrand(&seed));
} else if (max > I32_MAX) {
if (max >= 1ULL<<53) thrM("(rand).Range: 𝕩 must be less than 2⋆53");
f64* rp; r = m_f64arrv(&rp, am);
for (usz i = 0; i < am; i++) rp[i] = wy2u0k(wyrand(&seed), max);
} else {
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;
return r;
}
static NOINLINE void rand_init() {
rand_ns = bqn_exec(m_str32(U"{a←𝕨⋄b←𝕩⋄ints⇐0}"), inc(bi_emptyHVec), inc(bi_emptyHVec)); gc_add(rand_ns);
rand_intsName = m_str32(U"ints"); gc_add(rand_intsName);
rand_ints = registerNFn(m_str32(U"(rand).Ints"), rand_ints_c1, rand_ints_c2);
rand_ns = bqn_exec(m_str32(U"{a←𝕨⋄b←𝕩range⇐0}"), inc(bi_emptyHVec), inc(bi_emptyHVec)); gc_add(rand_ns);
rand_rangeName = m_str32(U"range"); gc_add(rand_rangeName);
rand_range = registerNFn(m_str32(U"(rand).Range"), rand_range_c1, rand_range_c2);
B tmp = c1(rand_ns, m_f64(0));
rand_a = ns_pos(tmp, m_str32(U"a"));
rand_b = ns_pos(tmp, m_str32(U"b"));
@ -208,10 +222,12 @@ B makeRand_c1(B t, B x) {
if (!isNum(x)) thrM("•MakeRand: 𝕩 must be a number");
if (rand_ns.u==0) rand_init();
B r = c2(rand_ns, b(x.u>>32), b(x.u&0xFFFFFFFF));
ns_set(r, rand_intsName, m_nfn(rand_ints, inc(r)));
ns_set(r, rand_rangeName, m_nfn(rand_range, inc(r)));
return r;
}
static B makeRel(B md) { // doesn't consume
return m1_d(inc(md), path_dir(inc(comp_currPath)));
}