Module: TrickBag::Numeric::BitMapping

Defined in:
lib/trick_bag/numeric/bit_mapping.rb

Overview

Provides methods for converting between the various representations of a bitmap: number, binary encoded string, array, and sparse array.

Where an array is used to represent bits, the first element (#0) will be the high bit and the last element will be the low (1’s column) bit.

Class Method Summary collapse

Class Method Details

.assert_non_negative(number) ⇒ Object

If number is negative, raises an ArgumentError; else does nothing.



118
119
120
121
122
123
124
# File 'lib/trick_bag/numeric/bit_mapping.rb', line 118

def assert_non_negative(number)
  unless number.is_a?(Integer) && number >= 0
    raise ArgumentError.new(
        "Parameter must be a nonnegative Integer (Fixnum, Bignum) " +
        "but is #{number.inspect} (a #{number.class})")
  end
end

.binary_string_to_bit_array(string, minimum_binary_places = 0) ⇒ Object

Converts a binary string to an array of bit values, e.g. “x0C” => [1, 1, 0, 0]



111
112
113
114
# File 'lib/trick_bag/numeric/bit_mapping.rb', line 111

def binary_string_to_bit_array(string, minimum_binary_places = 0)
  number = binary_string_to_number(string)
  number_to_bit_array(number, minimum_binary_places)
end

.binary_string_to_number(string) ⇒ Object

Converts from a binary string to a number, e.g. “x01x00” => 256



15
16
17
18
19
20
# File 'lib/trick_bag/numeric/bit_mapping.rb', line 15

def binary_string_to_number(string)
  string = string.clone.force_encoding(Encoding::ASCII_8BIT)
  string.bytes.inject(0) do |number, byte|
    number * 256 + byte.ord
  end
end

.bit_array_to_number(bit_array) ⇒ Object

Converts an array of bit values, e.g. [1, 0, 0, 1], to a number, e.g. 9



74
75
76
77
78
79
80
81
82
# File 'lib/trick_bag/numeric/bit_mapping.rb', line 74

def bit_array_to_number(bit_array)
  return nil if bit_array.empty?
  multiplier = 1
  bit_array.reverse.inject(0) do |result, n|
    result += n * multiplier
    multiplier *= 2
    result
  end
end

.number_to_binary_string(number, min_length = 0) ⇒ Object

Converts a number to a binary encoded string, e.g. 256 => “x01x00”



24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/trick_bag/numeric/bit_mapping.rb', line 24

def number_to_binary_string(number, min_length = 0)
  assert_non_negative(number)
  binary_string = ''.force_encoding(Encoding::ASCII_8BIT)

  while number > 0
    byte_value = number & 0xFF
    binary_string << byte_value
    number >>= 8
  end

  binary_string.reverse.rjust(min_length, "\x00")
end

.number_to_bit_array(number, minimum_binary_places = 0) ⇒ Object

Converts a number to an array of bit values, e.g. 9 => [1, 0, 0, 1]



59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/trick_bag/numeric/bit_mapping.rb', line 59

def number_to_bit_array(number, minimum_binary_places = 0)
  assert_non_negative(number)
  array = []
  while number > 0
    array << (number & 1)
    number >>= 1
  end
  array.reverse!
  zero_pad_count = minimum_binary_places - array.size
  zero_pad_count.times { array.unshift(0) }
  array
end

.number_to_place_value_array(number) ⇒ Object

Converts a number to an array of place values, e.g. 9 => [8, 0, 0, 1]



39
40
41
42
43
44
45
46
47
48
49
# File 'lib/trick_bag/numeric/bit_mapping.rb', line 39

def number_to_place_value_array(number)
  assert_non_negative(number)
  array = []
  bit_value = 1
  while number > 0
    array << ((number & 1 == 1) ? bit_value : 0)
    number >>= 1
    bit_value <<= 1
  end
  array.reverse
end

.number_to_set_bit_positions_array(number) ⇒ Object

Converts a number to a sparse array containing bit positions that are set/true/1. Note that these are bit positions, e.g. 76543210, and not bit column values such as 128/64/32/16/8/4/2/1.



88
89
90
91
92
93
94
95
96
97
98
# File 'lib/trick_bag/numeric/bit_mapping.rb', line 88

def number_to_set_bit_positions_array(number)
  assert_non_negative(number)
  array = []
  position = 0
  while number > 0
    array << position if number & 1 == 1
    position += 1
    number >>= 1
  end
  array
end

.place_value_array_to_number(place_value_array) ⇒ Object

Converts from a value array to a number, e.g. [8, 0, 0, 1] => 9



53
54
55
# File 'lib/trick_bag/numeric/bit_mapping.rb', line 53

def place_value_array_to_number(place_value_array)
  place_value_array.inject(&:+)
end

.reverse_binary_string_bits(binary_string) ⇒ Object

Reverses a binary string. Note that it is not enough to reverse the string itself because although the bytes would be reversed, the bits within each byte would not.



129
130
131
132
133
134
# File 'lib/trick_bag/numeric/bit_mapping.rb', line 129

def reverse_binary_string_bits(binary_string)
  binary_place_count = binary_string.size * 8
  reversed_bit_array = binary_string_to_bit_array(binary_string, binary_place_count).reverse
  number = bit_array_to_number(reversed_bit_array)
  number_to_binary_string(number)
end

.set_bit_position_array_to_number(position_array) ⇒ Object

Converts an array of bit position numbers to a numeric value, e.g. [0, 2] => 5



102
103
104
105
106
107
# File 'lib/trick_bag/numeric/bit_mapping.rb', line 102

def set_bit_position_array_to_number(position_array)
  return nil if position_array.empty?
  position_array.inject(0) do |result, n|
    result += 2 ** n
  end
end