public
Description: Rubinius, the Ruby VM
Homepage: http://rubini.us
Clone URL: git://github.com/evanphx/rubinius.git
Search Repo:
rubinius / kernel / core / integer.rb
100644 133 lines (115 sloc) 2.498 kb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
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
# depends on: class.rb numeric.rb ctype.rb precision.rb
 
class Integer < Numeric
  include CType
  include Precision
 
  def self.induced_from(obj)
    case obj
    when Fixnum, Bignum
      obj
    when Float
      obj.to_i
    else
      raise TypeError, "failed to convert #{obj.class} into Integer"
    end
  end
 
  def &(other)
    self & Type.coerce_to(other, Integer, :to_int)
  end
   
  def |(other)
    self | Type.coerce_to(other, Integer, :to_int)
  end
  
  def ^(other)
    self ^ Type.coerce_to(other, Integer, :to_int)
  end
 
  def times
    i = 0
    while i < self
      yield i
      i += 1
    end
    self
  end
  
  def upto(val)
    i = self
    while i <= val
      yield i
      i += 1
    end
    return self
  end
  
  def downto(val)
    i = self
    while i >= val
      yield i
      i -= 1
    end
    return self
  end
 
  def to_i
    self
  end
  alias_method :to_int, :to_i
  alias_method :round, :to_i
  alias_method :truncate, :to_i
 
  def chr
    raise RangeError.new("#{self} is out of the valid character range") if self > 255 || self < 0
    String.template 1, self
  end
  
  def [](index)
    return 0 if index.is_a?(Bignum)
    index = Type.coerce_to(index, Integer, :to_int)
    index < 0 ? 0 : (self >> index) & 1
  end
 
  def **(exp)
    if !exp.is_a?(Integer)
      b, a = math_coerce(exp)
      return a ** b
    end
    
    return 1 if exp == 0
    return self if exp == 1 || self == 0 || self == 1
    return exp % 2 == 0 ? 1 : -1 if self == -1
    
    if exp < 0
      Float(self) ** Float(exp)
    else
      out = 1
      base = self
      while exp > 0
        if (exp & 1) != 0
          out *= base
          exp -= 1
        else
          base *= base
          exp >>= 1
        end
      end
      out
    end
  end
 
  def next
    self + 1
  end
  alias_method :succ, :next
 
  def integer?
    true
  end
 
  ##
  # Returns the minimum number of bits required for integer in (signed int)
  # binary format
  #--
  # NOTE: rshift would probably be slightly more efficient but since i'm
  # probably going to use this to simplify the complex behavior of
  # ruby's << and >> it would defeat the purpose by creating a circular
  # dependency.
  #
  # TODO: convert algorithm to primitive so no circular dependency?
  #++
 
  def bits(int = self)
    if int.zero?
      1 # sign bit storage
    elsif int > 0
      bits(int / 2) + 1 # could use >> in primitive
    else
      bits(~int / 2) + 1 # could use >> in primitive
    end
  end
end