@@ -124,36 +124,45 @@ function _reducedim_init(f, op, fv, fop, A, region)
124
124
end
125
125
126
126
# initialization when computing minima and maxima requires a little care
127
- function reducedim_init (f:: F , :: Union{typeof(min),typeof(max)} , A:: AbstractArray , region) where {F}
128
- # First compute the reduce indices. This will throw an ArgumentError
129
- # if any region is invalid
130
- ri = reduced_indices (A, region)
127
+ for (f1, f2, initval, typeextreme) in ((:min , :max , :Inf , :typemax ), (:max , :min , :(- Inf ), :typemin ))
128
+ @eval function reducedim_init (f, op:: typeof ($ f1), A:: AbstractArray , region)
129
+ # First compute the reduce indices. This will throw an ArgumentError
130
+ # if any region is invalid
131
+ ri = reduced_indices (A, region)
131
132
132
- # Next, throw if reduction is over a region with length zero
133
- 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 ()
134
135
135
- # Make a view of the first slice of the region
136
- A1 = view (A, ri... )
136
+ # Make a view of the first slice of the region
137
+ A1 = view (A, ri... )
137
138
138
- # calculate the output type
139
- T = promote_typejoin_union (_return_type (f, Tuple{eltype (A)}))
140
-
141
- map! (f, reducedim_initarray (A,region,_InitialValue (),T), A1)
142
- end
139
+ if isempty (A1)
140
+ # If the slice is empty just return non-view version as the initial array
141
+ return copy (A1)
142
+ else
143
+ # otherwise use the min/max of the first slice as initial value
144
+ v0 = mapreduce (f, $ f2, A1)
145
+
146
+ T = _realtype (f, promote_union (eltype (A)))
147
+ Tr = v0 isa T ? T : typeof (v0)
148
+
149
+ # but NaNs and missing need to be avoided as initial values
150
+ if (v0 == v0) === false
151
+ # v0 is NaN
152
+ v0 = $ initval
153
+ elseif isunordered (v0)
154
+ # v0 is missing or a third-party unordered value
155
+ Tnm = nonmissingtype (Tr)
156
+ # TODO : Some types, like BigInt, don't support typemin/typemax.
157
+ # So a Matrix{Union{BigInt, Missing}} can still error here.
158
+ v0 = $ typeextreme (Tnm)
159
+ end
160
+ # v0 may have changed type.
161
+ Tr = v0 isa T ? T : typeof (v0)
143
162
144
- function reducedim_init (f:: ExtremaMap , :: typeof (_extrema_rf), A:: AbstractArray , region)
145
- ri = reduced_indices (A, region)
146
- any (i -> isempty (axes (A, i)), region) && _empty_reduce_error ()
147
- A1 = view (A, ri... )
148
- IT = eltype (A)
149
- if missing isa IT
150
- RT = promote_typejoin_union (_return_type (f. f, Tuple{nonmissingtype (IT)}))
151
- T = Union{Tuple{RT,RT},Tuple{Missing,Missing}}
152
- else
153
- RT = promote_typejoin_union (_return_type (f. f, Tuple{IT}))
154
- T = Union{Tuple{RT,RT}}
163
+ return reducedim_initarray (A, region, v0, Tr)
164
+ end
155
165
end
156
- map! (f, reducedim_initarray (A,region,_InitialValue (),T), A1)
157
166
end
158
167
159
168
reducedim_init (f:: Union{typeof(abs),typeof(abs2)} , op:: typeof (max), A:: AbstractArray{T} , region) where {T} =
0 commit comments