|
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 |
| - |
| 94 | +reducedim_initarray(A::AbstractArrayOrBroadcasted, region, ::_InitialValue, ::Type{R}) where {R} = similar(A,R,reduced_indices(A,region)) |
95 | 95 | # TODO: better way to handle reducedim initialization
|
96 | 96 | #
|
97 | 97 | # 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)
|
125 | 125 | end
|
126 | 126 |
|
127 | 127 | # 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) |
133 | 132 |
|
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() |
136 | 135 |
|
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...) |
139 | 138 |
|
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)})) |
163 | 141 |
|
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}} |
166 | 156 | end
|
| 157 | + map!(f, reducedim_initarray(A,region,_InitialValue(),T), A1) |
167 | 158 | end
|
| 159 | + |
168 | 160 | reducedim_init(f::Union{typeof(abs),typeof(abs2)}, op::typeof(max), A::AbstractArray{T}, region) where {T} =
|
169 | 161 | reducedim_initarray(A, region, zero(f(zero(T))), _realtype(f, T))
|
170 | 162 |
|
|
0 commit comments