summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoryugui <yugui@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2011-05-29 22:48:15 +0000
committeryugui <yugui@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2011-05-29 22:48:15 +0000
commitc101436215d4df12f9c63e2a800a37ce16649fb7 (patch)
tree2a8c75b129fb4ab02d143aea70095a2766eb3f55
parentcca6b1d3769835b70670c208bf18365d27812738 (diff)
merges r31158 from trunk into ruby_1_9_2.
-- * numeric.c (flo_round): fix inaccurate results. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_9_2@31790 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog4
-rw-r--r--include/ruby/intern.h1
-rw-r--r--numeric.c13
-rw-r--r--test/ruby/test_float.rb2
-rw-r--r--version.h2
5 files changed, 20 insertions, 2 deletions
diff --git a/ChangeLog b/ChangeLog
index f640b966cc..ac8001e1fa 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+Wed Mar 23 08:07:33 2011 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * numeric.c (flo_round): fix inaccurate results.
+
Wed Mar 23 00:12:16 2011 Tajima Akio <artonx@yahoo.co.jp>
* win32/win32.c: wait process real termination after reading
diff --git a/include/ruby/intern.h b/include/ruby/intern.h
index 0f1081715d..f0cff67928 100644
--- a/include/ruby/intern.h
+++ b/include/ruby/intern.h
@@ -114,6 +114,7 @@ VALUE rb_big_plus(VALUE, VALUE);
VALUE rb_big_minus(VALUE, VALUE);
VALUE rb_big_mul(VALUE, VALUE);
VALUE rb_big_div(VALUE, VALUE);
+VALUE rb_big_idiv(VALUE, VALUE);
VALUE rb_big_modulo(VALUE, VALUE);
VALUE rb_big_divmod(VALUE, VALUE);
VALUE rb_big_pow(VALUE, VALUE);
diff --git a/numeric.c b/numeric.c
index 6fb50a04e6..ce5031428d 100644
--- a/numeric.c
+++ b/numeric.c
@@ -97,6 +97,9 @@ round(double x)
}
#endif
+static VALUE fix_mul(VALUE x, VALUE y);
+static VALUE int_pow(long x, unsigned long y);
+
static ID id_coerce, id_to_i, id_eq;
VALUE rb_cNumeric;
@@ -1450,7 +1453,15 @@ flo_round(int argc, VALUE *argv, VALUE num)
if (ndigits < 0) number = 0;
}
else {
- if (ndigits < 0) number /= f;
+ if (ndigits < 0) {
+ if (fabs(number) < f) return INT2FIX(0);
+ if (!FIXABLE(number)) {
+ VALUE f10 = int_pow(10, -ndigits);
+ num = rb_big_idiv(rb_dbl2big(number), f10);
+ return FIXNUM_P(num) ? fix_mul(num, f10) : rb_big_mul(num, f10);
+ }
+ number /= f;
+ }
else number *= f;
number = round(number);
if (ndigits < 0) number *= f;
diff --git a/test/ruby/test_float.rb b/test/ruby/test_float.rb
index b465814140..ab5f9bdc07 100644
--- a/test/ruby/test_float.rb
+++ b/test/ruby/test_float.rb
@@ -295,6 +295,8 @@ class TestFloat < Test::Unit::TestCase
assert_equal(1.110, 1.111.round(2))
assert_equal(11110.0, 11111.1.round(-1))
assert_equal(11100.0, 11111.1.round(-2))
+
+ assert_equal(10**300, 1.1e300.round(-300))
end
VS = [
diff --git a/version.h b/version.h
index 3dad4685f3..9aeb85c740 100644
--- a/version.h
+++ b/version.h
@@ -1,5 +1,5 @@
#define RUBY_VERSION "1.9.2"
-#define RUBY_PATCHLEVEL 217
+#define RUBY_PATCHLEVEL 218
#define RUBY_VERSION_MAJOR 1
#define RUBY_VERSION_MINOR 9
#define RUBY_VERSION_TEENY 1