Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix ambiguities #192

Merged
merged 6 commits into from
Apr 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/constructors.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,22 @@ Mag(x) = set!(Mag(), x)
# later.
Mag(x::Union{MagRef,ArfRef}) = Mag(cstruct(x))
Mag(x, y) = set!(Mag(), x, y)
# disambiguation
Mag(x::Complex) = set!(Mag(), x)

# Arf
Arf(x; prec::Integer = _precision(x)) = set!(Arf(; prec), x)
# disambiguation
Arf(x::Arf; prec::Integer = precision(x)) = set!(Arf(; prec), x)
Arf(x::Rational; prec::Integer = _precision(x)) = set!(Arf(; prec), x)
Arf(x::Complex; prec::Integer = _precision(x)) = set!(Arf(; prec), x)

#Arb
Arb(x; prec::Integer = _precision(x)) = set!(Arb(; prec), x)
# disambiguation
Arb(x::Arb; prec::Integer = precision(x)) = set!(Arb(; prec), x)
Arb(x::Rational; prec::Integer = _precision(x)) = set!(Arb(; prec), x)
Arb(x::Complex; prec::Integer = _precision(x)) = set!(Arb(; prec), x)

function Arb(str::AbstractString; prec::Integer = DEFAULT_PRECISION[])
res = Arb(; prec)
Expand Down
23 changes: 14 additions & 9 deletions src/minmax.jl
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,18 @@ end
# doesn't solve the full problem.

# The default implementation in Base is not correct for Arb
Base._fast(::typeof(min), x::Arb, y::Arb) = min(x, y)
Base._fast(::typeof(min), x::Arb, y) = min(x, y)
Base._fast(::typeof(min), x, y::Arb) = min(x, y)
Base._fast(::typeof(max), x::Arb, y::Arb) = max(x, y)
Base._fast(::typeof(max), x::Arb, y) = max(x, y)
Base._fast(::typeof(max), x, y::Arb) = max(x, y)
Base._fast(::typeof(min), x::ArbOrRef, y::ArbOrRef) = min(x, y)
Base._fast(::typeof(min), x::ArbOrRef, y) = min(x, y)
Base._fast(::typeof(min), x, y::ArbOrRef) = min(x, y)
Base._fast(::typeof(max), x::ArbOrRef, y::ArbOrRef) = max(x, y)
Base._fast(::typeof(max), x::ArbOrRef, y) = max(x, y)
Base._fast(::typeof(max), x, y::ArbOrRef) = max(x, y)
# Handle ambiguous methods
Base._fast(::typeof(min), x::ArbOrRef, y::AbstractFloat) = min(x, y)
Base._fast(::typeof(min), x::AbstractFloat, y::ArbOrRef) = min(x, y)
Base._fast(::typeof(max), x::ArbOrRef, y::AbstractFloat) = max(x, y)
Base._fast(::typeof(max), x::AbstractFloat, y::ArbOrRef) = max(x, y)

# Mag, Arf and Arb don't have signed zeros
Base.isbadzero(::typeof(min), x::Union{Mag,Arf,Arb}) = false
Base.isbadzero(::typeof(max), x::Union{Mag,Arf,Arb}) = false
# Arf and Arb don't have signed zeros
Base.isbadzero(::typeof(min), x::Union{ArfOrRef,ArbOrRef}) = false
Base.isbadzero(::typeof(max), x::Union{ArfOrRef,ArbOrRef}) = false
12 changes: 12 additions & 0 deletions src/poly.jl
Original file line number Diff line number Diff line change
Expand Up @@ -652,6 +652,16 @@ function Base.:^(p::AcbSeries, q::AcbSeries)
deg = _degree(p, q)
return pow_series!(AcbSeries(degree = deg, prec = _precision(p, q)), p, q, deg + 1)
end
function Base.:^(p::ArbSeries, q::AcbSeries)
deg = _degree(p, q)
res = AcbSeries(p, degree = deg, prec = _precision(p, q))
return pow_series!(res, res, q, deg + 1)
end
function Base.:^(p::AcbSeries, q::ArbSeries)
deg = _degree(p, q)
res = AcbSeries(q, degree = deg, prec = _precision(p, q))
return pow_series!(res, p, res, deg + 1)
end

