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