summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2011-12-11 20:17:59 -0800
committerKaz Kylheku <kaz@kylheku.com>2011-12-11 20:17:59 -0800
commitdedf96f4bd008531e357c6141e3e8219b0ea7065 (patch)
tree893706b8d51c37cfac9cbcf03571d87c294d4a61
parent68fbc5322e282f41e2ee8c84cc16f6b6a4d39670 (diff)
downloadtxr-dedf96f4bd008531e357c6141e3e8219b0ea7065.tar.gz
txr-dedf96f4bd008531e357c6141e3e8219b0ea7065.tar.bz2
txr-dedf96f4bd008531e357c6141e3e8219b0ea7065.zip
* arith.c (trunc): Error messages prefixed with trunc:.
(mod): New function, reimplementation of removed mod from lib.c. * lib.c (mod): Function removed.
-rw-r--r--ChangeLog7
-rw-r--r--arith.c65
-rw-r--r--lib.c13
3 files changed, 68 insertions, 17 deletions
diff --git a/ChangeLog b/ChangeLog
index 6902db1a..b3cc4e39 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,12 @@
2011-12-11 Kaz Kylheku <kaz@kylheku.com>
+ * arith.c (trunc): Error messages prefixed with trunc:.
+ (mod): New function, reimplementation of removed mod from lib.c.
+
+ * lib.c (mod): Function removed.
+
+2011-12-11 Kaz Kylheku <kaz@kylheku.com>
+
Bignum division implemented. More portability bugs found in MPI:
code like 1 << n, where n exceeds the width of the type int.
diff --git a/arith.c b/arith.c
index 89907332..e4155442 100644
--- a/arith.c
+++ b/arith.c
@@ -512,7 +512,7 @@ val trunc(val anum, val bnum)
int neg = ((a < 0 && b > 0) || (a > 0 && b < 0));
if (b == 0)
- uw_throw(numeric_error_s, lit("division by zero"));
+ uw_throw(numeric_error_s, lit("trunc: division by zero"));
{
cnum quot = ap / bp;
@@ -531,7 +531,7 @@ val trunc(val anum, val bnum)
cnum b = c_num(bnum);
cnum bp = ABS(b);
if (mp_div_d(mp(anum), bp, mp(n), 0) != MP_OKAY)
- uw_throw(numeric_error_s, lit("division by zero"));
+ uw_throw(numeric_error_s, lit("trunc: division by zero"));
if (b < 0)
mp_neg(mp(n), mp(n));
} else {
@@ -539,7 +539,7 @@ val trunc(val anum, val bnum)
mp_init(&tmp);
mp_set_intptr(&tmp, c_num(bnum));
if (mp_div(mp(anum), &tmp, mp(n), 0) != MP_OKAY)
- uw_throw(numeric_error_s, lit("division by zero"));
+ uw_throw(numeric_error_s, lit("trunc: division by zero"));
}
return normalize(n);
}
@@ -550,7 +550,7 @@ val trunc(val anum, val bnum)
type_check(bnum, BGNUM);
n = make_bignum();
if (mp_div(mp(anum), mp(bnum), mp(n), 0) != MP_OKAY)
- uw_throw(numeric_error_s, lit("division by zero"));
+ uw_throw(numeric_error_s, lit("trunc: division by zero"));
return normalize(n);
}
}
@@ -558,6 +558,63 @@ val trunc(val anum, val bnum)
abort();
}
+val mod(val anum, val bnum)
+{
+ int tag_a = tag(anum);
+ int tag_b = tag(bnum);
+
+ switch (TAG_PAIR(tag_a, tag_b)) {
+ case TAG_PAIR(TAG_NUM, TAG_NUM):
+ {
+ cnum a = c_num(anum);
+ cnum b = c_num(bnum);
+
+ if (b == 0)
+ uw_throw(numeric_error_s, lit("mod: division by zero"));
+
+ {
+ cnum m = a % b;
+ return num(m < 0 ? m + ABS(b) : m);
+ }
+ }
+ case TAG_PAIR(TAG_NUM, TAG_PTR):
+ type_check(bnum, BGNUM);
+ return zero;
+ case TAG_PAIR(TAG_PTR, TAG_NUM):
+ {
+ type_check(anum, BGNUM);
+ if (sizeof (int_ptr_t) <= sizeof (mp_digit)) {
+ cnum b = c_num(bnum);
+ cnum bp = ABS(b);
+ mp_digit n;
+ if (mp_mod_d(mp(anum), bp, &n) != MP_OKAY)
+ uw_throw(numeric_error_s, lit("mod: division by zero"));
+ return num(n);
+ } else {
+ val n = make_bignum();
+ mp_int tmp;
+ mp_init(&tmp);
+ mp_set_intptr(&tmp, c_num(bnum));
+ if (mp_mod(mp(anum), &tmp, mp(n)) != MP_OKAY)
+ uw_throw(numeric_error_s, lit("mod: division by zero"));
+ return normalize(n);
+ }
+ }
+ case TAG_PAIR(TAG_PTR, TAG_PTR):
+ {
+ val n;
+ type_check(anum, BGNUM);
+ type_check(bnum, BGNUM);
+ n = make_bignum();
+ if (mp_mod(mp(anum), mp(bnum), mp(n)) != MP_OKAY)
+ uw_throw(numeric_error_s, lit("mod: division by zero"));
+ return normalize(n);
+ }
+ }
+ uw_throwf(error_s, lit("mod: invalid operands ~s ~s"), anum, bnum, nao);
+ abort();
+}
+
void arith_init(void)
{
mp_init(&NUM_MAX_MP);
diff --git a/lib.c b/lib.c
index cd9d8edd..9432111d 100644
--- a/lib.c
+++ b/lib.c
@@ -857,19 +857,6 @@ val mulv(val nlist)
return reduce_left(func_n2(mul), cdr(nlist), car(nlist), nil);
}
-val mod(val anum, val bnum)
-{
- cnum a = c_num(anum);
- cnum b = c_num(bnum);
-
- numeric_assert (b != 0);
-
- {
- cnum result = a % b;
- return num(result);
- }
-}
-
val zerop(val num)
{
return c_num(num) == 0 ? t : nil;