Class: Radix::Base

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

Overview

Radix::Base provides the means of converting to and from any base.

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

And it can handle any notation upto base 62.

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

And the notations need not be in ASCII order –odd notations can be used.

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

NOTE: Radix::Base is the original Radix API. But with the advent of v2.0 and the new Integer and Float classes, it is outmoded. For now it is here for backward compatibility. In a future version it may be deprecated, or reworked to serve as the backbone of the other classes.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

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

New Radix using chars representation.



46
47
48
49
50
51
52
53
# File 'lib/radix/base.rb', line 46

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

#baseObject (readonly)

Returns the value of attribute base.



41
42
43
# File 'lib/radix/base.rb', line 41

def base
  @base
end

#charsObject (readonly)

Returns the value of attribute chars.



39
40
41
# File 'lib/radix/base.rb', line 39

def chars
  @chars
end

#valuesObject (readonly)

Returns the value of attribute values.



43
44
45
# File 'lib/radix/base.rb', line 43

def values
  @values
end

Instance Method Details

#convert(number, radix_base) ⇒ Object

Convert an encoded number of given base to the Base’s radix.

Raises:

  • (TypeError)


56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/radix/base.rb', line 56

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) ⇒ Object

Convert any base to any other base, using array of digits.



78
79
80
81
82
83
84
85
86
87
88
# File 'lib/radix/base.rb', line 78

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) ⇒ Object

Decode a string that was previously encoded in the radix.



98
99
100
101
# File 'lib/radix/base.rb', line 98

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

#encode(byte_string) ⇒ Object

Encode a string in the radix.



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

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