Revision 4954af9c5ee5bb1b5b9172ddbcbac03ca6e151ea authored by Keno Fischer on 01 September 2023, 19:52:14 UTC, committed by GitHub on 01 September 2023, 19:52:14 UTC
The change in #50429 moves around some dispatch boundaries and pushes the allocations in the offsetarrays `maximum!` test over the limit. The implementation of that code is massively type unstable. Somewhat, ironically, the whole original point of that test was to test that the implementation was not type-unstable (#28941), so actually opt our OffsetArrays implementation into the interface that's supposed to guarantee that. If this PR is fine here, I'll submit the same upstream to avoid diverging the implementations too much. Co-authored-by: Jameson Nash <vtjnash@gmail.com>
1 parent a173010
reducedim.jl
# This file is a part of Julia. License is MIT: https://julialang.org/license
using Random
# main tests
# issue #35800
# tested very early since it can be state-dependent
function my_simple_count(pred, g::Vector{T}) where {T}
n::T = zero(T)
for x in g
n += pred(x)
end
return n
end
@test @inferred(mapreduce(x->my_simple_count(!iszero,x), +, [rand(1)]; init = 0.)) == 1.0
function safe_mapslices(op, A, region)
newregion = intersect(region, 1:ndims(A))
return isempty(newregion) ? A : mapslices(op, A, dims = newregion)
end
safe_sum(A::Array{T}, region) where {T} = safe_mapslices(sum, A, region)
safe_prod(A::Array{T}, region) where {T} = safe_mapslices(prod, A, region)
safe_maximum(A::Array{T}, region) where {T} = safe_mapslices(maximum, A, region)
safe_minimum(A::Array{T}, region) where {T} = safe_mapslices(minimum, A, region)
safe_count(A::AbstractArray{T}, region) where {T} = safe_mapslices(count, A, region)
safe_sumabs(A::Array{T}, region) where {T} = safe_mapslices(sum, abs.(A), region)
safe_sumabs2(A::Array{T}, region) where {T} = safe_mapslices(sum, abs2.(A), region)
safe_maxabs(A::Array{T}, region) where {T} = safe_mapslices(maximum, abs.(A), region)
safe_minabs(A::Array{T}, region) where {T} = safe_mapslices(minimum, abs.(A), region)
@testset "test reductions over region: $region" for region in Any[
1, 2, 3, 4, 5, (1, 2), (1, 3), (1, 4), (2, 3), (2, 4), (3, 4),
(1, 2, 3), (1, 3, 4), (2, 3, 4), (1, 2, 3, 4)]
Areduc = rand(3, 4, 5, 6)
Breduc = rand(Bool, 3, 4, 5, 6)
@assert axes(Areduc) == axes(Breduc)
r = fill(NaN, map(length, Base.reduced_indices(axes(Areduc), region)))
@test sum!(r, Areduc) ≈ safe_sum(Areduc, region)
@test prod!(r, Areduc) ≈ safe_prod(Areduc, region)
@test maximum!(r, Areduc) ≈ safe_maximum(Areduc, region)
@test minimum!(r, Areduc) ≈ safe_minimum(Areduc, region)
@test count!(r, Breduc) ≈ safe_count(Breduc, region)
@test sum!(abs, r, Areduc) ≈ safe_sumabs(Areduc, region)
@test sum!(abs2, r, Areduc) ≈ safe_sumabs2(Areduc, region)
@test maximum!(abs, r, Areduc) ≈ safe_maxabs(Areduc, region)
@test minimum!(abs, r, Areduc) ≈ safe_minabs(Areduc, region)
@test count!(!, r, Breduc) ≈ safe_count(.!Breduc, region)
# With init=false
r2 = similar(r)
fill!(r, 1)
@test sum!(r, Areduc, init=false) ≈ safe_sum(Areduc, region) .+ 1
fill!(r, 2.2)
@test prod!(r, Areduc, init=false) ≈ safe_prod(Areduc, region)*2.2
fill!(r, 1.8)
@test maximum!(r, Areduc, init=false) ≈ fill!(r2, 1.8)
fill!(r, -0.2)
@test minimum!(r, Areduc, init=false) ≈ fill!(r2, -0.2)
fill!(r, 1)
@test count!(r, Breduc, init=false) ≈ safe_count(Breduc, region) .+ 1
fill!(r, 8.1)
@test sum!(abs, r, Areduc, init=false) ≈ safe_sumabs(Areduc, region) .+ 8.1
fill!(r, 8.1)
@test sum!(abs2, r, Areduc, init=false) ≈ safe_sumabs2(Areduc, region) .+ 8.1
fill!(r, 1.5)
@test maximum!(abs, r, Areduc, init=false) ≈ fill!(r2, 1.5)
fill!(r, -1.5)
@test minimum!(abs, r, Areduc, init=false) ≈ fill!(r2, -1.5)
fill!(r, 1)
@test count!(!, r, Breduc, init=false) ≈ safe_count(.!Breduc, region) .+ 1
@test @inferred(sum(Areduc, dims=region)) ≈ safe_sum(Areduc, region)
@test @inferred(prod(Areduc, dims=region)) ≈ safe_prod(Areduc, region)
@test @inferred(maximum(Areduc, dims=region)) ≈ safe_maximum(Areduc, region)
@test @inferred(minimum(Areduc, dims=region)) ≈ safe_minimum(Areduc, region)
@test @inferred(count(Breduc, dims=region)) ≈ safe_count(Breduc, region)
@test @inferred(sum(abs, Areduc, dims=region)) ≈ safe_sumabs(Areduc, region)
@test @inferred(sum(abs2, Areduc, dims=region)) ≈ safe_sumabs2(Areduc, region)
@test @inferred(maximum(abs, Areduc, dims=region)) ≈ safe_maxabs(Areduc, region)
@test @inferred(minimum(abs, Areduc, dims=region)) ≈ safe_minabs(Areduc, region)
@test @inferred(count(!, Breduc, dims=region)) ≈ safe_count(.!Breduc, region)
@test isequal(
@inferred(count(Breduc, dims=region, init=0x02)),
safe_count(Breduc, region) .% UInt8 .+ 0x02,
)
@test isequal(
@inferred(count(!, Breduc, dims=region, init=Int16(0))),
safe_count(.!Breduc, region) .% Int16,
)
end
# Combining dims and init
A = Array{Int}(undef, 0, 3)
@test_throws "reducing over an empty collection is not allowed" maximum(A; dims=1)
@test maximum(A; dims=1, init=-1) == reshape([-1,-1,-1], 1, 3)
@test maximum(zeros(0, 2); dims=1, init=-1) == fill(-1, 1, 2)
@test minimum(zeros(0, 2); dims=1, init=1) == ones(1, 2)
@test extrema(zeros(0, 2); dims=1, init=(1, -1)) == fill((1, -1), 1, 2)
# Test reduction along first dimension; this is special-cased for
# size(A, 1) >= 16
Breduc = rand(64, 3)
r = fill(NaN, map(length, Base.reduced_indices(axes(Breduc), 1)))
@test sum!(r, Breduc) ≈ safe_sum(Breduc, 1)
@test sum!(abs, r, Breduc) ≈ safe_sumabs(Breduc, 1)
@test sum!(abs2, r, Breduc) ≈ safe_sumabs2(Breduc, 1)
@test sum(Breduc, dims=1) ≈ safe_sum(Breduc, 1)
@test sum(abs, Breduc, dims=1) ≈ safe_sumabs(Breduc, 1)
@test sum(abs2, Breduc, dims=1) ≈ safe_sumabs2(Breduc, 1)
fill!(r, 4.2)
@test sum!(r, Breduc, init=false) ≈ safe_sum(Breduc, 1) .+ 4.2
fill!(r, -6.3)
@test sum!(abs, r, Breduc, init=false) ≈ safe_sumabs(Breduc, 1) .- 6.3
fill!(r, -1.1)
@test sum!(abs2, r, Breduc, init=false) ≈ safe_sumabs2(Breduc, 1) .- 1.1
# Small arrays with init=false
let A = reshape(1:15, 3, 5)
R = fill(1, 3)
@test sum!(R, A, init=false) == [36,41,46]
R = fill(1, 1, 5)
@test sum!(R, A, init=false) == [7 16 25 34 43]
end
let R = [2]
A = reshape(1:6, 3, 2)
@test prod!(R, A, init=false) == [1440]
# min/max
@test reduce(max, A, dims=1) == [3 6]
@test reduce(min, A, dims=2) == reshape([1,2,3], 3, 1)
end
# Small integers
@test @inferred(sum(Int8[1], dims=1)) == [1]
@test @inferred(sum(UInt8[1], dims=1)) == [1]
# Complex types
@test typeof(@inferred(sum([1.0+1.0im], dims=1))) == Vector{ComplexF64}
@test typeof(@inferred(Base.sum(abs, [1.0+1.0im], dims=1))) == Vector{Float64}
@test typeof(@inferred(Base.sum(abs2, [1.0+1.0im], dims=1))) == Vector{Float64}
@test typeof(@inferred(prod([1.0+1.0im], dims=1))) == Vector{ComplexF64}
@test typeof(@inferred(Base.prod(abs, [1.0+1.0im], dims=1))) == Vector{Float64}
@test typeof(@inferred(Base.prod(abs2, [1.0+1.0im], dims=1))) == Vector{Float64}
@testset "heterogeneously typed arrays" begin
for x in (sum(Union{Float32, Float64}[1.0], dims=1),
prod(Union{Float32, Float64}[1.0], dims=1))
@test x == [1.0]
@test x isa Vector{Float64}
end
x = sum(Real[1.0], dims=1)
@test x == [1.0]
@test x isa Vector{Real}
x = mapreduce(cos, +, Union{Int,Missing}[1, 2], dims=1)
@test x == mapreduce(cos, +, [1, 2], dims=1)
@test x isa Vector{Float64}
end
@test reduce((a,b) -> a|b, [true false; false false], dims=1, init=false) == [true false]
let R = reduce((a,b) -> a+b, [1 2; 3 4], dims=2, init=0.0)
@test eltype(R) == Float64
@test R ≈ [3,7]
end
@test reduce((a,b) -> a+b, [1 2; 3 4], dims=1, init=0) == [4 6]
# inferred return types
@test typeof(@inferred(reduce(+, ones(3,3,3), dims=1, init=0.0))) == Array{Float64, 3}
@testset "empty cases" begin
A = Matrix{Int}(undef, 0,1)
@test sum(A) === 0
@test prod(A) === 1
@test_throws ["reducing over an empty",
"consider supplying `init`"] minimum(A)
@test_throws "consider supplying `init`" maximum(A)
@test isequal(sum(A, dims=1), zeros(Int, 1, 1))
@test isequal(sum(A, dims=2), zeros(Int, 0, 1))
@test isequal(sum(A, dims=(1, 2)), zeros(Int, 1, 1))
@test isequal(sum(A, dims=3), zeros(Int, 0, 1))
@test isequal(prod(A, dims=1), fill(1, 1, 1))
@test isequal(prod(A, dims=2), fill(1, 0, 1))
@test isequal(prod(A, dims=(1, 2)), fill(1, 1, 1))
@test isequal(prod(A, dims=3), fill(1, 0, 1))
for f in (minimum, maximum)
@test_throws "reducing over an empty collection is not allowed" f(A, dims=1)
@test isequal(f(A, dims=2), zeros(Int, 0, 1))
@test_throws "reducing over an empty collection is not allowed" f(A, dims=(1, 2))
@test isequal(f(A, dims=3), zeros(Int, 0, 1))
end
for f in (findmin, findmax)
@test_throws ArgumentError f(A, dims=1)
@test isequal(f(A, dims=2), (zeros(Int, 0, 1), zeros(Int, 0, 1)))
@test_throws ArgumentError f(A, dims=(1, 2))
@test isequal(f(A, dims=3), (zeros(Int, 0, 1), zeros(Int, 0, 1)))
@test_throws ArgumentError f(abs2, A, dims=1)
@test isequal(f(abs2, A, dims=2), (zeros(Int, 0, 1), zeros(Int, 0, 1)))
@test_throws ArgumentError f(abs2, A, dims=(1, 2))
@test isequal(f(abs2, A, dims=3), (zeros(Int, 0, 1), zeros(Int, 0, 1)))
end
end
## findmin/findmax/minimum/maximum
A = [1.0 5.0 6.0;
5.0 2.0 4.0]
for (tup, rval, rind) in [((1,), [1.0 2.0 4.0], [CartesianIndex(1,1) CartesianIndex(2,2) CartesianIndex(2,3)]),
((2,), reshape([1.0,2.0], 2, 1), reshape([CartesianIndex(1,1),CartesianIndex(2,2)], 2, 1)),
((1,2), fill(1.0,1,1),fill(CartesianIndex(1,1),1,1))]
@test findmin(A, dims=tup) == (rval, rind)
@test findmin!(similar(rval), similar(rind), A) == (rval, rind)
@test isequal(minimum(A, dims=tup), rval)
@test isequal(minimum!(similar(rval), A), rval)
@test isequal(minimum!(copy(rval), A, init=false), rval)
end
for (tup, rval, rind) in [((1,), [5.0 5.0 6.0], [CartesianIndex(2,1) CartesianIndex(1,2) CartesianIndex(1,3)]),
((2,), reshape([6.0,5.0], 2, 1), reshape([CartesianIndex(1,3),CartesianIndex(2,1)], 2, 1)),
((1,2), fill(6.0,1,1),fill(CartesianIndex(1,3),1,1))]
@test findmax(A, dims=tup) == (rval, rind)
@test findmax!(similar(rval), similar(rind), A) == (rval, rind)
@test isequal(maximum(A, dims=tup), rval)
@test isequal(maximum!(similar(rval), A), rval)
@test isequal(maximum!(copy(rval), A, init=false), rval)
end
@testset "findmin/findmax transformed arguments, numeric values" begin
A = [1.0 -5.0 -6.0;
-5.0 2.0 4.0]
TA = [((1,), [1.0 2.0 4.0], [CartesianIndex(1,1) CartesianIndex(2,2) CartesianIndex(2,3)]),
((2,), reshape([1.0, 2.0], 2, 1), reshape([CartesianIndex(1,1), CartesianIndex(2,2)], 2, 1)),
((1,2), fill(1.0,1,1), fill(CartesianIndex(1,1),1,1))]
TA2 = [((1,), [1.0 4.0 16.0], [CartesianIndex(1,1) CartesianIndex(2,2) CartesianIndex(2,3)]),
((2,), reshape([1.0, 4.0], 2, 1), reshape([CartesianIndex(1,1), CartesianIndex(2,2)], 2, 1)),
((1,2), fill(1.0,1,1), fill(CartesianIndex(1,1),1,1))]
TAc = [((1,), [0.28366218546322625 -0.4161468365471424 -0.6536436208636119], [CartesianIndex(2,1) CartesianIndex(2,2) CartesianIndex(2,3)]),
((2,), reshape([0.28366218546322625, -0.6536436208636119], 2, 1), reshape([CartesianIndex(1,2), CartesianIndex(2,3)], 2, 1)),
((1,2), fill(-0.6536436208636119,1,1), fill(CartesianIndex(2,3),1,1))]
for (f, At) in ((abs, TA), (abs2, TA2), (cos, TAc))
A′ = map(f, A)
for (tup, rval, rind) in At
(rval′, rind′) = findmin(f, A, dims=tup)
@test all(rval′ .≈ rval)
@test rind′ == rind
@test findmin(f, A, dims=tup) == (rval, rind)
@test (rval′, rind′) == findmin(A′, dims=tup)
end
end
TA = [((1,), [5.0 5.0 6.0], [CartesianIndex(2,1) CartesianIndex(1,2) CartesianIndex(1,3)]),
((2,), reshape([6.0,5.0], 2, 1), reshape([CartesianIndex(1,3), CartesianIndex(2,1)], 2, 1)),
((1,2), fill(6.0,1,1),fill(CartesianIndex(1,3),1,1))]
TA2 = [((1,), [25.0 25.0 36.0], [CartesianIndex(2,1) CartesianIndex(1,2) CartesianIndex(1,3)]),
((2,), reshape([36.0, 25.0], 2, 1), reshape([CartesianIndex(1,3), CartesianIndex(2,1)], 2, 1)),
((1,2), fill(36.0,1,1), fill(CartesianIndex(1,3),1,1))]
TAc = [((1,), [0.5403023058681398 0.28366218546322625 0.960170286650366], [CartesianIndex(1,1) CartesianIndex(1,2) CartesianIndex(1,3)]),
((2,), reshape([0.960170286650366, 0.28366218546322625], 2, 1), reshape([CartesianIndex(1,3), CartesianIndex(2,1)], 2, 1)),
((1,2), fill(0.960170286650366,1,1), fill(CartesianIndex(1,3),1,1))]
for (f, At) in ((abs, TA), (abs2, TA2), (cos, TAc))
A′ = map(f, A)
for (tup, rval, rind) in At
(rval′, rind′) = findmax(f, A, dims=tup)
@test all(rval′ .≈ rval)
@test rind′ == rind
@test findmax(f, A, dims=tup) == (rval, rind)
@test (rval′, rind′) == findmax(A′, dims=tup)
end
end
end
# findmin/findmax function arguments: output type inference
@testset "findmin/findmax output type inference" begin
A = ["1" "22"; "333" "4444"]
for (tup, rval, rind) in [((1,), [1 2], [CartesianIndex(1, 1) CartesianIndex(1, 2)]),
((2,), reshape([1, 3], 2, 1), reshape([CartesianIndex(1, 1), CartesianIndex(2, 1)], 2, 1)),
((1,2), fill(1,1,1), fill(CartesianIndex(1,1),1,1))]
rval′, rind′ = findmin(length, A, dims=tup)
@test (rval, rind) == (rval′, rind′)
@test typeof(rval′) == Matrix{Int}
end
for (tup, rval, rind) in [((1,), [3 4], [CartesianIndex(2, 1) CartesianIndex(2, 2)]),
((2,), reshape([2, 4], 2, 1), reshape([CartesianIndex(1, 2), CartesianIndex(2, 2)], 2, 1)),
((1,2), fill(4,1,1), fill(CartesianIndex(2,2),1,1))]
rval′, rind′ = findmax(length, A, dims=tup)
@test (rval, rind) == (rval′, rind′)
@test typeof(rval) == Matrix{Int}
end
B = [1.5 1.0; 5.5 6.0]
for (tup, rval, rind) in [((1,), [3//2 1//1], [CartesianIndex(1, 1) CartesianIndex(1, 2)]),
((2,), reshape([1//1, 11//2], 2, 1), reshape([CartesianIndex(1, 2), CartesianIndex(2, 1)], 2, 1)),
((1,2), fill(1//1,1,1), fill(CartesianIndex(1,2),1,1))]
rval′, rind′ = findmin(Rational, B, dims=tup)
@test (rval, rind) == (rval′, rind′)
@test typeof(rval) == Matrix{Rational{Int}}
rval′, rind′ = findmin(Rational ∘ abs ∘ complex, B, dims=tup)
@test (rval, rind) == (rval′, rind′)
@test typeof(rval) == Matrix{Rational{Int}}
end
end
@testset "missing in findmin/findmax" begin
B = [1.0 missing NaN;
5.0 NaN missing]
B′ = [1.0 missing -NaN;
-5.0 NaN missing]
for (tup, rval, rind) in [(1, [5.0 missing missing], [CartesianIndex(2, 1) CartesianIndex(1, 2) CartesianIndex(2, 3)]),
(2, [missing; missing], [CartesianIndex(1, 2) CartesianIndex(2, 3)] |> permutedims)]
(rval′, rind′) = findmax(B, dims=tup)
@test all(rval′ .=== rval)
@test all(rind′ .== rind)
@test all(maximum(B, dims=tup) .=== rval)
@test isequal(findmax(abs, B′, dims=tup), (rval′, rind′))
end
for (tup, rval, rind) in [(1, [1.0 missing missing], [CartesianIndex(1, 1) CartesianIndex(1, 2) CartesianIndex(2, 3)]),
(2, [missing; missing], [CartesianIndex(1, 2) CartesianIndex(2, 3)] |> permutedims)]
(rval′, rind′) = findmin(B, dims=tup)
@test all(rval′ .=== rval)
@test all(rind′ .== rind)
@test all(minimum(B, dims=tup) .=== rval)
@test isequal(findmin(abs, B′, dims=tup), (rval′, rind′))
end
end
@testset "reducedim_init min/max unorderable handling" begin
x = Any[1.0, NaN]
y = [1, missing]
for (v, rval1, rval2) in [(x, [NaN], x),
(y, [missing], y),
(Any[1. NaN; 1. 1.], Any[1. NaN], Any[NaN, 1.])]
for f in (minimum, maximum)
@test all(f(v, dims=1) .=== rval1)
@test all(f(v, dims=2) .=== rval2)
end
end
end
#issue #23209
A = [1.0 3.0 6.0;
NaN 2.0 4.0]
for (tup, rval, rind) in [((1,), [NaN 2.0 4.0], [CartesianIndex(2,1) CartesianIndex(2,2) CartesianIndex(2,3)]),
((2,), reshape([1.0, NaN], 2, 1), reshape([CartesianIndex(1,1),CartesianIndex(2,1)], 2, 1)),
((1,2), fill(NaN,1,1),fill(CartesianIndex(2,1),1,1))]
@test isequal(findmin(A, dims=tup), (rval, rind))
@test isequal(findmin(abs, A, dims=tup), (rval, rind))
@test isequal(findmin!(similar(rval), similar(rind), A), (rval, rind))
@test isequal(minimum(A, dims=tup), rval)
@test isequal(minimum!(similar(rval), A), rval)
@test isequal(minimum!(copy(rval), A, init=false), rval)
@test isequal(Base.reducedim!(min, copy(rval), A), rval)
end
for (tup, rval, rind) in [((1,), [NaN 3.0 6.0], [CartesianIndex(2,1) CartesianIndex(1,2) CartesianIndex(1,3)]),
((2,), reshape([6.0, NaN], 2, 1), reshape([CartesianIndex(1,3),CartesianIndex(2,1)], 2, 1)),
((1,2), fill(NaN,1,1),fill(CartesianIndex(2,1),1,1))]
@test isequal(findmax(A, dims=tup), (rval, rind))
@test isequal(findmax(abs, A, dims=tup), (rval, rind))
@test isequal(findmax!(similar(rval), similar(rind), A), (rval, rind))
@test isequal(maximum(A, dims=tup), rval)
@test isequal(maximum!(similar(rval), A), rval)
@test isequal(maximum!(copy(rval), A, init=false), rval)
@test isequal(Base.reducedim!(max, copy(rval), A), rval)
end
# issue #28320
@testset "reducedim issue with abstract complex arrays" begin
let A = Complex[1.5 0.5]
@test mapreduce(abs2, +, A, dims=2) == reshape([2.5], 1, 1)
@test sum(abs2, A, dims=2) == reshape([2.5], 1, 1)
@test prod(abs2, A, dims=2) == reshape([0.5625], 1, 1)
@test maximum(abs2, A, dims=2) == reshape([2.25], 1, 1)
@test minimum(abs2, A, dims=2) == reshape([0.25], 1, 1)
@test findmin(abs2, A, dims=2) == (fill(0.25, 1, 1), fill(CartesianIndex(1, 2), 1, 1))
@test findmax(abs2, A, dims=2) == (fill(2.25, 1, 1), fill(CartesianIndex(1, 1), 1, 1))
end
end
@testset "NaN in findmin/findmax/minimum/maximum" begin
A = [1.0 NaN 6.0;
NaN 2.0 4.0]
A′ = [-1.0 NaN -6.0;
NaN -2.0 4.0]
for (tup, rval, rind) in [((1,), [NaN NaN 4.0], [CartesianIndex(2,1) CartesianIndex(1,2) CartesianIndex(2,3)]),
((2,), reshape([NaN, NaN], 2, 1), reshape([CartesianIndex(1,2),CartesianIndex(2,1)], 2, 1)),
((1,2), fill(NaN,1,1),fill(CartesianIndex(2,1),1,1))]
@test isequal(findmin(A, dims=tup), (rval, rind))
@test isequal(findmin(abs, A′, dims=tup), (rval, rind))
@test isequal(findmin!(similar(rval), similar(rind), A), (rval, rind))
@test isequal(minimum(A, dims=tup), rval)
@test isequal(minimum!(similar(rval), A), rval)
@test isequal(minimum!(copy(rval), A, init=false), rval)
end
for (tup, rval, rind) in [((1,), [NaN NaN 6.0], [CartesianIndex(2,1) CartesianIndex(1,2) CartesianIndex(1,3)]),
((2,), reshape([NaN, NaN], 2, 1), reshape([CartesianIndex(1,2),CartesianIndex(2,1)], 2, 1)),
((1,2), fill(NaN,1,1),fill(CartesianIndex(2,1),1,1))]
@test isequal(findmax(A, dims=tup), (rval, rind))
@test isequal(findmax(abs, A′, dims=tup), (rval, rind))
@test isequal(findmax!(similar(rval), similar(rind), A), (rval, rind))
@test isequal(maximum(A, dims=tup), rval)
@test isequal(maximum!(similar(rval), A), rval)
@test isequal(maximum!(copy(rval), A, init=false), rval)
end
end
@testset "+/-Inf in findmin/findmax/minimum/maximum" begin
A = [Inf -Inf Inf -Inf;
Inf Inf -Inf -Inf]
A′ = [1 0 1 0;
1 1 0 0]
for (tup, rval, rind) in [((1,), [Inf -Inf -Inf -Inf], [CartesianIndex(1,1) CartesianIndex(1,2) CartesianIndex(2,3) CartesianIndex(1,4)]),
((2,), reshape([-Inf -Inf], 2, 1), reshape([CartesianIndex(1,2),CartesianIndex(2,3)], 2, 1)),
((1,2), fill(-Inf,1,1),fill(CartesianIndex(1,2),1,1))]
@test isequal(findmin(A, dims=tup), (rval, rind))
@test isequal(findmin(x -> x == 1 ? Inf : -Inf, A′, dims=tup), (rval, rind))
@test isequal(findmin!(similar(rval), similar(rind), A), (rval, rind))
@test isequal(minimum(A, dims=tup), rval)
@test isequal(minimum!(similar(rval), A), rval)
@test isequal(minimum!(copy(rval), A, init=false), rval)
end
for (tup, rval, rind) in [((1,), [Inf Inf Inf -Inf], [CartesianIndex(1,1) CartesianIndex(2,2) CartesianIndex(1,3) CartesianIndex(1,4)]),
((2,), reshape([Inf Inf], 2, 1), reshape([CartesianIndex(1,1),CartesianIndex(2,1)], 2, 1)),
((1,2), fill(Inf,1,1),fill(CartesianIndex(1,1),1,1))]
@test isequal(findmax(A, dims=tup), (rval, rind))
@test isequal(findmax(x -> x == 1 ? Inf : -Inf, A′, dims=tup), (rval, rind))
@test isequal(findmax!(similar(rval), similar(rind), A), (rval, rind))
@test isequal(maximum(A, dims=tup), rval)
@test isequal(maximum!(similar(rval), A), rval)
@test isequal(maximum!(copy(rval), A, init=false), rval)
end
end
@testset "BigInt in findmin/findmax/minimum/maximum" begin
A = [BigInt(10)]
A′ = [BigInt(1)]
for (tup, rval, rind) in [((2,), [BigInt(10)], [1])]
@test isequal(findmin(A, dims=tup), (rval, rind))
@test isequal(findmin(x -> 10^x, A′, dims=tup), (rval, rind))
@test isequal(findmin!(similar(rval), similar(rind), A), (rval, rind))
@test isequal(minimum(A, dims=tup), rval)
@test isequal(minimum!(similar(rval), A), rval)
@test isequal(minimum!(copy(rval), A, init=false), rval)
end
for (tup, rval, rind) in [((2,), [BigInt(10)], [1])]
@test isequal(findmax(A, dims=tup), (rval, rind))
@test isequal(findmax(x -> 10^x, A′, dims=tup), (rval, rind))
@test isequal(findmax!(similar(rval), similar(rind), A), (rval, rind))
@test isequal(maximum(A, dims=tup), rval)
@test isequal(maximum!(similar(rval), A), rval)
@test isequal(maximum!(copy(rval), A, init=false), rval)
end
A = [BigInt(-10)]
for (tup, rval, rind) in [((2,), [BigInt(-10)], [1])]
@test isequal(findmin(A, dims=tup), (rval, rind))
@test isequal(findmin(x -> -(x + 20), A, dims=tup), (rval, rind))
@test isequal(findmin!(similar(rval), similar(rind), A), (rval, rind))
@test isequal(minimum(A, dims=tup), rval)
@test isequal(minimum!(similar(rval), A), rval)
@test isequal(minimum!(copy(rval), A, init=false), rval)
end
for (tup, rval, rind) in [((2,), [BigInt(-10)], [1])]
@test isequal(findmax(A, dims=tup), (rval, rind))
@test isequal(findmax(x -> -(x + 20), A, dims=tup), (rval, rind))
@test isequal(findmax!(similar(rval), similar(rind), A), (rval, rind))
@test isequal(maximum(A, dims=tup), rval)
@test isequal(maximum!(similar(rval), A), rval)
@test isequal(maximum!(copy(rval), A, init=false), rval)
end
A = [BigInt(10) BigInt(-10)]
A′ = [BigInt(1) BigInt(10)]
for (tup, rval, rind) in [((2,), reshape([BigInt(-10)], 1, 1), reshape([CartesianIndex(1,2)], 1, 1))]
@test isequal(findmin(A, dims=tup), (rval, rind))
@test isequal(findmin(x -> x == 1 ? 10^x : x - 20, A′, dims=tup), (rval, rind))
@test isequal(findmin!(similar(rval), similar(rind), A), (rval, rind))
@test isequal(minimum(A, dims=tup), rval)
@test isequal(minimum!(similar(rval), A), rval)
@test isequal(minimum!(copy(rval), A, init=false), rval)
end
for (tup, rval, rind) in [((2,), reshape([BigInt(10)], 1, 1), reshape([CartesianIndex(1,1)], 1, 1))]
@test isequal(findmax(A, dims=tup), (rval, rind))
@test isequal(findmax(x -> x == 1 ? 10^x : x - 20, A′, dims=tup), (rval, rind))
@test isequal(findmax!(similar(rval), similar(rind), A), (rval, rind))
@test isequal(maximum(A, dims=tup), rval)
@test isequal(maximum!(similar(rval), A), rval)
@test isequal(maximum!(copy(rval), A, init=false), rval)
end
end
@testset "String in findmin/findmax/minimum/maximum" begin
A = ["a", "b"]
for (tup, rval, rind) in [((1,), ["a"], [1])]
@test isequal(findmin(A, dims=tup), (rval, rind))
@test isequal(findmin(x -> (x^2)[1:1], A, dims=tup), (rval, rind))
@test isequal(findmin!(similar(rval), similar(rind), A), (rval, rind))
@test isequal(minimum(A, dims=tup), rval)
@test isequal(minimum!(similar(rval), A), rval)
@test isequal(minimum!(copy(rval), A, init=false), rval)
end
for (tup, rval, rind) in [((1,), ["b"], [2])]
@test isequal(findmax(A, dims=tup), (rval, rind))
@test isequal(findmax(x -> (x^2)[1:1], A, dims=tup), (rval, rind))
@test isequal(findmax!(similar(rval), similar(rind), A), (rval, rind))
@test isequal(maximum(A, dims=tup), rval)
@test isequal(maximum!(similar(rval), A), rval)
@test isequal(maximum!(copy(rval), A, init=false), rval)
end
end
# issue #6672
@test sum(Real[1 2 3; 4 5.3 7.1], dims=2) == reshape([6, 16.4], 2, 1)
@test sum(Any[1 2;3 4], dims=1) == [4 6]
@test sum(Vector{Int}[[1,2],[4,3]], dims=1)[1] == [5,5]
@testset "Issue #10461. region=$region" for region in Any[-1, 0, (-1, 2), [0, 1], (1,-2,3), [0 1;
2 3], "hello"]
Areduc = rand(3, 4, 5, 6)
@test_throws ArgumentError sum(Areduc, dims=region)
@test_throws ArgumentError prod(Areduc, dims=region)
@test_throws ArgumentError maximum(Areduc, dims=region)
@test_throws ArgumentError minimum(Areduc, dims=region)
@test_throws ArgumentError sum(abs, Areduc, dims=region)
@test_throws ArgumentError sum(abs2, Areduc, dims=region)
@test_throws ArgumentError maximum(abs, Areduc, dims=region)
@test_throws ArgumentError minimum(abs, Areduc, dims=region)
end
# issue #26488
@testset "don't map over initial values not provided" begin
@test sum(x->x+1, [1], dims=1)[1] === sum(x->x+1, [1]) === 2
@test prod(x->x+1, [1], dims=1)[1] === prod(x->x+1, [1]) === 2
@test mapreduce(x->x+1, +, [1], dims=1)[1] === mapreduce(x->x+1, +, [1]) === 2
@test mapreduce(x->x+1, *, [1], dims=1)[1] === mapreduce(x->x+1, *, [1]) === 2
@test mapreduce(!, &, [false], dims=1)[1] === mapreduce(!, &, [false]) === true
@test mapreduce(!, |, [true], dims=1)[1] === mapreduce(!, |, [true]) === false
@test mapreduce(x->1/x, max, [1], dims=1)[1] === mapreduce(x->1/x, max, [1]) === 1.0
@test mapreduce(x->-1/x, min, [1], dims=1)[1] === mapreduce(x->-1/x, min, [1]) === -1.0
end
# check type of result
@testset "type of sum(::Array{$T}" for T in [UInt8, Int8, Int32, Int64, BigInt]
result = sum(T[1 2 3; 4 5 6; 7 8 9], dims=2)
@test result == hcat([6, 15, 24])
@test eltype(result) === (T <: Base.SmallSigned ? Int :
T <: Base.SmallUnsigned ? UInt :
T)
end
@testset "argmin/argmax" begin
B = reshape(3^3:-1:1, (3, 3, 3))
@test B[argmax(B, dims=[2, 3])] == @inferred(maximum(B, dims=[2, 3]))
@test B[argmin(B, dims=[2, 3])] == @inferred(minimum(B, dims=[2, 3]))
end
@testset "in-place reductions with mismatched dimensionalities" begin
B = reshape(1:24, 4, 3, 2)
for R in (fill(0, 4), fill(0, 4, 1), fill(0, 4, 1, 1))
@test @inferred(maximum!(R, B)) == reshape(21:24, size(R))
@test @inferred(minimum!(R, B)) == reshape(1:4, size(R))
@test @inferred(extrema!(fill((0,0), size(R)), B)) == reshape(tuple.(1:4, 21:24), size(R))
end
for R in (fill(0, 1, 3), fill(0, 1, 3, 1))
@test @inferred(maximum!(R, B)) == reshape(16:4:24, size(R))
@test @inferred(minimum!(R, B)) == reshape(1:4:9, size(R))
@test @inferred(extrema!(fill((0,0), size(R)), B)) == reshape(tuple.(1:4:9, 16:4:24), size(R))
end
for (ini, f!) in zip((0,0,(0,0)), (maximum!, minimum!, extrema!))
@test_throws DimensionMismatch f!(fill(ini, 4, 1, 1, 1), B)
@test_throws DimensionMismatch f!(fill(ini, 1, 3, 1, 1), B)
@test_throws DimensionMismatch f!(fill(ini, 1, 1, 2, 1), B)
end
end
function unordered_test_for_extrema(a; dims_test = ((), 1, 2, (1,2), 3))
for dims in dims_test
vext = extrema(a; dims)
vmin, vmax = minimum(a; dims), maximum(a; dims)
@test isequal(extrema!(copy(vext), a), vext)
@test all(x -> isequal(x[1], x[2:3]), zip(vext,vmin,vmax))
end
end
@testset "0.0,-0.0 test for extrema with dims" begin
@test extrema([-0.0;0.0], dims = 1)[1] === (-0.0,0.0)
@test tuple(extrema([-0.0;0.0], dims = 2)...) === ((-0.0, -0.0), (0.0, 0.0))
end
@testset "NaN/missing test for extrema with dims #43599" begin
for sz = (3, 10, 100)
for T in (Int, Float64, BigFloat)
Aₘ = Matrix{Union{T, Missing}}(rand(-sz:sz, sz, sz))
Aₘ[rand(1:sz*sz, sz)] .= missing
unordered_test_for_extrema(Aₘ)
if T <: AbstractFloat
Aₙ = map(i -> ismissing(i) ? T(NaN) : i, Aₘ)
unordered_test_for_extrema(Aₙ)
p = rand(1:sz*sz, sz)
Aₘ[p] .= NaN
unordered_test_for_extrema(Aₘ)
end
end
end
end
@test_broken minimum([missing;BigInt(1)], dims = 1)
@test_broken maximum([missing;BigInt(1)], dims = 1)
@test_broken extrema([missing;BigInt(1)], dims = 1)
# issue #26709
@testset "dimensional reduce with custom non-bitstype types" begin
struct Variable
name::Symbol
end
struct AffExpr
vars::Vector{Variable}
end
Base.zero(::Union{Variable, Type{Variable}, AffExpr}) = AffExpr(Variable[])
Base.:+(v::Variable, w::Variable) = AffExpr([v, w])
Base.:+(aff::AffExpr, v::Variable) = AffExpr([aff.vars; v])
Base.:+(aff1::AffExpr, aff2::AffExpr) = AffExpr([aff1.vars; aff2.vars])
Base.:(==)(a::Variable, b::Variable) = a.name == b.name
Base.:(==)(a::AffExpr, b::AffExpr) = a.vars == b.vars
@test sum([Variable(:x), Variable(:y)], dims=1) == [AffExpr([Variable(:x), Variable(:y)])]
end
# count
@testset "count: throw on non-bool types" begin
@test_throws TypeError count([1], dims=1)
@test_throws TypeError count!([1], [1])
end
@test @inferred(count(false:true, dims=:, init=0x0004)) === 0x0005
@test @inferred(count(isodd, reshape(1:9, 3, 3), dims=:, init=Int128(0))) === Int128(5)
@testset "reduced_index for BigInt (issue #39995)" begin
for T in [Int8, Int16, Int32, Int64, Int128, BigInt]
r = T(1):T(2)
ax = axes(r, 1)
axred = Base.reduced_index(ax)
@test axred == Base.OneTo(1)
@test typeof(axred) === typeof(ax)
r_red = reduce(+, r, dims = 1)
@test eltype(r_red) == T
@test r_red == [3]
end
end
@testset "type stability (issue #43461)" begin
@test (@inferred maximum(Float64, reshape(1:4,2,:); dims = 2)) == reshape([3,4],2,1)
end
@testset "Min/Max initialization test" begin
A = Vector{Union{Missing,Int}}(1:4)
A[2] = missing
@test_broken @inferred(minimum(exp, A; dims = 1))[1] === missing
@test_broken @inferred(maximum(exp, A; dims = 1))[1] === missing
@test_broken @inferred(extrema(exp, A; dims = 1))[1] === (missing, missing)
end
![swh spinner](/static/img/swh-spinner.gif)
Computing file changes ...