public
Description: Rubinius, the Ruby VM
Homepage: http://rubini.us
Clone URL: git://github.com/evanphx/rubinius.git
Rework Float operations to use primitives.
brixen (author)
Mon Feb 11 16:41:53 -0800 2008
commit  359166e79fe5bb5def62f639e37d9c613b0a731d
tree    20e9475bc90e9d59860b54812b8354c2fd22096b
parent  64b0fb4131276feda0d0ab13301824b20f8d7f8e
...
128
129
130
131
132
133
134
135
136
137
...
128
129
130
 
 
 
 
 
 
 
0
@@ -128,10 +128,3 @@ class Fixnum < Integer
0
     raise PrimitiveFailure, "primitive failed"
0
   end
0
 end
0
-
0
-class Numeric
0
- def coerce(other)
0
- Ruby.primitive(:numeric_coerce) # try to keep bignum/fixnum precision
0
- [Float(other), Float(self)]
0
- end
0
-end
...
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
...
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
 
 
155
156
...
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
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
...
177
178
179
 
 
 
 
 
 
180
 
 
 
 
 
 
 
181
182
183
 
0
@@ -19,102 +19,141 @@ class Float < Numeric
0
   EPSILON = Platform::Float.EPSILON
0
   STRLEN = 32
0
   
0
- alias_method :quo, :/
0
-
0
   def self.induced_from(obj)
0
- if [Float, Bignum, Fixnum].include?(obj.class)
0
+ case obj
0
+ when Float, Bignum, Fixnum
0
       obj.to_f
0
     else
0
       raise TypeError, "failed to convert #{obj.class} into Float"
0
     end
0
   end
0
   
0
+ def coerce(other)
0
+ return [other, self] if other.__kind_of__ Float
0
+ [Float(other), self]
0
+ end
0
+
0
+ # unary operators
0
+
0
+ def -@
0
+ Ruby.primitive :float_uminus
0
+ end
0
+
0
+ # binary math operators
0
+
0
   def +(other)
0
- return super(other) unless other.is_a?(Float)
0
- Platform::Float.add self, other
0
+ Ruby.primitive :float_add
0
+ b, a = math_coerce other
0
+ a + b
0
   end
0
   
0
   def -(other)
0
- return super(other) unless other.is_a?(Float)
0
- Platform::Float.sub self, other
0
+ Ruby.primitive :float_sub
0
+ b, a = math_coerce other
0
+ a - b
0
   end
0
   
0
   def *(other)
0
- return super(other) unless other.is_a?(Float)
0
- Platform::Float.mul self, other
0
+ Ruby.primitive :float_mul
0
+ b, a = math_coerce other
0
+ a * b
0
   end
0
   
0
   # see README-DEVELOPERS regarding safe math compiler plugin
0
   def divide(other)
0
- return super(other) unless other.is_a?(Float)
0
- Platform::Float.div self, other
0
+ Ruby.primitive :float_div
0
+ b, a = math_coerce other
0
+ a.divide b
0
   end
0
   alias_method :/, :divide
0
-
0
- def -@
0
- Platform::Float.uminus self
0
+ alias_method :quo, :/
0
+
0
+ def divmod(other)
0
+ Ruby.primitive :float_divmod
0
+ b, a = math_coerce other
0
+ a.divmod b
0
   end
0
 
0
- def <=>(other)
0
- return super(other) unless other.is_a?(Float)
0
- Platform::Float.compare self, other
0
+ def **(other)
0
+ Ruby.primitive :float_pow
0
+ b, a = math_coerce other
0
+ a ** b
0
   end
0
 
0
- def ==(other)
0
- return super(other) unless other.is_a?(Float)
0
- Platform::Float.eql? self, other
0
+ def %(other)
0
+ return 0 / 0.to_f if other == 0
0
+ self.divmod(Float(other))[1]
0
   end
0
+ alias_method :modulo, :%
0
 
