Skip to content

Commit

Permalink
Precision fixes for some code dealing with ArbField/AcbField (#1707)
Browse files Browse the repository at this point in the history
  • Loading branch information
fingolfin authored Apr 9, 2024
1 parent f033978 commit 928e06a
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 24 deletions.
8 changes: 4 additions & 4 deletions docs/src/acb.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ DocTestSetup = quote
end
```

# Fixed precisioncomplex balls
# Fixed precision complex balls

Arbitrary precision complex ball arithmetic is supplied by Arb which provides a
ball representation which tracks error bounds rigorously. Complex numbers are
Expand All @@ -17,9 +17,9 @@ constructs the parent object for the Arb complex field.
The types of complex boxes in Nemo are given in the following table, along with
the libraries that provide them and the associated types of the parent objects.

Library | Field | Element type | Parent type
---------|----------------------|---------------|--------------
Arb | $\mathbb{C}$ (boxes) | `AcbFieldElem` | `AcbField`
Library | Field | Element type | Parent type
---------|----------------------|----------------|--------------
Arb | $\mathbb{C}$ (boxes) | `AcbFieldElem` | `AcbField`

All the complex field types belong to the `Field` abstract type and the types of
elements in this field, i.e. complex boxes in this case, belong to the
Expand Down
26 changes: 12 additions & 14 deletions src/calcium/ca.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1339,7 +1339,7 @@ end

function (R::AcbField)(a::CalciumFieldElem; parts::Bool=false)
C = a.parent
prec = precision(Balls)
prec = precision(R)
z = R()
if parts
ccall((:ca_get_acb_accurate_parts, libcalcium),
Expand All @@ -1353,16 +1353,16 @@ end

function (R::ArbField)(a::CalciumFieldElem; check::Bool=true)
C = a.parent
prec = precision(Balls)
prec = precision(R)
if check
z = AcbField()(a, parts=true)
z = AcbField(prec)(a, parts=true)
if isreal(z)
return real(z)
else
error("unable to convert to a real number")
end
else
z = AcbField()(a, parts=false)
z = AcbField(prec)(a, parts=false)
if accuracy_bits(real(z)) < prec - 5
z = AcbField()(a, parts=true)
end
Expand All @@ -1371,16 +1371,14 @@ function (R::ArbField)(a::CalciumFieldElem; check::Bool=true)
end

function (::Type{ComplexF64})(x::CalciumFieldElem)
set_precision!(Balls, 53) do
z = AcbField()(x)
x = ArbFieldElem()
ccall((:acb_get_real, libarb), Nothing, (Ref{ArbFieldElem}, Ref{AcbFieldElem}), x, z)
xx = Float64(x)
y = ArbFieldElem()
ccall((:acb_get_imag, libarb), Nothing, (Ref{ArbFieldElem}, Ref{AcbFieldElem}), y, z)
yy = Float64(y)
return ComplexF64(xx, yy)
end
z = AcbField(53, cached = false)(x)
x = ArbFieldElem()
ccall((:acb_get_real, libarb), Nothing, (Ref{ArbFieldElem}, Ref{AcbFieldElem}), x, z)
xx = Float64(x)
y = ArbFieldElem()
ccall((:acb_get_imag, libarb), Nothing, (Ref{ArbFieldElem}, Ref{AcbFieldElem}), y, z)
yy = Float64(y)
return ComplexF64(xx, yy)
end

###############################################################################
Expand Down
8 changes: 4 additions & 4 deletions src/calcium/qqbar.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1363,7 +1363,7 @@ may be much smaller than a worst-case bound.
function guess end

function guess(R::QQBarField, x::T, maxdeg::Int, maxbits::Int=0) where {T <: Union{AcbFieldElem, ComplexFieldElem}}
prec = precision(Balls)
prec = precision(parent(x))
if maxbits <= 0
maxbits = prec
end
Expand All @@ -1378,7 +1378,7 @@ function guess(R::QQBarField, x::T, maxdeg::Int, maxbits::Int=0) where {T <: Uni
end

function guess(R::QQBarField, x::ArbFieldElem, maxdeg::Int, maxbits::Int=0)
CC = AcbField()
CC = AcbField(precision(parent(x)))
return guess(R, CC(x), maxdeg, maxbits)
end

Expand Down Expand Up @@ -1428,7 +1428,7 @@ Convert `a` to a real ball with the precision of the parent field `R`.
Throws if `a` is not a real number.
"""
function (R::RealField)(a::QQBarFieldElem)
prec = precision(R)
prec = precision(Balls)
z = R()
ccall((:qqbar_get_arb, libcalcium),
Nothing, (Ref{RealFieldElem}, Ref{QQBarFieldElem}, Int), z, a, prec)
Expand All @@ -1442,7 +1442,7 @@ end
Convert `a` to a complex ball with the precision of the parent field `R`.
"""
function (R::ComplexField)(a::QQBarFieldElem)
prec = precision(R)
prec = precision(Balls)
z = R()
ccall((:qqbar_get_acb, libcalcium),
Nothing, (Ref{ComplexFieldElem}, Ref{QQBarFieldElem}, Int), z, a, prec)
Expand Down
12 changes: 10 additions & 2 deletions test/calcium/ca-test.jl
Original file line number Diff line number Diff line change
Expand Up @@ -252,8 +252,8 @@ end
@test CalciumQQBar(c) == QQBarFieldElem(1+2im)
@test_throws ErrorException CalciumQQBar(t)

RR = ArbField()
CC = AcbField()
RR = ArbField(64)
CC = AcbField(64)

@test RR(h) == 0.5
@test CC(h) == 0.5
Expand All @@ -275,6 +275,14 @@ end

s = 1 * one(C) + 2 * onei(C)
@test ComplexF64(s) == 1 + 2 * im

# verify precision bug https://github.com/Nemocas/Nemo.jl/issues/1580 is fixed
x = C(pi)
F = ArbField(333)
y = F(x)
@test radius(y) < 1e-113
z = F("3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170680 +/- 1.79e-101")
@test contains(z,y)
end

@testset "CalciumFieldElem.inplace" begin
Expand Down

0 comments on commit 928e06a

Please sign in to comment.