'From Squeak3.2alpha of 3 October 2001 [latest update: #4599] on 7 January 2002 at 9:18:23 pm'! "Change Set: DigitLogicFix-hmm Date: 7 January 2002 Author: Hans-Martin Mosner Fixes a problem with digit logic involving large integers with different sign. Example: -2 bitAnd: 16rFFFFFFFF should result in 16rFFFFFFFE, but yields 16rFE without this fix. The class method testing various digit logic cases has been refactored into a SUnit test. To test, print the result of: IntegerDigitLogicTestCase suite run "! TestCase subclass: #IntegerDigitLogicTestCase instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Kernel-Numbers'! !Integer methodsFor: 'private' stamp: 'hmm 1/7/2002 20:55'! digitLogic: arg op: op length: len | 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. 1 to: result digitLength do: [:i | 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! ! !Integer class methodsFor: 'instance creation' stamp: 'hmm 1/7/2002 21:00'! testBitLogic "Integer testBitLogic" "This little suite of tests is designed to verify correct operation of most of Squeak's bit manipulation code, including two's complement representation of negative values. It was written in a hurry and is probably lacking several important checks." "Shift 1 bit left then right and test for 1" | n | 1 to: 100 do: [:i | ((1 bitShift: i) bitShift: i negated) = 1 ifFalse: [self error: 'Bit Logic Failure']]. "Shift -1 left then right and test for 1" 1 to: 100 do: [:i | ((-1 bitShift: i) bitShift: i negated) = -1 ifFalse: [self error: 'Bit Logic Failure']]. "And a single bit with -1 and test for same value" 1 to: 100 do: [:i | ((1 bitShift: i) bitAnd: -1) = (1 bitShift: i) ifFalse: [self error: 'Bit Logic Failure']]. "Verify that (n bitAnd: n negated) = n for single bits" 1 to: 100 do: [:i | n _ 1 bitShift: i. (n bitAnd: n negated) = n ifFalse: [self error: 'Bit Logic Failure']]. "Verify that n negated = (n complemented + 1) for single bits" 1 to: 100 do: [:i | n _ 1 bitShift: i. n negated = ((n bitXor: -1) + 1) ifFalse: [self error: 'Bit Logic Failure']]. "Verify that (n + n complemented) = -1 for single bits" 1 to: 100 do: [:i | n _ 1 bitShift: i. (n + (n bitXor: -1)) = -1 ifFalse: [self error: 'Bit Logic Failure']]. "Verify that n negated = (n complemented +1) for single bits" 1 to: 100 do: [:i | n _ 1 bitShift: i. n negated = ((n bitXor: -1) + 1) ifFalse: [self error: 'Bit Logic Failure']]. (-2 bitAnd: 16rFFFFFFFF) = 16rFFFFFFFE ifFalse: [self error: 'Bit Logic Failure']! ! !IntegerDigitLogicTestCase methodsFor: 'running' stamp: 'hmm 1/7/2002 21:12'! testAndSingleBitWithMinusOne "And a single bit with -1 and test for same value" 1 to: 100 do: [:i | self assert: ((1 bitShift: i) bitAnd: -1) = (1 bitShift: i)].! ! !IntegerDigitLogicTestCase methodsFor: 'running' stamp: 'hmm 1/7/2002 21:13'! testMixedSignDigitLogic "Verify that mixed sign logic with large integers works." self assert: (-2 bitAnd: 16rFFFFFFFF) = 16rFFFFFFFE! ! !IntegerDigitLogicTestCase methodsFor: 'running' stamp: 'hmm 1/7/2002 21:12'! testNBitAndNNegatedEqualsN "Verify that (n bitAnd: n negated) = n for single bits" | n | 1 to: 100 do: [:i | n _ 1 bitShift: i. self assert: (n bitAnd: n negated) = n]! ! !IntegerDigitLogicTestCase methodsFor: 'running' stamp: 'hmm 1/7/2002 21:12'! testNNegatedEqualsNComplementedPlusOne "Verify that n negated = (n complemented + 1) for single bits" | n | 1 to: 100 do: [:i | n _ 1 bitShift: i. self assert: n negated = ((n bitXor: -1) + 1)]! ! !IntegerDigitLogicTestCase methodsFor: 'running' stamp: 'hmm 1/7/2002 21:13'! testShiftMinusOne1LeftThenRight "Shift -1 left then right and test for 1" 1 to: 100 do: [:i | self assert: ((-1 bitShift: i) bitShift: i negated) = -1]. ! ! !IntegerDigitLogicTestCase methodsFor: 'running' stamp: 'hmm 1/7/2002 21:12'! testShiftOneLeftThenRight "Shift 1 bit left then right and test for 1" 1 to: 100 do: [:i | self assert: ((1 bitShift: i) bitShift: i negated) = 1]. ! ! IntegerDigitLogicTestCase removeSelector: #testShift1LeftThenRight! !Integer reorganize! ('testing' even isInteger isPowerOfTwo) ('arithmetic' * + - / // \\\ alignedTo: quo:) ('comparing' < = > hash) ('truncation and round off' asLargerPowerOfTwo asPowerOfTwo asSmallerPowerOfTwo atRandom atRandom: ceiling floor normalize rounded truncated) ('enumerating' timesRepeat:) ('mathematical functions' degreeCos degreeSin factorial gcd: lcm: raisedTo:modulo: take:) ('bit manipulation' << >> allMask: anyBitOfMagnitudeFrom:to: anyMask: bitAnd: bitClear: bitInvert bitInvert32 bitOr: bitShift: bitShiftMagnitude: bitXor: highBit highBitOfMagnitude lowBit noMask:) ('converting' adaptToFraction:andSend: asCharacter asColorOfDepth: asFloat asFraction asHexDigit asInteger) ('printing' asStringWithCommas asStringWithCommasSigned asTwoCharacterString asWords byteEncode:base: destinationBuffer: digitBuffer: hex hex8 isLiteral printOn:base: printStringRadix:on: radix: romanString) ('system primitives' lastDigit replaceFrom:to:with:startingAt:) ('private' copyto: digitAdd: digitCompare: digitDiv:neg: digitLogic:op:length: digitLshift: digitMultiply:neg: digitRshift:bytes:lookfirst: digitSubtract: growby: growto: romanDigits:for:on:) ('benchmarks' benchFib benchmark tinyBenchmarks) ('tiles' asPrecedenceName) ('VWCompatibility' printStringRadix:) !