summaryrefslogtreecommitdiff
path: root/numeric.c
diff options
context:
space:
mode:
authormarcandre <marcandre@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2012-11-06 17:14:16 +0000
committermarcandre <marcandre@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2012-11-06 17:14:16 +0000
commitf02c29ee4f0396735c260114fc9f93ba3dc8ca2e (patch)
treea12f15c2bd9a0d298e2903e932cfd585b094b12a /numeric.c
parentce0bf9f43d9d1828bfd1d8001dcba729d9553f38 (diff)
* numeric.c: Extract ruby_float_step_size
[Feature #6636] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@37514 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'numeric.c')
-rw-r--r--numeric.c52
1 files changed, 28 insertions, 24 deletions
diff --git a/numeric.c b/numeric.c
index d1a1932b69..bb51393190 100644
--- a/numeric.c
+++ b/numeric.c
@@ -1720,40 +1720,44 @@ num_truncate(VALUE num)
return flo_truncate(rb_Float(num));
}
+static double
+ruby_float_step_size(double beg, double end, double unit, int excl) {
+ const double epsilon = DBL_EPSILON;
+ double n = (end - beg)/unit;
+ double err = (fabs(beg) + fabs(end) + fabs(end-beg)) / fabs(unit) * epsilon;
+
+ if (isinf(unit)) {
+ return unit > 0 ? beg <= end : beg >= end;
+ }
+ if (err>0.5) err=0.5;
+ if (excl) {
+ if (n<=0) return 0;
+ if (n<1)
+ n = 0;
+ else
+ n = floor(n - err);
+ }
+ else {
+ if (n<0) return 0;
+ n = floor(n + err);
+ }
+ return n+1;
+}
int
ruby_float_step(VALUE from, VALUE to, VALUE step, int excl)
{
if (RB_TYPE_P(from, T_FLOAT) || RB_TYPE_P(to, T_FLOAT) || RB_TYPE_P(step, T_FLOAT)) {
- const double epsilon = DBL_EPSILON;
double beg = NUM2DBL(from);
double end = NUM2DBL(to);
double unit = NUM2DBL(step);
- double n = (end - beg)/unit;
- double err = (fabs(beg) + fabs(end) + fabs(end-beg)) / fabs(unit) * epsilon;
+ double n = ruby_float_step_size(beg, end, unit, excl);
long i;
- if (isinf(unit)) {
- if (unit > 0 ? beg <= end : beg >= end) rb_yield(DBL2NUM(beg));
- }
- else {
- if (err>0.5) err=0.5;
- if (excl) {
- if (n<=0) return TRUE;
- if (n<1)
- n = 0;
- else
- n = floor(n - err);
- }
- else {
- if (n<0) return TRUE;
- n = floor(n + err);
- }
- for (i=0; i<=n; i++) {
- double d = i*unit+beg;
- if (unit >= 0 ? end < d : d < end) d = end;
- rb_yield(DBL2NUM(d));
- }
+ for (i=0; i<n; i++) {
+ double d = i*unit+beg;
+ if (unit >= 0 ? end < d : d < end) d = end;
+ rb_yield(DBL2NUM(d));
}
return TRUE;
}