Skip to content

Commit 8992771

Browse files
committed
Deprecate (cum)sum_kbn
This removes `sum_kbn` and `cumsum_kbn` in favor of `sum` and `cumsum`, respectively, with the `*_kbn` functions moving to a package. Fixes #24804
1 parent b8ee561 commit 8992771

9 files changed

+20
-150
lines changed

base/abstractarraymath.jl

-67
Original file line numberDiff line numberDiff line change
@@ -238,73 +238,6 @@ function circshift(a::AbstractArray, shiftamt)
238238
circshift!(similar(a), a, map(Integer, (shiftamt...,)))
239239
end
240240

241-
# Uses K-B-N summation
242-
function cumsum_kbn(v::AbstractVector{T}) where T<:AbstractFloat
243-
r = similar(v)
244-
if isempty(v); return r; end
245-
246-
inds = indices(v, 1)
247-
i1 = first(inds)
248-
s = r[i1] = v[i1]
249-
c = zero(T)
250-
for i=i1+1:last(inds)
251-
vi = v[i]
252-
t = s + vi
253-
if abs(s) >= abs(vi)
254-
c += ((s-t) + vi)
255-
else
256-
c += ((vi-t) + s)
257-
end
258-
s = t
259-
r[i] = s+c
260-
end
261-
return r
262-
end
263-
264-
# Uses K-B-N summation
265-
# TODO: Needs a separate IndexCartesian method, this is only fast for IndexLinear
266-
267-
"""
268-
cumsum_kbn(A, dim::Integer)
269-
270-
Cumulative sum along a dimension, using the Kahan-Babuska-Neumaier compensated summation
271-
algorithm for additional accuracy.
272-
"""
273-
function cumsum_kbn(A::AbstractArray{T}, axis::Integer) where T<:AbstractFloat
274-
dimsA = size(A)
275-
ndimsA = ndims(A)
276-
axis_size = dimsA[axis]
277-
axis_stride = 1
278-
for i = 1:(axis-1)
279-
axis_stride *= size(A,i)
280-
end
281-
282-
if axis_size <= 1
283-
return A
284-
end
285-
286-
B = similar(A)
287-
C = similar(A)
288-
289-
for i = 1:length(A)
290-
if div(i-1, axis_stride) % axis_size == 0
291-
B[i] = A[i]
292-
C[i] = zero(T)
293-
else
294-
s = B[i-axis_stride]
295-
Ai = A[i]
296-
B[i] = t = s + Ai
297-
if abs(s) >= abs(Ai)
298-
C[i] = C[i-axis_stride] + ((s-t) + Ai)
299-
else
300-
C[i] = C[i-axis_stride] + ((Ai-t) + s)
301-
end
302-
end
303-
end
304-
305-
return B + C
306-
end
307-
308241
## Other array functions ##
309242

