00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "ruby/ruby.h"
00013 #include "ruby/encoding.h"
00014 #include "ruby/util.h"
00015 #include "internal.h"
00016 #include "id.h"
00017 #include <ctype.h>
00018 #include <math.h>
00019 #include <stdio.h>
00020
00021 #if defined(__FreeBSD__) && __FreeBSD__ < 4
00022 #include <floatingpoint.h>
00023 #endif
00024
00025 #ifdef HAVE_FLOAT_H
00026 #include <float.h>
00027 #endif
00028
00029 #ifdef HAVE_IEEEFP_H
00030 #include <ieeefp.h>
00031 #endif
00032
00033 #if !defined HAVE_ISFINITE && !defined isfinite
00034 #if defined HAVE_FINITE && !defined finite && !defined _WIN32
00035 extern int finite(double);
00036 # define HAVE_ISFINITE 1
00037 # define isfinite(x) finite(x)
00038 #endif
00039 #endif
00040
00041
00042 #ifndef FLT_RADIX
00043 #define FLT_RADIX 2
00044 #endif
00045 #ifndef FLT_ROUNDS
00046 #define FLT_ROUNDS 1
00047 #endif
00048 #ifndef DBL_MIN
00049 #define DBL_MIN 2.2250738585072014e-308
00050 #endif
00051 #ifndef DBL_MAX
00052 #define DBL_MAX 1.7976931348623157e+308
00053 #endif
00054 #ifndef DBL_MIN_EXP
00055 #define DBL_MIN_EXP (-1021)
00056 #endif
00057 #ifndef DBL_MAX_EXP
00058 #define DBL_MAX_EXP 1024
00059 #endif
00060 #ifndef DBL_MIN_10_EXP
00061 #define DBL_MIN_10_EXP (-307)
00062 #endif
00063 #ifndef DBL_MAX_10_EXP
00064 #define DBL_MAX_10_EXP 308
00065 #endif
00066 #ifndef DBL_DIG
00067 #define DBL_DIG 15
00068 #endif
00069 #ifndef DBL_MANT_DIG
00070 #define DBL_MANT_DIG 53
00071 #endif
00072 #ifndef DBL_EPSILON
00073 #define DBL_EPSILON 2.2204460492503131e-16
00074 #endif
00075
00076 #ifdef HAVE_INFINITY
00077 #elif !defined(WORDS_BIGENDIAN)
00078 const union bytesequence4_or_float rb_infinity = {{0x00, 0x00, 0x80, 0x7f}};
00079 #else
00080 const union bytesequence4_or_float rb_infinity = {{0x7f, 0x80, 0x00, 0x00}};
00081 #endif
00082
00083 #ifdef HAVE_NAN
00084 #elif !defined(WORDS_BIGENDIAN)
00085 const union bytesequence4_or_float rb_nan = {{0x00, 0x00, 0xc0, 0x7f}};
00086 #else
00087 const union bytesequence4_or_float rb_nan = {{0x7f, 0xc0, 0x00, 0x00}};
00088 #endif
00089
00090 #ifndef HAVE_ROUND
00091 double
00092 round(double x)
00093 {
00094 double f;
00095
00096 if (x > 0.0) {
00097 f = floor(x);
00098 x = f + (x - f >= 0.5);
00099 }
00100 else if (x < 0.0) {
00101 f = ceil(x);
00102 x = f - (f - x >= 0.5);
00103 }
00104 return x;
00105 }
00106 #endif
00107
00108 static VALUE fix_uminus(VALUE num);
00109 static VALUE fix_mul(VALUE x, VALUE y);
00110 static VALUE int_pow(long x, unsigned long y);
00111
00112 static ID id_coerce, id_to_i, id_eq, id_div, id_cmp;
00113
00114 VALUE rb_cNumeric;
00115 VALUE rb_cFloat;
00116 VALUE rb_cInteger;
00117 VALUE rb_cFixnum;
00118
00119 VALUE rb_eZeroDivError;
00120 VALUE rb_eFloatDomainError;
00121
00122 static ID id_to, id_by;
00123
00124 void
00125 rb_num_zerodiv(void)
00126 {
00127 rb_raise(rb_eZeroDivError, "divided by 0");
00128 }
00129
00130
00131 int
00132 rb_num_to_uint(VALUE val, unsigned int *ret)
00133 {
00134 #define NUMERR_TYPE 1
00135 #define NUMERR_NEGATIVE 2
00136 #define NUMERR_TOOLARGE 3
00137 if (FIXNUM_P(val)) {
00138 long v = FIX2LONG(val);
00139 #if SIZEOF_INT < SIZEOF_LONG
00140 if (v > (long)UINT_MAX) return NUMERR_TOOLARGE;
00141 #endif
00142 if (v < 0) return NUMERR_NEGATIVE;
00143 *ret = (unsigned int)v;
00144 return 0;
00145 }
00146
00147 if (RB_TYPE_P(val, T_BIGNUM)) {
00148 if (RBIGNUM_NEGATIVE_P(val)) return NUMERR_NEGATIVE;
00149 #if SIZEOF_INT < SIZEOF_LONG
00150
00151 return NUMERR_TOOLARGE;
00152 #else
00153
00154 if (rb_absint_size(val, NULL) > sizeof(int)) return NUMERR_TOOLARGE;
00155 *ret = (unsigned int)rb_big2ulong((VALUE)val);
00156 return 0;
00157 #endif
00158 }
00159 return NUMERR_TYPE;
00160 }
00161
00162 #define method_basic_p(klass) rb_method_basic_definition_p(klass, mid)
00163
00164 static inline int
00165 positive_int_p(VALUE num)
00166 {
00167 const ID mid = '>';
00168
00169 if (FIXNUM_P(num)) {
00170 if (method_basic_p(rb_cFixnum))
00171 return (SIGNED_VALUE)num > 0;
00172 }
00173 else if (RB_TYPE_P(num, T_BIGNUM)) {
00174 if (method_basic_p(rb_cBignum))
00175 return RBIGNUM_POSITIVE_P(num);
00176 }
00177 return RTEST(rb_funcall(num, mid, 1, INT2FIX(0)));
00178 }
00179
00180 static inline int
00181 negative_int_p(VALUE num)
00182 {
00183 const ID mid = '<';
00184
00185 if (FIXNUM_P(num)) {
00186 if (method_basic_p(rb_cFixnum))
00187 return (SIGNED_VALUE)num < 0;
00188 }
00189 else if (RB_TYPE_P(num, T_BIGNUM)) {
00190 if (method_basic_p(rb_cBignum))
00191 return RBIGNUM_NEGATIVE_P(num);
00192 }
00193 return RTEST(rb_funcall(num, mid, 1, INT2FIX(0)));
00194 }
00195
00196 int
00197 rb_num_negative_p(VALUE num)
00198 {
00199 return negative_int_p(num);
00200 }
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219 static VALUE
00220 num_coerce(VALUE x, VALUE y)
00221 {
00222 if (CLASS_OF(x) == CLASS_OF(y))
00223 return rb_assoc_new(y, x);
00224 x = rb_Float(x);
00225 y = rb_Float(y);
00226 return rb_assoc_new(y, x);
00227 }
00228
00229 static VALUE
00230 coerce_body(VALUE *x)
00231 {
00232 return rb_funcall(x[1], id_coerce, 1, x[0]);
00233 }
00234
00235 NORETURN(static void coerce_failed(VALUE x, VALUE y));
00236 static void
00237 coerce_failed(VALUE x, VALUE y)
00238 {
00239 rb_raise(rb_eTypeError, "%"PRIsVALUE" can't be coerced into %"PRIsVALUE,
00240 (rb_special_const_p(y)? rb_inspect(y) : rb_obj_class(y)),
00241 rb_obj_class(x));
00242 }
00243
00244 static VALUE
00245 coerce_rescue(VALUE *x)
00246 {
00247 coerce_failed(x[0], x[1]);
00248 return Qnil;
00249 }
00250
00251 static int
00252 do_coerce(VALUE *x, VALUE *y, int err)
00253 {
00254 VALUE ary;
00255 VALUE a[2];
00256
00257 a[0] = *x; a[1] = *y;
00258
00259 if (!rb_respond_to(*y, id_coerce)) {
00260 if (err) {
00261 coerce_rescue(a);
00262 }
00263 return FALSE;
00264 }
00265
00266 ary = rb_rescue(coerce_body, (VALUE)a, err ? coerce_rescue : 0, (VALUE)a);
00267 if (!RB_TYPE_P(ary, T_ARRAY) || RARRAY_LEN(ary) != 2) {
00268 if (err) {
00269 rb_raise(rb_eTypeError, "coerce must return [x, y]");
00270 }
00271 return FALSE;
00272 }
00273
00274 *x = RARRAY_AREF(ary, 0);
00275 *y = RARRAY_AREF(ary, 1);
00276 return TRUE;
00277 }
00278
00279 VALUE
00280 rb_num_coerce_bin(VALUE x, VALUE y, ID func)
00281 {
00282 do_coerce(&x, &y, TRUE);
00283 return rb_funcall(x, func, 1, y);
00284 }
00285
00286 VALUE
00287 rb_num_coerce_cmp(VALUE x, VALUE y, ID func)
00288 {
00289 if (do_coerce(&x, &y, FALSE))
00290 return rb_funcall(x, func, 1, y);
00291 return Qnil;
00292 }
00293
00294 VALUE
00295 rb_num_coerce_relop(VALUE x, VALUE y, ID func)
00296 {
00297 VALUE c, x0 = x, y0 = y;
00298
00299 if (!do_coerce(&x, &y, FALSE) ||
00300 NIL_P(c = rb_funcall(x, func, 1, y))) {
00301 rb_cmperr(x0, y0);
00302 return Qnil;
00303 }
00304 return c;
00305 }
00306
00307
00308
00309
00310
00311
00312
00313 static VALUE
00314 num_sadded(VALUE x, VALUE name)
00315 {
00316 ID mid = rb_to_id(name);
00317
00318 rb_remove_method_id(rb_singleton_class(x), mid);
00319 rb_raise(rb_eTypeError,
00320 "can't define singleton method \"%s\" for %s",
00321 rb_id2name(mid),
00322 rb_obj_classname(x));
00323
00324 UNREACHABLE;
00325 }
00326
00327
00328
00329
00330
00331
00332 static VALUE
00333 num_init_copy(VALUE x, VALUE y)
00334 {
00335 rb_raise(rb_eTypeError, "can't copy %s", rb_obj_classname(x));
00336
00337 UNREACHABLE;
00338 }
00339
00340
00341
00342
00343
00344
00345
00346
00347 static VALUE
00348 num_uplus(VALUE num)
00349 {
00350 return num;
00351 }
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361 static VALUE
00362 num_imaginary(VALUE num)
00363 {
00364 return rb_complex_new(INT2FIX(0), num);
00365 }
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375 static VALUE
00376 num_uminus(VALUE num)
00377 {
00378 VALUE zero;
00379
00380 zero = INT2FIX(0);
00381 do_coerce(&zero, &num, TRUE);
00382
00383 return rb_funcall(zero, '-', 1, num);
00384 }
00385
00386
00387
00388
00389
00390
00391
00392
00393 static VALUE
00394 num_fdiv(VALUE x, VALUE y)
00395 {
00396 return rb_funcall(rb_Float(x), '/', 1, y);
00397 }
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412 static VALUE
00413 num_div(VALUE x, VALUE y)
00414 {
00415 if (rb_equal(INT2FIX(0), y)) rb_num_zerodiv();
00416 return rb_funcall(rb_funcall(x, '/', 1, y), rb_intern("floor"), 0);
00417 }
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431 static VALUE
00432 num_modulo(VALUE x, VALUE y)
00433 {
00434 return rb_funcall(x, '-', 1,
00435 rb_funcall(y, '*', 1,
00436 rb_funcall(x, rb_intern("div"), 1, y)));
00437 }
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448 static VALUE
00449 num_remainder(VALUE x, VALUE y)
00450 {
00451 VALUE z = rb_funcall(x, '%', 1, y);
00452
00453 if ((!rb_equal(z, INT2FIX(0))) &&
00454 ((negative_int_p(x) &&
00455 positive_int_p(y)) ||
00456 (positive_int_p(x) &&
00457 negative_int_p(y)))) {
00458 return rb_funcall(z, '-', 1, y);
00459 }
00460 return z;
00461 }
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505 static VALUE
00506 num_divmod(VALUE x, VALUE y)
00507 {
00508 return rb_assoc_new(num_div(x, y), num_modulo(x, y));
00509 }
00510
00511
00512
00513
00514
00515
00516
00517
00518 static VALUE
00519 num_real_p(VALUE num)
00520 {
00521 return Qtrue;
00522 }
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534 static VALUE
00535 num_int_p(VALUE num)
00536 {
00537 return Qfalse;
00538 }
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554 static VALUE
00555 num_abs(VALUE num)
00556 {
00557 if (negative_int_p(num)) {
00558 return rb_funcall(num, rb_intern("-@"), 0);
00559 }
00560 return num;
00561 }
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571 static VALUE
00572 num_zero_p(VALUE num)
00573 {
00574 if (rb_equal(num, INT2FIX(0))) {
00575 return Qtrue;
00576 }
00577 return Qfalse;
00578 }
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594 static VALUE
00595 num_nonzero_p(VALUE num)
00596 {
00597 if (RTEST(rb_funcall(num, rb_intern("zero?"), 0, 0))) {
00598 return Qnil;
00599 }
00600 return num;
00601 }
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614 static VALUE
00615 num_to_int(VALUE num)
00616 {
00617 return rb_funcall(num, id_to_i, 0, 0);
00618 }
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636 VALUE
00637 rb_float_new_in_heap(double d)
00638 {
00639 NEWOBJ_OF(flt, struct RFloat, rb_cFloat, T_FLOAT | (RGENGC_WB_PROTECTED_FLOAT ? FL_WB_PROTECTED : 0));
00640
00641 flt->float_value = d;
00642 OBJ_FREEZE(flt);
00643 return (VALUE)flt;
00644 }
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655 static VALUE
00656 flo_to_s(VALUE flt)
00657 {
00658 char *ruby_dtoa(double d_, int mode, int ndigits, int *decpt, int *sign, char **rve);
00659 enum {decimal_mant = DBL_MANT_DIG-DBL_DIG};
00660 enum {float_dig = DBL_DIG+1};
00661 char buf[float_dig + (decimal_mant + CHAR_BIT - 1) / CHAR_BIT + 10];
00662 double value = RFLOAT_VALUE(flt);
00663 VALUE s;
00664 char *p, *e;
00665 int sign, decpt, digs;
00666
00667 if (isinf(value))
00668 return rb_usascii_str_new2(value < 0 ? "-Infinity" : "Infinity");
00669 else if (isnan(value))
00670 return rb_usascii_str_new2("NaN");
00671
00672 p = ruby_dtoa(value, 0, 0, &decpt, &sign, &e);
00673 s = sign ? rb_usascii_str_new_cstr("-") : rb_usascii_str_new(0, 0);
00674 if ((digs = (int)(e - p)) >= (int)sizeof(buf)) digs = (int)sizeof(buf) - 1;
00675 memcpy(buf, p, digs);
00676 xfree(p);
00677 if (decpt > 0) {
00678 if (decpt < digs) {
00679 memmove(buf + decpt + 1, buf + decpt, digs - decpt);
00680 buf[decpt] = '.';
00681 rb_str_cat(s, buf, digs + 1);
00682 }
00683 else if (decpt <= DBL_DIG) {
00684 long len;
00685 char *ptr;
00686 rb_str_cat(s, buf, digs);
00687 rb_str_resize(s, (len = RSTRING_LEN(s)) + decpt - digs + 2);
00688 ptr = RSTRING_PTR(s) + len;
00689 if (decpt > digs) {
00690 memset(ptr, '0', decpt - digs);
00691 ptr += decpt - digs;
00692 }
00693 memcpy(ptr, ".0", 2);
00694 }
00695 else {
00696 goto exp;
00697 }
00698 }
00699 else if (decpt > -4) {
00700 long len;
00701 char *ptr;
00702 rb_str_cat(s, "0.", 2);
00703 rb_str_resize(s, (len = RSTRING_LEN(s)) - decpt + digs);
00704 ptr = RSTRING_PTR(s);
00705 memset(ptr += len, '0', -decpt);
00706 memcpy(ptr -= decpt, buf, digs);
00707 }
00708 else {
00709 exp:
00710 if (digs > 1) {
00711 memmove(buf + 2, buf + 1, digs - 1);
00712 }
00713 else {
00714 buf[2] = '0';
00715 digs++;
00716 }
00717 buf[1] = '.';
00718 rb_str_cat(s, buf, digs + 1);
00719 rb_str_catf(s, "e%+03d", decpt - 1);
00720 }
00721 return s;
00722 }
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737 static VALUE
00738 flo_coerce(VALUE x, VALUE y)
00739 {
00740 return rb_assoc_new(rb_Float(y), x);
00741 }
00742
00743
00744
00745
00746
00747
00748
00749
00750 static VALUE
00751 flo_uminus(VALUE flt)
00752 {
00753 return DBL2NUM(-RFLOAT_VALUE(flt));
00754 }
00755
00756
00757
00758
00759
00760
00761
00762
00763 static VALUE
00764 flo_plus(VALUE x, VALUE y)
00765 {
00766 if (RB_TYPE_P(y, T_FIXNUM)) {
00767 return DBL2NUM(RFLOAT_VALUE(x) + (double)FIX2LONG(y));
00768 }
00769 else if (RB_TYPE_P(y, T_BIGNUM)) {
00770 return DBL2NUM(RFLOAT_VALUE(x) + rb_big2dbl(y));
00771 }
00772 else if (RB_TYPE_P(y, T_FLOAT)) {
00773 return DBL2NUM(RFLOAT_VALUE(x) + RFLOAT_VALUE(y));
00774 }
00775 else {
00776 return rb_num_coerce_bin(x, y, '+');
00777 }
00778 }
00779
00780
00781
00782
00783
00784
00785
00786
00787 static VALUE
00788 flo_minus(VALUE x, VALUE y)
00789 {
00790 if (RB_TYPE_P(y, T_FIXNUM)) {
00791 return DBL2NUM(RFLOAT_VALUE(x) - (double)FIX2LONG(y));
00792 }
00793 else if (RB_TYPE_P(y, T_BIGNUM)) {
00794 return DBL2NUM(RFLOAT_VALUE(x) - rb_big2dbl(y));
00795 }
00796 else if (RB_TYPE_P(y, T_FLOAT)) {
00797 return DBL2NUM(RFLOAT_VALUE(x) - RFLOAT_VALUE(y));
00798 }
00799 else {
00800 return rb_num_coerce_bin(x, y, '-');
00801 }
00802 }
00803
00804
00805
00806
00807
00808
00809
00810
00811 static VALUE
00812 flo_mul(VALUE x, VALUE y)
00813 {
00814 if (RB_TYPE_P(y, T_FIXNUM)) {
00815 return DBL2NUM(RFLOAT_VALUE(x) * (double)FIX2LONG(y));
00816 }
00817 else if (RB_TYPE_P(y, T_BIGNUM)) {
00818 return DBL2NUM(RFLOAT_VALUE(x) * rb_big2dbl(y));
00819 }
00820 else if (RB_TYPE_P(y, T_FLOAT)) {
00821 return DBL2NUM(RFLOAT_VALUE(x) * RFLOAT_VALUE(y));
00822 }
00823 else {
00824 return rb_num_coerce_bin(x, y, '*');
00825 }
00826 }
00827
00828
00829
00830
00831
00832
00833
00834
00835 static VALUE
00836 flo_div(VALUE x, VALUE y)
00837 {
00838 long f_y;
00839 double d;
00840
00841 if (RB_TYPE_P(y, T_FIXNUM)) {
00842 f_y = FIX2LONG(y);
00843 return DBL2NUM(RFLOAT_VALUE(x) / (double)f_y);
00844 }
00845 else if (RB_TYPE_P(y, T_BIGNUM)) {
00846 d = rb_big2dbl(y);
00847 return DBL2NUM(RFLOAT_VALUE(x) / d);
00848 }
00849 else if (RB_TYPE_P(y, T_FLOAT)) {
00850 return DBL2NUM(RFLOAT_VALUE(x) / RFLOAT_VALUE(y));
00851 }
00852 else {
00853 return rb_num_coerce_bin(x, y, '/');
00854 }
00855 }
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865 static VALUE
00866 flo_quo(VALUE x, VALUE y)
00867 {
00868 return rb_funcall(x, '/', 1, y);
00869 }
00870
00871 static void
00872 flodivmod(double x, double y, double *divp, double *modp)
00873 {
00874 double div, mod;
00875
00876 if (y == 0.0) rb_num_zerodiv();
00877 if ((x == 0.0) || (isinf(y) && !isinf(x)))
00878 mod = x;
00879 else {
00880 #ifdef HAVE_FMOD
00881 mod = fmod(x, y);
00882 #else
00883 double z;
00884
00885 modf(x/y, &z);
00886 mod = x - z * y;
00887 #endif
00888 }
00889 if (isinf(x) && !isinf(y) && !isnan(y))
00890 div = x;
00891 else
00892 div = (x - mod) / y;
00893 if (y*mod < 0) {
00894 mod += y;
00895 div -= 1.0;
00896 }
00897 if (modp) *modp = mod;
00898 if (divp) *divp = div;
00899 }
00900
00901
00902
00903
00904
00905
00906 double
00907 ruby_float_mod(double x, double y)
00908 {
00909 double mod;
00910 flodivmod(x, y, 0, &mod);
00911 return mod;
00912 }
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923
00924
00925
00926 static VALUE
00927 flo_mod(VALUE x, VALUE y)
00928 {
00929 double fy;
00930
00931 if (RB_TYPE_P(y, T_FIXNUM)) {
00932 fy = (double)FIX2LONG(y);
00933 }
00934 else if (RB_TYPE_P(y, T_BIGNUM)) {
00935 fy = rb_big2dbl(y);
00936 }
00937 else if (RB_TYPE_P(y, T_FLOAT)) {
00938 fy = RFLOAT_VALUE(y);
00939 }
00940 else {
00941 return rb_num_coerce_bin(x, y, '%');
00942 }
00943 return DBL2NUM(ruby_float_mod(RFLOAT_VALUE(x), fy));
00944 }
00945
00946 static VALUE
00947 dbl2ival(double d)
00948 {
00949 d = round(d);
00950 if (FIXABLE(d)) {
00951 return LONG2FIX((long)d);
00952 }
00953 return rb_dbl2big(d);
00954 }
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966 static VALUE
00967 flo_divmod(VALUE x, VALUE y)
00968 {
00969 double fy, div, mod;
00970 volatile VALUE a, b;
00971
00972 if (RB_TYPE_P(y, T_FIXNUM)) {
00973 fy = (double)FIX2LONG(y);
00974 }
00975 else if (RB_TYPE_P(y, T_BIGNUM)) {
00976 fy = rb_big2dbl(y);
00977 }
00978 else if (RB_TYPE_P(y, T_FLOAT)) {
00979 fy = RFLOAT_VALUE(y);
00980 }
00981 else {
00982 return rb_num_coerce_bin(x, y, rb_intern("divmod"));
00983 }
00984 flodivmod(RFLOAT_VALUE(x), fy, &div, &mod);
00985 a = dbl2ival(div);
00986 b = DBL2NUM(mod);
00987 return rb_assoc_new(a, b);
00988 }
00989
00990
00991
00992
00993
00994
00995
00996
00997
00998
00999
01000 static VALUE
01001 flo_pow(VALUE x, VALUE y)
01002 {
01003 if (RB_TYPE_P(y, T_FIXNUM)) {
01004 return DBL2NUM(pow(RFLOAT_VALUE(x), (double)FIX2LONG(y)));
01005 }
01006 else if (RB_TYPE_P(y, T_BIGNUM)) {
01007 return DBL2NUM(pow(RFLOAT_VALUE(x), rb_big2dbl(y)));
01008 }
01009 else if (RB_TYPE_P(y, T_FLOAT)) {
01010 {
01011 double dx = RFLOAT_VALUE(x);
01012 double dy = RFLOAT_VALUE(y);
01013 if (dx < 0 && dy != round(dy))
01014 return rb_funcall(rb_complex_raw1(x), rb_intern("**"), 1, y);
01015 return DBL2NUM(pow(dx, dy));
01016 }
01017 }
01018 else {
01019 return rb_num_coerce_bin(x, y, rb_intern("**"));
01020 }
01021 }
01022
01023
01024
01025
01026
01027
01028
01029
01030
01031
01032
01033
01034
01035 static VALUE
01036 num_eql(VALUE x, VALUE y)
01037 {
01038 if (TYPE(x) != TYPE(y)) return Qfalse;
01039
01040 return rb_equal(x, y);
01041 }
01042
01043
01044
01045
01046
01047
01048
01049
01050
01051 static VALUE
01052 num_cmp(VALUE x, VALUE y)
01053 {
01054 if (x == y) return INT2FIX(0);
01055 return Qnil;
01056 }
01057
01058 static VALUE
01059 num_equal(VALUE x, VALUE y)
01060 {
01061 if (x == y) return Qtrue;
01062 return rb_funcall(y, id_eq, 1, x);
01063 }
01064
01065
01066
01067
01068
01069
01070
01071
01072
01073
01074
01075
01076
01077
01078
01079 static VALUE
01080 flo_eq(VALUE x, VALUE y)
01081 {
01082 volatile double a, b;
01083
01084 if (RB_TYPE_P(y, T_FIXNUM) || RB_TYPE_P(y, T_BIGNUM)) {
01085 return rb_integer_float_eq(y, x);
01086 }
01087 else if (RB_TYPE_P(y, T_FLOAT)) {
01088 b = RFLOAT_VALUE(y);
01089 #if defined(_MSC_VER) && _MSC_VER < 1300
01090 if (isnan(b)) return Qfalse;
01091 #endif
01092 }
01093 else {
01094 return num_equal(x, y);
01095 }
01096 a = RFLOAT_VALUE(x);
01097 #if defined(_MSC_VER) && _MSC_VER < 1300
01098 if (isnan(a)) return Qfalse;
01099 #endif
01100 return (a == b)?Qtrue:Qfalse;
01101 }
01102
01103
01104
01105
01106
01107
01108
01109
01110 static VALUE
01111 flo_hash(VALUE num)
01112 {
01113 double d;
01114 st_index_t hash;
01115
01116 d = RFLOAT_VALUE(num);
01117
01118 if (d == 0.0) d = 0.0;
01119 hash = rb_memhash(&d, sizeof(d));
01120 return LONG2FIX(hash);
01121 }
01122
01123 VALUE
01124 rb_dbl_cmp(double a, double b)
01125 {
01126 if (isnan(a) || isnan(b)) return Qnil;
01127 if (a == b) return INT2FIX(0);
01128 if (a > b) return INT2FIX(1);
01129 if (a < b) return INT2FIX(-1);
01130 return Qnil;
01131 }
01132
01133
01134
01135
01136
01137
01138
01139
01140
01141
01142
01143
01144
01145
01146 static VALUE
01147 flo_cmp(VALUE x, VALUE y)
01148 {
01149 double a, b;
01150 VALUE i;
01151
01152 a = RFLOAT_VALUE(x);
01153 if (isnan(a)) return Qnil;
01154 if (RB_TYPE_P(y, T_FIXNUM) || RB_TYPE_P(y, T_BIGNUM)) {
01155 VALUE rel = rb_integer_float_cmp(y, x);
01156 if (FIXNUM_P(rel))
01157 return INT2FIX(-FIX2INT(rel));
01158 return rel;
01159 }
01160 else if (RB_TYPE_P(y, T_FLOAT)) {
01161 b = RFLOAT_VALUE(y);
01162 }
01163 else {
01164 if (isinf(a) && (i = rb_check_funcall(y, rb_intern("infinite?"), 0, 0)) != Qundef) {
01165 if (RTEST(i)) {
01166 int j = rb_cmpint(i, x, y);
01167 j = (a > 0.0) ? (j > 0 ? 0 : +1) : (j < 0 ? 0 : -1);
01168 return INT2FIX(j);
01169 }
01170 if (a > 0.0) return INT2FIX(1);
01171 return INT2FIX(-1);
01172 }
01173 return rb_num_coerce_cmp(x, y, id_cmp);
01174 }
01175 return rb_dbl_cmp(a, b);
01176 }
01177
01178
01179
01180
01181
01182
01183
01184
01185
01186
01187
01188 static VALUE
01189 flo_gt(VALUE x, VALUE y)
01190 {
01191 double a, b;
01192
01193 a = RFLOAT_VALUE(x);
01194 if (RB_TYPE_P(y, T_FIXNUM) || RB_TYPE_P(y, T_BIGNUM)) {
01195 VALUE rel = rb_integer_float_cmp(y, x);
01196 if (FIXNUM_P(rel))
01197 return -FIX2INT(rel) > 0 ? Qtrue : Qfalse;
01198 return Qfalse;
01199 }
01200 else if (RB_TYPE_P(y, T_FLOAT)) {
01201 b = RFLOAT_VALUE(y);
01202 #if defined(_MSC_VER) && _MSC_VER < 1300
01203 if (isnan(b)) return Qfalse;
01204 #endif
01205 }
01206 else {
01207 return rb_num_coerce_relop(x, y, '>');
01208 }
01209 #if defined(_MSC_VER) && _MSC_VER < 1300
01210 if (isnan(a)) return Qfalse;
01211 #endif
01212 return (a > b)?Qtrue:Qfalse;
01213 }
01214
01215
01216
01217
01218
01219
01220
01221
01222
01223
01224
01225 static VALUE
01226 flo_ge(VALUE x, VALUE y)
01227 {
01228 double a, b;
01229
01230 a = RFLOAT_VALUE(x);
01231 if (RB_TYPE_P(y, T_FIXNUM) || RB_TYPE_P(y, T_BIGNUM)) {
01232 VALUE rel = rb_integer_float_cmp(y, x);
01233 if (FIXNUM_P(rel))
01234 return -FIX2INT(rel) >= 0 ? Qtrue : Qfalse;
01235 return Qfalse;
01236 }
01237 else if (RB_TYPE_P(y, T_FLOAT)) {
01238 b = RFLOAT_VALUE(y);
01239 #if defined(_MSC_VER) && _MSC_VER < 1300
01240 if (isnan(b)) return Qfalse;
01241 #endif
01242 }
01243 else {
01244 return rb_num_coerce_relop(x, y, rb_intern(">="));
01245 }
01246 #if defined(_MSC_VER) && _MSC_VER < 1300
01247 if (isnan(a)) return Qfalse;
01248 #endif
01249 return (a >= b)?Qtrue:Qfalse;
01250 }
01251
01252
01253
01254
01255
01256
01257
01258
01259
01260
01261
01262 static VALUE
01263 flo_lt(VALUE x, VALUE y)
01264 {
01265 double a, b;
01266
01267 a = RFLOAT_VALUE(x);
01268 if (RB_TYPE_P(y, T_FIXNUM) || RB_TYPE_P(y, T_BIGNUM)) {
01269 VALUE rel = rb_integer_float_cmp(y, x);
01270 if (FIXNUM_P(rel))
01271 return -FIX2INT(rel) < 0 ? Qtrue : Qfalse;
01272 return Qfalse;
01273 }
01274 else if (RB_TYPE_P(y, T_FLOAT)) {
01275 b = RFLOAT_VALUE(y);
01276 #if defined(_MSC_VER) && _MSC_VER < 1300
01277 if (isnan(b)) return Qfalse;
01278 #endif
01279 }
01280 else {
01281 return rb_num_coerce_relop(x, y, '<');
01282 }
01283 #if defined(_MSC_VER) && _MSC_VER < 1300
01284 if (isnan(a)) return Qfalse;
01285 #endif
01286 return (a < b)?Qtrue:Qfalse;
01287 }
01288
01289
01290
01291
01292
01293
01294
01295
01296
01297
01298
01299 static VALUE
01300 flo_le(VALUE x, VALUE y)
01301 {
01302 double a, b;
01303
01304 a = RFLOAT_VALUE(x);
01305 if (RB_TYPE_P(y, T_FIXNUM) || RB_TYPE_P(y, T_BIGNUM)) {
01306 VALUE rel = rb_integer_float_cmp(y, x);
01307 if (FIXNUM_P(rel))
01308 return -FIX2INT(rel) <= 0 ? Qtrue : Qfalse;
01309 return Qfalse;
01310 }
01311 else if (RB_TYPE_P(y, T_FLOAT)) {
01312 b = RFLOAT_VALUE(y);
01313 #if defined(_MSC_VER) && _MSC_VER < 1300
01314 if (isnan(b)) return Qfalse;
01315 #endif
01316 }
01317 else {
01318 return rb_num_coerce_relop(x, y, rb_intern("<="));
01319 }
01320 #if defined(_MSC_VER) && _MSC_VER < 1300
01321 if (isnan(a)) return Qfalse;
01322 #endif
01323 return (a <= b)?Qtrue:Qfalse;
01324 }
01325
01326
01327
01328
01329
01330
01331
01332
01333
01334
01335
01336
01337
01338
01339 static VALUE
01340 flo_eql(VALUE x, VALUE y)
01341 {
01342 if (RB_TYPE_P(y, T_FLOAT)) {
01343 double a = RFLOAT_VALUE(x);
01344 double b = RFLOAT_VALUE(y);
01345 #if defined(_MSC_VER) && _MSC_VER < 1300
01346 if (isnan(a) || isnan(b)) return Qfalse;
01347 #endif
01348 if (a == b)
01349 return Qtrue;
01350 }
01351 return Qfalse;
01352 }
01353
01354
01355
01356
01357
01358
01359
01360
01361 static VALUE
01362 flo_to_f(VALUE num)
01363 {
01364 return num;
01365 }
01366
01367
01368
01369
01370
01371
01372
01373
01374
01375
01376
01377
01378
01379 static VALUE
01380 flo_abs(VALUE flt)
01381 {
01382 double val = fabs(RFLOAT_VALUE(flt));
01383 return DBL2NUM(val);
01384 }
01385
01386
01387
01388
01389
01390
01391
01392
01393
01394 static VALUE
01395 flo_zero_p(VALUE num)
01396 {
01397 if (RFLOAT_VALUE(num) == 0.0) {
01398 return Qtrue;
01399 }
01400 return Qfalse;
01401 }
01402
01403
01404
01405
01406
01407
01408
01409
01410
01411
01412
01413
01414
01415 static VALUE
01416 flo_is_nan_p(VALUE num)
01417 {
01418 double value = RFLOAT_VALUE(num);
01419
01420 return isnan(value) ? Qtrue : Qfalse;
01421 }
01422
01423
01424
01425
01426
01427
01428
01429
01430
01431
01432
01433
01434
01435
01436
01437
01438
01439
01440 static VALUE
01441 flo_is_infinite_p(VALUE num)
01442 {
01443 double value = RFLOAT_VALUE(num);
01444
01445 if (isinf(value)) {
01446 return INT2FIX( value < 0 ? -1 : 1 );
01447 }
01448
01449 return Qnil;
01450 }
01451
01452
01453
01454
01455
01456
01457
01458
01459
01460
01461 static VALUE
01462 flo_is_finite_p(VALUE num)
01463 {
01464 double value = RFLOAT_VALUE(num);
01465
01466 #if HAVE_ISFINITE
01467 if (!isfinite(value))
01468 return Qfalse;
01469 #else
01470 if (isinf(value) || isnan(value))
01471 return Qfalse;
01472 #endif
01473
01474 return Qtrue;
01475 }
01476
01477
01478
01479
01480
01481
01482
01483
01484
01485
01486
01487
01488
01489 static VALUE
01490 flo_floor(VALUE num)
01491 {
01492 double f = floor(RFLOAT_VALUE(num));
01493 long val;
01494
01495 if (!FIXABLE(f)) {
01496 return rb_dbl2big(f);
01497 }
01498 val = (long)f;
01499 return LONG2FIX(val);
01500 }
01501
01502
01503
01504
01505
01506
01507
01508
01509
01510
01511
01512
01513
01514 static VALUE
01515 flo_ceil(VALUE num)
01516 {
01517 double f = ceil(RFLOAT_VALUE(num));
01518 long val;
01519
01520 if (!FIXABLE(f)) {
01521 return rb_dbl2big(f);
01522 }
01523 val = (long)f;
01524 return LONG2FIX(val);
01525 }
01526
01527
01528
01529
01530 static VALUE
01531 int_round_0(VALUE num, int ndigits)
01532 {
01533 VALUE n, f, h, r;
01534 long bytes;
01535 ID op;
01536
01537
01538 bytes = FIXNUM_P(num) ? sizeof(long) : rb_funcall(num, idSize, 0);
01539 if (-0.415241 * ndigits - 0.125 > bytes ) {
01540 return INT2FIX(0);
01541 }
01542
01543 f = int_pow(10, -ndigits);
01544 if (FIXNUM_P(num) && FIXNUM_P(f)) {
01545 SIGNED_VALUE x = FIX2LONG(num), y = FIX2LONG(f);
01546 int neg = x < 0;
01547 if (neg) x = -x;
01548 x = (x + y / 2) / y * y;
01549 if (neg) x = -x;
01550 return LONG2NUM(x);
01551 }
01552 if (RB_TYPE_P(f, T_FLOAT)) {
01553
01554 return INT2FIX(0);
01555 }
01556 h = rb_funcall(f, '/', 1, INT2FIX(2));
01557 r = rb_funcall(num, '%', 1, f);
01558 n = rb_funcall(num, '-', 1, r);
01559 op = negative_int_p(num) ? rb_intern("<=") : '<';
01560 if (!RTEST(rb_funcall(r, op, 1, h))) {
01561 n = rb_funcall(n, '+', 1, f);
01562 }
01563 return n;
01564 }
01565
01566 static VALUE
01567 flo_truncate(VALUE num);
01568
01569
01570
01571
01572
01573
01574
01575
01576
01577
01578
01579
01580
01581
01582
01583
01584
01585
01586
01587
01588
01589
01590
01591
01592
01593
01594
01595
01596
01597
01598
01599
01600 static VALUE
01601 flo_round(int argc, VALUE *argv, VALUE num)
01602 {
01603 VALUE nd;
01604 double number, f;
01605 int ndigits = 0;
01606 int binexp;
01607 enum {float_dig = DBL_DIG+2};
01608
01609 if (argc > 0 && rb_scan_args(argc, argv, "01", &nd) == 1) {
01610 ndigits = NUM2INT(nd);
01611 }
01612 if (ndigits < 0) {
01613 return int_round_0(flo_truncate(num), ndigits);
01614 }
01615 number = RFLOAT_VALUE(num);
01616 if (ndigits == 0) {
01617 return dbl2ival(number);
01618 }
01619 frexp(number, &binexp);
01620
01621
01622
01623
01624
01625
01626
01627
01628
01629
01630
01631
01632
01633
01634
01635
01636
01637
01638 if (isinf(number) || isnan(number) ||
01639 (ndigits >= float_dig - (binexp > 0 ? binexp / 4 : binexp / 3 - 1))) {
01640 return num;
01641 }
01642 if (ndigits < - (binexp > 0 ? binexp / 3 + 1 : binexp / 4)) {
01643 return DBL2NUM(0);
01644 }
01645 f = pow(10, ndigits);
01646 return DBL2NUM(round(number * f) / f);
01647 }
01648
01649
01650
01651
01652
01653
01654
01655
01656
01657
01658
01659
01660 static VALUE
01661 flo_truncate(VALUE num)
01662 {
01663 double f = RFLOAT_VALUE(num);
01664 long val;
01665
01666 if (f > 0.0) f = floor(f);
01667 if (f < 0.0) f = ceil(f);
01668
01669 if (!FIXABLE(f)) {
01670 return rb_dbl2big(f);
01671 }
01672 val = (long)f;
01673 return LONG2FIX(val);
01674 }
01675
01676
01677
01678
01679
01680
01681
01682
01683
01684
01685
01686
01687
01688
01689 static VALUE
01690 num_floor(VALUE num)
01691 {
01692 return flo_floor(rb_Float(num));
01693 }
01694
01695
01696
01697
01698
01699
01700
01701
01702
01703
01704
01705
01706
01707
01708
01709
01710
01711
01712 static VALUE
01713 num_ceil(VALUE num)
01714 {
01715 return flo_ceil(rb_Float(num));
01716 }
01717
01718
01719
01720
01721
01722
01723
01724
01725
01726
01727
01728
01729
01730
01731 static VALUE
01732 num_round(int argc, VALUE* argv, VALUE num)
01733 {
01734 return flo_round(argc, argv, rb_Float(num));
01735 }
01736
01737
01738
01739
01740
01741
01742
01743
01744
01745
01746
01747 static VALUE
01748 num_truncate(VALUE num)
01749 {
01750 return flo_truncate(rb_Float(num));
01751 }
01752
01753 static double
01754 ruby_float_step_size(double beg, double end, double unit, int excl)
01755 {
01756 const double epsilon = DBL_EPSILON;
01757 double n = (end - beg)/unit;
01758 double err = (fabs(beg) + fabs(end) + fabs(end-beg)) / fabs(unit) * epsilon;
01759
01760 if (isinf(unit)) {
01761 return unit > 0 ? beg <= end : beg >= end;
01762 }
01763 if (unit == 0) {
01764 return INFINITY;
01765 }
01766 if (err>0.5) err=0.5;
01767 if (excl) {
01768 if (n<=0) return 0;
01769 if (n<1)
01770 n = 0;
01771 else
01772 n = floor(n - err);
01773 }
01774 else {
01775 if (n<0) return 0;
01776 n = floor(n + err);
01777 }
01778 return n+1;
01779 }
01780
01781 int
01782 ruby_float_step(VALUE from, VALUE to, VALUE step, int excl)
01783 {
01784 if (RB_TYPE_P(from, T_FLOAT) || RB_TYPE_P(to, T_FLOAT) || RB_TYPE_P(step, T_FLOAT)) {
01785 double beg = NUM2DBL(from);
01786 double end = NUM2DBL(to);
01787 double unit = NUM2DBL(step);
01788 double n = ruby_float_step_size(beg, end, unit, excl);
01789 long i;
01790
01791 if (isinf(unit)) {
01792
01793 if (n) rb_yield(DBL2NUM(beg));
01794 }
01795 else if (unit == 0) {
01796 VALUE val = DBL2NUM(beg);
01797 for (;;)
01798 rb_yield(val);
01799 }
01800 else {
01801 for (i=0; i<n; i++) {
01802 double d = i*unit+beg;
01803 if (unit >= 0 ? end < d : d < end) d = end;
01804 rb_yield(DBL2NUM(d));
01805 }
01806 }
01807 return TRUE;
01808 }
01809 return FALSE;
01810 }
01811
01812 VALUE
01813 ruby_num_interval_step_size(VALUE from, VALUE to, VALUE step, int excl)
01814 {
01815 if (FIXNUM_P(from) && FIXNUM_P(to) && FIXNUM_P(step)) {
01816 long delta, diff;
01817
01818 diff = FIX2LONG(step);
01819 if (diff == 0) {
01820 return DBL2NUM(INFINITY);
01821 }
01822 delta = FIX2LONG(to) - FIX2LONG(from);
01823 if (diff < 0) {
01824 diff = -diff;
01825 delta = -delta;
01826 }
01827 if (excl) {
01828 delta--;
01829 }
01830 if (delta < 0) {
01831 return INT2FIX(0);
01832 }
01833 return ULONG2NUM(delta / diff + 1UL);
01834 }
01835 else if (RB_TYPE_P(from, T_FLOAT) || RB_TYPE_P(to, T_FLOAT) || RB_TYPE_P(step, T_FLOAT)) {
01836 double n = ruby_float_step_size(NUM2DBL(from), NUM2DBL(to), NUM2DBL(step), excl);
01837
01838 if (isinf(n)) return DBL2NUM(n);
01839 if (POSFIXABLE(n)) return LONG2FIX(n);
01840 return rb_dbl2big(n);
01841 }
01842 else {
01843 VALUE result;
01844 ID cmp = '>';
01845 switch (rb_cmpint(rb_num_coerce_cmp(step, INT2FIX(0), id_cmp), step, INT2FIX(0))) {
01846 case 0: return DBL2NUM(INFINITY);
01847 case -1: cmp = '<'; break;
01848 }
01849 if (RTEST(rb_funcall(from, cmp, 1, to))) return INT2FIX(0);
01850 result = rb_funcall(rb_funcall(to, '-', 1, from), id_div, 1, step);
01851 if (!excl || RTEST(rb_funcall(rb_funcall(from, '+', 1, rb_funcall(result, '*', 1, step)), cmp, 1, to))) {
01852 result = rb_funcall(result, '+', 1, INT2FIX(1));
01853 }
01854 return result;
01855 }
01856 }
01857
01858 static int
01859 num_step_scan_args(int argc, const VALUE *argv, VALUE *to, VALUE *step)
01860 {
01861 VALUE hash;
01862 int desc;
01863
01864 argc = rb_scan_args(argc, argv, "02:", to, step, &hash);
01865 if (!NIL_P(hash)) {
01866 ID keys[2];
01867 VALUE values[2];
01868 keys[0] = id_to;
01869 keys[1] = id_by;
01870 rb_get_kwargs(hash, keys, 0, 2, values);
01871 if (values[0] != Qundef) {
01872 if (argc > 0) rb_raise(rb_eArgError, "to is given twice");
01873 *to = values[0];
01874 }
01875 if (values[1] != Qundef) {
01876 if (argc > 1) rb_raise(rb_eArgError, "step is given twice");
01877 *step = values[1];
01878 }
01879 }
01880 else {
01881
01882 if (argc > 1 && NIL_P(*step)) {
01883 rb_raise(rb_eTypeError, "step must be numeric");
01884 }
01885 if (rb_equal(*step, INT2FIX(0))) {
01886 rb_raise(rb_eArgError, "step can't be 0");
01887 }
01888 }
01889 if (NIL_P(*step)) {
01890 *step = INT2FIX(1);
01891 }
01892 desc = !positive_int_p(*step);
01893 if (NIL_P(*to)) {
01894 *to = desc ? DBL2NUM(-INFINITY) : DBL2NUM(INFINITY);
01895 }
01896 return desc;
01897 }
01898
01899 static VALUE
01900 num_step_size(VALUE from, VALUE args, VALUE eobj)
01901 {
01902 VALUE to, step;
01903 int argc = args ? RARRAY_LENINT(args) : 0;
01904 VALUE *argv = args ? RARRAY_PTR(args) : 0;
01905
01906 num_step_scan_args(argc, argv, &to, &step);
01907
01908 return ruby_num_interval_step_size(from, to, step, FALSE);
01909 }
01910
01911
01912
01913
01914
01915
01916
01917
01918
01919
01920
01921
01922
01923
01924
01925
01926
01927
01928
01929
01930
01931
01932
01933
01934
01935
01936
01937
01938
01939
01940
01941
01942
01943
01944
01945
01946
01947
01948
01949
01950
01951
01952
01953
01954
01955
01956
01957
01958
01959
01960
01961
01962
01963
01964 static VALUE
01965 num_step(int argc, VALUE *argv, VALUE from)
01966 {
01967 VALUE to, step;
01968 int desc, inf;
01969
01970 RETURN_SIZED_ENUMERATOR(from, argc, argv, num_step_size);
01971
01972 desc = num_step_scan_args(argc, argv, &to, &step);
01973 if (RTEST(rb_num_coerce_cmp(step, INT2FIX(0), id_eq))) {
01974 inf = 1;
01975 }
01976 else if (RB_TYPE_P(to, T_FLOAT)) {
01977 double f = RFLOAT_VALUE(to);
01978 inf = isinf(f) && (signbit(f) ? desc : !desc);
01979 }
01980 else inf = 0;
01981
01982 if (FIXNUM_P(from) && (inf || FIXNUM_P(to)) && FIXNUM_P(step)) {
01983 long i = FIX2LONG(from);
01984 long diff = FIX2LONG(step);
01985
01986 if (inf) {
01987 for (;; i += diff)
01988 rb_yield(LONG2FIX(i));
01989 }
01990 else {
01991 long end = FIX2LONG(to);
01992
01993 if (desc) {
01994 for (; i >= end; i += diff)
01995 rb_yield(LONG2FIX(i));
01996 }
01997 else {
01998 for (; i <= end; i += diff)
01999 rb_yield(LONG2FIX(i));
02000 }
02001 }
02002 }
02003 else if (!ruby_float_step(from, to, step, FALSE)) {
02004 VALUE i = from;
02005
02006 if (inf) {
02007 for (;; i = rb_funcall(i, '+', 1, step))
02008 rb_yield(i);
02009 }
02010 else {
02011 ID cmp = desc ? '<' : '>';
02012
02013 for (; !RTEST(rb_funcall(i, cmp, 1, to)); i = rb_funcall(i, '+', 1, step))
02014 rb_yield(i);
02015 }
02016 }
02017 return from;
02018 }
02019
02020 #define LONG_MIN_MINUS_ONE ((double)LONG_MIN-1)
02021 #define LONG_MAX_PLUS_ONE (2*(double)(LONG_MAX/2+1))
02022 #define ULONG_MAX_PLUS_ONE (2*(double)(ULONG_MAX/2+1))
02023 #define LONG_MIN_MINUS_ONE_IS_LESS_THAN(n) \
02024 (LONG_MIN_MINUS_ONE == (double)LONG_MIN ? \
02025 LONG_MIN <= (n): \
02026 LONG_MIN_MINUS_ONE < (n))
02027
02028 SIGNED_VALUE
02029 rb_num2long(VALUE val)
02030 {
02031 again:
02032 if (NIL_P(val)) {
02033 rb_raise(rb_eTypeError, "no implicit conversion from nil to integer");
02034 }
02035
02036 if (FIXNUM_P(val)) return FIX2LONG(val);
02037
02038 else if (RB_TYPE_P(val, T_FLOAT)) {
02039 if (RFLOAT_VALUE(val) < LONG_MAX_PLUS_ONE
02040 && LONG_MIN_MINUS_ONE_IS_LESS_THAN(RFLOAT_VALUE(val))) {
02041 return (long)RFLOAT_VALUE(val);
02042 }
02043 else {
02044 char buf[24];
02045 char *s;
02046
02047 snprintf(buf, sizeof(buf), "%-.10g", RFLOAT_VALUE(val));
02048 if ((s = strchr(buf, ' ')) != 0) *s = '\0';
02049 rb_raise(rb_eRangeError, "float %s out of range of integer", buf);
02050 }
02051 }
02052 else if (RB_TYPE_P(val, T_BIGNUM)) {
02053 return rb_big2long(val);
02054 }
02055 else {
02056 val = rb_to_int(val);
02057 goto again;
02058 }
02059 }
02060
02061 static unsigned long
02062 rb_num2ulong_internal(VALUE val, int *wrap_p)
02063 {
02064 again:
02065 if (NIL_P(val)) {
02066 rb_raise(rb_eTypeError, "no implicit conversion from nil to integer");
02067 }
02068
02069 if (FIXNUM_P(val)) {
02070 long l = FIX2LONG(val);
02071 if (wrap_p)
02072 *wrap_p = l < 0;
02073 return (unsigned long)l;
02074 }
02075 else if (RB_TYPE_P(val, T_FLOAT)) {
02076 if (RFLOAT_VALUE(val) < ULONG_MAX_PLUS_ONE
02077 && LONG_MIN_MINUS_ONE_IS_LESS_THAN(RFLOAT_VALUE(val))) {
02078 double d = RFLOAT_VALUE(val);
02079 if (wrap_p)
02080 *wrap_p = d <= -1.0;
02081 if (0 <= d)
02082 return (unsigned long)d;
02083 return (unsigned long)(long)d;
02084 }
02085 else {
02086 char buf[24];
02087 char *s;
02088
02089 snprintf(buf, sizeof(buf), "%-.10g", RFLOAT_VALUE(val));
02090 if ((s = strchr(buf, ' ')) != 0) *s = '\0';
02091 rb_raise(rb_eRangeError, "float %s out of range of integer", buf);
02092 }
02093 }
02094 else if (RB_TYPE_P(val, T_BIGNUM)) {
02095 {
02096 unsigned long ul = rb_big2ulong(val);
02097 if (wrap_p)
02098 *wrap_p = RBIGNUM_NEGATIVE_P(val);
02099 return ul;
02100 }
02101 }
02102 else {
02103 val = rb_to_int(val);
02104 goto again;
02105 }
02106 }
02107
02108 VALUE
02109 rb_num2ulong(VALUE val)
02110 {
02111 return rb_num2ulong_internal(val, NULL);
02112 }
02113
02114 #if SIZEOF_INT < SIZEOF_LONG
02115 void
02116 rb_out_of_int(SIGNED_VALUE num)
02117 {
02118 rb_raise(rb_eRangeError, "integer %"PRIdVALUE " too %s to convert to `int'",
02119 num, num < 0 ? "small" : "big");
02120 }
02121
02122 static void
02123 check_int(long num)
02124 {
02125 if ((long)(int)num != num) {
02126 rb_out_of_int(num);
02127 }
02128 }
02129
02130 static void
02131 check_uint(unsigned long num, int sign)
02132 {
02133 if (sign) {
02134
02135 if (num < (unsigned long)INT_MIN)
02136 rb_raise(rb_eRangeError, "integer %ld too small to convert to `unsigned int'", (long)num);
02137 }
02138 else {
02139
02140 if (UINT_MAX < num)
02141 rb_raise(rb_eRangeError, "integer %lu too big to convert to `unsigned int'", num);
02142 }
02143 }
02144
02145 long
02146 rb_num2int(VALUE val)
02147 {
02148 long num = rb_num2long(val);
02149
02150 check_int(num);
02151 return num;
02152 }
02153
02154 long
02155 rb_fix2int(VALUE val)
02156 {
02157 long num = FIXNUM_P(val)?FIX2LONG(val):rb_num2long(val);
02158
02159 check_int(num);
02160 return num;
02161 }
02162
02163 unsigned long
02164 rb_num2uint(VALUE val)
02165 {
02166 int wrap;
02167 unsigned long num = rb_num2ulong_internal(val, &wrap);
02168
02169 check_uint(num, wrap);
02170 return num;
02171 }
02172
02173 unsigned long
02174 rb_fix2uint(VALUE val)
02175 {
02176 unsigned long num;
02177
02178 if (!FIXNUM_P(val)) {
02179 return rb_num2uint(val);
02180 }
02181 num = FIX2ULONG(val);
02182
02183 check_uint(num, negative_int_p(val));
02184 return num;
02185 }
02186 #else
02187 long
02188 rb_num2int(VALUE val)
02189 {
02190 return rb_num2long(val);
02191 }
02192
02193 long
02194 rb_fix2int(VALUE val)
02195 {
02196 return FIX2INT(val);
02197 }
02198 #endif
02199
02200 void
02201 rb_out_of_short(SIGNED_VALUE num)
02202 {
02203 rb_raise(rb_eRangeError, "integer %"PRIdVALUE " too %s to convert to `short'",
02204 num, num < 0 ? "small" : "big");
02205 }
02206
02207 static void
02208 check_short(long num)
02209 {
02210 if ((long)(short)num != num) {
02211 rb_out_of_short(num);
02212 }
02213 }
02214
02215 static void
02216 check_ushort(unsigned long num, int sign)
02217 {
02218 if (sign) {
02219
02220 if (num < (unsigned long)SHRT_MIN)
02221 rb_raise(rb_eRangeError, "integer %ld too small to convert to `unsigned short'", (long)num);
02222 }
02223 else {
02224
02225 if (USHRT_MAX < num)
02226 rb_raise(rb_eRangeError, "integer %lu too big to convert to `unsigned short'", num);
02227 }
02228 }
02229
02230 short
02231 rb_num2short(VALUE val)
02232 {
02233 long num = rb_num2long(val);
02234
02235 check_short(num);
02236 return num;
02237 }
02238
02239 short
02240 rb_fix2short(VALUE val)
02241 {
02242 long num = FIXNUM_P(val)?FIX2LONG(val):rb_num2long(val);
02243
02244 check_short(num);
02245 return num;
02246 }
02247
02248 unsigned short
02249 rb_num2ushort(VALUE val)
02250 {
02251 int wrap;
02252 unsigned long num = rb_num2ulong_internal(val, &wrap);
02253
02254 check_ushort(num, wrap);
02255 return num;
02256 }
02257
02258 unsigned short
02259 rb_fix2ushort(VALUE val)
02260 {
02261 unsigned long num;
02262
02263 if (!FIXNUM_P(val)) {
02264 return rb_num2ushort(val);
02265 }
02266 num = FIX2ULONG(val);
02267
02268 check_ushort(num, negative_int_p(val));
02269 return num;
02270 }
02271
02272 VALUE
02273 rb_num2fix(VALUE val)
02274 {
02275 long v;
02276
02277 if (FIXNUM_P(val)) return val;
02278
02279 v = rb_num2long(val);
02280 if (!FIXABLE(v))
02281 rb_raise(rb_eRangeError, "integer %ld out of range of fixnum", v);
02282 return LONG2FIX(v);
02283 }
02284
02285 #if HAVE_LONG_LONG
02286
02287 #define LLONG_MIN_MINUS_ONE ((double)LLONG_MIN-1)
02288 #define LLONG_MAX_PLUS_ONE (2*(double)(LLONG_MAX/2+1))
02289 #define ULLONG_MAX_PLUS_ONE (2*(double)(ULLONG_MAX/2+1))
02290 #ifndef ULLONG_MAX
02291 #define ULLONG_MAX ((unsigned LONG_LONG)LLONG_MAX*2+1)
02292 #endif
02293 #define LLONG_MIN_MINUS_ONE_IS_LESS_THAN(n) \
02294 (LLONG_MIN_MINUS_ONE == (double)LLONG_MIN ? \
02295 LLONG_MIN <= (n): \
02296 LLONG_MIN_MINUS_ONE < (n))
02297
02298 LONG_LONG
02299 rb_num2ll(VALUE val)
02300 {
02301 if (NIL_P(val)) {
02302 rb_raise(rb_eTypeError, "no implicit conversion from nil");
02303 }
02304
02305 if (FIXNUM_P(val)) return (LONG_LONG)FIX2LONG(val);
02306
02307 else if (RB_TYPE_P(val, T_FLOAT)) {
02308 if (RFLOAT_VALUE(val) < LLONG_MAX_PLUS_ONE
02309 && (LLONG_MIN_MINUS_ONE_IS_LESS_THAN(RFLOAT_VALUE(val)))) {
02310 return (LONG_LONG)(RFLOAT_VALUE(val));
02311 }
02312 else {
02313 char buf[24];
02314 char *s;
02315
02316 snprintf(buf, sizeof(buf), "%-.10g", RFLOAT_VALUE(val));
02317 if ((s = strchr(buf, ' ')) != 0) *s = '\0';
02318 rb_raise(rb_eRangeError, "float %s out of range of long long", buf);
02319 }
02320 }
02321 else if (RB_TYPE_P(val, T_BIGNUM)) {
02322 return rb_big2ll(val);
02323 }
02324 else if (RB_TYPE_P(val, T_STRING)) {
02325 rb_raise(rb_eTypeError, "no implicit conversion from string");
02326 }
02327 else if (RB_TYPE_P(val, T_TRUE) || RB_TYPE_P(val, T_FALSE)) {
02328 rb_raise(rb_eTypeError, "no implicit conversion from boolean");
02329 }
02330
02331 val = rb_to_int(val);
02332 return NUM2LL(val);
02333 }
02334
02335 unsigned LONG_LONG
02336 rb_num2ull(VALUE val)
02337 {
02338 if (RB_TYPE_P(val, T_NIL)) {
02339 rb_raise(rb_eTypeError, "no implicit conversion from nil");
02340 }
02341 else if (RB_TYPE_P(val, T_FIXNUM)) {
02342 return (LONG_LONG)FIX2LONG(val);
02343 }
02344 else if (RB_TYPE_P(val, T_FLOAT)) {
02345 if (RFLOAT_VALUE(val) < ULLONG_MAX_PLUS_ONE
02346 && LLONG_MIN_MINUS_ONE_IS_LESS_THAN(RFLOAT_VALUE(val))) {
02347 if (0 <= RFLOAT_VALUE(val))
02348 return (unsigned LONG_LONG)(RFLOAT_VALUE(val));
02349 return (unsigned LONG_LONG)(LONG_LONG)(RFLOAT_VALUE(val));
02350 }
02351 else {
02352 char buf[24];
02353 char *s;
02354
02355 snprintf(buf, sizeof(buf), "%-.10g", RFLOAT_VALUE(val));
02356 if ((s = strchr(buf, ' ')) != 0) *s = '\0';
02357 rb_raise(rb_eRangeError, "float %s out of range of unsgined long long", buf);
02358 }
02359 }
02360 else if (RB_TYPE_P(val, T_BIGNUM)) {
02361 return rb_big2ull(val);
02362 }
02363 else if (RB_TYPE_P(val, T_STRING)) {
02364 rb_raise(rb_eTypeError, "no implicit conversion from string");
02365 }
02366 else if (RB_TYPE_P(val, T_TRUE) || RB_TYPE_P(val, T_FALSE)) {
02367 rb_raise(rb_eTypeError, "no implicit conversion from boolean");
02368 }
02369
02370 val = rb_to_int(val);
02371 return NUM2ULL(val);
02372 }
02373
02374 #endif
02375
02376
02377
02378
02379
02380
02381
02382
02383
02384
02385
02386
02387
02388
02389
02390
02391
02392
02393 static VALUE
02394 int_to_i(VALUE num)
02395 {
02396 return num;
02397 }
02398
02399
02400
02401
02402
02403
02404
02405
02406 static VALUE
02407 int_int_p(VALUE num)
02408 {
02409 return Qtrue;
02410 }
02411
02412
02413
02414
02415
02416
02417
02418
02419 static VALUE
02420 int_odd_p(VALUE num)
02421 {
02422 if (rb_funcall(num, '%', 1, INT2FIX(2)) != INT2FIX(0)) {
02423 return Qtrue;
02424 }
02425 return Qfalse;
02426 }
02427
02428
02429
02430
02431
02432
02433
02434
02435 static VALUE
02436 int_even_p(VALUE num)
02437 {
02438 if (rb_funcall(num, '%', 1, INT2FIX(2)) == INT2FIX(0)) {
02439 return Qtrue;
02440 }
02441 return Qfalse;
02442 }
02443
02444
02445
02446
02447
02448
02449
02450
02451
02452
02453
02454
02455 static VALUE
02456 fix_succ(VALUE num)
02457 {
02458 long i = FIX2LONG(num) + 1;
02459 return LONG2NUM(i);
02460 }
02461
02462
02463
02464
02465
02466
02467
02468
02469
02470
02471
02472
02473 VALUE
02474 rb_int_succ(VALUE num)
02475 {
02476 if (FIXNUM_P(num)) {
02477 long i = FIX2LONG(num) + 1;
02478 return LONG2NUM(i);
02479 }
02480 if (RB_TYPE_P(num, T_BIGNUM)) {
02481 return rb_big_plus(num, INT2FIX(1));
02482 }
02483 return rb_funcall(num, '+', 1, INT2FIX(1));
02484 }
02485
02486 #define int_succ rb_int_succ
02487
02488
02489
02490
02491
02492
02493
02494
02495
02496
02497
02498 VALUE
02499 rb_int_pred(VALUE num)
02500 {
02501 if (FIXNUM_P(num)) {
02502 long i = FIX2LONG(num) - 1;
02503 return LONG2NUM(i);
02504 }
02505 if (RB_TYPE_P(num, T_BIGNUM)) {
02506 return rb_big_minus(num, INT2FIX(1));
02507 }
02508 return rb_funcall(num, '-', 1, INT2FIX(1));
02509 }
02510
02511 #define int_pred rb_int_pred
02512
02513 VALUE
02514 rb_enc_uint_chr(unsigned int code, rb_encoding *enc)
02515 {
02516 int n;
02517 VALUE str;
02518 switch (n = rb_enc_codelen(code, enc)) {
02519 case ONIGERR_INVALID_CODE_POINT_VALUE:
02520 rb_raise(rb_eRangeError, "invalid codepoint 0x%X in %s", code, rb_enc_name(enc));
02521 break;
02522 case ONIGERR_TOO_BIG_WIDE_CHAR_VALUE:
02523 case 0:
02524 rb_raise(rb_eRangeError, "%u out of char range", code);
02525 break;
02526 }
02527 str = rb_enc_str_new(0, n, enc);
02528 rb_enc_mbcput(code, RSTRING_PTR(str), enc);
02529 if (rb_enc_precise_mbclen(RSTRING_PTR(str), RSTRING_END(str), enc) != n) {
02530 rb_raise(rb_eRangeError, "invalid codepoint 0x%X in %s", code, rb_enc_name(enc));
02531 }
02532 return str;
02533 }
02534
02535
02536
02537
02538
02539
02540
02541
02542
02543
02544
02545
02546
02547 static VALUE
02548 int_chr(int argc, VALUE *argv, VALUE num)
02549 {
02550 char c;
02551 unsigned int i;
02552 rb_encoding *enc;
02553
02554 if (rb_num_to_uint(num, &i) == 0) {
02555 }
02556 else if (FIXNUM_P(num)) {
02557 rb_raise(rb_eRangeError, "%ld out of char range", FIX2LONG(num));
02558 }
02559 else {
02560 rb_raise(rb_eRangeError, "bignum out of char range");
02561 }
02562
02563 switch (argc) {
02564 case 0:
02565 if (0xff < i) {
02566 enc = rb_default_internal_encoding();
02567 if (!enc) {
02568 rb_raise(rb_eRangeError, "%d out of char range", i);
02569 }
02570 goto decode;
02571 }
02572 c = (char)i;
02573 if (i < 0x80) {
02574 return rb_usascii_str_new(&c, 1);
02575 }
02576 else {
02577 return rb_str_new(&c, 1);
02578 }
02579 case 1:
02580 break;
02581 default:
02582 rb_check_arity(argc, 0, 1);
02583 break;
02584 }
02585 enc = rb_to_encoding(argv[0]);
02586 if (!enc) enc = rb_ascii8bit_encoding();
02587 decode:
02588 return rb_enc_uint_chr(i, enc);
02589 }
02590
02591
02592
02593
02594
02595
02596
02597
02598
02599
02600
02601
02602
02603
02604
02605 static VALUE
02606 int_ord(VALUE num)
02607 {
02608 return num;
02609 }
02610
02611
02612
02613
02614
02615
02616
02617
02618
02619
02620
02621
02622
02623
02624
02625
02626
02627
02628
02629
02630
02631
02632
02633
02634
02635
02636
02637 static VALUE
02638 fix_uminus(VALUE num)
02639 {
02640 return LONG2NUM(-FIX2LONG(num));
02641 }
02642
02643 VALUE
02644 rb_fix2str(VALUE x, int base)
02645 {
02646 extern const char ruby_digitmap[];
02647 char buf[SIZEOF_VALUE*CHAR_BIT + 2], *b = buf + sizeof buf;
02648 long val = FIX2LONG(x);
02649 int neg = 0;
02650
02651 if (base < 2 || 36 < base) {
02652 rb_raise(rb_eArgError, "invalid radix %d", base);
02653 }
02654 if (val == 0) {
02655 return rb_usascii_str_new2("0");
02656 }
02657 if (val < 0) {
02658 val = -val;
02659 neg = 1;
02660 }
02661 *--b = '\0';
02662 do {
02663 *--b = ruby_digitmap[(int)(val % base)];
02664 } while (val /= base);
02665 if (neg) {
02666 *--b = '-';
02667 }
02668
02669 return rb_usascii_str_new2(b);
02670 }
02671
02672
02673
02674
02675
02676
02677
02678
02679
02680
02681
02682
02683
02684
02685
02686
02687 static VALUE
02688 fix_to_s(int argc, VALUE *argv, VALUE x)
02689 {
02690 int base;
02691
02692 if (argc == 0) base = 10;
02693 else {
02694 VALUE b;
02695
02696 rb_scan_args(argc, argv, "01", &b);
02697 base = NUM2INT(b);
02698 }
02699
02700 return rb_fix2str(x, base);
02701 }
02702
02703
02704
02705
02706
02707
02708
02709
02710
02711 static VALUE
02712 fix_plus(VALUE x, VALUE y)
02713 {
02714 if (FIXNUM_P(y)) {
02715 long a, b, c;
02716 VALUE r;
02717
02718 a = FIX2LONG(x);
02719 b = FIX2LONG(y);
02720 c = a + b;
02721 r = LONG2NUM(c);
02722
02723 return r;
02724 }
02725 else if (RB_TYPE_P(y, T_BIGNUM)) {
02726 return rb_big_plus(y, x);
02727 }
02728 else if (RB_TYPE_P(y, T_FLOAT)) {
02729 return DBL2NUM((double)FIX2LONG(x) + RFLOAT_VALUE(y));
02730 }
02731 else {
02732 return rb_num_coerce_bin(x, y, '+');
02733 }
02734 }
02735
02736
02737
02738
02739
02740
02741
02742
02743
02744 static VALUE
02745 fix_minus(VALUE x, VALUE y)
02746 {
02747 if (FIXNUM_P(y)) {
02748 long a, b, c;
02749 VALUE r;
02750
02751 a = FIX2LONG(x);
02752 b = FIX2LONG(y);
02753 c = a - b;
02754 r = LONG2NUM(c);
02755
02756 return r;
02757 }
02758 else if (RB_TYPE_P(y, T_BIGNUM)) {
02759 x = rb_int2big(FIX2LONG(x));
02760 return rb_big_minus(x, y);
02761 }
02762 else if (RB_TYPE_P(y, T_FLOAT)) {
02763 return DBL2NUM((double)FIX2LONG(x) - RFLOAT_VALUE(y));
02764 }
02765 else {
02766 return rb_num_coerce_bin(x, y, '-');
02767 }
02768 }
02769
02770 #define SQRT_LONG_MAX ((SIGNED_VALUE)1<<((SIZEOF_LONG*CHAR_BIT-1)/2))
02771
02772 #define FIT_SQRT_LONG(n) (((n)<SQRT_LONG_MAX)&&((n)>=-SQRT_LONG_MAX))
02773
02774
02775
02776
02777
02778
02779
02780
02781
02782
02783 static VALUE
02784 fix_mul(VALUE x, VALUE y)
02785 {
02786 if (FIXNUM_P(y)) {
02787 #ifdef __HP_cc
02788
02789 volatile
02790 #endif
02791 long a, b;
02792 #if SIZEOF_LONG * 2 <= SIZEOF_LONG_LONG
02793 LONG_LONG d;
02794 #else
02795 VALUE r;
02796 #endif
02797
02798 a = FIX2LONG(x);
02799 b = FIX2LONG(y);
02800
02801 #if SIZEOF_LONG * 2 <= SIZEOF_LONG_LONG
02802 d = (LONG_LONG)a * b;
02803 if (FIXABLE(d)) return LONG2FIX(d);
02804 return rb_ll2inum(d);
02805 #else
02806 if (a == 0) return x;
02807 if (MUL_OVERFLOW_FIXNUM_P(a, b))
02808 r = rb_big_mul(rb_int2big(a), rb_int2big(b));
02809 else
02810 r = LONG2FIX(a * b);
02811 return r;
02812 #endif
02813 }
02814 else if (RB_TYPE_P(y, T_BIGNUM)) {
02815 return rb_big_mul(y, x);
02816 }
02817 else if (RB_TYPE_P(y, T_FLOAT)) {
02818 return DBL2NUM((double)FIX2LONG(x) * RFLOAT_VALUE(y));
02819 }
02820 else {
02821 return rb_num_coerce_bin(x, y, '*');
02822 }
02823 }
02824
02825 static void
02826 fixdivmod(long x, long y, long *divp, long *modp)
02827 {
02828 long div, mod;
02829
02830 if (y == 0) rb_num_zerodiv();
02831 if (y < 0) {
02832 if (x < 0)
02833 div = -x / -y;
02834 else
02835 div = - (x / -y);
02836 }
02837 else {
02838 if (x < 0)
02839 div = - (-x / y);
02840 else
02841 div = x / y;
02842 }
02843 mod = x - div*y;
02844 if ((mod < 0 && y > 0) || (mod > 0 && y < 0)) {
02845 mod += y;
02846 div -= 1;
02847 }
02848 if (divp) *divp = div;
02849 if (modp) *modp = mod;
02850 }
02851
02852
02853
02854
02855
02856
02857
02858
02859
02860
02861
02862
02863 static VALUE
02864 fix_fdiv(VALUE x, VALUE y)
02865 {
02866 if (FIXNUM_P(y)) {
02867 return DBL2NUM((double)FIX2LONG(x) / (double)FIX2LONG(y));
02868 }
02869 else if (RB_TYPE_P(y, T_BIGNUM)) {
02870 return rb_big_fdiv(rb_int2big(FIX2LONG(x)), y);
02871 }
02872 else if (RB_TYPE_P(y, T_FLOAT)) {
02873 return DBL2NUM((double)FIX2LONG(x) / RFLOAT_VALUE(y));
02874 }
02875 else {
02876 return rb_num_coerce_bin(x, y, rb_intern("fdiv"));
02877 }
02878 }
02879
02880 static VALUE
02881 fix_divide(VALUE x, VALUE y, ID op)
02882 {
02883 if (FIXNUM_P(y)) {
02884 long div;
02885
02886 fixdivmod(FIX2LONG(x), FIX2LONG(y), &div, 0);
02887 return LONG2NUM(div);
02888 }
02889 else if (RB_TYPE_P(y, T_BIGNUM)) {
02890 x = rb_int2big(FIX2LONG(x));
02891 return rb_big_div(x, y);
02892 }
02893 else if (RB_TYPE_P(y, T_FLOAT)) {
02894 {
02895 double div;
02896
02897 if (op == '/') {
02898 div = (double)FIX2LONG(x) / RFLOAT_VALUE(y);
02899 return DBL2NUM(div);
02900 }
02901 else {
02902 if (RFLOAT_VALUE(y) == 0) rb_num_zerodiv();
02903 div = (double)FIX2LONG(x) / RFLOAT_VALUE(y);
02904 return rb_dbl2big(floor(div));
02905 }
02906 }
02907 }
02908 else {
02909 if (RB_TYPE_P(y, T_RATIONAL) &&
02910 op == '/' && FIX2LONG(x) == 1)
02911 return rb_rational_reciprocal(y);
02912 return rb_num_coerce_bin(x, y, op);
02913 }
02914 }
02915
02916
02917
02918
02919
02920
02921
02922
02923
02924 static VALUE
02925 fix_div(VALUE x, VALUE y)
02926 {
02927 return fix_divide(x, y, '/');
02928 }
02929
02930
02931
02932
02933
02934
02935
02936
02937
02938 static VALUE
02939 fix_idiv(VALUE x, VALUE y)
02940 {
02941 return fix_divide(x, y, rb_intern("div"));
02942 }
02943
02944
02945
02946
02947
02948
02949
02950
02951
02952
02953
02954 static VALUE
02955 fix_mod(VALUE x, VALUE y)
02956 {
02957 if (FIXNUM_P(y)) {
02958 long mod;
02959
02960 fixdivmod(FIX2LONG(x), FIX2LONG(y), 0, &mod);
02961 return LONG2NUM(mod);
02962 }
02963 else if (RB_TYPE_P(y, T_BIGNUM)) {
02964 x = rb_int2big(FIX2LONG(x));
02965 return rb_big_modulo(x, y);
02966 }
02967 else if (RB_TYPE_P(y, T_FLOAT)) {
02968 return DBL2NUM(ruby_float_mod((double)FIX2LONG(x), RFLOAT_VALUE(y)));
02969 }
02970 else {
02971 return rb_num_coerce_bin(x, y, '%');
02972 }
02973 }
02974
02975
02976
02977
02978
02979
02980
02981 static VALUE
02982 fix_divmod(VALUE x, VALUE y)
02983 {
02984 if (FIXNUM_P(y)) {
02985 long div, mod;
02986
02987 fixdivmod(FIX2LONG(x), FIX2LONG(y), &div, &mod);
02988
02989 return rb_assoc_new(LONG2NUM(div), LONG2NUM(mod));
02990 }
02991 else if (RB_TYPE_P(y, T_BIGNUM)) {
02992 x = rb_int2big(FIX2LONG(x));
02993 return rb_big_divmod(x, y);
02994 }
02995 else if (RB_TYPE_P(y, T_FLOAT)) {
02996 {
02997 double div, mod;
02998 volatile VALUE a, b;
02999
03000 flodivmod((double)FIX2LONG(x), RFLOAT_VALUE(y), &div, &mod);
03001 a = dbl2ival(div);
03002 b = DBL2NUM(mod);
03003 return rb_assoc_new(a, b);
03004 }
03005 }
03006 else {
03007 return rb_num_coerce_bin(x, y, rb_intern("divmod"));
03008 }
03009 }
03010
03011 static VALUE
03012 int_pow(long x, unsigned long y)
03013 {
03014 int neg = x < 0;
03015 long z = 1;
03016
03017 if (neg) x = -x;
03018 if (y & 1)
03019 z = x;
03020 else
03021 neg = 0;
03022 y &= ~1;
03023 do {
03024 while (y % 2 == 0) {
03025 if (!FIT_SQRT_LONG(x)) {
03026 VALUE v;
03027 bignum:
03028 v = rb_big_pow(rb_int2big(x), LONG2NUM(y));
03029 if (z != 1) v = rb_big_mul(rb_int2big(neg ? -z : z), v);
03030 return v;
03031 }
03032 x = x * x;
03033 y >>= 1;
03034 }
03035 {
03036 if (MUL_OVERFLOW_FIXNUM_P(x, z)) {
03037 goto bignum;
03038 }
03039 z = x * z;
03040 }
03041 } while (--y);
03042 if (neg) z = -z;
03043 return LONG2NUM(z);
03044 }
03045
03046 VALUE
03047 rb_int_positive_pow(long x, unsigned long y)
03048 {
03049 return int_pow(x, y);
03050 }
03051
03052
03053
03054
03055
03056
03057
03058
03059
03060
03061
03062
03063
03064 static VALUE
03065 fix_pow(VALUE x, VALUE y)
03066 {
03067 long a = FIX2LONG(x);
03068
03069 if (FIXNUM_P(y)) {
03070 long b = FIX2LONG(y);
03071
03072 if (a == 1) return INT2FIX(1);
03073 if (a == -1) {
03074 if (b % 2 == 0)
03075 return INT2FIX(1);
03076 else
03077 return INT2FIX(-1);
03078 }
03079 if (b < 0)
03080 return rb_funcall(rb_rational_raw1(x), rb_intern("**"), 1, y);
03081
03082 if (b == 0) return INT2FIX(1);
03083 if (b == 1) return x;
03084 if (a == 0) {
03085 if (b > 0) return INT2FIX(0);
03086 return DBL2NUM(INFINITY);
03087 }
03088 return int_pow(a, b);
03089 }
03090 else if (RB_TYPE_P(y, T_BIGNUM)) {
03091 if (a == 1) return INT2FIX(1);
03092 if (a == -1) {
03093 if (int_even_p(y)) return INT2FIX(1);
03094 else return INT2FIX(-1);
03095 }
03096 if (negative_int_p(y))
03097 return rb_funcall(rb_rational_raw1(x), rb_intern("**"), 1, y);
03098 if (a == 0) return INT2FIX(0);
03099 x = rb_int2big(FIX2LONG(x));
03100 return rb_big_pow(x, y);
03101 }
03102 else if (RB_TYPE_P(y, T_FLOAT)) {
03103 if (RFLOAT_VALUE(y) == 0.0) return DBL2NUM(1.0);
03104 if (a == 0) {
03105 return DBL2NUM(RFLOAT_VALUE(y) < 0 ? INFINITY : 0.0);
03106 }
03107 if (a == 1) return DBL2NUM(1.0);
03108 {
03109 double dy = RFLOAT_VALUE(y);
03110 if (a < 0 && dy != round(dy))
03111 return rb_funcall(rb_complex_raw1(x), rb_intern("**"), 1, y);
03112 return DBL2NUM(pow((double)a, dy));
03113 }
03114 }
03115 else {
03116 return rb_num_coerce_bin(x, y, rb_intern("**"));
03117 }
03118 }
03119
03120
03121
03122
03123
03124
03125
03126
03127
03128
03129
03130 static VALUE
03131 fix_equal(VALUE x, VALUE y)
03132 {
03133 if (x == y) return Qtrue;
03134 if (FIXNUM_P(y)) return Qfalse;
03135 else if (RB_TYPE_P(y, T_BIGNUM)) {
03136 return rb_big_eq(y, x);
03137 }
03138 else if (RB_TYPE_P(y, T_FLOAT)) {
03139 return rb_integer_float_eq(x, y);
03140 }
03141 else {
03142 return num_equal(x, y);
03143 }
03144 }
03145
03146
03147
03148
03149
03150
03151
03152
03153
03154
03155
03156
03157
03158 static VALUE
03159 fix_cmp(VALUE x, VALUE y)
03160 {
03161 if (x == y) return INT2FIX(0);
03162 if (FIXNUM_P(y)) {
03163 if (FIX2LONG(x) > FIX2LONG(y)) return INT2FIX(1);
03164 return INT2FIX(-1);
03165 }
03166 else if (RB_TYPE_P(y, T_BIGNUM)) {
03167 return rb_big_cmp(rb_int2big(FIX2LONG(x)), y);
03168 }
03169 else if (RB_TYPE_P(y, T_FLOAT)) {
03170 return rb_integer_float_cmp(x, y);
03171 }
03172 else {
03173 return rb_num_coerce_cmp(x, y, id_cmp);
03174 }
03175 }
03176
03177
03178
03179
03180
03181
03182
03183
03184 static VALUE
03185 fix_gt(VALUE x, VALUE y)
03186 {
03187 if (FIXNUM_P(y)) {
03188 if (FIX2LONG(x) > FIX2LONG(y)) return Qtrue;
03189 return Qfalse;
03190 }
03191 else if (RB_TYPE_P(y, T_BIGNUM)) {
03192 return FIX2INT(rb_big_cmp(rb_int2big(FIX2LONG(x)), y)) > 0 ? Qtrue : Qfalse;
03193 }
03194 else if (RB_TYPE_P(y, T_FLOAT)) {
03195 return rb_integer_float_cmp(x, y) == INT2FIX(1) ? Qtrue : Qfalse;
03196 }
03197 else {
03198 return rb_num_coerce_relop(x, y, '>');
03199 }
03200 }
03201
03202
03203
03204
03205
03206
03207
03208
03209
03210 static VALUE
03211 fix_ge(VALUE x, VALUE y)
03212 {
03213 if (FIXNUM_P(y)) {
03214 if (FIX2LONG(x) >= FIX2LONG(y)) return Qtrue;
03215 return Qfalse;
03216 }
03217 else if (RB_TYPE_P(y, T_BIGNUM)) {
03218 return FIX2INT(rb_big_cmp(rb_int2big(FIX2LONG(x)), y)) >= 0 ? Qtrue : Qfalse;
03219 }
03220 else if (RB_TYPE_P(y, T_FLOAT)) {
03221 VALUE rel = rb_integer_float_cmp(x, y);
03222 return rel == INT2FIX(1) || rel == INT2FIX(0) ? Qtrue : Qfalse;
03223 }
03224 else {
03225 return rb_num_coerce_relop(x, y, rb_intern(">="));
03226 }
03227 }
03228
03229
03230
03231
03232
03233
03234
03235
03236 static VALUE
03237 fix_lt(VALUE x, VALUE y)
03238 {
03239 if (FIXNUM_P(y)) {
03240 if (FIX2LONG(x) < FIX2LONG(y)) return Qtrue;
03241 return Qfalse;
03242 }
03243 else if (RB_TYPE_P(y, T_BIGNUM)) {
03244 return FIX2INT(rb_big_cmp(rb_int2big(FIX2LONG(x)), y)) < 0 ? Qtrue : Qfalse;
03245 }
03246 else if (RB_TYPE_P(y, T_FLOAT)) {
03247 return rb_integer_float_cmp(x, y) == INT2FIX(-1) ? Qtrue : Qfalse;
03248 }
03249 else {
03250 return rb_num_coerce_relop(x, y, '<');
03251 }
03252 }
03253
03254
03255
03256
03257
03258
03259
03260
03261
03262 static VALUE
03263 fix_le(VALUE x, VALUE y)
03264 {
03265 if (FIXNUM_P(y)) {
03266 if (FIX2LONG(x) <= FIX2LONG(y)) return Qtrue;
03267 return Qfalse;
03268 }
03269 else if (RB_TYPE_P(y, T_BIGNUM)) {
03270 return FIX2INT(rb_big_cmp(rb_int2big(FIX2LONG(x)), y)) <= 0 ? Qtrue : Qfalse;
03271 }
03272 else if (RB_TYPE_P(y, T_FLOAT)) {
03273 VALUE rel = rb_integer_float_cmp(x, y);
03274 return rel == INT2FIX(-1) || rel == INT2FIX(0) ? Qtrue : Qfalse;
03275 }
03276 else {
03277 return rb_num_coerce_relop(x, y, rb_intern("<="));
03278 }
03279 }
03280
03281
03282
03283
03284
03285
03286
03287
03288 static VALUE
03289 fix_rev(VALUE num)
03290 {
03291 return ~num | FIXNUM_FLAG;
03292 }
03293
03294 static int
03295 bit_coerce(VALUE *x, VALUE *y, int err)
03296 {
03297 if (!FIXNUM_P(*y) && !RB_TYPE_P(*y, T_BIGNUM)) {
03298 do_coerce(x, y, err);
03299 if (!FIXNUM_P(*x) && !RB_TYPE_P(*x, T_BIGNUM)
03300 && !FIXNUM_P(*y) && !RB_TYPE_P(*y, T_BIGNUM)) {
03301 if (!err) return FALSE;
03302 coerce_failed(*x, *y);
03303 }
03304 }
03305 return TRUE;
03306 }
03307
03308 VALUE
03309 rb_num_coerce_bit(VALUE x, VALUE y, ID func)
03310 {
03311 bit_coerce(&x, &y, TRUE);
03312 return rb_funcall(x, func, 1, y);
03313 }
03314
03315
03316
03317
03318
03319
03320
03321
03322 static VALUE
03323 fix_and(VALUE x, VALUE y)
03324 {
03325 if (FIXNUM_P(y)) {
03326 long val = FIX2LONG(x) & FIX2LONG(y);
03327 return LONG2NUM(val);
03328 }
03329
03330 if (RB_TYPE_P(y, T_BIGNUM)) {
03331 return rb_big_and(y, x);
03332 }
03333
03334 bit_coerce(&x, &y, TRUE);
03335 return rb_funcall(x, rb_intern("&"), 1, y);
03336 }
03337
03338
03339
03340
03341
03342
03343
03344
03345 static VALUE
03346 fix_or(VALUE x, VALUE y)
03347 {
03348 if (FIXNUM_P(y)) {
03349 long val = FIX2LONG(x) | FIX2LONG(y);
03350 return LONG2NUM(val);
03351 }
03352
03353 if (RB_TYPE_P(y, T_BIGNUM)) {
03354 return rb_big_or(y, x);
03355 }
03356
03357 bit_coerce(&x, &y, TRUE);
03358 return rb_funcall(x, rb_intern("|"), 1, y);
03359 }
03360
03361
03362
03363
03364
03365
03366
03367
03368 static VALUE
03369 fix_xor(VALUE x, VALUE y)
03370 {
03371 if (FIXNUM_P(y)) {
03372 long val = FIX2LONG(x) ^ FIX2LONG(y);
03373 return LONG2NUM(val);
03374 }
03375
03376 if (RB_TYPE_P(y, T_BIGNUM)) {
03377 return rb_big_xor(y, x);
03378 }
03379
03380 bit_coerce(&x, &y, TRUE);
03381 return rb_funcall(x, rb_intern("^"), 1, y);
03382 }
03383
03384 static VALUE fix_lshift(long, unsigned long);
03385 static VALUE fix_rshift(long, unsigned long);
03386
03387
03388
03389
03390
03391
03392
03393
03394 static VALUE
03395 rb_fix_lshift(VALUE x, VALUE y)
03396 {
03397 long val, width;
03398
03399 val = NUM2LONG(x);
03400 if (!FIXNUM_P(y))
03401 return rb_big_lshift(rb_int2big(val), y);
03402 width = FIX2LONG(y);
03403 if (width < 0)
03404 return fix_rshift(val, (unsigned long)-width);
03405 return fix_lshift(val, width);
03406 }
03407
03408 static VALUE
03409 fix_lshift(long val, unsigned long width)
03410 {
03411 if (width > (SIZEOF_LONG*CHAR_BIT-1)
03412 || ((unsigned long)val)>>(SIZEOF_LONG*CHAR_BIT-1-width) > 0) {
03413 return rb_big_lshift(rb_int2big(val), ULONG2NUM(width));
03414 }
03415 val = val << width;
03416 return LONG2NUM(val);
03417 }
03418
03419
03420
03421
03422
03423
03424
03425
03426 static VALUE
03427 rb_fix_rshift(VALUE x, VALUE y)
03428 {
03429 long i, val;
03430
03431 val = FIX2LONG(x);
03432 if (!FIXNUM_P(y))
03433 return rb_big_rshift(rb_int2big(val), y);
03434 i = FIX2LONG(y);
03435 if (i == 0) return x;
03436 if (i < 0)
03437 return fix_lshift(val, (unsigned long)-i);
03438 return fix_rshift(val, i);
03439 }
03440
03441 static VALUE
03442 fix_rshift(long val, unsigned long i)
03443 {
03444 if (i >= sizeof(long)*CHAR_BIT-1) {
03445 if (val < 0) return INT2FIX(-1);
03446 return INT2FIX(0);
03447 }
03448 val = RSHIFT(val, i);
03449 return LONG2FIX(val);
03450 }
03451
03452
03453
03454
03455
03456
03457
03458
03459
03460
03461
03462
03463
03464
03465
03466 static VALUE
03467 fix_aref(VALUE fix, VALUE idx)
03468 {
03469 long val = FIX2LONG(fix);
03470 long i;
03471
03472 idx = rb_to_int(idx);
03473 if (!FIXNUM_P(idx)) {
03474 idx = rb_big_norm(idx);
03475 if (!FIXNUM_P(idx)) {
03476 if (!RBIGNUM_SIGN(idx) || val >= 0)
03477 return INT2FIX(0);
03478 return INT2FIX(1);
03479 }
03480 }
03481 i = FIX2LONG(idx);
03482
03483 if (i < 0) return INT2FIX(0);
03484 if (SIZEOF_LONG*CHAR_BIT-1 <= i) {
03485 if (val < 0) return INT2FIX(1);
03486 return INT2FIX(0);
03487 }
03488 if (val & (1L<<i))
03489 return INT2FIX(1);
03490 return INT2FIX(0);
03491 }
03492
03493
03494
03495
03496
03497
03498
03499
03500
03501 static VALUE
03502 fix_to_f(VALUE num)
03503 {
03504 double val;
03505
03506 val = (double)FIX2LONG(num);
03507
03508 return DBL2NUM(val);
03509 }
03510
03511
03512
03513
03514
03515
03516
03517
03518
03519
03520
03521
03522
03523 static VALUE
03524 fix_abs(VALUE fix)
03525 {
03526 long i = FIX2LONG(fix);
03527
03528 if (i < 0) i = -i;
03529
03530 return LONG2NUM(i);
03531 }
03532
03533
03534
03535
03536
03537
03538
03539
03540
03541
03542
03543
03544
03545
03546 static VALUE
03547 fix_size(VALUE fix)
03548 {
03549 return INT2FIX(sizeof(long));
03550 }
03551
03552
03553
03554
03555
03556
03557
03558
03559
03560
03561
03562
03563
03564
03565
03566
03567
03568
03569
03570
03571
03572
03573
03574
03575
03576
03577
03578
03579
03580
03581
03582 static VALUE
03583 rb_fix_bit_length(VALUE fix)
03584 {
03585 long v = FIX2LONG(fix);
03586 if (v < 0)
03587 v = ~v;
03588 return LONG2FIX(bit_length(v));
03589 }
03590
03591 static VALUE
03592 int_upto_size(VALUE from, VALUE args, VALUE eobj)
03593 {
03594 return ruby_num_interval_step_size(from, RARRAY_AREF(args, 0), INT2FIX(1), FALSE);
03595 }
03596
03597
03598
03599
03600
03601
03602
03603
03604
03605
03606
03607
03608
03609
03610
03611
03612
03613 static VALUE
03614 int_upto(VALUE from, VALUE to)
03615 {
03616 RETURN_SIZED_ENUMERATOR(from, 1, &to, int_upto_size);
03617 if (FIXNUM_P(from) && FIXNUM_P(to)) {
03618 long i, end;
03619
03620 end = FIX2LONG(to);
03621 for (i = FIX2LONG(from); i <= end; i++) {
03622 rb_yield(LONG2FIX(i));
03623 }
03624 }
03625 else {
03626 VALUE i = from, c;
03627
03628 while (!(c = rb_funcall(i, '>', 1, to))) {
03629 rb_yield(i);
03630 i = rb_funcall(i, '+', 1, INT2FIX(1));
03631 }
03632 if (NIL_P(c)) rb_cmperr(i, to);
03633 }
03634 return from;
03635 }
03636
03637 static VALUE
03638 int_downto_size(VALUE from, VALUE args, VALUE eobj)
03639 {
03640 return ruby_num_interval_step_size(from, RARRAY_AREF(args, 0), INT2FIX(-1), FALSE);
03641 }
03642
03643
03644
03645
03646
03647
03648
03649
03650
03651
03652
03653
03654
03655
03656
03657
03658 static VALUE
03659 int_downto(VALUE from, VALUE to)
03660 {
03661 RETURN_SIZED_ENUMERATOR(from, 1, &to, int_downto_size);
03662 if (FIXNUM_P(from) && FIXNUM_P(to)) {
03663 long i, end;
03664
03665 end = FIX2LONG(to);
03666 for (i=FIX2LONG(from); i >= end; i--) {
03667 rb_yield(LONG2FIX(i));
03668 }
03669 }
03670 else {
03671 VALUE i = from, c;
03672
03673 while (!(c = rb_funcall(i, '<', 1, to))) {
03674 rb_yield(i);
03675 i = rb_funcall(i, '-', 1, INT2FIX(1));
03676 }
03677 if (NIL_P(c)) rb_cmperr(i, to);
03678 }
03679 return from;
03680 }
03681
03682 static VALUE
03683 int_dotimes_size(VALUE num, VALUE args, VALUE eobj)
03684 {
03685 if (FIXNUM_P(num)) {
03686 if (NUM2LONG(num) <= 0) return INT2FIX(0);
03687 }
03688 else {
03689 if (RTEST(rb_funcall(num, '<', 1, INT2FIX(0)))) return INT2FIX(0);
03690 }
03691 return num;
03692 }
03693
03694
03695
03696
03697
03698
03699
03700
03701
03702
03703
03704
03705
03706
03707
03708
03709
03710 static VALUE
03711 int_dotimes(VALUE num)
03712 {
03713 RETURN_SIZED_ENUMERATOR(num, 0, 0, int_dotimes_size);
03714
03715 if (FIXNUM_P(num)) {
03716 long i, end;
03717
03718 end = FIX2LONG(num);
03719 for (i=0; i<end; i++) {
03720 rb_yield(LONG2FIX(i));
03721 }
03722 }
03723 else {
03724 VALUE i = INT2FIX(0);
03725
03726 for (;;) {
03727 if (!RTEST(rb_funcall(i, '<', 1, num))) break;
03728 rb_yield(i);
03729 i = rb_funcall(i, '+', 1, INT2FIX(1));
03730 }
03731 }
03732 return num;
03733 }
03734
03735
03736
03737
03738
03739
03740
03741
03742
03743
03744
03745
03746
03747
03748
03749 static VALUE
03750 int_round(int argc, VALUE* argv, VALUE num)
03751 {
03752 VALUE n;
03753 int ndigits;
03754
03755 if (argc == 0) return num;
03756 rb_scan_args(argc, argv, "1", &n);
03757 ndigits = NUM2INT(n);
03758 if (ndigits > 0) {
03759 return rb_Float(num);
03760 }
03761 if (ndigits == 0) {
03762 return num;
03763 }
03764 return int_round_0(num, ndigits);
03765 }
03766
03767
03768
03769
03770
03771
03772
03773
03774
03775 static VALUE
03776 fix_zero_p(VALUE num)
03777 {
03778 if (FIX2LONG(num) == 0) {
03779 return Qtrue;
03780 }
03781 return Qfalse;
03782 }
03783
03784
03785
03786
03787
03788
03789
03790
03791 static VALUE
03792 fix_odd_p(VALUE num)
03793 {
03794 if (num & 2) {
03795 return Qtrue;
03796 }
03797 return Qfalse;
03798 }
03799
03800
03801
03802
03803
03804
03805
03806
03807 static VALUE
03808 fix_even_p(VALUE num)
03809 {
03810 if (num & 2) {
03811 return Qfalse;
03812 }
03813 return Qtrue;
03814 }
03815
03816
03817
03818
03819
03820
03821
03822
03823
03824
03825
03826
03827
03828
03829
03830
03831
03832
03833
03834
03835
03836
03837
03838
03839
03840
03841
03842
03843
03844 void
03845 Init_Numeric(void)
03846 {
03847 #undef rb_intern
03848 #define rb_intern(str) rb_intern_const(str)
03849
03850 #if defined(__FreeBSD__) && __FreeBSD__ < 4
03851
03852 fpsetmask(fpgetmask() & ~(FP_X_DZ|FP_X_INV|FP_X_OFL));
03853 #elif defined(_UNICOSMP)
03854
03855 _set_Creg(0, 0);
03856 #elif defined(__BORLANDC__)
03857
03858 _control87(MCW_EM, MCW_EM);
03859 _control87(_control87(0,0),0x1FFF);
03860 #endif
03861 id_coerce = rb_intern("coerce");
03862 id_to_i = rb_intern("to_i");
03863 id_eq = rb_intern("==");
03864 id_div = rb_intern("div");
03865 id_cmp = rb_intern("<=>");
03866
03867 rb_eZeroDivError = rb_define_class("ZeroDivisionError", rb_eStandardError);
03868 rb_eFloatDomainError = rb_define_class("FloatDomainError", rb_eRangeError);
03869 rb_cNumeric = rb_define_class("Numeric", rb_cObject);
03870
03871 rb_define_method(rb_cNumeric, "singleton_method_added", num_sadded, 1);
03872 rb_include_module(rb_cNumeric, rb_mComparable);
03873 rb_define_method(rb_cNumeric, "initialize_copy", num_init_copy, 1);
03874 rb_define_method(rb_cNumeric, "coerce", num_coerce, 1);
03875
03876 rb_define_method(rb_cNumeric, "i", num_imaginary, 0);
03877 rb_define_method(rb_cNumeric, "+@", num_uplus, 0);
03878 rb_define_method(rb_cNumeric, "-@", num_uminus, 0);
03879 rb_define_method(rb_cNumeric, "<=>", num_cmp, 1);
03880 rb_define_method(rb_cNumeric, "eql?", num_eql, 1);
03881 rb_define_method(rb_cNumeric, "fdiv", num_fdiv, 1);
03882 rb_define_method(rb_cNumeric, "div", num_div, 1);
03883 rb_define_method(rb_cNumeric, "divmod", num_divmod, 1);
03884 rb_define_method(rb_cNumeric, "%", num_modulo, 1);
03885 rb_define_method(rb_cNumeric, "modulo", num_modulo, 1);
03886 rb_define_method(rb_cNumeric, "remainder", num_remainder, 1);
03887 rb_define_method(rb_cNumeric, "abs", num_abs, 0);
03888 rb_define_method(rb_cNumeric, "magnitude", num_abs, 0);
03889 rb_define_method(rb_cNumeric, "to_int", num_to_int, 0);
03890
03891 rb_define_method(rb_cNumeric, "real?", num_real_p, 0);
03892 rb_define_method(rb_cNumeric, "integer?", num_int_p, 0);
03893 rb_define_method(rb_cNumeric, "zero?", num_zero_p, 0);
03894 rb_define_method(rb_cNumeric, "nonzero?", num_nonzero_p, 0);
03895
03896 rb_define_method(rb_cNumeric, "floor", num_floor, 0);
03897 rb_define_method(rb_cNumeric, "ceil", num_ceil, 0);
03898 rb_define_method(rb_cNumeric, "round", num_round, -1);
03899 rb_define_method(rb_cNumeric, "truncate", num_truncate, 0);
03900 rb_define_method(rb_cNumeric, "step", num_step, -1);
03901
03902 rb_cInteger = rb_define_class("Integer", rb_cNumeric);
03903 rb_undef_alloc_func(rb_cInteger);
03904 rb_undef_method(CLASS_OF(rb_cInteger), "new");
03905
03906 rb_define_method(rb_cInteger, "integer?", int_int_p, 0);
03907 rb_define_method(rb_cInteger, "odd?", int_odd_p, 0);
03908 rb_define_method(rb_cInteger, "even?", int_even_p, 0);
03909 rb_define_method(rb_cInteger, "upto", int_upto, 1);
03910 rb_define_method(rb_cInteger, "downto", int_downto, 1);
03911 rb_define_method(rb_cInteger, "times", int_dotimes, 0);
03912 rb_define_method(rb_cInteger, "succ", int_succ, 0);
03913 rb_define_method(rb_cInteger, "next", int_succ, 0);
03914 rb_define_method(rb_cInteger, "pred", int_pred, 0);
03915 rb_define_method(rb_cInteger, "chr", int_chr, -1);
03916 rb_define_method(rb_cInteger, "ord", int_ord, 0);
03917 rb_define_method(rb_cInteger, "to_i", int_to_i, 0);
03918 rb_define_method(rb_cInteger, "to_int", int_to_i, 0);
03919 rb_define_method(rb_cInteger, "floor", int_to_i, 0);
03920 rb_define_method(rb_cInteger, "ceil", int_to_i, 0);
03921 rb_define_method(rb_cInteger, "truncate", int_to_i, 0);
03922 rb_define_method(rb_cInteger, "round", int_round, -1);
03923
03924 rb_cFixnum = rb_define_class("Fixnum", rb_cInteger);
03925
03926 rb_define_method(rb_cFixnum, "to_s", fix_to_s, -1);
03927 rb_define_alias(rb_cFixnum, "inspect", "to_s");
03928
03929 rb_define_method(rb_cFixnum, "-@", fix_uminus, 0);
03930 rb_define_method(rb_cFixnum, "+", fix_plus, 1);
03931 rb_define_method(rb_cFixnum, "-", fix_minus, 1);
03932 rb_define_method(rb_cFixnum, "*", fix_mul, 1);
03933 rb_define_method(rb_cFixnum, "/", fix_div, 1);
03934 rb_define_method(rb_cFixnum, "div", fix_idiv, 1);
03935 rb_define_method(rb_cFixnum, "%", fix_mod, 1);
03936 rb_define_method(rb_cFixnum, "modulo", fix_mod, 1);
03937 rb_define_method(rb_cFixnum, "divmod", fix_divmod, 1);
03938 rb_define_method(rb_cFixnum, "fdiv", fix_fdiv, 1);
03939 rb_define_method(rb_cFixnum, "**", fix_pow, 1);
03940
03941 rb_define_method(rb_cFixnum, "abs", fix_abs, 0);
03942 rb_define_method(rb_cFixnum, "magnitude", fix_abs, 0);
03943
03944 rb_define_method(rb_cFixnum, "==", fix_equal, 1);
03945 rb_define_method(rb_cFixnum, "===", fix_equal, 1);
03946 rb_define_method(rb_cFixnum, "<=>", fix_cmp, 1);
03947 rb_define_method(rb_cFixnum, ">", fix_gt, 1);
03948 rb_define_method(rb_cFixnum, ">=", fix_ge, 1);
03949 rb_define_method(rb_cFixnum, "<", fix_lt, 1);
03950 rb_define_method(rb_cFixnum, "<=", fix_le, 1);
03951
03952 rb_define_method(rb_cFixnum, "~", fix_rev, 0);
03953 rb_define_method(rb_cFixnum, "&", fix_and, 1);
03954 rb_define_method(rb_cFixnum, "|", fix_or, 1);
03955 rb_define_method(rb_cFixnum, "^", fix_xor, 1);
03956 rb_define_method(rb_cFixnum, "[]", fix_aref, 1);
03957
03958 rb_define_method(rb_cFixnum, "<<", rb_fix_lshift, 1);
03959 rb_define_method(rb_cFixnum, ">>", rb_fix_rshift, 1);
03960
03961 rb_define_method(rb_cFixnum, "to_f", fix_to_f, 0);
03962 rb_define_method(rb_cFixnum, "size", fix_size, 0);
03963 rb_define_method(rb_cFixnum, "bit_length", rb_fix_bit_length, 0);
03964 rb_define_method(rb_cFixnum, "zero?", fix_zero_p, 0);
03965 rb_define_method(rb_cFixnum, "odd?", fix_odd_p, 0);
03966 rb_define_method(rb_cFixnum, "even?", fix_even_p, 0);
03967 rb_define_method(rb_cFixnum, "succ", fix_succ, 0);
03968
03969 rb_cFloat = rb_define_class("Float", rb_cNumeric);
03970
03971 rb_undef_alloc_func(rb_cFloat);
03972 rb_undef_method(CLASS_OF(rb_cFloat), "new");
03973
03974
03975
03976
03977
03978
03979
03980
03981
03982
03983
03984
03985
03986
03987 rb_define_const(rb_cFloat, "ROUNDS", INT2FIX(FLT_ROUNDS));
03988
03989
03990
03991
03992
03993
03994 rb_define_const(rb_cFloat, "RADIX", INT2FIX(FLT_RADIX));
03995
03996
03997
03998
03999
04000 rb_define_const(rb_cFloat, "MANT_DIG", INT2FIX(DBL_MANT_DIG));
04001
04002
04003
04004
04005
04006 rb_define_const(rb_cFloat, "DIG", INT2FIX(DBL_DIG));
04007
04008
04009
04010
04011
04012
04013 rb_define_const(rb_cFloat, "MIN_EXP", INT2FIX(DBL_MIN_EXP));
04014
04015
04016
04017
04018
04019
04020 rb_define_const(rb_cFloat, "MAX_EXP", INT2FIX(DBL_MAX_EXP));
04021
04022
04023
04024
04025
04026
04027 rb_define_const(rb_cFloat, "MIN_10_EXP", INT2FIX(DBL_MIN_10_EXP));
04028
04029
04030
04031
04032
04033
04034 rb_define_const(rb_cFloat, "MAX_10_EXP", INT2FIX(DBL_MAX_10_EXP));
04035
04036
04037
04038
04039
04040 rb_define_const(rb_cFloat, "MIN", DBL2NUM(DBL_MIN));
04041
04042
04043
04044
04045
04046 rb_define_const(rb_cFloat, "MAX", DBL2NUM(DBL_MAX));
04047
04048
04049
04050
04051
04052
04053 rb_define_const(rb_cFloat, "EPSILON", DBL2NUM(DBL_EPSILON));
04054
04055
04056
04057 rb_define_const(rb_cFloat, "INFINITY", DBL2NUM(INFINITY));
04058
04059
04060
04061 rb_define_const(rb_cFloat, "NAN", DBL2NUM(NAN));
04062
04063 rb_define_method(rb_cFloat, "to_s", flo_to_s, 0);
04064 rb_define_alias(rb_cFloat, "inspect", "to_s");
04065 rb_define_method(rb_cFloat, "coerce", flo_coerce, 1);
04066 rb_define_method(rb_cFloat, "-@", flo_uminus, 0);
04067 rb_define_method(rb_cFloat, "+", flo_plus, 1);
04068 rb_define_method(rb_cFloat, "-", flo_minus, 1);
04069 rb_define_method(rb_cFloat, "*", flo_mul, 1);
04070 rb_define_method(rb_cFloat, "/", flo_div, 1);
04071 rb_define_method(rb_cFloat, "quo", flo_quo, 1);
04072 rb_define_method(rb_cFloat, "fdiv", flo_quo, 1);
04073 rb_define_method(rb_cFloat, "%", flo_mod, 1);
04074 rb_define_method(rb_cFloat, "modulo", flo_mod, 1);
04075 rb_define_method(rb_cFloat, "divmod", flo_divmod, 1);
04076 rb_define_method(rb_cFloat, "**", flo_pow, 1);
04077 rb_define_method(rb_cFloat, "==", flo_eq, 1);
04078 rb_define_method(rb_cFloat, "===", flo_eq, 1);
04079 rb_define_method(rb_cFloat, "<=>", flo_cmp, 1);
04080 rb_define_method(rb_cFloat, ">", flo_gt, 1);
04081 rb_define_method(rb_cFloat, ">=", flo_ge, 1);
04082 rb_define_method(rb_cFloat, "<", flo_lt, 1);
04083 rb_define_method(rb_cFloat, "<=", flo_le, 1);
04084 rb_define_method(rb_cFloat, "eql?", flo_eql, 1);
04085 rb_define_method(rb_cFloat, "hash", flo_hash, 0);
04086 rb_define_method(rb_cFloat, "to_f", flo_to_f, 0);
04087 rb_define_method(rb_cFloat, "abs", flo_abs, 0);
04088 rb_define_method(rb_cFloat, "magnitude", flo_abs, 0);
04089 rb_define_method(rb_cFloat, "zero?", flo_zero_p, 0);
04090
04091 rb_define_method(rb_cFloat, "to_i", flo_truncate, 0);
04092 rb_define_method(rb_cFloat, "to_int", flo_truncate, 0);
04093 rb_define_method(rb_cFloat, "floor", flo_floor, 0);
04094 rb_define_method(rb_cFloat, "ceil", flo_ceil, 0);
04095 rb_define_method(rb_cFloat, "round", flo_round, -1);
04096 rb_define_method(rb_cFloat, "truncate", flo_truncate, 0);
04097
04098 rb_define_method(rb_cFloat, "nan?", flo_is_nan_p, 0);
04099 rb_define_method(rb_cFloat, "infinite?", flo_is_infinite_p, 0);
04100 rb_define_method(rb_cFloat, "finite?", flo_is_finite_p, 0);
04101
04102 id_to = rb_intern("to");
04103 id_by = rb_intern("by");
04104 }
04105
04106 #undef rb_float_value
04107 double
04108 rb_float_value(VALUE v)
04109 {
04110 return rb_float_value_inline(v);
04111 }
04112
04113 #undef rb_float_new
04114 VALUE
04115 rb_float_new(double d)
04116 {
04117 return rb_float_new_inline(d);
04118 }
04119