V = VectorSpace(field, degree)
- # If we were asked to orthonormalize, and if the orthonormal
- # basis is different from the given one, then we also want to
- # compute multiplication and inner-product tables for the
- # deorthonormalized basis. These can be used later to
- # construct a deorthonormalized copy of this algebra over QQ
- # in which several operations are much faster.
+ # Save a copy of an algebra with the original, rational basis
+ # and over QQ where computations are fast.
self._rational_algebra = None
- if orthonormalize:
- if self.base_ring() is not QQ:
- # There's no point in constructing the extra algebra if this
- # one is already rational. If the original basis is rational
- # but normalization would make it irrational, then this whole
- # constructor will just fail anyway as it tries to stick an
- # irrational number into a rational algebra.
- #
- # Note: the same Jordan and inner-products work here,
- # because they are necessarily defined with respect to
- # ambient coordinates and not any particular basis.
- self._rational_algebra = RationalBasisEuclideanJordanAlgebra(
- basis,
- jordan_product,
- inner_product,
- field=QQ,
- orthonormalize=False,
- prefix=prefix,
- category=category,
- check_field=False,
- check_axioms=False)
+ if field is not QQ:
+ # There's no point in constructing the extra algebra if this
+ # one is already rational.
+ #
+ # Note: the same Jordan and inner-products work here,
+ # because they are necessarily defined with respect to
+ # ambient coordinates and not any particular basis.
+ self._rational_algebra = RationalBasisEuclideanJordanAlgebra(
+ basis,
+ jordan_product,
+ inner_product,
+ field=QQ,
+ orthonormalize=False,
+ prefix=prefix,
+ category=category,
+ check_field=False,
+ check_axioms=False)
+ if orthonormalize:
# Compute the deorthonormalized tables before we orthonormalize
# the given basis. The "check" parameter here guarantees that
# the basis is linearly-independent.
Algebraic Real Field
"""
- if self.base_ring() is QQ or self._rational_algebra is None:
+ if self._rational_algebra is None:
# There's no need to construct *another* algebra over the
# rationals if this one is already over the
# rationals. Likewise, if we never orthonormalized our
This gives the same answer as it would if we computed the trace
from the unembedded (original) matrices::
+ sage: set_random_seed()
+ sage: J = RealSymmetricEJA.random_instance()
+ sage: x,y = J.random_elements(2)
+ sage: Xe = x.to_matrix()
+ sage: Ye = y.to_matrix()
+ sage: X = J.real_unembed(Xe)
+ sage: Y = J.real_unembed(Ye)
+ sage: expected = (X*Y).trace()
+ sage: actual = J.trace_inner_product(Xe,Ye)
+ sage: actual == expected
+ True
+
+ ::
+
sage: set_random_seed()
sage: J = ComplexHermitianEJA.random_instance()
sage: x,y = J.random_elements(2)
sage: Xe = x.to_matrix()
sage: Ye = y.to_matrix()
- sage: X = ComplexHermitianEJA.real_unembed(Xe)
- sage: Y = ComplexHermitianEJA.real_unembed(Ye)
+ sage: X = J.real_unembed(Xe)
+ sage: Y = J.real_unembed(Ye)
sage: expected = (X*Y).trace().real()
- sage: actual = ComplexHermitianEJA.trace_inner_product(Xe,Ye)
+ sage: actual = J.trace_inner_product(Xe,Ye)
sage: actual == expected
True
sage: x,y = J.random_elements(2)
sage: Xe = x.to_matrix()
sage: Ye = y.to_matrix()
- sage: X = QuaternionHermitianEJA.real_unembed(Xe)
- sage: Y = QuaternionHermitianEJA.real_unembed(Ye)
+ sage: X = J.real_unembed(Xe)
+ sage: Y = J.real_unembed(Ye)
sage: expected = (X*Y).trace().coefficient_tuple()[0]
- sage: actual = QuaternionHermitianEJA.trace_inner_product(Xe,Ye)
+ sage: actual = J.trace_inner_product(Xe,Ye)
sage: actual == expected
True
try:
# Works in QQ, AA, RDF, et cetera.
- return tr.real() / cls.dimension_over_reals()
+ return tr.real()
except AttributeError:
# A quaternion doesn't have a real() method, but does
# have coefficient_tuple() method that returns the
# coefficients of 1, i, j, and k -- in that order.
- return tr.coefficient_tuple()[0] / cls.dimension_over_reals()
+ return tr.coefficient_tuple()[0]
class RealMatrixEuclideanJordanAlgebra(MatrixEuclideanJordanAlgebra):
field = M.base_ring()
R = PolynomialRing(field, 'z')
z = R.gen()
+
+ # Sage doesn't know how to adjoin the complex "i" (the root of
+ # x^2 + 1) to a field in a general way. Here, we just enumerate
+ # all of the cases that I have cared to support so far.
if field is AA:
# Sage doesn't know how to embed AA into QQbar, i.e. how
# to adjoin sqrt(-1) to AA.
F = QQbar
+ elif not field.is_exact():
+ # RDF or RR
+ F = field.complex_field()
else:
+ # Works for QQ and... maybe some other fields.
F = field.extension(z**2 + 1, 'I', embedding=CLF(-1).sqrt())
i = F.gen()