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