summaryrefslogtreecommitdiffstats
path: root/arith.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2015-01-27 06:30:11 -0800
committerKaz Kylheku <kaz@kylheku.com>2015-01-27 06:30:11 -0800
commite9b78ff2c7a7765b842588c9a93f84956de9834d (patch)
tree7a0bd22f89841184171f4344cf3080434b593e02 /arith.c
parent0515d6ee6af5f16a951f7dd61ddc3f3e2cd0e562 (diff)
downloadtxr-e9b78ff2c7a7765b842588c9a93f84956de9834d.tar.gz
txr-e9b78ff2c7a7765b842588c9a93f84956de9834d.tar.bz2
txr-e9b78ff2c7a7765b842588c9a93f84956de9834d.zip
* arith.c (width): New function.
* arith.h (width): Declared. * eval.c (eval_init): Width registered as intrisinc. * txr.1: Documented width.
Diffstat (limited to 'arith.c')
-rw-r--r--arith.c40
1 files changed, 40 insertions, 0 deletions
diff --git a/arith.c b/arith.c
index 365818e3..a037e5df 100644
--- a/arith.c
+++ b/arith.c
@@ -2187,6 +2187,46 @@ val toint(val obj, val base)
}
}
+val width(val obj)
+{
+ switch (tag(obj)) {
+ case TAG_NUM:
+ case TAG_CHR:
+ {
+ cnum n = c_num(obj);
+
+ if (n < 0) {
+ n &= INT_PTR_MAX;
+ n ^= INT_PTR_MAX;
+ return num_fast(highest_bit(n));
+ }
+ return num_fast(highest_bit(n));
+ }
+ case TAG_PTR:
+ if (type(obj) == BGNUM) {
+ int count;
+ if (mp_cmp_z(mp(obj)) == MP_LT) {
+ mp_int tmp;
+ int i;
+
+ mp_2comp(mp(obj), &tmp, mp(obj)->used);
+
+ for (i = 0; i < tmp.used; i++)
+ tmp.dp[i] ^= MP_DIGIT_MAX;
+
+ count = mp_count_bits(&tmp);
+ mp_clear(&tmp);
+ } else {
+ count = mp_count_bits(mp(obj));
+ }
+ return num(count);
+ }
+ default:
+ break;
+ }
+ uw_throwf(error_s, lit("integer-length: ~s isn't an integer"), obj, nao);
+}
+
void arith_init(void)
{
mp_init(&NUM_MAX_MP);