Ticket #7748: trac_7748-exp_integral_ver2.patch

File trac_7748-exp_integral_ver2.patch, 7.9 KB (added by fstan, 12 years ago)

Added derivative method.

  • sage/functions/transcendental.py

    # HG changeset patch
    # User Flavia Stan <flavia.stan@gmail.com>
    # Date 1266276244 -3600
    # Node ID 6f981d100b5cf86dea860b77a46e3562f7fbd21e
    # Parent  e634615fef0a8dc50ab2857b71bd3c03e069ae53
    Trac 7748: Make the exponential integral function Ei symbolic.
    
    diff --git a/sage/functions/transcendental.py b/sage/functions/transcendental.py
    a b  
    1818#*****************************************************************************
    1919
    2020import sys
    21 
     21from sage.libs.mpmath import utils as mpmath_utils
    2222import  sage.libs.pari.all
    2323from sage.libs.pari.all import pari, PariError
    2424import sage.rings.complex_field as complex_field
    2525import sage.rings.real_double as real_double
    2626import sage.rings.complex_number
    2727from sage.gsl.integration import numerical_integral
     28from sage.structure.parent import Parent
     29from sage.structure.coerce import parent
     30from sage.symbolic.expression import Expression
     31from sage.functions.log import exp
    2832
    2933from sage.rings.all import (is_RealNumber, RealField,
    3034                            is_ComplexNumber, ComplexField,
    3135                            ZZ, RR, RDF, CDF, prime_range)
    3236                           
    33 from sage.symbolic.function import BuiltinFunction, SR
     37from sage.symbolic.function import BuiltinFunction, SR, is_inexact
    3438
    3539import sage.plot.all
    3640
     
    210214        return R(0.5)
    211215   
    212216    return (s/2 + 1).gamma()   *    (s-1)   * (R.pi()**(-s/2))  *  s.zeta()
    213    
     217
    214218
    215219##     # Use PARI on complex nubmer
    216220##     prec = s.prec()
     
    230234#   return real_field.RealField(prec).pi()
    231235
    232236
    233 def Ei(z, prec=None):
    234     """
    235     Return the value of the complex exponential integral Ei(z) at a
    236     complex number z.
     237class Function_exp_integral(BuiltinFunction):
     238    def __init__(self):
     239        """
     240        Return the value of the complex exponential integral Ei(z) at a
     241        complex number z.
    237242       
    238     EXAMPLES::
     243        EXAMPLES::
     244
     245            sage: Ei(10)
     246            Ei(10)
     247            sage: Ei(I)
     248            Ei(I)
     249            sage: Ei(3+I)
     250            Ei(I + 3)
     251            sage: Ei(1.3)
     252            2.72139888023202
     253           
     254        The branch cut for this function is along the negative real axis::
    239255   
    240         sage: Ei(10)
    241         2492.22897624188
    242         sage: Ei(20)
    243         2.56156526640566e7
    244         sage: Ei(I)
    245         0.337403922900968 + 2.51687939716208*I
    246         sage: Ei(3+I)
    247         7.82313467600158 + 6.09751978399231*I
     256            sage: Ei(-3 + 0.1*I)
     257            -0.0129379427181693 + 3.13993830250942*I
     258            sage: Ei(-3 - 0.1*I)
     259            -0.0129379427181693 - 3.13993830250942*I
    248260   
    249     The branch cut for this function is along the negative real axis::
    250    
    251         sage: Ei(-3 + 0.1*I)
    252         -0.0129379427181693 + 3.13993830250942*I
    253         sage: Ei(-3 - 0.1*I)
    254         -0.0129379427181693 - 3.13993830250942*I
    255    
    256     ALGORITHM: Uses mpmath.
    257     """
    258     if prec is None:
    259         try:
    260             prec = z.prec()
    261         except AttributeError:
     261        ALGORITHM: Uses mpmath.
     262        """
     263        BuiltinFunction.__init__(self, "Ei")
     264
     265    def _eval_(self, x ):
     266        """
     267        EXAMPLES::
     268
     269            sage: Ei(10)
     270            Ei(10)
     271            sage: Ei(I)
     272            Ei(I)
     273            sage: Ei(1.3)
     274            2.72139888023202
     275            sage: Ei(10r)
     276            Ei(10)
     277            sage: Ei(1.3r)
     278            2.72139888023202
     279        """
     280        if not isinstance(x, Expression) and is_inexact(x):
     281            return self._evalf_(x, parent(x))
     282        return None
     283           
     284    def _evalf_(self, x, parent=None):
     285        """
     286        EXAMPLES::
     287
     288            sage: Ei(10).n()
     289            2492.22897624188
     290            sage: Ei(20).n()
     291            2.56156526640566e7
     292            sage: Ei(I).n()
     293            0.337403922900968 + 2.51687939716208*I
     294            sage: Ei(3+I).n()
     295            7.82313467600158 + 6.09751978399231*I
     296        """
     297        import mpmath
     298        if isinstance(parent, Parent) and hasattr(parent, 'prec'):
     299            prec = parent.prec()
     300        else:
    262301            prec = 53
     302        return mpmath_utils.call(mpmath.ei, x, prec=prec)
     303
     304    def __call__(self, x, prec=None, coerce=True, hold=False ):
     305        """
     306        Note that the ``prec`` argument is deprecated. The precision for
     307        the result is deduced from the precision of the input. Convert
     308        the input to a higher precision explicitly if a result with higher
     309        precision is desired.
     310
     311        EXAMPLES::
     312
     313            sage: t = Ei(RealField(100)(2.5)); t
     314            7.0737658945786007119235519625
     315            sage: t.prec()
     316            100
     317
     318            sage: Ei(1.1, prec=300)
     319            doctest:...: DeprecationWarning: The prec keyword argument is deprecated. Explicitly set the precision of the input, for example Ei(RealField(300)(1)), or use the prec argument to .n() for exact inputs, e.g., Ei(1).n(300), instead.
     320            2.16737827956340306615064476647912607220394065907142504328679588538509331805598360907980986
     321        """
     322        if prec is not None:
     323            from sage.misc.misc import deprecation
     324            deprecation("The prec keyword argument is deprecated. Explicitly set the precision of the input, for example Ei(RealField(300)(1)), or use the prec argument to .n() for exact inputs, e.g., Ei(1).n(300), instead.")
    263325           
    264     import sage.libs.mpmath.all as mp
    265     return mp.call(mp.ei, z, prec=prec)
     326            import mpmath
     327            return mpmath_utils.call(mpmath.ei, x, prec=prec)
     328
     329        return BuiltinFunction.__call__(self, x, coerce=coerce, hold=hold)
     330
     331    def _derivative_(self, x, diff_param=None):
     332        """
     333        EXAMPLES::
     334       
     335            sage: Ei(x).diff(x)
     336            e^x/x
     337            sage: Ei(x).diff(x).subs(x=1)
     338            e
     339            sage: Ei(x^2).diff(x)
     340            2*e^(x^2)/x
     341            sage: f = function('f')
     342            sage: Ei(f(x)).diff(x)
     343            e^f(x)*D[0](f)(x)/f(x)
     344        """
     345        return exp(x)/x
     346
     347Ei = Function_exp_integral()
     348
    266349
    267350def Li(x, eps_rel=None, err_bound=False):
    268351    r"""
  • sage/symbolic/function.pyx

    diff --git a/sage/symbolic/function.pyx b/sage/symbolic/function.pyx
    a b  
    11671167        return None
    11681168    return unpickle_function(p)
    11691169
     1170def is_inexact(x):
     1171    """
     1172    Returns True if the argument is an inexact object.
     1173
     1174    TESTS::
     1175
     1176        sage: from sage.symbolic.function import is_inexact
     1177        sage: is_inexact(5)
     1178        False
     1179        sage: is_inexact(5.)
     1180        True
     1181        sage: is_inexact(pi)
     1182        True
     1183        sage: is_inexact(5r)
     1184        False
     1185        sage: is_inexact(5.4r)
     1186        True
     1187    """
     1188    if isinstance(x, (float, complex)):
     1189        return True
     1190    if isinstance(x, Element):
     1191        return not (<Element>x)._parent.is_exact()
     1192    return False
  • sage/symbolic/random_tests.py

    diff --git a/sage/symbolic/random_tests.py b/sage/symbolic/random_tests.py
    a b  
    202202
    203203        sage: from sage.symbolic.random_tests import *
    204204        sage: random_expr(50, nvars=3, coeff_generator=CDF.random_element)
    205         sinh(sinh(-coth(v2)/erf(-(0.615863165633 + 0.879368031485*I)*v1^2*v3) - gamma(pi) + csch(-(0.708874026302 - 0.954135400334*I)*v3)))^coth(-cosh(-polylog((v2 + 0.913564344312 + 0.0898040160336*I)^(-(0.723896589334 - 0.799038508886*I)*v2), -v1 - v3))/arcsin(-(0.0263902659909 + 0.153261789843*I)*arctan2(pi, arccot(pi))))
     205        sinh(arcsech(-heaviside(v2)/erf(-(0.615863165633 + 0.879368031485*I)*v1^2*v3) - gamma(pi) + erf(-(0.708874026302 - 0.954135400334*I)*v3)))^coth(-cosh(-polylog((v2 + 0.913564344312 + 0.0898040160336*I)^(-(0.723896589334 - 0.799038508886*I)*v2), -v1 - v3))/dilog(-(0.0263902659909 + 0.153261789843*I)*arctan2(pi, arccot(pi))))
    206206        sage: random_expr(5, verbose=True)
    207207        About to apply <built-in function add> to [v1, v1]
    208208        About to apply <built-in function div> to [-1/3, 2*v1]