diff options
-rw-r--r-- | arith.c | 43 | ||||
-rw-r--r-- | eval.c | 3 | ||||
-rw-r--r-- | lib.h | 1 | ||||
-rw-r--r-- | txr.1 | 7 |
4 files changed, 53 insertions, 1 deletions
@@ -2461,6 +2461,49 @@ val logxor(val a, val b) { val c; + switch (TYPE_PAIR(type(a), type(b))) { + case TYPE_PAIR(NUM, CHR): + case TYPE_PAIR(CHR, NUM): + { + cnum ac = c_n(a); + cnum bc = c_n(b); + return chr(ac ^ bc); + } + case TYPE_PAIR(NUM, NUM): + { + cnum ac = c_n(a); + cnum bc = c_n(b); + return num_fast(ac ^ bc); + } + case TYPE_PAIR(BGNUM, NUM): + { + val tmp = a; + a = b; + b = tmp; + } + /* fallthrough */ + case TYPE_PAIR(NUM, BGNUM): + a = bignum(c_n(a)); + /* fallthrough */ + case TYPE_PAIR(BGNUM, BGNUM): + if (a == b) + return zero; + c = make_ubignum(); + if (mp_xor(mp(a), mp(b), mp(c)) != MP_OKAY) + goto bad; + return normalize(c); + default: + uw_throwf(error_s, lit("logxor: non-integral operands ~s ~s"), a, b, nao); + } + +bad: + uw_throwf(error_s, lit("logxor: operation failed on ~s ~s"), a, b, nao); +} + +val logxor_old(val a, val b) +{ + val c; + if (zerop(a) && zerop(b)) return zero; @@ -6476,7 +6476,8 @@ void eval_init(void) reg_fun(intern(lit("in"), user_package), func_n4o(in, 2)); reg_fun(intern(lit("logand"), user_package), func_n0v(logandv)); reg_fun(intern(lit("logior"), user_package), func_n0v(logiorv)); - reg_fun(intern(lit("logxor"), user_package), func_n2(logxor)); + reg_fun(intern(lit("logxor"), user_package), + func_n2(if3(opt_compat && opt_compat <= 202, logxor_old, logxor))); reg_fun(intern(lit("logtest"), user_package), func_n2(logtest)); reg_fun(intern(lit("lognot"), user_package), func_n2o(lognot, 1)); reg_fun(intern(lit("logtrunc"), user_package), func_n2(logtrunc)); @@ -749,6 +749,7 @@ val logior(val, val); val logandv(struct args *nlist); val logiorv(struct args *nlist); val logxor(val, val); +val logxor_old(val, val); val logtest(val, val); val lognot(val, val); val logtrunc(val a, val bits); @@ -65473,6 +65473,13 @@ of these version values, the described behaviors are provided if is given an argument which is equal or lower. For instance .code "-C 103" selects the behaviors described below for version 105, but not those for 102. +.IP 202 +Up to \*(TX 202, the +.code logxor +function was incorrectly implemented, producing wrong results when both +arguments are the same fixnum integer, or the same bignum object. +The incorrect behavior is restored if 202 or earlier compatibility is +requested. .IP 199 After \*(TX 199, certain global variables that had been deprecated for a long time, and no longer documented, were removed. Requesting 199 or |