From 9466848db3107535a6887469ad6c89adc1f911b3 Mon Sep 17 00:00:00 2001 From: matz Date: Mon, 1 May 2006 03:46:47 +0000 Subject: * numeric.c (num_div): use floor rather than rb_Integer(). [ruby-dev:28589] * numeric.c (flo_divmod): the first element of Float#divmod should be an integer. [ruby-dev:28589] * test/ruby/test_float.rb: add tests for divmod, div, modulo and remainder. * util.c (ruby_strtod): fixed wrong conversion. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8@10123 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 12 +++++++ numeric.c | 28 +++++++++++------ test/ruby/test_float.rb | 28 +++++++++++++++++ util.c | 84 ++++++++++++++----------------------------------- 4 files changed, 81 insertions(+), 71 deletions(-) diff --git a/ChangeLog b/ChangeLog index 8f11859f3c..95962c77c5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +Mon May 1 12:23:19 2006 + + * numeric.c (num_div): use floor rather than rb_Integer(). + [ruby-dev:28589] + + * numeric.c (flo_divmod): the first element of Float#divmod should + be an integer. [ruby-dev:28589] + + * test/ruby/test_float.rb: add tests for divmod, div, modulo and remainder. + Sat Apr 29 22:42:08 2006 GOTOU Yuuzou * ext/openssl/ossl_asn1.c (ossl_asn1_decode0): should initialize @@ -8,6 +18,8 @@ Fri Apr 28 10:53:16 2006 Yukihiro Matsumoto * util.c (ruby_strtod): should not cut off 18 digits for no reason. [ruby-core:07796] + * util.c (ruby_strtod): fixed wrong conversion. + Thu Apr 27 01:38:10 2006 Yukihiro Matsumoto * array.c (rb_ary_fill): internalize local variable "beg" to diff --git a/numeric.c b/numeric.c index 4c8bacdaf6..a937868ce4 100644 --- a/numeric.c +++ b/numeric.c @@ -256,6 +256,8 @@ num_quo(x, y) } +static VALUE num_floor(VALUE num); + /* * call-seq: * num.div(numeric) => integer @@ -269,7 +271,7 @@ static VALUE num_div(x, y) VALUE x, y; { - return rb_Integer(rb_funcall(x, '/', 1, y)); + return num_floor(rb_funcall(x, '/', 1, y)); } @@ -297,21 +299,21 @@ num_div(x, y) * ------+-----+---------------+---------+-------------+--------------- * -13 | -4 | 3, -1 | 3 | -1 | -1 * ------+-----+---------------+---------+-------------+--------------- - * 11.5 | 4 | 2.0, 3.5 | 2.875 | 3.5 | 3.5 + * 11.5 | 4 | 2, 3.5 | 2.875 | 3.5 | 3.5 * ------+-----+---------------+---------+-------------+--------------- - * 11.5 | -4 | -3.0, -0.5 | -2.875 | -0.5 | 3.5 + * 11.5 | -4 | -3, -0.5 | -2.875 | -0.5 | 3.5 * ------+-----+---------------+---------+-------------+--------------- - * -11.5 | 4 | -3.0 0.5 | -2.875 | 0.5 | -3.5 + * -11.5 | 4 | -3, 0.5 | -2.875 | 0.5 | -3.5 * ------+-----+---------------+---------+-------------+--------------- - * -11.5 | -4 | 2.0 -3.5 | 2.875 | -3.5 | -3.5 + * -11.5 | -4 | 2 -3.5 | 2.875 | -3.5 | -3.5 * * * Examples * 11.divmod(3) #=> [3, 2] * 11.divmod(-3) #=> [-4, -1] - * 11.divmod(3.5) #=> [3.0, 0.5] - * (-11).divmod(3.5) #=> [-4.0, 3.0] - * (11.5).divmod(3.5) #=> [3.0, 1.0] + * 11.divmod(3.5) #=> [3, 0.5] + * (-11).divmod(3.5) #=> [-4, 3.0] + * (11.5).divmod(3.5) #=> [3, 1.0] */ static VALUE @@ -715,7 +717,7 @@ static VALUE flo_divmod(x, y) VALUE x, y; { - double fy, div, mod; + double fy, div, mod, val; volatile VALUE a, b; switch (TYPE(y)) { @@ -732,7 +734,13 @@ flo_divmod(x, y) return rb_num_coerce_bin(x, y); } flodivmod(RFLOAT(x)->value, fy, &div, &mod); - a = rb_float_new(div); + if (FIXABLE(div)) { + val = div; + a = LONG2FIX(val); + } + else { + a = rb_dbl2big(div); + } b = rb_float_new(mod); return rb_assoc_new(a, b); } diff --git a/test/ruby/test_float.rb b/test/ruby/test_float.rb index 63979b5be0..c2e5041a21 100644 --- a/test/ruby/test_float.rb +++ b/test/ruby/test_float.rb @@ -87,4 +87,32 @@ class TestFloat < Test::Unit::TestCase assert_raise(ArgumentError){Float("1e")} # add expected behaviour here. end + + def test_divmod + assert_equal([2, 3.5], 11.5.divmod(4)) + assert_equal([-3, -0.5], 11.5.divmod(-4)) + assert_equal([-3, 0.5], (-11.5).divmod(4)) + assert_equal([2, -3.5], (-11.5).divmod(-4)) + end + + def test_div + assert_equal(2, 11.5.div(4)) + assert_equal(-3, 11.5.div(-4)) + assert_equal(-3, (-11.5).div(4)) + assert_equal(2, (-11.5).div(-4)) + end + + def test_modulo + assert_equal(3.5, 11.5.modulo(4)) + assert_equal(-0.5, 11.5.modulo(-4)) + assert_equal(0.5, (-11.5).modulo(4)) + assert_equal(-3.5, (-11.5).modulo(-4)) + end + + def test_remainder + assert_equal(3.5, 11.5.remainder(4)) + assert_equal(3.5, 11.5.remainder(-4)) + assert_equal(-3.5, (-11.5).remainder(4)) + assert_equal(-3.5, (-11.5).remainder(-4)) + end end diff --git a/util.c b/util.c index c4fd2fd2fa..42ab81039b 100644 --- a/util.c +++ b/util.c @@ -16,6 +16,7 @@ #include #include #include +#include #ifdef _WIN32 #include "missing/file.h" @@ -750,26 +751,25 @@ ruby_strtod(string, endPtr) errno = 0; p = string; - while (ISSPACE(*p)) { - p += 1; - } + while (ISSPACE(*p)) p++; if (*p == '-') { sign = Qtrue; - p += 1; + p++; } else { - if (*p == '+') { - p += 1; - } + if (*p == '+') p++; sign = Qfalse; } + fraction = 0.; + exp = 0; + /* * Count the number of digits in the mantissa * and also locate the decimal point. */ - for ( ; c = *p; p += 1) { + for ( ; c = *p; p++) { if (!ISDIGIT(c)) { if (c != '.' || hasPoint) { break; @@ -778,13 +778,13 @@ ruby_strtod(string, endPtr) } else { if (hasPoint) { /* already in fractional part */ - fracExp -= 1; + fracExp--; } if (mantSize) { /* already in mantissa */ - mantSize += 1; + mantSize++; } else if (c != '0') { /* have entered mantissa */ - mantSize += 1; + mantSize++; pMant = p; } hasDigit = Qtrue; @@ -807,30 +807,17 @@ ruby_strtod(string, endPtr) mantSize = 18; } if (!hasDigit) { + errno = ERANGE; fraction = 0.0; p = string; } else { - double frac1, frac2; - frac1 = 0; - for ( ; mantSize > 9; mantSize -= 1) { - c = *p; - p += 1; + for (; mantSize > 0; mantSize--) { + c = *p++; if (c == '.') { - c = *p; - p += 1; + c = *p++; } - frac1 = 10*frac1 + (c - '0'); - } - frac2 = 0; - for (; mantSize > 0; mantSize -= 1) { - c = *p; - p += 1; - if (c == '.') { - c = *p; - p += 1; - } - frac2 = 10*frac2 + (c - '0'); + fraction = 10*fraction + (c - '0'); } /* @@ -839,21 +826,20 @@ ruby_strtod(string, endPtr) p = pExp; if ((*p == 'E') || (*p == 'e')) { - p += 1; + p++; if (*p == '-') { expSign = Qtrue; - p += 1; + p++; } else { if (*p == '+') { - p += 1; + p++; } expSign = Qfalse; } if (ISDIGIT(*p)) { do { - exp = exp * 10 + (*p - '0'); - p += 1; + exp = exp * 10 + (*p++ - '0'); } while (ISDIGIT(*p)); } @@ -883,29 +869,6 @@ ruby_strtod(string, endPtr) errno = ERANGE; return 0.0 * (sign ? -1.0 : 1.0); } - if (frac1 > 0) { - fracExp = exp; - exp += 9; - if (exp < 0) { - expSign = Qtrue; - exp = -exp; - } - else { - expSign = Qfalse; - } - dblExp = 10.0; - while (exp) { - if (exp & 1) { - if (expSign) - frac1 /= dblExp; - else - frac1 *= dblExp; - } - exp >>= 1; - dblExp *= dblExp; - } - fraction = frac1; - } if (exp < 0) { expSign = Qtrue; exp = -exp; @@ -918,18 +881,17 @@ ruby_strtod(string, endPtr) { if (exp & 1) { if (expSign) - frac2 /= dblExp; + fraction /= dblExp; else - frac2 *= dblExp; + fraction *= dblExp; } exp >>= 1; dblExp *= dblExp; } - fraction += frac2; } if (endPtr != NULL) { - *endPtr = (char *) p; + *endPtr = (char *)p; } if (sign) { -- cgit v1.2.3