From 706e9bc7983ebb54cfbd7f95b1e98252dfd0d558 Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Thu, 29 Mar 2018 06:45:17 -0700 Subject: lib: eliminate reduce-left from n-ary math ops. Using reduce-left is inefficient; it conses up a list. We can decimate the stacked arguments without consing. * lib.c (nary_op): Replace reduce_left with iteration. (nary_simple_op): New function, variant of nary_op useable by functions that have a mandatory argument passed separately from the argument list. (minusv, divv): Replace reduce_left with iteration. (maxv, minv): Replace reduce_left with nary_simple_op. (abso_self): New static function. (gcdv, lcmv): Replace reduce_left with nary_op. * lib.h (nary_simple_op): Declared. --- lib.c | 80 +++++++++++++++++++++++++++++++++++++------------------------------ lib.h | 2 ++ 2 files changed, 46 insertions(+), 36 deletions(-) diff --git a/lib.c b/lib.c index 26af0ffb..eeaec7b7 100644 --- a/lib.c +++ b/lib.c @@ -3202,25 +3202,37 @@ val nary_op(val self, val (*bfun)(val, val), val (*ufun)(val self, val), struct args *args, val emptyval) { - val fi, se, re; + val acc, next; cnum index = 0; if (!args_more(args, index)) return emptyval; - fi = args_get(args, &index); + acc = args_get(args, &index); if (!args_more(args, index)) - return ufun(self, fi); + return ufun(self, acc); - se = args_get(args, &index); + do { + next = args_get(args, &index); + acc = bfun(acc, next); + } while (args_more(args, index)); - if (!args_more(args, index)) - return bfun(fi, se); + return acc; +} - re = args_get_rest(args, index); +val nary_simple_op(val self, val (*bfun)(val, val), + struct args *args, val firstval) +{ + val acc = firstval, next; + cnum index = 0; + + while (args_more(args, index)) { + next = args_get(args, &index); + acc = bfun(acc, next); + } - return reduce_left(func_n2(bfun), re, bfun(fi, se), nil); + return acc; } static val unary_num(val self, val arg) @@ -3257,19 +3269,18 @@ val plusv(struct args *nlist) val minusv(val minuend, struct args *nlist) { + val acc = minuend, next; cnum index = 0; - val fi; if (!args_more(nlist, index)) - return neg(minuend); + return neg(acc); - fi = args_get(nlist, &index); + do { + next = args_get(nlist, &index); + acc = minus(acc, next); + } while (args_more(nlist, index)); - if (!args_more(nlist, index)) - return minus(minuend, fi); - - return reduce_left(func_n2(minus), args_get_list(nlist), - minus(minuend, fi), nil); + return acc; } val mulv(struct args *nlist) @@ -3279,19 +3290,18 @@ val mulv(struct args *nlist) val divv(val dividend, struct args *nlist) { + val acc = dividend, next; cnum index = 0; - val fi; if (!args_more(nlist, index)) - return divi(one, dividend); + return divi(one, acc); - fi = args_get(nlist, &index); - - if (!args_more(nlist, index)) - return divi(dividend, fi); + do { + next = args_get(nlist, &index); + acc = divi(acc, next); + } while (args_more(nlist, index)); - return reduce_left(func_n2(divi), args_get_list(nlist), - divi(dividend, fi), nil); + return acc; } val logandv(struct args *nlist) @@ -3431,12 +3441,12 @@ val min2(val a, val b) val maxv(val first, struct args *rest) { - return reduce_left(func_n2(max2), args_get_list(rest), first, nil); + return nary_simple_op(lit("max"), max2, rest, first); } val minv(val first, struct args *rest) { - return reduce_left(func_n2(min2), args_get_list(rest), first, nil); + return nary_simple_op(lit("min"), min2, rest, first); } val maxl(val first, val rest) @@ -3461,22 +3471,20 @@ val exptv(struct args *nlist) return reduce_right(func_n2(expt), args_get_list(nlist), one, nil); } +static val abso_self(val self, val arg) +{ + (void) self; + return abso(arg); +} + val gcdv(struct args *nlist) { - if (!args_more(nlist, 0)) - return zero; - if (!args_two_more(nlist, 0)) - return abso(args_atz(nlist, 0)); - return reduce_left(func_n2(gcd), args_get_list(nlist), colon_k, nil); + return nary_op(lit("gcd"), gcd, abso_self, nlist, zero); } val lcmv(struct args *nlist) { - if (!args_more(nlist, 0)) - return one; - if (!args_two_more(nlist, 0)) - return abso(args_atz(nlist, 0)); - return reduce_left(func_n2(lcm), args_get_list(nlist), colon_k, nil); + return nary_op(lit("lcm"), lcm, abso_self, nlist, zero); } val string_own(wchar_t *str) diff --git a/lib.h b/lib.h index f5e4194f..f39f075a 100644 --- a/lib.h +++ b/lib.h @@ -661,6 +661,8 @@ val numberp(val num); val nary_op(val self, val (*bfun)(val, val), val (*ufun)(val self, val), struct args *args, val emptyval); +val nary_simple_op(val self, val (*bfun)(val, val), + struct args *args, val emptyval); val plus(val anum, val bnum); val plusv(struct args *); val minus(val anum, val bnum); -- cgit v1.2.3