diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2012-09-16 13:40:13 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2012-09-16 13:40:13 -0700 |
commit | 26c497d7da95a7d3f38bfcf7868ab65378f88007 (patch) | |
tree | acf59590b4ca25e4231ec9a3817409aa90fe36cf /arith.c | |
parent | 14e48e6f78988bc323908df944fe0a534a38629d (diff) | |
download | txr-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.c | 123 |
1 files changed, 123 insertions, 0 deletions
@@ -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); |