0
- def eql?(other)
0
- return false unless other.is_a?(Float)
0
- Platform::Float.eql? self, other
0
+ # comparison operators
0
+
0
+ def <(other)
0
+ Ruby.primitive :float_lt
0
+ b, a = math_coerce other, :compare_error
0
+ a < b
0
   end
0
   
0
- def divmod(other)
0
- raise FloatDomainError, "divide by 0" if other == 0
0
- return super(other) unless other.is_a?(Float)
0
- div = (self / other).floor;
0
- mod = Platform::Float.fmod self, other
0
-
0
- if (other * mod < 0)
0
- mod += other;
0
+ def <=(other)
0
+ Ruby.primitive :float_le
0
+ b, a = math_coerce other, :compare_error
0
+ a <= b
0
+ end
0
+
0
+ def >(other)
0
+ Ruby.primitive :float_gt
0
+ b, a = math_coerce other, :compare_error
0
+ a > b
0
+ end
0
+
0
+ def >=(other)
0
+ Ruby.primitive :float_ge
0
+ b, a = math_coerce other, :compare_error
0
+ a >= b
0
+ end
0
+
0
+ def <=>(other)
0
+ Ruby.primitive :float_compare
0
+ b, a = math_coerce other, :compare_error
0
+ a <=> b
0
+ end
0
+
0
+ def ==(other)
0
+ Ruby.primitive :float_equal
0
+ begin
0
+ b, a = math_coerce(other)
0
+ return a == b
0
+ rescue TypeError
0
+ return other == self
0
     end
0
- return [div.to_i, mod]
0
   end
0
 
0
+ # predicates
0
+
0
+ def eql?(other)
0
+ Ruby.primitive :float_eql
0
+ end
0
+
0
   def nan?
0
- Platform::Float.nan? self
0
+ Ruby.primitive :float_isnan
0
   end
0
 
0
   def infinite?
0
- Platform::Float.infinite? self
0
+ Ruby.primitive :float_isinf
0
   end
0
   
0
   def finite?
0
     not (nan? or infinite?)
0
   end
0
-
0
- def **(other)
0
- return super(other) unless other.is_a?(Float)
0
- Platform::Float.pow self, other
0
- end
0
+
0
+ # conversions
0
   
0
   def to_f
0
     self
0
   end
0
   
0
   def to_i
0
- if infinite?
0
- raise FloatDomainError, self < 0 ? "-Infinity" : "Infinity"
0
- elsif nan?
0
- return self
0
- else
0
- if self < Platform::Fixnum.MAX.to_f && self > Platform::Fixnum.MIN.to_f
0
- Platform::Float.to_i self
0
- else
0
- Bignum.from_float self
0
- end
0
- end
0
+ Ruby.primitive :float_to_i
0
   end
0
   alias_method :to_int, :to_i
0
   alias_method :truncate, :to_i
0
@@ -138,19 +177,7 @@ class Float < Numeric
0
   end
0
   private :to_s_formatted
0
   
0
- def %(other)
0
- return 0 / 0.to_f if other == 0
0
- self.divmod(Float(other))[1]
0
- end
0
- alias_method :modulo, :%
0
-
0
   def round
0
- if self < Platform::Fixnum.MAX.to_f && self > Platform::Fixnum.MIN.to_f
0
- Platform::Float.round self
0
- else
0
- Bignum.from_float self
0
- end
0
- end
0
-
0
+ Ruby.primitive :float_round
0
+ end
0
 end
0
-
...
9
10
11
 
 
 
 
 
 
 
 
 
 
 
12
13
14
...
58
59
60
61
 
62
63
64
...
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
...
69
70
71
 
72
73
74
75
0
@@ -9,6 +9,17 @@ class Integer < Numeric
0
     raise TypeError, "can't convert #{o.class} into Integer"
0
   end
0
 