Base.:^(p::ArbSeries, e::Real) = pow_arb_series!(zero(p), p, convert(Arb, e), length(p))
function Base.:^(p::ArbSeries, e::Number)
Expand All @@ -678,6 +688,8 @@ Base.:^(p::ArbSeries, e::Integer) = pow_arb_series!(zero(p), p, convert(Arb, e),
Base.:^(p::AcbSeries, e::Integer) = pow_acb_series!(zero(p), p, convert(Acb, e), length(p))
Base.:^(p::ArbSeries, e::Rational) = pow_arb_series!(zero(p), p, convert(Arb, e), length(p))
Base.:^(p::AcbSeries, e::Rational) = pow_acb_series!(zero(p), p, convert(Acb, e), length(p))
Base.:^(::Irrational{:ℯ}, e::ArbSeries) = exp(e)
Base.:^(::Irrational{:ℯ}, e::AcbSeries) = exp(e)

##
## Series methods
Expand Down
10 changes: 10 additions & 0 deletions src/setters.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ Base.setindex!(res::Union{MagLike,ArfLike,ArbLike,AcbLike}, x) = set!(res, x)
set!(res::MagLike, x::Integer) = set!(res, convert(UInt, x))
set!(res::MagLike, ::Irrational{:π}) = const_pi!(res)
set!(res::MagLike, x::Integer, y::Integer) = set_ui_2exp!(res, convert(UInt, x), y)
set!(res::MagLike, x::Complex) =
isreal(x) ? set!(res, real(x)) : throw(InexactError(:Mag, Mag, x))

# Arf
function set!(res::ArfLike, x::UInt128)
Expand Down Expand Up @@ -38,6 +40,9 @@ function set!(
return res
end

set!(res::ArfLike, x::Complex) =
isreal(x) ? set!(res, real(x)) : throw(InexactError(:Arf, Arf, x))

# Arb
function set!(res::ArbLike, x::Union{UInt128,Int128,MagLike,BigInt,BigFloat})
set!(midref(res), x)
Expand Down Expand Up @@ -98,6 +103,11 @@ function set!(res::ArbLike, (a, b)::Tuple{<:Real,<:Real}; prec::Integer = precis
return union!(res, a, b; prec)
end

set!(res::ArbLike, x::AcbOrRef) =
is_real(x) ? set!(res, realref(x)) : throw(InexactError(:Arb, Arb, x))
set!(res::ArbLike, x::Complex) =
isreal(x) ? set!(res, real(x)) : throw(InexactError(:Arb, Arb, x))

# Acb
function set!(res::AcbLike, x::Union{Real,MagLike,ArfLike,Tuple{<:Real,<:Real}})
set!(realref(res), x)
Expand Down
16 changes: 16 additions & 0 deletions test/constructors.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@
@test Mag(UInt64(1)) == Mag(1) == one(Mag) == one(Mag()) <= Mag(1.0)
@test π < Float64(Mag(π)) < 3.15
@test Mag(3, 4) == Mag(3 * 2^4)

# Check for ambiguities
@test Mag(1 + 0im) == Mag(1)
@test_throws InexactError Mag(1 + im)
end

@testset "Arf" begin
Expand All @@ -23,6 +27,10 @@

@test precision(zero(Arf(prec = 80))) == 80
@test precision(one(Arf(prec = 80))) == 80

# Check for ambiguities
@test Arf(1 + 0im) == 1
@test_throws InexactError Arf(1 + im)
end

@testset "Arb" begin
Expand Down Expand Up @@ -58,6 +66,10 @@
@test precision(Arb(MathConstants.catalan, prec = 80)) == 80
@test precision(Arb(MathConstants.φ, prec = 80)) == 80

@test Arb(Acb(1)) == 1
@test precision(Arb(Acb(1, prec = 80))) == 80
@test_throws InexactError Arb(Acb(1, 1))

# setball
@test isone(Arblib.setball(Arb, Arf(1), Mag(0)))
@test isone(Arblib.setball(Arb, 1, 0))
Expand All @@ -71,6 +83,10 @@

@test precision(Arblib.setball(Arb, Arf(prec = 80), 0)) == 80
@test precision(Arblib.setball(Arb, Arf(prec = 90), 0, prec = 80)) == 80

# Check for ambiguities
@test Arb(1 + 0im) == 1
@test_throws InexactError Arb(1 + im)
end

@testset "Acb" begin
Expand Down
34 changes: 32 additions & 2 deletions test/minmax.jl
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,7 @@
@test iszero(extrema(identity, -A)[2])

# Fails with default implementation due to Base._fast
#A = [Arb(0); [setball(Arb, 0, i) for i in reverse(0:257)]]
A = [setball(Arb, 0, i) for i = 0:257]
A = [Arb(0); [setball(Arb, 0, i) for i in reverse(0:257)]]
@test Arblib.contains(minimum(A), -257)
@test Arblib.contains(maximum(A), 257)
@test Arblib.contains(extrema(A)[1], -257)
Expand All @@ -71,6 +70,25 @@
@test Arblib.contains(maximum(identity, A), 257)
@test Arblib.contains(extrema(identity, A)[1], -257)
@test Arblib.contains(extrema(identity, A)[2], 257)
# In a previous version of Arblib, Base._fast was not correctly
# overloaded for ArbRef.
A = [
Arblib.realref(Acb(0))
[Arblib.realref(Acb(setball(Arb, 0, i))) for i in reverse(0:257)]
]
@test Arblib.contains(minimum(A), -257)
@test Arblib.contains(maximum(A), 257)
@test Arblib.contains(extrema(A)[1], -257)
@test Arblib.contains(extrema(A)[2], 257)
@test Arblib.contains(minimum(identity, A), -257)
@test Arblib.contains(maximum(identity, A), 257)
@test Arblib.contains(extrema(identity, A)[1], -257)
@test Arblib.contains(extrema(identity, A)[2], 257)
# In a previous version of Arblib, Base._fast was not correctly
# handling mixture of Arb and AbstractFloat
@test minimum(AbstractFloat[Arb(0); fill(1.0, 257)]) == 0
@test maximum(AbstractFloat[Arb(0); fill(1.0, 257)]) == 1
@test extrema(AbstractFloat[Arb(0); fill(1.0, 257)]) == (0, 1)

# Fails with default implementation due to both short circuit
# and Base._fast
Expand All @@ -92,17 +110,29 @@
@test !Base.isbadzero(min, zero(Mag))
@test !Base.isbadzero(min, zero(Arf))
@test !Base.isbadzero(min, zero(Arb))
@test !Base.isbadzero(min, Arblib.radref(zero(Arb)))
@test !Base.isbadzero(min, Arblib.midref(zero(Arb)))
@test !Base.isbadzero(min, Arblib.realref(zero(Acb)))

@test !Base.isbadzero(max, zero(Mag))
@test !Base.isbadzero(max, zero(Arf))
@test !Base.isbadzero(max, zero(Arb))
@test !Base.isbadzero(max, Arblib.radref(zero(Arb)))
@test !Base.isbadzero(max, Arblib.midref(zero(Arb)))
@test !Base.isbadzero(max, Arblib.realref(zero(Acb)))

@test !Base.isgoodzero(min, zero(Mag))
@test !Base.isgoodzero(min, zero(Arf))
@test !Base.isgoodzero(min, zero(Arb))
@test !Base.isgoodzero(min, Arblib.radref(zero(Arb)))
@test !Base.isgoodzero(min, Arblib.midref(zero(Arb)))
@test !Base.isgoodzero(min, Arblib.realref(zero(Acb)))

@test !Base.isgoodzero(max, zero(Mag))
@test !Base.isgoodzero(max, zero(Arf))
@test !Base.isgoodzero(max, zero(Arb))
@test !Base.isgoodzero(max, Arblib.radref(zero(Arb)))
@test !Base.isgoodzero(max, Arblib.midref(zero(Arb)))
@test !Base.isgoodzero(max, Arblib.realref(zero(Acb)))
end
end
18 changes: 17 additions & 1 deletion test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,23 @@ DocMeta.setdocmeta!(Arblib, :DocTestSetup, :(using Arblib); recursive = true)

@testset "Arblib" begin
doctest(Arblib)
Aqua.test_all(Arblib; ambiguities = (; broken = true))
# Some methods are excluded from the check for ambiguities. There
# are two reasons for these exclusions, methods in Base we don't
# care about and false positives from Aqua.

# The methods in Base that we don't care about are construction
# from AbstractChar or Base.TwicePrecision. Both of these have
# default constructors for Number types that clash with our catch
# all constructors. They do not seem important enough to warrant
# extra code for handling them.

# One set of false positives are for Arf(::Rational) and
# Arb(::Rational). The other set is for + and * with mix of
# ArbSeries and AcbSeries.
Aqua.test_all(
Arblib,
ambiguities = (exclude = [Mag, Arf, Arb, Acb, ArbSeries, AcbSeries, +, *],),
)

include("ArbCall/runtests.jl")

Expand Down
4 changes: 3 additions & 1 deletion test/series.jl
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,7 @@
p = TSeries([1, 2, 3])
q = TSeries([2, 3, 0])

@test p^q == TSeries([1, 4, 16])
@test p^q == ArbSeries([1, 2, 3])^q == p^ArbSeries([2, 3, 0]) == TSeries([1, 4, 16])

@test p^T(2) ==
p^Int(2) ==
Expand All @@ -322,6 +322,8 @@
@test 2^TSeries([1, 0]) == TSeries([2, 0])
@test (2 + im)^TSeries([1, 0]) == AcbSeries([2 + im, 0])

@test isequal(ℯ^p, exp(p))

@test precision(setprecision(p, 80)^setprecision(q, 90)) == 90
@test precision(setprecision(p, 80)^T(2)) == 80
end
Expand Down
14 changes: 14 additions & 0 deletions test/setters.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@

# Integer times power of 2
@test Arblib.set!(T(), 3, 4) == Arblib.set!(T(), 3 * 2^4)

# Complex
@test Arblib.set!(T(), 1 + 0im) == Mag(1)
@test_throws InexactError Arblib.set!(T(), 1 + 1im)
end

@testset "$name" for (name, T) in [("Arf", Arf), ("ArfRef", () -> Arblib.midref(Arb()))]
Expand Down Expand Up @@ -35,6 +39,10 @@
@test Arblib.set!(T(), 1 // BigInt(x)) == inv(Arf(x))
@test Arblib.set!(T(), BigInt(x) // (BigInt(x) + 1)) == Arf(x) / Arf(x + 1)
end

# Complex
@test Arblib.set!(T(), 1 + 0im) == 1
@test_throws InexactError Arblib.set!(T(), 1 + 1im)
end

@testset "$name" for (name, T) in
Expand Down Expand Up @@ -146,6 +154,12 @@
@test_throws ArgumentError Arblib.set!(T(), (2, 1))
@test_throws ArgumentError Arblib.set!(T(), (2.0, 1.0))
@test_throws ArgumentError Arblib.set!(T(), (2, 1.0))

# Complex
@test Arblib.set!(T(), Acb(1, 0)) == 1
@test_throws InexactError Arblib.set!(T(), Acb(1, 1))
@test Arblib.set!(T(), 1 + 0im) == 1
@test_throws InexactError Arblib.set!(T(), 1 + 1im)
end

@testset "$name" for (name, T) in [
Expand Down
Loading