+class KnownRankEJA(object):
+ """
+ A class for algebras that we actually know we can construct. The
+ main issue is that, for most of our methods to make sense, we need
+ to know the rank of our algebra. Thus we can't simply generate a
+ "random" algebra, or even check that a given basis and product
+ satisfy the axioms; because even if everything looks OK, we wouldn't
+ know the rank we need to actuallty build the thing.
+
+ Not really a subclass of FDEJA because doing that causes method
+ resolution errors, e.g.
+
+ TypeError: Error when calling the metaclass bases
+ Cannot create a consistent method resolution
+ order (MRO) for bases FiniteDimensionalEuclideanJordanAlgebra,
+ KnownRankEJA
+
+ """
+ @staticmethod
+ def _max_test_case_size():
+ """
+ Return an integer "size" that is an upper bound on the size of
+ this algebra when it is used in a random test
+ case. Unfortunately, the term "size" is quite vague -- when
+ dealing with `R^n` under either the Hadamard or Jordan spin
+ product, the "size" refers to the dimension `n`. When dealing
+ with a matrix algebra (real symmetric or complex/quaternion
+ Hermitian), it refers to the size of the matrix, which is
+ far less than the dimension of the underlying vector space.
+
+ We default to five in this class, which is safe in `R^n`. The
+ matrix algebra subclasses (or any class where the "size" is
+ interpreted to be far less than the dimension) should override
+ with a smaller number.
+ """
+ return 5
+
+ @classmethod
+ def random_instance(cls, field=QQ, **kwargs):
+ """
+ Return a random instance of this type of algebra.
+
+ Beware, this will crash for "most instances" because the
+ constructor below looks wrong.
+ """
+ if cls is TrivialEJA:
+ # The TrivialEJA class doesn't take an "n" argument because
+ # there's only one.
+ return cls(field)
+
+ n = ZZ.random_element(cls._max_test_case_size()) + 1
+ return cls(n, field, **kwargs)
+
+
+class RealCartesianProductEJA(FiniteDimensionalEuclideanJordanAlgebra,
+ KnownRankEJA):