aboutsummaryrefslogtreecommitdiffstats
path: root/numeric.c
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2016-08-15 01:59:58 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2016-08-15 01:59:58 +0000
commit125a8b3c07d99450e145f2cc8f3da7ac7c695491 (patch)
treec153e97b4d5954d4d9c0dc778cf237eb31ae0026 /numeric.c
parent6a54ed6e71418da0d5849098925ca3bda71d25eb (diff)
downloadruby-125a8b3c07d99450e145f2cc8f3da7ac7c695491.tar.gz
numeric.c: round_to_nearest
* numeric.c (round_to_nearest): extract and reduce for platforms where round is not available. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55897 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'numeric.c')
-rw-r--r--numeric.c33
1 files changed, 26 insertions, 7 deletions
diff --git a/numeric.c b/numeric.c
index 5adfaef7d0..ffa576149e 100644
--- a/numeric.c
+++ b/numeric.c
@@ -92,6 +92,31 @@ round(double x)
}
#endif
+static double
+round_to_nearest(double x, double s)
+{
+ double f, xs = x * s;
+
+#ifdef HAVE_ROUND
+ f = round(xs);
+#endif
+ if (x > 0) {
+#ifndef HAVE_ROUND
+ f = floor(xs);
+#endif
+ if ((double)((f + 0.5) / s) <= x) f += 1;
+ x = f;
+ }
+ else {
+#ifndef HAVE_ROUND
+ f = ceil(xs);
+#endif
+ if ((double)((f - 0.5) / s) >= x) f -= 1;
+ x = f;
+ }
+ return x;
+}
+
static VALUE fix_uminus(VALUE num);
static VALUE fix_mul(VALUE x, VALUE y);
static VALUE fix_lshift(long, unsigned long);
@@ -2089,13 +2114,7 @@ flo_round(int argc, VALUE *argv, VALUE num)
}
if (float_invariant_round(number, ndigits, &num)) return num;
f = pow(10, ndigits);
- x = round(number * f);
- if (x > 0) {
- if ((double)((x + 0.5) / f) <= number) x += 1;
- }
- else {
- if ((double)((x - 0.5) / f) >= number) x -= 1;
- }
+ x = round_to_nearest(number, f);
return DBL2NUM(x / f);
}