Skip to content

Commit

Permalink
Merge pull request #6197 from lindahua/dh/inplacesum
Browse files Browse the repository at this point in the history
Reduction functions with pre-allocated output storage.
  • Loading branch information
lindahua committed Mar 18, 2014
2 parents 5c7e8c2 + 548854c commit 14641d3
Show file tree
Hide file tree
Showing 5 changed files with 94 additions and 30 deletions.
4 changes: 4 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,9 @@ Deprecated or removed

* `read` methods that modify a passed array are now called `read!` ([#5970])

* Reduction functions that accept a pre-allocated output array, including
`sum!`, `prod!`, `maximum!`, `minimum!`, `all!`, `any!` ([#6197])

[#4042]: https://github.com/JuliaLang/julia/issues/4042
[#5164]: https://github.com/JuliaLang/julia/issues/5164
[#4026]: https://github.com/JuliaLang/julia/issues/4026
Expand Down Expand Up @@ -329,6 +332,7 @@ Deprecated or removed
[#5778]: https://github.com/JuliaLang/julia/issues/5778
[#6169]: https://github.com/JuliaLang/julia/issues/6169
[#5970]: https://github.com/JuliaLang/julia/issues/5970
[#6197]: https://github.com/JuliaLang/julia/pull/6197

Julia v0.2.0 Release Notes
==========================
Expand Down
6 changes: 6 additions & 0 deletions base/exports.jl
Original file line number Diff line number Diff line change
Expand Up @@ -529,8 +529,10 @@ export
logspace,
mapslices,
max,
maximum!,
maximum,
min,
minimum!,
minimum,
minmax,
nans,
Expand All @@ -548,6 +550,7 @@ export
permute!,
permutedims,
permutedims!,
prod!,
prod,
promote_shape,
randcycle,
Expand Down Expand Up @@ -581,6 +584,7 @@ export
strides,
sub,
sub2ind,
sum!,
sum,
sum_kbn,
vcat,
Expand Down Expand Up @@ -699,7 +703,9 @@ export
unshift!,

# collections
all!,
all,
any!,
any,
collect,
complement!,
Expand Down
44 changes: 31 additions & 13 deletions base/reducedim.jl
Original file line number Diff line number Diff line change
Expand Up @@ -116,20 +116,38 @@ reduction_init{T}(A::AbstractArray, region, initial::T) = fill!(similar(A,T,redu
### Pre-generated cases
# For performance, these bypass reducedim_cache

all(A::AbstractArray{Bool}, region) = all!(reduction_init(A,region,true), A)
eval(ngenerate(:N, :(typeof(R)), :(all!{N}(R::AbstractArray, A::AbstractArray{Bool,N})), N->gen_reduction_body(N, &)))
any(A::AbstractArray{Bool}, region) = any!(reduction_init(A,region,false), A)
eval(ngenerate(:N, :(typeof(R)), :(any!{N}(R::AbstractArray, A::AbstractArray{Bool,N})), N->gen_reduction_body(N, |)))
function initarray!{T}(a::AbstractArray{T}, v::T, init::Bool)
if init
fill!(a, v)
end
return a
end

eval(ngenerate(:N, :(typeof(R)), :(_all!{N}(R::AbstractArray, A::AbstractArray{Bool,N})), N->gen_reduction_body(N, &)))
all!(r::AbstractArray, A::AbstractArray{Bool}; init::Bool=true) = _all!(initarray!(r, true, init), A)
all(A::AbstractArray{Bool}, region) = _all!(reduction_init(A, region, true), A)

eval(ngenerate(:N, :(typeof(R)), :(_any!{N}(R::AbstractArray, A::AbstractArray{Bool,N})), N->gen_reduction_body(N, |)))
any!(r::AbstractArray, A::AbstractArray{Bool}; init::Bool=true) = _any!(initarray!(r, false, init), A)
any(A::AbstractArray{Bool}, region) = any!(reduction_init(A, region, false), A)

eval(ngenerate(:N, :(typeof(R)), :(_maximum!{T,N}(R::AbstractArray, A::AbstractArray{T,N})), N->gen_reduction_body(N, scalarmax)))
maximum!{R}(r::AbstractArray{R}, A::AbstractArray; init::Bool=true) = _maximum!(initarray!(r, typemin(R), init), A)
maximum{T}(A::AbstractArray{T}, region) =
isempty(A) ? similar(A,reduced_dims0(A,region)) : maximum!(reduction_init(A,region,typemin(T)), A)
eval(ngenerate(:N, :(typeof(R)), :(maximum!{T,N}(R::AbstractArray, A::AbstractArray{T,N})), N->gen_reduction_body(N, scalarmax)))
isempty(A) ? similar(A,reduced_dims0(A,region)) : _maximum!(reduction_init(A, region, typemin(T)), A)

eval(ngenerate(:N, :(typeof(R)), :(_minimum!{T,N}(R::AbstractArray, A::AbstractArray{T,N})), N->gen_reduction_body(N, scalarmin)))
minimum!{R}(r::AbstractArray{R}, A::AbstractArray; init::Bool=true) = _minimum!(initarray!(r, typemax(R), init), A)
minimum{T}(A::AbstractArray{T}, region) =
isempty(A) ? similar(A,reduced_dims0(A,region)) : minimum!(reduction_init(A,region,typemax(T)), A)
eval(ngenerate(:N, :(typeof(R)), :(minimum!{T,N}(R::AbstractArray, A::AbstractArray{T,N})), N->gen_reduction_body(N, scalarmin)))
sum{T}(A::AbstractArray{T}, region) = sum!(reduction_init(A,region,zero(T)), A)
sum(A::AbstractArray{Bool}, region) = sum!(reduction_init(A,region,0), A)
eval(ngenerate(:N, :(typeof(R)), :(sum!{T,N}(R::AbstractArray, A::AbstractArray{T,N})), N->gen_reduction_body(N, +)))
prod{T}(A::AbstractArray{T}, region) = prod!(reduction_init(A,region,one(T)), A)
eval(ngenerate(:N, :(typeof(R)), :(prod!{T,N}(R::AbstractArray, A::AbstractArray{T,N})), N->gen_reduction_body(N, *)))
isempty(A) ? similar(A, reduced_dims0(A, region)) : _minimum!(reduction_init(A, region, typemax(T)), A)

eval(ngenerate(:N, :(typeof(R)), :(_sum!{T,N}(R::AbstractArray, A::AbstractArray{T,N})), N->gen_reduction_body(N, +)))
sum!{R}(r::AbstractArray{R}, A::AbstractArray; init::Bool=true) = _sum!(initarray!(r, zero(R), init), A)
sum{T}(A::AbstractArray{T}, region) = _sum!(reduction_init(A, region, zero(T)+zero(T)), A)

eval(ngenerate(:N, :(typeof(R)), :(_prod!{T,N}(R::AbstractArray, A::AbstractArray{T,N})), N->gen_reduction_body(N, *)))
prod!{R}(r::AbstractArray{R}, A::AbstractArray; init::Bool=true) = _prod!(initarray!(r, one(R), init), A)
prod{T}(A::AbstractArray{T}, region) = _prod!(reduction_init(A, region, one(T)*one(T)), A)

prod(A::AbstractArray{Bool}, region) = error("use all() instead of prod() for boolean arrays")

54 changes: 42 additions & 12 deletions doc/stdlib/base.rst
Original file line number Diff line number Diff line change
Expand Up @@ -554,19 +554,29 @@ Iterable Collections

.. function:: maximum(itr)

Returns the largest element in a collection
Returns the largest element in a collection.

.. function:: maximum(A, dims)

Compute the maximum value of an array over the given dimensions
Compute the maximum value of an array over the given dimensions.

.. function:: maximum!(r, A)

Compute the maximum value of ``A`` over the singleton dimensions of ``r``,
and write results to ``r``.

.. function:: minimum(itr)

Returns the smallest element in a collection
Returns the smallest element in a collection.

.. function:: minimum(A, dims)

Compute the minimum value of an array over the given dimensions
Compute the minimum value of an array over the given dimensions.

.. function:: minimum!(r, A)

Compute the minimum value of ``A`` over the singleton dimensions of ``r``,
and write results to ``r``.

.. function:: extrema(itr)

Expand All @@ -575,56 +585,76 @@ Iterable Collections

.. function:: indmax(itr) -> Integer

Returns the index of the maximum element in a collection
Returns the index of the maximum element in a collection.

.. function:: indmin(itr) -> Integer

Returns the index of the minimum element in a collection
Returns the index of the minimum element in a collection.

.. function:: findmax(itr) -> (x, index)

Returns the maximum element and its index
Returns the maximum element and its index.

.. function:: findmin(itr) -> (x, index)

Returns the minimum element and its index
Returns the minimum element and its index.

.. function:: sum(itr)

Returns the sum of all elements in a collection
Returns the sum of all elements in a collection.

.. function:: sum(A, dims)

Sum elements of an array over the given dimensions.

.. function:: sum!(r, A)

Sum elements of ``A`` over the singleton dimensions of ``r``,
and write results to ``r``.

.. function:: sum(f, itr)

Sum the results of calling function ``f`` on each element of ``itr``.

.. function:: prod(itr)

Returns the product of all elements of a collection
Returns the product of all elements of a collection.

.. function:: prod(A, dims)

Multiply elements of an array over the given dimensions.

.. function:: prod!(r, A)

Multiply elements of ``A`` over the singleton dimensions of ``r``,
and write results to ``r``.

.. function:: any(itr) -> Bool

Test whether any elements of a boolean collection are true
Test whether any elements of a boolean collection are true.

.. function:: any(A, dims)

Test whether any values along the given dimensions of an array are true.

.. function:: any!(r, A)

Test whether any values in ``A`` along the singleton dimensions of ``r`` are true,
and write results to ``r``.

.. function:: all(itr) -> Bool

Test whether all elements of a boolean collection are true
Test whether all elements of a boolean collection are true.

.. function:: all(A, dims)

Test whether all values along the given dimensions of an array are true.

.. function:: all!(r, A)

Test whether all values in ``A`` along the singleton dimensions of ``r`` are true,
and write results to ``r``.

.. function:: count(p, itr) -> Integer

Count the number of elements in ``itr`` for which predicate ``p`` returns true.
Expand Down
16 changes: 11 additions & 5 deletions test/reducedim.jl
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,18 @@ safe_minimum{T}(A::Array{T}, region) = safe_mapslices(minimum, A, region)
Areduc = rand(3, 4, 5, 6)
for region in {
1, 2, 3, 4, 5, (1, 2), (1, 3), (1, 4), (2, 3), (2, 4), (3, 4),
(1, 2, 3), (1, 3, 4), (2, 3, 4), (1, 2, 3, 4)}
(1, 2, 3), (1, 3, 4), (2, 3, 4), (1, 2, 3, 4)}

@test_approx_eq sum(Areduc, region) safe_sum(Areduc, region)
@test_approx_eq prod(Areduc, region) safe_prod(Areduc, region)
@test_approx_eq maximum(Areduc, region) safe_maximum(Areduc, region)
@test_approx_eq minimum(Areduc, region) safe_minimum(Areduc, region)
r = fill(NaN, Base.reduced_dims(size(Areduc), region))
@test_approx_eq sum!(r, Areduc) safe_sum(Areduc, region)
@test_approx_eq prod!(r, Areduc) safe_prod(Areduc, region)
@test_approx_eq maximum!(r, Areduc) safe_maximum(Areduc, region)
@test_approx_eq minimum!(r, Areduc) safe_minimum(Areduc, region)

@test_approx_eq sum(Areduc, region) safe_sum(Areduc, region)
@test_approx_eq prod(Areduc, region) safe_prod(Areduc, region)
@test_approx_eq maximum(Areduc, region) safe_maximum(Areduc, region)
@test_approx_eq minimum(Areduc, region) safe_minimum(Areduc, region)
end

@test reducedim((a,b) -> a|b, [true false; false false], 1, false) == [true false]
Expand Down

0 comments on commit 14641d3

Please sign in to comment.