'From Squeak3.10beta of 22 July 2007 [latest update: #7159] on 26 January 2008 at 2:39:48 am'!
"Change Set: TwoComplementDigitLogic-Patch-M6874-nice
Date: 26 January 2008
Author: nice
This is patch for http://bugs.squeak.org/view.php?id=6874
bitAnd: use digitLogic:op:len: which is bugged in some special cases:
When bit logic is performed on LargeNegativeInteger (two complement)
And the highbit just fall on a digit (8bit) boundary
And a carry is not taken into account
Example of tricky two complement:
11111111 10000000 00000000 00000000 00000000 is (2 raisedTo: 31) negated
11111111 01111111 11111111 11111111 11111111 is (2 raisedTo: 31) negated-1
result of bitAnd:
11111111 00000000 00000000 00000000 00000000 is (2 raisedTo: 32) negated
Implementation is tricky, because the absolute value is stored, not the two complements. Thus there are sort of -1-self operations leading to some carry for processing two complement of two complements....
Well, except the carry rz in algorithm was not taken into account,
the result was stored on 4 digits,
then reduced to zero...
A symptom of this bug was http://bugs.squeak.org/view.php?id=6873"
!
!Integer methodsFor: 'private' stamp: 'nice 1/26/2008 02:12'!
digitLogic: arg op: op length: len
| i result neg1 neg2 rneg z1 z2 rz b1 b2 b |
neg1 := self negative.
neg2 := arg negative.
rneg := ((neg1
ifTrue: [-1]
ifFalse: [0])
perform: op
with: (neg2
ifTrue: [-1]
ifFalse: [0]))
< 0.
result := Integer new: len neg: rneg.
rz := z1 := z2 := true.
i := 0.
[(i := i + 1) <= len
or: ["mind a carry on result that might go past len digits"
rneg and: [rz
and: [result := result growby: 1.
true]]]]
whileTrue: [b1 := self digitAt: i.
neg1
ifTrue: [b1 := z1
ifTrue: [b1 = 0
ifTrue: [0]
ifFalse: [z1 := false.
256 - b1]]
ifFalse: [255 - b1]].
b2 := arg digitAt: i.
neg2
ifTrue: [b2 := z2
ifTrue: [b2 = 0
ifTrue: [0]
ifFalse: [z2 := false.
256 - b2]]
ifFalse: [255 - b2]].
b := b1 perform: op with: b2.
result
digitAt: i
put: (rneg
ifTrue: [rz
ifTrue: [b = 0
ifTrue: [0]
ifFalse: [rz := false.
256 - b]]
ifFalse: [255 - b]]
ifFalse: [b])].
^ result normalize! !