3. Bits¶
3.1. Wizardry¶
The following manipulation have been adapted from [Arn10].
3.1.1. Average without overflow¶
"Integer, protocol *Containers-Essentials"
bitAverage: anInteger
"See 'Matters Computational' (ftxbook) section 1.1.7, Average without overflow."
"Use: x+y == (x^y) + ((x&y)<<1), that is: sum == sum_without_carries + carries."
^ (self bitXor: anInteger) >> 1 + (self bitAnd: anInteger)
"IntegerTest, protocol *Containers-Essentials-Tests"
testBitAverage
| s n m slowBenchResult quickBenchResult seconds |
s := 2.
self timeLimit: (s * 2 + 1) seconds.
n := 38299527986758693756807879086754976930654.
m := 57483879867596837956739087695867359769587.
seconds := s seconds.
quickBenchResult := [ n bitAverage: m ] benchFor: seconds.
slowBenchResult := [ (n + m / 2) asInteger ] benchFor: seconds.
self assert: (n bitAverage: m) equals: (n + m / 2) asInteger.
"For the sake of clarity, a run yields: 730482 < 3673262"
self assert: slowBenchResult iterations < quickBenchResult iterations
3.1.2. Toggling between values¶
"Integer, protocol *Containers-Essentials"
bitToggle: anInteger do: aBlock
"See 'Matters Computational' (ftxbook) section 1.1.8, Toggling between values."
| t x |
t := self bitXor: anInteger.
x := anInteger.
^ aBlock value: [ x := x bitXor: t ]
"IntegerTest, protocol *Containers-Essentials-Tests"
testBitToggleDo
| n m |
n := 38299527986758693756807879086754976930654.
m := 57483879867596837956739087695867359769587.
n bitToggle: m do: [ :toggle |
self
assert: toggle value equals: n;
assert: toggle value equals: m;
assert: toggle value equals: n;
assert: toggle value equals: m;
assert: toggle value equals: n;
assert: toggle value equals: m;
assert: toggle value equals: n;
assert: toggle value equals: m ]
"IntegerTest, protocol *Containers-Essentials-Tests"
testBitToggleDo1
| n m |
n := 1.
m := 0.
n bitToggle: m do: [ :toggle |
self
assert: toggle value equals: n;
assert: toggle value equals: m;
assert: toggle value equals: n;
assert: toggle value equals: m;
assert: toggle value equals: n;
assert: toggle value equals: m;
assert: toggle value equals: n;
assert: toggle value equals: m ]
3.1.3. Next or previous even or odd value¶
"Integer, protocol *Containers-Essentials"
previousEven
"See 'Matters Computational' (ftxbook) section 1.1.9,
Next or previous even or odd value, optimized versions."
^ self - 1 bitAnd: 1 bitInvert
"IntegerTest, protocol *Containers-Essentials-Tests"
testPreviousEven
self
assert: -2 previousEven equals: -4;
assert: -1 previousEven equals: -2;
assert: 0 previousEven equals: -2;
assert: 1 previousEven equals: 0;
assert: 2 previousEven equals: 0
"Integer, protocol *Containers-Essentials"
nextEven
"See 'Matters Computational' (ftxbook) section 1.1.9,
Next or previous even or odd value, optimized versions."
^ (self bitOr: 1) + 1
"IntegerTest, protocol *Containers-Essentials-Tests"
testNextEven
self
assert: -2 nextEven equals: 0;
assert: -1 nextEven equals: 0;
assert: 0 nextEven equals: 2;
assert: 1 nextEven equals: 2;
assert: 2 nextEven equals: 4
"Integer, protocol *Containers-Essentials"
previousOdd
"See 'Matters Computational' (ftxbook) section 1.1.9,
Next or previous even or odd value, optimized versions."
^ (self bitAnd: 1 bitInvert) - 1
"IntegerTest, protocol *Containers-Essentials-Tests"
testPreviousOdd
self
assert: -2 previousOdd equals: -3;
assert: -1 previousOdd equals: -3;
assert: 0 previousOdd equals: -1;
assert: 1 previousOdd equals: -1;
assert: 2 previousOdd equals: 1
"Integer, protocol *Containers-Essentials"
nextOdd
"See 'Matters Computational' (ftxbook) section 1.1.9,
Next or previous even or odd value, optimized versions."
^ self + 1 bitOr: 1
"IntegerTest, protocol *Containers-Essentials-Tests"
testNextOdd
self
assert: -2 nextOdd equals: -1;
assert: -1 nextOdd equals: 1;
assert: 0 nextOdd equals: 1;
assert: 1 nextOdd equals: 3;
assert: 2 nextOdd equals: 3
The following messages return the unmodified argument if it has the required property, else the nearest such value:
"Integer, protocol *Containers-Essentials"
previousEvenOrSelf
"See 'Matters Computational' (ftxbook) section 1.1.9,
Next or previous even or odd value, optimized versions."
^ self bitAnd: 1 bitInvert
"IntegerTest, protocol *Containers-Essentials-Tests"
testPreviousEvenOrSelf
self
assert: -2 previousEvenOrSelf equals: -2;
assert: -1 previousEvenOrSelf equals: -2;
assert: 0 previousEvenOrSelf equals: 0;
assert: 1 previousEvenOrSelf equals: 0;
assert: 2 previousEvenOrSelf equals: 2
"Integer, protocol *Containers-Essentials"
nextEvenOrSelf
"See 'Matters Computational' (ftxbook) section 1.1.9,
Next or previous even or odd value, optimized versions."
^ self + 1 bitAnd: 1 bitInvert
"IntegerTest, protocol *Containers-Essentials-Tests"
testNextEvenOrSelf
self
assert: -2 nextEvenOrSelf equals: -2;
assert: -1 nextEvenOrSelf equals: 0;
assert: 0 nextEvenOrSelf equals: 0;
assert: 1 nextEvenOrSelf equals: 2;
assert: 2 nextEvenOrSelf equals: 2
"Integer, protocol *Containers-Essentials"
previousOddOrSelf
"See 'Matters Computational' (ftxbook) section 1.1.9,
Next or previous even or odd value, optimized versions."
^ self - 1 bitOr: 1
"IntegerTest, protocol *Containers-Essentials-Tests"
testPreviousOddOrSelf
self
assert: -2 previousOddOrSelf equals: -3;
assert: -1 previousOddOrSelf equals: -1;
assert: 0 previousOddOrSelf equals: -1;
assert: 1 previousOddOrSelf equals: 1;
assert: 2 previousOddOrSelf equals: 1
"Integer, protocol *Containers-Essentials"
nextOddOrSelf
"See 'Matters Computational' (ftxbook) section 1.1.9,
Next or previous even or odd value, optimized versions."
^ self bitOr: 1
"IntegerTest, protocol *Containers-Essentials-Tests"
testNextOddOrSelf
self
assert: -2 nextOddOrSelf equals: -1;
assert: -1 nextOddOrSelf equals: -1;
assert: 0 nextOddOrSelf equals: 1;
assert: 1 nextOddOrSelf equals: 1;
assert: 2 nextOddOrSelf equals: 3