Skip to content

Commit

Permalink
Add docstrings for accumulation methods on vectors
Browse files Browse the repository at this point in the history
Fix bug in accumulate when initial value is provided since the implementation
doesn't support multidimentional arrays.

Move the accumulate methods with initial values to the end
  • Loading branch information
andreasnoack committed Nov 22, 2017
1 parent b1173c6 commit 5ff1bad
Showing 1 changed file with 138 additions and 62 deletions.
200 changes: 138 additions & 62 deletions base/multidimensional.jl
Original file line number Diff line number Diff line change
Expand Up @@ -719,6 +719,27 @@ function cumsum(A::AbstractArray{T}, axis::Integer) where T
cumsum!(out, A, axis)
end

"""
cumsum(x::AbstractVector)
Cumulative sum a vector. See also [`cumsum!`](@ref)
to use a preallocated output array, both for performance and to control the precision of the
output (e.g. to avoid overflow).
```jldoctest
julia> cumsum([1, 1, 1])
3-element Array{Int64,1}:
1
2
3
julia> cumsum([fill(1, 2) for i in 1:3])
3-element Array{Array{Int64,1},1}:
[1, 1]
[2, 2]
[3, 3]
```
"""
cumsum(x::AbstractVector) = cumsum(x, 1)

"""
Expand All @@ -728,6 +749,11 @@ Cumulative sum of `A` along a dimension, storing the result in `B`. See also [`c
"""
cumsum!(B, A, axis::Integer) = accumulate!(+, B, A, axis)

"""
cumsum!(y::AbstractVector, x::AbstractVector)
Cumulative sum of a vector `x`, storing the result in `y`. See also [`cumsum`](@ref).
"""
cumsum!(y::AbstractVector, x::AbstractVector) = cumsum!(y, x, 1)

"""
Expand Down Expand Up @@ -756,6 +782,27 @@ julia> cumprod(a,2)
"""
cumprod(A::AbstractArray, axis::Integer) = accumulate(*, A, axis)

"""
cumprod(x::AbstractVector)
Cumulative product of a vector. See also
[`cumprod!`](@ref) to use a preallocated output array, both for performance and
to control the precision of the output (e.g. to avoid overflow).
```jldoctest
julia> cumprod(fill(1//2, 3))
3-element Array{Rational{Int64},1}:
1//2
1//4
1//8
julia> cumprod([fill(1//3, 2, 2) for i in 1:3])
3-element Array{Array{Rational{Int64},2},1}:
Rational{Int64}[1//3 1//3; 1//3 1//3]
Rational{Int64}[2//9 2//9; 2//9 2//9]
Rational{Int64}[4//27 4//27; 4//27 4//27]
```
"""
cumprod(x::AbstractVector) = cumprod(x, 1)

"""
Expand All @@ -766,6 +813,12 @@ See also [`cumprod`](@ref).
"""
cumprod!(B, A, axis::Integer) = accumulate!(*, B, A, axis)

"""
cumprod!(y::AbstractVector, x::AbstractVector)
Cumulative product of a vector `x`, storing the result in `y`.
See also [`cumprod`](@ref).
"""
cumprod!(y::AbstractVector, x::AbstractVector) = cumprod!(y, x, 1)

"""
Expand All @@ -778,83 +831,48 @@ there are specialized variants of `accumulate`, see:
[`cumsum`](@ref), [`cumprod`](@ref)
```jldoctest
julia> accumulate(+, [1,2,3])
3-element Array{Int64,1}:
1
3
6
julia> accumulate(*, [1,2,3])
3-element Array{Int64,1}:
1
2
6
julia> accumulate(+, fill(1, 3, 3), 1)
3×3 Array{Int64,2}:
1 1 1
2 2 2
3 3 3
julia> accumulate(+, fill(1, 3, 3), 2)
3×3 Array{Int64,2}:
1 2 3
1 2 3
1 2 3
```
"""
function accumulate(op, A, axis::Integer)
out = similar(A, rcum_promote_type(op, eltype(A)))
accumulate!(op, out, A, axis)
end

accumulate(op, x::AbstractVector) = accumulate(op, x, 1)