0
+ # We deviate from MRI behavior here because we ensure that
0
+ # Fixnum op Bignum => Bignum (possibly normalized to Fixnum)
0
+ #
0
+ # Note these differences on MRI, where a is a Fixnum, b is a Bignum
0
+ # a.coerce b => [Float, Float]
0
+ # b.coerce a => [Bignum, Bignum]
0
+ def coerce(other)
0
+ Ruby.primitive(:numeric_coerce)
0
+ [Float(other), Float(self)]
0
+ end
0
+
0
   def times
0
     i = 0
0
     while i < self
0
@@ -58,7 +69,7 @@ class Integer < Numeric
0
 
0
   def **(exp)
0
     if !exp.is_a?(Integer)
0
- b, a = self.do_coerce(exp, true)
0
+ b, a = math_coerce(exp)
0
       return a ** b
0
     end
0
     
...
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
...
85
86
87
88
 
 
89
90
91
92
93
94
95
 
96
97
98
99
100
101
 
102
103
104
...
113
114
115
116
117
118
 
 
 
 
119
120
121
122
123
124
125
 
 
 
 
 
126
127
128
...
139
140
141
142
 
143
144
145
...
165
166
167
168
169
 
 
 
 
 
 
 
 
 
 
170
171
172
173
174
175
176
177
 
178
179
180
181
182
 
183
184
 
185
186
 
 
 
 
 
 
 
 
 
 
 
187
188
...
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
...
85
86
87
 
88
89
90
91
92
93
94
95
 
96
97
98
99
100
101
 
102
103
104
105
...
114
115
116
 
 
 
117
118
119
120
121
122
123
124
125
 
 
126
127
128
129
130
131
132
133
...
144
145
146
 
147
148
149
150
...
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
196
197
198
199
200
201
202
203
204
205
206
 
0
@@ -4,35 +4,35 @@ class Numeric
0
   include Comparable
0
 
0
   def +(other)
0
- b, a = self.do_coerce(other, true)
0
+ b, a = math_coerce(other)
0
     a + b
0
   end
0
   
0
   def -(other)
0
- b, a = self.do_coerce(other, true)
0
+ b, a = math_coerce(other)
0
     a - b
0
   end
0
   
0
   def *(other)
0
- b, a = self.do_coerce(other, true)
0
+ b, a = math_coerce(other)
0
     a * b
0
   end
0
   
0
   # see README-DEVELOPERS regarding safe math compiler plugin
0
   def divide(other)
0
- b, a = self.do_coerce(other, true)
0
+ b, a = math_coerce(other)
0
     raise ZeroDivisionError, "divided by 0" unless b.kind_of?(Float) or b != 0
0
     a / b
0
   end
0
   alias_method :/, :divide
0
   
0
   def **(other)
0
- b, a = self.do_coerce(other, true)
0
+ b, a = math_coerce(other)
0
     a ** b
0
   end
0
   
0
   def %(other)
0
- b, a = self.do_coerce(other, true)
0
+ b, a = math_coerce(other)
0
     raise ZeroDivisionError, "divided by 0" unless b.kind_of?(Float) or b != 0
0
     a % b
0
   end
0
@@ -85,20 +85,21 @@ class Numeric
0
  
0
   def div(other)
0
     raise FloatDomainError, "NaN" if self == 0 && other.is_a?(Float) && other == 0
0
- (self / other).floor
0
+ b, a = math_coerce(other)
0
+ (a / b).floor
0
   end
0
 
0
   def quo(other)
0
     if other.is_a?(Integer)
0
       self / Float(other)
0
     else
0
- b, a = self.do_coerce(other, true)
0
+ b, a = math_coerce(other)
0
       a / b
0
     end
0
   end
0
 
0
   def divmod(other)
0
- b, a = self.do_coerce(other, true)
0
+ b, a = math_coerce(other)
0
     
0
     if other == 0
0
       raise FloatDomainError, "NaN" if other.is_a?(Float)
0
@@ -113,16 +114,20 @@ class Numeric
0
   end
0
   
0
   def ==(other)
