diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2017-06-14 22:02:11 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2017-06-14 22:02:11 -0700 |
commit | 2a5a5085c6f73d02f522703a02fb7e23a02dcace (patch) | |
tree | 0c57aa9d68c365abd1053f997e978e8970caf3b1 | |
parent | 6df765493bcfc913e7797e09ce134487773c40b7 (diff) | |
download | txr-2a5a5085c6f73d02f522703a02fb7e23a02dcace.tar.gz txr-2a5a5085c6f73d02f522703a02fb7e23a02dcace.tar.bz2 txr-2a5a5085c6f73d02f522703a02fb7e23a02dcace.zip |
bugfix: sign-extend broken for bignums.
* arith.c (sign_extend): After taking the two's complement
which works at the granularity of digits, not the exact
number of bits, we must truncate the number to the
exact number of bits before negating. Otherwise we end up
with an excessively large value. For instance if a bignum
like #x80... is sign extended tightly to the upper
1 bit, the resulting value is something like #-xFFFF80...,
rather than #x-80... as it should be. There are extra
1 bits padding up to the bignum digit. These must be
chopped away.
-rw-r--r-- | arith.c | 1 |
1 files changed, 1 insertions, 0 deletions
@@ -2405,6 +2405,7 @@ val sign_extend(val n, val nbits) { val out = make_ubignum(); mp_2comp(mp(ntrunc), mp(out), mp(ntrunc)->used); + mp_trunc(mp(out), mp(out), c_num(nbits)); mp_neg(mp(out), mp(out)); return normalize(out); } |