310243
"""

base/deprecated.jl

+4-1
Original file line numberDiff line numberDiff line change
@@ -2136,7 +2136,6 @@ end
21362136
@deprecate RowVector{T}(n::Tuple{Int,Int}) where {T} RowVector{T}(uninitialized, n)
21372137

21382138
@deprecate cumsum(A::AbstractArray) cumsum(A, 1)
2139-
@deprecate cumsum_kbn(A::AbstractArray) cumsum_kbn(A, 1)
21402139
@deprecate cumprod(A::AbstractArray) cumprod(A, 1)
21412140

21422141
# issue #16307
@@ -2176,6 +2175,10 @@ end
21762175
@deprecate similar(a::Associative) empty(a)
21772176
@deprecate similar(a::Associative, ::Type{Pair{K,V}}) where {K, V} empty(a, K, V)
21782177

2178+
# issue #24804
2179+
@deprecate_moved sum_kbn "KahanSummation"
2180+
@deprecate_moved cumsum_kbn "KahanSummation"
2181+
21792182
# END 0.7 deprecations
21802183

21812184
# BEGIN 1.0 deprecations

base/exports.jl

-2
Original file line numberDiff line numberDiff line change
@@ -431,7 +431,6 @@ export
431431
cumsum!,
432432
accumulate,
433433
accumulate!,
434-
cumsum_kbn,
435434
eachindex,
436435
extrema,
437436
fill!,
@@ -525,7 +524,6 @@ export
525524
sub2ind,
526525
sum!,
527526
sum,
528-
sum_kbn,
529527
to_indices,
530528
vcat,
531529
vec,

base/reduce.jl

-32
Original file line numberDiff line numberDiff line change
@@ -391,38 +391,6 @@ julia> sum(1:20)
391391
sum(a) = mapreduce(promote_sys_size_add, +, a)
392392
sum(a::AbstractArray{Bool}) = count(a)
393393

394-
395-
# Kahan (compensated) summation: O(1) error growth, at the expense
396-
# of a considerable increase in computational expense.
397-
398-
"""
399-
sum_kbn(A)
400-
401-
Returns the sum of all elements of `A`, using the Kahan-Babuska-Neumaier compensated
402-
summation algorithm for additional accuracy.
403-
"""
404-
function sum_kbn(A)
405-
T = @default_eltype(typeof(A))
406-
c = promote_sys_size_add(zero(T)::T)
407-
i = start(A)
408-
if done(A, i)
409-
return c
410-
end
411-
Ai, i = next(A, i)
412-
s = Ai - c
413-
while !(done(A, i))
414-
Ai, i = next(A, i)
415-
t = s + Ai
416-
if abs(s) >= abs(Ai)
417-
c -= ((s-t) + Ai)
418-
else
419-
c -= ((Ai-t) + s)
420-
end
421-
s = t
422-
end
423-
s - c
424-
end
425-
426394
## prod
427395
"""
428396
prod(f, itr)

doc/src/manual/style-guide.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ uses (e.g. `a[i]::Int`) than to try to pack many alternatives into one type.
159159
* functions are lowercase ([`maximum`](@ref), [`convert`](@ref)) and, when readable, with multiple
160160
words squashed together ([`isequal`](@ref), [`haskey`](@ref)). When necessary, use underscores
161161
as word separators. Underscores are also used to indicate a combination of concepts ([`remotecall_fetch`](@ref)
162-
as a more efficient implementation of `fetch(remotecall(...))`) or as modifiers ([`sum_kbn`](@ref)).
162+
as a more efficient implementation of `fetch(remotecall(...))`) or as modifiers.
163163
* conciseness is valued, but avoid abbreviation ([`indexin`](@ref) rather than `indxin`) as
164164
it becomes difficult to remember whether and how particular words are abbreviated.
165165

doc/src/stdlib/arrays.md

