Skip to content

Commit d7b4a77

Browse files
committed
Define reducedim_initarray(A, region, ::UndefInitializer, ::Type) for easier initialization
also simplify min/max init Replace `UndefInitializer` with `_InitialValue`
1 parent a03cec4 commit d7b4a77

File tree

2 files changed

+29
-36
lines changed

2 files changed

+29
-36
lines changed

base/reducedim.jl

Lines changed: 27 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ end
9191
# reducedim_initarray is called by
9292
reducedim_initarray(A::AbstractArrayOrBroadcasted, region, init, ::Type{R}) where {R} = fill!(similar(A,R,reduced_indices(A,region)), init)
9393
reducedim_initarray(A::AbstractArrayOrBroadcasted, region, init::T) where {T} = reducedim_initarray(A, region, init, T)
94-
94+
reducedim_initarray(A::AbstractArrayOrBroadcasted, region, ::_InitialValue, ::Type{R}) where {R} = similar(A,R,reduced_indices(A,region))
9595
# TODO: better way to handle reducedim initialization
9696
#
9797
# The current scheme is basically following Steven G. Johnson's original implementation
@@ -125,46 +125,38 @@ function _reducedim_init(f, op, fv, fop, A, region)
125125
end
126126

127127
# initialization when computing minima and maxima requires a little care
128-
for (f1, f2, initval, typeextreme) in ((:min, :max, :Inf, :typemax), (:max, :min, :(-Inf), :typemin))
129-
@eval function reducedim_init(f, op::typeof($f1), A::AbstractArray, region)
130-
# First compute the reduce indices. This will throw an ArgumentError
131-
# if any region is invalid
132-
ri = reduced_indices(A, region)
128+
function reducedim_init(f::F, ::Union{typeof(min),typeof(max)}, A::AbstractArray, region) where {F}
129+
# First compute the reduce indices. This will throw an ArgumentError
130+
# if any region is invalid
131+
ri = reduced_indices(A, region)
133132

134-
# Next, throw if reduction is over a region with length zero
135-
any(i -> isempty(axes(A, i)), region) && _empty_reduce_error()
133+
# Next, throw if reduction is over a region with length zero
134+
any(i -> isempty(axes(A, i)), region) && _empty_reduce_error()
136135

137-
# Make a view of the first slice of the region
138-
A1 = view(A, ri...)
136+
# Make a view of the first slice of the region
137+
A1 = view(A, ri...)
139138

140-
if isempty(A1)
141-
# If the slice is empty just return non-view version as the initial array
142-
return map(f, A1)
143-
else
144-
# otherwise use the min/max of the first slice as initial value
145-
v0 = mapreduce(f, $f2, A1)
146-
147-
T = _realtype(f, promote_union(eltype(A)))
148-
Tr = v0 isa T ? T : typeof(v0)
149-
150-
# but NaNs and missing need to be avoided as initial values
151-
if v0 isa Number && isnan(v0)
152-
# v0 is NaN
153-
v0 = oftype(v0, $initval)
154-
elseif isunordered(v0)
155-
# v0 is missing or a third-party unordered value
156-
Tnm = nonmissingtype(Tr)
157-
# TODO: Some types, like BigInt, don't support typemin/typemax.
158-
# So a Matrix{Union{BigInt, Missing}} can still error here.
159-
v0 = $typeextreme(Tnm)
160-
end
161-
# v0 may have changed type.
162-
Tr = v0 isa T ? T : typeof(v0)
139+
# calculate the output type
140+
T = promote_typejoin_union(_return_type(f, Tuple{eltype(A)}))
163141

164-
return reducedim_initarray(A, region, v0, Tr)
165-
end
142+
map!(f, reducedim_initarray(A,region,_InitialValue(),T), A1)
143+
end
144+
145+
function reducedim_init(f::ExtremaMap, ::typeof(_extrema_rf), A::AbstractArray, region)
146+
ri = reduced_indices(A, region)
147+
any(i -> isempty(axes(A, i)), region) && _empty_reduce_error()
148+
A1 = view(A, ri...)
149+
IT = eltype(A)
150+
if missing isa IT
151+
RT = promote_typejoin_union(_return_type(f.f, Tuple{nonmissingtype(IT)}))
152+
T = Union{Tuple{RT,RT},Tuple{Missing,Missing}}
153+
else
154+
RT = promote_typejoin_union(_return_type(f.f, Tuple{IT}))
155+
T = Union{Tuple{RT,RT}}
166156
end
157+
map!(f, reducedim_initarray(A,region,_InitialValue(),T), A1)
167158
end
159+
168160
reducedim_init(f::Union{typeof(abs),typeof(abs2)}, op::typeof(max), A::AbstractArray{T}, region) where {T} =
169161
reducedim_initarray(A, region, zero(f(zero(T))), _realtype(f, T))
170162

stdlib/LinearAlgebra/src/special.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
# Diagonal/Bidiagonal/Tridiagonal/SymTridiagonal matrix. However, reducedim should
88
# yield a dense vector to increase performance.
99
Base.reducedim_initarray(A::Union{Diagonal,Bidiagonal,Tridiagonal,SymTridiagonal}, region, init, ::Type{R}) where {R} = fill(convert(R, init), Base.reduced_indices(A,region))
10-
10+
Base.reducedim_initarray(A::Union{Diagonal,Bidiagonal,Tridiagonal,SymTridiagonal}, region, ::Base._InitialValue, ::Type{R}) where {R} =
11+
Array{R}(undef, Base.to_shape(Base.reduced_indices(A, region)))
1112

1213
# Interconversion between special matrix types
1314

0 commit comments

Comments
 (0)