Chez Scheme: repair bignum shift right
When a negative bignum is shifted right by a multiple of the bigint bit size (which is 32), when a shifted-off bit is non-0, and when the result would be a sequence of bigints with all 1 bits before rounding to deal with the dropped bits, a carry that should have been delivered to a new high bigint was dropped. Closes #3794
This commit is contained in:
parent
890aa076a9
commit
f383076784
|
@ -1328,6 +1328,8 @@
|
|||
(test -1 arithmetic-shift -1 (- (expt 2 100)))
|
||||
(test -1 arithmetic-shift (- (expt 2 100)) (- (expt 2 100)))
|
||||
|
||||
(test (- (expt 16 232)) arithmetic-shift (- 307 (expt 16 240)) -32)
|
||||
|
||||
(arity-test arithmetic-shift 2 2)
|
||||
(err/rt-test (arithmetic-shift "a" 1))
|
||||
(err/rt-test (arithmetic-shift 1 "a"))
|
||||
|
|
|
@ -1322,8 +1322,10 @@ static ptr s_big_ash(tc, xp, xl, sign, cnt) ptr tc; bigit *xp; iptr xl; IBOOL si
|
|||
if ((xl -= (whole_bigits = (cnt = -cnt) / bigit_bits)) <= 0) return sign ? FIX(-1) : FIX(0);
|
||||
cnt -= whole_bigits * bigit_bits;
|
||||
|
||||
/* shift by remaining count to scratch bignum, tracking bits shifted off to the right */
|
||||
PREPARE_BIGNUM(tc, W(tc),xl)
|
||||
/* shift by remaining count to scratch bignum, tracking bits shifted off to the right;
|
||||
prepare a bignum one large than probably needed, in case we have to deal with a
|
||||
carry bit when rounding down for a negative number */
|
||||
PREPARE_BIGNUM(tc, W(tc),xl+1)
|
||||
p1 = &BIGIT(W(tc), 0);
|
||||
p2 = xp;
|
||||
k = 0;
|
||||
|
@ -1353,6 +1355,13 @@ static ptr s_big_ash(tc, xp, xl, sign, cnt) ptr tc; bigit *xp; iptr xl; IBOOL si
|
|||
p1 = &BIGIT(W(tc), xl - 1);
|
||||
for (i = xl, k = 1; k != 0 && i-- > 0; p1 -= 1)
|
||||
EADDC(0, *p1, p1, &k)
|
||||
if (k) {
|
||||
/* add carry bit back; we prepared a large enough bignum,
|
||||
and since of all the middle are zero, we don't have to reshift */
|
||||
BIGIT(W(tc), xl) = 0;
|
||||
BIGIT(W(tc), 0) = 1;
|
||||
xl++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3300,6 +3300,7 @@
|
|||
(eqv? (bitwise-arithmetic-shift 0 (- (expt 2 100))) 0)
|
||||
(eqv? (bitwise-arithmetic-shift 0 (expt 2 100)) 0)
|
||||
(eqv? (bitwise-arithmetic-shift 0 (expt 2 100)) 0)
|
||||
(eqv? (- (expt 16 232)) (bitwise-arithmetic-shift (- 307 (expt 16 240)) -32))
|
||||
($test-right-shift (lambda (x n) (bitwise-arithmetic-shift x (- n))))
|
||||
)
|
||||
|
||||
|
@ -3348,6 +3349,7 @@
|
|||
(eqv? (bitwise-arithmetic-shift-right #x-8000000000000000 31) #x-100000000)
|
||||
(eqv? (bitwise-arithmetic-shift-right #x-8000000000000000 32) #x-80000000)
|
||||
(eqv? (bitwise-arithmetic-shift-right #x-8000000000000000 33) #x-40000000)
|
||||
(eqv? (- (expt 16 232)) (bitwise-arithmetic-shift-right (- 307 (expt 16 240)) 32))
|
||||
($test-right-shift (lambda (x n) (bitwise-arithmetic-shift-right x n)))
|
||||
)
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user