Skip to content

Commit 7cde1ca

Browse files
Release Managervbraun
Release Manager
authored andcommitted
Trac #17130: Fix coercion bugs in symbolic functions
This uses coercion correctly: {{{ sage: bessel_Y._eval_(RealField(300)(1), 1.0) -0.781212821300289 }}} However, it seems that `__call__()` coerces this result back to the first parent, giving false precision: {{{ sage: bessel_Y(RealField(300)(1), 1.0) -0.781212821300288684511770043172873556613922119140625000000000000000000 000000000000000000000 }}} Same issue with functions which are evaluated using Maxima, which does not support arbitrary precision: {{{ sage: R=RealField(300); elliptic_eu(R(1/2), R(1/8)) 0.4950737320232014848642165816272608935832977294921875000000000000000000 00000000000000000000 }}} The `gamma_inc()` function also mishandles parents: {{{ sage: gamma_inc(float(0), float(1)) AttributeError: type object 'float' has no attribute 'precision' }}} ---- Apart from this, this branch also removes lots of boilerplate from `_eval_` like {{{ if not isinstance(x, Expression) and not isinstance(y, Expression) and \ (is_inexact(x) or is_inexact(y)): x, y = coercion_model.canonical_coercion(x, y) return self._evalf_(x, y, s_parent(x)) }}} by wrapping `_eval_` inside the new method `_evalf_or_eval_` which automatically does this boilerplate. ---- Possible follow-ups: #10133, #14766, #16587, #17122, #15200 URL: http://trac.sagemath.org/17130 Reported by: jdemeyer Ticket author(s): Jeroen Demeyer Reviewer(s): Ralf Stephan
2 parents 23a8b0e + abab222 commit 7cde1ca

17 files changed

+370
-367
lines changed

src/doc/en/reference/calculus/index.rst

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@ Symbolic Calculus
77
sage/symbolic/expression
88
sage/symbolic/assumptions
99
sage/symbolic/relation
10-
sage/symbolic/function_factory
1110
sage/calculus/calculus
1211
sage/symbolic/units
1312
sage/symbolic/ring
14-
sage/calculus/functional
1513
sage/symbolic/function
14+
sage/symbolic/function_factory
15+
sage/calculus/functional
1616
sage/symbolic/integration/integral
1717
sage/calculus/test_sympy
1818
sage/calculus/tests

src/sage/functions/bessel.py

+16-54
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@
189189
from sage.structure.coerce import parent
190190
from sage.structure.element import get_coercion_model
191191
from sage.symbolic.constants import pi
192-
from sage.symbolic.function import BuiltinFunction, is_inexact
192+
from sage.symbolic.function import BuiltinFunction
193193
from sage.symbolic.expression import Expression
194194

195195
# remove after deprecation period
@@ -303,25 +303,6 @@ def __init__(self):
303303
maxima='bessel_j',
304304
sympy='besselj'))
305305