0
- if values = self.do_coerce(other, false)
0
- return values[1] == values[0]
0
- else
0
+ begin
0
+ b, a = math_coerce(other)
0
+ return a == b
0
+ rescue TypeError
0
       return other == self
0
     end
0
   end
0
   
0
   def <=>(other)
0
- if values = self.do_coerce(other)
0
- values[1] <=> values[0]
0
+ begin
0
+ b, a = math_coerce(other)
0
+ return a <=> b
0
+ rescue TypeError
0
+ return nil
0
     end
0
   end
0
   
0
@@ -139,7 +144,7 @@ class Numeric
0
   end
0
 
0
   def remainder(other)
0
- b, a = self.do_coerce(other, true)
0
+ b, a = math_coerce(other)
0
     mod = a % b
0
 
0
     if mod != 0 && (a < 0 && b > 0 || a > 0 && b < 0)
0
@@ -165,24 +170,37 @@ class Numeric
0
     raise ArgumentError, e.message
0
   end
0
 
0
- # Little helper to ease coercing
0
- def do_coerce(other, raise_error = false)
0
+ # This method mimics the semantics of MRI's do_coerce function
0
+ # in numeric.c. Note these differences between it and #coerce:
0
+ # 1.2.coerce("2") => [2.0, 1.2]
0
+ # 1.2 + "2" => TypeError: String can't be coerced into Float
0
+ #
0
+ # We do not attempt to produce the exact same exception message
0
+ # as MRI, so please do not edit it to match.
0
+ #
0
+ # See also our Numeric#coerce
0
+ def math_coerce(other, error=:coerce_error)
0
     begin
0
       values = other.coerce(self)
0
     rescue
0
- if raise_error
0
- message = "#{other.is_a?(Symbol) ? other.inspect : other.class} can't be coerced into #{self.class}"
0
- raise TypeError, message
0
- end
0
- return false
0
+ send error, other
0
     end
0
     
0
     unless values.is_a?(Array) && values.length == 2
0
- raise TypeError, "coerce must return [x, y]" if raise_error
0
- return false
0
+ raise TypeError, "coerce must return [x, y]"
0
     end
0
-
0
+
0
     return values[1], values[0]
0
   end
0
+ private :math_coerce
0
+
0
+ def coerce_error(other)
0
+ raise TypeError, "#{other.class} can't be coerced into #{self.class}"
0
+ end
0
+ private :coerce_error
0
+
0
+ def compare_error(other)
0
+ raise ArgumentError, "comparison of #{self.class} with #{other.class} failed"
0
+ end
0
+ private :compare_error
0
 end
0
-
...
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
...
13
14
15
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
17
18
19
 
 
 
 
 
 
 
 
 
 
 
 
20
21
22
0
@@ -13,36 +13,10 @@ class Platform::Float
0
   attach_function 'float_mant_dig', :MANT_DIG, [], :int
0
   attach_function 'float_epsilon', :EPSILON, [], :double
0
 
0
- attach_function 'float_to_i', :to_i, [:double], :int
0
- attach_function 'float_add', :add, [:double, :double], :double
0
- attach_function 'float_sub', :sub, [:double, :double], :double
0
- attach_function 'float_mul', :mul, [:double, :double], :double
0
- attach_function 'float_div', :div, [:double, :double], :double
0
- attach_function 'float_uminus', :uminus, [:double], :double
0
- attach_function 'float_equal', :value_equal, [:double, :double], :int
0
- attach_function 'float_compare', :compare, [:double, :double], :int
0
- attach_function 'float_round', :round, [:double], :int
0
- attach_function 'fmod', [:double, :double], :double
0
- attach_function 'pow', [:double, :double], :double
0
- attach_function 'isnan', [:double], :int
0
- attach_function 'isinf', [:double], :int
0
-
0
   attach_function 'frexp', [:double, :pointer], :double
0
   attach_function 'ldexp', [:double, :int], :double
0
   attach_function 'modf', [:double, :pointer], :double
0
 
