diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2019-03-09 11:42:11 -0800 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2019-03-09 11:42:11 -0800 |
commit | 285e3a5c375774135c29c6b7ff3b4b811b6cacd1 (patch) | |
tree | c032fa7aae6fcc31aef3d62d9a452d6f6d9822fc /arith.c | |
parent | e844d3a602af4380c196d896b803b67d58ecbcea (diff) | |
download | txr-285e3a5c375774135c29c6b7ff3b4b811b6cacd1.tar.gz txr-285e3a5c375774135c29c6b7ff3b4b811b6cacd1.tar.bz2 txr-285e3a5c375774135c29c6b7ff3b4b811b6cacd1.zip |
expt: handle negative integer exponents with integer bases.
* arith.c (expt): The function overhauled. Raising integers to
negative integers now works. Raising zero to a negative is
diagnosed as a division by zero for operands of all kinds.
* txr.1: Documentation updated for expt, and also division by
zero error is documented for the / function.
Diffstat (limited to 'arith.c')
-rw-r--r-- | arith.c | 70 |
1 files changed, 53 insertions, 17 deletions
@@ -1966,11 +1966,14 @@ tail: mp_int tmpa; val n; mp_err mpe = MP_OKAY; - if (b < 0) - goto negexp; - if (bnum == zero) + if (b < 0) { + if (anum == zero) + goto divzero; + return flo(pow(a, b)); + } + if (b == 0) return one; - if (bnum == one) + if (b == 1) return anum; n = make_bignum(); mp_init(&tmpa); @@ -1995,8 +1998,12 @@ tail: mp_int tmpa; val n; mp_err mpe = MP_OKAY; - if (mp_cmp_z(mp(bnum)) == MP_LT) - goto negexp; + if (mp_cmp_z(mp(bnum)) == MP_LT) { + if (anum == zero) + goto divzero; + bnum = flo_int(bnum); + goto tail; + } n = make_bignum(); mp_init(&tmpa); mp_set_intptr(&tmpa, a); @@ -2011,11 +2018,15 @@ tail: cnum b = c_n(bnum); val n; mp_err mpe = MP_OKAY; - if (b < 0) - goto negexp; - if (bnum == zero) + if (b < 0) { + if (mp_cmp_z(mp(anum)) == MP_LT) + goto divzero; + anum = flo_int(anum); + goto tail; + } + if (b == 0) return one; - if (bnum == one) + if (b == 1) return anum; n = make_bignum(); if (sizeof (int_ptr_t) <= sizeof (mp_digit)) { @@ -2035,8 +2046,13 @@ tail: { val n; mp_err mpe = MP_OKAY; - if (mp_cmp_z(mp(bnum)) == MP_LT) - goto negexp; + if (mp_cmp_z(mp(bnum)) == MP_LT) { + if (mp_cmp_z(mp(anum)) == MP_LT) + goto divzero; + anum = flo_int(anum); + bnum = flo_int(bnum); + goto tail; + } n = make_bignum(); mpe = mp_expt(mp(anum), mp(bnum), mp(n)); if (mpe != MP_OKAY) @@ -2045,12 +2061,32 @@ tail: return n; } case TYPE_PAIR(NUM, FLNUM): - /* TODO: error checking */ - return flo(pow(c_n(anum), c_flo(bnum, self))); + { + cnum a = c_n(anum); + double b = c_flo(bnum, self); + + if (a == 0 && b < 0) + goto divzero; + return flo(pow(a, b)); + } case TYPE_PAIR(FLNUM, NUM): + { + double a = c_flo(anum, self); + cnum b = c_n(bnum); + + if (a == 0 && b < 0) + goto divzero; + return flo(pow(a, b)); + } return flo(pow(c_flo(anum, self), c_n(bnum))); case TYPE_PAIR(FLNUM, FLNUM): - return flo(pow(c_flo(anum, self), c_flo(bnum, self))); + { + double a = c_flo(anum, self); + double b = c_flo(bnum, self); + if (a == 0 && b < 0) + goto divzero; + return flo(pow(a, b)); + } case TYPE_PAIR(BGNUM, FLNUM): anum = flo_int(anum); goto tail; @@ -2060,8 +2096,8 @@ tail: } invalid_ops(self, anum, bnum); -negexp: - uw_throwf(type_error_s, lit("~a: negative exponent"), self, nao); +divzero: + divzero(self); } val exptmod(val base, val exp, val mod) |