From b0b62df68c8d50fe8cc2d0f11ab6ee1a3802b709 Mon Sep 17 00:00:00 2001 From: Joel Dahne Date: Tue, 8 Aug 2023 11:24:23 +0200 Subject: [PATCH] Cleanup of minmax.jl Adds multi argument versions for min and max. --- src/minmax.jl | 35 +++++++++++++++++++++++---------- test/minmax.jl | 53 ++++++++++++++++++++++++++++++++++---------------- 2 files changed, 61 insertions(+), 27 deletions(-) diff --git a/src/minmax.jl b/src/minmax.jl index 0148e284..003c182b 100644 --- a/src/minmax.jl +++ b/src/minmax.jl @@ -1,21 +1,36 @@ -### Mag Base.min(x::MagOrRef, y::MagOrRef) = Arblib.min!(zero(x), x, y) Base.max(x::MagOrRef, y::MagOrRef) = Arblib.max!(zero(x), x, y) Base.minmax(x::MagOrRef, y::MagOrRef) = (min(x, y), max(x, y)) -### Arf +for T in (ArfOrRef, ArbOrRef) + @eval Base.min(x::$T, y::$T) = + Arblib.min!($(_nonreftype(T))(prec = _precision(x, y)), x, y) + @eval Base.max(x::$T, y::$T) = + Arblib.max!($(_nonreftype(T))(prec = _precision(x, y)), x, y) + @eval Base.minmax(x::$T, y::$T) = (min(x, y), max(x, y)) -Base.min(x::ArfOrRef, y::ArfOrRef) = Arblib.min!(zero(x), x, y) -Base.max(x::ArfOrRef, y::ArfOrRef) = Arblib.max!(zero(x), x, y) -Base.minmax(x::ArfOrRef, y::ArfOrRef) = (min(x, y), max(x, y)) + # Define more efficient multi argument versions, similar to + and * + # TODO: Now precision is determined by first two arguments + for (f, f!) in ((:min, :min!), (:max, :max!)) + @eval function Base.$f(a::$T, b::$T, c::$T) + z = $f(a, b) + return $f!(z, z, c) + end + + @eval function Base.$f(a::$T, b::$T, c::$T, d::$T) + z = $f(a, b) + return $f!(z, $f!(z, z, c), d) + end -### Arb and Acb -Base.min(x::ArbOrRef, y::ArbOrRef) = Arblib.min!(zero(x), x, y) -Base.max(x::ArbOrRef, y::ArbOrRef) = Arblib.max!(zero(x), x, y) -Base.minmax(x::ArbOrRef, y::ArbOrRef) = (min(x, y), max(x, y)) + @eval function Base.$f(a::$T, b::$T, c::$T, d::$T, e::$T) + z = $f(a, b) + return $f!(z, $f!(z, $f!(z, z, c), d), e) + end + end +end ### minimum and maximum -# The default implemented in Julia have several issues for Arb types. +# The default implemented in Julia have several issues for the Arb type. # See https://github.com/JuliaLang/julia/issues/45932. # Note that it works fine for Mag and Arf. diff --git a/test/minmax.jl b/test/minmax.jl index 36f6a605..e392eadc 100644 --- a/test/minmax.jl +++ b/test/minmax.jl @@ -1,20 +1,37 @@ @testset "MinMax" begin - @testset "Mag" begin - @test min(Mag(1), Mag(2)) == Mag(1) - @test max(Mag(1), Mag(2)) == Mag(2) - @test minmax(Mag(1), Mag(2)) == minmax(Mag(2), Mag(1)) == (Mag(1), Mag(2)) - end + @testset "$T" for T in (Mag, Arf, Mag) + @test min(T(1), T(2)) == T(1) + @test max(T(1), T(2)) == T(2) + @test minmax(T(1), T(2)) == minmax(T(2), T(1)) == (T(1), T(2)) + + @test min(T.((1, 2, 2))...) == T(1) + @test min(T.((1, 1, 2))...) == T(1) + @test min(T.((2, 2, 1))...) == T(1) + @test min(T.((1, 2, 2, 2))...) == T(1) + @test min(T.((1, 1, 2, 2))...) == T(1) + @test min(T.((2, 2, 1, 2))...) == T(1) + @test min(T.((2, 2, 2, 1))...) == T(1) + @test min(T.((1, 2, 2, 2, 2))...) == T(1) + @test min(T.((1, 1, 2, 2, 2))...) == T(1) + @test min(T.((2, 2, 1, 2, 2))...) == T(1) + @test min(T.((2, 2, 2, 1, 2))...) == T(1) + @test min(T.((2, 2, 2, 2, 1))...) == T(1) - @testset "Arf" begin - @test min(Arf(1), Arf(2)) == Arf(1) - @test max(Arf(1), Arf(2)) == Arf(2) - @test minmax(Arf(1), Arf(2)) == minmax(Arf(2), Arf(1)) == (Arf(1), Arf(2)) + @test max(T.((2, 1, 1))...) == T(2) + @test max(T.((2, 2, 1))...) == T(2) + @test max(T.((1, 1, 2))...) == T(2) + @test max(T.((2, 1, 1, 1))...) == T(2) + @test max(T.((2, 2, 1, 1))...) == T(2) + @test max(T.((1, 1, 2, 1))...) == T(2) + @test max(T.((1, 1, 1, 2))...) == T(2) + @test max(T.((2, 1, 1, 1, 1))...) == T(2) + @test max(T.((2, 2, 1, 1, 1))...) == T(2) + @test max(T.((1, 1, 2, 1, 1))...) == T(2) + @test max(T.((1, 1, 1, 2, 1))...) == T(2) + @test max(T.((1, 1, 1, 1, 2))...) == T(2) end - @testset "Arb" begin - @test min(Arb(1), Arb(2)) == Arb(1) - @test max(Arb(1), Arb(2)) == Arb(2) - @test minmax(Arb(1), Arb(2)) == minmax(Arb(2), Arb(1)) == (Arb(1), Arb(2)) + @testset "Arb - specific" begin @test Arblib.contains(min(Arb((0, 2)), Arb((-1, 3))), -1) @test Arblib.contains(min(Arb((0, 2)), Arb((-1, 3))), 2) @test !Arblib.contains(min(Arb((0, 2)), Arb((-1, 3))), 3) @@ -34,10 +51,12 @@ # default implementation works well. But to help find future # issues we test it here as well. - A = Arb[10:20; 0:9] - @test minimum(A) == 0 - @test maximum(A) == 20 - @test extrema(A) == (0, 20) + @testset "$T" for T in (Mag, Arf, Mag) + A = T[10:20; 0:9] + @test minimum(A) == T(0) + @test maximum(A) == T(20) + @test extrema(A) == (T(0), T(20)) + end A = [Arb((i, i + 1)) for i = 0:20] @test contains(minimum(A), Arb((0, 1)))