|
1 | 1 | using StaticArrays, Test
|
| 2 | +using Statistics: Statistics, median, median!, middle |
2 | 3 |
|
3 | 4 | @testset "sort" begin
|
4 | 5 |
|
@@ -30,4 +31,80 @@ using StaticArrays, Test
|
30 | 31 | @test sortperm(SA[1, 1, 1, 0]) == SA[4, 1, 2, 3]
|
31 | 32 | end
|
32 | 33 |
|
| 34 | + @testset "median" begin |
| 35 | + @test_throws ArgumentError median(SA[]) |
| 36 | + @test ismissing(median(SA[1, missing])) |
| 37 | + @test isnan(median(SA[1., NaN])) |
| 38 | + |
| 39 | + @testset for T in (Int, Float64) |
| 40 | + for N in (1, 2, 3, 10, 20, 30) |
| 41 | + v = rand(SVector{N,T}) |
| 42 | + mref = median(Vector(v)) |
| 43 | + |
| 44 | + @test @inferred(median(v) == mref) |
| 45 | + end |
| 46 | + end |
| 47 | + |
| 48 | + # Tests based on upstream `Statistics.jl`. |
| 49 | + # https://github.com/JuliaStats/Statistics.jl/blob/d49c2bf4f81e1efb4980a35fe39c815ef8396297/test/runtests.jl#L31-L92 |
| 50 | + @test median(SA[1.]) === 1. |
| 51 | + @test median(SA[1.,3]) === 2. |
| 52 | + @test median(SA[1.,3,2]) === 2. |
| 53 | + |
| 54 | + @test median(SA[1,3,2]) === 2.0 |
| 55 | + @test median(SA[1,3,2,4]) === 2.5 |
| 56 | + |
| 57 | + @test median(SA[0.0,Inf]) == Inf |
| 58 | + @test median(SA[0.0,-Inf]) == -Inf |
| 59 | + @test median(SA[0.,Inf,-Inf]) == 0.0 |
| 60 | + @test median(SA[1.,-1.,Inf,-Inf]) == 0.0 |
| 61 | + @test isnan(median(SA[-Inf,Inf])) |
| 62 | + |
| 63 | + X = SA[2 3 1 -1; 7 4 5 -4] |
| 64 | + @test all(median(X, dims=2) .== SA[1.5, 4.5]) |
| 65 | + @test all(median(X, dims=1) .== SA[4.5 3.5 3.0 -2.5]) |
| 66 | + @test X == SA[2 3 1 -1; 7 4 5 -4] # issue #17153 |
| 67 | + |
| 68 | + @test_throws ArgumentError median(SA[]) |
| 69 | + @test isnan(median(SA[NaN])) |
| 70 | + @test isnan(median(SA[0.0,NaN])) |
| 71 | + @test isnan(median(SA[NaN,0.0])) |
| 72 | + @test isnan(median(SA[NaN,0.0,1.0])) |
| 73 | + @test isnan(median(SA{Any}[NaN,0.0,1.0])) |
| 74 | + @test isequal(median(SA[NaN 0.0; 1.2 4.5], dims=2), reshape(SA[NaN; 2.85], 2, 1)) |
| 75 | + |
| 76 | + # the specific NaN value is propagated from the input |
| 77 | + @test median(SA[NaN]) === NaN |
| 78 | + @test median(SA[0.0,NaN]) === NaN |
| 79 | + @test median(SA[0.0,NaN,NaN]) === NaN |
| 80 | + @test median(SA[-NaN]) === -NaN |
| 81 | + @test median(SA[0.0,-NaN]) === -NaN |
| 82 | + @test median(SA[0.0,-NaN,-NaN]) === -NaN |
| 83 | + |
| 84 | + @test ismissing(median(SA[1, missing])) |
| 85 | + @test ismissing(median(SA[1, 2, missing])) |
| 86 | + @test ismissing(median(SA[NaN, 2.0, missing])) |
| 87 | + @test ismissing(median(SA[NaN, missing])) |
| 88 | + @test ismissing(median(SA[missing, NaN])) |
| 89 | + @test ismissing(median(SA{Any}[missing, 2.0, 3.0, 4.0, NaN])) |
| 90 | + @test median(skipmissing(SA[1, missing, 2])) === 1.5 |
| 91 | + |
| 92 | + @test median!(Base.copymutable(SA[1 2 3 4])) == 2.5 |
| 93 | + @test median!(Base.copymutable(SA[1 2; 3 4])) == 2.5 |
| 94 | + |
| 95 | + @test @inferred(median(SA{Float16}[1, 2, NaN])) === Float16(NaN) |
| 96 | + @test @inferred(median(SA{Float16}[1, 2, 3])) === Float16(2) |
| 97 | + @test @inferred(median(SA{Float32}[1, 2, NaN])) === NaN32 |
| 98 | + @test @inferred(median(SA{Float32}[1, 2, 3])) === 2.0f0 |
| 99 | + |
| 100 | + # custom type implementing minimal interface |
| 101 | + struct A |
| 102 | + x |
| 103 | + end |
| 104 | + Statistics.middle(x::A, y::A) = A(middle(x.x, y.x)) |
| 105 | + Base.isless(x::A, y::A) = isless(x.x, y.x) |
| 106 | + @test median(SA[A(1), A(2)]) === A(1.5) |
| 107 | + @test median(SA{Any}[A(1), A(2)]) === A(1.5) |
| 108 | + end |
| 109 | + |
33 | 110 | end
|
0 commit comments