def arithmetic(self, ex, operator): r""" This is the only method of the base class :class:`~sage.symbolic.expression_conversions.ExpressionTreeWalker` that is reimplemented, since square roots are considered as arithmetic operations with ``operator`` = ``pow`` and ``ex.operands()[1]`` = ``1/2`` or ``-1/2``. INPUT: - ``ex`` -- a symbolic expression - ``operator`` -- an arithmetic operator OUTPUT: - a symbolic expression, equivalent to ``ex`` with square roots simplified EXAMPLES:: sage: from sage.manifolds.utilities import SimplifySqrtReal sage: a = sqrt(x^2+2*x+1) sage: s = SimplifySqrtReal(a) sage: a.operator() <built-in function pow> sage: s.arithmetic(a, a.operator()) abs(x + 1) :: sage: a = x + 1 # no square root sage: s.arithmetic(a, a.operator()) x + 1 :: sage: a = x + 1 + sqrt(function('f')(x)^2) sage: s.arithmetic(a, a.operator()) x + abs(f(x)) + 1 """ if operator is _pow: operands = ex.operands() power = operands[1] one_half = Rational((1, 2)) minus_one_half = -one_half if (power == one_half) or (power == minus_one_half): # This is a square root or the inverse of a square root w0 = SR.wild(0) w1 = SR.wild(1) sqrt_pattern = w0**one_half inv_sqrt_pattern = w0**minus_one_half sqrt_ratio_pattern1 = w0**one_half * w1**minus_one_half sqrt_ratio_pattern2 = w0**minus_one_half * w1**one_half argum = operands[0] # the argument of sqrt if argum.has(sqrt_pattern) or argum.has(inv_sqrt_pattern): argum = self(argum) # treatment of nested sqrt's den = argum.denominator() if not (den == 1): # the argument of sqrt is a fraction # NB: after #19312 (integrated in Sage 6.10.beta7), the # above test cannot be written as "if den != 1:" num = argum.numerator() if num < 0 or den < 0: ex = sqrt(-num) / sqrt(-den) else: ex = sqrt(argum) else: ex = sqrt(argum) simpl = SR(ex._maxima_().radcan()) if (not simpl.match(sqrt_pattern) and not simpl.match(inv_sqrt_pattern) and not simpl.match(sqrt_ratio_pattern1) and not simpl.match(sqrt_ratio_pattern2)): # radcan transformed substantially the expression, # possibly getting rid of some sqrt; in order to ensure a # positive result, the absolute value of radcan's output # is taken, the call to simplify() taking care of possible # assumptions regarding signs of subexpression of simpl: simpl = abs(simpl).simplify() if power == minus_one_half: simpl = SR(1) / simpl return simpl # If operator is not a square root, we default to ExpressionTreeWalker: return super(SimplifySqrtReal, self).arithmetic(ex, operator)