From 81ed49eafbc4ec2b6e862889bc556014e8412071 Mon Sep 17 00:00:00 2001 From: Michael Abbott <32575566+mcabbott@users.noreply.github.com> Date: Sun, 24 Oct 2021 15:11:08 -0400 Subject: [PATCH] See also & docstrings for `foldl`, `accumulate` (#42019) Co-authored-by: Daniel Karrasch Co-authored-by: Jameson Nash --- base/accumulate.jl | 151 +++++++++++++++++++-------------------------- base/iterators.jl | 16 ++--- base/reduce.jl | 5 ++ 3 files changed, 79 insertions(+), 93 deletions(-) diff --git a/base/accumulate.jl b/base/accumulate.jl index 6f0b6e7d05ba3..663bd850695a8 100644 --- a/base/accumulate.jl +++ b/base/accumulate.jl @@ -116,35 +116,29 @@ end """ cumsum(itr) -Cumulative sum an iterator. 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). +Cumulative sum of an iterator. + +See also [`accumulate`](@ref) to apply functions other than `+`. !!! compat "Julia 1.5" `cumsum` on a non-array iterator requires at least Julia 1.5. # Examples ```jldoctest -julia> cumsum([1, 1, 1]) +julia> cumsum(1:3) 3-element Vector{Int64}: 1 - 2 3 + 6 + +julia> cumsum((true, false, true, false, true)) +(1, 1, 2, 2, 3) -julia> cumsum([fill(1, 2) for i in 1:3]) +julia> cumsum(fill(1, 2) for i in 1:3) 3-element Vector{Vector{Int64}}: [1, 1] [2, 2] [3, 3] - -julia> cumsum((1, 1, 1)) -(1, 2, 3) - -julia> cumsum(x^2 for x in 1:3) -3-element Vector{Int64}: - 1 - 5 - 14 ``` """ cumsum(x::AbstractVector) = cumsum(x, dims=1) @@ -177,10 +171,7 @@ to control the precision of the output (e.g. to avoid overflow). # Examples ```jldoctest -julia> a = [1 2 3; 4 5 6] -2×3 Matrix{Int64}: - 1 2 3 - 4 5 6 +julia> a = Int8[1 2 3; 4 5 6]; julia> cumprod(a, dims=1) 2×3 Matrix{Int64}: @@ -200,9 +191,7 @@ end """ cumprod(itr) -Cumulative product of an iterator. 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). +Cumulative product of an iterator. See also [`cumprod!`](@ref), [`accumulate`](@ref), [`cumsum`](@ref). @@ -217,20 +206,16 @@ julia> cumprod(fill(1//2, 3)) 1//4 1//8 -julia> cumprod([fill(1//3, 2, 2) for i in 1:3]) -3-element Vector{Matrix{Rational{Int64}}}: - [1//3 1//3; 1//3 1//3] - [2//9 2//9; 2//9 2//9] - [4//27 4//27; 4//27 4//27] +julia> cumprod((1, 2, 1, 3, 1)) +(1, 2, 2, 6, 6) -julia> cumprod((1, 2, 1)) -(1, 2, 2) - -julia> cumprod(x^2 for x in 1:3) -3-element Vector{Int64}: - 1 - 4 - 36 +julia> cumprod("julia") +5-element Vector{String}: + "j" + "ju" + "jul" + "juli" + "julia" ``` """ cumprod(x::AbstractVector) = cumprod(x, dims=1) @@ -243,8 +228,11 @@ cumprod(itr) = accumulate(mul_prod, itr) Cumulative operation `op` along the dimension `dims` of `A` (providing `dims` is optional for vectors). An initial value `init` may optionally be provided by a keyword argument. 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) +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). For a lazy version, see +[`Iterators.accumulate`](@ref). !!! compat "Julia 1.5" `accumulate` on a non-array iterator requires at least Julia 1.5. @@ -257,35 +245,28 @@ julia> accumulate(+, [1,2,3]) 3 6 -julia> accumulate(*, [1,2,3]) -3-element Vector{Int64}: - 1 - 2 - 6 +julia> accumulate(min, (1, -2, 3, -4, 5), init=0) +(0, -2, -2, -4, -4) -julia> accumulate(+, [1,2,3]; init=100) -3-element Vector{Int64}: - 101 - 103 - 106 +julia> accumulate(/, (2, 4, Inf), init=100) +(50.0, 12.5, 0.0) -julia> accumulate(min, [1,2,-1]; init=0) -3-element Vector{Int64}: - 0 - 0 - -1 - -julia> accumulate(+, fill(1, 3, 3), dims=1) -3×3 Matrix{Int64}: - 1 1 1 - 2 2 2 - 3 3 3 - -julia> accumulate(+, fill(1, 3, 3), dims=2) -3×3 Matrix{Int64}: - 1 2 3 - 1 2 3 - 1 2 3 +julia> accumulate(=>, i^2 for i in 1:3) +3-element Vector{Any}: + 1 + 1 => 4 + (1 => 4) => 9 + +julia> accumulate(+, fill(1, 3, 4)) +3×4 Matrix{Int64}: + 1 4 7 10 + 2 5 8 11 + 3 6 9 12 + +julia> accumulate(+, fill(1, 2, 5), dims=2, init=100.0) +2×5 Matrix{Float64}: + 101.0 102.0 103.0 104.0 105.0 + 101.0 102.0 103.0 104.0 105.0 ``` """ function accumulate(op, A; dims::Union{Nothing,Integer}=nothing, kw...) @@ -318,41 +299,39 @@ end Cumulative operation `op` on `A` along the dimension `dims`, storing the result in `B`. Providing `dims` is optional for vectors. If the keyword argument `init` is given, its -value is used to instantiate the accumulation. See also [`accumulate`](@ref). +value is used to instantiate the accumulation. + +See also [`accumulate`](@ref), [`cumsum!`](@ref), [`cumprod!`](@ref). # Examples ```jldoctest julia> x = [1, 0, 2, 0, 3]; -julia> y = [0, 0, 0, 0, 0]; +julia> y = rand(5); julia> accumulate!(+, y, x); julia> y -5-element Vector{Int64}: - 1 - 1 - 3 - 3 - 6 +5-element Vector{Float64}: + 1.0 + 1.0 + 3.0 + 3.0 + 6.0 -julia> A = [1 2; 3 4]; +julia> A = [1 2 3; 4 5 6]; -julia> B = [0 0; 0 0]; +julia> B = similar(A); -julia> accumulate!(-, B, A, dims=1); - -julia> B -2×2 Matrix{Int64}: - 1 2 - -2 -2 - -julia> accumulate!(-, B, A, dims=2); +julia> accumulate!(-, B, A, dims=1) +2×3 Matrix{Int64}: + 1 2 3 + -3 -3 -3 -julia> B -2×2 Matrix{Int64}: - 1 -1 - 3 -1 +julia> accumulate!(*, B, A, dims=2, init=10) +2×3 Matrix{Int64}: + 10 20 60 + 40 200 1200 ``` """ function accumulate!(op, B, A; dims::Union{Integer, Nothing} = nothing, kw...) diff --git a/base/iterators.jl b/base/iterators.jl index 176c66c591849..c76f8b8d4c3a0 100644 --- a/base/iterators.jl +++ b/base/iterators.jl @@ -480,20 +480,22 @@ This is effectively a lazy version of [`Base.accumulate`](@ref). # Examples ```jldoctest -julia> f = Iterators.accumulate(+, [1,2,3,4]); +julia> a = Iterators.accumulate(+, [1,2,3,4]); -julia> foreach(println, f) +julia> foreach(println, a) 1 3 6 10 -julia> f = Iterators.accumulate(+, [1,2,3]; init = 100); +julia> b = Iterators.accumulate(/, (2, 5, 2, 5); init = 100); -julia> foreach(println, f) -101 -103 -106 +julia> collect(b) +4-element Vector{Float64}: + 50.0 + 10.0 + 5.0 + 1.0 ``` """ accumulate(f, itr; init = Base._InitialValue()) = Accumulate(f, itr, init) diff --git a/base/reduce.jl b/base/reduce.jl index 59e6aeb117cfa..735bd2a0cc9b7 100644 --- a/base/reduce.jl +++ b/base/reduce.jl @@ -168,6 +168,8 @@ Like [`reduce`](@ref), but with guaranteed left associativity. If provided, the argument `init` will be used exactly once. In general, it will be necessary to provide `init` to work with empty collections. +See also [`mapfoldl`](@ref), [`foldr`](@ref), [`accumulate`](@ref). + # Examples ```jldoctest julia> foldl(=>, 1:4) @@ -175,6 +177,9 @@ julia> foldl(=>, 1:4) julia> foldl(=>, 1:4; init=0) (((0 => 1) => 2) => 3) => 4 + +julia> accumulate(=>, (1,2,3,4)) +(1, 1 => 2, (1 => 2) => 3, ((1 => 2) => 3) => 4) ``` """ foldl(op, itr; kw...) = mapfoldl(identity, op, itr; kw...)