Class: Radix::Base

Inherits:
Object
  • Object
show all
Defined in:
lib/radix/base.rb

Overview

Radix::Base is a functional model of a base system that can be used for number conversions.

Radix::Base is the original Radix API. But with the advent of v2.0 and the new Integer and Float classes, it is essentially deprecated.

Examples:

Convert any base

b10 = Radix::Base.new(10)
b10.convert_base([100, 10], 256)
#=> [2,5,6,1,0]

Convert to string notation upto base 62

b10.convert("10", 62)  #=> "62"

Odd notations

b10 = Radix::Base.new(%w{Q W E R T Y U I O U})
b10.convert("FF", 16) #=> "EYY"

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(chars = BASE::B62) ⇒ void

New Radix using chars representation.

Parameters:

  • chars (Array<String>, Numeric) (defaults to: BASE::B62)

    Array of string representation of number values of the base or a Numeric of the Base level.



88
89
90
91
92
93
94
95
# File 'lib/radix/base.rb', line 88

def initialize(chars=BASE::B62)
  if ::Numeric === chars
    chars = BASE::B62[0...chars]
  end
  @chars  = chars.map{ |c| c.to_s }
  @base   = @chars.size
  @values = Hash[*(0...@base).map { |i| [ @chars[i], i ] }.flatten]
end

Instance Attribute Details

#baseFixnum (readonly)

The base of this instance.

Returns:

  • (Fixnum)

    The base level in use.



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
# File 'lib/radix/base.rb', line 59

