From 9a369225132d685022657e40ead88a7620330daf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20G=C3=B6ttgens?= Date: Fri, 7 Jun 2024 17:31:29 +0200 Subject: [PATCH] Adapt QQBar documentation (#1715) Co-authored-by: Max Horn --- docs/src/algebraic.md | 45 +++++++------------ docs/src/exact.md | 4 +- src/Deprecations.jl | 6 +++ src/Exports.jl | 2 - src/Nemo.jl | 10 ----- src/calcium/CalciumTypes.jl | 2 - src/calcium/ca.jl | 2 +- src/calcium/qqbar.jl | 20 ++++++--- test/calcium/ca-test.jl | 7 +-- test/calcium/qqbar-test.jl | 89 ++++++++++++++++++------------------- 10 files changed, 86 insertions(+), 101 deletions(-) diff --git a/docs/src/algebraic.md b/docs/src/algebraic.md index 627f43826..27063c236 100644 --- a/docs/src/algebraic.md +++ b/docs/src/algebraic.md @@ -10,23 +10,13 @@ end Nemo allows working with exact real and complex algebraic numbers. The default algebraic number type in Nemo is provided by Calcium. The -associated field of algebraic numbers is represented by the constant -parent object called `CalciumQQBar`. +associated field of algebraic numbers can be constructed using +`QQBar = algebraic_closure(QQ)`. We will leave out this line from +all code blocks on this page for brevity. -For convenience we define - -``` -QQBar = CalciumQQBar -``` - -so that algebraic numbers can be constructed using `QQBar` instead of -`CalciumQQBar`. Note that this is the name of a specific parent object, -not the name of its type. - - - Library | Element type | Parent type -----------------|---------------|-------------------- -Calcium | `QQBarFieldElem` | `QQBarField` + Library | Element type | Parent type +----------------|------------------|-------------------- +Calcium | `QQBarFieldElem` | `QQBarField` **Important note on performance** @@ -38,8 +28,7 @@ For fast calculation in $\overline{\mathbb{Q}}$, `CalciumField` should typically be used instead (see the section on *Exact real and complex numbers*). Alternatively, to compute in a fixed subfield of $\overline{\mathbb{Q}}$, -you may fix a generator $a$ and construct an -Antic number field to represent $\mathbb{Q}(a)$. +you may fix a generator $a$ and construct a number field to represent $\mathbb{Q}(a)$. ## Algebraic number functionality @@ -58,7 +47,7 @@ Methods to construct algebraic numbers include: Arithmetic: -```jldoctest +```jldoctest; setup = :(QQBar = algebraic_closure(QQ)) julia> ZZRingElem(QQBar(3)) 3 @@ -71,7 +60,7 @@ Root 0.500000 + 0.866025*im of x^2 - x + 1 Solving the quintic equation: -```jldoctest +```jldoctest; setup = :(QQBar = algebraic_closure(QQ)) julia> R, x = polynomial_ring(QQ, "x") (Univariate polynomial ring in x over QQ, x) @@ -89,7 +78,7 @@ true Computing exact eigenvalues of a matrix: -```jldoctest +```jldoctest; setup = :(QQBar = algebraic_closure(QQ)) julia> eigenvalues(QQBar, ZZ[1 1 0; 0 1 1; 1 0 1]) 3-element Vector{QQBarFieldElem}: Root 2.00000 of x - 2 @@ -117,7 +106,7 @@ Algebraic numbers can be evaluated numerically to arbitrary precision by converting to real or complex Arb fields: -```jldoctest +```jldoctest; setup = :(QQBar = algebraic_closure(QQ)) julia> RR = ArbField(64); RR(sqrt(QQBar(2))) [1.414213562373095049 +/- 3.45e-19] @@ -132,7 +121,7 @@ julia> CC = AcbField(32); CC(QQBar(-1) ^ (QQBar(1) // 4)) Retrieving the minimal polynomial and algebraic conjugates of a given algebraic number: -```jldoctest +```jldoctest; setup = :(QQBar = algebraic_closure(QQ)) julia> minpoly(polynomial_ring(ZZ, "x")[1], QQBar(1+2im)) x^2 - 2*x + 5 @@ -165,7 +154,7 @@ height_bits(x::QQBarFieldElem) **Examples** -```jldoctest +```jldoctest; setup = :(QQBar = algebraic_closure(QQ)) julia> real(sqrt(QQBar(1im))) Root 0.707107 of 2x^2 - 1 @@ -223,7 +212,7 @@ first. **Examples** -```jldoctest +```jldoctest; setup = :(QQBar = algebraic_closure(QQ)) julia> 1 < sqrt(QQBar(2)) < QQBar(3)//2 true @@ -260,7 +249,7 @@ is_less_root_order(a::QQBarFieldElem, b::QQBarFieldElem) **Examples** -```jldoctest +```jldoctest; setup = :(QQBar = algebraic_closure(QQ)) julia> root(QQBar(2), 5) Root 1.14870 of x^5 - 2 @@ -315,7 +304,7 @@ atanpi(a::QQBarFieldElem) An algebraic number can be recovered from a numerical value: -```jldoctest +```jldoctest; setup = :(QQBar = algebraic_closure(QQ)) julia> RR = RealField(); guess(QQBar, RR("1.41421356 +/- 1e-6"), 2) Root 1.41421 of x^2 - 2 ``` @@ -325,7 +314,7 @@ approximation, you should add an error estimate; otherwise, at best the only algebraic number that can be guessed is the binary floating-point number itself, at worst no guess is possible. -```jldoctest +```jldoctest; setup = :(QQBar = algebraic_closure(QQ)) julia> RR = RealField(); julia> x = RR(0.1) # note: 53-bit binary approximation of 1//10 without radius diff --git a/docs/src/exact.md b/docs/src/exact.md index 66e4c5ce9..b1bc90f1d 100644 --- a/docs/src/exact.md +++ b/docs/src/exact.md @@ -151,7 +151,7 @@ x^4 + -10*x^2 + 1 ## Conversions and numerical evaluation Calcium numbers can created from integers (`ZZ`), rationals (`QQ`) -and algebraic numbers (`QQbar`), and through the application of +and algebraic numbers (`algebraic_closure(QQ)`), and through the application of arithmetic operations and transcendental functions. Calcium numbers can be converted to integers, rational and algebraic fields @@ -165,7 +165,7 @@ value because of evaluation limits. julia> QQ(C(1)) 1 -julia> QQBar(sqrt(C(2)) // 2) +julia> algebraic_closure(QQ)(sqrt(C(2)) // 2) Root 0.707107 of 2x^2 - 1 julia> QQ(C(pi)) diff --git a/src/Deprecations.jl b/src/Deprecations.jl index d03021664..fe97456f2 100644 --- a/src/Deprecations.jl +++ b/src/Deprecations.jl @@ -75,3 +75,9 @@ end is_power(x::IntegerUnion) = is_perfect_power_with_data(x) is_power(x::QQFieldElem) = is_perfect_power_with_data(x) is_power(x::Rational) = is_perfect_power_with_data(x) + +const QQBar = QQBarField() +export QQBar + +const CalciumQQBar = QQBarField() +export CalciumQQBar diff --git a/src/Exports.jl b/src/Exports.jl index 90f4f9413..34ed781a2 100644 --- a/src/Exports.jl +++ b/src/Exports.jl @@ -63,7 +63,6 @@ export bits export bound_inf_norm export CalciumField export CalciumFieldElem -export CalciumQQBar export canonical_unit export cdiv export cdivpow2 @@ -502,7 +501,6 @@ export QadicFieldElem export QQ export QQAbsPowerSeriesRing export QQAbsPowerSeriesRingElem -export QQBar export QQBarField export QQBarFieldElem export QQField diff --git a/src/Nemo.jl b/src/Nemo.jl index 16cd0c1bf..28937c26a 100644 --- a/src/Nemo.jl +++ b/src/Nemo.jl @@ -592,16 +592,6 @@ const FlintQQ = QQ GaussianIntegers() = FlintZZi GaussianRationals() = FlintQQi -############################################################################### -# -# Set domain for QQBar to Calcium -# -############################################################################### - -@doc qqbar_field_doc -const QQBar = CalciumQQBar - - ############################################################################### # # Some explicit type piracy against AbstractAlgebra diff --git a/src/calcium/CalciumTypes.jl b/src/calcium/CalciumTypes.jl index 00d5a4d42..a3edae706 100644 --- a/src/calcium/CalciumTypes.jl +++ b/src/calcium/CalciumTypes.jl @@ -86,8 +86,6 @@ Root 0.866025 of 4x^2 - 3 struct QQBarField <: Field end -const CalciumQQBar = QQBarField() - @doc qq_field_doc mutable struct QQBarFieldElem <: FieldElem coeffs::Ptr{Nothing} diff --git a/src/calcium/ca.jl b/src/calcium/ca.jl index e1510a21f..9706d4d53 100644 --- a/src/calcium/ca.jl +++ b/src/calcium/ca.jl @@ -1482,7 +1482,7 @@ end # todo: optimize function (C::CalciumField)(v::Complex{Int}) - return C(QQBar(v)) + return C(QQBarFieldElem(v)) end function (C::CalciumField)(x::Irrational) diff --git a/src/calcium/qqbar.jl b/src/calcium/qqbar.jl index 62f957bac..22ff12ced 100644 --- a/src/calcium/qqbar.jl +++ b/src/calcium/qqbar.jl @@ -10,7 +10,7 @@ # ############################################################################### -parent(a::QQBarFieldElem) = CalciumQQBar +parent(a::QQBarFieldElem) = QQBarField() parent_type(::Type{QQBarFieldElem}) = QQBarField @@ -178,9 +178,9 @@ zero(a::QQBarField) = a(0) one(a::QQBarField) = a(1) -zero(::Type{QQBarFieldElem}) = CalciumQQBar(0) +zero(::Type{QQBarFieldElem}) = QQBarFieldElem(0) -one(::Type{QQBarFieldElem}) = CalciumQQBar(1) +one(::Type{QQBarFieldElem}) = QQBarFieldElem(1) @doc raw""" degree(x::QQBarFieldElem) @@ -1176,7 +1176,9 @@ Throws if this value is transcendental. # Examples ```jldoctest -julia> x = sinpi(QQBar(1)//3) +julia> QQBar = algebraic_closure(QQ); + +julia> x = sinpi(QQBar(1//3)) Root 0.866025 of 4x^2 - 3 julia> sinpi(x) @@ -1202,7 +1204,9 @@ Throws if this value is transcendental. # Examples ```jldoctest -julia> x = cospi(QQBar(1)//6) +julia> QQBar = algebraic_closure(QQ); + +julia> x = cospi(QQBar(1//6)) Root 0.866025 of 4x^2 - 3 julia> cospi(x) @@ -1228,7 +1232,9 @@ Throws if either value is transcendental. # Examples ```jldoctest -julia> s, c = sincospi(QQBar(1)//3) +julia> QQBar = algebraic_closure(QQ); + +julia> s, c = sincospi(QQBar(1//3)) (Root 0.866025 of 4x^2 - 3, Root 0.500000 of 2x - 1) julia> sincospi(s) @@ -1547,4 +1553,4 @@ julia> sqrt(K(2)) Root 1.41421 of x^2 - 2 ``` """ -algebraic_closure(::QQField) = QQBar +algebraic_closure(::QQField) = QQBarField() diff --git a/test/calcium/ca-test.jl b/test/calcium/ca-test.jl index e5db1dfca..b9f1a8946 100644 --- a/test/calcium/ca-test.jl +++ b/test/calcium/ca-test.jl @@ -237,6 +237,7 @@ end @testset "CalciumFieldElem.conversions" begin C = CalciumField() + R = algebraic_closure(QQ) n = C(3) h = C(1) // 2 @@ -248,9 +249,9 @@ end @test QQ(h) == QQFieldElem(1) // 2 @test_throws ErrorException ZZ(h) - @test CalciumQQBar(h) == QQBarFieldElem(1) // 2 - @test CalciumQQBar(c) == QQBarFieldElem(1+2im) - @test_throws ErrorException CalciumQQBar(t) + @test R(h) == QQBarFieldElem(1) // 2 + @test R(c) == QQBarFieldElem(1+2im) + @test_throws ErrorException R(t) RR = ArbField(64) CC = AcbField(64) diff --git a/test/calcium/qqbar-test.jl b/test/calcium/qqbar-test.jl index 3e0bfb016..52778c7e0 100644 --- a/test/calcium/qqbar-test.jl +++ b/test/calcium/qqbar-test.jl @@ -1,13 +1,11 @@ @testset "QQBarFieldElem.constructors" begin - R = CalciumQQBar - - @test R == QQBar + R = algebraic_closure(QQ) @test elem_type(R) == QQBarFieldElem @test elem_type(QQBarField) == QQBarFieldElem @test parent_type(QQBarFieldElem) == QQBarField @test is_domain_type(QQBarFieldElem) == true - @test base_ring(CalciumQQBar) == Union{} + @test base_ring(R) == Union{} @test base_ring(QQBarFieldElem(3)) == Union{} @test isa(R, QQBarField) @@ -41,19 +39,20 @@ end @testset "QQBarFieldElem.printing" begin - a = CalciumQQBar(1) + R = algebraic_closure(QQ) + a = R(1) @test string(a) == "Root 1.00000 of x - 1" @test string(parent(a)) == "Field of algebraic numbers" @test string(-(QQBarFieldElem(10) ^ 20)) == "Root -1.00000e+20 of x + 100000000000000000000" - @test string(root_of_unity(CalciumQQBar, 3)) == "Root -0.500000 + 0.866025*im of x^2 + x + 1" + @test string(root_of_unity(R, 3)) == "Root -0.500000 + 0.866025*im of x^2 + x + 1" @test string(sqrt(QQBarFieldElem(-1)) // 3) == "Root 0.333333*im of 9x^2 + 1" end @testset "QQBarFieldElem.manipulation" begin - R = CalciumQQBar + R = algebraic_closure(QQ) @test zero(R) == 0 @test one(R) == 1 @@ -152,27 +151,27 @@ end @test root_of_unity_as_args(-i) == (4, 3) @test_throws DomainError root_of_unity_as_args(QQBarFieldElem(2)) - v = roots(CalciumQQBar, x^5-x-1) + v = roots(R, x^5-x-1) @test v[1]^5 - v[1] - 1 == 0 - v = roots(CalciumQQBar, y^2+1) + v = roots(R, y^2+1) @test v == [i, -i] - @test roots(CalciumQQBar, ZZx(0)) == [] - @test roots(CalciumQQBar, ZZx(1)) == [] - @test roots(CalciumQQBar, QQy(0)) == [] - @test roots(CalciumQQBar, QQy(1)) == [] - - @test eigenvalues(CalciumQQBar, zero(matrix_space(ZZ, 0, 0))) == [] - @test eigenvalues(CalciumQQBar, zero(matrix_space(QQ, 0, 0))) == [] - @test eigenvalues(CalciumQQBar, ZZ[1 1; 1 -1]) == [u, -u] - @test eigenvalues_with_multiplicities(CalciumQQBar, ZZ[1 1; 1 -1]) == [(u, 1), (-u, 1)] - @test eigenvalues(CalciumQQBar, diagonal_matrix(ZZ[1 1; 1 -1], ZZ[1 1; 1 -1])) == [u, -u] - @test eigenvalues_with_multiplicities(CalciumQQBar, diagonal_matrix(ZZ[1 1; 1 -1], ZZ[1 1; 1 -1])) == [(u, 2), (-u, 2)] - @test eigenvalues(CalciumQQBar, QQ[1 1; 1 -1]) == [u, -u] - @test eigenvalues_with_multiplicities(CalciumQQBar, QQ[1 1; 1 -1]) == [(u, 1), (-u, 1)] - @test eigenvalues(CalciumQQBar, diagonal_matrix(QQ[1 1; 1 -1], QQ[1 1; 1 -1])) == [u, -u] - @test eigenvalues_with_multiplicities(CalciumQQBar, diagonal_matrix(QQ[1 1; 1 -1], QQ[1 1; 1 -1])) == [(u, 2), (-u, 2)] + @test roots(R, ZZx(0)) == [] + @test roots(R, ZZx(1)) == [] + @test roots(R, QQy(0)) == [] + @test roots(R, QQy(1)) == [] + + @test eigenvalues(R, zero(matrix_space(ZZ, 0, 0))) == [] + @test eigenvalues(R, zero(matrix_space(QQ, 0, 0))) == [] + @test eigenvalues(R, ZZ[1 1; 1 -1]) == [u, -u] + @test eigenvalues_with_multiplicities(R, ZZ[1 1; 1 -1]) == [(u, 1), (-u, 1)] + @test eigenvalues(R, diagonal_matrix(ZZ[1 1; 1 -1], ZZ[1 1; 1 -1])) == [u, -u] + @test eigenvalues_with_multiplicities(R, diagonal_matrix(ZZ[1 1; 1 -1], ZZ[1 1; 1 -1])) == [(u, 2), (-u, 2)] + @test eigenvalues(R, QQ[1 1; 1 -1]) == [u, -u] + @test eigenvalues_with_multiplicities(R, QQ[1 1; 1 -1]) == [(u, 1), (-u, 1)] + @test eigenvalues(R, diagonal_matrix(QQ[1 1; 1 -1], QQ[1 1; 1 -1])) == [u, -u] + @test eigenvalues_with_multiplicities(R, diagonal_matrix(QQ[1 1; 1 -1], QQ[1 1; 1 -1])) == [(u, 2), (-u, 2)] @test conjugates(QQBarFieldElem(3)) == [QQBarFieldElem(3)] @test conjugates(u) == [u, -u] @@ -189,14 +188,14 @@ end @test_throws DomainError (RR(i)) v = sqrt(RR(2)) + sqrt(RR(3)) - @test guess(CalciumQQBar, v, 4) == sqrt(QQBarFieldElem(2)) + sqrt(QQBarFieldElem(3)) - @test guess(CalciumQQBar, v, 4, 10) == sqrt(QQBarFieldElem(2)) + sqrt(QQBarFieldElem(3)) - @test_throws ErrorException guess(CalciumQQBar, v, 2) + @test guess(R, v, 4) == sqrt(QQBarFieldElem(2)) + sqrt(QQBarFieldElem(3)) + @test guess(R, v, 4, 10) == sqrt(QQBarFieldElem(2)) + sqrt(QQBarFieldElem(3)) + @test_throws ErrorException guess(R, v, 2) - @test guess(CalciumQQBar, CC(2+i), 2, 10) == 2+i + @test guess(R, CC(2+i), 2, 10) == 2+i - Rx, x = polynomial_ring(QQBar, "x") - @test gcd(x^4 - 4*x^2 + 4, x^2 + sqrt(QQBar(18))*x + 4) == x + sqrt(QQBar(2)) + Rx, x = polynomial_ring(R, "x") + @test gcd(x^4 - 4*x^2 + 4, x^2 + sqrt(R(18))*x + 4) == x + sqrt(R(2)) end # floor, ceil, round @@ -232,20 +231,18 @@ end @test_throws DomainError (RR(i)) v = sqrt(RR(2)) + sqrt(RR(3)) - @test guess(CalciumQQBar, v, 4) == sqrt(QQBarFieldElem(2)) + sqrt(QQBarFieldElem(3)) - @test guess(CalciumQQBar, v, 4, 10) == sqrt(QQBarFieldElem(2)) + sqrt(QQBarFieldElem(3)) - @test_throws ErrorException guess(CalciumQQBar, v, 2) + @test guess(R, v, 4) == sqrt(QQBarFieldElem(2)) + sqrt(QQBarFieldElem(3)) + @test guess(R, v, 4, 10) == sqrt(QQBarFieldElem(2)) + sqrt(QQBarFieldElem(3)) + @test_throws ErrorException guess(R, v, 2) - @test guess(CalciumQQBar, CC(2+i), 2, 10) == 2+i + @test guess(R, CC(2+i), 2, 10) == 2+i - Rx, x = polynomial_ring(QQBar, "x") - @test gcd(x^4 - 4*x^2 + 4, x^2 + sqrt(QQBar(18))*x + 4) == x + sqrt(QQBar(2)) + Rx, x = polynomial_ring(R, "x") + @test gcd(x^4 - 4*x^2 + 4, x^2 + sqrt(R(18))*x + 4) == x + sqrt(R(2)) end @testset "QQBarFieldElem.adhoc_operations" begin - R = CalciumQQBar - @test QQBarFieldElem(2) + QQBarFieldElem(3) == 5 @test QQBarFieldElem(2) + 3 == 5 @test QQBarFieldElem(2) + ZZRingElem(3) == 5 @@ -297,7 +294,7 @@ end end @testset "QQBarFieldElem.comparison" begin - R = CalciumQQBar + R = algebraic_closure(QQ) u = R(3) // 2 i = sqrt(R(-1)) @@ -350,7 +347,7 @@ end @testset "QQBarFieldElem.inplace" begin - R = CalciumQQBar + R = algebraic_closure(QQ) x = R(7) zero!(x) @@ -374,25 +371,25 @@ end end @testset "QQBarFieldElem.rand" begin - R = CalciumQQBar + R = algebraic_closure(QQ) for i=1:10 - x = rand(CalciumQQBar, degree=5, bits=5) + x = rand(R, degree=5, bits=5) @test degree(x) <= 5 end for i=1:10 - x = rand(CalciumQQBar, degree=5, bits=5, randtype=:real) + x = rand(R, degree=5, bits=5, randtype=:real) @test isreal(x) end for i=1:10 - x = rand(CalciumQQBar, degree=5, bits=5, randtype=:nonreal) + x = rand(R, degree=5, bits=5, randtype=:nonreal) # todo: need to upgrade Calcium # @test !isreal(x) end - @test_throws ErrorException rand(CalciumQQBar, degree=2, bits=5, randtype=:gollum) + @test_throws ErrorException rand(R, degree=2, bits=5, randtype=:gollum) end @@ -401,6 +398,6 @@ function test_elem(R::QQBarField) end @testset "QQBarFieldElem.conformance_tests" begin - test_Field_interface(CalciumQQBar) + test_Field_interface(algebraic_closure(QQ)) end