+def _change_ring(x, R):
+ r"""
+ Change the ring of a vector, matrix, or a cartesian product of
+ those things.
+
+ SETUP::
+
+ sage: from mjo.eja.eja_utils import _change_ring
+
+ EXAMPLES::
+
+ sage: v = vector(QQ, (1,2,3))
+ sage: m = matrix(QQ, [[1,2],[3,4]])
+ sage: _change_ring(v, RDF)
+ (1.0, 2.0, 3.0)
+ sage: _change_ring(m, RDF)
+ [1.0 2.0]
+ [3.0 4.0]
+ sage: _change_ring((v,m), RDF)
+ (
+ [1.0 2.0]
+ (1.0, 2.0, 3.0), [3.0 4.0]
+ )
+ sage: V1 = cartesian_product([v.parent(), v.parent()])
+ sage: V = cartesian_product([v.parent(), V1])
+ sage: V((v, (v, v)))
+ ((1, 2, 3), ((1, 2, 3), (1, 2, 3)))
+ sage: _change_ring(V((v, (v, v))), RDF)
+ ((1.0, 2.0, 3.0), ((1.0, 2.0, 3.0), (1.0, 2.0, 3.0)))
+
+ """
+ try:
+ return x.change_ring(R)
+ except AttributeError:
+ try:
+ from sage.categories.sets_cat import cartesian_product
+ if hasattr(x, 'element_class'):
+ # x is a parent and we're in a recursive call.
+ return cartesian_product( [_change_ring(x_i, R)
+ for x_i in x.cartesian_factors()] )
+ else:
+ # x is an element, and we want to change the ring
+ # of its parent.
+ P = x.parent()
+ Q = cartesian_product( [_change_ring(P_i, R)
+ for P_i in P.cartesian_factors()] )
+ return Q(x)
+ except AttributeError:
+ # No parent for x
+ return x.__class__( _change_ring(x_i, R) for x_i in x )
+
+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
+
+