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