summaryrefslogtreecommitdiffstats
path: root/arith.c
diff options
context:
space:
mode:
Diffstat (limited to 'arith.c')
-rw-r--r--arith.c43
1 files changed, 43 insertions, 0 deletions
diff --git a/arith.c b/arith.c
index 90575fc5..badc5d84 100644
--- a/arith.c
+++ b/arith.c
@@ -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;