0
- def self.eql?(a, b)
0
- value_equal(a, b) == 1
0
- end
0
-
0
- def self.nan?(value)
0
- isnan(value) == 1
0
- end
0
-
0
- def self.infinite?(value)
0
- return (value < 0 ? -1 : 1) if isinf(value) != 0
0
- end
0
-
0
   def self.to_s_formatted(size, fmt, value)
0
     s, p = Platform::POSIX.sprintf_f value, size, fmt
0
     str = s.dup
...
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
...
57
58
59
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
60
61
62
0
@@ -57,38 +57,6 @@ int _object_stores_bytes(OBJECT self);
0
 
0
 #define ZLIB_CHUNK_SIZE 512
0
 
0
-#define INDEXED(obj) (RTEST(obj) && (REFERENCE_P(obj) || !object_stores_bytes_p(state, obj)))
0
-
0
-#define RTYPE(obj,type) (REFERENCE_P(obj) && obj->obj_type == type)
0
-#define RISA(obj,cls) (REFERENCE_P(obj) && ISA(obj,BASIC_CLASS(cls)))
0
-
0
-#define BIGNUM_P(obj) (RTYPE(obj, BignumType))
0
-#define FLOAT_P(obj) (RTYPE(obj, FloatType))
0
-#define COMPLEX_P(obj) (FALSE)
0
-
0
-#define INTEGER_P(obj) (FIXNUM_P(obj) || BIGNUM_P(obj))
0
-#define NUMERIC_P(obj) (FIXNUM_P(obj) || COMPLEX_P(obj) || BIGNUM_P(obj) || FLOAT_P(obj))
0
-
0
-#define CLASS_P(obj) RTYPE(obj, ClassType)
0
-#define TUPLE_P(obj) RTYPE(obj, TupleType)
0
-#define IO_P(obj) RISA(obj, io)
0
-#define STRING_P(obj) RTYPE(obj, StringType)
0
-// #define STRING_P(obj) RISA(obj, string)
0
-#define ARRAY_P(obj) RTYPE(obj, ArrayType)
0
-
0
-#define STRING_OR_NIL_P(obj) (STRING_P(obj) || NIL_P(obj))
0
-
0
-#define CMETHOD_P(obj) RTYPE(obj, CMethodType)
0
-#define REGEXP_P(obj) RTYPE(obj, RegexpType)
0
-
0
-#define CTX_P(obj) RISA(obj, fastctx)
0
-#define BYTEARRAY_P(obj) RTYPE(obj, ByteArrayType)
0
-#define ISEQ_P(obj) RTYPE(obj, ISeqType)
0
-#define TASK_P(obj) RTYPE(obj, TaskType)
0
-#define CHANNEL_P(obj) RTYPE(obj, ChannelType)
0
-#define BLOCKENV_P(obj) RTYPE(obj, BlockEnvType)
0
-#define THREAD_P(obj) RTYPE(obj, ThreadType)
0
-
0
 // defines a required arity for a primitive
0
 // return true because we want other handler code to ignore it
0
 // this is because it is raised directly in the primitive as an exception
...
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
...
86
87
88
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
89
90
91
...
118
119
120
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
121
122
123
...
17
18
19
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
21
22
23
24
...
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
...
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
0
@@ -17,42 +17,8 @@
0
 #include "shotgun/lib/shotgun.h"
0
 #include "shotgun/lib/string.h"
0
 #include "shotgun/lib/array.h"
