Skip to content

Commit

Permalink
Trac #17130: Fix coercion bugs in symbolic functions
Browse files Browse the repository at this point in the history
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
  • Loading branch information
Release Manager authored and vbraun committed Nov 29, 2014
2 parents 23a8b0e + abab222 commit 7cde1ca
Show file tree
Hide file tree
Showing 17 changed files with 370 additions and 367 deletions.
4 changes: 2 additions & 2 deletions src/doc/en/reference/calculus/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ Symbolic Calculus
sage/symbolic/expression
sage/symbolic/assumptions
sage/symbolic/relation
sage/symbolic/function_factory
sage/calculus/calculus
sage/symbolic/units
sage/symbolic/ring
sage/calculus/functional
sage/symbolic/function
sage/symbolic/function_factory
sage/calculus/functional
sage/symbolic/integration/integral
sage/calculus/test_sympy
sage/calculus/tests
Expand Down
70 changes: 16 additions & 54 deletions src/sage/functions/bessel.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@
from sage.structure.coerce import parent
from sage.structure.element import get_coercion_model
from sage.symbolic.constants import pi
from sage.symbolic.function import BuiltinFunction, is_inexact
from sage.symbolic.function import BuiltinFunction
from sage.symbolic.expression import Expression

# remove after deprecation period
Expand Down Expand Up @@ -303,25 +303,6 @@ def __init__(self):
maxima='bessel_j',
sympy='besselj'))

def _eval_(self, n, x):
"""
EXAMPLES::
sage: a, b = var('a, b')
sage: bessel_J(a, b)
bessel_J(a, b)
sage: bessel_J(1.0, 1.0)
0.440050585744933
"""
if (not isinstance(n, Expression) and
not isinstance(x, Expression) and
(is_inexact(n) or is_inexact(x))):
coercion_model = get_coercion_model()
n, x = coercion_model.canonical_coercion(n, x)
return self._evalf_(n, x, parent(n))

return None

def _evalf_(self, n, x, parent=None, algorithm=None):
"""
EXAMPLES::
Expand Down Expand Up @@ -405,6 +386,8 @@ class Function_Bessel_Y(BuiltinFunction):
1.03440456978312 - 0.135747669767038*I
sage: bessel_Y(0, 0).n()
-infinity
sage: bessel_Y(0, 1).n(128)
0.088256964215676957982926766023515162828
Examples of symbolic manipulation::
Expand Down Expand Up @@ -438,10 +421,23 @@ class Function_Bessel_Y(BuiltinFunction):
Numerical evaluation is handled by the mpmath library. Symbolics are
handled by a combination of Maxima and Sage (Ginac/Pynac).
TESTS:
Check whether the return value is real whenever the argument is real (:trac:`10251`)::
sage: bessel_Y(5, 1.5) in RR
True
Coercion works correctly (see :trac:`17130`)::
sage: r = bessel_Y(RealField(200)(1), 1.0); r
-0.781212821300289
sage: parent(r)
Real Field with 53 bits of precision
sage: r = bessel_Y(RealField(200)(1), 1); r
-0.78121282130028871654715000004796482054990639071644460784383
sage: parent(r)
Real Field with 200 bits of precision
"""
def __init__(self):
"""
Expand All @@ -457,24 +453,6 @@ def __init__(self):
maxima='bessel_y',
sympy='bessely'))

def _eval_(self, n, x):
"""
EXAMPLES::
sage: a,b = var('a, b')
sage: bessel_Y(a, b)
bessel_Y(a, b)
sage: bessel_Y(0, 1).n(128)
0.088256964215676957982926766023515162828
"""
if (not isinstance(n, Expression) and not isinstance(x, Expression) and
(is_inexact(n) or is_inexact(x))):
coercion_model = get_coercion_model()
n, x = coercion_model.canonical_coercion(n, x)
return self._evalf_(n, x, parent(n))

return None # leaves the expression unevaluated

def _evalf_(self, n, x, parent=None, algorithm=None):
"""
EXAMPLES::
Expand Down Expand Up @@ -632,20 +610,12 @@ def _eval_(self, n, x):
sage: bessel_I(-1/2, pi)
sqrt(2)*cosh(pi)/pi
"""
if (not isinstance(n, Expression) and not isinstance(x, Expression) and
(is_inexact(n) or is_inexact(x))):
coercion_model = get_coercion_model()
n, x = coercion_model.canonical_coercion(n, x)
return self._evalf_(n, x, parent(n))

# special identities
if n == Integer(1) / Integer(2):
return sqrt(2 / (pi * x)) * sinh(x)
elif n == -Integer(1) / Integer(2):
return sqrt(2 / (pi * x)) * cosh(x)

return None # leaves the expression unevaluated

def _evalf_(self, n, x, parent=None, algorithm=None):
"""
EXAMPLES::
Expand Down Expand Up @@ -810,18 +780,10 @@ def _eval_(self, n, x):
sage: bessel_K(-1, 1).n(128)
0.60190723019723457473754000153561733926
"""
if (not isinstance(n, Expression) and not isinstance(x, Expression) and
(is_inexact(n) or is_inexact(x))):
coercion_model = get_coercion_model()
n, x = coercion_model.canonical_coercion(n, x)
return self._evalf_(n, x, parent(n))

# special identity
if n == Integer(1) / Integer(2) and x > 0:
return sqrt(pi / 2) * exp(-x) * x ** (-Integer(1) / Integer(2))

return None # leaves the expression unevaluated

def _evalf_(self, n, x, parent=None, algorithm=None):
"""
EXAMPLES::
Expand Down
Loading

0 comments on commit 7cde1ca

Please sign in to comment.