aboutsummaryrefslogtreecommitdiffstats
path: root/enum.c
diff options
context:
space:
mode:
authorakr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2016-04-13 13:51:53 +0000
committerakr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2016-04-13 13:51:53 +0000
commitfecbe8dede764e1c466a9b0447fb1971b65f959f (patch)
treeb5932236ea53fb4dc0e1ec1c283566157170c263 /enum.c
parentc62cba56f0670703fdf787fbe98964c9ebc803ab (diff)
downloadruby-fecbe8dede764e1c466a9b0447fb1971b65f959f.tar.gz
* array.c (rb_ary_sum): Array#sum is implemented.
Kahan's compensated summation algorithm for precise sum of float numbers is moved from ary_inject_op in enum.c. * enum.c (ary_inject_op): Don't specialize for float numbers. [ruby-core:74569] [Feature#12217] proposed by mrkn. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@54565 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'enum.c')
-rw-r--r--enum.c48
1 files changed, 8 insertions, 40 deletions
diff --git a/enum.c b/enum.c
index 23e4f5a5e4..9387ec3b6a 100644
--- a/enum.c
+++ b/enum.c
@@ -634,7 +634,6 @@ ary_inject_op(VALUE ary, VALUE init, VALUE op)
ID id;
VALUE v, e;
long i, n;
- double f, c;
if (RARRAY_LEN(ary) == 0)
return init == Qundef ? Qnil : init;
@@ -656,7 +655,7 @@ ary_inject_op(VALUE ary, VALUE init, VALUE op)
rb_method_basic_definition_p(rb_cFixnum, idPLUS) &&
rb_method_basic_definition_p(rb_cBignum, idPLUS)) {
n = 0;
- while (1) {
+ for (; i < RARRAY_LEN(ary); i++) {
e = RARRAY_AREF(ary, i);
if (FIXNUM_P(e)) {
n += FIX2LONG(e); /* should not overflow long type */
@@ -668,49 +667,18 @@ ary_inject_op(VALUE ary, VALUE init, VALUE op)
else if (RB_TYPE_P(e, T_BIGNUM))
v = rb_big_plus(e, v);
else
- break;
- i++;
- if (RARRAY_LEN(ary) <= i)
- return n == 0 ? v : rb_fix_plus(LONG2FIX(n), v);
+ goto not_integer;
}
- if (n != 0) {
+ if (n != 0)
v = rb_fix_plus(LONG2FIX(n), v);
- }
- if (RB_FLOAT_TYPE_P(e) &&
- rb_method_basic_definition_p(rb_cFloat, idPLUS)) {
- f = NUM2DBL(v);
- goto sum_float;
- }
- }
- else if (RB_FLOAT_TYPE_P(v) &&
- rb_method_basic_definition_p(rb_cFloat, idPLUS)) {
- f = RFLOAT_VALUE(v);
- sum_float:
- c = 0.0;
- while (1) {
- double x, y, t;
- e = RARRAY_AREF(ary, i);
- if (RB_FLOAT_TYPE_P(e))
- x = RFLOAT_VALUE(e);
- else if (FIXNUM_P(e))
- x = FIX2LONG(e);
- else if (RB_TYPE_P(e, T_BIGNUM))
- x = rb_big2dbl(e);
- else
- break;
-
- y = x - c;
- t = f + y;
- c = (t - f) - y;
- f = t;
+ return v;
- i++;
- if (RARRAY_LEN(ary) <= i)
- return DBL2NUM(f);
- }
+ not_integer:
+ if (n != 0)
+ v = rb_fix_plus(LONG2FIX(n), v);
}
}
- for (; i<RARRAY_LEN(ary); i++) {
+ for (; i < RARRAY_LEN(ary); i++) {
v = rb_funcall(v, id, 1, RARRAY_AREF(ary, i));
}
return v;