Hi, has anybody else discovered that bit shifting of negative numbers is broken? Although the comment in Integer>>bitShift: says that it shifts the two's complement, it's actually doing one's complement shifting, i.e. (-1 bitShift: 1) = -2 which is plain wrong. Unfortunately, if I correct the SmallInteger>>bitShift: method, LargeInteger division breaks. And I don't want to mess with Integer>>digitDiv:neg: !
Hans-Martin
Hi, has anybody else discovered that bit shifting of negative numbers is broken? Although the comment in Integer>>bitShift: says that it shifts the two's complement, it's actually doing one's complement shifting, i.e. (-1 bitShift: 1) = -2 which is plain wrong. Unfortunately, if I correct the SmallInteger>>bitShift: method, LargeInteger division breaks. And I don't want to mess with Integer>>digitDiv:neg: !
Hans-Martin -
It would be easy enough to make a bitShift: b produce (a negated bitShift: b) negated if a is negative, and I would even be willing to dig into the problem in LargeInteger division.
HOWEVER, before doing that, there is a theoretical issue that I would want to hear some agreement on from the NAG (numerics affinity group -- you know hwo you are ;-). The issue is this: if folks are going to bitShift a number, then they are probably going to bitAnd it, too. Now, normally, "2's complement" is only defined with regard to some number of bits, since the sign bit is one of the bits, and you have to agree on where it will show up. Some of the Squeak code, inherited from ST-80, believes in 32-bit two's complement, to wit: (-2 bitAnd: 16rFF) hex = '16rFE' and (-2 bitAnd: 16rFFFFFFFFF) hex = '16rFFFFFFFE'. Why did ANDing with -2 shorten the second number, but not the first? Because -2 is 32 bits long in SOME parts of Squeak.
THEREFORE I would propose simply to forbid all bit manipulation on negative numbers, and fix the problems that crop up. This is the only way I see to avoid the problem of how negative numbers are represented in Squeak (which happens to be different for small and large integers!). Besides LI division, there may be a couple of places in the InterpreterSimulator where we are manipulating 32-bit words, but I would be willing to fix these, too.
Use positive numbers for bit patterns. Use divide to divide numbers, and bitShift to manipulate bit patterns.
Comments?
- Dan
At 01:25 PM 4/13/98 -0600, Dan Ingalls wrote: ....
THEREFORE I would propose simply to forbid all bit manipulation on
negative numbers, and fix the problems that crop up. This is the only way I see to avoid the problem of how negative numbers are represented in Squeak (which happens to be different for small and large integers!). Besides LI division, there may be a couple of places in the InterpreterSimulator where we are manipulating 32-bit words, but I would be willing to fix these, too.
Use positive numbers for bit patterns. Use divide to divide numbers, and bitShift to manipulate bit patterns.
Comments?
- Dan
Note that for similar reasons ANSI Smalltalk specified the results of bit operations involving negative integers as being "undefined" and does not specify a "not" operation. Not (to a specific bit precisions can be accomplished using #bitXor:). It also defines some additional bit field related operations that may be of interest.
In general, arbitrary length bit field operation and 2's complement arithmetic don't mix well.
Allen_Wirfs-Brock@Instantiations.com
Dan Ingalls wrote:
Comments?
IMNHO both the original poster and the ANSI standard are wrong :) As Ken Dickey pointed-out a 2's complement representation with infinite precision (infinitely many bits "to the left") is perfectly consistent. CLOS got it right. In this representation -1 bitShift: 1 *is* -2. -1 bitAt: n should be 1 for all n (even if in VisualWorks it creates an integer this large to test, and hence -1 bitAt: SmallInteger maxVal takes rather a long time to compute :) :)
Bit manipulation should be consistent with all negative numbers having an infinite number of ones "to the left" and all non-negative integers having an infinite number of zeros "to the left". Anyone assuming that -1 bitShift: 1 should be (2 raisedTo: 32) - 2 should be using C and avoiding i286s and Alphas at all costs... _______________,,,^..^,,,_______________ Eliot
squeak-dev@lists.squeakfoundation.org