diff --git a/src/Arblib.jl b/src/Arblib.jl index 69813d45..2429830b 100644 --- a/src/Arblib.jl +++ b/src/Arblib.jl @@ -76,6 +76,7 @@ include("minmax.jl") include("rand.jl") include("float.jl") include("interval.jl") +include("multi-argument.jl") include("ref.jl") include("vector.jl") diff --git a/src/arithmetic.jl b/src/arithmetic.jl index 8153c4ae..e51f2c70 100644 --- a/src/arithmetic.jl +++ b/src/arithmetic.jl @@ -32,31 +32,6 @@ for (jf, af) in [(:+, :add!), (:-, :sub!), (:*, :mul!), (:/, :div!)] @eval Base.$jf(x::Union{ArfOrRef,_BitInteger,Irrational}, y::ArbOrRef) = $jf(y, x) @eval Base.$jf(x::Union{ArbOrRef,_BitInteger,Irrational}, y::AcbOrRef) = $jf(y, x) - - # Define more efficient multi argument versions, similar to BigFloat - # TODO: Now precision is determined by first two arguments - for T in (MagOrRef, ArfOrRef, ArbOrRef, AcbOrRef) - @eval function Base.$jf(a::$T, b::$T, c::$T) - z = $jf(a, b) - $af(z, z, c) - return z - end - - @eval function Base.$jf(a::$T, b::$T, c::$T, d::$T) - z = $jf(a, b) - $af(z, z, c) - $af(z, z, d) - return z - end - - @eval function Base.$jf(a::$T, b::$T, c::$T, d::$T, e::$T) - z = $jf(a, b) - $af(z, z, c) - $af(z, z, d) - $af(z, z, e) - return z - end - end else @eval function Base.$jf(x::Irrational, y::Union{ArbOrRef,AcbOrRef}) z = zero(y) diff --git a/src/minmax.jl b/src/minmax.jl index 003c182b..aec6e5eb 100644 --- a/src/minmax.jl +++ b/src/minmax.jl @@ -8,25 +8,6 @@ for T in (ArfOrRef, ArbOrRef) @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)) - - # 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 - - @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 diff --git a/src/multi-argument.jl b/src/multi-argument.jl new file mode 100644 index 00000000..d02f858c --- /dev/null +++ b/src/multi-argument.jl @@ -0,0 +1,61 @@ +# Contains implementation of multi-argument versions of +, *, min and max + +for (jf, af) in [(:+, :add!), (:*, :mul!), (:min, :min!), (:max, :max!)] + @eval function Base.$jf(a::MagOrRef, b::MagOrRef, c::MagOrRef) + res = Mag() + $af(res, a, b) + $af(res, res, c) + return res + end + + @eval function Base.$jf(a::MagOrRef, b::MagOrRef, c::MagOrRef, d::MagOrRef) + res = Mag() + $af(res, a, b) + $af(res, res, c) + $af(res, res, d) + return res + end + + @eval function Base.$jf(a::MagOrRef, b::MagOrRef, c::MagOrRef, d::MagOrRef, e::MagOrRef) + res = Mag() + $af(res, a, b) + $af(res, res, c) + $af(res, res, d) + $af(res, res, e) + return res + end +end + +for T in (ArfOrRef, ArbOrRef, AcbOrRef) + @eval @inline _precision(x::$T, y::$T, z::$T, rest::Vararg{S}) where {S<:$T} = + max(precision(x), _precision(y, z, rest...)) + + for (jf, af) in [(:+, :add!), (:*, :mul!), (:min, :min!), (:max, :max!)] + T == AcbOrRef && jf == :min && continue + T == AcbOrRef && jf == :max && continue + + @eval function Base.$jf(a::$T, b::$T, c::$T) + res = $(_nonreftype(T))(prec = _precision(a, b, c)) + $af(res, a, b) + $af(res, res, c) + return res + end + + @eval function Base.$jf(a::$T, b::$T, c::$T, d::$T) + res = $(_nonreftype(T))(prec = _precision(a, b, c, d)) + $af(res, a, b) + $af(res, res, c) + $af(res, res, d) + return res + end + + @eval function Base.$jf(a::$T, b::$T, c::$T, d::$T, e::$T) + res = $(_nonreftype(T))(prec = _precision(a, b, c, d, e)) + $af(res, a, b) + $af(res, res, c) + $af(res, res, d) + $af(res, res, e) + return res + end + end +end diff --git a/test/arithmetic.jl b/test/arithmetic.jl index 1fc64d01..01f99168 100644 --- a/test/arithmetic.jl +++ b/test/arithmetic.jl @@ -13,13 +13,6 @@ @test Mag(1 / 4) <= inv(Mag(4)) <= Mag(1 / 3) - @test Mag(6) <= +(Mag.((1, 2, 3))...) <= Mag(7) - @test Mag(10) <= +(Mag.((1, 2, 3, 4))...) <= Mag(11) - @test Mag(15) <= +(Mag.((1, 2, 3, 4, 5))...) <= Mag(16) - @test Mag(6) <= *(Mag.((1, 2, 3))...) <= Mag(7) - @test Mag(24) <= *(Mag.((1, 2, 3, 4))...) <= Mag(25) - @test Mag(120) <= *(Mag.((1, 2, 3, 4, 5))...) <= Mag(121) - # signbit, sign and abs @test !signbit(Mag(0)) @test !signbit(Mag(2)) @@ -63,13 +56,6 @@ UInt8(6) / Arf(2) == 3 - @test +(Arf.((1, 2, 3))...) == 6 - @test +(Arf.((1, 2, 3, 4))...) == 10 - @test +(Arf.((1, 2, 3, 4, 5))...) == 15 - @test *(Arf.((1, 2, 3))...) == 6 - @test *(Arf.((1, 2, 3, 4))...) == 24 - @test *(Arf.((1, 2, 3, 4, 5))...) == 120 - # fma and muladd @test fma(Arf(2), Arf(3), Arf(4)) == muladd(Arf(2), Arf(3), Arf(4)) == 10 @@ -100,13 +86,6 @@ @test T(2) * T(3) == T(2) * 3 == 3 * T(2) == T(2) * UInt(3) == UInt(3) * T(2) == 6 @test T(6) / T(2) == T(6) / 2 == T(6) / UInt(2) == 3 - @test +(T.((1, 2, 3))...) == 6 - @test +(T.((1, 2, 3, 4))...) == 10 - @test +(T.((1, 2, 3, 4, 5))...) == 15 - @test *(T.((1, 2, 3))...) == 6 - @test *(T.((1, 2, 3, 4))...) == 24 - @test *(T.((1, 2, 3, 4, 5))...) == 120 - # ^ @test Base.literal_pow(^, T(2), Val(-2)) == T(2)^-2 == diff --git a/test/minmax.jl b/test/minmax.jl index e392eadc..9e250774 100644 --- a/test/minmax.jl +++ b/test/minmax.jl @@ -3,32 +3,6 @@ @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) - - @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 - specific" begin diff --git a/test/multi-argument.jl b/test/multi-argument.jl new file mode 100644 index 00000000..6429093b --- /dev/null +++ b/test/multi-argument.jl @@ -0,0 +1,49 @@ +@testset "Multi-argument" begin + @testset "Mag + and *" begin + @test Mag(6) <= +(Mag.((1, 2, 3))...) <= Mag(7) + @test Mag(10) <= +(Mag.((1, 2, 3, 4))...) <= Mag(11) + @test Mag(15) <= +(Mag.((1, 2, 3, 4, 5))...) <= Mag(16) + + @test Mag(6) <= *(Mag.((1, 2, 3))...) <= Mag(7) + @test Mag(24) <= *(Mag.((1, 2, 3, 4))...) <= Mag(25) + @test Mag(120) <= *(Mag.((1, 2, 3, 4, 5))...) <= Mag(121) + end + + @testset "$T + and *" for T in [Arf, Arb, Acb] + @test +(T.((1, 2, 3))...) == 6 + @test +(T.((1, 2, 3, 4))...) == 10 + @test +(T.((1, 2, 3, 4, 5))...) == 15 + + @test *(T.((1, 2, 3))...) == 6 + @test *(T.((1, 2, 3, 4))...) == 24 + @test *(T.((1, 2, 3, 4, 5))...) == 120 + end + + @testset "$T min and max" for T in [Mag, Arf, Arb] + @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) + + @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 +end diff --git a/test/runtests.jl b/test/runtests.jl index c1d91b13..151d9273 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -23,6 +23,7 @@ using Arblib, Test, LinearAlgebra, Random, Serialization, SpecialFunctions include("rand.jl") include("float.jl") include("interval.jl") + include("multi-argument.jl") include("vector.jl") include("matrix.jl") include("eigen.jl")