summaryrefslogtreecommitdiffstats
path: root/arith.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2012-09-16 13:40:13 -0700
committerKaz Kylheku <kaz@kylheku.com>2012-09-16 13:40:13 -0700
commit26c497d7da95a7d3f38bfcf7868ab65378f88007 (patch)
treeacf59590b4ca25e4231ec9a3817409aa90fe36cf /arith.c
parent14e48e6f78988bc323908df944fe0a534a38629d (diff)
downloadtxr-26c497d7da95a7d3f38bfcf7868ab65378f88007.tar.gz
txr-26c497d7da95a7d3f38bfcf7868ab65378f88007.tar.bz2
txr-26c497d7da95a7d3f38bfcf7868ab65378f88007.zip
Starting work on adding bit operations. The semantics is that
negative integers behave as an "infinite bit two's complement". * arith.c (logand, logor, logxor): New functions. * eval.c (eval_init): New intrinsic functions logand, logior, logxor. * lib.h (logand, logor, logxor): Declared. * mpi-patches/series: New patch, add-bitops. * mpi-patches/add-bitops: New file.
Diffstat (limited to 'arith.c')
-rw-r--r--arith.c123
1 files changed, 123 insertions, 0 deletions
diff --git a/arith.c b/arith.c
index 5b57faa1..82189866 100644
--- a/arith.c
+++ b/arith.c
@@ -1488,6 +1488,129 @@ val flo_int(val i)
}
}
+val logand(val a, val b)
+{
+ val c;
+
+ if (zerop(a) || zerop(b))
+ return zero;
+
+ switch (TYPE_PAIR(type(a), type(b))) {
+ case TYPE_PAIR(NUM, NUM):
+ if (a == b) {
+ return a;
+ } else {
+ cnum ac = c_num(a);
+ cnum bc = c_num(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_num(a));
+ /* fallthrough */
+ case TYPE_PAIR(BGNUM, BGNUM):
+ if (a == b)
+ return a;
+ c = make_bignum();
+ if (mp_and(mp(a), mp(b), mp(c)) != MP_OKAY)
+ goto bad;
+ return c;
+ default:
+ uw_throwf(error_s, lit("logand: non-integral operands ~s ~s"), a, b, nao);
+ }
+
+bad:
+ uw_throwf(error_s, lit("logand: operation failed on ~s ~s"), a, b, nao);
+}
+
+val logior(val a, val b)
+{
+ val c;
+
+ if (zerop(a) && zerop(b))
+ return zero;
+
+ switch (TYPE_PAIR(type(a), type(b))) {
+ case TYPE_PAIR(NUM, NUM):
+ if (a == b) {
+ return a;
+ } else {
+ cnum ac = c_num(a);
+ cnum bc = c_num(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_num(a));
+ /* fallthrough */
+ case TYPE_PAIR(BGNUM, BGNUM):
+ if (a == b)
+ return a;
+ c = make_bignum();
+ if (mp_or(mp(a), mp(b), mp(c)) != MP_OKAY)
+ goto bad;
+ return c;
+ default:
+ uw_throwf(error_s, lit("logior: non-integral operands ~s ~s"), a, b, nao);
+ }
+
+bad:
+ uw_throwf(error_s, lit("logior: operation failed on ~s ~s"), a, b, nao);
+}
+
+val logxor(val a, val b)
+{
+ val c;
+
+ if (zerop(a) && zerop(b))
+ return zero;
+
+ switch (TYPE_PAIR(type(a), type(b))) {
+ case TYPE_PAIR(NUM, NUM):
+ if (a == b) {
+ return a;
+ } else {
+ cnum ac = c_num(a);
+ cnum bc = c_num(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_num(a));
+ /* fallthrough */
+ case TYPE_PAIR(BGNUM, BGNUM):
+ if (a == b)
+ return a;
+ c = make_bignum();
+ if (mp_xor(mp(a), mp(b), mp(c)) != MP_OKAY)
+ goto bad;
+ return 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);
+}
+
void arith_init(void)
{
mp_init(&NUM_MAX_MP);