From 250e0ca0e37c7963ec68cf8cbccadcf3a3af4c2e Mon Sep 17 00:00:00 2001 From: Andy Ferris Date: Fri, 29 Jun 2018 16:33:16 +1000 Subject: [PATCH] Deprecate v0 in accumulate in favor of init keyword --- NEWS.md | 3 +- base/accumulate.jl | 84 ++++++++++++++++++++++++---------------------- base/deprecated.jl | 4 +++ test/arrayops.jl | 12 +++---- 4 files changed, 55 insertions(+), 48 deletions(-) diff --git a/NEWS.md b/NEWS.md index 61609b4539632..8b1b36bc4a004 100644 --- a/NEWS.md +++ b/NEWS.md @@ -721,7 +721,8 @@ Library improvements * The initial element `v0` in `reduce(op, v0, itr)` has been replaced with an `init` optional keyword argument, as in `reduce(op, itr; init=v0)`. Similarly for `foldl`, - `foldr`, `mapreduce`, `mapfoldl` and `mapfoldr`. ([#27711]) + `foldr`, `mapreduce`, `mapfoldl`, `mapfoldr`, `accumulate` and `accumulate!`. + ([#27711], [#27859]) Compiler/Runtime improvements ----------------------------- diff --git a/base/accumulate.jl b/base/accumulate.jl index 13b9096eac06b..d84ba05b1d48f 100644 --- a/base/accumulate.jl +++ b/base/accumulate.jl @@ -225,11 +225,12 @@ function accumulate(op, A; dims::Integer) end """ - accumulate(op, x::AbstractVector) + accumulate(op, x::AbstractVector; [init]) 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 +to control the precision of the output (e.g. to avoid overflow). You may optionally provide +an initial starting value via the keyword argument `init`. For common operations there are specialized variants of `accumulate`, see: [`cumsum`](@ref), [`cumprod`](@ref) @@ -246,9 +247,33 @@ julia> accumulate(*, [1,2,3]) 1 2 6 + +julia> accumulate(+, [1,2,3]; init=100) +3-element Array{Int64,1}: + 101 + 103 + 106 + +julia> accumulate(min, [1,2,-1]; init=0) +3-element Array{Int64,1}: + 0 + 0 + -1 ``` """ -accumulate(op, x::AbstractVector) = accumulate(op, x, dims=1) +function accumulate(op, x::AbstractVector; kw...) + nt = kw.data + if nt isa NamedTuple{()} + accumulate(op, x, dims=1) + elseif nt isa NamedTuple{(:init,)} + v0 = nt.init + T = promote_op(op, typeof(v0), eltype(x)) + out = similar(x, T) + accumulate!(op, out, v0, x) + else + throw(ArgumentError("acccumulate does not support the keyword arguments $(keys(nt))")) + end +end """ accumulate!(op, B, A; dims::Integer) @@ -305,9 +330,10 @@ function accumulate!(op, B, A; dims::Integer) end """ - accumulate!(op, y, x::AbstractVector) + accumulate!(op, y, x::AbstractVector; [init]) Cumulative operation `op` on a vector `x`, storing the result in `y`. +You may optionally provide an initial starting value via the keyword argument `init`. See also [`accumulate`](@ref). # Examples @@ -327,10 +353,19 @@ julia> y 6 ``` """ -function accumulate!(op::Op, y, x::AbstractVector) where Op - isempty(x) && return y - v1 = first(x) - _accumulate1!(op, y, v1, x, 1) +function accumulate!(op::Op, y, x::AbstractVector; kw...) where Op + nt = kw.data + if nt isa NamedTuple{()} + isempty(x) && return y + v1 = first(x) + _accumulate1!(op, y, v1, x, 1) + elseif nt isa NamedTuple{(:init,)} + isempty(x) && return y + v1 = op(nt.init, first(x)) + _accumulate1!(op, y, v1, x, 1) + else + throw(ArgumentError("acccumulate! does not support the keyword arguments $(keys(nt))")) + end end @noinline function _accumulate!(op, B, A, R1, ind, R2) @@ -346,39 +381,6 @@ end 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 = promote_op(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, dim::Integer) dim > 0 || throw(ArgumentError("dim must be a positive integer")) inds = LinearIndices(A) diff --git a/base/deprecated.jl b/base/deprecated.jl index 2a7fd0ac3726d..b14dcf68398b6 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -1723,6 +1723,10 @@ end @deprecate mapfoldl(f, op, v0, itr) mapfoldl(f, op, itr; init=v0) @deprecate mapfoldr(f, op, v0, itr) mapfoldr(f, op, itr; init=v0) +# PR #27859 +@deprecate accumulate(op, v0, x::AbstractVector) accumulate(op, x; init=v0) +@deprecate accumulate!(op, y, v0, x::AbstractVector) accumulate!(op, y, x; init=v0) + # END 0.7 deprecations # BEGIN 1.0 deprecations diff --git a/test/arrayops.jl b/test/arrayops.jl index 0b4479181cf68..e9b41f477d73f 100644 --- a/test/arrayops.jl +++ b/test/arrayops.jl @@ -2283,11 +2283,11 @@ end @test accumulate(min, [1 0; 0 1], dims=1) == [1 0; 0 0] @test accumulate(min, [1 0; 0 1], dims=2) == [1 0; 0 0] - @test isa(accumulate(+, Int[]) , Vector{Int}) - @test isa(accumulate(+, 1., Int[]) , Vector{Float64}) - @test accumulate(+, 1, [1,2]) == [2, 4] + @test isa(accumulate(+, Int[]), Vector{Int}) + @test isa(accumulate(+, Int[]; init=1.), Vector{Float64}) + @test accumulate(+, [1,2]; init=1) == [2, 4] arr = randn(4) - @test accumulate(*, 1, arr) ≈ accumulate(*, arr) + @test accumulate(*, arr; init=1) ≈ accumulate(*, arr) N = 5 for arr in [rand(Float64, N), rand(Bool, N), rand(-2:2, N)] @@ -2313,7 +2313,7 @@ end @test accumulate(+, oarr).parent == accumulate(+, arr) @inferred accumulate(+, randn(3)) - @inferred accumulate(+, 1, randn(3)) + @inferred accumulate(+, randn(3); init=1) # asymmetric operation op(x,y) = 2x+y @@ -2321,7 +2321,7 @@ end @test accumulate(op, [10 20 30], dims=2) == [10 op(10, 20) op(op(10, 20), 30)] == [10 40 110] #25506 - @test accumulate((acc, x) -> acc+x[1], 0, [(1,2), (3,4), (5,6)]) == [1, 4, 9] + @test accumulate((acc, x) -> acc+x[1], [(1,2), (3,4), (5,6)]; init=0) == [1, 4, 9] @test accumulate(*, ['a', 'b']) == ["a", "ab"] @inferred accumulate(*, String[]) @test accumulate(*, ['a' 'b'; 'c' 'd'], dims=1) == ["a" "b"; "ac" "bd"]