Skip to content

Commit 783f1ab

Browse files
committed
get pairwise-sum accuracy for cumsum (fix #9648)
1 parent a318578 commit 783f1ab

File tree

2 files changed

+16
-7
lines changed

2 files changed

+16
-7
lines changed

base/array.jl

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1439,20 +1439,24 @@ symdiff(a, b, rest...) = symdiff(a, symdiff(b, rest...))
14391439
_cumsum_type{T<:Number}(v::AbstractArray{T}) = typeof(+zero(T))
14401440
_cumsum_type(v) = typeof(v[1]+v[1])
14411441

1442-
for (f, fp, op) = ((:cumsum, :cumsum_pairwise, :+),
1443-
(:cumprod, :cumprod_pairwise, :*) )
1442+
for (f, fp, op) = ((:cumsum, :cumsum_pairwise!, :+),
1443+
(:cumprod, :cumprod_pairwise!, :*) )
14441444
# in-place cumsum of c = s+v(i1:n), using pairwise summation as for sum
1445-
@eval function ($fp)(v::AbstractVector, c::AbstractVector, s, i1, n)
1445+
@eval function ($fp){T}(v::AbstractVector, c::AbstractVector{T}, s, i1, n)
1446+
local s_::T # for sum(v(i1:n)), i.e. sum without s
14461447
if n < 128
1447-
@inbounds c[i1] = ($op)(s, v[i1])
1448+
@inbounds s_ = v[i1]
1449+
@inbounds c[i1] = ($op)(s, s_)
14481450
for i = i1+1:i1+n-1
1449-
@inbounds c[i] = $(op)(c[i-1], v[i])
1451+
@inbounds s_ = $(op)(s_, v[i])
1452+
@inbounds c[i] = $(op)(s, s_)
14501453
end
14511454
else
14521455
n2 = div(n,2)
1453-
($fp)(v, c, s, i1, n2)
1454-
($fp)(v, c, c[(i1+n2)-1], i1+n2, n-n2)
1456+
s_ = ($fp)(v, c, s, i1, n2)
1457+
s_ = $(op)(s_, ($fp)(v, c, s + s_, i1+n2, n-n2))
14551458
end
1459+
return s_
14561460
end
14571461

14581462
@eval function ($f)(v::AbstractVector)

test/arrayops.jl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -974,3 +974,8 @@ a = [ [ 1 0 0 ], [ 0 0 0 ] ]
974974
@test rotl90(a,4) == a
975975
@test rotr90(a,4) == a
976976
@test rot180(a,2) == a
977+
978+
# issue #9648
979+
let x = fill(1.5f0, 10^7)
980+
@test abs(1.5f7 - cumsum(x)[end]) < 3*eps(1.5f7)
981+
end

0 commit comments

Comments
 (0)