+
+ # BEWARE: The subalgebra_generated_by() method uses the result
+ # of this method to construct a basis for the subalgebra. That
+ # means, in particular, that we cannot implement this method
+ # as ``self.subalgebra_generated_by().dimension()``.
+
+ # Algorithm: keep appending (vector representations of) powers
+ # self as rows to a matrix and echelonizing it. When its rank
+ # stops increasing, we've reached a redundancy.
+
+ # Given the special cases above, we can assume that "self" is
+ # nonzero, the algebra is nontrivial, and that its dimension
+ # is at least two.
+ M = matrix([(self.parent().one()).to_vector()])
+ old_rank = 1
+
+ # Specifying the row-reduction algorithm can e.g. help over
+ # AA because it avoids the RecursionError that gets thrown
+ # when we have to look too hard for a root.
+ #
+ # Beware: QQ supports an entirely different set of "algorithm"
+ # keywords than do AA and RR.
+ algo = None
+ from sage.rings.all import QQ
+ if self.parent().base_ring() is not QQ:
+ algo = "scaled_partial_pivoting"
+
+ for d in range(1,n):
+ M = matrix(M.rows() + [(self**d).to_vector()])
+ M.echelonize(algo)
+ new_rank = M.rank()
+ if new_rank == old_rank:
+ return new_rank
+ else:
+ old_rank = new_rank
+
+ return n
+