-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Adjust initialization in maximum and minimum #27845
Conversation
31c67c2
to
cae4be0
Compare
base/reducedim.jl
Outdated
reducedim_init(f, op::typeof(min), A::AbstractArray{T}, region) where {T} = reducedim_initarray0(A, region, f, minimum) | ||
# initialization when computing minima and maxima requires a little care | ||
for (f1, f2, initval) in ((min, max, Inf), (max, min, -Inf)) | ||
function reducedim_init(f, op::typeof(f1), A::AbstractArray, region) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This needs an @eval
with interpolation — I don't think this will work as it stands.
base/reducedim.jl
Outdated
function reducedim_init(f, op::typeof(f1), A::AbstractArray, region) | ||
# First compute the reduce indices. This will throw an ArgumentError | ||
# if any region is invalid | ||
ri = Base.reduced_indices(A, region) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Base.
This seems like a good incremental improvement, but boy does this need a bigger revamp here. It's somewhat nice that only a very limited set of functions are supported right now, because when we go to support arbitrary reduction functions we'll need to change the requirements — we'll need to require two slices along the dimension. |
I'd hope that the arrays initialization code could be cleaned up more generally. It is quite convoluted. Regarding your comment about supporting more reducers then an alternative to using two slices might be that users who happen to have a new Back to the current PR. There is some funny business going on with julia> A = OffsetArray(rand(4,4), (-3,5)); What seems wrong to me is how julia> axes(A)
(Base.Slice(-2:1), Base.Slice(6:9))
julia> Base.reduced_indices(A, 1:2)
(Base.Slice(1:1), Base.Slice(1:1)) Notice that the last slice is not included in Finally, while trying to call collection functions on a Update: Maybe the |
As is often the case with OffsetArrays, we need to choose which aspect of the |
cae4be0
to
a1ac258
Compare
It was a bit more tricky to finish up than expected but I think it works now. I've changed the non- |
return copy(A1) | ||
else | ||
# otherwise use the min/max of the first slice as initial value | ||
v0 = mapreduce(f, $f2, A1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It doesn't seem to be correct to use the min/max of the first slice as the initial value for all slices. I'm probably missing something. (I wish I could have used something simpler than what I did for this at #28027).
BTW, typo below: "intial"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it should be fine. If you are computing the maximum along a dimension then it should be fine to initialize with any value less than or equal to the first element in the slice. The minimum over the first slice will satisfy this, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, I misunderstood "first slice". I thought it referred to the first slice along which reduction is performed. Carry on.
v0 = mapreduce(f, $f2, A1) | ||
|
||
# but NaNs need to be avoided as intial values | ||
v0 = v0 != v0 ? typeof(v0)($initval) : v0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AFAICT the mapreduce
call above will give NaN
whenever one of the values is NaN
. So this code is going to use the fallback initval
even if there are non-NaN
values which could be used. Maybe it would be better to use a custom loop to go over the first slice and skip NaN
values?
Actually, maybe something similar to the mapfirst!
method I had to write at #27845 to skip missing values is needed.
Anyway, a few tests for these corner cases would be good. ;-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is basically a check for floats but tries to be a little more generic. Using the initval
is fine for floats and only floats will probably ever be satisfy the test so I don't think there is an issue here.NaN
@timholy Are you okay with the reductions-on-offset-arrays behavior here? |
Yes, it's quite elegant! Sorry I didn't see this earlier, thanks for tackling it. |
This reverts commit 1859a91.
@@ -3,28 +3,41 @@ | |||
## Functions to compute the reduced shape | |||
|
|||
# for reductions that expand 0 dims to 1 | |||
reduced_index(i::OneTo) = OneTo(1) | |||
reduced_index(i::Slice) = Slice(first(i):first(i)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like simply making this a UnitRange
instead of a Slice
will do the trick — make -C test reduce reduced offsetarray
passes for me locally with that change.
Fixes #27836