@@ -1746,41 +1746,80 @@ 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)
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
+ function _extrema_op (x:: NTuple{2,T} , y:: NTuple{2,T} ) where {T<: IEEEFloat }
1754
+ (x1, x2), (y1, y2) = x, y
1755
+ z1 = ifelse (isnan (x1)| isnan (y1), x1- y1, ifelse (signbit (x1- y1), x1, y1))
1756
+ z2 = ifelse (isnan (x1)| isnan (y1), x1- y1, ifelse (signbit (x2- y2), y2, x2))
1757
+ z1, z2
1758
+ end
1759
+ # avoid allocation for BigFloat
1760
+ function _extrema_op (x:: NTuple{2,T} , y:: NTuple{2,T} ) where {T<: AbstractFloat }
1761
+ (x1, x2), (y1, y2) = x, y
1762
+ isnan (x1) && return x
1763
+ isnan (y1) && return y
1764
+ z1 = x1 < y1 || signbit (x1) > signbit (y1) ? x1 : y1
1765
+ z2 = x2 < y2 || signbit (x2) > signbit (y2) ? y2 : x2
1766
+ z1, z2
1767
+ end
1768
+
1769
+ function reducedim_init (f, :: typeof (_extrema_op), A:: AbstractArray , region)
1770
+ ri = reduced_indices (A, region)
1771
+ any (i -> isempty (axes (A, i)), region) && _empty_reduce_error ()
1772
+ A1 = view (A, ri... )
1773
+ IT = eltype (A)
1774
+ if missing isa IT
1775
+ RT = promote_typejoin_union (_return_type (i -> f (i)[1 ], Tuple{nonmissingtype (IT)}))
1776
+ T = Union{Tuple{RT,RT},Tuple{Missing,Missing}}
1777
+ else
1778
+ RT = promote_typejoin_union (_return_type (i -> f (i)[1 ], Tuple{IT}))
1779
+ T = Union{Tuple{RT,RT}}
1780
+ end
1781
+ map! (f, reducedim_initarray (A,region,undef,T), A1)
1782
+ end
1783
+
1784
+ function mapreduce_impl (f, op:: typeof (_extrema_op),
1785
+ A:: AbstractArrayOrBroadcasted , fi:: Int , la:: Int )
1786
+ @inline elf (i) = @inbounds f (A[i])[1 ]
1787
+ Eltype = _return_type (elf, Tuple{Int})
1788
+ Eltype <: IEEEFloat ||
1789
+ return invoke (mapreduce_impl,Tuple{Any,Any,typeof (A),Int,Int},f,op,A,fi,la)
1790
+ ini, i = elf (fi), fi
1791
+ v = ini, ini
1792
+ if la - i >= 8
1793
+ @noinline firstnan (temp) = (x= temp[findfirst (isnan,temp)]; ((x, x), fi))
1794
+ function simd_kernal (:: Val{N} , ini, i) where {N}
1795
+ vmins = ntuple (Returns (ini), Val (N))
1796
+ vmaxs = vmins
1797
+ index = ntuple (identity, Val (N))
1798
+ for _ in 1 : (la- i)÷ N
1799
+ temp = map (elf, i .+ index)
1800
+ mapreduce (isnan,| ,temp) && return firstnan (temp)
1801
+ vmins = map (_fast (min), vmins, temp)
1802
+ vmaxs = map (_fast (max), vmaxs, temp)
1803
+ i += N
1804
+ end
1805
+ (reduce (_fast (min), vmins), reduce (_fast (max), vmaxs)), i
1779
1806
end
1807
+ isnan (ini) && return v
1808
+ if la - i < 64
1809
+ v, i = simd_kernal (Val (4 ), ini, i)
1810
+ elseif la - i < 256
1811
+ v, i = simd_kernal (Val (8 ), ini, i)
1812
+ else
1813
+ v, i = simd_kernal (Val (64 ÷ sizeof (Eltype)), ini, i)
1814
+ end
1815
+ i == fi && return v
1780
1816
end
1781
- return B
1817
+ while i < la
1818
+ v′ = elf (i+= 1 )
1819
+ v = _extrema_op (v, (v′,v′))
1820
+ end
1821
+ return v
1782
1822
end
1783
- extrema! (B, A) = extrema! (identity, B, A)
1784
1823
1785
1824
# Show for pairs() with Cartesian indices. Needs to be here rather than show.jl for bootstrap order
1786
1825
function Base. showarg (io:: IO , r:: Iterators.Pairs{<:Integer, <:Any, <:Any, T} , toplevel) where T <: Union{AbstractVector, Tuple}
0 commit comments