@@ -1746,41 +1746,52 @@ of `A`.
1746
1746
This method requires Julia 1.2 or later.
1747
1747
"""
1748
1748
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}}
1780
1792
end
1781
- return B
1793
+ map! (f, reducedim_initarray (A,region,undef,T), A1)
1782
1794
end
1783
- extrema! (B, A) = extrema! (identity, B, A)
1784
1795
1785
1796
# Show for pairs() with Cartesian indices. Needs to be here rather than show.jl for bootstrap order
1786
1797
function Base. showarg (io:: IO , r:: Iterators.Pairs{<:Integer, <:Any, <:Any, T} , toplevel) where T <: Union{AbstractVector, Tuple}
0 commit comments