0
-
0
-/* use IEEE 64bit values if not defined */
0
-#ifndef FLT_RADIX
0
-#define FLT_RADIX 2
0
-#endif
0
-#ifndef FLT_ROUNDS
0
-#define FLT_ROUNDS 1
0
-#endif
0
-#ifndef DBL_MIN
0
-#define DBL_MIN 2.2250738585072014e-308
0
-#endif
0
-#ifndef DBL_MAX
0
-#define DBL_MAX 1.7976931348623157e+308
0
-#endif
0
-#ifndef DBL_MIN_EXP
0
-#define DBL_MIN_EXP (-1021)
0
-#endif
0
-#ifndef DBL_MAX_EXP
0
-#define DBL_MAX_EXP 1024
0
-#endif
0
-#ifndef DBL_MIN_10_EXP
0
-#define DBL_MIN_10_EXP (-307)
0
-#endif
0
-#ifndef DBL_MAX_10_EXP
0
-#define DBL_MAX_10_EXP 308
0
-#endif
0
-#ifndef DBL_DIG
0
-#define DBL_DIG 15
0
-#endif
0
-#ifndef DBL_MANT_DIG
0
-#define DBL_MANT_DIG 53
0
-#endif
0
-#ifndef DBL_EPSILON
0
-#define DBL_EPSILON 2.2204460492503131e-16
0
-#endif
0
-/* End borrowing from MRI 1.8.6 stable */
0
+#include "shotgun/lib/bignum.h"
0
+#include "shotgun/lib/float.h"
0
 
0
 int float_radix() { return FLT_RADIX; }
0
 int float_rounds() { return FLT_ROUNDS; }
0
@@ -86,6 +52,27 @@ void float_into_string(STATE, OBJECT self, char *buf, int sz) {
0
   snprintf(buf, sz, "%+.17e", FLOAT_TO_DOUBLE(self));
0
 }
0
 
0
+/* TODO: change float_to_i_prim name to float_to_i once
0
+ * the stables no longer depend on the FFI implementation
0
+ */
0
+OBJECT float_to_i_prim(STATE, double value) {
0
+ if (value > 0.0) value = floor(value);
0
+ if (value < 0.0) value = ceil(value);
0
+ return bignum_from_double(state, value);
0
+}
0
+
0
+OBJECT float_coerce(STATE, OBJECT value) {
0
+ if(FIXNUM_P(value)) {
0
+ return float_new(state, (double)N2I(value));
0
+ } else if(BIGNUM_P(value)) {
0
+ return float_new(state, bignum_to_double(state, value));
0
+ }
0
+ return value;
0
+}
0
+
0
+/* TODO: Remove all the following methods once the stables
0
+ * no longer depend on the FFI implementation of Float.
0
+ */
0
 double float_add(double a, double b) {
0
   return a + b;
0
 }
0
@@ -118,6 +105,22 @@ int float_compare(double a, double b) {
0
   return 0;
0
 }
0
 
