public
Description: Rubinius, the Ruby VM
Homepage: http://rubini.us
Clone URL: git://github.com/evanphx/rubinius.git
Reworked Fixnum, Bignum arithmetic primitives.
brixen (author)
Tue Feb 12 18:45:37 -0800 2008
commit  f7ff8d7de8f47023f372b75b66b1da1ec0c1eb2e
tree    b2d60b4993a5253e376e3f0285db3cd58ba5c021
parent  5c75721d5a78e25a77e9f068bf4c95e729604959
...
67
68
69
70
71
72
 
73
 
74
75
76
...
87
88
89
90
91
92
 
 
 
 
93
94
95
 
 
 
 
 
 
 
 
 
96
97
98
...
67
68
69
 
 
 
70
71
72
73
74
75
...
86
87
88
 
 
 
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
0
@@ -67,10 +67,9 @@ static inline OBJECT fixnum_mul(STATE, OBJECT a, OBJECT b) {
0
   }
0
 }
0
 
0
-static inline OBJECT fixnum_divmod(STATE, OBJECT a, OBJECT b) {
0
- OBJECT ary;
0
- long div, mod;
0
+static inline long fixnum_div(STATE, OBJECT a, OBJECT b, long *mod) {
0
   native_int x, y;
0
+ long div;
0
 
0
   x = N2I(a);
0
   y = N2I(b);
0
@@ -87,12 +86,22 @@ static inline OBJECT fixnum_divmod(STATE, OBJECT a, OBJECT b) {
0
     else
0
       div = x / y;
0
   }
0
- mod = x - div*y;
0
- if ((mod < 0 && y > 0) || (mod > 0 && y < 0)) {
0
- mod += y;
0
+
0
+ *mod = x - div*y;
0
+ if ((*mod < 0 && y > 0) || (*mod > 0 && y < 0)) {
0
+ *mod += y;
0
     div -= 1;
0
   }
0
   
0
+ return div;
0
+}
0
+
0
+static inline OBJECT fixnum_divmod(STATE, OBJECT a, OBJECT b) {
0
+ OBJECT ary;
0
+ long div, mod;
0
+
0
+ div = fixnum_div(state, a, b, &mod);
0
+
0
   ary = array_new(state, 2);
0
   array_set(state, ary, 0, I2N(div));
0
   array_set(state, ary, 1, I2N(mod));
...
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
...
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
...
1696
1697
1698
1699
 
1700
1701
1702
1703
1704
1705
1706
1707
 
 
 
 
1708
1709
1710
...
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
...
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
207
208
209
210
211
212
213
214
215
216
217
218
 
 
219
 
 
 
 
 
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
...
1738
1739
1740
 
1741
1742
1743
1744
1745
 
 
 
 
1746
1747
1748
1749
1750
1751
1752
0
@@ -94,56 +94,82 @@ class ShotgunPrimitives
0
 
0
   def add
0
     <<-CODE
0
- OBJECT t1;
0
-
0
     GUARD(FIXNUM_P(msg->recv));
0
- POP(t1, FIXNUM);
0
-
0
- RET(fixnum_add(state, msg->recv, t1));
0
+ OBJECT t1 = stack_pop();
0
+ if(FIXNUM_P(t1)) {
0
+ RET(fixnum_add(state, msg->recv, t1));
0
+ } else if(BIGNUM_P(t1)) {
0
+ RET(bignum_add(state, bignum_new(state, N2I(msg->recv)), t1));
0
+ } else if(FLOAT_P(t1)) {
0
+ OBJECT t2 = float_coerce(state, msg->recv);
0
+ RET(float_new(state, FLOAT_TO_DOUBLE(t2) + FLOAT_TO_DOUBLE(t1)));
0
+ } else {
0
+ FAIL();
0
+ }
0
     CODE
0
   end
0
   
0
   def bignum_add
0
     <<-CODE
0
- OBJECT t1;
0
-
0
     GUARD(BIGNUM_P(msg->recv));
0
- POP(t1, BIGNUM);
0
-
0
- RET(bignum_add(state, msg->recv, t1));
0
+ OBJECT t1 = stack_pop();
0
+ if(BIGNUM_P(t1) || FIXNUM_P(t1)) {
0
+ RET(bignum_add(state, msg->recv, t1));
0
+ } else if(FLOAT_P(t1)) {
0
+ double a = bignum_to_double(state, msg->recv);
0
+ RET(float_new(state, a + FLOAT_TO_DOUBLE(t1)));
0
+ } else {
0
+ FAIL();
0
+ }
0
     CODE
0
   end
0
   
0
   def sub
0
     <<-CODE
0
- OBJECT t1;
0
-
0
     GUARD(FIXNUM_P(msg->recv));
0
- POP(t1, FIXNUM);
0
-
0
- RET(fixnum_sub(state, msg->recv, t1));
0
+ OBJECT t1 = stack_pop();
0
+ if(FIXNUM_P(t1)) {
0
+ RET(fixnum_sub(state, msg->recv, t1));
0
+ } else if(BIGNUM_P(t1)) {
0
+ RET(bignum_sub(state, bignum_new(state, N2I(msg->recv)), t1));
0
+ } else if(FLOAT_P(t1)) {
0
+ OBJECT t2 = float_coerce(state, msg->recv);
0
+ RET(float_new(state, FLOAT_TO_DOUBLE(t2) - FLOAT_TO_DOUBLE(t1)));
0
+ } else {
0
+ FAIL();
0
+ }
0
     CODE
0
   end
0
   
0
   def bignum_sub
0
     <<-CODE
0
- OBJECT t1;
0
-
0
     GUARD(BIGNUM_P(msg->recv));
0
- POP(t1, INTEGER);
0
-
0
- RET(bignum_sub(state, msg->recv, t1));
0
+ OBJECT t1 = stack_pop();
0
+ if(BIGNUM_P(t1) || FIXNUM_P(t1)) {
0
+ RET(bignum_sub(state, msg->recv, t1));
0
+ } else if(FLOAT_P(t1)) {
0
+ double a = bignum_to_double(state, msg->recv);
0
+ RET(float_new(state, a - FLOAT_TO_DOUBLE(t1)));
0
+ } else {
0
+ FAIL();
0
+ }
0
     CODE
0
   end
0
   
0
   def fixnum_mul
0
     <<-CODE
0
- OBJECT t1;
0
-
0
     GUARD(FIXNUM_P(msg->recv));
0
- POP(t1, FIXNUM);
0
-
0
- RET(fixnum_mul(state, msg->recv, t1));
0
+ OBJECT t1 = stack_pop();
0
+ if(FIXNUM_P(t1)) {
0
+ RET(fixnum_mul(state, msg->recv, t1));
0
+ } else if(BIGNUM_P(t1)) {
0
+ RET(bignum_mul(state, bignum_new(state, N2I(msg->recv)), t1));
0
+ } else if(FLOAT_P(t1)) {
0
+ OBJECT t2 = float_coerce(state, msg->recv);
0
+ RET(float_new(state, FLOAT_TO_DOUBLE(t2) * FLOAT_TO_DOUBLE(t1)));
0
+ } else {
0
+ FAIL();
0
+ }
0
     CODE
0
   end
0
   
0
@@ -155,39 +181,55 @@ class ShotgunPrimitives
0
 
0
   def bignum_mul
0
     <<-CODE
0
- OBJECT t1;
0
-
0
     GUARD(BIGNUM_P(msg->recv));
0
- POP(t1, INTEGER);
0
-
0
- RET(bignum_mul(state, msg->recv, t1));
0
+ OBJECT t1 = stack_pop();
0
+ if(BIGNUM_P(t1) || FIXNUM_P(t1)) {
0
+ RET(bignum_mul(state, msg->recv, t1));
0
+ } else if(FLOAT_P(t1)) {
0
+ double a = bignum_to_double(state, msg->recv);
0
+ RET(float_new(state, a * FLOAT_TO_DOUBLE(t1)));
0
+ } else {
0
+ FAIL();
0
+ }
0
     CODE
0
   end
0
   
0
   def fixnum_div
0
     <<-CODE
0
- OBJECT t1, t3;
0
-
0
     GUARD(FIXNUM_P(msg->recv));
0
- POP(t1, FIXNUM);
0
-
0
- GUARD( N2I(t1) != 0 ) // no divide by zero
0
-
0
- t3 = fixnum_divmod(state, msg->recv, t1);
0
- RET(array_get(state, t3, 0));
0
+ OBJECT t1 = stack_pop();
0
+ if(FIXNUM_P(t1)) {
0
+ long mod;
0
+ GUARD(N2I(t1) != 0) // no divide by zero
0
+ RET(I2N(fixnum_div(state, msg->recv, t1, &mod)));
0
+ } else if(BIGNUM_P(t1)) {
0
+ GUARD(!bignum_is_zero(state, t1));
0
+ RET(bignum_div(state, bignum_new(state, N2I(msg->recv)), t1));
0
+ } else if(FLOAT_P(t1)) {
0
+ OBJECT t2 = float_coerce(state, msg->recv);
0
+ RET(float_new(state, FLOAT_TO_DOUBLE(t2) / FLOAT_TO_DOUBLE(t1)));
0
+ } else {
0
+ FAIL();
0
+ }
0
     CODE
0
   end
0
   
0
   def bignum_div
0
     <<-CODE
0
- OBJECT t1;
0
-
0
     GUARD(BIGNUM_P(msg->recv));
0
- POP(t1, BIGNUM);
0
-
0
- // Can this ever happen since bignum will always be > zero?
0
- GUARD(!bignum_is_zero(state, t1));
0
- RET(bignum_div(state, msg->recv, t1));
0
+ OBJECT t1 = stack_pop();
0
+ if(BIGNUM_P(t1)) {
0
+ GUARD(!bignum_is_zero(state, t1));
0
+ RET(bignum_div(state, msg->recv, t1));
0
+ } else if(FIXNUM_P(t1)) {
0
+ GUARD(N2I(t1) != 0) // no divide by zero
0
+ RET(bignum_div(state, msg->recv, t1));
0
+ } else if(FLOAT_P(t1)) {
0
+ double a = bignum_to_double(state, msg->recv);
0
+ RET(float_new(state, a / FLOAT_TO_DOUBLE(t1)));
0
+ } else {
0
+ FAIL();
0
+ }
0
     CODE
0
   end
0
 
0
@@ -1696,15 +1738,15 @@ class ShotgunPrimitives
0
 
0
   def fixnum_modulo
0
     <<-CODE
0
- OBJECT t1, t3;
0
+ OBJECT t1;
0
 
0
     GUARD(FIXNUM_P(msg->recv));
0
     POP(t1, FIXNUM);
0
 
0
- GUARD( N2I(t1) != 0 ) // no divide by zero
0
-
0
- t3 = fixnum_divmod(state, msg->recv, t1);
0
- RET(array_get(state, t3, 1));
0
+ GUARD(N2I(t1) != 0) // no divide by zero
0
+ long mod;
0
+ fixnum_div(state, msg->recv, t1, &mod);
0
+ RET(I2N(mod));
0
     CODE
0
   end
0
   

Comments

    No one has commented yet.