+def _charpoly_sage_input(s):
+ r"""
+ Helper function that you can use on the string output from sage
+ to convert a charpoly coefficient into the corresponding input
+ to be cached.
+
+ SETUP::
+
+ sage: from mjo.eja.eja_algebra import JordanSpinEJA
+ sage: from mjo.eja.eja_utils import _charpoly_sage_input
+
+ EXAMPLES::
+
+ sage: J = JordanSpinEJA(4,QQ)
+ sage: a = J._charpoly_coefficients()
+ sage: a[0]
+ X1^2 - X2^2 - X3^2 - X4^2
+ sage: _charpoly_sage_input(str(a[0]))
+ 'X[0]**2 - X[1]**2 - X[2]**2 - X[3]**2'
+
+ """
+ import re
+
+ exponent_out = r"\^"
+ exponent_in = r"**"
+
+ digit_out = r"X([0-9]+)"
+
+ def replace_digit(m):
+ # m is a match object
+ return "X[" + str(int(m.group(1)) - 1) + "]"
+
+ s = re.sub(exponent_out, exponent_in, s)
+ return re.sub(digit_out, replace_digit, s)
+
+
+def _scale(x, alpha):
+ r"""
+ Scale the vector, matrix, or cartesian-product-of-those-things
+ ``x`` by ``alpha``.
+
+ This works around the inability to scale certain elements of
+ Cartesian product spaces, as reported in
+
+ https://trac.sagemath.org/ticket/31435
+
+ ..WARNING:
+
+ This will do the wrong thing if you feed it a tuple or list.
+
+ SETUP::
+
+ sage: from mjo.eja.eja_utils import _scale
+
+ EXAMPLES::
+
+ sage: v = vector(QQ, (1,2,3))
+ sage: _scale(v,2)
+ (2, 4, 6)
+ sage: m = matrix(QQ, [[1,2],[3,4]])
+ sage: M = cartesian_product([m.parent(), m.parent()])
+ sage: _scale(M((m,m)), 2)
+ ([2 4]
+ [6 8], [2 4]
+ [6 8])
+
+ """
+ if hasattr(x, 'cartesian_factors'):
+ P = x.parent()
+ return P(tuple( _scale(x_i, alpha)
+ for x_i in x.cartesian_factors() ))
+ else:
+ return x*alpha
+
+