0
+OBJECT float_lt(double a, double b) {
0
+ return a < b ? Qtrue : Qfalse;
0
+}
0
+
0
+OBJECT float_lte(double a, double b) {
0
+ return a <= b ? Qtrue : Qfalse;
0
+}
0
+
0
+OBJECT float_gt(double a, double b) {
0
+ return a > b ? Qtrue : Qfalse;
0
+}
0
+
0
+OBJECT float_gte(double a, double b) {
0
+ return a >= b ? Qtrue : Qfalse;
0
+}
0
+
0
 int float_to_i(double value) {
0
   if (value > 0.0) value = floor(value);
0
   if (value < 0.0) value = ceil(value);
...
1
2
3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
5
6
7
8
9
10
11
12
13
 
 
14
15
16
17
...
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
0
@@ -1,17 +1,47 @@
0
 #ifndef RBS_FLOAT_H
0
 #define RBS_FLOAT_H
0
 
0
+/* use IEEE 64bit values if not defined */
0
+#ifndef FLT_RADIX
0
+#define FLT_RADIX 2
0
+#endif
0
+#ifndef FLT_ROUNDS
0
+#define FLT_ROUNDS 1
0
+#endif
0
+#ifndef DBL_MIN
0
+#define DBL_MIN 2.2250738585072014e-308
0
+#endif
0
+#ifndef DBL_MAX
0
+#define DBL_MAX 1.7976931348623157e+308
0
+#endif
0
+#ifndef DBL_MIN_EXP
0
+#define DBL_MIN_EXP (-1021)
0
+#endif
0
+#ifndef DBL_MAX_EXP
0
+#define DBL_MAX_EXP 1024
0
+#endif
0
+#ifndef DBL_MIN_10_EXP
0
+#define DBL_MIN_10_EXP (-307)
0
+#endif
0
+#ifndef DBL_MAX_10_EXP
0
+#define DBL_MAX_10_EXP 308
0
+#endif
0
+#ifndef DBL_DIG
0
+#define DBL_DIG 15
0
+#endif
0
+#ifndef DBL_MANT_DIG
0
+#define DBL_MANT_DIG 53
0
+#endif
0
+#ifndef DBL_EPSILON
0
+#define DBL_EPSILON 2.2204460492503131e-16
0
+#endif
0
+/* End borrowing from MRI 1.8.6 stable */
0
+
0
 OBJECT float_new(STATE, double dbl);
0
 OBJECT float_from_string(STATE, char *str);
0
 void float_into_string(STATE, OBJECT self, char *buf, int sz);
0
-double float_add(double a, double b);
0
-double float_sub(double a, double b);
0
-double float_mul(double a, double b);
0
-double float_div(double a, double b);
0
-double float_uminus(double a);
0
-int float_equal(double a, double b);
0
-int float_compare(double a, double b);
0
+OBJECT float_coerce(STATE, OBJECT value);
0
+OBJECT float_to_i_prim(STATE, double value);
0
 int float_to_i(double value);
0
-int float_round(double value);
0
 
0
 #endif
...
265
266
267
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
268
269
270
...
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
0
@@ -265,6 +265,38 @@ to be a simple test for that bit pattern.
0
 
0
 #define REFERENCE2_P(v) (v && REFERENCE_P(v))
0
 
0
+#define INDEXED(obj) (RTEST(obj) && (REFERENCE_P(obj) || !object_stores_bytes_p(state, obj)))
0
+
0
+#define RTYPE(obj,type) (REFERENCE_P(obj) && obj->obj_type == type)
0
+#define RISA(obj,cls) (REFERENCE_P(obj) && ISA(obj,BASIC_CLASS(cls)))
0
+
0
+#define BIGNUM_P(obj) (RTYPE(obj, BignumType))
0
+#define FLOAT_P(obj) (RTYPE(obj, FloatType))
0
+#define COMPLEX_P(obj) (FALSE)
0
+
0
+#define INTEGER_P(obj) (FIXNUM_P(obj) || BIGNUM_P(obj))
0
+#define NUMERIC_P(obj) (FIXNUM_P(obj) || COMPLEX_P(obj) || BIGNUM_P(obj) || FLOAT_P(obj))
0
+
0
+#define CLASS_P(obj) RTYPE(obj, ClassType)
0
+#define TUPLE_P(obj) RTYPE(obj, TupleType)
0
+#define IO_P(obj) RISA(obj, io)
0
+#define STRING_P(obj) RTYPE(obj, StringType)
0
+#define HASH_P(obj) (RISA(obj, hash))
0
+#define ARRAY_P(obj) RTYPE(obj, ArrayType)
0
+
0
+#define STRING_OR_NIL_P(obj) (STRING_P(obj) || NIL_P(obj))
0
+
0
+#define CMETHOD_P(obj) RTYPE(obj, CMethodType)
0
+#define REGEXP_P(obj) RTYPE(obj, RegexpType)
0
+
0
+#define CTX_P(obj) RISA(obj, fastctx)
0
+#define BYTEARRAY_P(obj) RTYPE(obj, ByteArrayType)
0
+#define ISEQ_P(obj) RTYPE(obj, ISeqType)
0
+#define TASK_P(obj) RTYPE(obj, TaskType)
0
+#define CHANNEL_P(obj) RTYPE(obj, ChannelType)
0
+#define BLOCKENV_P(obj) RTYPE(obj, BlockEnvType)
0
+#define THREAD_P(obj) RTYPE(obj, ThreadType)
0
+
0
 #ifndef TRUE
0
 #define TRUE 1
0
 #endif