summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog5
-rw-r--r--numeric.c64
-rw-r--r--version.h6
3 files changed, 49 insertions, 26 deletions
diff --git a/ChangeLog b/ChangeLog
index be6743c7f9..680df9c0e3 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+Wed Nov 30 02:28:22 2011 Marc-Andre Lafortune <ruby-core@marc-andre.ca>
+
+ * numeric.c (int_round): Integer#round always returns an Integer [Bug
+ #5271]
+
Fri Nov 4 01:56:30 2011 NAKAMURA Usaku <usa@ruby-lang.org>
* io.c (make_writeconv): unversal_newline converter is for reading.
diff --git a/numeric.c b/numeric.c
index 4a94a95608..962d3f3883 100644
--- a/numeric.c
+++ b/numeric.c
@@ -1456,6 +1456,45 @@ flo_ceil(VALUE num)
}
/*
+ * Assumes num is an Integer, ndigits <= 0
+ */
+static VALUE
+int_round_0(VALUE num, int ndigits)
+{
+ VALUE n, f, h, r;
+ long bytes;
+ ID op;
+ /* If 10**N / 2 > num, then return 0 */
+ /* We have log_256(10) > 0.415241 and log_256(1/2) = -0.125, so */
+ bytes = FIXNUM_P(num) ? sizeof(long) : rb_funcall(num, rb_intern("size"), 0);
+ if (-0.415241 * ndigits - 0.125 > bytes ) {
+ return INT2FIX(0);
+ }
+
+ f = int_pow(10, -ndigits);
+ if (FIXNUM_P(num) && FIXNUM_P(f)) {
+ SIGNED_VALUE x = FIX2LONG(num), y = FIX2LONG(f);
+ int neg = x < 0;
+ if (neg) x = -x;
+ x = (x + y / 2) / y * y;
+ if (neg) x = -x;
+ return LONG2NUM(x);
+ }
+ if (TYPE(f) == T_FLOAT) {
+ /* then int_pow overflow */
+ return INT2FIX(0);
+ }
+ h = rb_funcall(f, '/', 1, INT2FIX(2));
+ r = rb_funcall(num, '%', 1, f);
+ n = rb_funcall(num, '-', 1, r);
+ op = RTEST(rb_funcall(num, '<', 1, INT2FIX(0))) ? rb_intern("<=") : '<';
+ if (!RTEST(rb_funcall(r, op, 1, h))) {
+ n = rb_funcall(n, '+', 1, f);
+ }
+ return n;
+}
+
+/*
* call-seq:
* flt.round([ndigits]) -> integer or float
*
@@ -3318,9 +3357,8 @@ int_dotimes(VALUE num)
static VALUE
int_round(int argc, VALUE* argv, VALUE num)
{
- VALUE n, f, h, r;
+ VALUE n;
int ndigits;
- ID op;
if (argc == 0) return num;
rb_scan_args(argc, argv, "1", &n);
@@ -3331,27 +3369,7 @@ int_round(int argc, VALUE* argv, VALUE num)
if (ndigits == 0) {
return num;
}
- ndigits = -ndigits;
- if (ndigits < 0) {
- rb_raise(rb_eArgError, "ndigits out of range");
- }
- f = int_pow(10, ndigits);
- if (FIXNUM_P(num) && FIXNUM_P(f)) {
- SIGNED_VALUE x = FIX2LONG(num), y = FIX2LONG(f);
- int neg = x < 0;
- if (neg) x = -x;
- x = (x + y / 2) / y * y;
- if (neg) x = -x;
- return LONG2NUM(x);
- }
- h = rb_funcall(f, '/', 1, INT2FIX(2));
- r = rb_funcall(num, '%', 1, f);
- n = rb_funcall(num, '-', 1, r);
- op = RTEST(rb_funcall(num, '<', 1, INT2FIX(0))) ? rb_intern("<=") : '<';
- if (!RTEST(rb_funcall(r, op, 1, h))) {
- n = rb_funcall(n, '+', 1, f);
- }
- return n;
+ return int_round_0(num, ndigits);
}
/*
diff --git a/version.h b/version.h
index 6311194c3b..4e5b0953bc 100644
--- a/version.h
+++ b/version.h
@@ -1,10 +1,10 @@
#define RUBY_VERSION "1.9.3"
-#define RUBY_PATCHLEVEL 0
+#define RUBY_PATCHLEVEL 1
-#define RUBY_RELEASE_DATE "2011-11-08"
+#define RUBY_RELEASE_DATE "2011-11-30"
#define RUBY_RELEASE_YEAR 2011
#define RUBY_RELEASE_MONTH 11
-#define RUBY_RELEASE_DAY 8
+#define RUBY_RELEASE_DAY 30
#include "ruby/version.h"