Skip to content

Commit 1fcb6d9

Browse files
committed
implement extrema with mapreduce machinery
Update multidimensional.jl
1 parent c15b9da commit 1fcb6d9

File tree

1 file changed

+44
-33
lines changed

1 file changed

+44
-33
lines changed

base/multidimensional.jl

Lines changed: 44 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1746,41 +1746,52 @@ of `A`.
17461746
This method requires Julia 1.2 or later.
17471747
"""
17481748
extrema(f, A::AbstractArray; dims=:) = _extrema_dims(f, A, dims)
1749-
1750-
_extrema_dims(f, A::AbstractArray, ::Colon) = _extrema_itr(f, A)
1751-
1752-
function _extrema_dims(f, A::AbstractArray, dims)
1753-
sz = size(A)
1754-
for d in dims
1755-
sz = setindex(sz, 1, d)
1756-
end
1757-
T = promote_op(f, eltype(A))
1758-
B = Array{Tuple{T,T}}(undef, sz...)
1759-
return extrema!(f, B, A)
1760-
end
1761-
1762-
@noinline function extrema!(f, B, A)
1763-
require_one_based_indexing(B, A)
1764-
sA = size(A)
1765-
sB = size(B)
1766-
for I in CartesianIndices(sB)
1767-
fAI = f(A[I])
1768-
B[I] = (fAI, fAI)
1769-
end
1770-
Bmax = CartesianIndex(sB)
1771-
@inbounds @simd for I in CartesianIndices(sA)
1772-
J = min(Bmax,I)
1773-
BJ = B[J]
1774-
fAI = f(A[I])
1775-
if fAI < BJ[1]
1776-
B[J] = (fAI, BJ[2])
1777-
elseif fAI > BJ[2]
1778-
B[J] = (BJ[1], fAI)
1779-
end
1749+
_extrema_dims(f, A::AbstractArray, dims) = mapreduce(x -> (fx = f(x); (fx, fx)), _extrema_op, A; dims)
1750+
extrema!(B, A) = extrema!(identity, B, A)
1751+
extrema!(f, B, A) = mapreduce!(x -> (fx = f(x); (fx, fx)), _extrema_op, B, A)
1752+
_extrema_op((a, b), (c, d)) = min(a, c), max(b, d)
1753+
# TODO: fuse this with min/max
1754+
_isless(x::T, y::T) where {T<:Union{Float32,Float64}}= signbit(x - y)
1755+
_isless(x::T, y::T) where {T<:AbstractFloat}= (x < y) | (signbit(x) > signbit(y))
1756+
function _extrema_op(x::NTuple{2,T}, y::NTuple{2,T}) where {T<:AbstractFloat}
1757+
(x1, x2), (y1, y2) = x, y
1758+
z1 = ifelse(isnan(x1) | ~isnan(y1) & _isless(x1, y1), x1, y1)
1759+
z2 = ifelse(isnan(x1) | ~isnan(y1) & _isless(y2, x2), x2, y2)
1760+
z1, z2
1761+
end
1762+
function mapreduce_impl(f, ::typeof(_extrema_op), A::AbstractArrayOrBroadcasted, fi::Int, la::Int)
1763+
@inline elf(i) = @inbounds f(A[i])
1764+
Eltype = _return_type(elf, Tuple{Int})
1765+
Eltype <: NTuple{2,AbstractFloat} ||
1766+
return invoke(mapreduce_impl,Tuple{Any,Any,AbstractArrayOrBroadcasted,Int,Int},f,_extrema_op,A,fi,la)
1767+
v1 = v2 = v3 = v4 = Eltype((Inf,-Inf))
1768+
iter = fi:4:la-4
1769+
for i in iter
1770+
v1 = _extrema_op(v1, elf(i))
1771+
v2 = _extrema_op(v2, elf(i+1))
1772+
v3 = _extrema_op(v3, elf(i+2))
1773+
v4 = _extrema_op(v4, elf(i+3))
1774+
end
1775+
v = _extrema_op(_extrema_op(v1, v2), _extrema_op(v3, v4))
1776+
for i in last(iter)+4:la
1777+
v = _extrema_op(v, elf(i))
1778+
end
1779+
v
1780+
end
1781+
function reducedim_init(f, ::typeof(_extrema_op), A::AbstractArray, region)
1782+
ri = reduced_indices(A, region)
1783+
any(i -> isempty(axes(A, i)), region) && _empty_reduce_error()
1784+
A1 = view(A, ri...)
1785+
IT = eltype(A)
1786+
if missing isa IT
1787+
RT = promote_typejoin_union(_return_type(i -> f(i)[1], Tuple{nonmissingtype(IT)}))
1788+
T = Union{Tuple{RT,RT},Tuple{Missing,Missing}}
1789+
else
1790+
RT = promote_typejoin_union(_return_type(i -> f(i)[1], Tuple{IT}))
1791+
T = Union{Tuple{RT,RT}}
17801792
end
1781-
return B
1793+
map!(f, reducedim_initarray(A,region,undef,T), A1)
17821794
end
1783-
extrema!(B, A) = extrema!(identity, B, A)
17841795

17851796
# Show for pairs() with Cartesian indices. Needs to be here rather than show.jl for bootstrap order
17861797
function Base.showarg(io::IO, r::Iterators.Pairs{<:Integer, <:Any, <:Any, T}, toplevel) where T <: Union{AbstractVector, Tuple}

0 commit comments

Comments
 (0)