'From Squeak3.10beta of 22 July 2007 [latest update: #7159] on 21 March 2008 at 9:50:48 pm'!
"Change Set: Integer_bitAt_M6985-nice
Date: 21 March 2008
Author: nice
Add is a simple feature that is missing:
anInteger bitAt: n answers 1 if nth bit is set to 1, 0 otherwise.
Negatives act as two complements, also LargeNegativeInteger."!
!Integer methodsFor: 'bit manipulation' stamp: 'nice 3/21/2008 21:47'!
bitAt: anInteger
"Answer 1 if the bit at position anInteger is set to 1, 0 otherwise.
self is considered an infinite sequence of bits, so anInteger can be any strictly positive integer.
Bit at position 1 is the least significant bit.
Negative numbers are in two-complements.
This is a naive implementation that can be refined in subclass for speed"
^(self bitShift: 1 - anInteger) bitAnd: 1! !
!LargePositiveInteger methodsFor: 'bit manipulation' stamp: 'nice 3/21/2008 00:09'!
bitAt: anInteger
"Optimize super algorithm to avoid long bit operations.
Instead work on digits which are known to be SmallInteger and fast.
Note that this algorithm does not work for negative integers."
| digitIndex bitIndex |
digitIndex := anInteger - 1 // 8 + 1.
digitIndex > self digitLength ifTrue: [^0].
bitIndex := anInteger - 1 \\ 8 + 1.
^(self digitAt: digitIndex) bitAt: bitIndex! !
!LargeNegativeInteger methodsFor: 'bit manipulation' stamp: 'nice 3/21/2008 01:02'!
bitAt: anInteger
"super would not work because we have to pretend we are in two-complement.
this has to be tricky..."
| digitIndex bitIndex i |
digitIndex := anInteger - 1 // 8 + 1.
digitIndex > self digitLength ifTrue: [^1].
bitIndex := anInteger - 1 \\ 8 + 1.
i := 1.
[i = digitIndex
ifTrue:
["evaluate two complement (bitInvert + 1) on the digit :
(if digitIndex > 1, we must still add 1 due to the carry).
but x bitInvert is -1-x, bitInvert+1 is just x negated..."
^(self digitAt: digitIndex) negated bitAt: bitIndex].
(self digitAt: i) = 0]
whileTrue: [
"two complement (bitInvert + 1) raises a carry:
0 bitInvert -> 2r11111111. 2r11111111 + 1 -> 0 with carry...
Thus we must inquire one digit forward"
i := i + 1].
"We escaped the while loop, because there is no more carry.
Do a simple bitInvert without a carry"
^1 - ((self digitAt: digitIndex) bitAt: bitIndex)! !