# deorthonormalized basis. These can be used later to
# construct a deorthonormalized copy of this algebra over QQ
# in which several operations are much faster.
- self._deortho_multiplication_table = None
- self._deortho_inner_product_table = None
+ 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(
+ QQ,
+ basis,
+ jordan_product,
+ inner_product,
+ orthonormalize=False,
+ prefix=prefix,
+ category=category,
+ check_field=False,
+ check_axioms=False)
+
# Compute the deorthonormalized tables before we orthonormalize
# the given basis.
W = V.span_of_basis( vector_basis )
- # TODO: use symmetry
- self._deortho_multiplication_table = [ [0 for j in range(n)]
- for i in range(n) ]
- self._deortho_inner_product_table = [ [0 for j in range(n)]
- for i in range(n) ]
-
# Note: the Jordan and inner-products are defined in terms
# of the ambient basis. It's important that their arguments
# are in ambient coordinates as well.
# table is in terms of vectors
elt = _mat2vec(elt)
- # TODO: use symmetry
- elt = W.coordinate_vector(elt)
- self._deortho_multiplication_table[i][j] = elt
- self._deortho_multiplication_table[j][i] = elt
- self._deortho_inner_product_table[i][j] = ip
- self._deortho_inner_product_table[j][i] = ip
-
- if self._deortho_multiplication_table is not None:
- self._deortho_multiplication_table = tuple(map(tuple, self._deortho_multiplication_table))
- if self._deortho_inner_product_table is not None:
- self._deortho_inner_product_table = tuple(map(tuple, self._deortho_inner_product_table))
-
# We overwrite the name "vector_basis" in a second, but never modify it
# in place, to this effectively makes a copy of it.
deortho_vector_basis = vector_basis
self._deortho_matrix = matrix( U.coordinate_vector(q)
for q in vector_basis )
- # TODO: use symmetry
- mult_table = [ [0 for j in range(n)] for i in range(n) ]
- ip_table = [ [0 for j in range(n)] for i in range(n) ]
+ # If the superclass constructor is going to verify the
+ # symmetry of this table, it has better at least be
+ # square...
+ if check_axioms:
+ mult_table = [ [0 for j in range(n)] for i in range(n) ]
+ ip_table = [ [0 for j in range(n)] for i in range(n) ]
+ else:
+ mult_table = [ [0 for j in range(i+1)] for i in range(n) ]
+ ip_table = [ [0 for j in range(i+1)] for i in range(n) ]
# Note: the Jordan and inner-products are defined in terms
# of the ambient basis. It's important that their arguments
# table is in terms of vectors
elt = _mat2vec(elt)
- # TODO: use symmetry
elt = W.coordinate_vector(elt)
mult_table[i][j] = elt
- mult_table[j][i] = elt
ip_table[i][j] = ip
- ip_table[j][i] = ip
+ if check_axioms:
+ # The tables are square if we're verifying that they
+ # are commutative.
+ mult_table[j][i] = elt
+ ip_table[j][i] = ip
if basis_is_matrices:
for m in basis:
# Do the computation over the rationals. The answer will be
# the same, because all we've done is a change of basis.
- J = FiniteDimensionalEuclideanJordanAlgebra(QQ,
- self._deortho_multiplication_table,
- self._deortho_inner_product_table)
-
- # Change back from QQ to our real base ring
+ # Then, change back from QQ to our real base ring
a = ( a_i.change_ring(self.base_ring())
- for a_i in J._charpoly_coefficients() )
+ for a_i in self._rational_algebra._charpoly_coefficients() )
# Now convert the coordinate variables back to the
# deorthonormalized ones.
else:
Sij = Eij + Eij.transpose()
S.append(Sij)
- return S
+ return tuple(S)
@staticmethod
n2 = J2.dimension()
n = n1+n2
V = VectorSpace(field, n)
- mult_table = [ [ V.zero() for j in range(n) ]
+ mult_table = [ [ V.zero() for j in range(i+1) ]
for i in range(n) ]
for i in range(n1):
- for j in range(n1):
+ for j in range(i+1):
p = (J1.monomial(i)*J1.monomial(j)).to_vector()
mult_table[i][j] = V(p.list() + [field.zero()]*n2)
for i in range(n2):
- for j in range(n2):
+ for j in range(i+1):
p = (J2.monomial(i)*J2.monomial(j)).to_vector()
mult_table[n1+i][n1+j] = V([field.zero()]*n1 + p.list())
# TODO: build the IP table here from the two constituent IP
# matrices (it'll be block diagonal, I think).
- ip_table = None
+ ip_table = [ [ field.zero() for j in range(i+1) ]
+ for i in range(n) ]
super(DirectSumEJA, self).__init__(field,
mult_table,
ip_table,