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) 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
02042
02043
02044
02045
02046
02047
02048
02049
02050
02051
02052
02053 static VALUE
02054 int_chr(int argc, VALUE *argv, VALUE num)
02055 {
02056 char c;
02057 int n;
02058 SIGNED_VALUE i = NUM2LONG(num);
02059 rb_encoding *enc;
02060 VALUE str;
02061
02062 switch (argc) {
02063 case 0:
02064 if (i < 0) {
02065 out_of_range:
02066 rb_raise(rb_eRangeError, "%"PRIdVALUE " out of char range", i);
02067 }
02068 if (0xff < i) {
02069 enc = rb_default_internal_encoding();
02070 if (!enc) goto out_of_range;
02071 goto decode;
02072 }
02073 c = (char)i;
02074 if (i < 0x80) {
02075 return rb_usascii_str_new(&c, 1);
02076 }
02077 else {
02078 return rb_str_new(&c, 1);
02079 }
02080 case 1:
02081 break;
02082 default:
02083 rb_raise(rb_eArgError, "wrong number of arguments (%d for 0..1)", argc);
02084 break;
02085 }
02086 enc = rb_to_encoding(argv[0]);
02087 if (!enc) enc = rb_ascii8bit_encoding();
02088 decode:
02089 #if SIZEOF_INT < SIZEOF_VALUE
02090 if (i > UINT_MAX) goto out_of_range;
02091 #endif
02092 if (i < 0 || (n = rb_enc_codelen((int)i, enc)) <= 0) goto out_of_range;
02093 str = rb_enc_str_new(0, n, enc);
02094 rb_enc_mbcput((int)i, RSTRING_PTR(str), enc);
02095 return str;
02096 }
02097
02098
02099
02100
02101
02102
02103
02104
02105
02106
02107
02108
02109
02110
02111 static VALUE
02112 int_ord(num)
02113 VALUE num;
02114 {
02115 return num;
02116 }
02117
02118
02119
02120
02121
02122
02123
02124
02125
02126
02127
02128
02129
02130
02131
02132
02133
02134
02135
02136
02137
02138
02139
02140
02141
02142
02143
02144 static VALUE
02145 fix_uminus(VALUE num)
02146 {
02147 return LONG2NUM(-FIX2LONG(num));
02148 }
02149
02150 VALUE
02151 rb_fix2str(VALUE x, int base)
02152 {
02153 extern const char ruby_digitmap[];
02154 char buf[SIZEOF_VALUE*CHAR_BIT + 2], *b = buf + sizeof buf;
02155 long val = FIX2LONG(x);
02156 int neg = 0;
02157
02158 if (base < 2 || 36 < base) {
02159 rb_raise(rb_eArgError, "invalid radix %d", base);
02160 }
02161 if (val == 0) {
02162 return rb_usascii_str_new2("0");
02163 }
02164 if (val < 0) {
02165 val = -val;
02166 neg = 1;
02167 }
02168 *--b = '\0';
02169 do {
02170 *--b = ruby_digitmap[(int)(val % base)];
02171 } while (val /= base);
02172 if (neg) {
02173 *--b = '-';
02174 }
02175
02176 return rb_usascii_str_new2(b);
02177 }
02178
02179
02180
02181
02182
02183
02184
02185
02186
02187
02188
02189
02190
02191
02192
02193
02194 static VALUE
02195 fix_to_s(int argc, VALUE *argv, VALUE x)
02196 {
02197 int base;
02198
02199 if (argc == 0) base = 10;
02200 else {
02201 VALUE b;
02202
02203 rb_scan_args(argc, argv, "01", &b);
02204 base = NUM2INT(b);
02205 }
02206
02207 return rb_fix2str(x, base);
02208 }
02209
02210
02211
02212
02213
02214
02215
02216
02217
02218
02219 static VALUE
02220 fix_plus(VALUE x, VALUE y)
02221 {
02222 if (FIXNUM_P(y)) {
02223 long a, b, c;
02224 VALUE r;
02225
02226 a = FIX2LONG(x);
02227 b = FIX2LONG(y);
02228 c = a + b;
02229 r = LONG2NUM(c);
02230
02231 return r;
02232 }
02233 switch (TYPE(y)) {
02234 case T_BIGNUM:
02235 return rb_big_plus(y, x);
02236 case T_FLOAT:
02237 return DBL2NUM((double)FIX2LONG(x) + RFLOAT_VALUE(y));
02238 default:
02239 return rb_num_coerce_bin(x, y, '+');
02240 }
02241 }
02242
02243
02244
02245
02246
02247
02248
02249
02250
02251
02252 static VALUE
02253 fix_minus(VALUE x, VALUE y)
02254 {
02255 if (FIXNUM_P(y)) {
02256 long a, b, c;
02257 VALUE r;
02258
02259 a = FIX2LONG(x);
02260 b = FIX2LONG(y);
02261 c = a - b;
02262 r = LONG2NUM(c);
02263
02264 return r;
02265 }
02266 switch (TYPE(y)) {
02267 case T_BIGNUM:
02268 x = rb_int2big(FIX2LONG(x));
02269 return rb_big_minus(x, y);
02270 case T_FLOAT:
02271 return DBL2NUM((double)FIX2LONG(x) - RFLOAT_VALUE(y));
02272 default:
02273 return rb_num_coerce_bin(x, y, '-');
02274 }
02275 }
02276
02277 #define SQRT_LONG_MAX ((SIGNED_VALUE)1<<((SIZEOF_LONG*CHAR_BIT-1)/2))
02278
02279 #define FIT_SQRT_LONG(n) (((n)<SQRT_LONG_MAX)&&((n)>=-SQRT_LONG_MAX))
02280
02281
02282
02283
02284
02285
02286
02287
02288
02289
02290 static VALUE
02291 fix_mul(VALUE x, VALUE y)
02292 {
02293 if (FIXNUM_P(y)) {
02294 #ifdef __HP_cc
02295
02296 volatile
02297 #endif
02298 long a, b;
02299 #if SIZEOF_LONG * 2 <= SIZEOF_LONG_LONG
02300 LONG_LONG d;
02301 #else
02302 long c;
02303 VALUE r;
02304 #endif
02305
02306 a = FIX2LONG(x);
02307 b = FIX2LONG(y);
02308
02309 #if SIZEOF_LONG * 2 <= SIZEOF_LONG_LONG
02310 d = (LONG_LONG)a * b;
02311 if (FIXABLE(d)) return LONG2FIX(d);
02312 return rb_ll2inum(d);
02313 #else
02314 if (FIT_SQRT_LONG(a) && FIT_SQRT_LONG(b))
02315 return LONG2FIX(a*b);
02316 c = a * b;
02317 r = LONG2FIX(c);
02318
02319 if (a == 0) return x;
02320 if (FIX2LONG(r) != c || c/a != b) {
02321 r = rb_big_mul(rb_int2big(a), rb_int2big(b));
02322 }
02323 return r;
02324 #endif
02325 }
02326 switch (TYPE(y)) {
02327 case T_BIGNUM:
02328 return rb_big_mul(y, x);
02329 case T_FLOAT:
02330 return DBL2NUM((double)FIX2LONG(x) * RFLOAT_VALUE(y));
02331 default:
02332 return rb_num_coerce_bin(x, y, '*');
02333 }
02334 }
02335
02336 static void
02337 fixdivmod(long x, long y, long *divp, long *modp)
02338 {
02339 long div, mod;
02340
02341 if (y == 0) rb_num_zerodiv();
02342 if (y < 0) {
02343 if (x < 0)
02344 div = -x / -y;
02345 else
02346 div = - (x / -y);
02347 }
02348 else {
02349 if (x < 0)
02350 div = - (-x / y);
02351 else
02352 div = x / y;
02353 }
02354 mod = x - div*y;
02355 if ((mod < 0 && y > 0) || (mod > 0 && y < 0)) {
02356 mod += y;
02357 div -= 1;
02358 }
02359 if (divp) *divp = div;
02360 if (modp) *modp = mod;
02361 }
02362
02363 VALUE rb_big_fdiv(VALUE x, VALUE y);
02364
02365
02366
02367
02368
02369
02370
02371
02372
02373
02374
02375
02376
02377 static VALUE
02378 fix_fdiv(VALUE x, VALUE y)
02379 {
02380 if (FIXNUM_P(y)) {
02381 return DBL2NUM((double)FIX2LONG(x) / (double)FIX2LONG(y));
02382 }
02383 switch (TYPE(y)) {
02384 case T_BIGNUM:
02385 return rb_big_fdiv(rb_int2big(FIX2LONG(x)), y);
02386 case T_FLOAT:
02387 return DBL2NUM((double)FIX2LONG(x) / RFLOAT_VALUE(y));
02388 default:
02389 return rb_num_coerce_bin(x, y, rb_intern("fdiv"));
02390 }
02391 }
02392
02393 VALUE rb_rational_reciprocal(VALUE x);
02394
02395 static VALUE
02396 fix_divide(VALUE x, VALUE y, ID op)
02397 {
02398 if (FIXNUM_P(y)) {
02399 long div;
02400
02401 fixdivmod(FIX2LONG(x), FIX2LONG(y), &div, 0);
02402 return LONG2NUM(div);
02403 }
02404 switch (TYPE(y)) {
02405 case T_BIGNUM:
02406 x = rb_int2big(FIX2LONG(x));
02407 return rb_big_div(x, y);
02408 case T_FLOAT:
02409 {
02410 double div;
02411
02412 if (op == '/') {
02413 div = (double)FIX2LONG(x) / RFLOAT_VALUE(y);
02414 return DBL2NUM(div);
02415 }
02416 else {
02417 if (RFLOAT_VALUE(y) == 0) rb_num_zerodiv();
02418 div = (double)FIX2LONG(x) / RFLOAT_VALUE(y);
02419 return rb_dbl2big(floor(div));
02420 }
02421 }
02422 case T_RATIONAL:
02423 if (op == '/' && FIX2LONG(x) == 1)
02424 return rb_rational_reciprocal(y);
02425
02426 default:
02427 return rb_num_coerce_bin(x, y, op);
02428 }
02429 }
02430
02431
02432
02433
02434
02435
02436
02437
02438
02439
02440 static VALUE
02441 fix_div(VALUE x, VALUE y)
02442 {
02443 return fix_divide(x, y, '/');
02444 }
02445
02446
02447
02448
02449
02450
02451
02452
02453 static VALUE
02454 fix_idiv(VALUE x, VALUE y)
02455 {
02456 return fix_divide(x, y, rb_intern("div"));
02457 }
02458
02459
02460
02461
02462
02463
02464
02465
02466
02467
02468 static VALUE
02469 fix_mod(VALUE x, VALUE y)
02470 {
02471 if (FIXNUM_P(y)) {
02472 long mod;
02473
02474 fixdivmod(FIX2LONG(x), FIX2LONG(y), 0, &mod);
02475 return LONG2NUM(mod);
02476 }
02477 switch (TYPE(y)) {
02478 case T_BIGNUM:
02479 x = rb_int2big(FIX2LONG(x));
02480 return rb_big_modulo(x, y);
02481 case T_FLOAT:
02482 {
02483 double mod;
02484
02485 flodivmod((double)FIX2LONG(x), RFLOAT_VALUE(y), 0, &mod);
02486 return DBL2NUM(mod);
02487 }
02488 default:
02489 return rb_num_coerce_bin(x, y, '%');
02490 }
02491 }
02492
02493
02494
02495
02496
02497
02498
02499 static VALUE
02500 fix_divmod(VALUE x, VALUE y)
02501 {
02502 if (FIXNUM_P(y)) {
02503 long div, mod;
02504
02505 fixdivmod(FIX2LONG(x), FIX2LONG(y), &div, &mod);
02506
02507 return rb_assoc_new(LONG2NUM(div), LONG2NUM(mod));
02508 }
02509 switch (TYPE(y)) {
02510 case T_BIGNUM:
02511 x = rb_int2big(FIX2LONG(x));
02512 return rb_big_divmod(x, y);
02513 case T_FLOAT:
02514 {
02515 double div, mod;
02516 volatile VALUE a, b;
02517
02518 flodivmod((double)FIX2LONG(x), RFLOAT_VALUE(y), &div, &mod);
02519 a = dbl2ival(div);
02520 b = DBL2NUM(mod);
02521 return rb_assoc_new(a, b);
02522 }
02523 default:
02524 return rb_num_coerce_bin(x, y, rb_intern("divmod"));
02525 }
02526 }
02527
02528 static VALUE
02529 int_pow(long x, unsigned long y)
02530 {
02531 int neg = x < 0;
02532 long z = 1;
02533
02534 if (neg) x = -x;
02535 if (y & 1)
02536 z = x;
02537 else
02538 neg = 0;
02539 y &= ~1;
02540 do {
02541 while (y % 2 == 0) {
02542 if (!FIT_SQRT_LONG(x)) {
02543 VALUE v;
02544 bignum:
02545 v = rb_big_pow(rb_int2big(x), LONG2NUM(y));
02546 if (z != 1) v = rb_big_mul(rb_int2big(neg ? -z : z), v);
02547 return v;
02548 }
02549 x = x * x;
02550 y >>= 1;
02551 }
02552 {
02553 long xz = x * z;
02554 if (!POSFIXABLE(xz) || xz / x != z) {
02555 goto bignum;
02556 }
02557 z = xz;
02558 }
02559 } while (--y);
02560 if (neg) z = -z;
02561 return LONG2NUM(z);
02562 }
02563
02564
02565
02566
02567
02568
02569
02570
02571
02572
02573
02574
02575
02576 static VALUE
02577 fix_pow(VALUE x, VALUE y)
02578 {
02579 long a = FIX2LONG(x);
02580
02581 if (FIXNUM_P(y)) {
02582 long b = FIX2LONG(y);
02583
02584 if (b < 0)
02585 return rb_funcall(rb_rational_raw1(x), rb_intern("**"), 1, y);
02586
02587 if (b == 0) return INT2FIX(1);
02588 if (b == 1) return x;
02589 if (a == 0) {
02590 if (b > 0) return INT2FIX(0);
02591 return DBL2NUM(INFINITY);
02592 }
02593 if (a == 1) return INT2FIX(1);
02594 if (a == -1) {
02595 if (b % 2 == 0)
02596 return INT2FIX(1);
02597 else
02598 return INT2FIX(-1);
02599 }
02600 return int_pow(a, b);
02601 }
02602 switch (TYPE(y)) {
02603 case T_BIGNUM:
02604
02605 if (rb_funcall(y, '<', 1, INT2FIX(0)))
02606 return rb_funcall(rb_rational_raw1(x), rb_intern("**"), 1, y);
02607
02608 if (a == 0) return INT2FIX(0);
02609 if (a == 1) return INT2FIX(1);
02610 if (a == -1) {
02611 if (int_even_p(y)) return INT2FIX(1);
02612 else return INT2FIX(-1);
02613 }
02614 x = rb_int2big(FIX2LONG(x));
02615 return rb_big_pow(x, y);
02616 case T_FLOAT:
02617 if (RFLOAT_VALUE(y) == 0.0) return DBL2NUM(1.0);
02618 if (a == 0) {
02619 return DBL2NUM(RFLOAT_VALUE(y) < 0 ? INFINITY : 0.0);
02620 }
02621 if (a == 1) return DBL2NUM(1.0);
02622 {
02623 double dy = RFLOAT_VALUE(y);
02624 if (a < 0 && dy != round(dy))
02625 return rb_funcall(rb_complex_raw1(x), rb_intern("**"), 1, y);
02626 return DBL2NUM(pow((double)a, dy));
02627 }
02628 default:
02629 return rb_num_coerce_bin(x, y, rb_intern("**"));
02630 }
02631 }
02632
02633
02634
02635
02636
02637
02638
02639
02640
02641
02642
02643
02644 static VALUE
02645 fix_equal(VALUE x, VALUE y)
02646 {
02647 if (x == y) return Qtrue;
02648 if (FIXNUM_P(y)) return Qfalse;
02649 switch (TYPE(y)) {
02650 case T_BIGNUM:
02651 return rb_big_eq(y, x);
02652 case T_FLOAT:
02653 return (double)FIX2LONG(x) == RFLOAT_VALUE(y) ? Qtrue : Qfalse;
02654 default:
02655 return num_equal(x, y);
02656 }
02657 }
02658
02659
02660
02661
02662
02663
02664
02665
02666
02667
02668
02669 static VALUE
02670 fix_cmp(VALUE x, VALUE y)
02671 {
02672 if (x == y) return INT2FIX(0);
02673 if (FIXNUM_P(y)) {
02674 if (FIX2LONG(x) > FIX2LONG(y)) return INT2FIX(1);
02675 return INT2FIX(-1);
02676 }
02677 switch (TYPE(y)) {
02678 case T_BIGNUM:
02679 return rb_big_cmp(rb_int2big(FIX2LONG(x)), y);
02680 case T_FLOAT:
02681 return rb_dbl_cmp((double)FIX2LONG(x), RFLOAT_VALUE(y));
02682 default:
02683 return rb_num_coerce_cmp(x, y, rb_intern("<=>"));
02684 }
02685 }
02686
02687
02688
02689
02690
02691
02692
02693
02694
02695 static VALUE
02696 fix_gt(VALUE x, VALUE y)
02697 {
02698 if (FIXNUM_P(y)) {
02699 if (FIX2LONG(x) > FIX2LONG(y)) return Qtrue;
02700 return Qfalse;
02701 }
02702 switch (TYPE(y)) {
02703 case T_BIGNUM:
02704 return FIX2INT(rb_big_cmp(rb_int2big(FIX2LONG(x)), y)) > 0 ? Qtrue : Qfalse;
02705 case T_FLOAT:
02706 return (double)FIX2LONG(x) > RFLOAT_VALUE(y) ? Qtrue : Qfalse;
02707 default:
02708 return rb_num_coerce_relop(x, y, '>');
02709 }
02710 }
02711
02712
02713
02714
02715
02716
02717
02718
02719
02720 static VALUE
02721 fix_ge(VALUE x, VALUE y)
02722 {
02723 if (FIXNUM_P(y)) {
02724 if (FIX2LONG(x) >= FIX2LONG(y)) return Qtrue;
02725 return Qfalse;
02726 }
02727 switch (TYPE(y)) {
02728 case T_BIGNUM:
02729 return FIX2INT(rb_big_cmp(rb_int2big(FIX2LONG(x)), y)) >= 0 ? Qtrue : Qfalse;
02730 case T_FLOAT:
02731 return (double)FIX2LONG(x) >= RFLOAT_VALUE(y) ? Qtrue : Qfalse;
02732 default:
02733 return rb_num_coerce_relop(x, y, rb_intern(">="));
02734 }
02735 }
02736
02737
02738
02739
02740
02741
02742
02743
02744
02745 static VALUE
02746 fix_lt(VALUE x, VALUE y)
02747 {
02748 if (FIXNUM_P(y)) {
02749 if (FIX2LONG(x) < FIX2LONG(y)) return Qtrue;
02750 return Qfalse;
02751 }
02752 switch (TYPE(y)) {
02753 case T_BIGNUM:
02754 return FIX2INT(rb_big_cmp(rb_int2big(FIX2LONG(x)), y)) < 0 ? Qtrue : Qfalse;
02755 case T_FLOAT:
02756 return (double)FIX2LONG(x) < RFLOAT_VALUE(y) ? Qtrue : Qfalse;
02757 default:
02758 return rb_num_coerce_relop(x, y, '<');
02759 }
02760 }
02761
02762
02763
02764
02765
02766
02767
02768
02769
02770 static VALUE
02771 fix_le(VALUE x, VALUE y)
02772 {
02773 if (FIXNUM_P(y)) {
02774 if (FIX2LONG(x) <= FIX2LONG(y)) return Qtrue;
02775 return Qfalse;
02776 }
02777 switch (TYPE(y)) {
02778 case T_BIGNUM:
02779 return FIX2INT(rb_big_cmp(rb_int2big(FIX2LONG(x)), y)) <= 0 ? Qtrue : Qfalse;
02780 case T_FLOAT:
02781 return (double)FIX2LONG(x) <= RFLOAT_VALUE(y) ? Qtrue : Qfalse;
02782 default:
02783 return rb_num_coerce_relop(x, y, rb_intern("<="));
02784 }
02785 }
02786
02787
02788
02789
02790
02791
02792
02793
02794 static VALUE
02795 fix_rev(VALUE num)
02796 {
02797 long val = FIX2LONG(num);
02798
02799 val = ~val;
02800 return LONG2NUM(val);
02801 }
02802
02803 static VALUE
02804 bit_coerce(VALUE x)
02805 {
02806 while (!FIXNUM_P(x) && TYPE(x) != T_BIGNUM) {
02807 if (TYPE(x) == T_FLOAT) {
02808 rb_raise(rb_eTypeError, "can't convert Float into Integer");
02809 }
02810 x = rb_to_int(x);
02811 }
02812 return x;
02813 }
02814
02815
02816
02817
02818
02819
02820
02821
02822 static VALUE
02823 fix_and(VALUE x, VALUE y)
02824 {
02825 long val;
02826
02827 if (!FIXNUM_P(y = bit_coerce(y))) {
02828 return rb_big_and(y, x);
02829 }
02830 val = FIX2LONG(x) & FIX2LONG(y);
02831 return LONG2NUM(val);
02832 }
02833
02834
02835
02836
02837
02838
02839
02840
02841 static VALUE
02842 fix_or(VALUE x, VALUE y)
02843 {
02844 long val;
02845
02846 if (!FIXNUM_P(y = bit_coerce(y))) {
02847 return rb_big_or(y, x);
02848 }
02849 val = FIX2LONG(x) | FIX2LONG(y);
02850 return LONG2NUM(val);
02851 }
02852
02853
02854
02855
02856
02857
02858
02859
02860 static VALUE
02861 fix_xor(VALUE x, VALUE y)
02862 {
02863 long val;
02864
02865 if (!FIXNUM_P(y = bit_coerce(y))) {
02866 return rb_big_xor(y, x);
02867 }
02868 val = FIX2LONG(x) ^ FIX2LONG(y);
02869 return LONG2NUM(val);
02870 }
02871
02872 static VALUE fix_lshift(long, unsigned long);
02873 static VALUE fix_rshift(long, unsigned long);
02874
02875
02876
02877
02878
02879
02880
02881
02882 static VALUE
02883 rb_fix_lshift(VALUE x, VALUE y)
02884 {
02885 long val, width;
02886
02887 val = NUM2LONG(x);
02888 if (!FIXNUM_P(y))
02889 return rb_big_lshift(rb_int2big(val), y);
02890 width = FIX2LONG(y);
02891 if (width < 0)
02892 return fix_rshift(val, (unsigned long)-width);
02893 return fix_lshift(val, width);
02894 }
02895
02896 static VALUE
02897 fix_lshift(long val, unsigned long width)
02898 {
02899 if (width > (SIZEOF_LONG*CHAR_BIT-1)
02900 || ((unsigned long)val)>>(SIZEOF_LONG*CHAR_BIT-1-width) > 0) {
02901 return rb_big_lshift(rb_int2big(val), ULONG2NUM(width));
02902 }
02903 val = val << width;
02904 return LONG2NUM(val);
02905 }
02906
02907
02908
02909
02910
02911
02912
02913
02914 static VALUE
02915 rb_fix_rshift(VALUE x, VALUE y)
02916 {
02917 long i, val;
02918
02919 val = FIX2LONG(x);
02920 if (!FIXNUM_P(y))
02921 return rb_big_rshift(rb_int2big(val), y);
02922 i = FIX2LONG(y);
02923 if (i == 0) return x;
02924 if (i < 0)
02925 return fix_lshift(val, (unsigned long)-i);
02926 return fix_rshift(val, i);
02927 }
02928
02929 static VALUE
02930 fix_rshift(long val, unsigned long i)
02931 {
02932 if (i >= sizeof(long)*CHAR_BIT-1) {
02933 if (val < 0) return INT2FIX(-1);
02934 return INT2FIX(0);
02935 }
02936 val = RSHIFT(val, i);
02937 return LONG2FIX(val);
02938 }
02939
02940
02941
02942
02943
02944
02945
02946
02947
02948
02949
02950
02951
02952
02953
02954
02955
02956 static VALUE
02957 fix_aref(VALUE fix, VALUE idx)
02958 {
02959 long val = FIX2LONG(fix);
02960 long i;
02961
02962 idx = rb_to_int(idx);
02963 if (!FIXNUM_P(idx)) {
02964 idx = rb_big_norm(idx);
02965 if (!FIXNUM_P(idx)) {
02966 if (!RBIGNUM_SIGN(idx) || val >= 0)
02967 return INT2FIX(0);
02968 return INT2FIX(1);
02969 }
02970 }
02971 i = FIX2LONG(idx);
02972
02973 if (i < 0) return INT2FIX(0);
02974 if (SIZEOF_LONG*CHAR_BIT-1 < i) {
02975 if (val < 0) return INT2FIX(1);
02976 return INT2FIX(0);
02977 }
02978 if (val & (1L<<i))
02979 return INT2FIX(1);
02980 return INT2FIX(0);
02981 }
02982
02983
02984
02985
02986
02987
02988
02989
02990
02991 static VALUE
02992 fix_to_f(VALUE num)
02993 {
02994 double val;
02995
02996 val = (double)FIX2LONG(num);
02997
02998 return DBL2NUM(val);
02999 }
03000
03001
03002
03003
03004
03005
03006
03007
03008
03009
03010
03011
03012
03013 static VALUE
03014 fix_abs(VALUE fix)
03015 {
03016 long i = FIX2LONG(fix);
03017
03018 if (i < 0) i = -i;
03019
03020 return LONG2NUM(i);
03021 }
03022
03023
03024
03025
03026
03027
03028
03029
03030
03031
03032
03033
03034
03035
03036
03037 static VALUE
03038 fix_size(VALUE fix)
03039 {
03040 return INT2FIX(sizeof(long));
03041 }
03042
03043
03044
03045
03046
03047
03048
03049
03050
03051
03052
03053
03054
03055
03056
03057
03058
03059
03060 static VALUE
03061 int_upto(VALUE from, VALUE to)
03062 {
03063 RETURN_ENUMERATOR(from, 1, &to);
03064 if (FIXNUM_P(from) && FIXNUM_P(to)) {
03065 long i, end;
03066
03067 end = FIX2LONG(to);
03068 for (i = FIX2LONG(from); i <= end; i++) {
03069 rb_yield(LONG2FIX(i));
03070 }
03071 }
03072 else {
03073 VALUE i = from, c;
03074
03075 while (!(c = rb_funcall(i, '>', 1, to))) {
03076 rb_yield(i);
03077 i = rb_funcall(i, '+', 1, INT2FIX(1));
03078 }
03079 if (NIL_P(c)) rb_cmperr(i, to);
03080 }
03081 return from;
03082 }
03083
03084
03085
03086
03087
03088
03089
03090
03091
03092
03093
03094
03095
03096
03097
03098
03099
03100
03101
03102 static VALUE
03103 int_downto(VALUE from, VALUE to)
03104 {
03105 RETURN_ENUMERATOR(from, 1, &to);
03106 if (FIXNUM_P(from) && FIXNUM_P(to)) {
03107 long i, end;
03108
03109 end = FIX2LONG(to);
03110 for (i=FIX2LONG(from); i >= end; i--) {
03111 rb_yield(LONG2FIX(i));
03112 }
03113 }
03114 else {
03115 VALUE i = from, c;
03116
03117 while (!(c = rb_funcall(i, '<', 1, to))) {
03118 rb_yield(i);
03119 i = rb_funcall(i, '-', 1, INT2FIX(1));
03120 }
03121 if (NIL_P(c)) rb_cmperr(i, to);
03122 }
03123 return from;
03124 }
03125
03126
03127
03128
03129
03130
03131
03132
03133
03134
03135
03136
03137
03138
03139
03140
03141
03142
03143
03144
03145 static VALUE
03146 int_dotimes(VALUE num)
03147 {
03148 RETURN_ENUMERATOR(num, 0, 0);
03149
03150 if (FIXNUM_P(num)) {
03151 long i, end;
03152
03153 end = FIX2LONG(num);
03154 for (i=0; i<end; i++) {
03155 rb_yield(LONG2FIX(i));
03156 }
03157 }
03158 else {
03159 VALUE i = INT2FIX(0);
03160
03161 for (;;) {
03162 if (!RTEST(rb_funcall(i, '<', 1, num))) break;
03163 rb_yield(i);
03164 i = rb_funcall(i, '+', 1, INT2FIX(1));
03165 }
03166 }
03167 return num;
03168 }
03169
03170
03171
03172
03173
03174
03175
03176
03177
03178
03179
03180
03181
03182
03183 static VALUE
03184 int_round(int argc, VALUE* argv, VALUE num)
03185 {
03186 VALUE n, f, h, r;
03187 int ndigits;
03188
03189 if (argc == 0) return num;
03190 rb_scan_args(argc, argv, "1", &n);
03191 ndigits = NUM2INT(n);
03192 if (ndigits > 0) {
03193 return rb_Float(num);
03194 }
03195 if (ndigits == 0) {
03196 return num;
03197 }
03198 ndigits = -ndigits;
03199 if (ndigits < 0) {
03200 rb_raise(rb_eArgError, "ndigits out of range");
03201 }
03202 f = int_pow(10, ndigits);
03203 if (FIXNUM_P(num) && FIXNUM_P(f)) {
03204 SIGNED_VALUE x = FIX2LONG(num), y = FIX2LONG(f);
03205 int neg = x < 0;
03206 if (neg) x = -x;
03207 x = (x + y / 2) / y * y;
03208 if (neg) x = -x;
03209 return LONG2NUM(x);
03210 }
03211 h = rb_funcall(f, '/', 1, INT2FIX(2));
03212 r = rb_funcall(num, '%', 1, f);
03213 n = rb_funcall(num, '-', 1, r);
03214 if (!RTEST(rb_funcall(r, '<', 1, h))) {
03215 n = rb_funcall(n, '+', 1, f);
03216 }
03217 return n;
03218 }
03219
03220
03221
03222
03223
03224
03225
03226
03227
03228 static VALUE
03229 fix_zero_p(VALUE num)
03230 {
03231 if (FIX2LONG(num) == 0) {
03232 return Qtrue;
03233 }
03234 return Qfalse;
03235 }
03236
03237
03238
03239
03240
03241
03242
03243
03244 static VALUE
03245 fix_odd_p(VALUE num)
03246 {
03247 if (num & 2) {
03248 return Qtrue;
03249 }
03250 return Qfalse;
03251 }
03252
03253
03254
03255
03256
03257
03258
03259
03260 static VALUE
03261 fix_even_p(VALUE num)
03262 {
03263 if (num & 2) {
03264 return Qfalse;
03265 }
03266 return Qtrue;
03267 }
03268
03269
03270
03271
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 void
03302 Init_Numeric(void)
03303 {
03304 #undef rb_intern
03305 #define rb_intern(str) rb_intern_const(str)
03306
03307 #if defined(__FreeBSD__) && __FreeBSD__ < 4
03308
03309 fpsetmask(fpgetmask() & ~(FP_X_DZ|FP_X_INV|FP_X_OFL));
03310 #elif defined(_UNICOSMP)
03311
03312 _set_Creg(0, 0);
03313 #elif defined(__BORLANDC__)
03314
03315 _control87(MCW_EM, MCW_EM);
03316 #endif
03317 id_coerce = rb_intern("coerce");
03318 id_to_i = rb_intern("to_i");
03319 id_eq = rb_intern("==");
03320
03321 rb_eZeroDivError = rb_define_class("ZeroDivisionError", rb_eStandardError);
03322 rb_eFloatDomainError = rb_define_class("FloatDomainError", rb_eRangeError);
03323 rb_cNumeric = rb_define_class("Numeric", rb_cObject);
03324
03325 rb_define_method(rb_cNumeric, "singleton_method_added", num_sadded, 1);
03326 rb_include_module(rb_cNumeric, rb_mComparable);
03327 rb_define_method(rb_cNumeric, "initialize_copy", num_init_copy, 1);
03328 rb_define_method(rb_cNumeric, "coerce", num_coerce, 1);
03329
03330 rb_define_method(rb_cNumeric, "i", num_imaginary, 0);
03331 rb_define_method(rb_cNumeric, "+@", num_uplus, 0);
03332 rb_define_method(rb_cNumeric, "-@", num_uminus, 0);
03333 rb_define_method(rb_cNumeric, "<=>", num_cmp, 1);
03334 rb_define_method(rb_cNumeric, "eql?", num_eql, 1);
03335 rb_define_method(rb_cNumeric, "quo", num_quo, 1);
03336 rb_define_method(rb_cNumeric, "fdiv", num_fdiv, 1);
03337 rb_define_method(rb_cNumeric, "div", num_div, 1);
03338 rb_define_method(rb_cNumeric, "divmod", num_divmod, 1);
03339 rb_define_method(rb_cNumeric, "%", num_modulo, 1);
03340 rb_define_method(rb_cNumeric, "modulo", num_modulo, 1);
03341 rb_define_method(rb_cNumeric, "remainder", num_remainder, 1);
03342 rb_define_method(rb_cNumeric, "abs", num_abs, 0);
03343 rb_define_method(rb_cNumeric, "magnitude", num_abs, 0);
03344 rb_define_method(rb_cNumeric, "to_int", num_to_int, 0);
03345
03346 rb_define_method(rb_cNumeric, "real?", num_real_p, 0);
03347 rb_define_method(rb_cNumeric, "integer?", num_int_p, 0);
03348 rb_define_method(rb_cNumeric, "zero?", num_zero_p, 0);
03349 rb_define_method(rb_cNumeric, "nonzero?", num_nonzero_p, 0);
03350
03351 rb_define_method(rb_cNumeric, "floor", num_floor, 0);
03352 rb_define_method(rb_cNumeric, "ceil", num_ceil, 0);
03353 rb_define_method(rb_cNumeric, "round", num_round, -1);
03354 rb_define_method(rb_cNumeric, "truncate", num_truncate, 0);
03355 rb_define_method(rb_cNumeric, "step", num_step, -1);
03356
03357 rb_cInteger = rb_define_class("Integer", rb_cNumeric);
03358 rb_undef_alloc_func(rb_cInteger);
03359 rb_undef_method(CLASS_OF(rb_cInteger), "new");
03360
03361 rb_define_method(rb_cInteger, "integer?", int_int_p, 0);
03362 rb_define_method(rb_cInteger, "odd?", int_odd_p, 0);
03363 rb_define_method(rb_cInteger, "even?", int_even_p, 0);
03364 rb_define_method(rb_cInteger, "upto", int_upto, 1);
03365 rb_define_method(rb_cInteger, "downto", int_downto, 1);
03366 rb_define_method(rb_cInteger, "times", int_dotimes, 0);
03367 rb_define_method(rb_cInteger, "succ", int_succ, 0);
03368 rb_define_method(rb_cInteger, "next", int_succ, 0);
03369 rb_define_method(rb_cInteger, "pred", int_pred, 0);
03370 rb_define_method(rb_cInteger, "chr", int_chr, -1);
03371 rb_define_method(rb_cInteger, "ord", int_ord, 0);
03372 rb_define_method(rb_cInteger, "to_i", int_to_i, 0);
03373 rb_define_method(rb_cInteger, "to_int", int_to_i, 0);
03374 rb_define_method(rb_cInteger, "floor", int_to_i, 0);
03375 rb_define_method(rb_cInteger, "ceil", int_to_i, 0);
03376 rb_define_method(rb_cInteger, "truncate", int_to_i, 0);
03377 rb_define_method(rb_cInteger, "round", int_round, -1);
03378
03379 rb_cFixnum = rb_define_class("Fixnum", rb_cInteger);
03380
03381 rb_define_method(rb_cFixnum, "to_s", fix_to_s, -1);
03382
03383 rb_define_method(rb_cFixnum, "-@", fix_uminus, 0);
03384 rb_define_method(rb_cFixnum, "+", fix_plus, 1);
03385 rb_define_method(rb_cFixnum, "-", fix_minus, 1);
03386 rb_define_method(rb_cFixnum, "*", fix_mul, 1);
03387 rb_define_method(rb_cFixnum, "/", fix_div, 1);
03388 rb_define_method(rb_cFixnum, "div", fix_idiv, 1);
03389 rb_define_method(rb_cFixnum, "%", fix_mod, 1);
03390 rb_define_method(rb_cFixnum, "modulo", fix_mod, 1);
03391 rb_define_method(rb_cFixnum, "divmod", fix_divmod, 1);
03392 rb_define_method(rb_cFixnum, "fdiv", fix_fdiv, 1);
03393 rb_define_method(rb_cFixnum, "**", fix_pow, 1);
03394
03395 rb_define_method(rb_cFixnum, "abs", fix_abs, 0);
03396 rb_define_method(rb_cFixnum, "magnitude", fix_abs, 0);
03397
03398 rb_define_method(rb_cFixnum, "==", fix_equal, 1);
03399 rb_define_method(rb_cFixnum, "===", fix_equal, 1);
03400 rb_define_method(rb_cFixnum, "<=>", fix_cmp, 1);
03401 rb_define_method(rb_cFixnum, ">", fix_gt, 1);
03402 rb_define_method(rb_cFixnum, ">=", fix_ge, 1);
03403 rb_define_method(rb_cFixnum, "<", fix_lt, 1);
03404 rb_define_method(rb_cFixnum, "<=", fix_le, 1);
03405
03406 rb_define_method(rb_cFixnum, "~", fix_rev, 0);
03407 rb_define_method(rb_cFixnum, "&", fix_and, 1);
03408 rb_define_method(rb_cFixnum, "|", fix_or, 1);
03409 rb_define_method(rb_cFixnum, "^", fix_xor, 1);
03410 rb_define_method(rb_cFixnum, "[]", fix_aref, 1);
03411
03412 rb_define_method(rb_cFixnum, "<<", rb_fix_lshift, 1);
03413 rb_define_method(rb_cFixnum, ">>", rb_fix_rshift, 1);
03414
03415 rb_define_method(rb_cFixnum, "to_f", fix_to_f, 0);
03416 rb_define_method(rb_cFixnum, "size", fix_size, 0);
03417 rb_define_method(rb_cFixnum, "zero?", fix_zero_p, 0);
03418 rb_define_method(rb_cFixnum, "odd?", fix_odd_p, 0);
03419 rb_define_method(rb_cFixnum, "even?", fix_even_p, 0);
03420 rb_define_method(rb_cFixnum, "succ", fix_succ, 0);
03421
03422 rb_cFloat = rb_define_class("Float", rb_cNumeric);
03423
03424 rb_undef_alloc_func(rb_cFloat);
03425 rb_undef_method(CLASS_OF(rb_cFloat), "new");
03426
03427 rb_define_const(rb_cFloat, "ROUNDS", INT2FIX(FLT_ROUNDS));
03428 rb_define_const(rb_cFloat, "RADIX", INT2FIX(FLT_RADIX));
03429 rb_define_const(rb_cFloat, "MANT_DIG", INT2FIX(DBL_MANT_DIG));
03430 rb_define_const(rb_cFloat, "DIG", INT2FIX(DBL_DIG));
03431 rb_define_const(rb_cFloat, "MIN_EXP", INT2FIX(DBL_MIN_EXP));
03432 rb_define_const(rb_cFloat, "MAX_EXP", INT2FIX(DBL_MAX_EXP));
03433 rb_define_const(rb_cFloat, "MIN_10_EXP", INT2FIX(DBL_MIN_10_EXP));
03434 rb_define_const(rb_cFloat, "MAX_10_EXP", INT2FIX(DBL_MAX_10_EXP));
03435 rb_define_const(rb_cFloat, "MIN", DBL2NUM(DBL_MIN));
03436 rb_define_const(rb_cFloat, "MAX", DBL2NUM(DBL_MAX));
03437 rb_define_const(rb_cFloat, "EPSILON", DBL2NUM(DBL_EPSILON));
03438 rb_define_const(rb_cFloat, "INFINITY", DBL2NUM(INFINITY));
03439 rb_define_const(rb_cFloat, "NAN", DBL2NUM(NAN));
03440
03441 rb_define_method(rb_cFloat, "to_s", flo_to_s, 0);
03442 rb_define_method(rb_cFloat, "coerce", flo_coerce, 1);
03443 rb_define_method(rb_cFloat, "-@", flo_uminus, 0);
03444 rb_define_method(rb_cFloat, "+", flo_plus, 1);
03445 rb_define_method(rb_cFloat, "-", flo_minus, 1);
03446 rb_define_method(rb_cFloat, "*", flo_mul, 1);
03447 rb_define_method(rb_cFloat, "/", flo_div, 1);
03448 rb_define_method(rb_cFloat, "quo", flo_quo, 1);
03449 rb_define_method(rb_cFloat, "fdiv", flo_quo, 1);
03450 rb_define_method(rb_cFloat, "%", flo_mod, 1);
03451 rb_define_method(rb_cFloat, "modulo", flo_mod, 1);
03452 rb_define_method(rb_cFloat, "divmod", flo_divmod, 1);
03453 rb_define_method(rb_cFloat, "**", flo_pow, 1);
03454 rb_define_method(rb_cFloat, "==", flo_eq, 1);
03455 rb_define_method(rb_cFloat, "===", flo_eq, 1);
03456 rb_define_method(rb_cFloat, "<=>", flo_cmp, 1);
03457 rb_define_method(rb_cFloat, ">", flo_gt, 1);
03458 rb_define_method(rb_cFloat, ">=", flo_ge, 1);
03459 rb_define_method(rb_cFloat, "<", flo_lt, 1);
03460 rb_define_method(rb_cFloat, "<=", flo_le, 1);
03461 rb_define_method(rb_cFloat, "eql?", flo_eql, 1);
03462 rb_define_method(rb_cFloat, "hash", flo_hash, 0);
03463 rb_define_method(rb_cFloat, "to_f", flo_to_f, 0);
03464 rb_define_method(rb_cFloat, "abs", flo_abs, 0);
03465 rb_define_method(rb_cFloat, "magnitude", flo_abs, 0);
03466 rb_define_method(rb_cFloat, "zero?", flo_zero_p, 0);
03467
03468 rb_define_method(rb_cFloat, "to_i", flo_truncate, 0);
03469 rb_define_method(rb_cFloat, "to_int", flo_truncate, 0);
03470 rb_define_method(rb_cFloat, "floor", flo_floor, 0);
03471 rb_define_method(rb_cFloat, "ceil", flo_ceil, 0);
03472 rb_define_method(rb_cFloat, "round", flo_round, -1);
03473 rb_define_method(rb_cFloat, "truncate", flo_truncate, 0);
03474
03475 rb_define_method(rb_cFloat, "nan?", flo_is_nan_p, 0);
03476 rb_define_method(rb_cFloat, "infinite?", flo_is_infinite_p, 0);
03477 rb_define_method(rb_cFloat, "finite?", flo_is_finite_p, 0);
03478 }
03479