@@ -124,45 +124,31 @@ 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
- 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)
132
-
133
- # Next, throw if reduction is over a region with length zero
134
- any (i -> isempty (axes (A, i)), region) && _empty_reduce_error ()
135
-
136
- # Make a view of the first slice of the region
137
- A1 = view (A, ri... )
138
-
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)
162
-
163
- return reducedim_initarray (A, region, v0, Tr)
164
- end
127
+ function reducedim_init (f:: F , op:: 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)
131
+
132
+ # Next, throw if reduction is over a region with length zero
133
+ any (i -> isempty (axes (A, i)), region) && _empty_reduce_error ()
134
+
135
+ # Make a view of the first slice of the region
136
+ A1 = view (A, ri... )
137
+
138
+ # Then we try to derive the container's eltype.
139
+ T = _return_type (f, Tuple{eltype (A)})
140
+ if isempty (A) || (isconcretetype (nonmissingtype (T)) && T === _return_type (op, Tuple{T,T}))
141
+ # Trust the inference result only when:
142
+ # 1.`nonmissingtype(T)` is concrete. And `T`'s `min`/`max` is well defined.
143
+ # 2. `A1` is empty.
144
+ return map! (f, reducedim_initarray (A,region,_InitialValue (),T), A1)
165
145
end
146
+ # Otherwise, we'd better not rely on inference.
147
+ v0 = mapreduce (f, op, A1) # 1. Try to reduce A1
148
+ T = _realtype (f, promote_union (eltype (A))) # 2. A possible wrong guess.
149
+ Tr = v0 isa T ? T : typeof (v0) # 3. If T is wrong. Use typeof(v0) instead.
150
+ # Note: `Tr` still might be wrong, but this can't be truely resolved except we reduce `A`.
151
+ return map! (f, reducedim_initarray (A,region,_InitialValue (),Tr), A1)
166
152
end
167
153
168
154
reducedim_init (f:: Union{typeof(abs),typeof(abs2)} , op:: typeof (max), A:: AbstractArray{T} , region) where {T} =
0 commit comments