"""
accumulate(op, v0, A)
accumulate(op, x::AbstractVector)
Like `accumulate`, but using a starting element `v0`. The first entry of the result will be
`op(v0, first(A))`.
Cumulative operation `op` on a vector. See also
[`accumulate!`](@ref) to use a preallocated output array, both for performance and
to control the precision of the output (e.g. to avoid overflow). For common operations
there are specialized variants of `accumulate`, see:
[`cumsum`](@ref), [`cumprod`](@ref)
# Examples
```jldoctest
julia> accumulate(+, 100, [1,2,3])
julia> accumulate(+, [1,2,3])
3-element Array{Int64,1}:
101
103
106
1
3
6
julia> accumulate(min, 0, [1,2,-1])
julia> accumulate(*, [1,2,3])
3-element Array{Int64,1}:
0
0
-1
1
2
6
```
"""
function accumulate(op, v0, A, axis::Integer)
T = rcum_promote_type(op, typeof(v0), eltype(A))
out = similar(A, T)
accumulate!(op, out, v0, A, 1)
end

accumulate(op, v0, x::AbstractVector) = accumulate(op, v0, x, 1)

function accumulate!(op::Op, B, A::AbstractVector, axis::Integer) where Op
isempty(A) && return B
v1 = first(A)
_accumulate1!(op, B, v1, A, axis)
end

function accumulate!(op, B, v0, A::AbstractVector, axis::Integer)
isempty(A) && return B
v1 = op(v0, first(A))
_accumulate1!(op, B, v1, A, axis)
end

accumulate!(op, y::AbstractVector, v0, x::AbstractVector) = accumulate!(op, y, v0, x, 1)

function _accumulate1!(op, B, v1, A::AbstractVector, axis::Integer)
axis > 0 || throw(ArgumentError("axis must be a positive integer"))
inds = linearindices(A)
inds == linearindices(B) || throw(DimensionMismatch("linearindices of A and B don't match"))
axis > 1 && return copy!(B, A)
i1 = inds[1]
cur_val = v1
B[i1] = cur_val
@inbounds for i in inds[2:end]
cur_val = op(cur_val, A[i])
B[i] = cur_val
end
return B
end
accumulate(op, x::AbstractVector) = accumulate(op, x, 1)

"""
accumulate!(op, B, A, dim)
Expand Down Expand Up @@ -888,7 +906,17 @@ function accumulate!(op, B, A, axis::Integer)
return B
end

accumulate!(op, y::AbstractVector, x::AbstractVector) = accumulate!(op, y, x, 1)
"""
accumulate!(op, y, x::AbstractVector)
Cumulative operation `op` on a vector `x`, storing the result in `y`.
See also [`accumulate`](@ref).
"""
function accumulate!(op::Op, y, x::AbstractVector) where Op
isempty(x) && return y
v1 = first(x)
_accumulate1!(op, y, v1, x, 1)
end

@noinline function _accumulate!(op, B, A, R1, ind, R2)
# Copy the initial element in each 1d vector along dimension `axis`
Expand All @@ -903,6 +931,54 @@ accumulate!(op, y::AbstractVector, x::AbstractVector) = accumulate!(op, y, x, 1)
B
end

"""
accumulate(op, v0, x::AbstractVector)
Like `accumulate`, but using a starting element `v0`. The first entry of the result will be
`op(v0, first(A))`.
# Examples
```jldoctest
julia> accumulate(+, 100, [1,2,3])
3-element Array{Int64,1}:
101
103
106
julia> accumulate(min, 0, [1,2,-1])
3-element Array{Int64,1}:
0
0
-1
```
"""
function accumulate(op, v0, x::AbstractVector)
T = rcum_promote_type(op, typeof(v0), eltype(x))
out = similar(x, T)
accumulate!(op, out, v0, x)
end

function accumulate!(op, y, v0, x::AbstractVector)
isempty(x) && return y
v1 = op(v0, first(x))
_accumulate1!(op, y, v1, x, 1)
end

function _accumulate1!(op, B, v1, A::AbstractVector, axis::Integer)
axis > 0 || throw(ArgumentError("axis must be a positive integer"))
inds = linearindices(A)
inds == linearindices(B) || throw(DimensionMismatch("linearindices of A and B don't match"))
axis > 1 && return copy!(B, A)
i1 = inds[1]
cur_val = v1
B[i1] = cur_val
@inbounds for i in inds[2:end]
cur_val = op(cur_val, A[i])
B[i] = cur_val
end
return B
end

### from abstractarray.jl

"""
Expand Down

0 comments on commit 5ff1bad

Please sign in to comment.