-2
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,6 @@ Base.cumprod
147147
Base.cumprod!
148148
Base.cumsum
149149
Base.cumsum!
150-
Base.cumsum_kbn
151150
Base.LinAlg.diff
152151
Base.repeat(::AbstractArray)
153152
Base.rot180
@@ -156,7 +155,6 @@ Base.rotr90
156155
Base.reducedim
157156
Base.mapreducedim
158157
Base.mapslices
159-
Base.sum_kbn
160158
```
161159

162160
## Combinatorics

test/arrayops.jl

-23
Original file line numberDiff line numberDiff line change
@@ -870,29 +870,6 @@ end
870870
@test c[2,2] == A[3,1]+A[3,3]
871871
end
872872

873-
v = [1,1e100,1,-1e100]*1000
874-
v2 = [1,-1e100,1,1e100]*1000
875-
876-
cv = [1,1e100,1e100,2]*1000
877-
cv2 = [1,-1e100,-1e100,2]*1000
878-
879-
@test isequal(cumsum_kbn(v), cv)
880-
@test isequal(cumsum_kbn(v2), cv2)
881-
882-
A = [v reverse(v) v2 reverse(v2)]
883-
884-
c = cumsum_kbn(A, 1)
885-
886-
@test isequal(c[:,1], cv)
887-
@test isequal(c[:,3], cv2)
888-
@test isequal(c[4,:], [2.0, 2.0, 2.0, 2.0]*1000)
889-
890-
c = cumsum_kbn(A, 2)
891-
892-
@test isequal(c[1,:], cv2)
893-
@test isequal(c[3,:], cv)
894-
@test isequal(c[:,4], [2.0,2.0,2.0,2.0]*1000)
895-
896873
@test repeat(BitMatrix(Matrix(I, 2, 2)), inner = (2,1), outer = (1,2)) ==
897874
repeat(Matrix(I, 2, 2), inner = (2,1), outer = (1,2))
898875
end

test/offsetarray.jl

+14-8
Original file line numberDiff line numberDiff line change
@@ -383,14 +383,20 @@ I,J,N = findnz(z)
383383
@test vecnorm(A) vecnorm(parent(A))
384384
@test vecdot(v, v) vecdot(v0, v0)
385385

386-
v = OffsetArray([1,1e100,1,-1e100], (-3,))*1000
387-
v2 = OffsetArray([1,-1e100,1,1e100], (5,))*1000
388-
@test isa(v, OffsetArray)
389-
cv = OffsetArray([1,1e100,1e100,2], (-3,))*1000
390-
cv2 = OffsetArray([1,-1e100,-1e100,2], (5,))*1000
391-
@test isequal(cumsum_kbn(v), cv)
392-
@test isequal(cumsum_kbn(v2), cv2)
393-
@test isequal(sum_kbn(v), sum_kbn(parent(v)))
386+
# Prior to its removal from Base, cumsum_kbn was used here. To achieve the same level of
387+
# accuracy in the tests, we need to use BigFloats with enlarged precision.
388+
@testset "high-precision array reduction" begin
389+
setprecision(BigFloat, 500) do
390+
v = OffsetArray(BigFloat[1,1e100,1,-1e100], (-3,)) .* 1000
391+
v2 = OffsetArray(BigFloat[1,-1e100,1,1e100], ( 5,)) .* 1000
392+
@test isa(v, OffsetArray)
393+
cv = OffsetArray(BigFloat[1, 1e100, 1e100,2], (-3,)) .* 1000
394+
cv2 = OffsetArray(BigFloat[1,-1e100,-1e100,2], ( 5,)) .* 1000
395+
@test isequal(cumsum(v), cv)
396+
@test isequal(cumsum(v2), cv2)
397+
@test isequal(sum(v), sum(parent(v)))
398+
end
399+
end
394400

395401
io = IOBuffer()
396402
writedlm(io, A)

test/reduce.jl

+1-14
Original file line numberDiff line numberDiff line change
@@ -135,18 +135,6 @@ for f in (sum3, sum4, sum7, sum8)
135135
end
136136
@test typeof(sum(Int8[])) == typeof(sum(Int8[1])) == typeof(sum(Int8[1 7]))
137137

138-
@test sum_kbn([1,1e100,1,-1e100]) === 2.0
139-
@test sum_kbn(Float64[]) === 0.0
140-
@test sum_kbn(i for i=1.0:1.0:10.0) === 55.0
141-
@test sum_kbn(i for i=1:1:10) === 55
142-
@test sum_kbn([1 2 3]) === 6
143-
@test sum_kbn([2+im 3-im]) === 5+0im
144-
@test sum_kbn([1+im 2+3im]) === 3+4im
145-
@test sum_kbn([7 8 9]) === sum_kbn([8 9 7])
146-
@test sum_kbn(i for i=1:1:10) === sum_kbn(i for i=10:-1:1)
147-
@test sum_kbn([-0.0]) === -0.0
148-
@test sum_kbn([-0.0,-0.0]) === -0.0
149-
150138
# check sum(abs, ...) for support of empty collections
151139
@testset "sum(abs, [])" begin
152140
@test @inferred(sum(abs, Float64[])) === 0.0
@@ -362,14 +350,13 @@ end
362350
## cumsum, cummin, cummax
363351

364352
z = rand(10^6)
365-
let es = sum_kbn(z), es2 = sum_kbn(z[1:10^5])
353+
let es = sum(BigFloat.(z)), es2 = sum(BigFloat.(z[1:10^5]))
366354
@test (es - sum(z)) < es * 1e-13
367355
cs = cumsum(z)
368356
@test (es - cs[end]) < es * 1e-13
369357
@test (es2 - cs[10^5]) < es2 * 1e-13
370358
end
371359

372-
373360
@test sum(collect(map(UInt8,0:255))) == 32640
374361
@test sum(collect(map(UInt8,254:255))) == 509
375362

0 commit comments

Comments
 (0)