# Ticket #13355: trac_13355_plot_with_complex_intermediates.patch

File trac_13355_plot_with_complex_intermediates.patch, 7.8 KB (added by tkluck, 6 years ago)
• ## sage/ext/fast_callable.pyx

```# HG changeset patch
# User Timo Kluck <tkluck@infty.nl>
# Date 1344514850 -7200
# Node ID d683f2edd6b10f1e8b770dec7ebd761492c4a176
Fix plotting with complex intermediates

diff --git a/sage/ext/fast_callable.pyx b/sage/ext/fast_callable.pyx```
 a sage: fc = fast_callable(expr, domain=float) sage: fc(5, 7) 0.5514266812416906 Check that fast_callable also works for symbolic functions with evaluation functions: sage: def evalf_func(self, x, y, parent): return parent(x*y) sage: x,y = var('x,y') sage: f = function('f', evalf_func=evalf_func) sage: fc = fast_callable(f(x,y), vars=[x,y]) sage: fc(3,4) 12.0 """ cdef Expression et if isinstance(x, Expression):
• ## sage/symbolic/expression.pyx

`diff --git a/sage/symbolic/expression.pyx b/sage/symbolic/expression.pyx`
 a from sage.symbolic.expression_conversions import fast_float return fast_float(self, *vars) def _fast_callable_(self, etb): """ Given an ExpressionTreeBuilder *etb*, return an Expression representing sage: abs((I*10+1)^4) 10201 sage: plot(s) Check that this also works when we plot a function that implicitely takes complex values: sage: f = function('f', evalf_func=lambda self,x,parent: I*x) sage: plot(abs(f(x)), 0,5) """ try: # First we try fast float.  However, this doesn't work on some
• ## sage/symbolic/expression_conversions.py

`diff --git a/sage/symbolic/expression_conversions.py b/sage/symbolic/expression_conversions.py`
 a 1.41421356237309... """ f = operator if f.range_for_domain(float) != float: raise TypeError("Cannot use fast_float to calculate a function with complex intermediates") g = map(self, ex.operands()) try: return f(*g) sin(sqrt(add(v_0, v_1))) sage: arctan2(x,y)._fast_callable_(etb) {arctan2}(v_0, v_1) sage: def evalf_func(self, x, y, parent): return parent(x*y) sage: f = function('f', evalf_func=evalf_func) sage: f(x,y)._fast_callable_(etb) {evalf_func}(v_0, v_1, ) """ return self.etb.call(function, *ex.operands()) try: domain = self.etb._domain if domain == None: domain = float return self.etb.call(function._evalf_, *(ex.operands() + [domain])) except AttributeError: return self.etb.call(function, *ex.operands()) def fast_callable(ex, etb):
• ## sage/symbolic/function.pyx

`diff --git a/sage/symbolic/function.pyx b/sage/symbolic/function.pyx`
 a """ raise NotImplementedError("The Function %s does not support numpy arrays as arguments" % self.name()) def range_for_domain(self, domain): """ Return the parent of self(x) when x is an element of domain It is very common for functions to return real values when given a real value and complex values when given a complex value. Such functions can specify that by overriding this function, which will enable certain optimizations. The default implementation returns the complex field corresponding to domain, and `complex` if it cannot find one. Default behaviour: sage: f = function('f') sage: f.range_for_domain(float) sage: f.range_for_domain(RR) Complex Field with 53 bits of precision Common behaviour: sage: sin.range_for_domain(float) sage: sin.range_for_domain(RR) Real Field with 53 bits of precision sage: sin.range_for_domain(CC) Complex Field with 53 bits of precision """ try: return domain.complex_field() except AttributeError: return complex cdef class GinacFunction(BuiltinFunction): """ This class provides a wrapper around symbolic functions already defined in # we should never end up here raise ValueError, "cannot read pickle" def range_for_domain(self, domain): """ Return the parent of self(x) when x is an element of domain All builtin functions return real values when given a real value and complex values when given a complex value. We specify that in this override. Behaviour for builtin functions: sage: sin.range_for_domain(float) sage: sin.range_for_domain(RR) Real Field with 53 bits of precision sage: sin.range_for_domain(CC) Complex Field with 53 bits of precision """ return domain cdef class SymbolicFunction(Function): """
• ## sage/ext/fast_callable.pyx

```# HG changeset patch
# User Timo Kluck <tkluck@infty.nl>
# Date 1344521180 -7200
# Node ID aae73ef825642da8f76d731cd4d7f37d79d8d13b
# Parent  d683f2edd6b10f1e8b770dec7ebd761492c4a176
handle domain properly in evalf functions

diff --git a/sage/ext/fast_callable.pyx b/sage/ext/fast_callable.pyx```
 a Check that fast_callable also works for symbolic functions with evaluation functions: sage: def evalf_func(self, x, y, parent): return parent(x*y) sage: def evalf_func(self, x, y, parent): return parent(x*y) if parent!=None else x*y sage: x,y = var('x,y') sage: f = function('f', evalf_func=evalf_func) sage: fc = fast_callable(f(x,y), vars=[x,y]) sage: fc(3,4) 12.0 12 And also when there's complex values involved: sage: def evalf_func(self, x, y, parent): return parent(I*x*y) if parent!=None else I*x*y sage: g = function('g', evalf_func=evalf_func) sage: fc = fast_callable(g(x,y), vars=[x,y]) sage: fc(3,4) 12*I sage: fc2 = fast_callable(g(x,y), domain=complex, vars=[x,y]) sage: fc2(3,4) 12j sage: fc3 = fast_callable(g(x,y), domain=float, vars=[x,y]) sage: fc3(3,4) Traceback (most recent call last): ... TypeError: unable to simplify to float approximation """ cdef Expression et if isinstance(x, Expression):
• ## sage/symbolic/expression_conversions.py

`diff --git a/sage/symbolic/expression_conversions.py b/sage/symbolic/expression_conversions.py`
 a sage: def evalf_func(self, x, y, parent): return parent(x*y) sage: f = function('f', evalf_func=evalf_func) sage: f(x,y)._fast_callable_(etb) {evalf_func}(v_0, v_1, ) {placeholder_function}(v_0, v_1) """ try: domain = self.etb._domain if domain == None: domain = float return self.etb.call(function._evalf_, *(ex.operands() + [domain])) except AttributeError: if hasattr(function, "_evalf_"): def placeholder_function(*args): return function._evalf_(*args, parent=self.etb._domain) return self.etb.call(placeholder_function, *ex.operands()) else: return self.etb.call(function, *ex.operands())