Skip to content

Commit 208560b

Browse files
mbaumanLilith HafnerLilithHafner
authored
Dimensional any and all reduce with Boolean operations (#58185)
and not bitwise ones. Specifically, they are now reductions using these operators: ```julia and_all(x, y) = (x && y)::Bool or_any(x, y) = (x || y)::Bool # As a performance optimization, avoid runtime branches: and_all(x::Bool, y::Bool) = (x & y)::Bool or_any(x::Bool, y::Bool) = (x | y)::Bool ``` Fixes half of #45562. --------- Co-authored-by: Lilith Hafner <Lilith.Hafner@gmail.com> Co-authored-by: Lilith Orion Hafner <lilithhafner@gmail.com>
1 parent 1aeea19 commit 208560b

File tree

3 files changed

+43
-10
lines changed

3 files changed

+43
-10
lines changed

base/reduce.jl

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,12 @@ mul_prod(x::BitSignedSmall, y::BitSignedSmall) = Int(x) * Int(y)
2929
mul_prod(x::BitUnsignedSmall, y::BitUnsignedSmall) = UInt(x) * UInt(y)
3030
mul_prod(x::Real, y::Real)::Real = x * y
3131

32+
and_all(x, y) = (x && y)::Bool
33+
or_any(x, y) = (x || y)::Bool
34+
# As a performance optimization, avoid runtime branches:
35+
and_all(x::Bool, y::Bool) = (x & y)::Bool
36+
or_any(x::Bool, y::Bool) = (x | y)::Bool
37+
3238
## foldl && mapfoldl
3339

3440
function mapfoldl_impl(f::F, op::OP, nt, itr) where {F,OP}
@@ -338,6 +344,8 @@ reduce_empty(::typeof(*), ::Type{T}) where {T} = one(T)
338344
reduce_empty(::typeof(*), ::Type{<:AbstractChar}) = ""
339345
reduce_empty(::typeof(&), ::Type{Bool}) = true
340346
reduce_empty(::typeof(|), ::Type{Bool}) = false
347+
reduce_empty(::typeof(and_all), ::Type{T}) where {T} = true
348+
reduce_empty(::typeof(or_any), ::Type{T}) where {T} = false
341349

342350
reduce_empty(::typeof(add_sum), ::Type{T}) where {T} = reduce_empty(+, T)
343351
reduce_empty(::typeof(add_sum), ::Type{T}) where {T<:BitSignedSmall} = zero(Int)

base/reducedim.jl

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ end
4545
initarray!(a::AbstractArray{T}, f, ::Union{typeof(min),typeof(max),typeof(_extrema_rf)},
4646
init::Bool, src::AbstractArray) where {T} = (init && mapfirst!(f, a, src); a)
4747

48-
for (Op, initval) in ((:(typeof(&)), true), (:(typeof(|)), false))
48+
for (Op, initval) in ((:(typeof(and_all)), true), (:(typeof(or_any)), false))
4949
@eval initarray!(a::AbstractArray, ::Any, ::$(Op), init::Bool, src::AbstractArray) = (init && fill!(a, $initval); a)
5050
end
5151

@@ -173,6 +173,10 @@ end
173173
reducedim_init(f::Union{typeof(abs),typeof(abs2)}, op::typeof(max), A::AbstractArray{T}, region) where {T} =
174174
reducedim_initarray(A, region, zero(f(zero(T))), _realtype(f, T))
175175

176+
reducedim_init(f, op::typeof(and_all), A::AbstractArrayOrBroadcasted, region) = reducedim_initarray(A, region, true)
177+
reducedim_init(f, op::typeof(or_any), A::AbstractArrayOrBroadcasted, region) = reducedim_initarray(A, region, false)
178+
179+
# These definitions are wrong in general; Cf. JuliaLang/julia#45562
176180
reducedim_init(f, op::typeof(&), A::AbstractArrayOrBroadcasted, region) = reducedim_initarray(A, region, true)
177181
reducedim_init(f, op::typeof(|), A::AbstractArrayOrBroadcasted, region) = reducedim_initarray(A, region, false)
178182

@@ -883,13 +887,13 @@ julia> A = [true false; true false]
883887
1 0
884888
1 0
885889
886-
julia> all!([1; 1], A)
887-
2-element Vector{Int64}:
890+
julia> all!(Bool[1; 1], A)
891+
2-element Vector{Bool}:
888892
0
889893
0
890894
891-
julia> all!([1 1], A)
892-
1×2 Matrix{Int64}:
895+
julia> all!(Bool[1 1], A)
896+
1×2 Matrix{Bool}:
893897
1 0
894898
```
895899
"""
@@ -958,13 +962,13 @@ julia> A = [true false; true false]
958962
1 0
959963
1 0
960964
961-
julia> any!([1; 1], A)
962-
2-element Vector{Int64}:
965+
julia> any!(Bool[1; 1], A)
966+
2-element Vector{Bool}:
963967
1
964968
1
965969
966-
julia> any!([1 1], A)
967-
1×2 Matrix{Int64}:
970+
julia> any!(Bool[1 1], A)
971+
1×2 Matrix{Bool}:
968972
1 0
969973
```
970974
"""
@@ -994,7 +998,7 @@ _all(a, ::Colon) = _all(identity, a, :)
994998

995999
for (fname, op) in [(:sum, :add_sum), (:prod, :mul_prod),
9961000
(:maximum, :max), (:minimum, :min),
997-
(:all, :&), (:any, :|),
1001+
(:all, :and_all), (:any, :or_any),
9981002
(:extrema, :_extrema_rf)]
9991003
fname! = Symbol(fname, '!')
10001004
_fname = Symbol('_', fname)

test/reduce.jl

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -681,6 +681,27 @@ end
681681
end
682682
end
683683

684+
@testset "issue #45562" begin
685+
@test all([true, true, true], dims = 1) == [true]
686+
@test any([true, true, true], dims = 1) == [true]
687+
@test_throws TypeError all([3, 3, 3], dims = 1)
688+
@test_throws TypeError any([3, 3, 3], dims = 1)
689+
@test_throws TypeError all(Any[true, 3, 3], dims = 1)
690+
@test_throws TypeError any(Any[false, 3, 3], dims = 1)
691+
@test_throws TypeError all([1, 1, 1], dims = 1)
692+
@test_throws TypeError any([0, 0, 0], dims = 1)
693+
@test_throws TypeError all!([false], [3, 3, 3])
694+
@test_throws TypeError any!([false], [3, 3, 3])
695+
@test_throws TypeError all!([false], Any[true, 3, 3])
696+
@test_throws TypeError any!([false], Any[false, 3, 3])
697+
@test_throws TypeError all!([false], [1, 1, 1])
698+
@test_throws TypeError any!([false], [0, 0, 0])
699+
@test reduce(|, Bool[]) == false
700+
@test reduce(&, Bool[]) == true
701+
@test reduce(|, Bool[], dims=1) == [false]
702+
@test reduce(&, Bool[], dims=1) == [true]
703+
end
704+
684705
# issue #45748
685706
@testset "foldl's stability for nested Iterators" begin
686707
a = Iterators.flatten((1:3, 1:3))

0 commit comments

Comments
 (0)