* 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
This commit is contained in:
marcandre 2012-11-06 17:14:16 +00:00
Родитель ce0bf9f43d
Коммит f02c29ee4f
1 изменённых файлов: 28 добавлений и 24 удалений

Просмотреть файл

@ -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;
}