This file is also available as a jupyter notebook and a julia file:
Quaternion algebras
Creation
julia> Q = quaternion_algebra(QQ, -1, -1)
Quaternion algebra
over rational field
defined by i^2 = -1, j^2 = -1
Construct the standard basis:
julia> _, i, j, k = basis(Q)
4-element Vector{AssociativeAlgebraElem{QQFieldElem, Hecke.QuaternionAlgebra{QQFieldElem}}}:
1
i
j
k
Verifying the relations:
julia> i^2 == -1 && j^2 == -1 && i * j == k
true
Construction of elements:
julia> alpha = 1 + 2*i + 3*j
1 + 2*i + 3*j
Or via directly supplying the coordinates as a vector:
julia> alpha == Q([1, 2, 3, 0])
true
This works for also for number fields:
julia> K, sqrt2 = quadratic_field(2)
(Real quadratic field defined by x^2 - 2, sqrt(2))
julia> Q = quaternion_algebra(K, sqrt2, K(3))
Quaternion algebra
over real quadratic field defined by x^2 - 2
defined by i^2 = sqrt(2), j^2 = 3
julia> alpha = Q([sqrt2, 1, 0, 1])
sqrt(2) + i + k
Properties of elements
Get the coefficients with respect to the canonical basis:
julia> coefficients(alpha)
4-element Vector{AbsSimpleNumFieldElem}:
sqrt(2)
1
0
1
Trace and norm (also reduced version)
julia> tr(alpha), norm(alpha)
(4*sqrt(2), 8*sqrt(2) + 12)
julia> trred(alpha), normred(alpha)
(2*sqrt(2), 2*sqrt(2) + 2)
Image of elements under canonical involution:
julia> conjugate(alpha)
sqrt(2) - i - k
julia> normred(alpha) == conjugate(alpha) * alpha
true
Division
For division there are the two functions divexact_left
and divexact_right
. If c = divexact_right(a, b)
, then a == c * b
. So, divexact_right(a, b)
returns an element c
, such that b
becomes a right-divisor of a
.
julia> _, i, j, k = basis(Q);
julia> divexact_right(k, j)
i
julia> k == i * j
true
julia> divexact_left(k, j)
-i
julia> k == j * (-i)
true
Polynomials
Polynomials behave very much like polynonomials over commutative rings, except that everything related to divisions needs to specifiy the "side".
julia> Q = quaternion_algebra(QQ, -1, -1)
Quaternion algebra
over rational field
defined by i^2 = -1, j^2 = -1
julia> _, i, j, k = basis(Q)
4-element Vector{AssociativeAlgebraElem{QQFieldElem, Hecke.QuaternionAlgebra{QQFieldElem}}}:
1
i
j
k
julia> Qx, x = Q[:x]
(Univariate polynomial ring in x over quaternion algebra, x)
julia> f = i * x^2 + j * x
i*x^2 + j*x
julia> g = i * x
i*x
julia> divexact_right(f, g) == x + k
true
julia> divexact_left(f, g) == x + (- k)
true
julia> Hecke.divrem_right(f, g)
(x + k, 0)
julia> Hecke.gcd_right(f, g)
i*x
Splitting of quaternion algebras
julia> Q = quaternion_algebra(QQ, -1, -1)
Quaternion algebra
over rational field
defined by i^2 = -1, j^2 = -1
julia> is_split(Q)
false
julia> Q = quaternion_algebra(QQ, 1, -1)
Quaternion algebra
over rational field
defined by i^2 = 1, j^2 = -1
julia> is_split(Q)
true
julia> is_split_with_zero_divisor(Q)
(true, 1 + i)
Solving norm equations
Let's solve a norm equation. We want to check whether
julia> K, sqrt2 = quadratic_field(2)
(Real quadratic field defined by x^2 - 2, sqrt(2))
julia> fl, a = is_norm(K, 2);
julia> fl
true
Since elements with given norm are in general large, they are represented in special "factored" form:
julia> a
(sqrt(2) + 64)^1*89^-1*(sqrt(2) + 25)^1*23^-1*1^-1*(sqrt(2) + 5)^1*7^-1*(sqrt(2) + 3)^1
We can turn this into an ordinary elements using evaluate
:
julia> b = evaluate(a)
sqrt(2) + 2
julia> norm(b) == 2
true
If we know that a norm equation has a solution, we can directly ask for it:
julia> norm_equation(K, 2)
sqrt(2) + 2
Representation by binary quadratic forms
Assume that we have two diagonal quadratic forms
julia> K = QQ;
julia> a1, a2 = 2, 3
(2, 3)
julia> b1, b2 = 3, 4
(3, 4)
We form the quadratic form
julia> q = quadratic_space(K, diagonal_matrix(K, [a1, a2, -b1, b2]));
Checking whether such an isotropic vector exists:
julia> is_isotropic(q)
true
julia> fl, v = is_isotropic_with_vector(q)
(true, QQFieldElem[0, -1//6, 1//6, 0])
To extract the element
julia> d = v[1]^2 * a1 + v[2]^2 * a2
1//12
julia> v[1]^2 * a1 + v[2]^2 * a2 == v[3]^2 * b1 + v[4]^2 * b2
true