00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include "ruby.h"
00014 #include "env.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 static ID id_coerce, id_to_i, id_eq;
00067
00068 VALUE rb_cNumeric;
00069 VALUE rb_cFloat;
00070 VALUE rb_cInteger;
00071 VALUE rb_cFixnum;
00072
00073 VALUE rb_eZeroDivError;
00074 VALUE rb_eFloatDomainError;
00075
00076 void
00077 rb_num_zerodiv()
00078 {
00079 rb_raise(rb_eZeroDivError, "divided by 0");
00080 }
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099 static VALUE
00100 num_coerce(x, y)
00101 VALUE x, y;
00102 {
00103 if (CLASS_OF(x) == CLASS_OF(y))
00104 return rb_assoc_new(y, x);
00105 return rb_assoc_new(rb_Float(y), rb_Float(x));
00106 }
00107
00108 static VALUE
00109 coerce_body(x)
00110 VALUE *x;
00111 {
00112 return rb_funcall(x[1], id_coerce, 1, x[0]);
00113 }
00114
00115 static VALUE
00116 coerce_rescue(x)
00117 VALUE *x;
00118 {
00119 volatile VALUE v = rb_inspect(x[1]);
00120
00121 rb_raise(rb_eTypeError, "%s can't be coerced into %s",
00122 rb_special_const_p(x[1])?
00123 RSTRING(v)->ptr:
00124 rb_obj_classname(x[1]),
00125 rb_obj_classname(x[0]));
00126 return Qnil;
00127 }
00128
00129 static int
00130 do_coerce(x, y, err)
00131 VALUE *x, *y;
00132 int err;
00133 {
00134 VALUE ary;
00135 VALUE a[2];
00136
00137 a[0] = *x; a[1] = *y;
00138
00139 ary = rb_rescue(coerce_body, (VALUE)a, err?coerce_rescue:0, (VALUE)a);
00140 if (TYPE(ary) != T_ARRAY || RARRAY(ary)->len != 2) {
00141 if (err) {
00142 rb_raise(rb_eTypeError, "coerce must return [x, y]");
00143 }
00144 return Qfalse;
00145 }
00146
00147 *x = RARRAY(ary)->ptr[0];
00148 *y = RARRAY(ary)->ptr[1];
00149 return Qtrue;
00150 }
00151
00152 VALUE
00153 rb_num_coerce_bin(x, y)
00154 VALUE x, y;
00155 {
00156 do_coerce(&x, &y, Qtrue);
00157 return rb_funcall(x, ruby_frame->orig_func, 1, y);
00158 }
00159
00160 VALUE
00161 rb_num_coerce_cmp(x, y)
00162 VALUE x, y;
00163 {
00164 if (do_coerce(&x, &y, Qfalse))
00165 return rb_funcall(x, ruby_frame->orig_func, 1, y);
00166 return Qnil;
00167 }
00168
00169 VALUE
00170 rb_num_coerce_relop(x, y)
00171 VALUE x, y;
00172 {
00173 VALUE c, x0 = x, y0 = y;
00174
00175 if (!do_coerce(&x, &y, Qfalse) ||
00176 NIL_P(c = rb_funcall(x, ruby_frame->orig_func, 1, y))) {
00177 rb_cmperr(x0, y0);
00178 return Qnil;
00179 }
00180 return c;
00181 }
00182
00183
00184
00185
00186
00187
00188 static VALUE
00189 num_sadded(x, name)
00190 VALUE x, name;
00191 {
00192 ruby_frame = ruby_frame->prev;
00193
00194 rb_raise(rb_eTypeError,
00195 "can't define singleton method \"%s\" for %s",
00196 rb_id2name(rb_to_id(name)),
00197 rb_obj_classname(x));
00198 return Qnil;
00199 }
00200
00201
00202 static VALUE
00203 num_init_copy(x, y)
00204 VALUE x, y;
00205 {
00206
00207 rb_raise(rb_eTypeError, "can't copy %s", rb_obj_classname(x));
00208 return Qnil;
00209 }
00210
00211
00212
00213
00214
00215
00216
00217
00218 static VALUE
00219 num_uplus(num)
00220 VALUE num;
00221 {
00222 return num;
00223 }
00224
00225
00226
00227
00228
00229
00230
00231
00232 static VALUE
00233 num_uminus(num)
00234 VALUE num;
00235 {
00236 VALUE zero;
00237
00238 zero = INT2FIX(0);
00239 do_coerce(&zero, &num, Qtrue);
00240
00241 return rb_funcall(zero, '-', 1, num);
00242 }
00243
00244
00245
00246
00247
00248
00249
00250
00251 static VALUE
00252 num_quo(x, y)
00253 VALUE x, y;
00254 {
00255 return rb_funcall(x, '/', 1, y);
00256 }
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268 static VALUE
00269 num_div(x, y)
00270 VALUE x, y;
00271 {
00272 return rb_Integer(rb_funcall(x, '/', 1, y));
00273 }
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317 static VALUE
00318 num_divmod(x, y)
00319 VALUE x, y;
00320 {
00321 return rb_assoc_new(num_div(x, y), rb_funcall(x, '%', 1, y));
00322 }
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332 static VALUE
00333 num_modulo(x, y)
00334 VALUE x, y;
00335 {
00336 return rb_funcall(x, '%', 1, y);
00337 }
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351 static VALUE
00352 num_remainder(x, y)
00353 VALUE x, y;
00354 {
00355 VALUE z = rb_funcall(x, '%', 1, y);
00356
00357 if ((!rb_equal(z, INT2FIX(0))) &&
00358 ((RTEST(rb_funcall(x, '<', 1, INT2FIX(0))) &&
00359 RTEST(rb_funcall(y, '>', 1, INT2FIX(0)))) ||
00360 (RTEST(rb_funcall(x, '>', 1, INT2FIX(0))) &&
00361 RTEST(rb_funcall(y, '<', 1, INT2FIX(0)))))) {
00362 return rb_funcall(z, '-', 1, y);
00363 }
00364 return z;
00365 }
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375 static VALUE
00376 num_int_p(num)
00377 VALUE num;
00378 {
00379 return Qfalse;
00380 }
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393 static VALUE
00394 num_abs(num)
00395 VALUE num;
00396 {
00397 if (RTEST(rb_funcall(num, '<', 1, INT2FIX(0)))) {
00398 return rb_funcall(num, rb_intern("-@"), 0);
00399 }
00400 return num;
00401 }
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411 static VALUE
00412 num_zero_p(num)
00413 VALUE num;
00414 {
00415 if (rb_equal(num, INT2FIX(0))) {
00416 return Qtrue;
00417 }
00418 return Qfalse;
00419 }
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434 static VALUE
00435 num_nonzero_p(num)
00436 VALUE num;
00437 {
00438 if (RTEST(rb_funcall(num, rb_intern("zero?"), 0, 0))) {
00439 return Qnil;
00440 }
00441 return num;
00442 }
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452 static VALUE
00453 num_to_int(num)
00454 VALUE num;
00455 {
00456 return rb_funcall(num, id_to_i, 0, 0);
00457 }
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468 VALUE
00469 rb_float_new(d)
00470 double d;
00471 {
00472 NEWOBJ(flt, struct RFloat);
00473 OBJSETUP(flt, rb_cFloat, T_FLOAT);
00474
00475 flt->value = d;
00476 return (VALUE)flt;
00477 }
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489 static VALUE
00490 flo_to_s(flt)
00491 VALUE flt;
00492 {
00493 char buf[32];
00494 double value = RFLOAT(flt)->value;
00495 char *p, *e;
00496
00497 if (isinf(value))
00498 return rb_str_new2(value < 0 ? "-Infinity" : "Infinity");
00499 else if(isnan(value))
00500 return rb_str_new2("NaN");
00501
00502 sprintf(buf, "%#.15g", value);
00503 if (!(e = strchr(buf, 'e'))) {
00504 e = buf + strlen(buf);
00505 }
00506 if (!ISDIGIT(e[-1])) {
00507 sprintf(buf, "%#.14e", value);
00508 if (!(e = strchr(buf, 'e'))) {
00509 e = buf + strlen(buf);
00510 }
00511 }
00512 p = e;
00513 while (p[-1]=='0' && ISDIGIT(p[-2]))
00514 p--;
00515 memmove(p, e, strlen(e)+1);
00516 return rb_str_new2(buf);
00517 }
00518
00519
00520
00521
00522
00523 static VALUE
00524 flo_coerce(x, y)
00525 VALUE x, y;
00526 {
00527 return rb_assoc_new(rb_Float(y), x);
00528 }
00529
00530
00531
00532
00533
00534
00535
00536
00537 static VALUE
00538 flo_uminus(flt)
00539 VALUE flt;
00540 {
00541 return rb_float_new(-RFLOAT(flt)->value);
00542 }
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552 static VALUE
00553 flo_plus(x, y)
00554 VALUE x, y;
00555 {
00556 switch (TYPE(y)) {
00557 case T_FIXNUM:
00558 return rb_float_new(RFLOAT(x)->value + (double)FIX2LONG(y));
00559 case T_BIGNUM:
00560 return rb_float_new(RFLOAT(x)->value + rb_big2dbl(y));
00561 case T_FLOAT:
00562 return rb_float_new(RFLOAT(x)->value + RFLOAT(y)->value);
00563 default:
00564 return rb_num_coerce_bin(x, y);
00565 }
00566 }
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576 static VALUE
00577 flo_minus(x, y)
00578 VALUE x, y;
00579 {
00580 switch (TYPE(y)) {
00581 case T_FIXNUM:
00582 return rb_float_new(RFLOAT(x)->value - (double)FIX2LONG(y));
00583 case T_BIGNUM:
00584 return rb_float_new(RFLOAT(x)->value - rb_big2dbl(y));
00585 case T_FLOAT:
00586 return rb_float_new(RFLOAT(x)->value - RFLOAT(y)->value);
00587 default:
00588 return rb_num_coerce_bin(x, y);
00589 }
00590 }
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600 static VALUE
00601 flo_mul(x, y)
00602 VALUE x, y;
00603 {
00604 switch (TYPE(y)) {
00605 case T_FIXNUM:
00606 return rb_float_new(RFLOAT(x)->value * (double)FIX2LONG(y));
00607 case T_BIGNUM:
00608 return rb_float_new(RFLOAT(x)->value * rb_big2dbl(y));
00609 case T_FLOAT:
00610 return rb_float_new(RFLOAT(x)->value * RFLOAT(y)->value);
00611 default:
00612 return rb_num_coerce_bin(x, y);
00613 }
00614 }
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624 static VALUE
00625 flo_div(x, y)
00626 VALUE x, y;
00627 {
00628 long f_y;
00629 double d;
00630
00631 switch (TYPE(y)) {
00632 case T_FIXNUM:
00633 f_y = FIX2LONG(y);
00634 return rb_float_new(RFLOAT(x)->value / (double)f_y);
00635 case T_BIGNUM:
00636 d = rb_big2dbl(y);
00637 return rb_float_new(RFLOAT(x)->value / d);
00638 case T_FLOAT:
00639 return rb_float_new(RFLOAT(x)->value / RFLOAT(y)->value);
00640 default:
00641 return rb_num_coerce_bin(x, y);
00642 }
00643 }
00644
00645
00646 static void
00647 flodivmod(x, y, divp, modp)
00648 double x, y;
00649 double *divp, *modp;
00650 {
00651 double div, mod;
00652
00653 #ifdef HAVE_FMOD
00654 mod = fmod(x, y);
00655 #else
00656 {
00657 double z;
00658
00659 modf(x/y, &z);
00660 mod = x - z * y;
00661 }
00662 #endif
00663 div = (x - mod) / y;
00664 if (y*mod < 0) {
00665 mod += y;
00666 div -= 1.0;
00667 }
00668 if (modp) *modp = mod;
00669 if (divp) *divp = div;
00670 }
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684 static VALUE
00685 flo_mod(x, y)
00686 VALUE x, y;
00687 {
00688 double fy, mod;
00689
00690 switch (TYPE(y)) {
00691 case T_FIXNUM:
00692 fy = (double)FIX2LONG(y);
00693 break;
00694 case T_BIGNUM:
00695 fy = rb_big2dbl(y);
00696 break;
00697 case T_FLOAT:
00698 fy = RFLOAT(y)->value;
00699 break;
00700 default:
00701 return rb_num_coerce_bin(x, y);
00702 }
00703 flodivmod(RFLOAT(x)->value, fy, 0, &mod);
00704 return rb_float_new(mod);
00705 }
00706
00707
00708
00709
00710
00711
00712
00713
00714 static VALUE
00715 flo_divmod(x, y)
00716 VALUE x, y;
00717 {
00718 double fy, div, mod;
00719 volatile VALUE a, b;
00720
00721 switch (TYPE(y)) {
00722 case T_FIXNUM:
00723 fy = (double)FIX2LONG(y);
00724 break;
00725 case T_BIGNUM:
00726 fy = rb_big2dbl(y);
00727 break;
00728 case T_FLOAT:
00729 fy = RFLOAT(y)->value;
00730 break;
00731 default:
00732 return rb_num_coerce_bin(x, y);
00733 }
00734 flodivmod(RFLOAT(x)->value, fy, &div, &mod);
00735 a = rb_float_new(div);
00736 b = rb_float_new(mod);
00737 return rb_assoc_new(a, b);
00738 }
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748 static VALUE
00749 flo_pow(x, y)
00750 VALUE x, y;
00751 {
00752 switch (TYPE(y)) {
00753 case T_FIXNUM:
00754 return rb_float_new(pow(RFLOAT(x)->value, (double)FIX2LONG(y)));
00755 case T_BIGNUM:
00756 return rb_float_new(pow(RFLOAT(x)->value, rb_big2dbl(y)));
00757 case T_FLOAT:
00758 return rb_float_new(pow(RFLOAT(x)->value, RFLOAT(y)->value));
00759 default:
00760 return rb_num_coerce_bin(x, y);
00761 }
00762 }
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776 static VALUE
00777 num_eql(x, y)
00778 VALUE x, y;
00779 {
00780 if (TYPE(x) != TYPE(y)) return Qfalse;
00781
00782 return rb_equal(x, y);
00783 }
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793 static VALUE
00794 num_cmp(x, y)
00795 VALUE x, y;
00796 {
00797 if (x == y) return INT2FIX(0);
00798 return Qnil;
00799 }
00800
00801 static VALUE
00802 num_equal(x, y)
00803 VALUE x, y;
00804 {
00805 if (x == y) return Qtrue;
00806 return rb_funcall(y, id_eq, 1, x);
00807 }
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821 static VALUE
00822 flo_eq(x, y)
00823 VALUE x, y;
00824 {
00825 volatile double a, b;
00826
00827 switch (TYPE(y)) {
00828 case T_FIXNUM:
00829 b = FIX2LONG(y);
00830 break;
00831 case T_BIGNUM:
00832 b = rb_big2dbl(y);
00833 break;
00834 case T_FLOAT:
00835 b = RFLOAT(y)->value;
00836 if (isnan(b)) return Qfalse;
00837 break;
00838 default:
00839 return num_equal(x, y);
00840 }
00841 a = RFLOAT(x)->value;
00842 if (isnan(a)) return Qfalse;
00843 return (a == b)?Qtrue:Qfalse;
00844 }
00845
00846
00847
00848
00849
00850
00851
00852
00853 static VALUE
00854 flo_hash(num)
00855 VALUE num;
00856 {
00857 double d;
00858 char *c;
00859 int i, hash;
00860
00861 d = RFLOAT(num)->value;
00862 if (d == 0) d = fabs(d);
00863 c = (char*)&d;
00864 for (hash=0, i=0; i<sizeof(double);i++) {
00865 hash += c[i] * 971;
00866 }
00867 if (hash < 0) hash = -hash;
00868 return INT2FIX(hash);
00869 }
00870
00871 VALUE
00872 rb_dbl_cmp(a, b)
00873 double a, b;
00874 {
00875 if (isnan(a) || isnan(b)) return Qnil;
00876 if (a == b) return INT2FIX(0);
00877 if (a > b) return INT2FIX(1);
00878 if (a < b) return INT2FIX(-1);
00879 return Qnil;
00880 }
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891 static VALUE
00892 flo_cmp(x, y)
00893 VALUE x, y;
00894 {
00895 double a, b;
00896
00897 a = RFLOAT(x)->value;
00898 switch (TYPE(y)) {
00899 case T_FIXNUM:
00900 b = (double)FIX2LONG(y);
00901 break;
00902
00903 case T_BIGNUM:
00904 b = rb_big2dbl(y);
00905 break;
00906
00907 case T_FLOAT:
00908 b = RFLOAT(y)->value;
00909 break;
00910
00911 default:
00912 return rb_num_coerce_cmp(x, y);
00913 }
00914 return rb_dbl_cmp(a, b);
00915 }
00916
00917
00918
00919
00920
00921
00922
00923
00924 static VALUE
00925 flo_gt(x, y)
00926 VALUE x, y;
00927 {
00928 double a, b;
00929
00930 a = RFLOAT(x)->value;
00931 switch (TYPE(y)) {
00932 case T_FIXNUM:
00933 b = (double)FIX2LONG(y);
00934 break;
00935
00936 case T_BIGNUM:
00937 b = rb_big2dbl(y);
00938 break;
00939
00940 case T_FLOAT:
00941 b = RFLOAT(y)->value;
00942 if (isnan(b)) return Qfalse;
00943 break;
00944
00945 default:
00946 return rb_num_coerce_relop(x, y);
00947 }
00948 if (isnan(a)) return Qfalse;
00949 return (a > b)?Qtrue:Qfalse;
00950 }
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960 static VALUE
00961 flo_ge(x, y)
00962 VALUE x, y;
00963 {
00964 double a, b;
00965
00966 a = RFLOAT(x)->value;
00967 switch (TYPE(y)) {
00968 case T_FIXNUM:
00969 b = (double)FIX2LONG(y);
00970 break;
00971
00972 case T_BIGNUM:
00973 b = rb_big2dbl(y);
00974 break;
00975
00976 case T_FLOAT:
00977 b = RFLOAT(y)->value;
00978 if (isnan(b)) return Qfalse;
00979 break;
00980
00981 default:
00982 return rb_num_coerce_relop(x, y);
00983 }
00984 if (isnan(a)) return Qfalse;
00985 return (a >= b)?Qtrue:Qfalse;
00986 }
00987
00988
00989
00990
00991
00992
00993
00994
00995 static VALUE
00996 flo_lt(x, y)
00997 VALUE x, y;
00998 {
00999 double a, b;
01000
01001 a = RFLOAT(x)->value;
01002 switch (TYPE(y)) {
01003 case T_FIXNUM:
01004 b = (double)FIX2LONG(y);
01005 break;
01006
01007 case T_BIGNUM:
01008 b = rb_big2dbl(y);
01009 break;
01010
01011 case T_FLOAT:
01012 b = RFLOAT(y)->value;
01013 if (isnan(b)) return Qfalse;
01014 break;
01015
01016 default:
01017 return rb_num_coerce_relop(x, y);
01018 }
01019 if (isnan(a)) return Qfalse;
01020 return (a < b)?Qtrue:Qfalse;
01021 }
01022
01023
01024
01025
01026
01027
01028
01029
01030
01031 static VALUE
01032 flo_le(x, y)
01033 VALUE x, y;
01034 {
01035 double a, b;
01036
01037 a = RFLOAT(x)->value;
01038 switch (TYPE(y)) {
01039 case T_FIXNUM:
01040 b = (double)FIX2LONG(y);
01041 break;
01042
01043 case T_BIGNUM:
01044 b = rb_big2dbl(y);
01045 break;
01046
01047 case T_FLOAT:
01048 b = RFLOAT(y)->value;
01049 if (isnan(b)) return Qfalse;
01050 break;
01051
01052 default:
01053 return rb_num_coerce_relop(x, y);
01054 }
01055 if (isnan(a)) return Qfalse;
01056 return (a <= b)?Qtrue:Qfalse;
01057 }
01058
01059
01060
01061
01062
01063
01064
01065
01066
01067
01068
01069
01070 static VALUE
01071 flo_eql(x, y)
01072 VALUE x, y;
01073 {
01074 if (TYPE(y) == T_FLOAT) {
01075 double a = RFLOAT(x)->value;
01076 double b = RFLOAT(y)->value;
01077
01078 if (isnan(a) || isnan(b)) return Qfalse;
01079 if (a == b) return Qtrue;
01080 }
01081 return Qfalse;
01082 }
01083
01084
01085
01086
01087
01088
01089
01090
01091 static VALUE
01092 flo_to_f(num)
01093 VALUE num;
01094 {
01095 return num;
01096 }
01097
01098
01099
01100
01101
01102
01103
01104
01105
01106
01107
01108
01109 static VALUE
01110 flo_abs(flt)
01111 VALUE flt;
01112 {
01113 double val = fabs(RFLOAT(flt)->value);
01114 return rb_float_new(val);
01115 }
01116
01117
01118
01119
01120
01121
01122
01123
01124
01125 static VALUE
01126 flo_zero_p(num)
01127 VALUE num;
01128 {
01129 if (RFLOAT(num)->value == 0.0) {
01130 return Qtrue;
01131 }
01132 return Qfalse;
01133 }
01134
01135
01136
01137
01138
01139
01140
01141
01142
01143
01144
01145
01146
01147
01148 static VALUE
01149 flo_is_nan_p(num)
01150 VALUE num;
01151 {
01152 double value = RFLOAT(num)->value;
01153
01154 return isnan(value) ? Qtrue : Qfalse;
01155 }
01156
01157
01158
01159
01160
01161
01162
01163
01164
01165
01166
01167
01168
01169 static VALUE
01170 flo_is_infinite_p(num)
01171 VALUE num;
01172 {
01173 double value = RFLOAT(num)->value;
01174
01175 if (isinf(value)) {
01176 return INT2FIX( value < 0 ? -1 : 1 );
01177 }
01178
01179 return Qnil;
01180 }
01181
01182
01183
01184
01185
01186
01187
01188
01189
01190
01191
01192 static VALUE
01193 flo_is_finite_p(num)
01194 VALUE num;
01195 {
01196 double value = RFLOAT(num)->value;
01197
01198 #if HAVE_FINITE
01199 if (!finite(value))
01200 return Qfalse;
01201 #else
01202 if (isinf(value) || isnan(value))
01203 return Qfalse;
01204 #endif
01205
01206 return Qtrue;
01207 }
01208
01209
01210
01211
01212
01213
01214
01215
01216
01217
01218
01219
01220
01221 static VALUE
01222 flo_floor(num)
01223 VALUE num;
01224 {
01225 double f = floor(RFLOAT(num)->value);
01226 long val;
01227
01228 if (!FIXABLE(f)) {
01229 return rb_dbl2big(f);
01230 }
01231 val = f;
01232 return LONG2FIX(val);
01233 }
01234
01235
01236
01237
01238
01239
01240
01241
01242
01243
01244
01245
01246
01247
01248 static VALUE
01249 flo_ceil(num)
01250 VALUE num;
01251 {
01252 double f = ceil(RFLOAT(num)->value);
01253 long val;
01254
01255 if (!FIXABLE(f)) {
01256 return rb_dbl2big(f);
01257 }
01258 val = f;
01259 return LONG2FIX(val);
01260 }
01261
01262
01263
01264
01265
01266
01267
01268
01269
01270
01271
01272
01273
01274
01275
01276
01277
01278
01279 static VALUE
01280 flo_round(num)
01281 VALUE num;
01282 {
01283 double f = RFLOAT(num)->value;
01284 long val;
01285
01286 if (f > 0.0) f = floor(f+0.5);
01287 if (f < 0.0) f = ceil(f-0.5);
01288
01289 if (!FIXABLE(f)) {
01290 return rb_dbl2big(f);
01291 }
01292 val = f;
01293 return LONG2FIX(val);
01294 }
01295
01296
01297
01298
01299
01300
01301
01302
01303
01304
01305 static VALUE
01306 flo_truncate(num)
01307 VALUE num;
01308 {
01309 double f = RFLOAT(num)->value;
01310 long val;
01311
01312 if (f > 0.0) f = floor(f);
01313 if (f < 0.0) f = ceil(f);
01314
01315 if (!FIXABLE(f)) {
01316 return rb_dbl2big(f);
01317 }
01318 val = f;
01319 return LONG2FIX(val);
01320 }
01321
01322
01323
01324
01325
01326
01327
01328
01329
01330
01331
01332
01333
01334
01335 static VALUE
01336 num_floor(num)
01337 VALUE num;
01338 {
01339 return flo_floor(rb_Float(num));
01340 }
01341
01342
01343
01344
01345
01346
01347
01348
01349
01350
01351
01352
01353
01354
01355
01356
01357
01358 static VALUE
01359 num_ceil(num)
01360 VALUE num;
01361 {
01362 return flo_ceil(rb_Float(num));
01363 }
01364
01365
01366
01367
01368
01369
01370
01371
01372
01373
01374 static VALUE
01375 num_round(num)
01376 VALUE num;
01377 {
01378 return flo_round(rb_Float(num));
01379 }
01380
01381
01382
01383
01384
01385
01386
01387
01388
01389
01390 static VALUE
01391 num_truncate(num)
01392 VALUE num;
01393 {
01394 return flo_truncate(rb_Float(num));
01395 }
01396
01397
01398
01399
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 static VALUE
01426 num_step(argc, argv, from)
01427 int argc;
01428 VALUE *argv;
01429 VALUE from;
01430 {
01431 VALUE to, step;
01432
01433 if (argc == 1) {
01434 to = argv[0];
01435 step = INT2FIX(1);
01436 }
01437 else {
01438 if (argc == 2) {
01439 to = argv[0];
01440 step = argv[1];
01441 }
01442 else {
01443 rb_raise(rb_eArgError, "wrong number of arguments");
01444 }
01445 if (rb_equal(step, INT2FIX(0))) {
01446 rb_raise(rb_eArgError, "step can't be 0");
01447 }
01448 }
01449
01450 if (FIXNUM_P(from) && FIXNUM_P(to) && FIXNUM_P(step)) {
01451 long i, end, diff;
01452
01453 i = FIX2LONG(from);
01454 end = FIX2LONG(to);
01455 diff = FIX2LONG(step);
01456
01457 if (diff > 0) {
01458 while (i <= end) {
01459 rb_yield(LONG2FIX(i));
01460 i += diff;
01461 }
01462 }
01463 else {
01464 while (i >= end) {
01465 rb_yield(LONG2FIX(i));
01466 i += diff;
01467 }
01468 }
01469 }
01470 else if (TYPE(from) == T_FLOAT || TYPE(to) == T_FLOAT || TYPE(step) == T_FLOAT) {
01471 const double epsilon = DBL_EPSILON;
01472 double beg = NUM2DBL(from);
01473 double end = NUM2DBL(to);
01474 double unit = NUM2DBL(step);
01475 double n = (end - beg)/unit;
01476 double err = (fabs(beg) + fabs(end) + fabs(end-beg)) / fabs(unit) * epsilon;
01477 long i;
01478
01479 if (err>0.5) err=0.5;
01480 n = floor(n + err) + 1;
01481 for (i=0; i<n; i++) {
01482 rb_yield(rb_float_new(i*unit+beg));
01483 }
01484 }
01485 else {
01486 VALUE i = from;
01487 ID cmp;
01488
01489 if (RTEST(rb_funcall(step, '>', 1, INT2FIX(0)))) {
01490 cmp = '>';
01491 }
01492 else {
01493 cmp = '<';
01494 }
01495 for (;;) {
01496 if (RTEST(rb_funcall(i, cmp, 1, to))) break;
01497 rb_yield(i);
01498 i = rb_funcall(i, '+', 1, step);
01499 }
01500 }
01501 return from;
01502 }
01503
01504 long
01505 rb_num2long(val)
01506 VALUE val;
01507 {
01508 if (NIL_P(val)) {
01509 rb_raise(rb_eTypeError, "no implicit conversion from nil to integer");
01510 }
01511
01512 if (FIXNUM_P(val)) return FIX2LONG(val);
01513
01514 switch (TYPE(val)) {
01515 case T_FLOAT:
01516 if (RFLOAT(val)->value <= (double)LONG_MAX
01517 && RFLOAT(val)->value >= (double)LONG_MIN) {
01518 return (long)(RFLOAT(val)->value);
01519 }
01520 else {
01521 char buf[24];
01522 char *s;
01523
01524 sprintf(buf, "%-.10g", RFLOAT(val)->value);
01525 if (s = strchr(buf, ' ')) *s = '\0';
01526 rb_raise(rb_eRangeError, "float %s out of range of integer", buf);
01527 }
01528
01529 case T_BIGNUM:
01530 return rb_big2long(val);
01531
01532 default:
01533 val = rb_to_int(val);
01534 return NUM2LONG(val);
01535 }
01536 }
01537
01538 unsigned long
01539 rb_num2ulong(val)
01540 VALUE val;
01541 {
01542 if (TYPE(val) == T_BIGNUM) {
01543 return rb_big2ulong(val);
01544 }
01545 return (unsigned long)rb_num2long(val);
01546 }
01547
01548 #if SIZEOF_INT < SIZEOF_LONG
01549 static void
01550 check_int(num)
01551 long num;
01552 {
01553 const char *s;
01554
01555 if (num < INT_MIN) {
01556 s = "small";
01557 }
01558 else if (num > INT_MAX) {
01559 s = "big";
01560 }
01561 else {
01562 return;
01563 }
01564 rb_raise(rb_eRangeError, "integer %ld too %s to convert to `int'", num, s);
01565 }
01566
01567 static void
01568 check_uint(num)
01569 unsigned long num;
01570 {
01571 if (num > UINT_MAX) {
01572 rb_raise(rb_eRangeError, "integer %lu too big to convert to `unsigned int'", num);
01573 }
01574 }
01575
01576 long
01577 rb_num2int(val)
01578 VALUE val;
01579 {
01580 long num = rb_num2long(val);
01581
01582 check_int(num);
01583 return num;
01584 }
01585
01586 long
01587 rb_fix2int(val)
01588 VALUE val;
01589 {
01590 long num = FIXNUM_P(val)?FIX2LONG(val):rb_num2long(val);
01591
01592 check_int(num);
01593 return num;
01594 }
01595
01596 unsigned long
01597 rb_num2uint(val)
01598 VALUE val;
01599 {
01600 unsigned long num = rb_num2ulong(val);
01601
01602 if (RTEST(rb_funcall(INT2FIX(0), '<', 1, val))) {
01603 check_uint(num);
01604 }
01605 return num;
01606 }
01607
01608 unsigned long
01609 rb_fix2uint(val)
01610 VALUE val;
01611 {
01612 unsigned long num;
01613
01614 if (!FIXNUM_P(val)) {
01615 return rb_num2uint(val);
01616 }
01617 num = FIX2ULONG(val);
01618 if (FIX2LONG(val) > 0) {
01619 check_uint(num);
01620 }
01621 return num;
01622 }
01623 #else
01624 long
01625 rb_num2int(val)
01626 VALUE val;
01627 {
01628 return rb_num2long(val);
01629 }
01630
01631 long
01632 rb_fix2int(val)
01633 VALUE val;
01634 {
01635 return FIX2INT(val);
01636 }
01637 #endif
01638
01639 VALUE
01640 rb_num2fix(val)
01641 VALUE val;
01642 {
01643 long v;
01644
01645 if (FIXNUM_P(val)) return val;
01646
01647 v = rb_num2long(val);
01648 if (!FIXABLE(v))
01649 rb_raise(rb_eRangeError, "integer %ld out of range of fixnum", v);
01650 return LONG2FIX(v);
01651 }
01652
01653 #if HAVE_LONG_LONG
01654
01655 LONG_LONG
01656 rb_num2ll(val)
01657 VALUE val;
01658 {
01659 if (NIL_P(val)) {
01660 rb_raise(rb_eTypeError, "no implicit conversion from nil");
01661 }
01662
01663 if (FIXNUM_P(val)) return (LONG_LONG)FIX2LONG(val);
01664
01665 switch (TYPE(val)) {
01666 case T_FLOAT:
01667 if (RFLOAT(val)->value <= (double)LLONG_MAX
01668 && RFLOAT(val)->value >= (double)LLONG_MIN) {
01669 return (LONG_LONG)(RFLOAT(val)->value);
01670 }
01671 else {
01672 char buf[24];
01673 char *s;
01674
01675 sprintf(buf, "%-.10g", RFLOAT(val)->value);
01676 if (s = strchr(buf, ' ')) *s = '\0';
01677 rb_raise(rb_eRangeError, "float %s out of range of long long", buf);
01678 }
01679
01680 case T_BIGNUM:
01681 return rb_big2ll(val);
01682
01683 case T_STRING:
01684 rb_raise(rb_eTypeError, "no implicit conversion from string");
01685 return Qnil;
01686
01687 case T_TRUE:
01688 case T_FALSE:
01689 rb_raise(rb_eTypeError, "no implicit conversion from boolean");
01690 return Qnil;
01691
01692 default:
01693 val = rb_to_int(val);
01694 return NUM2LL(val);
01695 }
01696 }
01697
01698 unsigned LONG_LONG
01699 rb_num2ull(val)
01700 VALUE val;
01701 {
01702 if (TYPE(val) == T_BIGNUM) {
01703 return rb_big2ull(val);
01704 }
01705 return (unsigned LONG_LONG)rb_num2ll(val);
01706 }
01707
01708 #endif
01709
01710
01711
01712
01713
01714
01715
01716
01717
01718
01719
01720
01721
01722
01723
01724
01725
01726
01727
01728
01729
01730
01731
01732
01733 static VALUE
01734 int_to_i(num)
01735 VALUE num;
01736 {
01737 return num;
01738 }
01739
01740
01741
01742
01743
01744
01745
01746
01747 static VALUE
01748 int_int_p(num)
01749 VALUE num;
01750 {
01751 return Qtrue;
01752 }
01753
01754
01755
01756
01757
01758
01759
01760
01761
01762
01763
01764
01765 static VALUE
01766 int_succ(num)
01767 VALUE num;
01768 {
01769 if (FIXNUM_P(num)) {
01770 long i = FIX2LONG(num) + 1;
01771 return LONG2NUM(i);
01772 }
01773 return rb_funcall(num,