diff --git a/src/sage/interfaces/interface.py b/src/sage/interfaces/interface.py index 4b9e929645d..7c860137d31 100644 --- a/src/sage/interfaces/interface.py +++ b/src/sage/interfaces/interface.py @@ -1219,10 +1219,46 @@ def gen(self, n): P = self._check_valid() return P.new('%s.%s'%(self._name, int(n))) - def _operation(self, operation, right): + def _operation(self, operation, other=None): + r""" + Return the result of applying the binary operation + ``operation`` on the arguments ``self`` and ``other``, or the + unary operation on ``self`` if ``other`` is not given. + + This is a utility function which factors out much of the + commonality used in the arithmetic operations for interface + elements. + + INPUT: + + - ``operation`` -- a string representing the operation + being performed. For example, '*', or '1/'. + + - ``other`` -- the other operand. If ``other`` is ``None``, + then the operation is assumed to be unary rather than binary. + + OUTPUT: an interface element + + EXAMPLES:: + + sage: a = gp('23') + sage: b = gp('5') + sage: a._operation('%', b) + 3 + sage: a._operation('19+') + 42 + sage: a._operation('!@#$%') + Traceback (most recent call last): + ... + TypeError: Error executing code in GP:... + """ P = self._check_valid() + if other is None: + cmd = '%s %s'%(operation, self._name) + else: + cmd = '%s %s %s'%(self._name, operation, other._name) try: - return P.new('%s %s %s'%(self._name, operation, right._name)) + return P.new(cmd) except Exception as msg: raise TypeError(msg) @@ -1238,6 +1274,31 @@ def _add_(self, right): cos(_SAGE_VAR_x)+2 sage: 2 + f cos(_SAGE_VAR_x)+2 + + :: + + sage: x,y = var('x,y') + sage: f = maxima.function('x','sin(x)') + sage: g = maxima.function('x','-cos(x)') + sage: f+g + sin(x)-cos(x) + sage: f+3 + sin(x)+3 + + The Maxima variable ``x`` is different from the Sage symbolic variable:: + + sage: (f+maxima.cos(x)) + cos(_SAGE_VAR_x)+sin(x) + sage: (f+maxima.cos(y)) + cos(_SAGE_VAR_y)+sin(x) + + Note that you may get unexpected results when calling symbolic expressions + and not explicitly giving the variables:: + + sage: (f+maxima.cos(x))(2) + cos(_SAGE_VAR_x)+sin(2) + sage: (f+maxima.cos(y))(2) + cos(_SAGE_VAR_y)+sin(2) """ return self._operation("+", right) @@ -1253,9 +1314,42 @@ def _sub_(self, right): cos(_SAGE_VAR_x)-2 sage: 2 - f 2-cos(_SAGE_VAR_x) + + :: + + sage: x,y = var('x,y') + sage: f = maxima.function('x','sin(x)') + + The Maxima variable ``x`` is different from the Sage symbolic variable:: + + sage: (f-maxima.cos(x)) + sin(x)-cos(_SAGE_VAR_x) + sage: (f-maxima.cos(y)) + sin(x)-cos(_SAGE_VAR_y) + + Note that you may get unexpected results when calling symbolic expressions + and not explicitly giving the variables:: + + sage: (f-maxima.cos(x))(2) + sin(2)-cos(_SAGE_VAR_x) + sage: (f-maxima.cos(y))(2) + sin(2)-cos(_SAGE_VAR_y) """ return self._operation('-', right) + def _neg_(self): + """ + EXAMPLES:: + + sage: f = maxima('sin(x)') + sage: -f + -sin(x) + sage: f = maxima.function('x','sin(x)') + sage: -f + -sin(x) + """ + return self._operation('-') + def _mul_(self, right): """ EXAMPLES:: @@ -1266,6 +1360,26 @@ def _mul_(self, right): cos(_SAGE_VAR_x)*sin(_SAGE_VAR_x) sage: 2*f 2*cos(_SAGE_VAR_x) + + :: + + sage: f = maxima.function('x','sin(x)') + sage: g = maxima('-cos(x)') # not a function! + sage: f*g + -cos(x)*sin(x) + sage: _(2) + -cos(2)*sin(2) + + :: + + sage: f = maxima.function('x','sin(x)') + sage: g = maxima('-cos(x)') + sage: g*f + -cos(x)*sin(x) + sage: _(2) + -cos(2)*sin(2) + sage: 2*f + 2*sin(x) """ return self._operation('*', right) @@ -1279,9 +1393,42 @@ def _div_(self, right): cos(_SAGE_VAR_x)/sin(_SAGE_VAR_x) sage: f/2 cos(_SAGE_VAR_x)/2 + + :: + + sage: f = maxima.function('x','sin(x)') + sage: g = maxima('-cos(x)') + sage: f/g + -sin(x)/cos(x) + sage: _(2) + -sin(2)/cos(2) + + :: + + sage: f = maxima.function('x','sin(x)') + sage: g = maxima('-cos(x)') + sage: g/f + -cos(x)/sin(x) + sage: _(2) + -cos(2)/sin(2) + sage: 2/f + 2/sin(x) """ return self._operation("/", right) + def __invert__(self): + """ + EXAMPLES:: + + sage: f = maxima('sin(x)') + sage: ~f + 1/sin(x) + sage: f = maxima.function('x','sin(x)') + sage: ~f + 1/sin(x) + """ + return self._operation('1/') + def _mod_(self, right): """ EXAMPLES:: @@ -1300,6 +1447,20 @@ def __pow__(self, n): sage: a = maxima('2') sage: a^(3/4) 2^(3/4) + + :: + + sage: f = maxima.function('x','sin(x)') + sage: g = maxima('-cos(x)') + sage: f^g + 1/sin(x)^cos(x) + + :: + + sage: f = maxima.function('x','sin(x)') + sage: g = maxima('-cos(x)') # not a function + sage: g^f + (-cos(x))^sin(x) """ P = self._check_valid() if parent(n) is not P: diff --git a/src/sage/interfaces/maxima_abstract.py b/src/sage/interfaces/maxima_abstract.py index 6ff638aa610..079f9527653 100644 --- a/src/sage/interfaces/maxima_abstract.py +++ b/src/sage/interfaces/maxima_abstract.py @@ -1880,22 +1880,30 @@ def partial_fraction_decomposition(self, var='x'): """ return self.partfrac(var) - def _operation(self, operation, right): + def _operation(self, operation, other=None): r""" - Return the result of "self operation right" in Maxima. + Return the result of applying the binary operation + ``operation`` on the arguments ``self`` and ``other``, or the + unary operation on ``self`` if ``other`` is not given. + + This is a utility function which factors out much of the + commonality used in the arithmetic operations for interface + elements. INPUT: - - ``operation`` - string; operator + - ``operation`` -- a string representing the operation + being performed. For example, '*', or '1/'. - - ``right`` - Maxima object; right operand + - ``other`` -- the other operand. If ``other`` is ``None``, + then the operation is assumed to be unary rather than binary. OUTPUT: Maxima object - Note that right's parent should already be Maxima since this should + Note that other's parent should already be Maxima since this should be called after coercion has been performed. - If right is a ``MaximaFunction``, then we convert + If other is a ``MaximaFunction``, then we convert ``self`` to a ``MaximaFunction`` that takes no arguments, and let the ``MaximaFunction._operation`` code handle everything @@ -1909,12 +1917,15 @@ def _operation(self, operation, right): """ P = self._check_valid() - if isinstance(right, P._object_function_class()): + if other is None: + cmd = '%s %s'%(operation, self._name) + elif isinstance(other, P._object_function_class()): fself = P.function('', repr(self)) - return fself._operation(operation, right) - + return fself._operation(operation, other) + else: + cmd = '%s %s %s'%(self._name, operation, other._name) try: - return P.new('%s %s %s'%(self._name, operation, right._name)) + return P.new(cmd) except Exception as msg: raise TypeError(msg) @@ -2176,159 +2187,6 @@ def _operation(self, operation, f=None): return P.function(args,P.eval(defn)) - def _add_(self, f): - """ - This Maxima function as left summand. - - EXAMPLES:: - - sage: x,y = var('x,y') - sage: f = maxima.function('x','sin(x)') - sage: g = maxima.function('x','-cos(x)') - sage: f+g - sin(x)-cos(x) - sage: f+3 - sin(x)+3 - - The Maxima variable ``x`` is different from the Sage symbolic variable:: - - sage: (f+maxima.cos(x)) - cos(_SAGE_VAR_x)+sin(x) - sage: (f+maxima.cos(y)) - cos(_SAGE_VAR_y)+sin(x) - - Note that you may get unexpected results when calling symbolic expressions - and not explicitly giving the variables:: - - sage: (f+maxima.cos(x))(2) - cos(_SAGE_VAR_x)+sin(2) - sage: (f+maxima.cos(y))(2) - cos(_SAGE_VAR_y)+sin(2) - """ - return self._operation("+", f) - - def _sub_(self, f): - r""" - This Maxima function as minuend. - - EXAMPLES:: - - sage: x,y = var('x,y') - sage: f = maxima.function('x','sin(x)') - - The Maxima variable ``x`` is different from the Sage symbolic variable:: - - sage: (f-maxima.cos(x)) - sin(x)-cos(_SAGE_VAR_x) - sage: (f-maxima.cos(y)) - sin(x)-cos(_SAGE_VAR_y) - - Note that you may get unexpected results when calling symbolic expressions - and not explicitly giving the variables:: - - sage: (f-maxima.cos(x))(2) - sin(2)-cos(_SAGE_VAR_x) - sage: (f-maxima.cos(y))(2) - sin(2)-cos(_SAGE_VAR_y) - """ - return self._operation("-", f) - - def _mul_(self, f): - r""" - This Maxima function as left factor. - - EXAMPLES:: - - sage: f = maxima.function('x','sin(x)') - sage: g = maxima('-cos(x)') # not a function! - sage: f*g - -cos(x)*sin(x) - sage: _(2) - -cos(2)*sin(2) - - :: - - sage: f = maxima.function('x','sin(x)') - sage: g = maxima('-cos(x)') - sage: g*f - -cos(x)*sin(x) - sage: _(2) - -cos(2)*sin(2) - sage: 2*f - 2*sin(x) - """ - return self._operation("*", f) - - def _div_(self, f): - r""" - This Maxima function as dividend. - - EXAMPLES:: - - sage: f=maxima.function('x','sin(x)') - sage: g=maxima('-cos(x)') - sage: f/g - -sin(x)/cos(x) - sage: _(2) - -sin(2)/cos(2) - - :: - - sage: f=maxima.function('x','sin(x)') - sage: g=maxima('-cos(x)') - sage: g/f - -cos(x)/sin(x) - sage: _(2) - -cos(2)/sin(2) - sage: 2/f - 2/sin(x) - """ - return self._operation("/", f) - - def __neg__(self): - r""" - Additive inverse of this Maxima function. - - EXAMPLES:: - - sage: f=maxima.function('x','sin(x)') - sage: -f - -sin(x) - """ - return self._operation('-') - - def __inv__(self): - r""" - Multiplicative inverse of this Maxima function. - - EXAMPLES:: - - sage: f = maxima.function('x','sin(x)') - sage: ~f - 1/sin(x) - """ - return self._operation('1/') - - def __pow__(self,f): - r""" - This Maxima function raised to some power. - - EXAMPLES:: - - sage: f=maxima.function('x','sin(x)') - sage: g=maxima('-cos(x)') - sage: f^g - 1/sin(x)^cos(x) - - :: - - sage: f=maxima.function('x','sin(x)') - sage: g=maxima('-cos(x)') # not a function - sage: g^f - (-cos(x))^sin(x) - """ - return self._operation("^", f) - def reduce_load_MaximaAbstract_function(parent, defn, args, latex): r"""