summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2018-03-29 06:45:17 -0700
committerKaz Kylheku <kaz@kylheku.com>2018-03-29 06:45:17 -0700
commit706e9bc7983ebb54cfbd7f95b1e98252dfd0d558 (patch)
tree86422b089d1b08600328641aa7e97e0fa0366ad8
parent37b9e093822a7cb4d813b5ea41d6097cce54de33 (diff)
downloadtxr-706e9bc7983ebb54cfbd7f95b1e98252dfd0d558.tar.gz
txr-706e9bc7983ebb54cfbd7f95b1e98252dfd0d558.tar.bz2
txr-706e9bc7983ebb54cfbd7f95b1e98252dfd0d558.zip
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.
-rw-r--r--lib.c80
-rw-r--r--lib.h2
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);