diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2011-12-13 20:00:49 -0800 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2011-12-13 20:00:49 -0800 |
commit | 901f7e6c7588b86cbd63172a4871be22bb024b6d (patch) | |
tree | 05ed4b47f6a035d1ceab458fefc3bfc4724c73e8 /arith.c | |
parent | 64b06932ed7d8dd8c904e66a70a53ae4c8ec4448 (diff) | |
download | txr-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.c | 53 |
1 files changed, 53 insertions, 0 deletions
@@ -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); |