From 5b8d9f5e0c31fdb446ce3c38bd3e4382ce74a0cf Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Wed, 19 Jun 2024 18:01:15 -0700 Subject: New rpermi: iterator version of rperm * combi.c (rpermi_get, rpermi_peek, rpermi_clone): New static functions. (rpermi_ops): New static structure. (rpermi): New function. * combi.h (rpermi): Declared. * eval.c (eval_init): Register rpermi intrinsic. --- combi.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ combi.h | 1 + eval.c | 1 + 3 files changed, 86 insertions(+) diff --git a/combi.c b/combi.c index 8e011187..cfe8c71f 100644 --- a/combi.c +++ b/combi.c @@ -475,6 +475,90 @@ val rperm(val seq, val k) } } +static int rpermi_get(struct seq_iter *it, val *pval) +{ + val env = it->inf.obj; + + if (it->ul.next) { + *pval = it->ui.iter; + it->ui.iter = nil; + it->ul.next = 0; + return 1; + } + + if (rperm_while_fun(env)) { + *pval = rperm_seq_gen_fun(env); + return 1; + } + + return 0; +} + +static int rpermi_peek(struct seq_iter *it, val *pval) +{ + val env = it->inf.obj; + + if (it->ul.next) { + *pval = it->ui.iter; + it->ui.iter = nil; + return 1; + } + + if (rperm_while_fun(env)) { + it->ui.iter = *pval = rperm_seq_gen_fun(env); + it->ul.next = t; + return 1; + } + + return 0; +} + +static void rpermi_clone(const struct seq_iter *sit, struct seq_iter *dit) +{ + val env = sit->inf.obj; + val list = vecref(env, zero); + val vec = vecref(env, one); + val extra = vecref(env, two); + val nenv = vector(three, nil); + + set(vecref_l(nenv, zero), list); + set(vecref_l(nenv, one), copy_vec(vec)); + set(vecref_l(nenv, two), extra); + + *dit = *sit; + + dit->inf.obj = nenv; +} + +struct seq_iter_ops rpermi_ops = seq_iter_ops_init_clone(rpermi_get, + rpermi_peek, + rpermi_clone); + +val rpermi(val seq, val k) +{ + check_k(k, lit("rpermi")); + + if (k == zero) { + return cons(make_like(nil, seq), nil); + } else { + val obj; + val list = list_seq(seq); + val env = rperm_init(list, k, seq); + struct seq_iter *it = coerce(struct seq_iter *, chk_calloc(1, sizeof *it)); + + it->inf.obj = env; + it->inf.kind = SEQ_NOTSEQ; + + it->ops = &rpermi_ops; + + obj = cobj(coerce(mem_t *, it), seq_iter_cls, &seq_iter_cobj_ops); + + gc_hint(seq); + + return obj; + } +} + static val k_conses(val list, val k, val self) { cnum i, n = c_num(k, self); diff --git a/combi.h b/combi.h index 907aec87..17465cc1 100644 --- a/combi.h +++ b/combi.h @@ -29,5 +29,6 @@ val perm(val seq, val k); val permi(val seq, val k); val rperm(val seq, val k); +val rpermi(val seq, val k); val comb(val seq, val k); val rcomb(val seq, val k); diff --git a/eval.c b/eval.c index f8d8c047..c38f673f 100644 --- a/eval.c +++ b/eval.c @@ -7898,6 +7898,7 @@ void eval_init(void) reg_fun(force_s, func_n1(force)); reg_fun(intern(lit("promisep"), user_package), func_n1(promisep)); reg_fun(intern(lit("rperm"), user_package), func_n2(rperm)); + reg_fun(intern(lit("rpermi"), user_package), func_n2o(rpermi, 1)); reg_fun(intern(lit("perm"), user_package), func_n2o(perm, 1)); reg_fun(intern(lit("permi"), user_package), func_n2o(permi, 1)); reg_fun(intern(lit("comb"), user_package), func_n2(comb)); -- cgit v1.2.3