Conversation
2553673 to
e120c61
Compare
|
This has the benefit of being able to get rid of the funny composition behaviour to get the widening behaviour of |
e120c61 to
937b954
Compare
|
Okay, I think this should be ready. I tried to avoid touching the |
|
@TotalVerb You did the last deep dive into this code: would you mind having a quick look over it? |
base/reduce.jl
Outdated
| reduce_single(op, x) = x | ||
| reduce_single(::typeof(+), x::Bool) = Int(x) | ||
|
|
||
| reduce_single(::typeof(add_sum), x) = reduce_single(+, x) |
There was a problem hiding this comment.
Although adding + zero(x) for add and * one(x) was ugly, I think it is more general. There are theoretically other types than Bool that are not the type of their "additive monoid" or "multiplicative monoid". Char is now one of these for multiplication. Of course, Irrational is one of these, but that doesn't support zero either. The extra add or multiply should be easily optimized by LLVM for all types except already-slow ones like BigInt, anyway.
There was a problem hiding this comment.
zero(pi) and one('a') both currently throw errors, so they won't work either.
There was a problem hiding this comment.
Well, let's leave it as is then. one('a') should theoretically return "" though.
There was a problem hiding this comment.
Yeah, I'll add a fix for that.
| overflow results in -128. | ||
| """ | ||
| sum(f::Callable, a) = mapreduce(promote_sys_size_add ∘ f, +, a) | ||
| sum(f, a) = mapreduce(f, add_sum, a) |
There was a problem hiding this comment.
Good catch: it looks like this Callable is not necessary for avoiding ambiguity any more. The same change should apply for prod.
| reducedim_initarray(A, region, real(zero(eltype(A)))) | ||
| global reducedim_init(f::Union{typeof(abs),typeof(abs2)}, op::typeof(*), A::T, region) = | ||
| reducedim_initarray(A, region, real(one(eltype(A)))) | ||
| global reducedim_init(f, op::Union{typeof(+),typeof(add_sum)}, A::T, region) = |
There was a problem hiding this comment.
I think it's not safe to generalize this to f ∉ [identity, abs, abs2] because we need the reduction operator to be type stable over whatever is produced by the f used for mapreduce. Nevertheless, it's a nice simplification to have, but I think we will need to continue hardcoding the list of acceptable map functions.
There was a problem hiding this comment.
Won't mapreduce_single(f, op, zero(eltype(A))) should handle that?
There was a problem hiding this comment.
In general, for some choices of f, this assumes that mr_single(f, +, 0) + f(0), etc., will be of the same concrete type of mr_single(f, +, 0), which one can design f to make it fail (for example, in the case of *, if f return a dimensionful quantity, like 1m, which has different concrete type than 1m^2). This seems to be where _reducedim_init is more general and guards against. Of course it is also possible to thwart _reducedim_init with badly behaving f, so 😕.
There was a problem hiding this comment.
Although I'm not actually sure _reducedim_init does what it should in these type unstable cases, so maybe it's best to leave cleanup of _reducedim_init to later.
| prod(a) = mapreduce(identity, mul_prod, a) | ||
|
|
||
| ## maximum & minimum | ||
|
|
There was a problem hiding this comment.
It might be worth changing the f(a1) in the below function to mapreduce_single(f, op, a1) for consistency, although no reasonable types I can think of should have a lattice structure outside the type itself.
| @@ -133,7 +141,7 @@ function mapfoldr(f, op, itr) | |||
| if isempty(itr) | |||
There was a problem hiding this comment.
Unrelated comment, which can be done as part of this PR or in a later one: Since we have #24187 Iterators.Reverse now, I think we can write these mapfoldr functions generically. As it stands it only works with arrays, and this generalization may allow it to work with arbitrary reversible iterators.
|
How about calling this |
Because it deals with singleton case, in the same way that Perhaps it would be best to change it to |
|
I would say go with |
eae9a54 to
982c833
Compare
|
Okay done. One question: should |
|
Also, I didn't touch |
|
LGTM. Rebase? |
Since the demise of `r_promote` in #22825, there is now a type-instability in `mapreduce` if the operator does not give an element of the same type as the input. This arose during my implementation of Kahan summation using a reduction operator, see: JuliaMath/KahanSummation.jl#7 This adds a `mapreduce_single` function which defines what the result should be in these cases.
The promotion machinery for reduction in sum/prod was changed in JuliaLang/julia#25051. This updates the use.
Since the demise of
r_promotein #22825, there is now a type-instability inmapreduceif the operator does not give an element of the same type as the input. This arose during my implementation of Kahan summation using a reduction operator, see: JuliaMath/KahanSummation.jl#7This adds a
mapreduce_singlefunction which defines what the result should be in these cases.