class Base

  ##
  # The characters for this base level.
  #
  # @return [Array<String>] The ASCII character set in use.
  attr :chars

  ##
  # The base of this instance.
  #
  # @return [Fixnum] The base level in use.
  attr :base

  ##
  # Hash of characters and values.
  #
  # @return [Hash{String=>Fixnum}]
  #   A hash of characters and their respective value.
  attr :values

  ##
  # New Radix using +chars+ representation.
  #
  # @param [Array<String>, Numeric] chars
  #   Array of string representation of number values of the base
  #   or a Numeric of the Base level.
  #
  # @return [void]
  def initialize(chars=BASE::B62)
    if ::Numeric === chars
      chars = BASE::B62[0...chars]
    end
    @chars  = chars.map{ |c| c.to_s }
    @base   = @chars.size
    @values = Hash[*(0...@base).map { |i| [ @chars[i], i ] }.flatten]
  end

  ##
  # Convert a value of given radix_base to that of the base instance.
  #
  # @param [String, Numeric, Array<String>] number
  #   The value in "radix_base" context.
  #
  # @param [Radix::Base, Numeric] radix_base
  #   Numeric for the radix or instance of Radix::Base.
  #
  # @example Convert Testing (Binary, Decimal, Hex)
  #   > b = Radix::Base.new(2)
  #   > d = Radix::Base.new(10)
  #   > h = Radix::Base.new(16)
  #   > d.convert("A", h)
  #   "10"
  #   > h.convert("A", d)
  #   TypeError
  #   > h.convert(10, d)
  #   "A"
  #   > h.convert(10, 10)
  #   "A"
  #   > b.convert(10, d)
  #   "1010"
  #   > b.convert(10, h)
  #   "10000"
  #
  # @return [String] representation of "number" in self.base level.
  def convert(number, radix_base)
    radix_base = Radix::Base.new(radix_base) unless Radix::Base === radix_base
    case number
    when ::String, ::Numeric
      digits = number.to_s.split(//)
    else
      digits = number
    end

    # decode the digits
    digits = digits.map{ |digit| radix_base.values[digit] }

    # THINK: Is best way to check for base out of bounds?
    raise TypeError if digits.any?{ |digit| digit.nil? }

    digits = Radix.convert_base(digits, radix_base.base, base)
    digits = digits.map{ |digit| chars[digit] }
    digits.join
  end

  ##
  # Convert any base to any other base, using array of Fixnum's. Indexes of
  # the array correspond to values for each column of the number in from_base
  #
  # @param [Array<Fixnum>] digits
  #   Array of values for each digit of source base.
  #
  # @param [Fixnum] from_base
  #   Source Base
  #
  # @param [Fixnum] to_base
  #   Destination Base
  #
  # @return [String] The value of digits in from_base converted as to_base.
  def convert_base(digits, from_base, to_base)
    bignum = 0
    digits.each { |digit| bignum = bignum * from_base + digit }
    converted = []
    until bignum.zero?
      bignum, digit = bignum.divmod(to_base)
      converted.push(digit)
    end
    converted << 0 if converted.empty?  # THINK: correct?
    converted.reverse
  end

  ##
  # Encode a string in the radix.
  #
  # @param [String] byte_string
  #   String value in this base. 
  #
  # @return [String] Encoded string from this Base.
  def encode(byte_string)
    digits = byte_string.unpack("C*")
    digits = Radix.convert_base(digits, 256, base)
    digits.map{ |d| @chars[d] }.join
  end

  ##
  # Decode a string that was previously encoded in the radix.
  #
  # @param [String] encoded
  #   Encoded string from this Base.
  #
  # @return [String] Decoded string of value from this base. 
  def decode(encoded)
    digits = encoded.split(//).map{ |c| @values[c] }
    Radix.convert_base(digits, base, 256).pack("C*")
  end

end

#charsArray<String> (readonly)

The characters for this base level.

Returns:



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
# File 'lib/radix/base.rb', line 59

class Base

  ##
  # The characters for this base level.
  #
  # @return [Array<String>] The ASCII character set in use.
  attr :chars

  ##
  # The base of this instance.
  #
  # @return [Fixnum] The base level in use.
  attr :base

  ##
  # Hash of characters and values.
  #
  # @return [Hash{String=>Fixnum}]
  #   A hash of characters and their respective value.
  attr :values

  ##
  # New Radix using +chars+ representation.
  #
  # @param [Array<String>, Numeric] chars
  #   Array of string representation of number values of the base
  #   or a Numeric of the Base level.
  #
  # @return [void]
  def initialize(chars=BASE::B62)
    if ::Numeric === chars
      chars = BASE::B62[0...chars]
    end
    @chars  = chars.map{ |c| c.to_s }
    @base   = @chars.size
    @values = Hash[*(0...@base).map { |i| [ @chars[i], i ] }.flatten]
  end

  ##
  # Convert a value of given radix_base to that of the base instance.
  #
  # @param [String, Numeric, Array<String>] number
  #   The value in "radix_base" context.
  #
  # @param [Radix::Base, Numeric] radix_base
  #   Numeric for the radix or instance of Radix::Base.
  #
  # @example Convert Testing (Binary, Decimal, Hex)
  #   > b = Radix::Base.new(2)
  #   > d = Radix::Base.new(10)
  #   > h = Radix::Base.new(16)
  #   > d.convert("A", h)
  #   "10"
  #   > h.convert("A", d)
  #   TypeError
  #   > h.convert(10, d)
  #   "A"
  #   > h.convert(10, 10)
  #   "A"
  #   > b.convert(10, d)
  #   "1010"
  #   > b.convert(10, h)
  #   "10000"
  #
  # @return [String] representation of "number" in self.base level.
  def convert(number, radix_base)
    radix_base = Radix::Base.new(radix_base) unless Radix::Base === radix_base
    case number
    when ::String, ::Numeric
      digits = number.to_s.split(//)
    else
      digits = number
    end

    # decode the digits
    digits = digits.map{ |digit| radix_base.values[digit] }

    # THINK: Is best way to check for base out of bounds?
    raise TypeError if digits.any?{ |digit| digit.nil? }

    digits = Radix.convert_base(digits, radix_base.base, base)
    digits = digits.map{ |digit| chars[digit] }
    digits.join
  end

  ##
  # Convert any base to any other base, using array of Fixnum's. Indexes of
  # the array correspond to values for each column of the number in from_base
  #
  # @param [Array<Fixnum>] digits
  #   Array of values for each digit of source base.
  #
  # @param [Fixnum] from_base
  #   Source Base
  #
  # @param [Fixnum] to_base
  #   Destination Base
  #
  # @return [String] The value of digits in from_base converted as to_base.
  def convert_base(digits, from_base, to_base)
    bignum = 0
    digits.each { |digit| bignum = bignum * from_base + digit }
    converted = []
    until bignum.zero?
      bignum, digit = bignum.divmod(to_base)
      converted.push(digit)
    end
    converted << 0 if converted.empty?  # THINK: correct?
    converted.reverse
  end

  ##
  # Encode a string in the radix.
  #
  # @param [String] byte_string
  #   String value in this base. 
  #
  # @return [String] Encoded string from this Base.
  def encode(byte_string)
    digits = byte_string.unpack("C*")
    digits = Radix.convert_base(digits, 256, base)
    digits.map{ |d| @chars[d] }.join
  end

  ##
  # Decode a string that was previously encoded in the radix.
  #
  # @param [String] encoded
  #   Encoded string from this Base.
  #
  # @return [String] Decoded string of value from this base. 
  def decode(encoded)
    digits = encoded.split(//).map{ |c| @values[c] }
    Radix.convert_base(digits, base, 256).pack("C*")
  end

end

#valuesHash{String=>Fixnum} (readonly)

Hash of characters and values.

Returns:

  • (Hash{String=>Fixnum})

    A hash of characters and their respective value.



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
# File 'lib/radix/base.rb', line 59

class Base

  ##
  # The characters for this base level.
  #
  # @return [Array<String>] The ASCII character set in use.
  attr :chars

  ##
  # The base of this instance.
  #
  # @return [Fixnum] The base level in use.
  attr :base

  ##
  # Hash of characters and values.
  #
  # @return [Hash{String=>Fixnum}]
  #   A hash of characters and their respective value.
  attr :values

  ##
  # New Radix using +chars+ representation.
  #
  # @param [Array<String>, Numeric] chars
  #   Array of string representation of number values of the base
  #   or a Numeric of the Base level.
  #
  # @return [void]
  def initialize(chars=BASE::B62)
    if ::Numeric === chars
      chars = BASE::B62[0...chars]
    end
    @chars  = chars.map{ |c| c.to_s }
    @base   = @chars.size
    @values = Hash[*(0...@base).map { |i| [ @chars[i], i ] }.flatten]
  end

  ##
  # Convert a value of given radix_base to that of the base instance.
  #
  # @param [String, Numeric, Array<String>] number
  #   The value in "radix_base" context.
  #
  # @param [Radix::Base, Numeric] radix_base
  #   Numeric for the radix or instance of Radix::Base.
  #
  # @example Convert Testing (Binary, Decimal, Hex)
  #   > b = Radix::Base.new(2)
  #   > d = Radix::Base.new(10)
  #   > h = Radix::Base.new(16)
  #   > d.convert("A", h)
  #   "10"
  #   > h.convert("A", d)
  #   TypeError
  #   > h.convert(10, d)
  #   "A"
  #   > h.convert(10, 10)
  #   "A"
  #   > b.convert(10, d)
  #   "1010"
  #   > b.convert(10, h)
  #   "10000"
  #
  # @return [String] representation of "number" in self.base level.
  def convert(number, radix_base)
    radix_base = Radix::Base.new(radix_base) unless Radix::Base === radix_base
    case number
    when ::String, ::Numeric
      digits = number.to_s.split(//)
    else
      digits = number
    end

    # decode the digits
    digits = digits.map{ |digit| radix_base.values[digit] }

    # THINK: Is best way to check for base out of bounds?
    raise TypeError if digits.any?{ |digit| digit.nil? }

    digits = Radix.convert_base(digits, radix_base.base, base)
    digits = digits.map{ |digit| chars[digit] }
    digits.join
  end

  ##
  # Convert any base to any other base, using array of Fixnum's. Indexes of
  # the array correspond to values for each column of the number in from_base
  #
  # @param [Array<Fixnum>] digits
  #   Array of values for each digit of source base.
  #
  # @param [Fixnum] from_base
  #   Source Base
  #
  # @param [Fixnum] to_base
  #   Destination Base
  #
  # @return [String] The value of digits in from_base converted as to_base.
  def convert_base(digits, from_base, to_base)
    bignum = 0
    digits.each { |digit| bignum = bignum * from_base + digit }
    converted = []
    until bignum.zero?
      bignum, digit = bignum.divmod(to_base)
      converted.push(digit)
    end
    converted << 0 if converted.empty?  # THINK: correct?
    converted.reverse
  end

  ##
  # Encode a string in the radix.
  #
  # @param [String] byte_string
  #   String value in this base. 
  #
  # @return [String] Encoded string from this Base.
  def encode(byte_string)
    digits = byte_string.unpack("C*")
    digits = Radix.convert_base(digits, 256, base)
    digits.map{ |d| @chars[d] }.join
  end

  ##
  # Decode a string that was previously encoded in the radix.
  #
  # @param [String] encoded
  #   Encoded string from this Base.
  #
  # @return [String] Decoded string of value from this base. 
  def decode(encoded)
    digits = encoded.split(//).map{ |c| @values[c] }
    Radix.convert_base(digits, base, 256).pack("C*")
  end

end

Instance Method Details

#convert(number, radix_base) ⇒ String

Convert a value of given radix_base to that of the base instance.

Examples:

Convert Testing (Binary, Decimal, Hex)

> b = Radix::Base.new(2)
> d = Radix::Base.new(10)
> h = Radix::Base.new(16)
> d.convert("A", h)
"10"
> h.convert("A", d)
TypeError
> h.convert(10, d)
"A"
> h.convert(10, 10)
"A"
> b.convert(10, d)
"1010"
> b.convert(10, h)
"10000"

Parameters:

Returns:

  • (String)

    representation of “number” in self.base level.

Raises:

  • (TypeError)


124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# File 'lib/radix/base.rb', line 124

def convert(number, radix_base)
  radix_base = Radix::Base.new(radix_base) unless Radix::Base === radix_base
  case number
  when ::String, ::Numeric
    digits = number.to_s.split(//)
  else
    digits = number
  end

  # decode the digits
  digits = digits.map{ |digit| radix_base.values[digit] }

  # THINK: Is best way to check for base out of bounds?
  raise TypeError if digits.any?{ |digit| digit.nil? }

  digits = Radix.convert_base(digits, radix_base.base, base)
  digits = digits.map{ |digit| chars[digit] }
  digits.join
end

#convert_base(digits, from_base, to_base) ⇒ String

Convert any base to any other base, using array of Fixnum’s. Indexes of the array correspond to values for each column of the number in from_base

Parameters:

  • digits (Array<Fixnum>)

    Array of values for each digit of source base.

  • from_base (Fixnum)

    Source Base

  • to_base (Fixnum)

    Destination Base

Returns:

  • (String)

    The value of digits in from_base converted as to_base.



158
159
160
161
162
163
164
165
166
167
168
# File 'lib/radix/base.rb', line 158

def convert_base(digits, from_base, to_base)
  bignum = 0
  digits.each { |digit| bignum = bignum * from_base + digit }
  converted = []
  until bignum.zero?
    bignum, digit = bignum.divmod(to_base)
    converted.push(digit)
  end
  converted << 0 if converted.empty?  # THINK: correct?
  converted.reverse
end

#decode(encoded) ⇒ String

Decode a string that was previously encoded in the radix.

Parameters:

  • encoded (String)

    Encoded string from this Base.

Returns:

  • (String)

    Decoded string of value from this base.



190
191
192
193
# File 'lib/radix/base.rb', line 190

def decode(encoded)
  digits = encoded.split(//).map{ |c| @values[c] }
  Radix.convert_base(digits, base, 256).pack("C*")
end

#encode(byte_string) ⇒ String

Encode a string in the radix.

Parameters:

  • byte_string (String)

    String value in this base.

Returns:

  • (String)

    Encoded string from this Base.



177
178
179
180
181
# File 'lib/radix/base.rb', line 177

def encode(byte_string)
  digits = byte_string.unpack("C*")
  digits = Radix.convert_base(digits, 256, base)
  digits.map{ |d| @chars[d] }.join
end