numeric.c


DEFINITIONS

This source file includes following functions.
  1. rb_num_zerodiv
  2. num_coerce
  3. coerce_body
  4. coerce_rescue
  5. do_coerce
  6. rb_num_coerce_bin
  7. num_become
  8. num_uplus
  9. num_uminus
  10. num_div
  11. num_divmod
  12. num_modulo
  13. num_remainder
  14. num_int_p
  15. num_abs
  16. num_zero_p
  17. num_nonzero_p
  18. num_to_int
  19. rb_float_new
  20. flo_to_s
  21. flo_coerce
  22. flo_uminus
  23. flo_plus
  24. flo_minus
  25. flo_mul
  26. flo_div
  27. flodivmod
  28. flo_mod
  29. flo_divmod
  30. flo_pow
  31. num_eql
  32. num_equal
  33. flo_eq
  34. flo_hash
  35. rb_dbl_cmp
  36. flo_cmp
  37. flo_gt
  38. flo_ge
  39. flo_lt
  40. flo_le
  41. flo_eql
  42. flo_to_f
  43. flo_abs
  44. flo_zero_p
  45. flo_is_nan_p
  46. flo_is_infinite_p
  47. flo_is_finite_p
  48. flo_floor
  49. flo_ceil
  50. flo_round
  51. flo_truncate
  52. num_floor
  53. num_ceil
  54. num_round
  55. num_truncate
  56. num_step
  57. rb_num2long
  58. rb_num2ulong
  59. rb_num2int
  60. rb_fix2int
  61. rb_num2int
  62. rb_fix2int
  63. rb_num2fix
  64. rb_num2ll
  65. rb_num2ull
  66. int_to_i
  67. int_int_p
  68. int_succ
  69. int_chr
  70. rb_fix_induced_from
  71. rb_int_induced_from
  72. rb_flo_induced_from
  73. fix_uminus
  74. rb_fix2str
  75. fix_to_s
  76. fix_plus
  77. fix_minus
  78. fix_mul
  79. fixdivmod
  80. fix_div
  81. fix_mod
  82. fix_divmod
  83. fix_pow
  84. fix_equal
  85. fix_cmp
  86. fix_gt
  87. fix_ge
  88. fix_lt
  89. fix_le
  90. fix_rev
  91. fix_and
  92. fix_or
  93. fix_xor
  94. fix_lshift
  95. fix_rshift
  96. fix_aref
  97. fix_to_f
  98. fix_abs
  99. fix_id2name
  100. fix_size
  101. int_upto
  102. int_downto
  103. int_dotimes
  104. fix_zero_p
  105. Init_Numeric


   1  /**********************************************************************
   2  
   3    numeric.c -
   4  
   5    $Author: michal $
   6    $Date: 2002/08/28 08:05:23 $
   7    created at: Fri Aug 13 18:33:09 JST 1993
   8  
   9    Copyright (C) 1993-2002 Yukihiro Matsumoto
  10  
  11  **********************************************************************/
  12  
  13  #include "ruby.h"
  14  #include <math.h>
  15  #include <stdio.h>
  16  #if defined(__FreeBSD__) && __FreeBSD__ < 4
  17  #include <floatingpoint.h>
  18  #endif
  19  
  20  static ID id_coerce, id_to_i, id_div;
  21  
  22  VALUE rb_cNumeric;
  23  VALUE rb_cFloat;
  24  VALUE rb_cInteger;
  25  VALUE rb_cFixnum;
  26  
  27  VALUE rb_eZeroDivError;
  28  VALUE rb_eFloatDomainError;
  29  
  30  void
  31  rb_num_zerodiv()
  32  {
  33      rb_raise(rb_eZeroDivError, "divided by 0");
  34  }
  35  
  36  static VALUE
  37  num_coerce(x, y)
  38      VALUE x, y;
  39  {
  40      if (CLASS_OF(x) == CLASS_OF(y))
  41          return rb_assoc_new(y, x);
  42      return rb_assoc_new(rb_Float(y), rb_Float(x));
  43  }
  44  
  45  static VALUE
  46  coerce_body(x)
  47      VALUE *x;
  48  {
  49      return rb_funcall(x[1], id_coerce, 1, x[0]);
  50  }
  51  
  52  static VALUE
  53  coerce_rescue(x)
  54      VALUE *x;
  55  {
  56      rb_raise(rb_eTypeError, "%s can't be coerced into %s",
  57               rb_special_const_p(x[1])?
  58               RSTRING(rb_inspect(x[1]))->ptr:
  59               rb_class2name(CLASS_OF(x[1])),
  60               rb_class2name(CLASS_OF(x[0])));
  61      return Qnil;                /* dummy */
  62  }
  63  
  64  static void
  65  do_coerce(x, y)
  66      VALUE *x, *y;
  67  {
  68      VALUE ary;
  69      VALUE a[2];
  70  
  71      a[0] = *x; a[1] = *y;
  72  
  73      ary = rb_rescue(coerce_body, (VALUE)a, coerce_rescue, (VALUE)a);
  74      if (TYPE(ary) != T_ARRAY || RARRAY(ary)->len != 2) {
  75          rb_raise(rb_eTypeError, "coerce must return [x, y]");
  76      }
  77  
  78      *x = RARRAY(ary)->ptr[0];
  79      *y = RARRAY(ary)->ptr[1];
  80  }
  81  
  82  VALUE
  83  rb_num_coerce_bin(x, y)
  84      VALUE x, y;
  85  {
  86      do_coerce(&x, &y);
  87      return rb_funcall(x, rb_frame_last_func(), 1, y);
  88  }
  89  
  90  static VALUE
  91  num_become(x, y)
  92      VALUE x, y;
  93  {
  94      /* Numerics are immutable values, which should not be copied */
  95      rb_raise(rb_eTypeError, "can't copy %s", rb_class2name(CLASS_OF(x)));
  96      return Qnil;                /* not reached */
  97  }
  98  
  99  static VALUE
 100  num_uplus(num)
 101      VALUE num;
 102  {
 103      return num;
 104  }
 105  
 106  static VALUE
 107  num_uminus(num)
 108      VALUE num;
 109  {
 110      VALUE zero;
 111  
 112      zero = INT2FIX(0);
 113      do_coerce(&zero, &num);
 114  
 115      return rb_funcall(zero, '-', 1, num);
 116  }
 117  
 118  static VALUE
 119  num_div(x, y)
 120      VALUE x, y;
 121  {
 122      return rb_funcall(x, id_div, 1, y);
 123  }
 124  
 125  static VALUE
 126  num_divmod(x, y)
 127      VALUE x, y;
 128  {
 129      VALUE div, mod;
 130  
 131      div = rb_funcall(x, id_div, 1, y);
 132      if (TYPE(div) == T_FLOAT) {
 133          double d = floor(RFLOAT(div)->value);
 134  
 135          if (RFLOAT(div)->value > d) {
 136              div = rb_float_new(d);
 137          }
 138      }
 139      mod = rb_funcall(x, '%', 1, y);
 140      return rb_assoc_new(div, mod);
 141  }
 142  
 143  static VALUE
 144  num_modulo(x, y)
 145      VALUE x, y;
 146  {
 147      return rb_funcall(x, '%', 1, y);
 148  }
 149  
 150  static VALUE
 151  num_remainder(x, y)
 152      VALUE x, y;
 153  {
 154      VALUE z = rb_funcall(x, '%', 1, y);
 155  
 156      if ((!rb_equal(z, INT2FIX(0))) &&
 157          ((RTEST(rb_funcall(x, '<', 1, INT2FIX(0))) &&
 158            RTEST(rb_funcall(y, '>', 1, INT2FIX(0)))) ||
 159           (RTEST(rb_funcall(x, '>', 1, INT2FIX(0))) &&
 160            RTEST(rb_funcall(y, '<', 1, INT2FIX(0)))))) {
 161          return rb_funcall(z, '-', 1, y);
 162      }
 163      return z;
 164  }
 165  
 166  static VALUE
 167  num_int_p(num)
 168      VALUE num;
 169  {
 170      return Qfalse;
 171  }
 172  
 173  static VALUE
 174  num_abs(num)
 175      VALUE num;
 176  {
 177      if (RTEST(rb_funcall(num, '<', 1, INT2FIX(0)))) {
 178          return rb_funcall(num, rb_intern("-@"), 0);
 179      }
 180      return num;
 181  }
 182  
 183  static VALUE
 184  num_zero_p(num)
 185      VALUE num;
 186  {
 187      if (rb_equal(num, INT2FIX(0))) {
 188          return Qtrue;
 189      }
 190      return Qfalse;
 191  }
 192  
 193  static VALUE
 194  num_nonzero_p(num)
 195      VALUE num;
 196  {
 197      if (RTEST(rb_funcall(num, rb_intern("zero?"), 0, 0))) {
 198          return Qnil;
 199      }
 200      return num;
 201  }
 202  
 203  static VALUE
 204  num_to_int(num)
 205      VALUE num;
 206  {
 207      return rb_funcall(num, id_to_i, 0, 0);
 208  }
 209  
 210  VALUE
 211  rb_float_new(d)
 212      double d;
 213  {
 214      NEWOBJ(flt, struct RFloat);
 215      OBJSETUP(flt, rb_cFloat, T_FLOAT);
 216  
 217      flt->value = d;
 218      return (VALUE)flt;
 219  }
 220  
 221  static VALUE
 222  flo_to_s(flt)
 223      VALUE flt;
 224  {
 225      char buf[24];
 226      char *fmt = "%.16g";
 227      double value = RFLOAT(flt)->value;
 228      double avalue, d1, d2;
 229  
 230      if (isinf(value))
 231          return rb_str_new2(value < 0 ? "-Infinity" : "Infinity");
 232      else if(isnan(value))
 233          return rb_str_new2("NaN");
 234      
 235      avalue = fabs(value);
 236      if (avalue == 0.0) {
 237          fmt = "%.1f";
 238      }
 239      else if (avalue < 1.0e-3) {
 240          d1 = avalue;
 241          while (d1 < 1.0) d1 *= 10.0;
 242          d1 = modf(d1, &d2);
 243          if (d1 == 0) fmt = "%.1e";
 244      }    
 245      else if (avalue >= 1.0e15) {
 246          d1 = avalue;
 247          while (d1 > 10.0) d1 /= 10.0;
 248          d1 = modf(d1, &d2);
 249          if (d1 == 0) fmt = "%.1e";
 250          else fmt = "%.16e";
 251      }    
 252      else if ((d1 = modf(value, &d2)) == 0) {
 253          fmt = "%.1f";
 254      }
 255      sprintf(buf, fmt, value);
 256  
 257      return rb_str_new2(buf);
 258  }
 259  
 260  static VALUE
 261  flo_coerce(x, y)
 262      VALUE x, y;
 263  {
 264      return rb_assoc_new(rb_Float(y), x);
 265  }
 266  
 267  static VALUE
 268  flo_uminus(flt)
 269      VALUE flt;
 270  {
 271      return rb_float_new(-RFLOAT(flt)->value);
 272  }
 273  
 274  static VALUE
 275  flo_plus(x, y)
 276      VALUE x, y;
 277  {
 278      switch (TYPE(y)) {
 279        case T_FIXNUM:
 280          return rb_float_new(RFLOAT(x)->value + (double)FIX2LONG(y));
 281        case T_BIGNUM:
 282          return rb_float_new(RFLOAT(x)->value + rb_big2dbl(y));
 283        case T_FLOAT:
 284          return rb_float_new(RFLOAT(x)->value + RFLOAT(y)->value);
 285        default:
 286          return rb_num_coerce_bin(x, y);
 287      }
 288  }
 289  
 290  static VALUE
 291  flo_minus(x, y)
 292      VALUE x, y;
 293  {
 294      switch (TYPE(y)) {
 295        case T_FIXNUM:
 296          return rb_float_new(RFLOAT(x)->value - (double)FIX2LONG(y));
 297        case T_BIGNUM:
 298          return rb_float_new(RFLOAT(x)->value - rb_big2dbl(y));
 299        case T_FLOAT:
 300          return rb_float_new(RFLOAT(x)->value - RFLOAT(y)->value);
 301        default:
 302          return rb_num_coerce_bin(x, y);
 303      }
 304  }
 305  
 306  static VALUE
 307  flo_mul(x, y)
 308      VALUE x, y;
 309  {
 310      switch (TYPE(y)) {
 311        case T_FIXNUM:
 312          return rb_float_new(RFLOAT(x)->value * (double)FIX2LONG(y));
 313        case T_BIGNUM:
 314          return rb_float_new(RFLOAT(x)->value * rb_big2dbl(y));
 315        case T_FLOAT:
 316          return rb_float_new(RFLOAT(x)->value * RFLOAT(y)->value);
 317        default:
 318          return rb_num_coerce_bin(x, y);
 319      }
 320  }
 321  
 322  static VALUE
 323  flo_div(x, y)
 324      VALUE x, y;
 325  {
 326      long f_y;
 327      double d;
 328  
 329      switch (TYPE(y)) {
 330        case T_FIXNUM:
 331          f_y = FIX2LONG(y);
 332          return rb_float_new(RFLOAT(x)->value / (double)f_y);
 333        case T_BIGNUM:
 334          d = rb_big2dbl(y);
 335          return rb_float_new(RFLOAT(x)->value / d);
 336        case T_FLOAT:
 337          return rb_float_new(RFLOAT(x)->value / RFLOAT(y)->value);
 338        default:
 339          return rb_num_coerce_bin(x, y);
 340      }
 341  }
 342  
 343  static void
 344  flodivmod(x, y, divp, modp)
 345      double x, y;
 346      double *divp, *modp;
 347  {
 348      double div, mod;
 349  
 350  #ifdef HAVE_FMOD
 351      mod = fmod(x, y);
 352  #else
 353      {
 354          double z;
 355  
 356          modf(x/y, &z);
 357          mod = x - z * y;
 358      }
 359  #endif
 360      div = (x - mod) / y;
 361      if (y*mod < 0) {
 362          mod += y;
 363          div -= 1.0;
 364      }
 365      if (modp) *modp = mod;
 366      if (divp) *divp = div;
 367  }
 368  
 369  static VALUE
 370  flo_mod(x, y)
 371      VALUE x, y;
 372  {
 373      double fy, mod;
 374  
 375      switch (TYPE(y)) {
 376        case T_FIXNUM:
 377          fy = (double)FIX2LONG(y);
 378          break;
 379        case T_BIGNUM:
 380          fy = rb_big2dbl(y);
 381          break;
 382        case T_FLOAT:
 383          fy = RFLOAT(y)->value;
 384          break;
 385        default:
 386          return rb_num_coerce_bin(x, y);
 387      }
 388      flodivmod(RFLOAT(x)->value, fy, 0, &mod);
 389      return rb_float_new(mod);
 390  }
 391  
 392  static VALUE
 393  flo_divmod(x, y)
 394      VALUE x, y;
 395  {
 396      double fy, div, mod;
 397  
 398      switch (TYPE(y)) {
 399        case T_FIXNUM:
 400          fy = (double)FIX2LONG(y);
 401          break;
 402        case T_BIGNUM:
 403          fy = rb_big2dbl(y);
 404          break;
 405        case T_FLOAT:
 406          fy = RFLOAT(y)->value;
 407          break;
 408        default:
 409          return rb_num_coerce_bin(x, y);
 410      }
 411      flodivmod(RFLOAT(x)->value, fy, &div, &mod);
 412      return rb_assoc_new(rb_float_new(div), rb_float_new(mod));
 413  }
 414  
 415  static VALUE
 416  flo_pow(x, y)
 417      VALUE x, y;
 418  {
 419      switch (TYPE(y)) {
 420        case T_FIXNUM:
 421          return rb_float_new(pow(RFLOAT(x)->value, (double)FIX2LONG(y)));
 422        case T_BIGNUM:
 423          return rb_float_new(pow(RFLOAT(x)->value, rb_big2dbl(y)));
 424        case T_FLOAT:
 425          return rb_float_new(pow(RFLOAT(x)->value, RFLOAT(y)->value));
 426        default:
 427          return rb_num_coerce_bin(x, y);
 428      }
 429  }
 430  
 431  static VALUE
 432  num_eql(x, y)
 433      VALUE x, y;
 434  {
 435      if (TYPE(x) != TYPE(y)) return Qfalse;
 436  
 437      return rb_equal(x, y);
 438  }
 439  
 440  static VALUE
 441  num_equal(x, y)
 442      VALUE x, y;
 443  {
 444      return rb_equal(y, x);
 445  }
 446  
 447  static VALUE
 448  flo_eq(x, y)
 449      VALUE x, y;
 450  {
 451      switch (TYPE(y)) {
 452        case T_FIXNUM:
 453          if (RFLOAT(x)->value == FIX2LONG(y)) return Qtrue;
 454          return Qfalse;
 455        case T_BIGNUM:
 456          return (RFLOAT(x)->value == rb_big2dbl(y))?Qtrue:Qfalse;
 457        case T_FLOAT:
 458          return (RFLOAT(x)->value == RFLOAT(y)->value)?Qtrue:Qfalse;
 459        default:
 460          return num_equal(x, y);
 461      }
 462  }
 463  
 464  static VALUE
 465  flo_hash(num)
 466      VALUE num;
 467  {
 468      double d;
 469      char *c;
 470      int i, hash;
 471  
 472      d = RFLOAT(num)->value;
 473      if (d == 0) d = fabs(d);
 474      c = (char*)&d;
 475      for (hash=0, i=0; i<sizeof(double);i++) {
 476          hash += c[i] * 971;
 477      }
 478      if (hash < 0) hash = -hash;
 479      return INT2FIX(hash);
 480  }
 481  
 482  VALUE
 483  rb_dbl_cmp(a, b)
 484      double a, b;
 485  {
 486      if (a == b) return INT2FIX(0);
 487      if (a > b) return INT2FIX(1);
 488      if (a < b) return INT2FIX(-1);
 489      rb_raise(rb_eFloatDomainError, "comparing NaN");
 490  }
 491  
 492  static VALUE
 493  flo_cmp(x, y)
 494      VALUE x, y;
 495  {
 496      double a, b;
 497  
 498      a = RFLOAT(x)->value;
 499      switch (TYPE(y)) {
 500        case T_FIXNUM:
 501          b = (double)FIX2LONG(y);
 502          break;
 503  
 504        case T_BIGNUM:
 505          b = rb_big2dbl(y);
 506          break;
 507  
 508        case T_FLOAT:
 509          b = RFLOAT(y)->value;
 510          break;
 511  
 512        default:
 513          return rb_num_coerce_bin(x, y);
 514      }
 515      return rb_dbl_cmp(a, b);
 516  }
 517  
 518  static VALUE
 519  flo_gt(x, y)
 520      VALUE x, y;
 521  {
 522      double a, b;
 523  
 524      a = RFLOAT(x)->value;
 525      switch (TYPE(y)) {
 526        case T_FIXNUM:
 527          b = (double)FIX2LONG(y);
 528          break;
 529  
 530        case T_BIGNUM:
 531          b = rb_big2dbl(y);
 532          break;
 533  
 534        case T_FLOAT:
 535          b = RFLOAT(y)->value;
 536          break;
 537  
 538        default:
 539          return rb_num_coerce_bin(x, y);
 540      }
 541      return (a > b)?Qtrue:Qfalse;
 542  }
 543  
 544  static VALUE
 545  flo_ge(x, y)
 546      VALUE x, y;
 547  {
 548      double a, b;
 549  
 550      a = RFLOAT(x)->value;
 551      switch (TYPE(y)) {
 552        case T_FIXNUM:
 553          b = (double)FIX2LONG(y);
 554          break;
 555  
 556        case T_BIGNUM:
 557          b = rb_big2dbl(y);
 558          break;
 559  
 560        case T_FLOAT:
 561          b = RFLOAT(y)->value;
 562          break;
 563  
 564        default:
 565          return rb_num_coerce_bin(x, y);
 566      }
 567      return (a >= b)?Qtrue:Qfalse;
 568  }
 569  
 570  static VALUE
 571  flo_lt(x, y)
 572      VALUE x, y;
 573  {
 574      double a, b;
 575  
 576      a = RFLOAT(x)->value;
 577      switch (TYPE(y)) {
 578        case T_FIXNUM:
 579          b = (double)FIX2LONG(y);
 580          break;
 581  
 582        case T_BIGNUM:
 583          b = rb_big2dbl(y);
 584          break;
 585  
 586        case T_FLOAT:
 587          b = RFLOAT(y)->value;
 588          break;
 589  
 590        default:
 591          return rb_num_coerce_bin(x, y);
 592      }
 593      return (a < b)?Qtrue:Qfalse;
 594  }
 595  
 596  static VALUE
 597  flo_le(x, y)
 598      VALUE x, y;
 599  {
 600      double a, b;
 601  
 602      a = RFLOAT(x)->value;
 603      switch (TYPE(y)) {
 604        case T_FIXNUM:
 605          b = (double)FIX2LONG(y);
 606          break;
 607  
 608        case T_BIGNUM:
 609          b = rb_big2dbl(y);
 610          break;
 611  
 612        case T_FLOAT:
 613          b = RFLOAT(y)->value;
 614          break;
 615  
 616        default:
 617          return rb_num_coerce_bin(x, y);
 618      }
 619      return (a <= b)?Qtrue:Qfalse;
 620  }
 621  
 622  static VALUE
 623  flo_eql(x, y)
 624      VALUE x, y;
 625  {
 626      if (TYPE(y) == T_FLOAT && RFLOAT(x)->value == RFLOAT(y)->value) {
 627          return Qtrue;
 628      }
 629      return Qfalse;
 630  }
 631  
 632  static VALUE
 633  flo_to_f(num)
 634      VALUE num;
 635  {
 636      return num;
 637  }
 638  
 639  static VALUE
 640  flo_abs(flt)
 641      VALUE flt;
 642  {
 643      double val = fabs(RFLOAT(flt)->value);
 644      return rb_float_new(val);
 645  }
 646  
 647  static VALUE
 648  flo_zero_p(num)
 649      VALUE num;
 650  {
 651      if (RFLOAT(num)->value == 0.0) {
 652          return Qtrue;
 653      }
 654      return Qfalse;
 655  }
 656  
 657  static VALUE
 658  flo_is_nan_p(num)
 659       VALUE num;
 660  {     
 661  
 662    double value = RFLOAT(num)->value;
 663  
 664    return isnan(value) ? Qtrue : Qfalse;
 665  }
 666  
 667  static VALUE
 668  flo_is_infinite_p(num)
 669       VALUE num;
 670  {     
 671    double value = RFLOAT(num)->value;
 672  
 673    if (isinf(value)) {
 674      return INT2FIX( value < 0 ? -1 : 1 );
 675    }
 676  
 677    return Qnil;
 678  }
 679  
 680  static VALUE
 681  flo_is_finite_p(num)
 682       VALUE num;
 683  {     
 684    double value = RFLOAT(num)->value;
 685  
 686    if (isinf(value) || isnan(value))
 687      return Qfalse;
 688    
 689    return Qtrue;
 690  }
 691  
 692  
 693  static VALUE
 694  flo_floor(num)
 695      VALUE num;
 696  {
 697      double f = floor(RFLOAT(num)->value);
 698      long val;
 699  
 700      if (!FIXABLE(f)) {
 701          return rb_dbl2big(f);
 702      }
 703      val = f;
 704      return LONG2FIX(val);
 705  }
 706  
 707  static VALUE
 708  flo_ceil(num)
 709      VALUE num;
 710  {
 711      double f = ceil(RFLOAT(num)->value);
 712      long val;
 713  
 714      if (!FIXABLE(f)) {
 715          return rb_dbl2big(f);
 716      }
 717      val = f;
 718      return LONG2FIX(val);
 719  }
 720  
 721  static VALUE
 722  flo_round(num)
 723      VALUE num;
 724  {
 725      double f = RFLOAT(num)->value;
 726      long val;
 727  
 728      if (f > 0.0) f = floor(f+0.5);
 729      if (f < 0.0) f = ceil(f-0.5);
 730  
 731      if (!FIXABLE(f)) {
 732          return rb_dbl2big(f);
 733      }
 734      val = f;
 735      return LONG2FIX(val);
 736  }
 737  
 738  static VALUE
 739  flo_truncate(num)
 740      VALUE num;
 741  {
 742      double f = RFLOAT(num)->value;
 743      long val;
 744  
 745      if (f > 0.0) f = floor(f);
 746      if (f < 0.0) f = ceil(f);
 747  
 748      if (!FIXABLE(f)) {
 749          return rb_dbl2big(f);
 750      }
 751      val = f;
 752      return LONG2FIX(val);
 753  }
 754  
 755  static VALUE
 756  num_floor(num)
 757      VALUE num;
 758  {
 759      return flo_floor(rb_Float(num));
 760  }
 761  
 762  static VALUE
 763  num_ceil(num)
 764      VALUE num;
 765  {
 766      return flo_ceil(rb_Float(num));
 767  }
 768  
 769  static VALUE
 770  num_round(num)
 771      VALUE num;
 772  {
 773      return flo_round(rb_Float(num));
 774  }
 775  
 776  static VALUE
 777  num_truncate(num)
 778      VALUE num;
 779  {
 780      return flo_truncate(rb_Float(num));
 781  }
 782  
 783  static VALUE
 784  num_step(argc, argv, from)
 785      int argc;
 786      VALUE *argv;
 787      VALUE from;
 788  {
 789      VALUE to, step;
 790  
 791      if (rb_scan_args(argc, argv, "11", &to, &step) == 1) {
 792          step = INT2FIX(1);
 793      }
 794      else if (rb_equal(step, INT2FIX(0))) {
 795          rb_raise(rb_eArgError, "step cannot be 0");
 796      }
 797  
 798      if (FIXNUM_P(from) && FIXNUM_P(to) && FIXNUM_P(step)) {
 799          long i, end, diff;
 800  
 801          i = FIX2LONG(from);
 802          end = FIX2LONG(to);
 803          diff = FIX2LONG(step);
 804  
 805          if (diff > 0) {
 806              while (i <= end) {
 807                  rb_yield(LONG2FIX(i));
 808                  i += diff;
 809              }
 810          }
 811          else {
 812              while (i >= end) {
 813                  rb_yield(LONG2FIX(i));
 814                  i += diff;
 815              }
 816          }
 817      }
 818      else if (TYPE(from) == T_FLOAT || TYPE(to) == T_FLOAT || TYPE(step) == T_FLOAT) {
 819          const double epsilon = 2.2204460492503131E-16;
 820          double beg = NUM2DBL(from);
 821          double end = NUM2DBL(to);
 822          double unit = NUM2DBL(step);
 823          double n = (end - beg)/unit;
 824          long i;
 825  
 826          n = floor(n + n*epsilon) + 1;
 827          for (i=0; i<n; i++) {
 828              rb_yield(rb_float_new(i*unit+beg));
 829          }
 830      }
 831      else {
 832          VALUE i = from;
 833          ID cmp;
 834  
 835          if (RTEST(rb_funcall(step, '>', 1, INT2FIX(0)))) {
 836              cmp = '>';
 837          }
 838          else {
 839              cmp = '<';
 840          }
 841          for (;;) {
 842              if (RTEST(rb_funcall(i, cmp, 1, to))) break;
 843              rb_yield(i);
 844              i = rb_funcall(i, '+', 1, step);
 845          }
 846      }
 847      return from;
 848  }
 849  
 850  long
 851  rb_num2long(val)
 852      VALUE val;
 853  {
 854      if (NIL_P(val)) {
 855          rb_raise(rb_eTypeError, "no implicit conversion from nil to integer");
 856      }
 857  
 858      if (FIXNUM_P(val)) return FIX2LONG(val);
 859  
 860      switch (TYPE(val)) {
 861        case T_FLOAT:
 862          if (RFLOAT(val)->value <= (double)LONG_MAX
 863              && RFLOAT(val)->value >= (double)LONG_MIN) {
 864              return (long)(RFLOAT(val)->value);
 865          }
 866          else {
 867              char buf[24];
 868              char *s;
 869  
 870              sprintf(buf, "%-.10g", RFLOAT(val)->value);
 871              if (s = strchr(buf, ' ')) *s = '\0';
 872              rb_raise(rb_eRangeError, "float %s out of range of integer", buf);
 873          }
 874  
 875        case T_BIGNUM:
 876          return rb_big2long(val);
 877  
 878        default:
 879          val = rb_to_int(val);
 880          return NUM2LONG(val);
 881      }
 882  }
 883  
 884  unsigned long
 885  rb_num2ulong(val)
 886      VALUE val;
 887  {
 888      if (TYPE(val) == T_BIGNUM) {
 889          return rb_big2ulong(val);
 890      }
 891      return (unsigned long)rb_num2long(val);
 892  }
 893  
 894  #if SIZEOF_INT < SIZEOF_LONG
 895  int
 896  rb_num2int(val)
 897      VALUE val;
 898  {
 899      long num = rb_num2long(val);
 900  
 901      if (num < INT_MIN || INT_MAX < num) {
 902          rb_raise(rb_eRangeError, "integer %ld too big to convert to `int'", num);
 903      }
 904      return (int)num;
 905  }
 906  
 907  int
 908  rb_fix2int(val)
 909      VALUE val;
 910  {
 911      long num = FIXNUM_P(val)?FIX2LONG(val):rb_num2long(val);
 912  
 913      if (num < INT_MIN || INT_MAX < num) {
 914          rb_raise(rb_eRangeError, "integer %ld too big to convert to `int'", num);
 915      }
 916      return (int)num;
 917  }
 918  #else
 919  int
 920  rb_num2int(val)
 921      VALUE val;
 922  {
 923      return rb_num2long(val);
 924  }
 925  
 926  int
 927  rb_fix2int(val)
 928      VALUE val;
 929  {
 930      return FIX2INT(val);
 931  }
 932  #endif
 933  
 934  VALUE
 935  rb_num2fix(val)
 936      VALUE val;
 937  {
 938      long v;
 939  
 940      if (FIXNUM_P(val)) return val;
 941  
 942      v = rb_num2long(val);
 943      if (!FIXABLE(v))
 944          rb_raise(rb_eRangeError, "integer %ld out of range of fixnum", v);
 945      return LONG2FIX(v);
 946  }
 947  
 948  #if HAVE_LONG_LONG
 949  
 950  LONG_LONG
 951  rb_num2ll(val)
 952      VALUE val;
 953  {
 954      if (NIL_P(val)) {
 955          rb_raise(rb_eTypeError, "no implicit conversion from nil");
 956      }
 957  
 958      if (FIXNUM_P(val)) return (LONG_LONG)FIX2LONG(val);
 959  
 960      switch (TYPE(val)) {
 961      case T_FLOAT:
 962          if (RFLOAT(val)->value <= (double)LLONG_MAX
 963              && RFLOAT(val)->value >= (double)LLONG_MIN) {
 964              return (LONG_LONG)(RFLOAT(val)->value);
 965          }
 966          else {
 967              char buf[24];
 968              char *s;
 969  
 970              sprintf(buf, "%-.10g", RFLOAT(val)->value);
 971              if (s = strchr(buf, ' ')) *s = '\0';
 972              rb_raise(rb_eRangeError, "float %s out of range of long long", buf);
 973          }
 974  
 975      case T_BIGNUM:
 976          return rb_big2ll(val);
 977  
 978      case T_STRING:
 979          rb_raise(rb_eTypeError, "no implicit conversion from string");
 980          return Qnil;            /* not reached */
 981  
 982      case T_TRUE:
 983      case T_FALSE:
 984          rb_raise(rb_eTypeError, "no implicit conversion from boolean");
 985          return Qnil;            /* not reached */
 986  
 987        default:
 988            val = rb_to_int(val);
 989            return NUM2LL(val);
 990      }
 991  }
 992  
 993  unsigned LONG_LONG
 994  rb_num2ull(val)
 995      VALUE val;
 996  {
 997      if (TYPE(val) == T_BIGNUM) {
 998          return rb_big2ull(val);
 999      }
1000      return (unsigned LONG_LONG)rb_num2ll(val);
1001  }
1002  
1003  #endif  /* HAVE_LONG_LONG */
1004  
1005  static VALUE
1006  int_to_i(num)
1007      VALUE num;
1008  {
1009      return num;
1010  }
1011  
1012  static VALUE
1013  int_int_p(num)
1014      VALUE num;
1015  {
1016      return Qtrue;
1017  }
1018  
1019  static VALUE
1020  int_succ(num)
1021      VALUE num;
1022  {
1023      if (FIXNUM_P(num)) {
1024          long i = FIX2LONG(num) + 1;
1025          return LONG2NUM(i);
1026      }
1027      return rb_funcall(num, '+', 1, INT2FIX(1));
1028  }
1029  
1030  static VALUE
1031  int_chr(num)
1032      VALUE num;
1033  {
1034      char c;
1035      long i = NUM2LONG(num);
1036  
1037      if (i < 0 || 0xff < i)
1038          rb_raise(rb_eRangeError, "%ld out of char range", i);
1039      c = i;
1040      return rb_str_new(&c, 1);
1041  }
1042  
1043  static VALUE
1044  rb_fix_induced_from(klass, x)
1045      VALUE klass, x;
1046  {
1047      return rb_num2fix(x);
1048  }
1049  
1050  static VALUE
1051  rb_int_induced_from(klass, x)
1052      VALUE klass, x;
1053  {
1054      switch (TYPE(x)) {
1055      case T_FIXNUM:
1056      case T_BIGNUM:
1057         return x;
1058      case T_FLOAT:
1059         return rb_funcall(x, id_to_i, 0);
1060      default:
1061         rb_raise(rb_eTypeError, "failed to convert %s into Integer",
1062                  rb_class2name(CLASS_OF(x)));
1063      }
1064  }
1065  
1066  static VALUE
1067  rb_flo_induced_from(klass, x)
1068      VALUE klass, x;
1069  {
1070      switch (TYPE(x)) {
1071      case T_FIXNUM:
1072      case T_BIGNUM:
1073         return rb_funcall(x, rb_intern("to_f"), 0);
1074      case T_FLOAT:
1075         return x;
1076      default:
1077         rb_raise(rb_eTypeError, "failed to convert %s into Float",
1078                  rb_class2name(CLASS_OF(x)));
1079      }
1080  }
1081  
1082  static VALUE
1083  fix_uminus(num)
1084      VALUE num;
1085  {
1086      return LONG2NUM(-FIX2LONG(num));
1087  }
1088  
1089  VALUE
1090  rb_fix2str(x, base)
1091      VALUE x;
1092      int base;
1093  {
1094      char fmt[4], buf[22], *b = buf;
1095      long val = FIX2LONG(x);
1096  
1097      fmt[0] = '%'; fmt[1] = 'l'; fmt[3] = '\0';
1098      if (base == 10) fmt[2] = 'd';
1099      else if (base == 16) fmt[2] = 'x';
1100      else if (base == 8) fmt[2] = 'o';
1101      else rb_raise(rb_eArgError, "illegal radix %d", base);
1102      if (val < 0) {
1103          val = -val;
1104          *b++ = '-';
1105      }
1106  
1107      sprintf(b, fmt, val);
1108      return rb_str_new2(buf);
1109  }
1110  
1111  static VALUE
1112  fix_to_s(argc, argv, x)
1113      int argc;
1114      VALUE *argv;
1115      VALUE x;
1116  {
1117      VALUE b;
1118      int base;
1119  
1120      rb_scan_args(argc, argv, "01", &b);
1121      if (argc == 0) base = 10;
1122      else base = NUM2INT(b);
1123  
1124      if (base == 2) {
1125          /* rb_fix2str() does not handle binary */
1126          return rb_big2str(rb_int2big(FIX2INT(x)), 2);
1127      }
1128      return rb_fix2str(x, base);
1129  }
1130  
1131  static VALUE
1132  fix_plus(x, y)
1133      VALUE x, y;
1134  {
1135      if (FIXNUM_P(y)) {
1136          long a, b, c;
1137          VALUE r;
1138  
1139          a = FIX2LONG(x);
1140          b = FIX2LONG(y);
1141          c = a + b;
1142          r = LONG2FIX(c);
1143  
1144          if (FIX2LONG(r) != c) {
1145              r = rb_big_plus(rb_int2big(a), rb_int2big(b));
1146          }
1147          return r;
1148      }
1149      if (TYPE(y) == T_FLOAT) {
1150          return rb_float_new((double)FIX2LONG(x) + RFLOAT(y)->value);
1151      }
1152      return rb_num_coerce_bin(x, y);
1153  }
1154  
1155  static VALUE
1156  fix_minus(x, y)
1157      VALUE x, y;
1158  {
1159      if (FIXNUM_P(y)) {
1160          long a, b, c;
1161          VALUE r;
1162  
1163          a = FIX2LONG(x);
1164          b = FIX2LONG(y);
1165          c = a - b;
1166          r = LONG2FIX(c);
1167  
1168          if (FIX2LONG(r) != c) {
1169              r = rb_big_minus(rb_int2big(a), rb_int2big(b));
1170          }
1171          return r;
1172      }
1173      if (TYPE(y) == T_FLOAT) {
1174          return rb_float_new((double)FIX2LONG(x) - RFLOAT(y)->value);
1175      }
1176      return rb_num_coerce_bin(x, y);
1177  }
1178  
1179  static VALUE
1180  fix_mul(x, y)
1181      VALUE x, y;
1182  {
1183      if (FIXNUM_P(y)) {
1184          long a, b, c;
1185          VALUE r;
1186  
1187          a = FIX2LONG(x);
1188          if (a == 0) return x;
1189  
1190          b = FIX2LONG(y);
1191          c = a * b;
1192          r = LONG2FIX(c);
1193  
1194          if (FIX2LONG(r) != c || c/a != b) {
1195              r = rb_big_mul(rb_int2big(a), rb_int2big(b));
1196          }
1197          return r;
1198      }
1199      if (TYPE(y) == T_FLOAT) {
1200          return rb_float_new((double)FIX2LONG(x) * RFLOAT(y)->value);
1201      }
1202      return rb_num_coerce_bin(x, y);
1203  }
1204  
1205  static void
1206  fixdivmod(x, y, divp, modp)
1207      long x, y;
1208      long *divp, *modp;
1209  {
1210      long div, mod;
1211  
1212      if (y == 0) rb_num_zerodiv();
1213      if (y < 0) {
1214          if (x < 0)
1215              div = -x / -y;
1216          else
1217              div = - (x / -y);
1218      }
1219      else {
1220          if (x < 0)
1221              div = - (-x / y);
1222          else
1223              div = x / y;
1224      }
1225      mod = x - div*y;
1226      if ((mod < 0 && y > 0) || (mod > 0 && y < 0)) {
1227          mod += y;
1228          div -= 1;
1229      }
1230      if (divp) *divp = div;
1231      if (modp) *modp = mod;
1232  }
1233  
1234  static VALUE
1235  fix_div(x, y)
1236      VALUE x, y;
1237  {
1238      if (FIXNUM_P(y)) {
1239          long div;
1240  
1241          fixdivmod(FIX2LONG(x), FIX2LONG(y), &div, 0);
1242          return LONG2NUM(div);
1243      }
1244      return rb_num_coerce_bin(x, y);
1245  }
1246  
1247  static VALUE
1248  fix_mod(x, y)
1249      VALUE x, y;
1250  {
1251      if (FIXNUM_P(y)) {
1252          long mod;
1253  
1254          fixdivmod(FIX2LONG(x), FIX2LONG(y), 0, &mod);
1255          return LONG2NUM(mod);
1256      }
1257      return rb_num_coerce_bin(x, y);
1258  }
1259  
1260  static VALUE
1261  fix_divmod(x, y)
1262      VALUE x, y;
1263  {
1264      if (FIXNUM_P(y)) {
1265          long div, mod;
1266  
1267          fixdivmod(FIX2LONG(x), FIX2LONG(y), &div, &mod);
1268  
1269          return rb_assoc_new(LONG2NUM(div), LONG2NUM(mod));
1270      }
1271      return rb_num_coerce_bin(x, y);
1272  }
1273  
1274  static VALUE
1275  fix_pow(x, y)
1276      VALUE x, y;
1277  {
1278      if (FIXNUM_P(y)) {
1279          long a, b;
1280  
1281          b = FIX2LONG(y);
1282          if (b == 0) return INT2FIX(1);
1283          if (b == 1) return x;
1284          a = FIX2LONG(x);
1285          if (b > 0) {
1286              return rb_big_pow(rb_int2big(a), y);
1287          }
1288          return rb_float_new(pow((double)a, (double)b));
1289      }
1290      return rb_num_coerce_bin(x, y);
1291  }
1292  
1293  static VALUE
1294  fix_equal(x, y)
1295      VALUE x, y;
1296  {
1297      if (FIXNUM_P(y)) {
1298          return (FIX2LONG(x) == FIX2LONG(y))?Qtrue:Qfalse;
1299      }
1300      else {
1301          return num_equal(x, y);
1302      }
1303  }
1304  
1305  static VALUE
1306  fix_cmp(x, y)
1307      VALUE x, y;
1308  {
1309      if (FIXNUM_P(y)) {
1310          long a = FIX2LONG(x), b = FIX2LONG(y);
1311  
1312          if (a == b) return INT2FIX(0);
1313          if (a > b) return INT2FIX(1);
1314          return INT2FIX(-1);
1315      }
1316      else {
1317          return rb_num_coerce_bin(x, y);
1318      }
1319  }
1320  
1321  static VALUE
1322  fix_gt(x, y)
1323      VALUE x, y;
1324  {
1325      if (FIXNUM_P(y)) {
1326          long a = FIX2LONG(x), b = FIX2LONG(y);
1327  
1328          if (a > b) return Qtrue;
1329          return Qfalse;
1330      }
1331      else {
1332          return rb_num_coerce_bin(x, y);
1333      }
1334  }
1335  
1336  static VALUE
1337  fix_ge(x, y)
1338      VALUE x, y;
1339  {
1340      if (FIXNUM_P(y)) {
1341          long a = FIX2LONG(x), b = FIX2LONG(y);
1342  
1343          if (a >= b) return Qtrue;
1344          return Qfalse;
1345      }
1346      else {
1347          return rb_num_coerce_bin(x, y);
1348      }
1349  }
1350  
1351  static VALUE
1352  fix_lt(x, y)
1353      VALUE x, y;
1354  {
1355      if (FIXNUM_P(y)) {
1356          long a = FIX2LONG(x), b = FIX2LONG(y);
1357  
1358          if (a < b) return Qtrue;
1359          return Qfalse;
1360      }
1361      else {
1362          return rb_num_coerce_bin(x, y);
1363      }
1364  }
1365  
1366  static VALUE
1367  fix_le(x, y)
1368      VALUE x, y;
1369  {
1370      if (FIXNUM_P(y)) {
1371          long a = FIX2LONG(x), b = FIX2LONG(y);
1372  
1373          if (a <= b) return Qtrue;
1374          return Qfalse;
1375      }
1376      else {
1377          return rb_num_coerce_bin(x, y);
1378      }
1379  }
1380  
1381  static VALUE
1382  fix_rev(num)
1383      VALUE num;
1384  {
1385      long val = FIX2LONG(num);
1386  
1387      val = ~val;
1388      return LONG2NUM(val);
1389  }
1390  
1391  static VALUE
1392  fix_and(x, y)
1393      VALUE x, y;
1394  {
1395      long val;
1396  
1397      if (TYPE(y) == T_BIGNUM) {
1398          return rb_big_and(y, x);
1399      }
1400      val = FIX2LONG(x) & NUM2LONG(y);
1401      return LONG2NUM(val);
1402  }
1403  
1404  static VALUE
1405  fix_or(x, y)
1406      VALUE x, y;
1407  {
1408      long val;
1409  
1410      if (TYPE(y) == T_BIGNUM) {
1411          return rb_big_or(y, x);
1412      }
1413      val = FIX2LONG(x) | NUM2LONG(y);
1414      return LONG2NUM(val);
1415  }
1416  
1417  static VALUE
1418  fix_xor(x, y)
1419      VALUE x, y;
1420  {
1421      long val;
1422  
1423      if (TYPE(y) == T_BIGNUM) {
1424          return rb_big_xor(y, x);
1425      }
1426      val = FIX2LONG(x) ^ NUM2LONG(y);
1427      return LONG2NUM(val);
1428  }
1429  
1430  static VALUE fix_rshift _((VALUE, VALUE));
1431  
1432  static VALUE
1433  fix_lshift(x, y)
1434      VALUE x, y;
1435  {
1436      long val, width;
1437  
1438      val = NUM2LONG(x);
1439      width = NUM2LONG(y);
1440      if (width < 0)
1441          return fix_rshift(x, LONG2FIX(-width));
1442      if (width > (sizeof(VALUE)*CHAR_BIT-1)
1443          || ((unsigned long)val)>>(sizeof(VALUE)*CHAR_BIT-1-width) > 0) {
1444          return rb_big_lshift(rb_int2big(val), y);
1445      }
1446      val = val << width;
1447      return LONG2NUM(val);
1448  }
1449  
1450  static VALUE
1451  fix_rshift(x, y)
1452      VALUE x, y;
1453  {
1454      long i, val;
1455  
1456      i = NUM2LONG(y);
1457      if (i < 0)
1458          return fix_lshift(x, LONG2FIX(-i));
1459      if (i == 0) return x;
1460      val = FIX2LONG(x);
1461      if (i >= sizeof(long)*CHAR_BIT-1) {
1462          if (val < 0) return INT2FIX(-1);
1463          return INT2FIX(0);
1464      }
1465      val = RSHIFT(val, i);
1466      return LONG2FIX(val);
1467  }
1468  
1469  static VALUE
1470  fix_aref(fix, idx)
1471      VALUE fix, idx;
1472  {
1473      long val = FIX2LONG(fix);
1474      long i;
1475  
1476      if (TYPE(idx) == T_BIGNUM) {
1477          idx = rb_big_norm(idx);
1478          if (!FIXNUM_P(idx)) {
1479              if (!RBIGNUM(idx)->sign || val >= 0)
1480                  return INT2FIX(0);
1481              return INT2FIX(1);
1482          }
1483      }
1484      i = NUM2LONG(idx);
1485  
1486      if (i < 0) return INT2FIX(0);
1487      if (sizeof(VALUE)*CHAR_BIT-1 < i) {
1488          if (val < 0) return INT2FIX(1);
1489          return INT2FIX(0);
1490      }
1491      if (val & (1L<<i))
1492          return INT2FIX(1);
1493      return INT2FIX(0);
1494  }
1495  
1496  static VALUE
1497  fix_to_f(num)
1498      VALUE num;
1499  {
1500      double val;
1501  
1502      val = (double)FIX2LONG(num);
1503  
1504      return rb_float_new(val);
1505  }
1506  
1507  static VALUE
1508  fix_abs(fix)
1509      VALUE fix;
1510  {
1511      long i = FIX2LONG(fix);
1512  
1513      if (i < 0) i = -i;
1514  
1515      return LONG2NUM(i);
1516  }
1517  
1518  static VALUE
1519  fix_id2name(fix)
1520      VALUE fix;
1521  {
1522      char *name = rb_id2name(FIX2UINT(fix));
1523      if (name) return rb_str_new2(name);
1524      return Qnil;
1525  }
1526  
1527  static VALUE
1528  fix_size(fix)
1529      VALUE fix;
1530  {
1531      return INT2FIX(sizeof(long));
1532  }
1533  
1534  static VALUE
1535  int_upto(from, to)
1536      VALUE from, to;
1537  {
1538      if (FIXNUM_P(from) && FIXNUM_P(to)) {
1539          long i, end;
1540  
1541          end = FIX2LONG(to);
1542          for (i = FIX2LONG(from); i <= end; i++) {
1543              rb_yield(LONG2FIX(i));
1544          }
1545      }
1546      else {
1547          VALUE i = from;
1548  
1549          for (;;) {
1550              if (RTEST(rb_funcall(i, '>', 1, to))) break;
1551              rb_yield(i);
1552              i = rb_funcall(i, '+', 1, INT2FIX(1));
1553          }
1554      }
1555      return from;
1556  }
1557  
1558  static VALUE
1559  int_downto(from, to)
1560      VALUE from, to;
1561  {
1562      if (FIXNUM_P(from) && FIXNUM_P(to)) {
1563          long i, end;
1564  
1565          end = FIX2LONG(to);
1566          for (i=FIX2LONG(from); i >= end; i--) {
1567              rb_yield(LONG2FIX(i));
1568          }
1569      }
1570      else {
1571          VALUE i = from;
1572  
1573          for (;;) {
1574              if (RTEST(rb_funcall(i, '<', 1, to))) break;
1575              rb_yield(i);
1576              i = rb_funcall(i, '-', 1, INT2FIX(1));
1577          }
1578      }
1579      return from;
1580  }
1581  
1582  static VALUE
1583  int_dotimes(num)
1584      VALUE num;
1585  {
1586      if (FIXNUM_P(num)) {
1587          long i, end;
1588  
1589          end = FIX2LONG(num);
1590          for (i=0; i<end; i++) {
1591              rb_yield(LONG2FIX(i));
1592          }
1593      }
1594      else {
1595          VALUE i = INT2FIX(0);
1596  
1597          for (;;) {
1598              if (!RTEST(rb_funcall(i, '<', 1, num))) break;
1599              rb_yield(i);
1600              i = rb_funcall(i, '+', 1, INT2FIX(1));
1601          }
1602      }
1603      return num;
1604  }
1605  
1606  static VALUE
1607  fix_zero_p(num)
1608      VALUE num;
1609  {
1610      if (FIX2LONG(num) == 0) {
1611          return Qtrue;
1612      }
1613      return Qfalse;
1614  }
1615  
1616  void
1617  Init_Numeric()
1618  {
1619  #if defined(__FreeBSD__) && __FreeBSD__ < 4
1620      /* allow divide by zero -- Inf */
1621      fpsetmask(fpgetmask() & ~(FP_X_DZ|FP_X_INV|FP_X_OFL));
1622  #endif
1623      id_coerce = rb_intern("coerce");
1624      id_to_i = rb_intern("to_i");
1625      id_div = rb_intern("div");
1626  
1627      rb_eZeroDivError = rb_define_class("ZeroDivisionError", rb_eStandardError);
1628      rb_eFloatDomainError = rb_define_class("FloatDomainError", rb_eRangeError);
1629      rb_cNumeric = rb_define_class("Numeric", rb_cObject);
1630  
1631      rb_include_module(rb_cNumeric, rb_mComparable);
1632      rb_define_method(rb_cNumeric, "coerce", num_coerce, 1);
1633      rb_define_method(rb_cNumeric, "become", num_become, 1);
1634  
1635      rb_define_method(rb_cNumeric, "+@", num_uplus, 0);
1636      rb_define_method(rb_cNumeric, "-@", num_uminus, 0);
1637      rb_define_method(rb_cNumeric, "===", num_equal, 1);
1638      rb_define_method(rb_cNumeric, "eql?", num_eql, 1);
1639      rb_define_method(rb_cNumeric, "/", num_div, 1);
1640      rb_define_method(rb_cNumeric, "divmod", num_divmod, 1);
1641      rb_define_method(rb_cNumeric, "modulo", num_modulo, 1);
1642      rb_define_method(rb_cNumeric, "remainder", num_remainder, 1);
1643      rb_define_method(rb_cNumeric, "abs", num_abs, 0);
1644      rb_define_method(rb_cNumeric, "to_int", num_to_int, 0);
1645  
1646      rb_define_method(rb_cNumeric, "integer?", num_int_p, 0);
1647      rb_define_method(rb_cNumeric, "zero?", num_zero_p, 0);
1648      rb_define_method(rb_cNumeric, "nonzero?", num_nonzero_p, 0);
1649  
1650      rb_define_method(rb_cNumeric, "floor", num_floor, 0);
1651      rb_define_method(rb_cNumeric, "ceil", num_ceil, 0);
1652      rb_define_method(rb_cNumeric, "round", num_round, 0);
1653      rb_define_method(rb_cNumeric, "truncate", num_truncate, 0);
1654      rb_define_method(rb_cNumeric, "step", num_step, -1);
1655  
1656      rb_cInteger = rb_define_class("Integer", rb_cNumeric);
1657      rb_undef_method(CLASS_OF(rb_cInteger), "allocate");
1658      rb_undef_method(CLASS_OF(rb_cInteger), "new");
1659  
1660      rb_define_method(rb_cInteger, "integer?", int_int_p, 0);
1661      rb_define_method(rb_cInteger, "upto", int_upto, 1);
1662      rb_define_method(rb_cInteger, "downto", int_downto, 1);
1663      rb_define_method(rb_cInteger, "times", int_dotimes, 0);
1664      rb_include_module(rb_cInteger, rb_mPrecision);
1665      rb_define_method(rb_cInteger, "succ", int_succ, 0);
1666      rb_define_method(rb_cInteger, "next", int_succ, 0);
1667      rb_define_method(rb_cInteger, "chr", int_chr, 0);
1668      rb_define_method(rb_cInteger, "to_i", int_to_i, 0);
1669      rb_define_method(rb_cInteger, "to_int", int_to_i, 0);
1670      rb_define_method(rb_cInteger, "floor", int_to_i, 0);
1671      rb_define_method(rb_cInteger, "ceil", int_to_i, 0);
1672      rb_define_method(rb_cInteger, "round", int_to_i, 0);
1673      rb_define_method(rb_cInteger, "truncate", int_to_i, 0);
1674  
1675      rb_cFixnum = rb_define_class("Fixnum", rb_cInteger);
1676      rb_include_module(rb_cFixnum, rb_mPrecision);
1677      rb_define_singleton_method(rb_cFixnum, "induced_from", rb_fix_induced_from, 1);
1678      rb_define_singleton_method(rb_cInteger, "induced_from", rb_int_induced_from, 1);
1679  
1680      rb_define_method(rb_cFixnum, "to_s", fix_to_s, -1);
1681  
1682      rb_define_method(rb_cFixnum, "id2name", fix_id2name, 0);
1683  
1684      rb_define_method(rb_cFixnum, "-@", fix_uminus, 0);
1685      rb_define_method(rb_cFixnum, "+", fix_plus, 1);
1686      rb_define_method(rb_cFixnum, "-", fix_minus, 1);
1687      rb_define_method(rb_cFixnum, "*", fix_mul, 1);
1688      rb_define_method(rb_cFixnum, "/", fix_div, 1);
1689      rb_define_method(rb_cFixnum, "div", fix_div, 1);
1690      rb_define_method(rb_cFixnum, "%", fix_mod, 1);
1691      rb_define_method(rb_cFixnum, "modulo", fix_mod, 1);
1692      rb_define_method(rb_cFixnum, "divmod", fix_divmod, 1);
1693      rb_define_method(rb_cFixnum, "**", fix_pow, 1);
1694  
1695      rb_define_method(rb_cFixnum, "abs", fix_abs, 0);
1696  
1697      rb_define_method(rb_cFixnum, "==", fix_equal, 1);
1698      rb_define_method(rb_cFixnum, "<=>", fix_cmp, 1);
1699      rb_define_method(rb_cFixnum, ">",  fix_gt, 1);
1700      rb_define_method(rb_cFixnum, ">=", fix_ge, 1);
1701      rb_define_method(rb_cFixnum, "<",  fix_lt, 1);
1702      rb_define_method(rb_cFixnum, "<=", fix_le, 1);
1703  
1704      rb_define_method(rb_cFixnum, "~", fix_rev, 0);
1705      rb_define_method(rb_cFixnum, "&", fix_and, 1);
1706      rb_define_method(rb_cFixnum, "|", fix_or,  1);
1707      rb_define_method(rb_cFixnum, "^", fix_xor, 1);
1708      rb_define_method(rb_cFixnum, "[]", fix_aref, 1);
1709  
1710      rb_define_method(rb_cFixnum, "<<", fix_lshift, 1);
1711      rb_define_method(rb_cFixnum, ">>", fix_rshift, 1);
1712  
1713      rb_define_method(rb_cFixnum, "to_f", fix_to_f, 0);
1714      rb_define_method(rb_cFixnum, "size", fix_size, 0);
1715      rb_define_method(rb_cFixnum, "zero?", fix_zero_p, 0);
1716  
1717      rb_cFloat  = rb_define_class("Float", rb_cNumeric);
1718  
1719      rb_undef_method(CLASS_OF(rb_cFloat), "allocate");
1720      rb_undef_method(CLASS_OF(rb_cFloat), "new");
1721  
1722      rb_define_singleton_method(rb_cFloat, "induced_from", rb_flo_induced_from, 1);
1723      rb_include_module(rb_cFloat, rb_mPrecision);
1724  
1725      rb_define_method(rb_cFloat, "to_s", flo_to_s, 0);
1726      rb_define_method(rb_cFloat, "coerce", flo_coerce, 1);
1727      rb_define_method(rb_cFloat, "-@", flo_uminus, 0);
1728      rb_define_method(rb_cFloat, "+", flo_plus, 1);
1729      rb_define_method(rb_cFloat, "-", flo_minus, 1);
1730      rb_define_method(rb_cFloat, "*", flo_mul, 1);
1731      rb_define_method(rb_cFloat, "/", flo_div, 1);
1732      rb_define_method(rb_cFloat, "%", flo_mod, 1);
1733      rb_define_method(rb_cFloat, "modulo", flo_mod, 1);
1734      rb_define_method(rb_cFloat, "divmod", flo_divmod, 1);
1735      rb_define_method(rb_cFloat, "**", flo_pow, 1);
1736      rb_define_method(rb_cFloat, "==", flo_eq, 1);
1737      rb_define_method(rb_cFloat, "<=>", flo_cmp, 1);
1738      rb_define_method(rb_cFloat, ">",  flo_gt, 1);
1739      rb_define_method(rb_cFloat, ">=", flo_ge, 1);
1740      rb_define_method(rb_cFloat, "<",  flo_lt, 1);
1741      rb_define_method(rb_cFloat, "<=", flo_le, 1);
1742      rb_define_method(rb_cFloat, "eql?", flo_eql, 1);
1743      rb_define_method(rb_cFloat, "hash", flo_hash, 0);
1744      rb_define_method(rb_cFloat, "to_f", flo_to_f, 0);
1745      rb_define_method(rb_cFloat, "abs", flo_abs, 0);
1746      rb_define_method(rb_cFloat, "zero?", flo_zero_p, 0);
1747  
1748      rb_define_method(rb_cFloat, "to_i", flo_truncate, 0);
1749      rb_define_method(rb_cFloat, "to_int", flo_truncate, 0);
1750      rb_define_method(rb_cFloat, "floor", flo_floor, 0);
1751      rb_define_method(rb_cFloat, "ceil", flo_ceil, 0);
1752      rb_define_method(rb_cFloat, "round", flo_round, 0);
1753      rb_define_method(rb_cFloat, "truncate", flo_truncate, 0);
1754  
1755      rb_define_method(rb_cFloat, "nan?",      flo_is_nan_p, 0);
1756      rb_define_method(rb_cFloat, "infinite?", flo_is_infinite_p, 0);
1757      rb_define_method(rb_cFloat, "finite?",   flo_is_finite_p, 0);
1758  }
1759