306-
def _eval_(self, n, x):
307-
"""
308-
EXAMPLES::
309-
310-
sage: a, b = var('a, b')
311-
sage: bessel_J(a, b)
312-
bessel_J(a, b)
313-
sage: bessel_J(1.0, 1.0)
314-
0.440050585744933
315-
"""
316-
if (not isinstance(n, Expression) and
317-
not isinstance(x, Expression) and
318-
(is_inexact(n) or is_inexact(x))):
319-
coercion_model = get_coercion_model()
320-
n, x = coercion_model.canonical_coercion(n, x)
321-
return self._evalf_(n, x, parent(n))
322-
323-
return None
324-
325306
def _evalf_(self, n, x, parent=None, algorithm=None):
326307
"""
327308
EXAMPLES::
@@ -405,6 +386,8 @@ class Function_Bessel_Y(BuiltinFunction):
405386
1.03440456978312 - 0.135747669767038*I
406387
sage: bessel_Y(0, 0).n()
407388
-infinity
389+
sage: bessel_Y(0, 1).n(128)
390+
0.088256964215676957982926766023515162828
408391
409392
Examples of symbolic manipulation::
410393
@@ -438,10 +421,23 @@ class Function_Bessel_Y(BuiltinFunction):
438421
Numerical evaluation is handled by the mpmath library. Symbolics are
439422
handled by a combination of Maxima and Sage (Ginac/Pynac).
440423
424+
TESTS:
425+
441426
Check whether the return value is real whenever the argument is real (:trac:`10251`)::
442427
443428
sage: bessel_Y(5, 1.5) in RR
444429
True
430+
431+
Coercion works correctly (see :trac:`17130`)::
432+
433+
sage: r = bessel_Y(RealField(200)(1), 1.0); r
434+
-0.781212821300289
435+
sage: parent(r)
436+
Real Field with 53 bits of precision
437+
sage: r = bessel_Y(RealField(200)(1), 1); r
438+
-0.78121282130028871654715000004796482054990639071644460784383
439+
sage: parent(r)
440+
Real Field with 200 bits of precision
445441
"""
446442
def __init__(self):
447443
"""
@@ -457,24 +453,6 @@ def __init__(self):
457453
maxima='bessel_y',
458454
sympy='bessely'))
459455

460-
def _eval_(self, n, x):
461-
"""
462-
EXAMPLES::
463-
464-
sage: a,b = var('a, b')
465-
sage: bessel_Y(a, b)
466-
bessel_Y(a, b)
467-
sage: bessel_Y(0, 1).n(128)
468-
0.088256964215676957982926766023515162828
469-
"""
470-
if (not isinstance(n, Expression) and not isinstance(x, Expression) and
471-
(is_inexact(n) or is_inexact(x))):
472-
coercion_model = get_coercion_model()
473-
n, x = coercion_model.canonical_coercion(n, x)
474-
return self._evalf_(n, x, parent(n))
475-
476-
return None # leaves the expression unevaluated
477-
478456
def _evalf_(self, n, x, parent=None, algorithm=None):
479457
"""
480458
EXAMPLES::
@@ -632,20 +610,12 @@ def _eval_(self, n, x):
632610
sage: bessel_I(-1/2, pi)
633611
sqrt(2)*cosh(pi)/pi
634612
"""
635-
if (not isinstance(n, Expression) and not isinstance(x, Expression) and
636-
(is_inexact(n) or is_inexact(x))):
637-
coercion_model = get_coercion_model()
638-
n, x = coercion_model.canonical_coercion(n, x)
639-
return self._evalf_(n, x, parent(n))
640-
641613
# special identities
642614
if n == Integer(1) / Integer(2):
643615
return sqrt(2 / (pi * x)) * sinh(x)
644616
elif n == -Integer(1) / Integer(2):
645617
return sqrt(2 / (pi * x)) * cosh(x)
646618

647-
return None # leaves the expression unevaluated
648-
649619
def _evalf_(self, n, x, parent=None, algorithm=None):
650620
"""
651621
EXAMPLES::
@@ -810,18 +780,10 @@ def _eval_(self, n, x):
810780
sage: bessel_K(-1, 1).n(128)
811781
0.60190723019723457473754000153561733926
812782
"""
813-
if (not isinstance(n, Expression) and not isinstance(x, Expression) and
814-
(is_inexact(n) or is_inexact(x))):
815-
coercion_model = get_coercion_model()
816-
n, x = coercion_model.canonical_coercion(n, x)
817-
return self._evalf_(n, x, parent(n))
818-
819783
# special identity
820784
if n == Integer(1) / Integer(2) and x > 0:
821785
return sqrt(pi / 2) * exp(-x) * x ** (-Integer(1) / Integer(2))
822786

823-
return None # leaves the expression unevaluated
824-
825787
def _evalf_(self, n, x, parent=None, algorithm=None):
826788
"""
827789
EXAMPLES::

0 commit comments

Comments
 (0)