summaryrefslogtreecommitdiffstats
path: root/arith.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2011-12-13 20:00:49 -0800
committerKaz Kylheku <kaz@kylheku.com>2011-12-13 20:00:49 -0800
commit901f7e6c7588b86cbd63172a4871be22bb024b6d (patch)
tree05ed4b47f6a035d1ceab458fefc3bfc4724c73e8 /arith.c
parent64b06932ed7d8dd8c904e66a70a53ae4c8ec4448 (diff)
downloadtxr-901f7e6c7588b86cbd63172a4871be22bb024b6d.tar.gz
txr-901f7e6c7588b86cbd63172a4871be22bb024b6d.tar.bz2
txr-901f7e6c7588b86cbd63172a4871be22bb024b6d.zip
* arith.c (exptmod, gcd): New functions.
* eval.c (eval_init): New functions registered as intrisics. * lib.h (exptmod, gcd): Declared. * txr.1: Documentation stubs added.
Diffstat (limited to 'arith.c')
-rw-r--r--arith.c53
1 files changed, 53 insertions, 0 deletions
diff --git a/arith.c b/arith.c
index bde39aad..f222617d 100644
--- a/arith.c
+++ b/arith.c
@@ -932,6 +932,34 @@ val expt(val anum, val bnum)
abort();
}
+val exptmod(val base, val exp, val mod)
+{
+ val n;
+
+ if (!numberp(base) || !numberp(exp) || !numberp(mod))
+ goto inval;
+
+ if (fixnump(base))
+ base = bignum(c_num(base));
+
+ if (fixnump(exp))
+ exp = bignum(c_num(exp));
+
+ if (fixnump(mod))
+ mod = bignum(c_num(mod));
+
+ n = make_bignum();
+
+ if (mp_exptmod(mp(base), mp(exp), mp(mod), mp(n)) != MP_OKAY)
+ goto inval;
+
+ return n;
+inval:
+ uw_throwf(error_s, lit("exptmod: invalid operands ~s ~s ~s"),
+ base, exp, mod, nao);
+ abort();
+}
+
static int_ptr_t isqrt_fixnum(int_ptr_t a)
{
int_ptr_t mask = (int_ptr_t) 1 << (highest_bit(a) / 2);
@@ -962,6 +990,31 @@ val isqrt(val anum)
uw_throwf(error_s, lit("sqrt: invalid operand ~s"), anum, nao);
}
+val gcd(val anum, val bnum)
+{
+ val n;
+
+ if (!numberp(anum) || !numberp(bnum))
+ goto inval;
+
+ if (fixnump(anum))
+ anum = bignum(c_num(anum));
+
+ if (fixnump(bnum))
+ bnum = bignum(c_num(bnum));
+
+ n = make_bignum();
+
+ if (mp_gcd(mp(anum), mp(bnum), mp(n)) != MP_OKAY)
+ goto inval;
+
+ return n;
+inval:
+ uw_throwf(error_s, lit("gcd: invalid operands ~s ~s ~s"),
+ anum, bnum, nao);
+ abort();
+}
+
void arith_init(void)
{
mp_init(&NUM_MAX_MP);