1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@520 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
matz 1999-08-13 05:45:20 +00:00
parent fcd020c830
commit 65a5162550
156 changed files with 21888 additions and 18301 deletions

122
numeric.c
View file

@ -6,13 +6,16 @@
$Date$
created at: Fri Aug 13 18:33:09 JST 1993
Copyright (C) 1993-1998 Yukihiro Matsumoto
Copyright (C) 1993-1999 Yukihiro Matsumoto
************************************************/
#include "ruby.h"
#include <math.h>
#include <stdio.h>
#ifdef __FreeBSD__
#include <floatingpoint.h>
#endif
static ID coerce;
static ID to_i;
@ -22,7 +25,8 @@ VALUE rb_cFloat;
VALUE rb_cInteger;
VALUE rb_cFixnum;
VALUE rb_eZeroDiv;
VALUE rb_eZeroDivError;
VALUE rb_eFloatDomainError;
ID rb_frame_last_func();
VALUE rb_float_new();
@ -31,7 +35,7 @@ double rb_big2dbl();
void
rb_num_zerodiv()
{
rb_raise(rb_eZeroDiv, "divided by 0");
rb_raise(rb_eZeroDivError, "divided by 0");
}
static VALUE
@ -163,7 +167,7 @@ num_nonzero_p(num)
VALUE num;
{
if (RTEST(rb_funcall(num, rb_intern("zero?"), 0, 0))) {
return Qfalse;
return Qnil;
}
return num;
}
@ -183,10 +187,19 @@ static VALUE
flo_to_s(flt)
VALUE flt;
{
char buf[32];
char buf[24];
char *s;
double value = RFLOAT(flt)->value;
sprintf(buf, "%g", RFLOAT(flt)->value);
if (strchr(buf, '.') == 0) {
if (isinf(value))
return rb_str_new2(value < 0 ? "-Infinity" : "Infinity");
else if(isnan(value))
return rb_str_new2("NaN");
else
sprintf(buf, "%-.10g", value);
if (s = strchr(buf, ' ')) *s = '\0';
s = buf; if (s[0] == '-') s++;
if (strchr(s, '.') == 0) {
int len = strlen(buf);
char *ind = strchr(buf, 'e');
@ -274,14 +287,11 @@ flo_div(x, y)
switch (TYPE(y)) {
case T_FIXNUM:
f_y = FIX2LONG(y);
if (f_y == 0) rb_num_zerodiv();
return rb_float_new(RFLOAT(x)->value / (double)f_y);
case T_BIGNUM:
d = rb_big2dbl(y);
if (d == 0.0) rb_num_zerodiv();
return rb_float_new(RFLOAT(x)->value / d);
case T_FLOAT:
if (RFLOAT(y)->value == 0.0) rb_num_zerodiv();
return rb_float_new(RFLOAT(x)->value / RFLOAT(y)->value);
default:
return rb_num_coerce_bin(x, y);
@ -433,7 +443,8 @@ flo_cmp(x, y)
}
if (a == b) return INT2FIX(0);
if (a > b) return INT2FIX(1);
return INT2FIX(-1);
if (a < b) return INT2FIX(-1);
rb_raise(rb_eFloatDomainError, "comparing NaN");
}
static VALUE
@ -666,8 +677,12 @@ rb_num2long(val)
return (long)(RFLOAT(val)->value);
}
else {
rb_raise(rb_eTypeError, "float %g out of rang of integer",
RFLOAT(val)->value);
char buf[24];
char *s;
sprintf(buf, "%-.10g", RFLOAT(val)->value);
if (s = strchr(buf, ' ')) *s = '\0';
rb_raise(rb_eTypeError, "float %s out of rang of integer", buf);
}
case T_BIGNUM:
@ -677,6 +692,11 @@ rb_num2long(val)
rb_raise(rb_eTypeError, "no implicit conversion from string");
return Qnil; /* not reached */
case T_TRUE:
case T_FALSE:
rb_raise(rb_eTypeError, "no implicit conversion from boolean");
return Qnil; /* not reached */
default:
val = rb_rescue(to_integer, val, fail_to_integer, val);
if (!rb_obj_is_kind_of(val, rb_cInteger)) {
@ -704,7 +724,7 @@ rb_num2int(val)
long num = rb_num2long(val);
if (num < INT_MIN || INT_MAX < num) {
rb_raise(rb_eArgError, "integer %d too big to convert to `int'.", num);
rb_raise(rb_eArgError, "integer %d too big to convert to `int'", num);
}
return (int)num;
}
@ -716,7 +736,7 @@ rb_fix2int(val)
long num = FIXNUM_P(val)?FIX2LONG(val):rb_num2long(val);
if (num < INT_MIN || INT_MAX < num) {
rb_raise(rb_eArgError, "integer %d too big to convert to `int'.", num);
rb_raise(rb_eArgError, "integer %d too big to convert to `int'", num);
}
return (int)num;
}
@ -777,6 +797,45 @@ int_chr(num)
return rb_str_new(&c, 1);
}
static VALUE
rb_fix_induced_from(klass, x)
VALUE klass, x;
{
return rb_num2fix(x);
}
static VALUE
rb_int_induced_from(klass, x)
VALUE klass, x;
{
switch (TYPE(x)) {
case T_FIXNUM:
case T_BIGNUM:
return x;
case T_FLOAT:
return rb_funcall(x, rb_intern("to_i"), 0);
default:
rb_raise(rb_eTypeError, "failed to convert %s into Integer",
rb_class2name(CLASS_OF(x)));
}
}
static VALUE
rb_flo_induced_from(klass, x)
VALUE klass, x;
{
switch (TYPE(x)) {
case T_FIXNUM:
case T_BIGNUM:
return rb_funcall(x, rb_intern("to_f"), 0);
case T_FLOAT:
return x;
default:
rb_raise(rb_eTypeError, "failed to convert %s into Float",
rb_class2name(CLASS_OF(x)));
}
}
static VALUE
fix_uminus(num)
VALUE num;
@ -797,7 +856,7 @@ rb_fix2str(x, base)
else if (base == 8) fmt[2] = 'o';
else rb_fatal("fixnum cannot treat base %d", base);
sprintf(buf, fmt, FIX2LONG(x));
snprintf(buf, 22, fmt, FIX2LONG(x));
return rb_str_new2(buf);
}
@ -892,7 +951,7 @@ fix_div(x, y)
i = FIX2LONG(y);
if (i == 0) rb_num_zerodiv();
i = FIX2LONG(x)/i;
return INT2FIX(i);
return INT2NUM(i); /* FIXNUM_MIN / -1 > FIXNUM_MAX */
}
return rb_num_coerce_bin(x, y);
}
@ -940,15 +999,13 @@ fix_pow(x, y)
b = FIX2LONG(y);
if (b == 0) return INT2FIX(1);
if (b == 1) return x;
a = FIX2LONG(x);
if (b > 0) {
return rb_big_pow(rb_int2big(a), y);
}
return rb_float_new(pow((double)a, (double)b));
}
else if (NIL_P(y)) {
return INT2FIX(1);
}
return rb_num_coerce_bin(x, y);
}
@ -1044,7 +1101,7 @@ static VALUE
fix_rev(num)
VALUE num;
{
unsigned long val = FIX2ULONG(num);
long val = FIX2LONG(num);
val = ~val;
return rb_int2inum(val);
@ -1309,20 +1366,23 @@ fix_step(from, to, step)
if (!FIXNUM_P(to) || !FIXNUM_P(step))
return int_step(from, to, step);
i = FIX2LONG(from);
end = FIX2LONG(to);
diff = FIX2LONG(step);
if (diff == 0) {
rb_raise(rb_eArgError, "step cannot be 0");
}
else if (diff > 0) {
for (i=FIX2LONG(from); i <= end; i+=diff) {
if (diff > 0) {
while (i <= end) {
rb_yield(INT2FIX(i));
i += diff;
}
}
else {
for (i=FIX2LONG(from); i >= end; i+=diff) {
while (i >= end) {
rb_yield(INT2FIX(i));
i += diff;
}
}
return from;
@ -1354,10 +1414,15 @@ fix_zero_p(num)
void
Init_Numeric()
{
#ifdef __FreeBSD__
/* allow divide by zero -- Inf */
fpsetmask(fpgetmask() & ~(FP_X_DZ|FP_X_INV|FP_X_OFL));
#endif
coerce = rb_intern("coerce");
to_i = rb_intern("to_i");
rb_eZeroDiv = rb_define_class("ZeroDivisionError", rb_eStandardError);
rb_eZeroDivError = rb_define_class("ZeroDivisionError", rb_eStandardError);
rb_eFloatDomainError = rb_define_class("FloatDomainError", rb_eStandardError);
rb_cNumeric = rb_define_class("Numeric", rb_cObject);
rb_include_module(rb_cNumeric, rb_mComparable);
@ -1380,11 +1445,15 @@ Init_Numeric()
rb_define_method(rb_cInteger, "downto", int_downto, 1);
rb_define_method(rb_cInteger, "step", int_step, 2);
rb_define_method(rb_cInteger, "times", int_dotimes, 0);
rb_include_module(rb_cInteger, rb_mPrecision);
rb_define_method(rb_cInteger, "succ", int_succ, 0);
rb_define_method(rb_cInteger, "next", int_succ, 0);
rb_define_method(rb_cInteger, "chr", int_chr, 0);
rb_cFixnum = rb_define_class("Fixnum", rb_cInteger);
rb_include_module(rb_cFixnum, rb_mPrecision);
rb_define_singleton_method(rb_cFixnum, "induced_from", rb_fix_induced_from, 1);
rb_define_singleton_method(rb_cInteger, "induced_from", rb_int_induced_from, 1);
rb_undef_method(CLASS_OF(rb_cFixnum), "new");
@ -1437,6 +1506,9 @@ Init_Numeric()
rb_undef_method(CLASS_OF(rb_cFloat), "new");
rb_define_singleton_method(rb_cFloat, "induced_from", rb_flo_induced_from, 1);
rb_include_module(rb_cFloat, rb_mPrecision);
rb_define_method(rb_cFloat, "to_s", flo_to_s, 0);
rb_define_method(rb_cFloat, "coerce", flo_coerce, 1);
rb_define_method(rb_cFloat, "-@", flo_uminus, 0);