Python ints, longs and floats may be passed to the
QuaternionAlgebra(a,b) constructor, as may all pairs of nonzero
elements of a ring not of characteristic 2. The following tests address
the issues raised in trac ticket #10601:

sage: QuaternionAlgebra(1r,1)Quaternion Algebra (1, 1) with base ring Rational Fieldsage: QuaternionAlgebra(1,1.0r)Quaternion Algebra (1.00000000000000, 1.00000000000000) with base ring Real Field with 53 bits of precisionsage: QuaternionAlgebra(0,0)Traceback (most recent call last):...ValueError: a and b must be nonzerosage: QuaternionAlgebra(GF(2)(1),1)Traceback (most recent call last):...ValueError: a and b must be elements of a ring with characteristic not 2sage: a=PermutationGroupElement([1,2,3])sage: QuaternionAlgebra(a,a)Traceback (most recent call last):...ValueError: a and b must be elements of a ring with characteristic not 2

Return the inner product matrix associated to self, i.e. the
Gram matrix of the reduced norm as a quadratic form on self.
The standard basis \(1\), \(i\), \(j\), \(k\) is orthogonal, so this matrix
is just the diagonal matrix with diagonal entries \(1\), \(a\), \(b\), \(ab\).

This is \(2\times 2\)
matrices \(I\), \(J\), \(K\) over the finite field \(\GF{p}\) such that if
the quaternion algebra has generators \(i, j, k\), then \(I^2 =
i^2\), \(J^2 = j^2\), \(IJ=K\) and \(IJ=-JI\).

Note

Currently only implemented when \(p\) is odd and the base
ring is \(\QQ\).

sage: Q.modp_splitting_data(5)Traceback (most recent call last):...NotImplementedError: algorithm for computing local splittings not implemented in general (currently require the first invariant to be coprime to p)sage: Q.modp_splitting_data(2)Traceback (most recent call last):...NotImplementedError: p must be odd

This is the
Gram matrix of the reduced norm as a quadratic form on self.
The standard basis \(1\), \(i\), \(j\), \(k\) is orthogonal, so this matrix
is just the diagonal matrix with diagonal entries \(2\), \(2a\), \(2b\),
\(2ab\).

Return basis matrix \(M\) in Hermite normal form for self as a
matrix with rational entries.

If \(Q\) is the ambient quaternion algebra, then the \(\ZZ\)-span of
the rows of \(M\) viewed as linear combinations of Q.basis() =
\([1,i,j,k]\) is the fractional ideal self. Also,
M*M.denominator() is an integer matrix in Hermite normal form.

Let \(I\) = self. This function returns the right subideals
\(J\) of \(I\) such that \(I/J\) is an \(\GF{p}\)-vector space of
dimension 2.

INPUT:

p – prime number (see below)

alpha – (default: None) element of quaternion algebra,
which can be used to parameterize the order of the
ideals \(J\). More precisely the \(J\)’s are the right annihilators
of \((1,0) \alpha^i\) for \(i=0,1,2,...,p\)

OUTPUT:

list of right ideals

Note

Currently, \(p\) must satisfy a bunch of conditions, or a
NotImplementedError is raised. In particular, \(p\) must be
odd and unramified in the quaternion algebra, must be
coprime to the index of the right order in the maximal
order, and also coprime to the normal of self. (The Brandt
modules code has a more general algorithm in some cases.)

sage: I.cyclic_right_subideals(3)[0].cyclic_right_subideals(3)Traceback (most recent call last):...NotImplementedError: general algorithm not implemented (The given basis vectors must be linearly independent.)

The following is a big consistency check. We take reps for
all the right ideal classes of a certain order, take the
corresponding left orders, then take ideals in the left orders
and from those compute the right order again:

This function computes the positive definition quadratic form
obtained by letting G be the trace zero subspace of \(\ZZ\) +
2* self, which has rank 3, and restricting the pairing:

(x,y) = (x.conjugate()*y).reduced_trace()

to \(G\).

APPLICATIONS: Ternary quadratic forms associated to an order
in a rational quaternion algebra are useful in computing with
Gross points, in decided whether quaternion orders have
embeddings from orders in quadratic imaginary fields, and in
computing elements of the Kohnen plus subspace of modular
forms of weight 3/2.

Intersect the \(\ZZ\)-modules with basis matrices the full rank \(4 \times 4\)\(\QQ\)-matrices in the list v.

The returned intersection is
represented by a \(4 \times 4\) matrix over \(\QQ\). This can also be done
using modules and intersection, but that would take over twice as long
because of overhead, hence this function.

Compute a (at p) normalized basis from the given basis e
of a \(\ZZ\)-module.

The returned basis is (at p) a \(\ZZ_p\) basis for the same
module, and has the property that with respect to it the quadratic
form induced by the bilinear form B is represented as a orthogonal
sum of atomic forms multiplied by p-powers.

If \(p \neq 2\) this means that the form is diagonal with respect to
this basis.

If \(p = 2\) there may be additional 2-dimensional subspaces on which
the form is represented as \(2^e (ax^2 + bxy + cx^2)\) with
\(0 = v_2(b) = v_2(a) \leq v_2(c)\).

INPUT:

e – list; basis of a \(\ZZ\) module.
WARNING: will be modified!

p – prime for at which the basis should be normalized

B – (default:
lambdax,y:((x*y).conjugate()).reduced_trace())
a bilinear form with respect to which to normalize

OUTPUT:

A list containing two-element tuples: The first element of
each tuple is a basis element, the second the valuation of
the orthogonal summand to which it belongs. The list is sorted
by ascending valuation.