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