Ignore:
Timestamp:
Jul 9, 2020, 8:51:43 AM (4 years ago)
Author:
coas-nagasima
Message:

mrubyを2.1.1に更新

Location:
EcnlProtoTool/trunk/mruby-2.1.1
Files:
1 edited
1 moved

Legend:

Unmodified
Added
Removed
  • EcnlProtoTool/trunk/mruby-2.1.1/src/numeric.c

    r331 r439  
    55*/
    66
     7#ifndef MRB_WITHOUT_FLOAT
    78#include <float.h>
     9#include <math.h>
     10#endif
    811#include <limits.h>
    9 #include <math.h>
    1012#include <stdlib.h>
     13#include <string.h>
    1114
    1215#include <mruby.h>
     
    1619#include <mruby/class.h>
    1720
     21#ifndef MRB_WITHOUT_FLOAT
    1822#ifdef MRB_USE_FLOAT
    1923#define trunc(f) truncf(f)
     
    2125#define ceil(f) ceilf(f)
    2226#define fmod(x,y) fmodf(x,y)
    23 #define MRB_FLO_TO_STR_FMT "%.7g"
    24 #else
    25 #define MRB_FLO_TO_STR_FMT "%.14g"
    26 #endif
    27 
     27#define FLO_TO_STR_PREC 8
     28#else
     29#define FLO_TO_STR_PREC 16
     30#endif
     31#endif
     32
     33#ifndef MRB_WITHOUT_FLOAT
    2834MRB_API mrb_float
    2935mrb_to_flo(mrb_state *mrb, mrb_value val)
     
    4046}
    4147
     48MRB_API mrb_value
     49mrb_int_value(mrb_state *mrb, mrb_float f)
     50{
     51  if (FIXABLE_FLOAT(f)) {
     52    return mrb_fixnum_value((mrb_int)f);
     53  }
     54  return mrb_float_value(mrb, f);
     55}
     56#endif
     57
    4258/*
    4359 * call-seq:
     
    5066 */
    5167static mrb_value
    52 num_pow(mrb_state *mrb, mrb_value x)
    53 {
    54   mrb_value y;
     68integral_pow(mrb_state *mrb, mrb_value x)
     69{
     70  mrb_value y;
     71#ifndef MRB_WITHOUT_FLOAT
    5572  mrb_float d;
     73#endif
    5674
    5775  mrb_get_args(mrb, "o", &y);
     
    6280    mrb_int result = 1;
    6381
    64     if (exp < 0) goto float_pow;
     82    if (exp < 0)
     83#ifdef MRB_WITHOUT_FLOAT
     84      return mrb_fixnum_value(0);
     85#else
     86      goto float_pow;
     87#endif
    6588    for (;;) {
    6689      if (exp & 1) {
    6790        if (mrb_int_mul_overflow(result, base, &result)) {
     91#ifndef MRB_WITHOUT_FLOAT
    6892          goto float_pow;
     93#endif
    6994        }
    7095      }
     
    7297      if (exp == 0) break;
    7398      if (mrb_int_mul_overflow(base, base, &base)) {
     99#ifndef MRB_WITHOUT_FLOAT
    74100        goto float_pow;
     101#endif
    75102      }
    76103    }
    77104    return mrb_fixnum_value(result);
    78105  }
     106#ifdef MRB_WITHOUT_FLOAT
     107  mrb_raise(mrb, E_TYPE_ERROR, "non fixnum value");
     108#else
    79109 float_pow:
    80110  d = pow(mrb_to_flo(mrb, x), mrb_to_flo(mrb, y));
    81111  return mrb_float_value(mrb, d);
     112#endif
     113}
     114
     115static mrb_value
     116integral_idiv(mrb_state *mrb, mrb_value x)
     117{
     118#ifdef MRB_WITHOUT_FLOAT
     119  mrb_value y;
     120
     121  mrb_get_args(mrb, "o", &y);
     122  if (!mrb_fixnum_p(y)) {
     123    mrb_raise(mrb, E_TYPE_ERROR, "non fixnum value");
     124  }
     125  return mrb_fixnum_value(mrb_fixnum(x) / mrb_fixnum(y));
     126#else
     127  mrb_float y;
     128
     129  mrb_get_args(mrb, "f", &y);
     130  return mrb_int_value(mrb, mrb_to_flo(mrb, x) / y);
     131#endif
    82132}
    83133
     
    93143 */
    94144
    95 mrb_value
    96 mrb_num_div(mrb_state *mrb, mrb_value x, mrb_value y)
    97 {
    98   return mrb_float_value(mrb, mrb_to_flo(mrb, x) / mrb_to_flo(mrb, y));
    99 }
    100 
    101145/* 15.2.9.3.19(x) */
    102146/*
     
    108152
    109153static mrb_value
    110 num_div(mrb_state *mrb, mrb_value x)
    111 {
     154integral_div(mrb_state *mrb, mrb_value x)
     155{
     156#ifdef MRB_WITHOUT_FLOAT
     157  mrb_value y;
     158
     159  mrb_get_args(mrb, "o", &y);
     160  if (!mrb_fixnum_p(y)) {
     161    mrb_raise(mrb, E_TYPE_ERROR, "non fixnum value");
     162  }
     163  return mrb_fixnum_value(mrb_fixnum(x) / mrb_fixnum(y));
     164#else
    112165  mrb_float y;
    113166
    114167  mrb_get_args(mrb, "f", &y);
    115168  return mrb_float_value(mrb, mrb_to_flo(mrb, x) / y);
    116 }
    117 
     169#endif
     170}
     171
     172static mrb_value
     173integral_coerce_step_counter(mrb_state *mrb, mrb_value self)
     174{
     175  mrb_value num, step;
     176
     177  mrb_get_args(mrb, "oo", &num, &step);
     178
     179#ifndef MRB_WITHOUT_FLOAT
     180  if (mrb_float_p(self) || mrb_float_p(num) || mrb_float_p(step)) {
     181    return mrb_Float(mrb, self);
     182  }
     183#endif
     184
     185  return self;
     186}
     187
     188#ifndef MRB_WITHOUT_FLOAT
    118189/********************************************************************
    119190 *
     
    139210flo_to_s(mrb_state *mrb, mrb_value flt)
    140211{
    141   if (isnan(mrb_float(flt))) {
     212  mrb_float f = mrb_float(flt);
     213
     214  if (isinf(f)) {
     215    return f < 0 ? mrb_str_new_lit(mrb, "-Infinity")
     216                 : mrb_str_new_lit(mrb, "Infinity");
     217  }
     218  else if (isnan(f)) {
    142219    return mrb_str_new_lit(mrb, "NaN");
    143220  }
    144   return mrb_float_to_str(mrb, flt, MRB_FLO_TO_STR_FMT);
     221  else {
     222    char fmt[] = "%." MRB_STRINGIZE(FLO_TO_STR_PREC) "g";
     223    mrb_value str = mrb_float_to_str(mrb, flt, fmt);
     224    mrb_int len;
     225    char *begp, *p, *endp;
     226
     227    insert_dot_zero:
     228    begp = RSTRING_PTR(str);
     229    len = RSTRING_LEN(str);
     230    for (p = begp, endp = p + len; p < endp; ++p) {
     231      if (*p == '.') {
     232        return str;
     233      }
     234      else if (*p == 'e') {
     235        ptrdiff_t e_pos = p - begp;
     236        mrb_str_cat(mrb, str, ".0", 2);
     237        p = RSTRING_PTR(str) + e_pos;
     238        memmove(p + 2, p, len - e_pos);
     239        memcpy(p, ".0", 2);
     240        return str;
     241      }
     242    }
     243
     244    if (FLO_TO_STR_PREC + (begp[0] == '-') <= len) {
     245      --fmt[sizeof(fmt) - 3];  /* %.16g(%.8g) -> %.15g(%.7g) */
     246      str = mrb_float_to_str(mrb, flt, fmt);
     247      goto insert_dot_zero;
     248    }
     249
     250    return str;
     251  }
    145252}
    146253
     
    182289
    183290static void
    184 flodivmod(mrb_state *mrb, mrb_float x, mrb_float y, mrb_float *divp, mrb_float *modp)
    185 {
    186   mrb_float div;
    187   mrb_float mod;
    188 
     291flodivmod(mrb_state *mrb, double x, double y, mrb_float *divp, mrb_float *modp)
     292{
     293  double div, mod;
     294
     295  if (isnan(y)) {
     296    /* y is NaN so all results are NaN */
     297    div = mod = y;
     298    goto exit;
     299  }
    189300  if (y == 0.0) {
    190     div = INFINITY;
     301    if (x == 0) div = NAN;
     302    else if (x > 0.0) div = INFINITY;
     303    else div = -INFINITY;       /* x < 0.0 */
    191304    mod = NAN;
     305    goto exit;
     306  }
     307  if ((x == 0.0) || (isinf(y) && !isinf(x))) {
     308    mod = x;
    192309  }
    193310  else {
    194311    mod = fmod(x, y);
    195     if (isinf(x) && isfinite(y))
    196       div = x;
    197     else
    198       div = (x - mod) / y;
    199     if (y*mod < 0) {
    200       mod += y;
    201       div -= 1.0;
    202     }
    203   }
    204 
     312  }
     313  if (isinf(x) && !isinf(y)) {
     314    div = x;
     315  }
     316  else {
     317    div = (x - mod) / y;
     318    if (modp && divp) div = round(div);
     319  }
     320  if (div == 0) div = 0.0;
     321  if (mod == 0) mod = 0.0;
     322  if (y*mod < 0) {
     323    mod += y;
     324    div -= 1.0;
     325  }
     326 exit:
    205327  if (modp) *modp = mod;
    206328  if (divp) *divp = div;
     
    230352  return mrb_float_value(mrb, mod);
    231353}
     354#endif
    232355
    233356/* 15.2.8.3.16 */
     
    253376}
    254377
     378#ifndef MRB_WITHOUT_FLOAT
    255379static mrb_value
    256380flo_eql(mrb_state *mrb, mrb_value x)
     
    260384  mrb_get_args(mrb, "o", &y);
    261385  if (!mrb_float_p(y)) return mrb_false_value();
    262   return mrb_bool_value(mrb_float(x) == (mrb_float)mrb_fixnum(y));
     386  return mrb_bool_value(mrb_float(x) == mrb_float(y));
    263387}
    264388
     
    312436int64_value(mrb_state *mrb, int64_t v)
    313437{
    314   if (FIXABLE(v)) {
     438  if (TYPED_FIXABLE(v,int64_t)) {
    315439    return mrb_fixnum_value((mrb_int)v);
    316440  }
     
    322446{
    323447  int64_t v1;
    324   mrb_get_args(mrb, "");
    325448  v1 = (int64_t)mrb_float(x);
    326449  return int64_value(mrb, ~v1);
     
    375498    while (width++) {
    376499      val /= 2;
     500      if (val < 1.0) {
     501        val = 0;
     502        break;
     503      }
    377504    }
    378505#if defined(_ISOC99_SOURCE)
    379506    val = trunc(val);
    380507#else
    381     val = val > 0 ? floor(val) : ceil(val);
     508    if (val > 0){
     509        val = floor(val);
     510    } else {
     511        val = ceil(val);
     512    }
    382513#endif
    383514    if (val == 0 && mrb_float(x) < 0) {
     
    390521    }
    391522  }
    392   if (FIXABLE_FLOAT(val)) {
    393     return mrb_fixnum_value((mrb_int)val);
    394   }
    395   return mrb_float_value(mrb, val);
    396 }
    397 
    398 static mrb_value
    399 flo_lshift(mrb_state *mrb, mrb_value x)
     523  return mrb_int_value(mrb, val);
     524}
     525
     526static mrb_value
     527flo_rshift(mrb_state *mrb, mrb_value x)
    400528{
    401529  mrb_int width;
     
    406534
    407535static mrb_value
    408 flo_rshift(mrb_state *mrb, mrb_value x)
     536flo_lshift(mrb_state *mrb, mrb_value x)
    409537{
    410538  mrb_int width;
     
    412540  mrb_get_args(mrb, "i", &width);
    413541  return flo_shift(mrb, x, width);
    414 }
    415 
    416 /* 15.2.8.3.18 */
    417 /*
    418  * call-seq:
    419  *   flt.hash  ->  integer
    420  *
    421  * Returns a hash code for this float.
    422  */
    423 static mrb_value
    424 flo_hash(mrb_state *mrb, mrb_value num)
    425 {
    426   mrb_float d;
    427   char *c;
    428   size_t i;
    429   mrb_int hash;
    430 
    431   d = (mrb_float)mrb_fixnum(num);
    432   /* normalize -0.0 to 0.0 */
    433   if (d == 0) d = 0.0;
    434   c = (char*)&d;
    435   for (hash=0,i=0; i<sizeof(mrb_float); i++) {
    436     hash = (hash * 971) ^ (unsigned char)c[i];
    437   }
    438   if (hash < 0) hash = -hash;
    439   return mrb_fixnum_value(hash);
    440542}
    441543
     
    525627
    526628  mrb_check_num_exact(mrb, f);
    527   if (!FIXABLE_FLOAT(f)) {
    528     return mrb_float_value(mrb, f);
    529   }
    530   return mrb_fixnum_value((mrb_int)f);
     629  return mrb_int_value(mrb, f);
    531630}
    532631
     
    551650
    552651  mrb_check_num_exact(mrb, f);
    553   if (!FIXABLE_FLOAT(f)) {
    554     return mrb_float_value(mrb, f);
    555   }
    556   return mrb_fixnum_value((mrb_int)f);
     652  return mrb_int_value(mrb, f);
    557653}
    558654
     
    605701  f = 1.0;
    606702  i = ndigits >= 0 ? ndigits : -ndigits;
     703  if (ndigits > DBL_DIG+2) return num;
    607704  while  (--i >= 0)
    608705    f = f*10.0;
     
    635732    return mrb_float_value(mrb, number);
    636733  }
    637   return mrb_fixnum_value((mrb_int)number);
     734  return mrb_int_value(mrb, number);
    638735}
    639736
     
    643740 *  call-seq:
    644741 *     flt.to_i      ->  integer
    645  *     flt.to_int    ->  integer
    646742 *     flt.truncate  ->  integer
    647743 *
     
    658754
    659755  mrb_check_num_exact(mrb, f);
    660   if (!FIXABLE_FLOAT(f)) {
    661     return mrb_float_value(mrb, f);
    662   }
    663   return mrb_fixnum_value((mrb_int)f);
     756  return mrb_int_value(mrb, f);
    664757}
    665758
     
    669762  return mrb_bool_value(isnan(mrb_float(num)));
    670763}
     764#endif
    671765
    672766/*
     
    682776 *  call-seq:
    683777 *     int.to_i      ->  integer
    684  *     int.to_int    ->  integer
    685778 *
    686779 *  As <i>int</i> is already an <code>Integer</code>, all these
     
    694787}
    695788
    696 mrb_value
    697 mrb_fixnum_mul(mrb_state *mrb, mrb_value x, mrb_value y)
     789static mrb_value
     790fixnum_mul(mrb_state *mrb, mrb_value x, mrb_value y)
    698791{
    699792  mrb_int a;
     
    706799    b = mrb_fixnum(y);
    707800    if (mrb_int_mul_overflow(a, b, &c)) {
     801#ifndef MRB_WITHOUT_FLOAT
    708802      return mrb_float_value(mrb, (mrb_float)a * (mrb_float)b);
     803#endif
    709804    }
    710805    return mrb_fixnum_value(c);
    711806  }
     807#ifdef MRB_WITHOUT_FLOAT
     808  mrb_raise(mrb, E_TYPE_ERROR, "non fixnum value");
     809#else
    712810  return mrb_float_value(mrb, (mrb_float)a * mrb_to_flo(mrb, y));
     811#endif
     812}
     813
     814MRB_API mrb_value
     815mrb_num_mul(mrb_state *mrb, mrb_value x, mrb_value y)
     816{
     817  if (mrb_fixnum_p(x)) {
     818    return fixnum_mul(mrb, x, y);
     819  }
     820#ifndef MRB_WITHOUT_FLOAT
     821  if (mrb_float_p(x)) {
     822    return mrb_float_value(mrb, mrb_float(x) * mrb_to_flo(mrb, y));
     823  }
     824#endif
     825  mrb_raise(mrb, E_TYPE_ERROR, "no number multiply");
     826  return mrb_nil_value();       /* not reached */
    713827}
    714828
     
    729843
    730844  mrb_get_args(mrb, "o", &y);
    731   return mrb_fixnum_mul(mrb, x, y);
     845  return fixnum_mul(mrb, x, y);
    732846}
    733847
     
    774888{
    775889  mrb_value y;
    776   mrb_int a;
     890  mrb_int a, b;
    777891
    778892  mrb_get_args(mrb, "o", &y);
    779893  a = mrb_fixnum(x);
    780   if (mrb_fixnum_p(y)) {
    781     mrb_int b, mod;
    782 
    783     if ((b=mrb_fixnum(y)) == 0) {
     894   if (mrb_fixnum_p(y) && a != MRB_INT_MIN && (b=mrb_fixnum(y)) != MRB_INT_MIN) {
     895    mrb_int mod;
     896
     897    if (b == 0) {
     898#ifdef MRB_WITHOUT_FLOAT
     899      /* ZeroDivisionError */
     900      return mrb_fixnum_value(0);
     901#else
     902      if (a > 0) return mrb_float_value(mrb, INFINITY);
     903      if (a < 0) return mrb_float_value(mrb, INFINITY);
    784904      return mrb_float_value(mrb, NAN);
    785     }
    786     fixdivmod(mrb, a, b, 0, &mod);
     905#endif
     906    }
     907    fixdivmod(mrb, a, b, NULL, &mod);
    787908    return mrb_fixnum_value(mod);
    788909  }
     910#ifdef MRB_WITHOUT_FLOAT
     911  mrb_raise(mrb, E_TYPE_ERROR, "non fixnum value");
     912#else
    789913  else {
    790914    mrb_float mod;
    791915
    792     flodivmod(mrb, (mrb_float)a, mrb_to_flo(mrb, y), 0, &mod);
     916    flodivmod(mrb, (mrb_float)a, mrb_to_flo(mrb, y), NULL, &mod);
    793917    return mrb_float_value(mrb, mod);
    794918  }
     919#endif
    795920}
    796921
     
    812937
    813938    if (mrb_fixnum(y) == 0) {
    814       return mrb_assoc_new(mrb, mrb_float_value(mrb, INFINITY),
    815         mrb_float_value(mrb, NAN));
     939#ifdef MRB_WITHOUT_FLOAT
     940      return mrb_assoc_new(mrb, mrb_fixnum_value(0), mrb_fixnum_value(0));
     941#else
     942      return mrb_assoc_new(mrb, ((mrb_fixnum(x) == 0) ?
     943                                 mrb_float_value(mrb, NAN):
     944                                 mrb_float_value(mrb, INFINITY)),
     945                           mrb_float_value(mrb, NAN));
     946#endif
    816947    }
    817948    fixdivmod(mrb, mrb_fixnum(x), mrb_fixnum(y), &div, &mod);
    818949    return mrb_assoc_new(mrb, mrb_fixnum_value(div), mrb_fixnum_value(mod));
    819950  }
     951#ifdef MRB_WITHOUT_FLOAT
     952  mrb_raise(mrb, E_TYPE_ERROR, "non fixnum value");
     953#else
    820954  else {
    821955    mrb_float div, mod;
     
    823957
    824958    flodivmod(mrb, (mrb_float)mrb_fixnum(x), mrb_to_flo(mrb, y), &div, &mod);
    825     a = mrb_float_value(mrb, (mrb_int)div);
     959    a = mrb_int_value(mrb, div);
    826960    b = mrb_float_value(mrb, mod);
    827961    return mrb_assoc_new(mrb, a, b);
    828962  }
    829 }
    830 
     963#endif
     964}
     965
     966#ifndef MRB_WITHOUT_FLOAT
    831967static mrb_value
    832968flo_divmod(mrb_state *mrb, mrb_value x)
     
    839975
    840976  flodivmod(mrb, mrb_float(x), mrb_to_flo(mrb, y), &div, &mod);
    841   a = mrb_float_value(mrb, (mrb_int)div);
     977  a = mrb_int_value(mrb, div);
    842978  b = mrb_float_value(mrb, mod);
    843979  return mrb_assoc_new(mrb, a, b);
    844980}
     981#endif
    845982
    846983/* 15.2.8.3.7  */
     
    8651002  case MRB_TT_FIXNUM:
    8661003    return mrb_bool_value(mrb_fixnum(x) == mrb_fixnum(y));
     1004#ifndef MRB_WITHOUT_FLOAT
    8671005  case MRB_TT_FLOAT:
    8681006    return mrb_bool_value((mrb_float)mrb_fixnum(x) == mrb_float(y));
     1007#endif
    8691008  default:
    8701009    return mrb_false_value();
     
    8911030}
    8921031
     1032#ifdef MRB_WITHOUT_FLOAT
     1033#define bit_op(x,y,op1,op2) do {\
     1034  return mrb_fixnum_value(mrb_fixnum(x) op2 mrb_fixnum(y));\
     1035} while(0)
     1036#else
    8931037static mrb_value flo_and(mrb_state *mrb, mrb_value x);
    8941038static mrb_value flo_or(mrb_state *mrb, mrb_value x);
     
    8961040#define bit_op(x,y,op1,op2) do {\
    8971041  if (mrb_fixnum_p(y)) return mrb_fixnum_value(mrb_fixnum(x) op2 mrb_fixnum(y));\
    898   return flo_ ## op1(mrb, mrb_float_value(mrb, mrb_fixnum(x)));\
     1042  return flo_ ## op1(mrb, mrb_float_value(mrb, (mrb_float)mrb_fixnum(x)));\
    8991043} while(0)
     1044#endif
    9001045
    9011046/* 15.2.8.3.9  */
     
    9561101{
    9571102  if (width < 0) {              /* mrb_int overflow */
     1103#ifdef MRB_WITHOUT_FLOAT
     1104    return mrb_fixnum_value(0);
     1105#else
    9581106    return mrb_float_value(mrb, INFINITY);
     1107#endif
    9591108  }
    9601109  if (val > 0) {
    9611110    if ((width > NUMERIC_SHIFT_WIDTH_MAX) ||
    9621111        (val   > (MRB_INT_MAX >> width))) {
     1112#ifdef MRB_WITHOUT_FLOAT
     1113      return mrb_fixnum_value(-1);
     1114#else
    9631115      goto bit_overflow;
    964     }
     1116#endif
     1117    }
     1118    return mrb_fixnum_value(val << width);
    9651119  }
    9661120  else {
    9671121    if ((width > NUMERIC_SHIFT_WIDTH_MAX) ||
    968         (val   < (MRB_INT_MIN >> width))) {
     1122        (val   <= (MRB_INT_MIN >> width))) {
     1123#ifdef MRB_WITHOUT_FLOAT
     1124      return mrb_fixnum_value(0);
     1125#else
    9691126      goto bit_overflow;
    970     }
    971   }
    972 
    973   return mrb_fixnum_value(val << width);
    974 
     1127#endif
     1128    }
     1129    return mrb_fixnum_value(val * ((mrb_int)1 << width));
     1130  }
     1131
     1132#ifndef MRB_WITHOUT_FLOAT
    9751133bit_overflow:
    9761134  {
     
    9811139    return mrb_float_value(mrb, f);
    9821140  }
     1141#endif
    9831142}
    9841143
     
    10571216 */
    10581217
     1218#ifndef MRB_WITHOUT_FLOAT
    10591219static mrb_value
    10601220fix_to_f(mrb_state *mrb, mrb_value num)
     
    10701230 *  to numerical classes which don't support them.
    10711231 *
    1072  *     Float::INFINITY.to_r
     1232 *     Float::INFINITY.to_i
    10731233 *
    10741234 *  <em>raises the exception:</em>
     
    10891249    mrb_float d = mrb_float(x);
    10901250
    1091     if (isinf(d)) {
    1092       mrb_raise(mrb, E_FLOATDOMAIN_ERROR, d < 0 ? "-Infinity" : "Infinity");
    1093     }
    1094     if (isnan(d)) {
    1095       mrb_raise(mrb, E_FLOATDOMAIN_ERROR, "NaN");
    1096     }
     1251    mrb_check_num_exact(mrb, d);
    10971252    if (FIXABLE_FLOAT(d)) {
    10981253      z = (mrb_int)d;
    10991254    }
    11001255    else {
    1101       mrb_raisef(mrb, E_ARGUMENT_ERROR, "number (%S) too big for integer", x);
     1256      mrb_raisef(mrb, E_RANGE_ERROR, "number (%v) too big for integer", x);
    11021257    }
    11031258  }
    11041259  return mrb_fixnum_value(z);
    11051260}
    1106 
    1107 mrb_value
    1108 mrb_fixnum_plus(mrb_state *mrb, mrb_value x, mrb_value y)
     1261#endif
     1262
     1263static mrb_value
     1264fixnum_plus(mrb_state *mrb, mrb_value x, mrb_value y)
    11091265{
    11101266  mrb_int a;
     
    11171273    b = mrb_fixnum(y);
    11181274    if (mrb_int_add_overflow(a, b, &c)) {
     1275#ifndef MRB_WITHOUT_FLOAT
    11191276      return mrb_float_value(mrb, (mrb_float)a + (mrb_float)b);
     1277#endif
    11201278    }
    11211279    return mrb_fixnum_value(c);
    11221280  }
     1281#ifdef MRB_WITHOUT_FLOAT
     1282  mrb_raise(mrb, E_TYPE_ERROR, "non fixnum value");
     1283#else
    11231284  return mrb_float_value(mrb, (mrb_float)a + mrb_to_flo(mrb, y));
     1285#endif
     1286}
     1287
     1288MRB_API mrb_value
     1289mrb_num_plus(mrb_state *mrb, mrb_value x, mrb_value y)
     1290{
     1291  if (mrb_fixnum_p(x)) {
     1292    return fixnum_plus(mrb, x, y);
     1293  }
     1294#ifndef MRB_WITHOUT_FLOAT
     1295  if (mrb_float_p(x)) {
     1296    return mrb_float_value(mrb, mrb_float(x) + mrb_to_flo(mrb, y));
     1297  }
     1298#endif
     1299  mrb_raise(mrb, E_TYPE_ERROR, "no number addition");
     1300  return mrb_nil_value();       /* not reached */
    11241301}
    11251302
     
    11391316
    11401317  mrb_get_args(mrb, "o", &other);
    1141   return mrb_fixnum_plus(mrb, self, other);
    1142 }
    1143 
    1144 mrb_value
    1145 mrb_fixnum_minus(mrb_state *mrb, mrb_value x, mrb_value y)
     1318  return fixnum_plus(mrb, self, other);
     1319}
     1320
     1321static mrb_value
     1322fixnum_minus(mrb_state *mrb, mrb_value x, mrb_value y)
    11461323{
    11471324  mrb_int a;
     
    11531330    b = mrb_fixnum(y);
    11541331    if (mrb_int_sub_overflow(a, b, &c)) {
     1332#ifndef MRB_WITHOUT_FLOAT
    11551333      return mrb_float_value(mrb, (mrb_float)a - (mrb_float)b);
     1334#endif
    11561335    }
    11571336    return mrb_fixnum_value(c);
    11581337  }
     1338#ifdef MRB_WITHOUT_FLOAT
     1339  mrb_raise(mrb, E_TYPE_ERROR, "non fixnum value");
     1340#else
    11591341  return mrb_float_value(mrb, (mrb_float)a - mrb_to_flo(mrb, y));
     1342#endif
     1343}
     1344
     1345MRB_API mrb_value
     1346mrb_num_minus(mrb_state *mrb, mrb_value x, mrb_value y)
     1347{
     1348  if (mrb_fixnum_p(x)) {
     1349    return fixnum_minus(mrb, x, y);
     1350  }
     1351#ifndef MRB_WITHOUT_FLOAT
     1352  if (mrb_float_p(x)) {
     1353    return mrb_float_value(mrb, mrb_float(x) - mrb_to_flo(mrb, y));
     1354  }
     1355#endif
     1356  mrb_raise(mrb, E_TYPE_ERROR, "no number subtraction");
     1357  return mrb_nil_value();       /* not reached */
    11601358}
    11611359
     
    11761374
    11771375  mrb_get_args(mrb, "o", &other);
    1178   return mrb_fixnum_minus(mrb, self, other);
     1376  return fixnum_minus(mrb, self, other);
    11791377}
    11801378
    11811379
    11821380MRB_API mrb_value
    1183 mrb_fixnum_to_str(mrb_state *mrb, mrb_value x, int base)
     1381mrb_fixnum_to_str(mrb_state *mrb, mrb_value x, mrb_int base)
    11841382{
    11851383  char buf[MRB_INT_BIT+1];
     
    11881386
    11891387  if (base < 2 || 36 < base) {
    1190     mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalid radix %S", mrb_fixnum_value(base));
     1388    mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalid radix %i", base);
    11911389  }
    11921390
     
    12321430  mrb_get_args(mrb, "|i", &base);
    12331431  return mrb_fixnum_to_str(mrb, self, base);
     1432}
     1433
     1434/* compare two numbers: (1:0:-1; -2 for error) */
     1435static mrb_int
     1436cmpnum(mrb_state *mrb, mrb_value v1, mrb_value v2)
     1437{
     1438#ifdef MRB_WITHOUT_FLOAT
     1439  mrb_int x, y;
     1440#else
     1441  mrb_float x, y;
     1442#endif
     1443
     1444#ifdef MRB_WITHOUT_FLOAT
     1445  x = mrb_fixnum(v1);
     1446#else
     1447  x = mrb_to_flo(mrb, v1);
     1448#endif
     1449  switch (mrb_type(v2)) {
     1450  case MRB_TT_FIXNUM:
     1451#ifdef MRB_WITHOUT_FLOAT
     1452    y = mrb_fixnum(v2);
     1453#else
     1454    y = (mrb_float)mrb_fixnum(v2);
     1455#endif
     1456    break;
     1457#ifndef MRB_WITHOUT_FLOAT
     1458  case MRB_TT_FLOAT:
     1459    y = mrb_float(v2);
     1460    break;
     1461#endif
     1462  default:
     1463    return -2;
     1464  }
     1465  if (x > y)
     1466    return 1;
     1467  else {
     1468    if (x < y)
     1469      return -1;
     1470    return 0;
     1471  }
    12341472}
    12351473
     
    12461484 */
    12471485static mrb_value
    1248 num_cmp(mrb_state *mrb, mrb_value self)
     1486integral_cmp(mrb_state *mrb, mrb_value self)
    12491487{
    12501488  mrb_value other;
    1251   mrb_float x, y;
     1489  mrb_int n;
    12521490
    12531491  mrb_get_args(mrb, "o", &other);
    1254 
    1255   x = mrb_to_flo(mrb, self);
    1256   switch (mrb_type(other)) {
     1492  n = cmpnum(mrb, self, other);
     1493  if (n == -2) return mrb_nil_value();
     1494  return mrb_fixnum_value(n);
     1495}
     1496
     1497static mrb_noreturn void
     1498cmperr(mrb_state *mrb, mrb_value v1, mrb_value v2)
     1499{
     1500  mrb_raisef(mrb, E_ARGUMENT_ERROR, "comparison of %t with %t failed", v1, v2);
     1501}
     1502
     1503static mrb_value
     1504integral_lt(mrb_state *mrb, mrb_value self)
     1505{
     1506  mrb_value other;
     1507  mrb_int n;
     1508
     1509  mrb_get_args(mrb, "o", &other);
     1510  n = cmpnum(mrb, self, other);
     1511  if (n == -2) cmperr(mrb, self, other);
     1512  if (n < 0) return mrb_true_value();
     1513  return mrb_false_value();
     1514}
     1515
     1516static mrb_value
     1517integral_le(mrb_state *mrb, mrb_value self)
     1518{
     1519  mrb_value other;
     1520  mrb_int n;
     1521
     1522  mrb_get_args(mrb, "o", &other);
     1523  n = cmpnum(mrb, self, other);
     1524  if (n == -2) cmperr(mrb, self, other);
     1525  if (n <= 0) return mrb_true_value();
     1526  return mrb_false_value();
     1527}
     1528
     1529static mrb_value
     1530integral_gt(mrb_state *mrb, mrb_value self)
     1531{
     1532  mrb_value other;
     1533  mrb_int n;
     1534
     1535  mrb_get_args(mrb, "o", &other);
     1536  n = cmpnum(mrb, self, other);
     1537  if (n == -2) cmperr(mrb, self, other);
     1538  if (n > 0) return mrb_true_value();
     1539  return mrb_false_value();
     1540}
     1541
     1542static mrb_value
     1543integral_ge(mrb_state *mrb, mrb_value self)
     1544{
     1545  mrb_value other;
     1546  mrb_int n;
     1547
     1548  mrb_get_args(mrb, "o", &other);
     1549  n = cmpnum(mrb, self, other);
     1550  if (n == -2) cmperr(mrb, self, other);
     1551  if (n >= 0) return mrb_true_value();
     1552  return mrb_false_value();
     1553}
     1554
     1555MRB_API mrb_int
     1556mrb_cmp(mrb_state *mrb, mrb_value obj1, mrb_value obj2)
     1557{
     1558  mrb_value v;
     1559
     1560  switch (mrb_type(obj1)) {
    12571561  case MRB_TT_FIXNUM:
    1258     y = (mrb_float)mrb_fixnum(other);
    1259     break;
    12601562  case MRB_TT_FLOAT:
    1261     y = mrb_float(other);
    1262     break;
     1563    return cmpnum(mrb, obj1, obj2);
     1564  case MRB_TT_STRING:
     1565    if (!mrb_string_p(obj2))
     1566      return -2;
     1567    return mrb_str_cmp(mrb, obj1, obj2);
    12631568  default:
    1264     return mrb_nil_value();
    1265   }
    1266   if (x > y)
    1267     return mrb_fixnum_value(1);
    1268   else {
    1269     if (x < y)
    1270       return mrb_fixnum_value(-1);
    1271     return mrb_fixnum_value(0);
    1272   }
     1569    v = mrb_funcall(mrb, obj1, "<=>", 1, obj2);
     1570    if (mrb_nil_p(v) || !mrb_fixnum_p(v))
     1571      return -2;
     1572    return mrb_fixnum(v);
     1573  }
     1574}
     1575
     1576static mrb_value
     1577num_finite_p(mrb_state *mrb, mrb_value self)
     1578{
     1579  return mrb_true_value();
     1580}
     1581
     1582static mrb_value
     1583num_infinite_p(mrb_state *mrb, mrb_value self)
     1584{
     1585  return mrb_false_value();
    12731586}
    12741587
     
    12811594 * and <code>other</code>.
    12821595 */
     1596#ifndef MRB_WITHOUT_FLOAT
    12831597static mrb_value
    12841598flo_plus(mrb_state *mrb, mrb_value x)
     
    12891603  return mrb_float_value(mrb, mrb_float(x) + mrb_to_flo(mrb, y));
    12901604}
     1605#endif
    12911606
    12921607/* ------------------------------------------------------------------------*/
     
    12941609mrb_init_numeric(mrb_state *mrb)
    12951610{
    1296   struct RClass *numeric, *integer, *fixnum, *fl;
     1611  struct RClass *numeric, *integer, *fixnum, *integral;
     1612#ifndef MRB_WITHOUT_FLOAT
     1613  struct RClass *fl;
     1614#endif
     1615
     1616  integral = mrb_define_module(mrb, "Integral");
     1617  mrb_define_method(mrb, integral,"**",       integral_pow,    MRB_ARGS_REQ(1));
     1618  mrb_define_method(mrb, integral,"/",        integral_div,    MRB_ARGS_REQ(1)); /* 15.2.{8,9}.3.6  */
     1619  mrb_define_method(mrb, integral,"quo",      integral_div,    MRB_ARGS_REQ(1)); /* 15.2.7.4.5 (x) */
     1620  mrb_define_method(mrb, integral,"div",      integral_idiv,   MRB_ARGS_REQ(1));
     1621  mrb_define_method(mrb, integral,"<=>",      integral_cmp,    MRB_ARGS_REQ(1)); /* 15.2.{8,9}.3.1  */
     1622  mrb_define_method(mrb, integral,"<",        integral_lt,     MRB_ARGS_REQ(1));
     1623  mrb_define_method(mrb, integral,"<=",       integral_le,     MRB_ARGS_REQ(1));
     1624  mrb_define_method(mrb, integral,">",        integral_gt,     MRB_ARGS_REQ(1));
     1625  mrb_define_method(mrb, integral,">=",       integral_ge,     MRB_ARGS_REQ(1));
     1626  mrb_define_method(mrb, integral,"__coerce_step_counter", integral_coerce_step_counter, MRB_ARGS_REQ(2));
    12971627
    12981628  /* Numeric Class */
    12991629  numeric = mrb_define_class(mrb, "Numeric",  mrb->object_class);                /* 15.2.7 */
    1300 
    1301   mrb_define_method(mrb, numeric, "**",       num_pow,         MRB_ARGS_REQ(1));
    1302   mrb_define_method(mrb, numeric, "/",        num_div,         MRB_ARGS_REQ(1)); /* 15.2.8.3.4  */
    1303   mrb_define_method(mrb, numeric, "quo",      num_div,         MRB_ARGS_REQ(1)); /* 15.2.7.4.5 (x) */
    1304   mrb_define_method(mrb, numeric, "<=>",      num_cmp,         MRB_ARGS_REQ(1)); /* 15.2.9.3.6  */
     1630  mrb_define_method(mrb, numeric, "finite?",  num_finite_p,    MRB_ARGS_NONE());
     1631  mrb_define_method(mrb, numeric, "infinite?",num_infinite_p,  MRB_ARGS_NONE());
    13051632
    13061633  /* Integer Class */
     
    13101637  mrb_define_method(mrb, integer, "to_i",     int_to_i,        MRB_ARGS_NONE()); /* 15.2.8.3.24 */
    13111638  mrb_define_method(mrb, integer, "to_int",   int_to_i,        MRB_ARGS_NONE());
    1312   mrb_define_method(mrb, integer, "ceil",     int_to_i,        MRB_ARGS_REQ(1)); /* 15.2.8.3.8 (x) */
    1313   mrb_define_method(mrb, integer, "floor",    int_to_i,        MRB_ARGS_REQ(1)); /* 15.2.8.3.10 (x) */
    1314   mrb_define_method(mrb, integer, "round",    int_to_i,        MRB_ARGS_REQ(1)); /* 15.2.8.3.12 (x) */
    1315   mrb_define_method(mrb, integer, "truncate", int_to_i,        MRB_ARGS_REQ(1)); /* 15.2.8.3.15 (x) */
     1639#ifndef MRB_WITHOUT_FLOAT
     1640  mrb_define_method(mrb, integer, "ceil",     int_to_i,        MRB_ARGS_NONE()); /* 15.2.8.3.8 (x) */
     1641  mrb_define_method(mrb, integer, "floor",    int_to_i,        MRB_ARGS_NONE()); /* 15.2.8.3.10 (x) */
     1642  mrb_define_method(mrb, integer, "round",    int_to_i,        MRB_ARGS_NONE()); /* 15.2.8.3.12 (x) */
     1643  mrb_define_method(mrb, integer, "truncate", int_to_i,        MRB_ARGS_NONE()); /* 15.2.8.3.15 (x) */
     1644#endif
    13161645
    13171646  /* Fixnum Class */
     
    13291658  mrb_define_method(mrb, fixnum,  ">>",       fix_rshift,      MRB_ARGS_REQ(1)); /* 15.2.8.3.13 */
    13301659  mrb_define_method(mrb, fixnum,  "eql?",     fix_eql,         MRB_ARGS_REQ(1)); /* 15.2.8.3.16 */
    1331   mrb_define_method(mrb, fixnum,  "hash",     flo_hash,        MRB_ARGS_NONE()); /* 15.2.8.3.18 */
     1660#ifndef MRB_WITHOUT_FLOAT
    13321661  mrb_define_method(mrb, fixnum,  "to_f",     fix_to_f,        MRB_ARGS_NONE()); /* 15.2.8.3.23 */
    1333   mrb_define_method(mrb, fixnum,  "to_s",     fix_to_s,        MRB_ARGS_NONE()); /* 15.2.8.3.25 */
    1334   mrb_define_method(mrb, fixnum,  "inspect",  fix_to_s,        MRB_ARGS_NONE());
     1662#endif
     1663  mrb_define_method(mrb, fixnum,  "to_s",     fix_to_s,        MRB_ARGS_OPT(1)); /* 15.2.8.3.25 */
     1664  mrb_define_method(mrb, fixnum,  "inspect",  fix_to_s,        MRB_ARGS_OPT(1));
    13351665  mrb_define_method(mrb, fixnum,  "divmod",   fix_divmod,      MRB_ARGS_REQ(1)); /* 15.2.8.3.30 (x) */
    13361666
     1667#ifndef MRB_WITHOUT_FLOAT
    13371668  /* Float Class */
    13381669  mrb->float_class = fl = mrb_define_class(mrb, "Float", numeric);                 /* 15.2.9 */
     
    13481679  mrb_define_method(mrb, fl,      "|",         flo_or,         MRB_ARGS_REQ(1));
    13491680  mrb_define_method(mrb, fl,      "^",         flo_xor,        MRB_ARGS_REQ(1));
    1350   mrb_define_method(mrb, fl,      ">>",        flo_lshift,     MRB_ARGS_REQ(1));
    1351   mrb_define_method(mrb, fl,      "<<",        flo_rshift,     MRB_ARGS_REQ(1));
     1681  mrb_define_method(mrb, fl,      ">>",        flo_rshift,     MRB_ARGS_REQ(1));
     1682  mrb_define_method(mrb, fl,      "<<",        flo_lshift,     MRB_ARGS_REQ(1));
    13521683  mrb_define_method(mrb, fl,      "ceil",      flo_ceil,       MRB_ARGS_NONE()); /* 15.2.9.3.8  */
    13531684  mrb_define_method(mrb, fl,      "finite?",   flo_finite_p,   MRB_ARGS_NONE()); /* 15.2.9.3.9  */
     
    13721703  mrb_define_const(mrb, fl, "NAN", mrb_float_value(mrb, NAN));
    13731704#endif
    1374 }
     1705
     1706  mrb_include_module(mrb, fl, integral);
     1707#endif
     1708}
Note: See TracChangeset for help on using the changeset viewer.