summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arith.c78
-rw-r--r--tests/016/arith.tl24
-rw-r--r--txr.14
3 files changed, 72 insertions, 34 deletions
diff --git a/arith.c b/arith.c
index 44e466df..225d6586 100644
--- a/arith.c
+++ b/arith.c
@@ -4185,41 +4185,61 @@ val nary_op(val self, val (*bfun)(val, val),
return acc;
}
-static val nary_op_keyfun(val self, val (*bfun)(val, val),
- val (*ufun)(val self, val),
- struct args *args, val emptyval,
- val keyfun)
+val nary_simple_op(val (*bfun)(val, val),
+ struct args *args, val firstval)
{
- val acc, next;
+ val acc = firstval, next;
cnum index = 0;
- if (!args_more(args, index))
- return emptyval;
+ while (args_more(args, index)) {
+ next = args_get(args, &index);
+ acc = bfun(acc, next);
+ }
- acc = funcall1(keyfun, args_get(args, &index));
+ return acc;
+}
- if (!args_more(args, index))
+static val nary_op_seq(val self, val (*bfun)(val, val),
+ val (*ufun)(val self, val),
+ val seq, val emptyval)
+{
+ seq_iter_t item_iter;
+ val acc, next;
+ seq_iter_init(self, &item_iter, seq);
+
+ if (!seq_get(&item_iter, &acc))
+ return emptyval;
+
+ if (!seq_get(&item_iter, &next))
return ufun(self, acc);
do {
- next = funcall1(keyfun, args_get(args, &index));
acc = bfun(acc, next);
- } while (args_more(args, index));
+ } while (seq_get(&item_iter, &next));
return acc;
}
-
-val nary_simple_op(val (*bfun)(val, val),
- struct args *args, val firstval)
+static val nary_op_seq_keyfun(val self, val (*bfun)(val, val),
+ val (*ufun)(val self, val),
+ val seq, val emptyval, val keyfun)
{
- val acc = firstval, next;
- cnum index = 0;
+ seq_iter_t item_iter;
+ val acc, next;
+ seq_iter_init(self, &item_iter, seq);
- while (args_more(args, index)) {
- next = args_get(args, &index);
+ if (!seq_get(&item_iter, &acc))
+ return emptyval;
+
+ acc = funcall1(keyfun, acc);
+
+ if (!seq_get(&item_iter, &next))
+ return ufun(self, acc);
+
+ do {
+ next = funcall1(keyfun, next);
acc = bfun(acc, next);
- }
+ } while (seq_get(&item_iter, &next));
return acc;
}
@@ -4428,26 +4448,18 @@ val numneqv(struct args *args)
}
}
-static val sumv(struct args *nlist, val keyfun)
-{
- return nary_op_keyfun(plus_s, plus, unary_arith, nlist, zero, keyfun);
-}
-
val sum(val seq, val keyfun)
{
- args_decl_list(args, ARGS_MIN, tolist(seq));
- return if3(missingp(keyfun), plusv(args), sumv(args, keyfun));
-}
-
-static val prodv(struct args *nlist, val keyfun)
-{
- return nary_op_keyfun(mul_s, mul, unary_num, nlist, one, keyfun);
+ return if3(missingp(keyfun),
+ nary_op_seq(plus_s, plus, unary_arith, seq, zero),
+ nary_op_seq_keyfun(plus_s, plus, unary_arith, seq, zero, keyfun));
}
val prod(val seq, val keyfun)
{
- args_decl_list(args, ARGS_MIN, tolist(seq));
- return if3(missingp(keyfun), mulv(args), prodv(args, keyfun));
+ return if3(missingp(keyfun),
+ nary_op_seq(mul_s, mul, unary_num, seq, one),
+ nary_op_seq_keyfun(mul_s, mul, unary_num, seq, one, keyfun));
}
static val rexpt(val right, val left)
diff --git a/tests/016/arith.tl b/tests/016/arith.tl
index 43efb6bb..52e8667b 100644
--- a/tests/016/arith.tl
+++ b/tests/016/arith.tl
@@ -142,3 +142,27 @@
(test (ffi-get (ffi-put #x-8000000000000000 (ffi int64)) (ffi int64))
#x-8000000000000000)
+
+(mtest
+ (sum #()) 0
+ (sum #(1)) 1
+ (sum #(1 2)) 3
+ (sum #(1 2 3)) 6
+ (sum #() (op * 10)) 0
+ (sum #(1) (op * 10)) 10
+ (sum #(1 2) (op * 10)) 30
+ (sum #(1 2 3) (op * 10)) 60
+ (sum 1..10) 45
+ (sum 2..10) 44)
+
+(mtest
+ (prod #()) 1
+ (prod #(1)) 1
+ (prod #(1 2)) 2
+ (prod #(1 2 3)) 6
+ (prod #() (op * 10)) 1
+ (prod #(1) (op * 10)) 10
+ (prod #(1 2) (op * 10)) 200
+ (prod #(1 2 3) (op * 10)) 6000
+ (prod 2..8) 5040
+ (prod 3..8) 2520)
diff --git a/txr.1 b/txr.1
index 1a172ca7..32a38b4a 100644
--- a/txr.1
+++ b/txr.1
@@ -43961,7 +43961,9 @@ The
and
.code prod
functions operate on an effective sequence of numbers derived from
-.metn sequence .
+.metn sequence ,
+which is an object suitable for iteration according to
+.codn seq-begin .
If the
.meta keyfun