mbed I/F binding for mruby
Dependents: mruby_mbed_web mirb_mbed
mbed-mruby
How to use
Class
src/numeric.c@1:8ccd1d494a4b, 2015-04-13 (annotated)
- Committer:
- mzta
- Date:
- Mon Apr 13 05:20:15 2015 +0000
- Revision:
- 1:8ccd1d494a4b
- Parent:
- 0:158c61bb030f
- code refactoring.; - add SPI, SPISlave, I2C class to mruby-mbed (Incomplete).
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
mzta | 0:158c61bb030f | 1 | /* |
mzta | 0:158c61bb030f | 2 | ** numeric.c - Numeric, Integer, Float, Fixnum class |
mzta | 0:158c61bb030f | 3 | ** |
mzta | 0:158c61bb030f | 4 | ** See Copyright Notice in mruby.h |
mzta | 0:158c61bb030f | 5 | */ |
mzta | 0:158c61bb030f | 6 | |
mzta | 0:158c61bb030f | 7 | #include <float.h> |
mzta | 0:158c61bb030f | 8 | #include <limits.h> |
mzta | 0:158c61bb030f | 9 | #include <math.h> |
mzta | 0:158c61bb030f | 10 | #include <stdlib.h> |
mzta | 0:158c61bb030f | 11 | |
mzta | 0:158c61bb030f | 12 | #include "mruby.h" |
mzta | 0:158c61bb030f | 13 | #include "mruby/array.h" |
mzta | 0:158c61bb030f | 14 | #include "mruby/numeric.h" |
mzta | 0:158c61bb030f | 15 | #include "mruby/string.h" |
mzta | 0:158c61bb030f | 16 | |
mzta | 0:158c61bb030f | 17 | #ifdef MRB_USE_FLOAT |
mzta | 0:158c61bb030f | 18 | #define floor(f) floorf(f) |
mzta | 0:158c61bb030f | 19 | #define ceil(f) ceilf(f) |
mzta | 0:158c61bb030f | 20 | #define fmod(x,y) fmodf(x,y) |
mzta | 0:158c61bb030f | 21 | #define FLO_MAX_DIGITS 7 |
mzta | 0:158c61bb030f | 22 | #define FLO_MAX_SIGN_LENGTH 3 |
mzta | 0:158c61bb030f | 23 | #define FLO_EPSILON FLT_EPSILON |
mzta | 0:158c61bb030f | 24 | #else |
mzta | 0:158c61bb030f | 25 | #define FLO_MAX_DIGITS 14 |
mzta | 0:158c61bb030f | 26 | #define FLO_MAX_SIGN_LENGTH 10 |
mzta | 0:158c61bb030f | 27 | #define FLO_EPSILON DBL_EPSILON |
mzta | 0:158c61bb030f | 28 | #endif |
mzta | 0:158c61bb030f | 29 | |
mzta | 0:158c61bb030f | 30 | MRB_API mrb_float |
mzta | 0:158c61bb030f | 31 | mrb_to_flo(mrb_state *mrb, mrb_value val) |
mzta | 0:158c61bb030f | 32 | { |
mzta | 0:158c61bb030f | 33 | switch (mrb_type(val)) { |
mzta | 0:158c61bb030f | 34 | case MRB_TT_FIXNUM: |
mzta | 0:158c61bb030f | 35 | return (mrb_float)mrb_fixnum(val); |
mzta | 0:158c61bb030f | 36 | case MRB_TT_FLOAT: |
mzta | 0:158c61bb030f | 37 | break; |
mzta | 0:158c61bb030f | 38 | default: |
mzta | 0:158c61bb030f | 39 | mrb_raise(mrb, E_TYPE_ERROR, "non float value"); |
mzta | 0:158c61bb030f | 40 | } |
mzta | 0:158c61bb030f | 41 | return mrb_float(val); |
mzta | 0:158c61bb030f | 42 | } |
mzta | 0:158c61bb030f | 43 | |
mzta | 0:158c61bb030f | 44 | /* |
mzta | 0:158c61bb030f | 45 | * call-seq: |
mzta | 0:158c61bb030f | 46 | * |
mzta | 0:158c61bb030f | 47 | * num ** other -> num |
mzta | 0:158c61bb030f | 48 | * |
mzta | 0:158c61bb030f | 49 | * Raises <code>num</code> the <code>other</code> power. |
mzta | 0:158c61bb030f | 50 | * |
mzta | 0:158c61bb030f | 51 | * 2.0**3 #=> 8.0 |
mzta | 0:158c61bb030f | 52 | */ |
mzta | 0:158c61bb030f | 53 | static mrb_value |
mzta | 0:158c61bb030f | 54 | num_pow(mrb_state *mrb, mrb_value x) |
mzta | 0:158c61bb030f | 55 | { |
mzta | 0:158c61bb030f | 56 | mrb_value y; |
mzta | 0:158c61bb030f | 57 | mrb_float d, yv; |
mzta | 0:158c61bb030f | 58 | |
mzta | 0:158c61bb030f | 59 | mrb_get_args(mrb, "o", &y); |
mzta | 0:158c61bb030f | 60 | yv = mrb_to_flo(mrb, y); |
mzta | 0:158c61bb030f | 61 | d = pow(mrb_to_flo(mrb, x), yv); |
mzta | 0:158c61bb030f | 62 | if (mrb_fixnum_p(x) && mrb_fixnum_p(y) && FIXABLE(d) && yv > 0) |
mzta | 0:158c61bb030f | 63 | return mrb_fixnum_value((mrb_int)d); |
mzta | 0:158c61bb030f | 64 | return mrb_float_value(mrb, d); |
mzta | 0:158c61bb030f | 65 | } |
mzta | 0:158c61bb030f | 66 | |
mzta | 0:158c61bb030f | 67 | /* 15.2.8.3.4 */ |
mzta | 0:158c61bb030f | 68 | /* 15.2.9.3.4 */ |
mzta | 0:158c61bb030f | 69 | /* |
mzta | 0:158c61bb030f | 70 | * call-seq: |
mzta | 0:158c61bb030f | 71 | * num / other -> num |
mzta | 0:158c61bb030f | 72 | * |
mzta | 0:158c61bb030f | 73 | * Performs division: the class of the resulting object depends on |
mzta | 0:158c61bb030f | 74 | * the class of <code>num</code> and on the magnitude of the |
mzta | 0:158c61bb030f | 75 | * result. |
mzta | 0:158c61bb030f | 76 | */ |
mzta | 0:158c61bb030f | 77 | |
mzta | 0:158c61bb030f | 78 | mrb_value |
mzta | 0:158c61bb030f | 79 | mrb_num_div(mrb_state *mrb, mrb_value x, mrb_value y) |
mzta | 0:158c61bb030f | 80 | { |
mzta | 0:158c61bb030f | 81 | return mrb_float_value(mrb, mrb_to_flo(mrb, x) / mrb_to_flo(mrb, y)); |
mzta | 0:158c61bb030f | 82 | } |
mzta | 0:158c61bb030f | 83 | |
mzta | 0:158c61bb030f | 84 | /* 15.2.9.3.19(x) */ |
mzta | 0:158c61bb030f | 85 | /* |
mzta | 0:158c61bb030f | 86 | * call-seq: |
mzta | 0:158c61bb030f | 87 | * num.quo(numeric) -> real |
mzta | 0:158c61bb030f | 88 | * |
mzta | 0:158c61bb030f | 89 | * Returns most exact division. |
mzta | 0:158c61bb030f | 90 | */ |
mzta | 0:158c61bb030f | 91 | |
mzta | 0:158c61bb030f | 92 | static mrb_value |
mzta | 0:158c61bb030f | 93 | num_div(mrb_state *mrb, mrb_value x) |
mzta | 0:158c61bb030f | 94 | { |
mzta | 0:158c61bb030f | 95 | mrb_float y; |
mzta | 0:158c61bb030f | 96 | |
mzta | 0:158c61bb030f | 97 | mrb_get_args(mrb, "f", &y); |
mzta | 0:158c61bb030f | 98 | return mrb_float_value(mrb, mrb_to_flo(mrb, x) / y); |
mzta | 0:158c61bb030f | 99 | } |
mzta | 0:158c61bb030f | 100 | |
mzta | 0:158c61bb030f | 101 | /******************************************************************** |
mzta | 0:158c61bb030f | 102 | * |
mzta | 0:158c61bb030f | 103 | * Document-class: Float |
mzta | 0:158c61bb030f | 104 | * |
mzta | 0:158c61bb030f | 105 | * <code>Float</code> objects represent inexact real numbers using |
mzta | 0:158c61bb030f | 106 | * the native architecture's double-precision floating point |
mzta | 0:158c61bb030f | 107 | * representation. |
mzta | 0:158c61bb030f | 108 | */ |
mzta | 0:158c61bb030f | 109 | |
mzta | 0:158c61bb030f | 110 | static mrb_value |
mzta | 0:158c61bb030f | 111 | mrb_flo_to_str(mrb_state *mrb, mrb_float flo) |
mzta | 0:158c61bb030f | 112 | { |
mzta | 0:158c61bb030f | 113 | double n = (double)flo; |
mzta | 0:158c61bb030f | 114 | int max_digits = FLO_MAX_DIGITS; |
mzta | 0:158c61bb030f | 115 | |
mzta | 0:158c61bb030f | 116 | if (isnan(n)) { |
mzta | 0:158c61bb030f | 117 | return mrb_str_new_lit(mrb, "NaN"); |
mzta | 0:158c61bb030f | 118 | } |
mzta | 0:158c61bb030f | 119 | else if (isinf(n)) { |
mzta | 0:158c61bb030f | 120 | if (n < 0) { |
mzta | 0:158c61bb030f | 121 | return mrb_str_new_lit(mrb, "-inf"); |
mzta | 0:158c61bb030f | 122 | } |
mzta | 0:158c61bb030f | 123 | else { |
mzta | 0:158c61bb030f | 124 | return mrb_str_new_lit(mrb, "inf"); |
mzta | 0:158c61bb030f | 125 | } |
mzta | 0:158c61bb030f | 126 | } |
mzta | 0:158c61bb030f | 127 | else { |
mzta | 0:158c61bb030f | 128 | int digit; |
mzta | 0:158c61bb030f | 129 | int m = 0; |
mzta | 0:158c61bb030f | 130 | int exp; |
mzta | 0:158c61bb030f | 131 | mrb_bool e = FALSE; |
mzta | 0:158c61bb030f | 132 | char s[48]; |
mzta | 0:158c61bb030f | 133 | char *c = &s[0]; |
mzta | 0:158c61bb030f | 134 | int length = 0; |
mzta | 0:158c61bb030f | 135 | |
mzta | 0:158c61bb030f | 136 | if (signbit(n)) { |
mzta | 0:158c61bb030f | 137 | n = -n; |
mzta | 0:158c61bb030f | 138 | *(c++) = '-'; |
mzta | 0:158c61bb030f | 139 | } |
mzta | 0:158c61bb030f | 140 | |
mzta | 0:158c61bb030f | 141 | if (n != 0.0) { |
mzta | 0:158c61bb030f | 142 | if (n > 1.0) { |
mzta | 0:158c61bb030f | 143 | exp = (int)floor(log10(n)); |
mzta | 0:158c61bb030f | 144 | } |
mzta | 0:158c61bb030f | 145 | else { |
mzta | 0:158c61bb030f | 146 | exp = (int)-ceil(-log10(n)); |
mzta | 0:158c61bb030f | 147 | } |
mzta | 0:158c61bb030f | 148 | } |
mzta | 0:158c61bb030f | 149 | else { |
mzta | 0:158c61bb030f | 150 | exp = 0; |
mzta | 0:158c61bb030f | 151 | } |
mzta | 0:158c61bb030f | 152 | |
mzta | 0:158c61bb030f | 153 | /* preserve significands */ |
mzta | 0:158c61bb030f | 154 | if (exp < 0) { |
mzta | 0:158c61bb030f | 155 | int i, beg = -1, end = 0; |
mzta | 0:158c61bb030f | 156 | double f = n; |
mzta | 0:158c61bb030f | 157 | double fd = 0; |
mzta | 0:158c61bb030f | 158 | for (i = 0; i < FLO_MAX_DIGITS; ++i) { |
mzta | 0:158c61bb030f | 159 | f = (f - fd) * 10.0; |
mzta | 0:158c61bb030f | 160 | fd = floor(f + FLO_EPSILON); |
mzta | 0:158c61bb030f | 161 | if (fd != 0) { |
mzta | 0:158c61bb030f | 162 | if (beg < 0) beg = i; |
mzta | 0:158c61bb030f | 163 | end = i + 1; |
mzta | 0:158c61bb030f | 164 | } |
mzta | 0:158c61bb030f | 165 | } |
mzta | 0:158c61bb030f | 166 | if (beg >= 0) length = end - beg; |
mzta | 0:158c61bb030f | 167 | if (length > FLO_MAX_SIGN_LENGTH) length = FLO_MAX_SIGN_LENGTH; |
mzta | 0:158c61bb030f | 168 | } |
mzta | 0:158c61bb030f | 169 | |
mzta | 0:158c61bb030f | 170 | if (abs(exp) + length >= FLO_MAX_DIGITS) { |
mzta | 0:158c61bb030f | 171 | /* exponent representation */ |
mzta | 0:158c61bb030f | 172 | e = TRUE; |
mzta | 0:158c61bb030f | 173 | n = n / pow(10.0, exp); |
mzta | 0:158c61bb030f | 174 | if (isinf(n)) { |
mzta | 0:158c61bb030f | 175 | if (s < c) { /* s[0] == '-' */ |
mzta | 0:158c61bb030f | 176 | return mrb_str_new_lit(mrb, "-0.0"); |
mzta | 0:158c61bb030f | 177 | } |
mzta | 0:158c61bb030f | 178 | else { |
mzta | 0:158c61bb030f | 179 | return mrb_str_new_lit(mrb, "0.0"); |
mzta | 0:158c61bb030f | 180 | } |
mzta | 0:158c61bb030f | 181 | } |
mzta | 0:158c61bb030f | 182 | } |
mzta | 0:158c61bb030f | 183 | else { |
mzta | 0:158c61bb030f | 184 | /* un-exponent (normal) representation */ |
mzta | 0:158c61bb030f | 185 | if (exp > 0) { |
mzta | 0:158c61bb030f | 186 | m = exp; |
mzta | 0:158c61bb030f | 187 | } |
mzta | 0:158c61bb030f | 188 | } |
mzta | 0:158c61bb030f | 189 | |
mzta | 0:158c61bb030f | 190 | /* puts digits */ |
mzta | 0:158c61bb030f | 191 | while (max_digits >= 0) { |
mzta | 0:158c61bb030f | 192 | double weight = (m < 0) ? 0.0 : pow(10.0, m); |
mzta | 0:158c61bb030f | 193 | double fdigit = (m < 0) ? n * 10.0 : n / weight; |
mzta | 0:158c61bb030f | 194 | |
mzta | 0:158c61bb030f | 195 | if (fdigit < 0) fdigit = n = 0; |
mzta | 0:158c61bb030f | 196 | if (m < -1 && fdigit < FLO_EPSILON) { |
mzta | 0:158c61bb030f | 197 | if (e || exp > 0 || m <= -abs(exp)) { |
mzta | 0:158c61bb030f | 198 | break; |
mzta | 0:158c61bb030f | 199 | } |
mzta | 0:158c61bb030f | 200 | } |
mzta | 0:158c61bb030f | 201 | digit = (int)floor(fdigit + FLO_EPSILON); |
mzta | 0:158c61bb030f | 202 | if (m == 0 && digit > 9) { |
mzta | 0:158c61bb030f | 203 | n /= 10.0; |
mzta | 0:158c61bb030f | 204 | exp++; |
mzta | 0:158c61bb030f | 205 | continue; |
mzta | 0:158c61bb030f | 206 | } |
mzta | 0:158c61bb030f | 207 | *(c++) = '0' + digit; |
mzta | 0:158c61bb030f | 208 | n = (m < 0) ? n * 10.0 - digit : n - (digit * weight); |
mzta | 0:158c61bb030f | 209 | max_digits--; |
mzta | 0:158c61bb030f | 210 | if (m-- == 0) { |
mzta | 0:158c61bb030f | 211 | *(c++) = '.'; |
mzta | 0:158c61bb030f | 212 | } |
mzta | 0:158c61bb030f | 213 | } |
mzta | 0:158c61bb030f | 214 | if (c[-1] == '0') { |
mzta | 0:158c61bb030f | 215 | while (&s[0] < c && c[-1] == '0') { |
mzta | 0:158c61bb030f | 216 | c--; |
mzta | 0:158c61bb030f | 217 | } |
mzta | 0:158c61bb030f | 218 | c++; |
mzta | 0:158c61bb030f | 219 | } |
mzta | 0:158c61bb030f | 220 | |
mzta | 0:158c61bb030f | 221 | if (e) { |
mzta | 0:158c61bb030f | 222 | *(c++) = 'e'; |
mzta | 0:158c61bb030f | 223 | if (exp > 0) { |
mzta | 0:158c61bb030f | 224 | *(c++) = '+'; |
mzta | 0:158c61bb030f | 225 | } |
mzta | 0:158c61bb030f | 226 | else { |
mzta | 0:158c61bb030f | 227 | *(c++) = '-'; |
mzta | 0:158c61bb030f | 228 | exp = -exp; |
mzta | 0:158c61bb030f | 229 | } |
mzta | 0:158c61bb030f | 230 | |
mzta | 0:158c61bb030f | 231 | if (exp >= 100) { |
mzta | 0:158c61bb030f | 232 | *(c++) = '0' + exp / 100; |
mzta | 0:158c61bb030f | 233 | exp -= exp / 100 * 100; |
mzta | 0:158c61bb030f | 234 | } |
mzta | 0:158c61bb030f | 235 | |
mzta | 0:158c61bb030f | 236 | *(c++) = '0' + exp / 10; |
mzta | 0:158c61bb030f | 237 | *(c++) = '0' + exp % 10; |
mzta | 0:158c61bb030f | 238 | } |
mzta | 0:158c61bb030f | 239 | |
mzta | 0:158c61bb030f | 240 | *c = '\0'; |
mzta | 0:158c61bb030f | 241 | |
mzta | 0:158c61bb030f | 242 | return mrb_str_new(mrb, &s[0], c - &s[0]); |
mzta | 0:158c61bb030f | 243 | } |
mzta | 0:158c61bb030f | 244 | } |
mzta | 0:158c61bb030f | 245 | |
mzta | 0:158c61bb030f | 246 | /* 15.2.9.3.16(x) */ |
mzta | 0:158c61bb030f | 247 | /* |
mzta | 0:158c61bb030f | 248 | * call-seq: |
mzta | 0:158c61bb030f | 249 | * flt.to_s -> string |
mzta | 0:158c61bb030f | 250 | * |
mzta | 0:158c61bb030f | 251 | * Returns a string containing a representation of self. As well as a |
mzta | 0:158c61bb030f | 252 | * fixed or exponential form of the number, the call may return |
mzta | 0:158c61bb030f | 253 | * ``<code>NaN</code>'', ``<code>Infinity</code>'', and |
mzta | 0:158c61bb030f | 254 | * ``<code>-Infinity</code>''. |
mzta | 0:158c61bb030f | 255 | */ |
mzta | 0:158c61bb030f | 256 | |
mzta | 0:158c61bb030f | 257 | static mrb_value |
mzta | 0:158c61bb030f | 258 | flo_to_s(mrb_state *mrb, mrb_value flt) |
mzta | 0:158c61bb030f | 259 | { |
mzta | 0:158c61bb030f | 260 | return mrb_flo_to_str(mrb, mrb_float(flt)); |
mzta | 0:158c61bb030f | 261 | } |
mzta | 0:158c61bb030f | 262 | |
mzta | 0:158c61bb030f | 263 | /* 15.2.9.3.2 */ |
mzta | 0:158c61bb030f | 264 | /* |
mzta | 0:158c61bb030f | 265 | * call-seq: |
mzta | 0:158c61bb030f | 266 | * float - other -> float |
mzta | 0:158c61bb030f | 267 | * |
mzta | 0:158c61bb030f | 268 | * Returns a new float which is the difference of <code>float</code> |
mzta | 0:158c61bb030f | 269 | * and <code>other</code>. |
mzta | 0:158c61bb030f | 270 | */ |
mzta | 0:158c61bb030f | 271 | |
mzta | 0:158c61bb030f | 272 | static mrb_value |
mzta | 0:158c61bb030f | 273 | flo_minus(mrb_state *mrb, mrb_value x) |
mzta | 0:158c61bb030f | 274 | { |
mzta | 0:158c61bb030f | 275 | mrb_value y; |
mzta | 0:158c61bb030f | 276 | |
mzta | 0:158c61bb030f | 277 | mrb_get_args(mrb, "o", &y); |
mzta | 0:158c61bb030f | 278 | return mrb_float_value(mrb, mrb_float(x) - mrb_to_flo(mrb, y)); |
mzta | 0:158c61bb030f | 279 | } |
mzta | 0:158c61bb030f | 280 | |
mzta | 0:158c61bb030f | 281 | /* 15.2.9.3.3 */ |
mzta | 0:158c61bb030f | 282 | /* |
mzta | 0:158c61bb030f | 283 | * call-seq: |
mzta | 0:158c61bb030f | 284 | * float * other -> float |
mzta | 0:158c61bb030f | 285 | * |
mzta | 0:158c61bb030f | 286 | * Returns a new float which is the product of <code>float</code> |
mzta | 0:158c61bb030f | 287 | * and <code>other</code>. |
mzta | 0:158c61bb030f | 288 | */ |
mzta | 0:158c61bb030f | 289 | |
mzta | 0:158c61bb030f | 290 | static mrb_value |
mzta | 0:158c61bb030f | 291 | flo_mul(mrb_state *mrb, mrb_value x) |
mzta | 0:158c61bb030f | 292 | { |
mzta | 0:158c61bb030f | 293 | mrb_value y; |
mzta | 0:158c61bb030f | 294 | |
mzta | 0:158c61bb030f | 295 | mrb_get_args(mrb, "o", &y); |
mzta | 0:158c61bb030f | 296 | return mrb_float_value(mrb, mrb_float(x) * mrb_to_flo(mrb, y)); |
mzta | 0:158c61bb030f | 297 | } |
mzta | 0:158c61bb030f | 298 | |
mzta | 0:158c61bb030f | 299 | static void |
mzta | 0:158c61bb030f | 300 | flodivmod(mrb_state *mrb, mrb_float x, mrb_float y, mrb_float *divp, mrb_float *modp) |
mzta | 0:158c61bb030f | 301 | { |
mzta | 0:158c61bb030f | 302 | mrb_float div; |
mzta | 0:158c61bb030f | 303 | mrb_float mod; |
mzta | 0:158c61bb030f | 304 | |
mzta | 0:158c61bb030f | 305 | if (y == 0.0) { |
mzta | 0:158c61bb030f | 306 | div = INFINITY; |
mzta | 0:158c61bb030f | 307 | mod = NAN; |
mzta | 0:158c61bb030f | 308 | } |
mzta | 0:158c61bb030f | 309 | else { |
mzta | 0:158c61bb030f | 310 | mod = fmod(x, y); |
mzta | 0:158c61bb030f | 311 | if (isinf(x) && isfinite(y)) |
mzta | 0:158c61bb030f | 312 | div = x; |
mzta | 0:158c61bb030f | 313 | else |
mzta | 0:158c61bb030f | 314 | div = (x - mod) / y; |
mzta | 0:158c61bb030f | 315 | if (y*mod < 0) { |
mzta | 0:158c61bb030f | 316 | mod += y; |
mzta | 0:158c61bb030f | 317 | div -= 1.0; |
mzta | 0:158c61bb030f | 318 | } |
mzta | 0:158c61bb030f | 319 | } |
mzta | 0:158c61bb030f | 320 | |
mzta | 0:158c61bb030f | 321 | if (modp) *modp = mod; |
mzta | 0:158c61bb030f | 322 | if (divp) *divp = div; |
mzta | 0:158c61bb030f | 323 | } |
mzta | 0:158c61bb030f | 324 | |
mzta | 0:158c61bb030f | 325 | /* 15.2.9.3.5 */ |
mzta | 0:158c61bb030f | 326 | /* |
mzta | 0:158c61bb030f | 327 | * call-seq: |
mzta | 0:158c61bb030f | 328 | * flt % other -> float |
mzta | 0:158c61bb030f | 329 | * flt.modulo(other) -> float |
mzta | 0:158c61bb030f | 330 | * |
mzta | 0:158c61bb030f | 331 | * Return the modulo after division of <code>flt</code> by <code>other</code>. |
mzta | 0:158c61bb030f | 332 | * |
mzta | 0:158c61bb030f | 333 | * 6543.21.modulo(137) #=> 104.21 |
mzta | 0:158c61bb030f | 334 | * 6543.21.modulo(137.24) #=> 92.9299999999996 |
mzta | 0:158c61bb030f | 335 | */ |
mzta | 0:158c61bb030f | 336 | |
mzta | 0:158c61bb030f | 337 | static mrb_value |
mzta | 0:158c61bb030f | 338 | flo_mod(mrb_state *mrb, mrb_value x) |
mzta | 0:158c61bb030f | 339 | { |
mzta | 0:158c61bb030f | 340 | mrb_value y; |
mzta | 0:158c61bb030f | 341 | mrb_float mod; |
mzta | 0:158c61bb030f | 342 | |
mzta | 0:158c61bb030f | 343 | mrb_get_args(mrb, "o", &y); |
mzta | 0:158c61bb030f | 344 | |
mzta | 0:158c61bb030f | 345 | flodivmod(mrb, mrb_float(x), mrb_to_flo(mrb, y), 0, &mod); |
mzta | 0:158c61bb030f | 346 | return mrb_float_value(mrb, mod); |
mzta | 0:158c61bb030f | 347 | } |
mzta | 0:158c61bb030f | 348 | |
mzta | 0:158c61bb030f | 349 | /* 15.2.8.3.16 */ |
mzta | 0:158c61bb030f | 350 | /* |
mzta | 0:158c61bb030f | 351 | * call-seq: |
mzta | 0:158c61bb030f | 352 | * num.eql?(numeric) -> true or false |
mzta | 0:158c61bb030f | 353 | * |
mzta | 0:158c61bb030f | 354 | * Returns <code>true</code> if <i>num</i> and <i>numeric</i> are the |
mzta | 0:158c61bb030f | 355 | * same type and have equal values. |
mzta | 0:158c61bb030f | 356 | * |
mzta | 0:158c61bb030f | 357 | * 1 == 1.0 #=> true |
mzta | 0:158c61bb030f | 358 | * 1.eql?(1.0) #=> false |
mzta | 0:158c61bb030f | 359 | * (1.0).eql?(1.0) #=> true |
mzta | 0:158c61bb030f | 360 | */ |
mzta | 0:158c61bb030f | 361 | static mrb_value |
mzta | 0:158c61bb030f | 362 | fix_eql(mrb_state *mrb, mrb_value x) |
mzta | 0:158c61bb030f | 363 | { |
mzta | 0:158c61bb030f | 364 | mrb_value y; |
mzta | 0:158c61bb030f | 365 | |
mzta | 0:158c61bb030f | 366 | mrb_get_args(mrb, "o", &y); |
mzta | 0:158c61bb030f | 367 | if (!mrb_fixnum_p(y)) return mrb_false_value(); |
mzta | 0:158c61bb030f | 368 | return mrb_bool_value(mrb_fixnum(x) == mrb_fixnum(y)); |
mzta | 0:158c61bb030f | 369 | } |
mzta | 0:158c61bb030f | 370 | |
mzta | 0:158c61bb030f | 371 | static mrb_value |
mzta | 0:158c61bb030f | 372 | flo_eql(mrb_state *mrb, mrb_value x) |
mzta | 0:158c61bb030f | 373 | { |
mzta | 0:158c61bb030f | 374 | mrb_value y; |
mzta | 0:158c61bb030f | 375 | |
mzta | 0:158c61bb030f | 376 | mrb_get_args(mrb, "o", &y); |
mzta | 0:158c61bb030f | 377 | if (!mrb_float_p(y)) return mrb_false_value(); |
mzta | 0:158c61bb030f | 378 | return mrb_bool_value(mrb_float(x) == (mrb_float)mrb_fixnum(y)); |
mzta | 0:158c61bb030f | 379 | } |
mzta | 0:158c61bb030f | 380 | |
mzta | 0:158c61bb030f | 381 | /* 15.2.9.3.7 */ |
mzta | 0:158c61bb030f | 382 | /* |
mzta | 0:158c61bb030f | 383 | * call-seq: |
mzta | 0:158c61bb030f | 384 | * flt == obj -> true or false |
mzta | 0:158c61bb030f | 385 | * |
mzta | 0:158c61bb030f | 386 | * Returns <code>true</code> only if <i>obj</i> has the same value |
mzta | 0:158c61bb030f | 387 | * as <i>flt</i>. Contrast this with <code>Float#eql?</code>, which |
mzta | 0:158c61bb030f | 388 | * requires <i>obj</i> to be a <code>Float</code>. |
mzta | 0:158c61bb030f | 389 | * |
mzta | 0:158c61bb030f | 390 | * 1.0 == 1 #=> true |
mzta | 0:158c61bb030f | 391 | * |
mzta | 0:158c61bb030f | 392 | */ |
mzta | 0:158c61bb030f | 393 | |
mzta | 0:158c61bb030f | 394 | static mrb_value |
mzta | 0:158c61bb030f | 395 | flo_eq(mrb_state *mrb, mrb_value x) |
mzta | 0:158c61bb030f | 396 | { |
mzta | 0:158c61bb030f | 397 | mrb_value y; |
mzta | 0:158c61bb030f | 398 | mrb_get_args(mrb, "o", &y); |
mzta | 0:158c61bb030f | 399 | |
mzta | 0:158c61bb030f | 400 | switch (mrb_type(y)) { |
mzta | 0:158c61bb030f | 401 | case MRB_TT_FIXNUM: |
mzta | 0:158c61bb030f | 402 | return mrb_bool_value(mrb_float(x) == (mrb_float)mrb_fixnum(y)); |
mzta | 0:158c61bb030f | 403 | case MRB_TT_FLOAT: |
mzta | 0:158c61bb030f | 404 | return mrb_bool_value(mrb_float(x) == mrb_float(y)); |
mzta | 0:158c61bb030f | 405 | default: |
mzta | 0:158c61bb030f | 406 | return mrb_false_value(); |
mzta | 0:158c61bb030f | 407 | } |
mzta | 0:158c61bb030f | 408 | } |
mzta | 0:158c61bb030f | 409 | |
mzta | 0:158c61bb030f | 410 | /* 15.2.8.3.18 */ |
mzta | 0:158c61bb030f | 411 | /* |
mzta | 0:158c61bb030f | 412 | * call-seq: |
mzta | 0:158c61bb030f | 413 | * flt.hash -> integer |
mzta | 0:158c61bb030f | 414 | * |
mzta | 0:158c61bb030f | 415 | * Returns a hash code for this float. |
mzta | 0:158c61bb030f | 416 | */ |
mzta | 0:158c61bb030f | 417 | static mrb_value |
mzta | 0:158c61bb030f | 418 | flo_hash(mrb_state *mrb, mrb_value num) |
mzta | 0:158c61bb030f | 419 | { |
mzta | 0:158c61bb030f | 420 | mrb_float d; |
mzta | 0:158c61bb030f | 421 | char *c; |
mzta | 0:158c61bb030f | 422 | size_t i; |
mzta | 0:158c61bb030f | 423 | int hash; |
mzta | 0:158c61bb030f | 424 | |
mzta | 0:158c61bb030f | 425 | d = (mrb_float)mrb_fixnum(num); |
mzta | 0:158c61bb030f | 426 | /* normalize -0.0 to 0.0 */ |
mzta | 0:158c61bb030f | 427 | if (d == 0) d = 0.0; |
mzta | 0:158c61bb030f | 428 | c = (char*)&d; |
mzta | 0:158c61bb030f | 429 | for (hash=0, i=0; i<sizeof(mrb_float);i++) { |
mzta | 0:158c61bb030f | 430 | hash = (hash * 971) ^ (unsigned char)c[i]; |
mzta | 0:158c61bb030f | 431 | } |
mzta | 0:158c61bb030f | 432 | if (hash < 0) hash = -hash; |
mzta | 0:158c61bb030f | 433 | return mrb_fixnum_value(hash); |
mzta | 0:158c61bb030f | 434 | } |
mzta | 0:158c61bb030f | 435 | |
mzta | 0:158c61bb030f | 436 | /* 15.2.9.3.13 */ |
mzta | 0:158c61bb030f | 437 | /* |
mzta | 0:158c61bb030f | 438 | * call-seq: |
mzta | 0:158c61bb030f | 439 | * flt.to_f -> self |
mzta | 0:158c61bb030f | 440 | * |
mzta | 0:158c61bb030f | 441 | * As <code>flt</code> is already a float, returns +self+. |
mzta | 0:158c61bb030f | 442 | */ |
mzta | 0:158c61bb030f | 443 | |
mzta | 0:158c61bb030f | 444 | static mrb_value |
mzta | 0:158c61bb030f | 445 | flo_to_f(mrb_state *mrb, mrb_value num) |
mzta | 0:158c61bb030f | 446 | { |
mzta | 0:158c61bb030f | 447 | return num; |
mzta | 0:158c61bb030f | 448 | } |
mzta | 0:158c61bb030f | 449 | |
mzta | 0:158c61bb030f | 450 | /* 15.2.9.3.11 */ |
mzta | 0:158c61bb030f | 451 | /* |
mzta | 0:158c61bb030f | 452 | * call-seq: |
mzta | 0:158c61bb030f | 453 | * flt.infinite? -> nil, -1, +1 |
mzta | 0:158c61bb030f | 454 | * |
mzta | 0:158c61bb030f | 455 | * Returns <code>nil</code>, -1, or +1 depending on whether <i>flt</i> |
mzta | 0:158c61bb030f | 456 | * is finite, -infinity, or +infinity. |
mzta | 0:158c61bb030f | 457 | * |
mzta | 0:158c61bb030f | 458 | * (0.0).infinite? #=> nil |
mzta | 0:158c61bb030f | 459 | * (-1.0/0.0).infinite? #=> -1 |
mzta | 0:158c61bb030f | 460 | * (+1.0/0.0).infinite? #=> 1 |
mzta | 0:158c61bb030f | 461 | */ |
mzta | 0:158c61bb030f | 462 | |
mzta | 0:158c61bb030f | 463 | static mrb_value |
mzta | 0:158c61bb030f | 464 | flo_infinite_p(mrb_state *mrb, mrb_value num) |
mzta | 0:158c61bb030f | 465 | { |
mzta | 0:158c61bb030f | 466 | mrb_float value = mrb_float(num); |
mzta | 0:158c61bb030f | 467 | |
mzta | 0:158c61bb030f | 468 | if (isinf(value)) { |
mzta | 0:158c61bb030f | 469 | return mrb_fixnum_value(value < 0 ? -1 : 1); |
mzta | 0:158c61bb030f | 470 | } |
mzta | 0:158c61bb030f | 471 | return mrb_nil_value(); |
mzta | 0:158c61bb030f | 472 | } |
mzta | 0:158c61bb030f | 473 | |
mzta | 0:158c61bb030f | 474 | /* 15.2.9.3.9 */ |
mzta | 0:158c61bb030f | 475 | /* |
mzta | 0:158c61bb030f | 476 | * call-seq: |
mzta | 0:158c61bb030f | 477 | * flt.finite? -> true or false |
mzta | 0:158c61bb030f | 478 | * |
mzta | 0:158c61bb030f | 479 | * Returns <code>true</code> if <i>flt</i> is a valid IEEE floating |
mzta | 0:158c61bb030f | 480 | * point number (it is not infinite, and <code>nan?</code> is |
mzta | 0:158c61bb030f | 481 | * <code>false</code>). |
mzta | 0:158c61bb030f | 482 | * |
mzta | 0:158c61bb030f | 483 | */ |
mzta | 0:158c61bb030f | 484 | |
mzta | 0:158c61bb030f | 485 | static mrb_value |
mzta | 0:158c61bb030f | 486 | flo_finite_p(mrb_state *mrb, mrb_value num) |
mzta | 0:158c61bb030f | 487 | { |
mzta | 0:158c61bb030f | 488 | return mrb_bool_value(isfinite(mrb_float(num))); |
mzta | 0:158c61bb030f | 489 | } |
mzta | 0:158c61bb030f | 490 | |
mzta | 0:158c61bb030f | 491 | /* 15.2.9.3.10 */ |
mzta | 0:158c61bb030f | 492 | /* |
mzta | 0:158c61bb030f | 493 | * call-seq: |
mzta | 0:158c61bb030f | 494 | * flt.floor -> integer |
mzta | 0:158c61bb030f | 495 | * |
mzta | 0:158c61bb030f | 496 | * Returns the largest integer less than or equal to <i>flt</i>. |
mzta | 0:158c61bb030f | 497 | * |
mzta | 0:158c61bb030f | 498 | * 1.2.floor #=> 1 |
mzta | 0:158c61bb030f | 499 | * 2.0.floor #=> 2 |
mzta | 0:158c61bb030f | 500 | * (-1.2).floor #=> -2 |
mzta | 0:158c61bb030f | 501 | * (-2.0).floor #=> -2 |
mzta | 0:158c61bb030f | 502 | */ |
mzta | 0:158c61bb030f | 503 | |
mzta | 0:158c61bb030f | 504 | static mrb_value |
mzta | 0:158c61bb030f | 505 | flo_floor(mrb_state *mrb, mrb_value num) |
mzta | 0:158c61bb030f | 506 | { |
mzta | 0:158c61bb030f | 507 | mrb_float f = floor(mrb_float(num)); |
mzta | 0:158c61bb030f | 508 | |
mzta | 0:158c61bb030f | 509 | if (!FIXABLE(f)) { |
mzta | 0:158c61bb030f | 510 | return mrb_float_value(mrb, f); |
mzta | 0:158c61bb030f | 511 | } |
mzta | 0:158c61bb030f | 512 | return mrb_fixnum_value((mrb_int)f); |
mzta | 0:158c61bb030f | 513 | } |
mzta | 0:158c61bb030f | 514 | |
mzta | 0:158c61bb030f | 515 | /* 15.2.9.3.8 */ |
mzta | 0:158c61bb030f | 516 | /* |
mzta | 0:158c61bb030f | 517 | * call-seq: |
mzta | 0:158c61bb030f | 518 | * flt.ceil -> integer |
mzta | 0:158c61bb030f | 519 | * |
mzta | 0:158c61bb030f | 520 | * Returns the smallest <code>Integer</code> greater than or equal to |
mzta | 0:158c61bb030f | 521 | * <i>flt</i>. |
mzta | 0:158c61bb030f | 522 | * |
mzta | 0:158c61bb030f | 523 | * 1.2.ceil #=> 2 |
mzta | 0:158c61bb030f | 524 | * 2.0.ceil #=> 2 |
mzta | 0:158c61bb030f | 525 | * (-1.2).ceil #=> -1 |
mzta | 0:158c61bb030f | 526 | * (-2.0).ceil #=> -2 |
mzta | 0:158c61bb030f | 527 | */ |
mzta | 0:158c61bb030f | 528 | |
mzta | 0:158c61bb030f | 529 | static mrb_value |
mzta | 0:158c61bb030f | 530 | flo_ceil(mrb_state *mrb, mrb_value num) |
mzta | 0:158c61bb030f | 531 | { |
mzta | 0:158c61bb030f | 532 | mrb_float f = ceil(mrb_float(num)); |
mzta | 0:158c61bb030f | 533 | |
mzta | 0:158c61bb030f | 534 | if (!FIXABLE(f)) { |
mzta | 0:158c61bb030f | 535 | return mrb_float_value(mrb, f); |
mzta | 0:158c61bb030f | 536 | } |
mzta | 0:158c61bb030f | 537 | return mrb_fixnum_value((mrb_int)f); |
mzta | 0:158c61bb030f | 538 | } |
mzta | 0:158c61bb030f | 539 | |
mzta | 0:158c61bb030f | 540 | /* 15.2.9.3.12 */ |
mzta | 0:158c61bb030f | 541 | /* |
mzta | 0:158c61bb030f | 542 | * call-seq: |
mzta | 0:158c61bb030f | 543 | * flt.round([ndigits]) -> integer or float |
mzta | 0:158c61bb030f | 544 | * |
mzta | 0:158c61bb030f | 545 | * Rounds <i>flt</i> to a given precision in decimal digits (default 0 digits). |
mzta | 0:158c61bb030f | 546 | * Precision may be negative. Returns a floating point number when ndigits |
mzta | 0:158c61bb030f | 547 | * is more than zero. |
mzta | 0:158c61bb030f | 548 | * |
mzta | 0:158c61bb030f | 549 | * 1.4.round #=> 1 |
mzta | 0:158c61bb030f | 550 | * 1.5.round #=> 2 |
mzta | 0:158c61bb030f | 551 | * 1.6.round #=> 2 |
mzta | 0:158c61bb030f | 552 | * (-1.5).round #=> -2 |
mzta | 0:158c61bb030f | 553 | * |
mzta | 0:158c61bb030f | 554 | * 1.234567.round(2) #=> 1.23 |
mzta | 0:158c61bb030f | 555 | * 1.234567.round(3) #=> 1.235 |
mzta | 0:158c61bb030f | 556 | * 1.234567.round(4) #=> 1.2346 |
mzta | 0:158c61bb030f | 557 | * 1.234567.round(5) #=> 1.23457 |
mzta | 0:158c61bb030f | 558 | * |
mzta | 0:158c61bb030f | 559 | * 34567.89.round(-5) #=> 0 |
mzta | 0:158c61bb030f | 560 | * 34567.89.round(-4) #=> 30000 |
mzta | 0:158c61bb030f | 561 | * 34567.89.round(-3) #=> 35000 |
mzta | 0:158c61bb030f | 562 | * 34567.89.round(-2) #=> 34600 |
mzta | 0:158c61bb030f | 563 | * 34567.89.round(-1) #=> 34570 |
mzta | 0:158c61bb030f | 564 | * 34567.89.round(0) #=> 34568 |
mzta | 0:158c61bb030f | 565 | * 34567.89.round(1) #=> 34567.9 |
mzta | 0:158c61bb030f | 566 | * 34567.89.round(2) #=> 34567.89 |
mzta | 0:158c61bb030f | 567 | * 34567.89.round(3) #=> 34567.89 |
mzta | 0:158c61bb030f | 568 | * |
mzta | 0:158c61bb030f | 569 | */ |
mzta | 0:158c61bb030f | 570 | |
mzta | 0:158c61bb030f | 571 | static mrb_value |
mzta | 0:158c61bb030f | 572 | flo_round(mrb_state *mrb, mrb_value num) |
mzta | 0:158c61bb030f | 573 | { |
mzta | 0:158c61bb030f | 574 | double number, f; |
mzta | 0:158c61bb030f | 575 | mrb_int ndigits = 0; |
mzta | 0:158c61bb030f | 576 | int i; |
mzta | 0:158c61bb030f | 577 | |
mzta | 0:158c61bb030f | 578 | mrb_get_args(mrb, "|i", &ndigits); |
mzta | 0:158c61bb030f | 579 | number = mrb_float(num); |
mzta | 0:158c61bb030f | 580 | |
mzta | 0:158c61bb030f | 581 | if (isinf(number)) { |
mzta | 0:158c61bb030f | 582 | if (0 < ndigits) return num; |
mzta | 0:158c61bb030f | 583 | else mrb_raise(mrb, E_FLOATDOMAIN_ERROR, number < 0 ? "-Infinity" : "Infinity"); |
mzta | 0:158c61bb030f | 584 | } |
mzta | 0:158c61bb030f | 585 | if (isnan(number)) { |
mzta | 0:158c61bb030f | 586 | if (0 < ndigits) return num; |
mzta | 0:158c61bb030f | 587 | else mrb_raise(mrb, E_FLOATDOMAIN_ERROR, "NaN"); |
mzta | 0:158c61bb030f | 588 | } |
mzta | 0:158c61bb030f | 589 | |
mzta | 0:158c61bb030f | 590 | f = 1.0; |
mzta | 0:158c61bb030f | 591 | i = abs(ndigits); |
mzta | 0:158c61bb030f | 592 | while (--i >= 0) |
mzta | 0:158c61bb030f | 593 | f = f*10.0; |
mzta | 0:158c61bb030f | 594 | |
mzta | 0:158c61bb030f | 595 | if (isinf(f)) { |
mzta | 0:158c61bb030f | 596 | if (ndigits < 0) number = 0; |
mzta | 0:158c61bb030f | 597 | } |
mzta | 0:158c61bb030f | 598 | else { |
mzta | 0:158c61bb030f | 599 | double d; |
mzta | 0:158c61bb030f | 600 | |
mzta | 0:158c61bb030f | 601 | if (ndigits < 0) number /= f; |
mzta | 0:158c61bb030f | 602 | else number *= f; |
mzta | 0:158c61bb030f | 603 | |
mzta | 0:158c61bb030f | 604 | /* home-made inline implementation of round(3) */ |
mzta | 0:158c61bb030f | 605 | if (number > 0.0) { |
mzta | 0:158c61bb030f | 606 | d = floor(number); |
mzta | 0:158c61bb030f | 607 | number = d + (number - d >= 0.5); |
mzta | 0:158c61bb030f | 608 | } |
mzta | 0:158c61bb030f | 609 | else if (number < 0.0) { |
mzta | 0:158c61bb030f | 610 | d = ceil(number); |
mzta | 0:158c61bb030f | 611 | number = d - (d - number >= 0.5); |
mzta | 0:158c61bb030f | 612 | } |
mzta | 0:158c61bb030f | 613 | |
mzta | 0:158c61bb030f | 614 | if (ndigits < 0) number *= f; |
mzta | 0:158c61bb030f | 615 | else number /= f; |
mzta | 0:158c61bb030f | 616 | } |
mzta | 0:158c61bb030f | 617 | |
mzta | 0:158c61bb030f | 618 | if (ndigits > 0) { |
mzta | 0:158c61bb030f | 619 | if (!isfinite(number)) return num; |
mzta | 0:158c61bb030f | 620 | return mrb_float_value(mrb, number); |
mzta | 0:158c61bb030f | 621 | } |
mzta | 0:158c61bb030f | 622 | return mrb_fixnum_value((mrb_int)number); |
mzta | 0:158c61bb030f | 623 | } |
mzta | 0:158c61bb030f | 624 | |
mzta | 0:158c61bb030f | 625 | /* 15.2.9.3.14 */ |
mzta | 0:158c61bb030f | 626 | /* 15.2.9.3.15 */ |
mzta | 0:158c61bb030f | 627 | /* |
mzta | 0:158c61bb030f | 628 | * call-seq: |
mzta | 0:158c61bb030f | 629 | * flt.to_i -> integer |
mzta | 0:158c61bb030f | 630 | * flt.to_int -> integer |
mzta | 0:158c61bb030f | 631 | * flt.truncate -> integer |
mzta | 0:158c61bb030f | 632 | * |
mzta | 0:158c61bb030f | 633 | * Returns <i>flt</i> truncated to an <code>Integer</code>. |
mzta | 0:158c61bb030f | 634 | */ |
mzta | 0:158c61bb030f | 635 | |
mzta | 0:158c61bb030f | 636 | static mrb_value |
mzta | 0:158c61bb030f | 637 | flo_truncate(mrb_state *mrb, mrb_value num) |
mzta | 0:158c61bb030f | 638 | { |
mzta | 0:158c61bb030f | 639 | mrb_float f = mrb_float(num); |
mzta | 0:158c61bb030f | 640 | |
mzta | 0:158c61bb030f | 641 | if (f > 0.0) f = floor(f); |
mzta | 0:158c61bb030f | 642 | if (f < 0.0) f = ceil(f); |
mzta | 0:158c61bb030f | 643 | |
mzta | 0:158c61bb030f | 644 | if (!FIXABLE(f)) { |
mzta | 0:158c61bb030f | 645 | return mrb_float_value(mrb, f); |
mzta | 0:158c61bb030f | 646 | } |
mzta | 0:158c61bb030f | 647 | return mrb_fixnum_value((mrb_int)f); |
mzta | 0:158c61bb030f | 648 | } |
mzta | 0:158c61bb030f | 649 | |
mzta | 0:158c61bb030f | 650 | static mrb_value |
mzta | 0:158c61bb030f | 651 | flo_nan_p(mrb_state *mrb, mrb_value num) |
mzta | 0:158c61bb030f | 652 | { |
mzta | 0:158c61bb030f | 653 | return mrb_bool_value(isnan(mrb_float(num))); |
mzta | 0:158c61bb030f | 654 | } |
mzta | 0:158c61bb030f | 655 | |
mzta | 0:158c61bb030f | 656 | /* |
mzta | 0:158c61bb030f | 657 | * Document-class: Integer |
mzta | 0:158c61bb030f | 658 | * |
mzta | 0:158c61bb030f | 659 | * <code>Integer</code> is the basis for the two concrete classes that |
mzta | 0:158c61bb030f | 660 | * hold whole numbers, <code>Bignum</code> and <code>Fixnum</code>. |
mzta | 0:158c61bb030f | 661 | * |
mzta | 0:158c61bb030f | 662 | */ |
mzta | 0:158c61bb030f | 663 | |
mzta | 0:158c61bb030f | 664 | |
mzta | 0:158c61bb030f | 665 | /* |
mzta | 0:158c61bb030f | 666 | * call-seq: |
mzta | 0:158c61bb030f | 667 | * int.to_i -> integer |
mzta | 0:158c61bb030f | 668 | * int.to_int -> integer |
mzta | 0:158c61bb030f | 669 | * |
mzta | 0:158c61bb030f | 670 | * As <i>int</i> is already an <code>Integer</code>, all these |
mzta | 0:158c61bb030f | 671 | * methods simply return the receiver. |
mzta | 0:158c61bb030f | 672 | */ |
mzta | 0:158c61bb030f | 673 | |
mzta | 0:158c61bb030f | 674 | static mrb_value |
mzta | 0:158c61bb030f | 675 | int_to_i(mrb_state *mrb, mrb_value num) |
mzta | 0:158c61bb030f | 676 | { |
mzta | 0:158c61bb030f | 677 | return num; |
mzta | 0:158c61bb030f | 678 | } |
mzta | 0:158c61bb030f | 679 | |
mzta | 0:158c61bb030f | 680 | /*tests if N*N would overflow*/ |
mzta | 0:158c61bb030f | 681 | #define SQRT_INT_MAX ((mrb_int)1<<((MRB_INT_BIT-1-MRB_FIXNUM_SHIFT)/2)) |
mzta | 0:158c61bb030f | 682 | #define FIT_SQRT_INT(n) (((n)<SQRT_INT_MAX)&&((n)>=-SQRT_INT_MAX)) |
mzta | 0:158c61bb030f | 683 | |
mzta | 0:158c61bb030f | 684 | mrb_value |
mzta | 0:158c61bb030f | 685 | mrb_fixnum_mul(mrb_state *mrb, mrb_value x, mrb_value y) |
mzta | 0:158c61bb030f | 686 | { |
mzta | 0:158c61bb030f | 687 | mrb_int a; |
mzta | 0:158c61bb030f | 688 | |
mzta | 0:158c61bb030f | 689 | a = mrb_fixnum(x); |
mzta | 0:158c61bb030f | 690 | if (mrb_fixnum_p(y)) { |
mzta | 0:158c61bb030f | 691 | mrb_float c; |
mzta | 0:158c61bb030f | 692 | mrb_int b; |
mzta | 0:158c61bb030f | 693 | |
mzta | 0:158c61bb030f | 694 | if (a == 0) return x; |
mzta | 0:158c61bb030f | 695 | b = mrb_fixnum(y); |
mzta | 0:158c61bb030f | 696 | if (FIT_SQRT_INT(a) && FIT_SQRT_INT(b)) |
mzta | 0:158c61bb030f | 697 | return mrb_fixnum_value(a*b); |
mzta | 0:158c61bb030f | 698 | c = a * b; |
mzta | 0:158c61bb030f | 699 | if ((a != 0 && c/a != b) || !FIXABLE(c)) { |
mzta | 0:158c61bb030f | 700 | return mrb_float_value(mrb, (mrb_float)a*(mrb_float)b); |
mzta | 0:158c61bb030f | 701 | } |
mzta | 0:158c61bb030f | 702 | return mrb_fixnum_value((mrb_int)c); |
mzta | 0:158c61bb030f | 703 | } |
mzta | 0:158c61bb030f | 704 | return mrb_float_value(mrb, (mrb_float)a * mrb_to_flo(mrb, y)); |
mzta | 0:158c61bb030f | 705 | } |
mzta | 0:158c61bb030f | 706 | |
mzta | 0:158c61bb030f | 707 | /* 15.2.8.3.3 */ |
mzta | 0:158c61bb030f | 708 | /* |
mzta | 0:158c61bb030f | 709 | * call-seq: |
mzta | 0:158c61bb030f | 710 | * fix * numeric -> numeric_result |
mzta | 0:158c61bb030f | 711 | * |
mzta | 0:158c61bb030f | 712 | * Performs multiplication: the class of the resulting object depends on |
mzta | 0:158c61bb030f | 713 | * the class of <code>numeric</code> and on the magnitude of the |
mzta | 0:158c61bb030f | 714 | * result. |
mzta | 0:158c61bb030f | 715 | */ |
mzta | 0:158c61bb030f | 716 | |
mzta | 0:158c61bb030f | 717 | static mrb_value |
mzta | 0:158c61bb030f | 718 | fix_mul(mrb_state *mrb, mrb_value x) |
mzta | 0:158c61bb030f | 719 | { |
mzta | 0:158c61bb030f | 720 | mrb_value y; |
mzta | 0:158c61bb030f | 721 | |
mzta | 0:158c61bb030f | 722 | mrb_get_args(mrb, "o", &y); |
mzta | 0:158c61bb030f | 723 | return mrb_fixnum_mul(mrb, x, y); |
mzta | 0:158c61bb030f | 724 | } |
mzta | 0:158c61bb030f | 725 | |
mzta | 0:158c61bb030f | 726 | static void |
mzta | 0:158c61bb030f | 727 | fixdivmod(mrb_state *mrb, mrb_int x, mrb_int y, mrb_int *divp, mrb_int *modp) |
mzta | 0:158c61bb030f | 728 | { |
mzta | 0:158c61bb030f | 729 | mrb_int div, mod; |
mzta | 0:158c61bb030f | 730 | |
mzta | 0:158c61bb030f | 731 | /* TODO: add mrb_assert(y != 0) to make sure */ |
mzta | 0:158c61bb030f | 732 | |
mzta | 0:158c61bb030f | 733 | if (y < 0) { |
mzta | 0:158c61bb030f | 734 | if (x < 0) |
mzta | 0:158c61bb030f | 735 | div = -x / -y; |
mzta | 0:158c61bb030f | 736 | else |
mzta | 0:158c61bb030f | 737 | div = - (x / -y); |
mzta | 0:158c61bb030f | 738 | } |
mzta | 0:158c61bb030f | 739 | else { |
mzta | 0:158c61bb030f | 740 | if (x < 0) |
mzta | 0:158c61bb030f | 741 | div = - (-x / y); |
mzta | 0:158c61bb030f | 742 | else |
mzta | 0:158c61bb030f | 743 | div = x / y; |
mzta | 0:158c61bb030f | 744 | } |
mzta | 0:158c61bb030f | 745 | mod = x - div*y; |
mzta | 0:158c61bb030f | 746 | if ((mod < 0 && y > 0) || (mod > 0 && y < 0)) { |
mzta | 0:158c61bb030f | 747 | mod += y; |
mzta | 0:158c61bb030f | 748 | div -= 1; |
mzta | 0:158c61bb030f | 749 | } |
mzta | 0:158c61bb030f | 750 | if (divp) *divp = div; |
mzta | 0:158c61bb030f | 751 | if (modp) *modp = mod; |
mzta | 0:158c61bb030f | 752 | } |
mzta | 0:158c61bb030f | 753 | |
mzta | 0:158c61bb030f | 754 | /* 15.2.8.3.5 */ |
mzta | 0:158c61bb030f | 755 | /* |
mzta | 0:158c61bb030f | 756 | * call-seq: |
mzta | 0:158c61bb030f | 757 | * fix % other -> real |
mzta | 0:158c61bb030f | 758 | * fix.modulo(other) -> real |
mzta | 0:158c61bb030f | 759 | * |
mzta | 0:158c61bb030f | 760 | * Returns <code>fix</code> modulo <code>other</code>. |
mzta | 0:158c61bb030f | 761 | * See <code>numeric.divmod</code> for more information. |
mzta | 0:158c61bb030f | 762 | */ |
mzta | 0:158c61bb030f | 763 | |
mzta | 0:158c61bb030f | 764 | static mrb_value |
mzta | 0:158c61bb030f | 765 | fix_mod(mrb_state *mrb, mrb_value x) |
mzta | 0:158c61bb030f | 766 | { |
mzta | 0:158c61bb030f | 767 | mrb_value y; |
mzta | 0:158c61bb030f | 768 | mrb_int a; |
mzta | 0:158c61bb030f | 769 | |
mzta | 0:158c61bb030f | 770 | mrb_get_args(mrb, "o", &y); |
mzta | 0:158c61bb030f | 771 | a = mrb_fixnum(x); |
mzta | 0:158c61bb030f | 772 | if (mrb_fixnum_p(y)) { |
mzta | 0:158c61bb030f | 773 | mrb_int b, mod; |
mzta | 0:158c61bb030f | 774 | |
mzta | 0:158c61bb030f | 775 | if ((b=mrb_fixnum(y)) == 0) { |
mzta | 0:158c61bb030f | 776 | return mrb_float_value(mrb, NAN); |
mzta | 0:158c61bb030f | 777 | } |
mzta | 0:158c61bb030f | 778 | fixdivmod(mrb, a, b, 0, &mod); |
mzta | 0:158c61bb030f | 779 | return mrb_fixnum_value(mod); |
mzta | 0:158c61bb030f | 780 | } |
mzta | 0:158c61bb030f | 781 | else { |
mzta | 0:158c61bb030f | 782 | mrb_float mod; |
mzta | 0:158c61bb030f | 783 | |
mzta | 0:158c61bb030f | 784 | flodivmod(mrb, (mrb_float)a, mrb_to_flo(mrb, y), 0, &mod); |
mzta | 0:158c61bb030f | 785 | return mrb_float_value(mrb, mod); |
mzta | 0:158c61bb030f | 786 | } |
mzta | 0:158c61bb030f | 787 | } |
mzta | 0:158c61bb030f | 788 | |
mzta | 0:158c61bb030f | 789 | /* |
mzta | 0:158c61bb030f | 790 | * call-seq: |
mzta | 0:158c61bb030f | 791 | * fix.divmod(numeric) -> array |
mzta | 0:158c61bb030f | 792 | * |
mzta | 0:158c61bb030f | 793 | * See <code>Numeric#divmod</code>. |
mzta | 0:158c61bb030f | 794 | */ |
mzta | 0:158c61bb030f | 795 | static mrb_value |
mzta | 0:158c61bb030f | 796 | fix_divmod(mrb_state *mrb, mrb_value x) |
mzta | 0:158c61bb030f | 797 | { |
mzta | 0:158c61bb030f | 798 | mrb_value y; |
mzta | 0:158c61bb030f | 799 | |
mzta | 0:158c61bb030f | 800 | mrb_get_args(mrb, "o", &y); |
mzta | 0:158c61bb030f | 801 | |
mzta | 0:158c61bb030f | 802 | if (mrb_fixnum_p(y)) { |
mzta | 0:158c61bb030f | 803 | mrb_int div, mod; |
mzta | 0:158c61bb030f | 804 | |
mzta | 0:158c61bb030f | 805 | if (mrb_fixnum(y) == 0) { |
mzta | 0:158c61bb030f | 806 | return mrb_assoc_new(mrb, mrb_float_value(mrb, INFINITY), |
mzta | 0:158c61bb030f | 807 | mrb_float_value(mrb, NAN)); |
mzta | 0:158c61bb030f | 808 | } |
mzta | 0:158c61bb030f | 809 | fixdivmod(mrb, mrb_fixnum(x), mrb_fixnum(y), &div, &mod); |
mzta | 0:158c61bb030f | 810 | return mrb_assoc_new(mrb, mrb_fixnum_value(div), mrb_fixnum_value(mod)); |
mzta | 0:158c61bb030f | 811 | } |
mzta | 0:158c61bb030f | 812 | else { |
mzta | 0:158c61bb030f | 813 | mrb_float div, mod; |
mzta | 0:158c61bb030f | 814 | mrb_value a, b; |
mzta | 0:158c61bb030f | 815 | |
mzta | 0:158c61bb030f | 816 | flodivmod(mrb, (mrb_float)mrb_fixnum(x), mrb_to_flo(mrb, y), &div, &mod); |
mzta | 0:158c61bb030f | 817 | a = mrb_float_value(mrb, (mrb_int)div); |
mzta | 0:158c61bb030f | 818 | b = mrb_float_value(mrb, mod); |
mzta | 0:158c61bb030f | 819 | return mrb_assoc_new(mrb, a, b); |
mzta | 0:158c61bb030f | 820 | } |
mzta | 0:158c61bb030f | 821 | } |
mzta | 0:158c61bb030f | 822 | |
mzta | 0:158c61bb030f | 823 | static mrb_value |
mzta | 0:158c61bb030f | 824 | flo_divmod(mrb_state *mrb, mrb_value x) |
mzta | 0:158c61bb030f | 825 | { |
mzta | 0:158c61bb030f | 826 | mrb_value y; |
mzta | 0:158c61bb030f | 827 | mrb_float div, mod; |
mzta | 0:158c61bb030f | 828 | mrb_value a, b; |
mzta | 0:158c61bb030f | 829 | |
mzta | 0:158c61bb030f | 830 | mrb_get_args(mrb, "o", &y); |
mzta | 0:158c61bb030f | 831 | |
mzta | 0:158c61bb030f | 832 | flodivmod(mrb, mrb_float(x), mrb_to_flo(mrb, y), &div, &mod); |
mzta | 0:158c61bb030f | 833 | a = mrb_float_value(mrb, (mrb_int)div); |
mzta | 0:158c61bb030f | 834 | b = mrb_float_value(mrb, mod); |
mzta | 0:158c61bb030f | 835 | return mrb_assoc_new(mrb, a, b); |
mzta | 0:158c61bb030f | 836 | } |
mzta | 0:158c61bb030f | 837 | |
mzta | 0:158c61bb030f | 838 | /* 15.2.8.3.7 */ |
mzta | 0:158c61bb030f | 839 | /* |
mzta | 0:158c61bb030f | 840 | * call-seq: |
mzta | 0:158c61bb030f | 841 | * fix == other -> true or false |
mzta | 0:158c61bb030f | 842 | * |
mzta | 0:158c61bb030f | 843 | * Return <code>true</code> if <code>fix</code> equals <code>other</code> |
mzta | 0:158c61bb030f | 844 | * numerically. |
mzta | 0:158c61bb030f | 845 | * |
mzta | 0:158c61bb030f | 846 | * 1 == 2 #=> false |
mzta | 0:158c61bb030f | 847 | * 1 == 1.0 #=> true |
mzta | 0:158c61bb030f | 848 | */ |
mzta | 0:158c61bb030f | 849 | |
mzta | 0:158c61bb030f | 850 | static mrb_value |
mzta | 0:158c61bb030f | 851 | fix_equal(mrb_state *mrb, mrb_value x) |
mzta | 0:158c61bb030f | 852 | { |
mzta | 0:158c61bb030f | 853 | mrb_value y; |
mzta | 0:158c61bb030f | 854 | |
mzta | 0:158c61bb030f | 855 | mrb_get_args(mrb, "o", &y); |
mzta | 0:158c61bb030f | 856 | switch (mrb_type(y)) { |
mzta | 0:158c61bb030f | 857 | case MRB_TT_FIXNUM: |
mzta | 0:158c61bb030f | 858 | return mrb_bool_value(mrb_fixnum(x) == mrb_fixnum(y)); |
mzta | 0:158c61bb030f | 859 | case MRB_TT_FLOAT: |
mzta | 0:158c61bb030f | 860 | return mrb_bool_value((mrb_float)mrb_fixnum(x) == mrb_float(y)); |
mzta | 0:158c61bb030f | 861 | default: |
mzta | 0:158c61bb030f | 862 | return mrb_false_value(); |
mzta | 0:158c61bb030f | 863 | } |
mzta | 0:158c61bb030f | 864 | } |
mzta | 0:158c61bb030f | 865 | |
mzta | 0:158c61bb030f | 866 | /* 15.2.8.3.8 */ |
mzta | 0:158c61bb030f | 867 | /* |
mzta | 0:158c61bb030f | 868 | * call-seq: |
mzta | 0:158c61bb030f | 869 | * ~fix -> integer |
mzta | 0:158c61bb030f | 870 | * |
mzta | 0:158c61bb030f | 871 | * One's complement: returns a number where each bit is flipped. |
mzta | 0:158c61bb030f | 872 | * ex.0---00001 (1)-> 1---11110 (-2) |
mzta | 0:158c61bb030f | 873 | * ex.0---00010 (2)-> 1---11101 (-3) |
mzta | 0:158c61bb030f | 874 | * ex.0---00100 (4)-> 1---11011 (-5) |
mzta | 0:158c61bb030f | 875 | */ |
mzta | 0:158c61bb030f | 876 | |
mzta | 0:158c61bb030f | 877 | static mrb_value |
mzta | 0:158c61bb030f | 878 | fix_rev(mrb_state *mrb, mrb_value num) |
mzta | 0:158c61bb030f | 879 | { |
mzta | 0:158c61bb030f | 880 | mrb_int val = mrb_fixnum(num); |
mzta | 0:158c61bb030f | 881 | |
mzta | 0:158c61bb030f | 882 | return mrb_fixnum_value(~val); |
mzta | 0:158c61bb030f | 883 | } |
mzta | 0:158c61bb030f | 884 | |
mzta | 0:158c61bb030f | 885 | static mrb_value |
mzta | 0:158c61bb030f | 886 | bit_coerce(mrb_state *mrb, mrb_value x) |
mzta | 0:158c61bb030f | 887 | { |
mzta | 0:158c61bb030f | 888 | while (!mrb_fixnum_p(x)) { |
mzta | 0:158c61bb030f | 889 | if (mrb_float_p(x)) { |
mzta | 0:158c61bb030f | 890 | mrb_raise(mrb, E_TYPE_ERROR, "can't convert Float into Integer"); |
mzta | 0:158c61bb030f | 891 | } |
mzta | 0:158c61bb030f | 892 | x = mrb_to_int(mrb, x); |
mzta | 0:158c61bb030f | 893 | } |
mzta | 0:158c61bb030f | 894 | return x; |
mzta | 0:158c61bb030f | 895 | } |
mzta | 0:158c61bb030f | 896 | |
mzta | 0:158c61bb030f | 897 | /* 15.2.8.3.9 */ |
mzta | 0:158c61bb030f | 898 | /* |
mzta | 0:158c61bb030f | 899 | * call-seq: |
mzta | 0:158c61bb030f | 900 | * fix & integer -> integer_result |
mzta | 0:158c61bb030f | 901 | * |
mzta | 0:158c61bb030f | 902 | * Bitwise AND. |
mzta | 0:158c61bb030f | 903 | */ |
mzta | 0:158c61bb030f | 904 | |
mzta | 0:158c61bb030f | 905 | static mrb_value |
mzta | 0:158c61bb030f | 906 | fix_and(mrb_state *mrb, mrb_value x) |
mzta | 0:158c61bb030f | 907 | { |
mzta | 0:158c61bb030f | 908 | mrb_value y; |
mzta | 0:158c61bb030f | 909 | |
mzta | 0:158c61bb030f | 910 | mrb_get_args(mrb, "o", &y); |
mzta | 0:158c61bb030f | 911 | |
mzta | 0:158c61bb030f | 912 | y = bit_coerce(mrb, y); |
mzta | 0:158c61bb030f | 913 | return mrb_fixnum_value(mrb_fixnum(x) & mrb_fixnum(y)); |
mzta | 0:158c61bb030f | 914 | } |
mzta | 0:158c61bb030f | 915 | |
mzta | 0:158c61bb030f | 916 | /* 15.2.8.3.10 */ |
mzta | 0:158c61bb030f | 917 | /* |
mzta | 0:158c61bb030f | 918 | * call-seq: |
mzta | 0:158c61bb030f | 919 | * fix | integer -> integer_result |
mzta | 0:158c61bb030f | 920 | * |
mzta | 0:158c61bb030f | 921 | * Bitwise OR. |
mzta | 0:158c61bb030f | 922 | */ |
mzta | 0:158c61bb030f | 923 | |
mzta | 0:158c61bb030f | 924 | static mrb_value |
mzta | 0:158c61bb030f | 925 | fix_or(mrb_state *mrb, mrb_value x) |
mzta | 0:158c61bb030f | 926 | { |
mzta | 0:158c61bb030f | 927 | mrb_value y; |
mzta | 0:158c61bb030f | 928 | |
mzta | 0:158c61bb030f | 929 | mrb_get_args(mrb, "o", &y); |
mzta | 0:158c61bb030f | 930 | |
mzta | 0:158c61bb030f | 931 | y = bit_coerce(mrb, y); |
mzta | 0:158c61bb030f | 932 | return mrb_fixnum_value(mrb_fixnum(x) | mrb_fixnum(y)); |
mzta | 0:158c61bb030f | 933 | } |
mzta | 0:158c61bb030f | 934 | |
mzta | 0:158c61bb030f | 935 | /* 15.2.8.3.11 */ |
mzta | 0:158c61bb030f | 936 | /* |
mzta | 0:158c61bb030f | 937 | * call-seq: |
mzta | 0:158c61bb030f | 938 | * fix ^ integer -> integer_result |
mzta | 0:158c61bb030f | 939 | * |
mzta | 0:158c61bb030f | 940 | * Bitwise EXCLUSIVE OR. |
mzta | 0:158c61bb030f | 941 | */ |
mzta | 0:158c61bb030f | 942 | |
mzta | 0:158c61bb030f | 943 | static mrb_value |
mzta | 0:158c61bb030f | 944 | fix_xor(mrb_state *mrb, mrb_value x) |
mzta | 0:158c61bb030f | 945 | { |
mzta | 0:158c61bb030f | 946 | mrb_value y; |
mzta | 0:158c61bb030f | 947 | |
mzta | 0:158c61bb030f | 948 | mrb_get_args(mrb, "o", &y); |
mzta | 0:158c61bb030f | 949 | |
mzta | 0:158c61bb030f | 950 | y = bit_coerce(mrb, y); |
mzta | 0:158c61bb030f | 951 | return mrb_fixnum_value(mrb_fixnum(x) ^ mrb_fixnum(y)); |
mzta | 0:158c61bb030f | 952 | } |
mzta | 0:158c61bb030f | 953 | |
mzta | 0:158c61bb030f | 954 | #define NUMERIC_SHIFT_WIDTH_MAX (MRB_INT_BIT-1) |
mzta | 0:158c61bb030f | 955 | |
mzta | 0:158c61bb030f | 956 | static mrb_value |
mzta | 0:158c61bb030f | 957 | lshift(mrb_state *mrb, mrb_int val, mrb_int width) |
mzta | 0:158c61bb030f | 958 | { |
mzta | 0:158c61bb030f | 959 | mrb_assert(width >= 0); |
mzta | 0:158c61bb030f | 960 | if (width > NUMERIC_SHIFT_WIDTH_MAX) { |
mzta | 0:158c61bb030f | 961 | mrb_raisef(mrb, E_RANGE_ERROR, "width(%S) > (%S:MRB_INT_BIT-1)", |
mzta | 0:158c61bb030f | 962 | mrb_fixnum_value(width), |
mzta | 0:158c61bb030f | 963 | mrb_fixnum_value(NUMERIC_SHIFT_WIDTH_MAX)); |
mzta | 0:158c61bb030f | 964 | } |
mzta | 0:158c61bb030f | 965 | return mrb_fixnum_value(val << width); |
mzta | 0:158c61bb030f | 966 | } |
mzta | 0:158c61bb030f | 967 | |
mzta | 0:158c61bb030f | 968 | static mrb_value |
mzta | 0:158c61bb030f | 969 | rshift(mrb_int val, mrb_int width) |
mzta | 0:158c61bb030f | 970 | { |
mzta | 0:158c61bb030f | 971 | mrb_assert(width >= 0); |
mzta | 0:158c61bb030f | 972 | if (width >= NUMERIC_SHIFT_WIDTH_MAX) { |
mzta | 0:158c61bb030f | 973 | if (val < 0) { |
mzta | 0:158c61bb030f | 974 | return mrb_fixnum_value(-1); |
mzta | 0:158c61bb030f | 975 | } |
mzta | 0:158c61bb030f | 976 | return mrb_fixnum_value(0); |
mzta | 0:158c61bb030f | 977 | } |
mzta | 0:158c61bb030f | 978 | return mrb_fixnum_value(val >> width); |
mzta | 0:158c61bb030f | 979 | } |
mzta | 0:158c61bb030f | 980 | |
mzta | 0:158c61bb030f | 981 | static inline void |
mzta | 0:158c61bb030f | 982 | fix_shift_get_width(mrb_state *mrb, mrb_int *width) |
mzta | 0:158c61bb030f | 983 | { |
mzta | 0:158c61bb030f | 984 | mrb_value y; |
mzta | 0:158c61bb030f | 985 | |
mzta | 0:158c61bb030f | 986 | mrb_get_args(mrb, "o", &y); |
mzta | 0:158c61bb030f | 987 | *width = mrb_fixnum(bit_coerce(mrb, y)); |
mzta | 0:158c61bb030f | 988 | } |
mzta | 0:158c61bb030f | 989 | |
mzta | 0:158c61bb030f | 990 | /* 15.2.8.3.12 */ |
mzta | 0:158c61bb030f | 991 | /* |
mzta | 0:158c61bb030f | 992 | * call-seq: |
mzta | 0:158c61bb030f | 993 | * fix << count -> integer |
mzta | 0:158c61bb030f | 994 | * |
mzta | 0:158c61bb030f | 995 | * Shifts _fix_ left _count_ positions (right if _count_ is negative). |
mzta | 0:158c61bb030f | 996 | */ |
mzta | 0:158c61bb030f | 997 | |
mzta | 0:158c61bb030f | 998 | static mrb_value |
mzta | 0:158c61bb030f | 999 | fix_lshift(mrb_state *mrb, mrb_value x) |
mzta | 0:158c61bb030f | 1000 | { |
mzta | 0:158c61bb030f | 1001 | mrb_int width, val; |
mzta | 0:158c61bb030f | 1002 | |
mzta | 0:158c61bb030f | 1003 | fix_shift_get_width(mrb, &width); |
mzta | 0:158c61bb030f | 1004 | |
mzta | 0:158c61bb030f | 1005 | if (width == 0) { |
mzta | 0:158c61bb030f | 1006 | return x; |
mzta | 0:158c61bb030f | 1007 | } |
mzta | 0:158c61bb030f | 1008 | val = mrb_fixnum(x); |
mzta | 0:158c61bb030f | 1009 | if (width < 0) { |
mzta | 0:158c61bb030f | 1010 | return rshift(val, -width); |
mzta | 0:158c61bb030f | 1011 | } |
mzta | 0:158c61bb030f | 1012 | return lshift(mrb, val, width); |
mzta | 0:158c61bb030f | 1013 | } |
mzta | 0:158c61bb030f | 1014 | |
mzta | 0:158c61bb030f | 1015 | /* 15.2.8.3.13 */ |
mzta | 0:158c61bb030f | 1016 | /* |
mzta | 0:158c61bb030f | 1017 | * call-seq: |
mzta | 0:158c61bb030f | 1018 | * fix >> count -> integer |
mzta | 0:158c61bb030f | 1019 | * |
mzta | 0:158c61bb030f | 1020 | * Shifts _fix_ right _count_ positions (left if _count_ is negative). |
mzta | 0:158c61bb030f | 1021 | */ |
mzta | 0:158c61bb030f | 1022 | |
mzta | 0:158c61bb030f | 1023 | static mrb_value |
mzta | 0:158c61bb030f | 1024 | fix_rshift(mrb_state *mrb, mrb_value x) |
mzta | 0:158c61bb030f | 1025 | { |
mzta | 0:158c61bb030f | 1026 | mrb_int width, val; |
mzta | 0:158c61bb030f | 1027 | |
mzta | 0:158c61bb030f | 1028 | fix_shift_get_width(mrb, &width); |
mzta | 0:158c61bb030f | 1029 | |
mzta | 0:158c61bb030f | 1030 | if (width == 0) { |
mzta | 0:158c61bb030f | 1031 | return x; |
mzta | 0:158c61bb030f | 1032 | } |
mzta | 0:158c61bb030f | 1033 | val = mrb_fixnum(x); |
mzta | 0:158c61bb030f | 1034 | if (width < 0) { |
mzta | 0:158c61bb030f | 1035 | return lshift(mrb, val, -width); |
mzta | 0:158c61bb030f | 1036 | } |
mzta | 0:158c61bb030f | 1037 | return rshift(val, width); |
mzta | 0:158c61bb030f | 1038 | } |
mzta | 0:158c61bb030f | 1039 | |
mzta | 0:158c61bb030f | 1040 | /* 15.2.8.3.23 */ |
mzta | 0:158c61bb030f | 1041 | /* |
mzta | 0:158c61bb030f | 1042 | * call-seq: |
mzta | 0:158c61bb030f | 1043 | * fix.to_f -> float |
mzta | 0:158c61bb030f | 1044 | * |
mzta | 0:158c61bb030f | 1045 | * Converts <i>fix</i> to a <code>Float</code>. |
mzta | 0:158c61bb030f | 1046 | * |
mzta | 0:158c61bb030f | 1047 | */ |
mzta | 0:158c61bb030f | 1048 | |
mzta | 0:158c61bb030f | 1049 | static mrb_value |
mzta | 0:158c61bb030f | 1050 | fix_to_f(mrb_state *mrb, mrb_value num) |
mzta | 0:158c61bb030f | 1051 | { |
mzta | 0:158c61bb030f | 1052 | return mrb_float_value(mrb, (mrb_float)mrb_fixnum(num)); |
mzta | 0:158c61bb030f | 1053 | } |
mzta | 0:158c61bb030f | 1054 | |
mzta | 0:158c61bb030f | 1055 | /* |
mzta | 0:158c61bb030f | 1056 | * Document-class: FloatDomainError |
mzta | 0:158c61bb030f | 1057 | * |
mzta | 0:158c61bb030f | 1058 | * Raised when attempting to convert special float values |
mzta | 0:158c61bb030f | 1059 | * (in particular infinite or NaN) |
mzta | 0:158c61bb030f | 1060 | * to numerical classes which don't support them. |
mzta | 0:158c61bb030f | 1061 | * |
mzta | 0:158c61bb030f | 1062 | * Float::INFINITY.to_r |
mzta | 0:158c61bb030f | 1063 | * |
mzta | 0:158c61bb030f | 1064 | * <em>raises the exception:</em> |
mzta | 0:158c61bb030f | 1065 | * |
mzta | 0:158c61bb030f | 1066 | * FloatDomainError: Infinity |
mzta | 0:158c61bb030f | 1067 | */ |
mzta | 0:158c61bb030f | 1068 | /* ------------------------------------------------------------------------*/ |
mzta | 0:158c61bb030f | 1069 | MRB_API mrb_value |
mzta | 0:158c61bb030f | 1070 | mrb_flo_to_fixnum(mrb_state *mrb, mrb_value x) |
mzta | 0:158c61bb030f | 1071 | { |
mzta | 0:158c61bb030f | 1072 | mrb_int z; |
mzta | 0:158c61bb030f | 1073 | |
mzta | 0:158c61bb030f | 1074 | if (!mrb_float_p(x)) { |
mzta | 0:158c61bb030f | 1075 | mrb_raise(mrb, E_TYPE_ERROR, "non float value"); |
mzta | 0:158c61bb030f | 1076 | z = 0; /* not reached. just suppress warnings. */ |
mzta | 0:158c61bb030f | 1077 | } |
mzta | 0:158c61bb030f | 1078 | else { |
mzta | 0:158c61bb030f | 1079 | mrb_float d = mrb_float(x); |
mzta | 0:158c61bb030f | 1080 | |
mzta | 0:158c61bb030f | 1081 | if (isinf(d)) { |
mzta | 0:158c61bb030f | 1082 | mrb_raise(mrb, E_FLOATDOMAIN_ERROR, d < 0 ? "-Infinity" : "Infinity"); |
mzta | 0:158c61bb030f | 1083 | } |
mzta | 0:158c61bb030f | 1084 | if (isnan(d)) { |
mzta | 0:158c61bb030f | 1085 | mrb_raise(mrb, E_FLOATDOMAIN_ERROR, "NaN"); |
mzta | 0:158c61bb030f | 1086 | } |
mzta | 0:158c61bb030f | 1087 | z = (mrb_int)d; |
mzta | 0:158c61bb030f | 1088 | } |
mzta | 0:158c61bb030f | 1089 | return mrb_fixnum_value(z); |
mzta | 0:158c61bb030f | 1090 | } |
mzta | 0:158c61bb030f | 1091 | |
mzta | 0:158c61bb030f | 1092 | mrb_value |
mzta | 0:158c61bb030f | 1093 | mrb_fixnum_plus(mrb_state *mrb, mrb_value x, mrb_value y) |
mzta | 0:158c61bb030f | 1094 | { |
mzta | 0:158c61bb030f | 1095 | mrb_int a; |
mzta | 0:158c61bb030f | 1096 | |
mzta | 0:158c61bb030f | 1097 | a = mrb_fixnum(x); |
mzta | 0:158c61bb030f | 1098 | if (mrb_fixnum_p(y)) { |
mzta | 0:158c61bb030f | 1099 | mrb_int b, c; |
mzta | 0:158c61bb030f | 1100 | |
mzta | 0:158c61bb030f | 1101 | if (a == 0) return y; |
mzta | 0:158c61bb030f | 1102 | b = mrb_fixnum(y); |
mzta | 0:158c61bb030f | 1103 | if (mrb_int_add_overflow(a, b, &c)) { |
mzta | 0:158c61bb030f | 1104 | return mrb_float_value(mrb, (mrb_float)a + (mrb_float)b); |
mzta | 0:158c61bb030f | 1105 | } |
mzta | 0:158c61bb030f | 1106 | return mrb_fixnum_value(c); |
mzta | 0:158c61bb030f | 1107 | } |
mzta | 0:158c61bb030f | 1108 | return mrb_float_value(mrb, (mrb_float)a + mrb_to_flo(mrb, y)); |
mzta | 0:158c61bb030f | 1109 | } |
mzta | 0:158c61bb030f | 1110 | |
mzta | 0:158c61bb030f | 1111 | /* 15.2.8.3.1 */ |
mzta | 0:158c61bb030f | 1112 | /* |
mzta | 0:158c61bb030f | 1113 | * call-seq: |
mzta | 0:158c61bb030f | 1114 | * fix + numeric -> numeric_result |
mzta | 0:158c61bb030f | 1115 | * |
mzta | 0:158c61bb030f | 1116 | * Performs addition: the class of the resulting object depends on |
mzta | 0:158c61bb030f | 1117 | * the class of <code>numeric</code> and on the magnitude of the |
mzta | 0:158c61bb030f | 1118 | * result. |
mzta | 0:158c61bb030f | 1119 | */ |
mzta | 0:158c61bb030f | 1120 | static mrb_value |
mzta | 0:158c61bb030f | 1121 | fix_plus(mrb_state *mrb, mrb_value self) |
mzta | 0:158c61bb030f | 1122 | { |
mzta | 0:158c61bb030f | 1123 | mrb_value other; |
mzta | 0:158c61bb030f | 1124 | |
mzta | 0:158c61bb030f | 1125 | mrb_get_args(mrb, "o", &other); |
mzta | 0:158c61bb030f | 1126 | return mrb_fixnum_plus(mrb, self, other); |
mzta | 0:158c61bb030f | 1127 | } |
mzta | 0:158c61bb030f | 1128 | |
mzta | 0:158c61bb030f | 1129 | mrb_value |
mzta | 0:158c61bb030f | 1130 | mrb_fixnum_minus(mrb_state *mrb, mrb_value x, mrb_value y) |
mzta | 0:158c61bb030f | 1131 | { |
mzta | 0:158c61bb030f | 1132 | mrb_int a; |
mzta | 0:158c61bb030f | 1133 | |
mzta | 0:158c61bb030f | 1134 | a = mrb_fixnum(x); |
mzta | 0:158c61bb030f | 1135 | if (mrb_fixnum_p(y)) { |
mzta | 0:158c61bb030f | 1136 | mrb_int b, c; |
mzta | 0:158c61bb030f | 1137 | |
mzta | 0:158c61bb030f | 1138 | b = mrb_fixnum(y); |
mzta | 0:158c61bb030f | 1139 | if (mrb_int_sub_overflow(a, b, &c)) { |
mzta | 0:158c61bb030f | 1140 | return mrb_float_value(mrb, (mrb_float)a - (mrb_float)b); |
mzta | 0:158c61bb030f | 1141 | } |
mzta | 0:158c61bb030f | 1142 | return mrb_fixnum_value(c); |
mzta | 0:158c61bb030f | 1143 | } |
mzta | 0:158c61bb030f | 1144 | return mrb_float_value(mrb, (mrb_float)a - mrb_to_flo(mrb, y)); |
mzta | 0:158c61bb030f | 1145 | } |
mzta | 0:158c61bb030f | 1146 | |
mzta | 0:158c61bb030f | 1147 | /* 15.2.8.3.2 */ |
mzta | 0:158c61bb030f | 1148 | /* 15.2.8.3.16 */ |
mzta | 0:158c61bb030f | 1149 | /* |
mzta | 0:158c61bb030f | 1150 | * call-seq: |
mzta | 0:158c61bb030f | 1151 | * fix - numeric -> numeric_result |
mzta | 0:158c61bb030f | 1152 | * |
mzta | 0:158c61bb030f | 1153 | * Performs subtraction: the class of the resulting object depends on |
mzta | 0:158c61bb030f | 1154 | * the class of <code>numeric</code> and on the magnitude of the |
mzta | 0:158c61bb030f | 1155 | * result. |
mzta | 0:158c61bb030f | 1156 | */ |
mzta | 0:158c61bb030f | 1157 | static mrb_value |
mzta | 0:158c61bb030f | 1158 | fix_minus(mrb_state *mrb, mrb_value self) |
mzta | 0:158c61bb030f | 1159 | { |
mzta | 0:158c61bb030f | 1160 | mrb_value other; |
mzta | 0:158c61bb030f | 1161 | |
mzta | 0:158c61bb030f | 1162 | mrb_get_args(mrb, "o", &other); |
mzta | 0:158c61bb030f | 1163 | return mrb_fixnum_minus(mrb, self, other); |
mzta | 0:158c61bb030f | 1164 | } |
mzta | 0:158c61bb030f | 1165 | |
mzta | 0:158c61bb030f | 1166 | |
mzta | 0:158c61bb030f | 1167 | MRB_API mrb_value |
mzta | 0:158c61bb030f | 1168 | mrb_fixnum_to_str(mrb_state *mrb, mrb_value x, int base) |
mzta | 0:158c61bb030f | 1169 | { |
mzta | 0:158c61bb030f | 1170 | char buf[MRB_INT_BIT+1]; |
mzta | 0:158c61bb030f | 1171 | char *b = buf + sizeof buf; |
mzta | 0:158c61bb030f | 1172 | mrb_int val = mrb_fixnum(x); |
mzta | 0:158c61bb030f | 1173 | |
mzta | 0:158c61bb030f | 1174 | if (base < 2 || 36 < base) { |
mzta | 0:158c61bb030f | 1175 | mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalid radix %S", mrb_fixnum_value(base)); |
mzta | 0:158c61bb030f | 1176 | } |
mzta | 0:158c61bb030f | 1177 | |
mzta | 0:158c61bb030f | 1178 | if (val == 0) { |
mzta | 0:158c61bb030f | 1179 | *--b = '0'; |
mzta | 0:158c61bb030f | 1180 | } |
mzta | 0:158c61bb030f | 1181 | else if (val < 0) { |
mzta | 0:158c61bb030f | 1182 | do { |
mzta | 0:158c61bb030f | 1183 | *--b = mrb_digitmap[-(val % base)]; |
mzta | 0:158c61bb030f | 1184 | } while (val /= base); |
mzta | 0:158c61bb030f | 1185 | *--b = '-'; |
mzta | 0:158c61bb030f | 1186 | } |
mzta | 0:158c61bb030f | 1187 | else { |
mzta | 0:158c61bb030f | 1188 | do { |
mzta | 0:158c61bb030f | 1189 | *--b = mrb_digitmap[(int)(val % base)]; |
mzta | 0:158c61bb030f | 1190 | } while (val /= base); |
mzta | 0:158c61bb030f | 1191 | } |
mzta | 0:158c61bb030f | 1192 | |
mzta | 0:158c61bb030f | 1193 | return mrb_str_new(mrb, b, buf + sizeof(buf) - b); |
mzta | 0:158c61bb030f | 1194 | } |
mzta | 0:158c61bb030f | 1195 | |
mzta | 0:158c61bb030f | 1196 | /* 15.2.8.3.25 */ |
mzta | 0:158c61bb030f | 1197 | /* |
mzta | 0:158c61bb030f | 1198 | * call-seq: |
mzta | 0:158c61bb030f | 1199 | * fix.to_s(base=10) -> string |
mzta | 0:158c61bb030f | 1200 | * |
mzta | 0:158c61bb030f | 1201 | * Returns a string containing the representation of <i>fix</i> radix |
mzta | 0:158c61bb030f | 1202 | * <i>base</i> (between 2 and 36). |
mzta | 0:158c61bb030f | 1203 | * |
mzta | 0:158c61bb030f | 1204 | * 12345.to_s #=> "12345" |
mzta | 0:158c61bb030f | 1205 | * 12345.to_s(2) #=> "11000000111001" |
mzta | 0:158c61bb030f | 1206 | * 12345.to_s(8) #=> "30071" |
mzta | 0:158c61bb030f | 1207 | * 12345.to_s(10) #=> "12345" |
mzta | 0:158c61bb030f | 1208 | * 12345.to_s(16) #=> "3039" |
mzta | 0:158c61bb030f | 1209 | * 12345.to_s(36) #=> "9ix" |
mzta | 0:158c61bb030f | 1210 | * |
mzta | 0:158c61bb030f | 1211 | */ |
mzta | 0:158c61bb030f | 1212 | static mrb_value |
mzta | 0:158c61bb030f | 1213 | fix_to_s(mrb_state *mrb, mrb_value self) |
mzta | 0:158c61bb030f | 1214 | { |
mzta | 0:158c61bb030f | 1215 | mrb_int base = 10; |
mzta | 0:158c61bb030f | 1216 | |
mzta | 0:158c61bb030f | 1217 | mrb_get_args(mrb, "|i", &base); |
mzta | 0:158c61bb030f | 1218 | return mrb_fixnum_to_str(mrb, self, base); |
mzta | 0:158c61bb030f | 1219 | } |
mzta | 0:158c61bb030f | 1220 | |
mzta | 0:158c61bb030f | 1221 | /* 15.2.9.3.6 */ |
mzta | 0:158c61bb030f | 1222 | /* |
mzta | 0:158c61bb030f | 1223 | * call-seq: |
mzta | 0:158c61bb030f | 1224 | * self.f <=> other.f => -1, 0, +1 |
mzta | 0:158c61bb030f | 1225 | * < => -1 |
mzta | 0:158c61bb030f | 1226 | * = => 0 |
mzta | 0:158c61bb030f | 1227 | * > => +1 |
mzta | 0:158c61bb030f | 1228 | * Comparison---Returns -1, 0, or +1 depending on whether <i>fix</i> is |
mzta | 0:158c61bb030f | 1229 | * less than, equal to, or greater than <i>numeric</i>. This is the |
mzta | 0:158c61bb030f | 1230 | * basis for the tests in <code>Comparable</code>. |
mzta | 0:158c61bb030f | 1231 | */ |
mzta | 0:158c61bb030f | 1232 | static mrb_value |
mzta | 0:158c61bb030f | 1233 | num_cmp(mrb_state *mrb, mrb_value self) |
mzta | 0:158c61bb030f | 1234 | { |
mzta | 0:158c61bb030f | 1235 | mrb_value other; |
mzta | 0:158c61bb030f | 1236 | mrb_float x, y; |
mzta | 0:158c61bb030f | 1237 | |
mzta | 0:158c61bb030f | 1238 | mrb_get_args(mrb, "o", &other); |
mzta | 0:158c61bb030f | 1239 | |
mzta | 0:158c61bb030f | 1240 | x = mrb_to_flo(mrb, self); |
mzta | 0:158c61bb030f | 1241 | switch (mrb_type(other)) { |
mzta | 0:158c61bb030f | 1242 | case MRB_TT_FIXNUM: |
mzta | 0:158c61bb030f | 1243 | y = (mrb_float)mrb_fixnum(other); |
mzta | 0:158c61bb030f | 1244 | break; |
mzta | 0:158c61bb030f | 1245 | case MRB_TT_FLOAT: |
mzta | 0:158c61bb030f | 1246 | y = mrb_float(other); |
mzta | 0:158c61bb030f | 1247 | break; |
mzta | 0:158c61bb030f | 1248 | default: |
mzta | 0:158c61bb030f | 1249 | return mrb_nil_value(); |
mzta | 0:158c61bb030f | 1250 | } |
mzta | 0:158c61bb030f | 1251 | if (x > y) |
mzta | 0:158c61bb030f | 1252 | return mrb_fixnum_value(1); |
mzta | 0:158c61bb030f | 1253 | else { |
mzta | 0:158c61bb030f | 1254 | if (x < y) |
mzta | 0:158c61bb030f | 1255 | return mrb_fixnum_value(-1); |
mzta | 0:158c61bb030f | 1256 | return mrb_fixnum_value(0); |
mzta | 0:158c61bb030f | 1257 | } |
mzta | 0:158c61bb030f | 1258 | } |
mzta | 0:158c61bb030f | 1259 | |
mzta | 0:158c61bb030f | 1260 | /* 15.2.9.3.1 */ |
mzta | 0:158c61bb030f | 1261 | /* |
mzta | 0:158c61bb030f | 1262 | * call-seq: |
mzta | 0:158c61bb030f | 1263 | * float + other -> float |
mzta | 0:158c61bb030f | 1264 | * |
mzta | 0:158c61bb030f | 1265 | * Returns a new float which is the sum of <code>float</code> |
mzta | 0:158c61bb030f | 1266 | * and <code>other</code>. |
mzta | 0:158c61bb030f | 1267 | */ |
mzta | 0:158c61bb030f | 1268 | static mrb_value |
mzta | 0:158c61bb030f | 1269 | flo_plus(mrb_state *mrb, mrb_value x) |
mzta | 0:158c61bb030f | 1270 | { |
mzta | 0:158c61bb030f | 1271 | mrb_value y; |
mzta | 0:158c61bb030f | 1272 | |
mzta | 0:158c61bb030f | 1273 | mrb_get_args(mrb, "o", &y); |
mzta | 0:158c61bb030f | 1274 | return mrb_float_value(mrb, mrb_float(x) + mrb_to_flo(mrb, y)); |
mzta | 0:158c61bb030f | 1275 | } |
mzta | 0:158c61bb030f | 1276 | |
mzta | 0:158c61bb030f | 1277 | /* ------------------------------------------------------------------------*/ |
mzta | 0:158c61bb030f | 1278 | void |
mzta | 0:158c61bb030f | 1279 | mrb_init_numeric(mrb_state *mrb) |
mzta | 0:158c61bb030f | 1280 | { |
mzta | 0:158c61bb030f | 1281 | struct RClass *numeric, *integer, *fixnum, *fl; |
mzta | 0:158c61bb030f | 1282 | |
mzta | 0:158c61bb030f | 1283 | /* Numeric Class */ |
mzta | 0:158c61bb030f | 1284 | numeric = mrb_define_class(mrb, "Numeric", mrb->object_class); /* 15.2.7 */ |
mzta | 0:158c61bb030f | 1285 | |
mzta | 0:158c61bb030f | 1286 | mrb_define_method(mrb, numeric, "**", num_pow, MRB_ARGS_REQ(1)); |
mzta | 0:158c61bb030f | 1287 | mrb_define_method(mrb, numeric, "/", num_div, MRB_ARGS_REQ(1)); /* 15.2.8.3.4 */ |
mzta | 0:158c61bb030f | 1288 | mrb_define_method(mrb, numeric, "quo", num_div, MRB_ARGS_REQ(1)); /* 15.2.7.4.5 (x) */ |
mzta | 0:158c61bb030f | 1289 | mrb_define_method(mrb, numeric, "<=>", num_cmp, MRB_ARGS_REQ(1)); /* 15.2.9.3.6 */ |
mzta | 0:158c61bb030f | 1290 | |
mzta | 0:158c61bb030f | 1291 | /* Integer Class */ |
mzta | 0:158c61bb030f | 1292 | integer = mrb_define_class(mrb, "Integer", numeric); /* 15.2.8 */ |
mzta | 0:158c61bb030f | 1293 | mrb_undef_class_method(mrb, integer, "new"); |
mzta | 0:158c61bb030f | 1294 | mrb_define_method(mrb, integer, "to_i", int_to_i, MRB_ARGS_NONE()); /* 15.2.8.3.24 */ |
mzta | 0:158c61bb030f | 1295 | mrb_define_method(mrb, integer, "to_int", int_to_i, MRB_ARGS_NONE()); |
mzta | 0:158c61bb030f | 1296 | |
mzta | 0:158c61bb030f | 1297 | /* Fixnum Class */ |
mzta | 0:158c61bb030f | 1298 | fixnum = mrb->fixnum_class = mrb_define_class(mrb, "Fixnum", integer); |
mzta | 0:158c61bb030f | 1299 | mrb_define_method(mrb, fixnum, "+", fix_plus, MRB_ARGS_REQ(1)); /* 15.2.8.3.1 */ |
mzta | 0:158c61bb030f | 1300 | mrb_define_method(mrb, fixnum, "-", fix_minus, MRB_ARGS_REQ(1)); /* 15.2.8.3.2 */ |
mzta | 0:158c61bb030f | 1301 | mrb_define_method(mrb, fixnum, "*", fix_mul, MRB_ARGS_REQ(1)); /* 15.2.8.3.3 */ |
mzta | 0:158c61bb030f | 1302 | mrb_define_method(mrb, fixnum, "%", fix_mod, MRB_ARGS_REQ(1)); /* 15.2.8.3.5 */ |
mzta | 0:158c61bb030f | 1303 | mrb_define_method(mrb, fixnum, "==", fix_equal, MRB_ARGS_REQ(1)); /* 15.2.8.3.7 */ |
mzta | 0:158c61bb030f | 1304 | mrb_define_method(mrb, fixnum, "~", fix_rev, MRB_ARGS_NONE()); /* 15.2.8.3.8 */ |
mzta | 0:158c61bb030f | 1305 | mrb_define_method(mrb, fixnum, "&", fix_and, MRB_ARGS_REQ(1)); /* 15.2.8.3.9 */ |
mzta | 0:158c61bb030f | 1306 | mrb_define_method(mrb, fixnum, "|", fix_or, MRB_ARGS_REQ(1)); /* 15.2.8.3.10 */ |
mzta | 0:158c61bb030f | 1307 | mrb_define_method(mrb, fixnum, "^", fix_xor, MRB_ARGS_REQ(1)); /* 15.2.8.3.11 */ |
mzta | 0:158c61bb030f | 1308 | mrb_define_method(mrb, fixnum, "<<", fix_lshift, MRB_ARGS_REQ(1)); /* 15.2.8.3.12 */ |
mzta | 0:158c61bb030f | 1309 | mrb_define_method(mrb, fixnum, ">>", fix_rshift, MRB_ARGS_REQ(1)); /* 15.2.8.3.13 */ |
mzta | 0:158c61bb030f | 1310 | mrb_define_method(mrb, fixnum, "eql?", fix_eql, MRB_ARGS_REQ(1)); /* 15.2.8.3.16 */ |
mzta | 0:158c61bb030f | 1311 | mrb_define_method(mrb, fixnum, "hash", flo_hash, MRB_ARGS_NONE()); /* 15.2.8.3.18 */ |
mzta | 0:158c61bb030f | 1312 | mrb_define_method(mrb, fixnum, "to_f", fix_to_f, MRB_ARGS_NONE()); /* 15.2.8.3.23 */ |
mzta | 0:158c61bb030f | 1313 | mrb_define_method(mrb, fixnum, "to_s", fix_to_s, MRB_ARGS_NONE()); /* 15.2.8.3.25 */ |
mzta | 0:158c61bb030f | 1314 | mrb_define_method(mrb, fixnum, "inspect", fix_to_s, MRB_ARGS_NONE()); |
mzta | 0:158c61bb030f | 1315 | mrb_define_method(mrb, fixnum, "divmod", fix_divmod, MRB_ARGS_REQ(1)); /* 15.2.8.3.30 (x) */ |
mzta | 0:158c61bb030f | 1316 | |
mzta | 0:158c61bb030f | 1317 | /* Float Class */ |
mzta | 0:158c61bb030f | 1318 | fl = mrb->float_class = mrb_define_class(mrb, "Float", numeric); /* 15.2.9 */ |
mzta | 0:158c61bb030f | 1319 | mrb_undef_class_method(mrb, fl, "new"); |
mzta | 0:158c61bb030f | 1320 | mrb_define_method(mrb, fl, "+", flo_plus, MRB_ARGS_REQ(1)); /* 15.2.9.3.1 */ |
mzta | 0:158c61bb030f | 1321 | mrb_define_method(mrb, fl, "-", flo_minus, MRB_ARGS_REQ(1)); /* 15.2.9.3.2 */ |
mzta | 0:158c61bb030f | 1322 | mrb_define_method(mrb, fl, "*", flo_mul, MRB_ARGS_REQ(1)); /* 15.2.9.3.3 */ |
mzta | 0:158c61bb030f | 1323 | mrb_define_method(mrb, fl, "%", flo_mod, MRB_ARGS_REQ(1)); /* 15.2.9.3.5 */ |
mzta | 0:158c61bb030f | 1324 | mrb_define_method(mrb, fl, "==", flo_eq, MRB_ARGS_REQ(1)); /* 15.2.9.3.7 */ |
mzta | 0:158c61bb030f | 1325 | mrb_define_method(mrb, fl, "ceil", flo_ceil, MRB_ARGS_NONE()); /* 15.2.9.3.8 */ |
mzta | 0:158c61bb030f | 1326 | mrb_define_method(mrb, fl, "finite?", flo_finite_p, MRB_ARGS_NONE()); /* 15.2.9.3.9 */ |
mzta | 0:158c61bb030f | 1327 | mrb_define_method(mrb, fl, "floor", flo_floor, MRB_ARGS_NONE()); /* 15.2.9.3.10 */ |
mzta | 0:158c61bb030f | 1328 | mrb_define_method(mrb, fl, "infinite?", flo_infinite_p, MRB_ARGS_NONE()); /* 15.2.9.3.11 */ |
mzta | 0:158c61bb030f | 1329 | mrb_define_method(mrb, fl, "round", flo_round, MRB_ARGS_OPT(1)); /* 15.2.9.3.12 */ |
mzta | 0:158c61bb030f | 1330 | mrb_define_method(mrb, fl, "to_f", flo_to_f, MRB_ARGS_NONE()); /* 15.2.9.3.13 */ |
mzta | 0:158c61bb030f | 1331 | mrb_define_method(mrb, fl, "to_i", flo_truncate, MRB_ARGS_NONE()); /* 15.2.9.3.14 */ |
mzta | 0:158c61bb030f | 1332 | mrb_define_method(mrb, fl, "to_int", flo_truncate, MRB_ARGS_NONE()); |
mzta | 0:158c61bb030f | 1333 | mrb_define_method(mrb, fl, "truncate", flo_truncate, MRB_ARGS_NONE()); /* 15.2.9.3.15 */ |
mzta | 0:158c61bb030f | 1334 | mrb_define_method(mrb, fl, "divmod", flo_divmod, MRB_ARGS_REQ(1)); |
mzta | 0:158c61bb030f | 1335 | mrb_define_method(mrb, fl, "eql?", flo_eql, MRB_ARGS_REQ(1)); /* 15.2.8.3.16 */ |
mzta | 0:158c61bb030f | 1336 | |
mzta | 0:158c61bb030f | 1337 | mrb_define_method(mrb, fl, "to_s", flo_to_s, MRB_ARGS_NONE()); /* 15.2.9.3.16(x) */ |
mzta | 0:158c61bb030f | 1338 | mrb_define_method(mrb, fl, "inspect", flo_to_s, MRB_ARGS_NONE()); |
mzta | 0:158c61bb030f | 1339 | mrb_define_method(mrb, fl, "nan?", flo_nan_p, MRB_ARGS_NONE()); |
mzta | 0:158c61bb030f | 1340 | |
mzta | 0:158c61bb030f | 1341 | #ifdef INFINITY |
mzta | 0:158c61bb030f | 1342 | mrb_define_const(mrb, fl, "INFINITY", mrb_float_value(mrb, INFINITY)); |
mzta | 0:158c61bb030f | 1343 | #endif |
mzta | 0:158c61bb030f | 1344 | #ifdef NAN |
mzta | 0:158c61bb030f | 1345 | mrb_define_const(mrb, fl, "NAN", mrb_float_value(mrb, NAN)); |
mzta | 0:158c61bb030f | 1346 | #endif |
mzta | 0:158c61bb030f | 1347 | } |
mzta | 0:158c61bb030f | 1348 |