array.c: sum for Rational and Float mixed arrays
* array.c (rb_ary_sum): apply the precision compensated algorithm for an array in which Rational and Float values are mixed. * test/ruby/test_array.rb (test_sum): add assertions for the above change. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@54601 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
4bf8fa83b7
commit
a945eb9dda
@ -1,3 +1,11 @@
|
||||
Fri Apr 15 22:31:00 2016 Kenta Murata <mrkn@mrkn.jp>
|
||||
|
||||
* array.c (rb_ary_sum): apply the precision compensated algorithm
|
||||
for an array in which Rational and Float values are mixed.
|
||||
|
||||
* test/ruby/test_array.rb (test_sum): add assertions for the above
|
||||
change.
|
||||
|
||||
Fri Apr 15 22:30:01 2016 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||
|
||||
* thread.c (rb_thread_setname): defer setting native thread name
|
||||
|
18
array.c
18
array.c
@ -5722,6 +5722,8 @@ rb_ary_sum(int argc, VALUE *argv, VALUE ary)
|
||||
if (RB_FLOAT_TYPE_P(e)) {
|
||||
/* Kahan's compensated summation algorithm */
|
||||
double f, c;
|
||||
|
||||
float_value:
|
||||
f = NUM2DBL(v);
|
||||
c = 0.0;
|
||||
for (; i < RARRAY_LEN(ary); i++) {
|
||||
@ -5735,6 +5737,8 @@ rb_ary_sum(int argc, VALUE *argv, VALUE ary)
|
||||
x = FIX2LONG(e);
|
||||
else if (RB_TYPE_P(e, T_BIGNUM))
|
||||
x = rb_big2dbl(e);
|
||||
else if (RB_TYPE_P(e, T_RATIONAL))
|
||||
x = rb_num2dbl(e);
|
||||
else
|
||||
goto not_float;
|
||||
|
||||
@ -5749,6 +5753,20 @@ rb_ary_sum(int argc, VALUE *argv, VALUE ary)
|
||||
v = DBL2NUM(f);
|
||||
}
|
||||
|
||||
if (RB_TYPE_P(e, T_RATIONAL)) {
|
||||
for (; i < RARRAY_LEN(ary); i++) {
|
||||
e = RARRAY_AREF(ary, i);
|
||||
if (block_given)
|
||||
e = rb_yield(e);
|
||||
if (RB_FLOAT_TYPE_P(e)) {
|
||||
v = rb_to_float(v);
|
||||
goto float_value;
|
||||
}
|
||||
v = rb_funcall(v, idPLUS, 1, e);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
for (; i < RARRAY_LEN(ary); i++) {
|
||||
e = RARRAY_AREF(ary, i);
|
||||
if (block_given)
|
||||
|
@ -2774,6 +2774,8 @@ class TestArray < Test::Unit::TestCase
|
||||
small_number /= 10
|
||||
end
|
||||
assert_float_equal(large_number+(small_number*10), [large_number, *[small_number]*10].sum)
|
||||
assert_float_equal(large_number+(small_number*10), [large_number/1r, *[small_number]*10].sum)
|
||||
assert_float_equal(large_number+(small_number*11), [small_number, large_number/1r, *[small_number]*10].sum)
|
||||
end
|
||||
|
||||
private
|
||||
|
Loading…
x
Reference in New Issue
Block a user