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