Ticket #12455: trac_12455-airy_review.patch

File trac_12455-airy_review.patch, 14.3 KB (added by burcin, 6 years ago)
  • sage/functions/airy.py

    # HG changeset patch
    # User Burcin Erocal <burcin@erocal.org>
    # Date 1371691887 -7200
    #      Thu Jun 20 03:31:27 2013 +0200
    # Node ID 99ce058338cb7f20044271c32f2a64a2816bfda9
    # Parent  56b284a7bf444ed1b7fa302f5209ff1f5fa8e638
    trac 12455: fix bugs in symbolic airy functions
    
    - airy_{a,b}i_general should evaluate to airy_{a,b}i_simple,
      airy_{a,b}i_prime, etc. depending on the first parameter
    
    - differentiating airy_{a,b}i_general in the first parameter is not allowed
    
    - _evalf_ should not raise errors for unrecognized algorithm argument
    
    diff --git a/sage/functions/airy.py b/sage/functions/airy.py
    a b  
    3636from sage.symbolic.function import BuiltinFunction
    3737from sage.symbolic.expression import Expression
    3838from sage.symbolic.function import is_inexact
     39from sage.symbolic.ring import SR
    3940from sage.structure.coerce import parent as sage_structure_coerce_parent
    4041from sage.functions.other import gamma
    4142from sage.rings.integer_ring import ZZ
    4243from sage.rings.real_double import RDF
    4344from sage.rings.rational import Rational as R
    4445from sage.functions.special import meval
    45 from sage.calculus.var import var
    4646from sage.calculus.functional import derivative
    4747
    4848
     
    9090        BuiltinFunction.__init__(self, "airy_ai", nargs=2,
    9191                                 latex_name=r"\operatorname{Ai}")
    9292
    93     def _derivative_(self, alpha, *args, **kwds):
     93    def _derivative_(self, alpha, x, diff_param=None):
    9494        """
    9595        EXAMPLES::
    9696
    9797            sage: x, n = var('x n')
    9898            sage: derivative(airy_ai(n, x), x)  # indirect doctest
    9999            airy_ai(n + 1, x)
     100            sage: derivative(airy_ai(n, x), n)  # indirect doctest
     101            Traceback (most recent call last):
     102            ...
     103            ValueError: cannot differentiate airy_ai in the first parameter
    100104        """
    101         x = args[0]
     105        if diff_param == 0:
     106            raise ValueError("cannot differentiate airy_ai in the first parameter")
    102107        return airy_ai_general(alpha + 1, x)
    103108
    104     def _eval_(self, alpha, *args):
     109    def _eval_(self, alpha, x):
    105110        """
    106111        EXAMPLES::
    107112
     
    111116            sage: airy_ai(n, 1.0)  # indirect doctest
    112117            airy_ai(n, 1.00000000000000)
    113118        """
    114         x = args[0]
    115 
    116         if not isinstance(x, Expression) and not isinstance(alpha, Expression):
     119        if not isinstance(x, Expression) and \
     120                not isinstance(alpha, Expression):
    117121            if is_inexact(x):
    118122                return self._evalf_(alpha, x)
     123            if alpha == 0:
     124                return airy_ai_simple(x)
     125            if alpha == 1:
     126                return airy_ai_prime(x)
     127            if alpha == 2:
     128                return x*airy_ai_simple(x)
    119129        else:
    120130            return None
    121131
    122     def _evalf_(self, alpha, x, **kwargs):
     132    def _evalf_(self, alpha, x, parent=None, algorithm=None):
    123133        """
    124134        EXAMPLES::
    125135
    126136            sage: airy_ai(-2, 1.0)  # indirect doctest
    127137            0.136645379421096
    128138        """
    129         algorithm = kwargs.get('algorithm', None) or 'mpmath'
    130         parent = sage_structure_coerce_parent(x)
    131         if algorithm == 'mpmath':
    132             import mpmath
    133             from sage.libs.mpmath import utils as mpmath_utils
    134             return mpmath_utils.call(mpmath.airyai, x, derivative=alpha,
    135                                      parent=parent)
    136         elif algorithm == 'maxima':
    137             raise NotImplementedError("general case not available in Maxima")
    138         else:
    139             raise ValueError("unknown algorithm")
     139        import mpmath
     140        from sage.libs.mpmath import utils as mpmath_utils
     141        return mpmath_utils.call(mpmath.airyai, x, derivative=alpha,
     142                                 parent=parent)
    140143
    141144
    142145class FunctionAiryAiSimple(BuiltinFunction):
     
    187190        else:
    188191            return None
    189192
    190     def _evalf_(self, x, **kwargs):
     193    def _evalf_(self, x, parent=None, algorithm=None):
    191194        """
    192195        EXAMPLES::
    193196
     
    210213            sage: airy_ai(3).n(algorithm='maxima', prec=70)
    211214            Traceback (most recent call last):
    212215            ...
    213             ValueError: for the Maxima algorithm the precision must be 53
     216            ValueError: precision must be 53 for algorithm=maxima
     217        """
     218        if algorithm == 'maxima':
     219            try:
     220                prec = parent.prec()
     221            except AttributeError:
     222                prec = 53
     223            if prec != 53:
     224                raise ValueError("precision must be 53 "
     225                                 "for algorithm=maxima")
     226            return RDF(meval("airy_ai({})".format(RDF(x))))
    214227
    215         """
    216         algorithm = kwargs.get('algorithm', None) or 'mpmath'
    217         parent = sage_structure_coerce_parent(x)
    218         prec = parent.prec() if hasattr(parent, 'prec') else 53
    219         if algorithm == 'mpmath':
    220             import mpmath
    221             from sage.libs.mpmath import utils as mpmath_utils
    222             return mpmath_utils.call(mpmath.airyai, x, parent=parent)
    223         elif algorithm == 'maxima':
    224             if prec != 53:
    225                 raise ValueError("for the Maxima algorithm the precision must "
    226                                  "be 53")
    227             return RDF(meval("airy_ai({})".format(RDF(x))))
    228         else:
    229             raise ValueError("unknown algorithm")
     228        import mpmath
     229        from sage.libs.mpmath import utils as mpmath_utils
     230        return mpmath_utils.call(mpmath.airyai, x, parent=parent)
    230231
    231232
    232233class FunctionAiryAiPrime(BuiltinFunction):
     
    275276        else:
    276277            return None
    277278
    278     def _evalf_(self, x, **kwargs):
     279    def _evalf_(self, x, parent=None, algorithm=None):
    279280        """
    280281        EXAMPLES::
    281282
     
    296297            sage: airy_ai(1, 4).n(algorithm='maxima', prec=70)
    297298            Traceback (most recent call last):
    298299            ...
    299             ValueError: for the Maxima algorithm the precision must be 53
     300            ValueError: precision must be 53 for algorithm=maxima
    300301        """
    301         algorithm = kwargs.get('algorithm', None) or 'mpmath'
    302         parent = sage_structure_coerce_parent(x)
    303         prec = parent.prec() if hasattr(parent, 'prec') else 53
    304         if algorithm == 'mpmath':
    305             import mpmath
    306             from sage.libs.mpmath import utils as mpmath_utils
    307             return mpmath_utils.call(mpmath.airyai, x, derivative=1,
    308                                      parent=parent)
    309         elif algorithm == 'maxima':
     302        if algorithm == 'maxima':
     303            try:
     304                prec = parent.prec()
     305            except AttributeError:
     306                prec = 53
    310307            if prec != 53:
    311                 raise ValueError("for the Maxima algorithm the precision must "
    312                                  "be 53")
     308                raise ValueError("precision must be 53 "
     309                                 "for algorithm=maxima")
    313310            return RDF(meval("airy_dai({})".format(RDF(x))))
    314         else:
    315             raise ValueError("unknown algorithm")
     311
     312        import mpmath
     313        from sage.libs.mpmath import utils as mpmath_utils
     314        return mpmath_utils.call(mpmath.airyai, x, derivative=1,
     315                                 parent=parent)
    316316
    317317airy_ai_general = FunctionAiryAiGeneral()
    318318airy_ai_simple = FunctionAiryAiSimple()
     
    428428
    429429    # We take care of all other cases.
    430430    if not alpha in ZZ and not isinstance(alpha, Expression):
    431         raise ValueError("alpha must be an integer")
     431        return airy_ai_general(alpha, x, **kwds)
    432432    if hold_derivative:
    433433        return airy_ai_general(alpha, x, **kwds)
    434434    elif alpha == 0:
     
    441441        # which would return 0. What we want is the value of
    442442        # the derivative at the value and not the derivative of
    443443        # a particular value of the function.
    444         v = var('v')
    445         return derivative(airy_ai_simple(v, **kwds), v, alpha).subs(v=x)
     444        v = SR.symbol()
     445        return derivative(airy_ai_simple(v, **kwds), v, alpha).subs({v: x})
    446446    else:
    447447        return airy_ai_general(alpha, x, **kwds)
    448448
     
    494494        BuiltinFunction.__init__(self, "airy_bi", nargs=2,
    495495                                 latex_name=r"\operatorname{Bi}")
    496496
    497     def _derivative_(self, alpha, *args, **kwds):
     497    def _derivative_(self, alpha, x, diff_param=None):
    498498        """
    499499        EXAMPLES::
    500500
    501501            sage: x, n = var('x n')
    502502            sage: derivative(airy_bi(n, x), x)  # indirect doctest
    503503            airy_bi(n + 1, x)
     504            sage: derivative(airy_bi(n, x), n)  # indirect doctest
     505            Traceback (most recent call last):
     506            ...
     507            ValueError: cannot differentiate airy_bi in the first parameter
    504508        """
    505         x = args[0]
     509        if diff_param == 0:
     510            raise ValueError("cannot differentiate airy_bi in the first parameter")
    506511        return airy_bi_general(alpha + 1, x)
    507512
    508     def _eval_(self, alpha, *args):
     513    def _eval_(self, alpha, x):
    509514        """
    510515        EXAMPLES::
    511516
     
    515520            sage: airy_bi(n, 1.0)  # indirect doctest
    516521            airy_bi(n, 1.00000000000000)
    517522        """
    518         x = args[0]
    519         if not isinstance(x, Expression) and not isinstance(alpha, Expression):
     523        if not isinstance(x, Expression) and \
     524                not isinstance(alpha, Expression):
    520525            if is_inexact(x):
    521526                return self._evalf_(alpha, x)
     527            if alpha == 0:
     528                return airy_bi_simple(x)
     529            if alpha == 1:
     530                return airy_bi_prime(x)
     531            if alpha == 2:
     532                return x*airy_bi_simple(x)
    522533        else:
    523534            return None
    524535
     
    530541            0.388621540699059
    531542
    532543        """
    533         algorithm = kwargs.get('algorithm', None) or 'mpmath'
    534         parent = sage_structure_coerce_parent(x)
    535         if algorithm == 'mpmath':
    536             import mpmath
    537             from sage.libs.mpmath import utils as mpmath_utils
    538             return mpmath_utils.call(mpmath.airybi, x, derivative=alpha,
    539                                      parent=parent)
    540         elif algorithm == 'maxima':
    541             raise NotImplementedError("general case not available in Maxima")
    542         else:
    543             raise ValueError("unknown algorithm")
     544        parent = kwargs.get('parent')
     545        import mpmath
     546        from sage.libs.mpmath import utils as mpmath_utils
     547        return mpmath_utils.call(mpmath.airybi, x, derivative=alpha,
     548                                 parent=parent)
    544549
    545550
    546551class FunctionAiryBiSimple(BuiltinFunction):
     
    616621            sage: airy_bi(3).n(algorithm='maxima', prec=100)
    617622            Traceback (most recent call last):
    618623            ...
    619             ValueError: for the Maxima algorithm the precision must be 53
    620 
     624            ValueError: precision must be 53 for algorithm=maxima
    621625        """
    622626        algorithm = kwargs.get('algorithm', None) or 'mpmath'
    623         parent = sage_structure_coerce_parent(x)
    624         prec = parent.prec() if hasattr(parent, 'prec') else 53
    625         if algorithm == 'mpmath':
    626             import mpmath
    627             from sage.libs.mpmath import utils as mpmath_utils
    628             return mpmath_utils.call(mpmath.airybi, x, parent=parent)
    629         elif algorithm == 'maxima':
     627        parent = kwargs.get('parent')
     628        if algorithm == 'maxima':
     629            try:
     630                prec = parent.prec()
     631            except AttributeError:
     632                prec = 53
    630633            if prec != 53:
    631                 raise ValueError("for the Maxima algorithm the precision must "
    632                                  "be 53")
     634                raise ValueError("precision must be 53 "
     635                                 "for algorithm=maxima")
    633636            return RDF(meval("airy_bi({})".format(RDF(x))))
    634         else:
    635             raise ValueError("unknown algorithm")
     637
     638        import mpmath
     639        from sage.libs.mpmath import utils as mpmath_utils
     640        return mpmath_utils.call(mpmath.airybi, x, parent=parent)
    636641
    637642
    638643class FunctionAiryBiPrime(BuiltinFunction):
     
    702707            sage: airy_bi(1, 4).n(algorithm='maxima', prec=70)
    703708            Traceback (most recent call last):
    704709            ...
    705             ValueError: for the Maxima algorithm the precision must be 53
     710            ValueError: precision must be 53 for algorithm=maxima
    706711        """
    707712        algorithm = kwargs.get('algorithm', None) or 'mpmath'
    708713        parent = sage_structure_coerce_parent(x)
    709         prec = parent.prec() if hasattr(parent, 'prec') else 53
    710         if algorithm == 'mpmath':
    711             import mpmath
    712             from sage.libs.mpmath import utils as mpmath_utils
    713             return mpmath_utils.call(mpmath.airybi, x, derivative=1,
    714                                      parent=parent)
    715         elif algorithm == 'maxima':
     714        if algorithm == 'maxima':
     715            try:
     716                prec = parent.prec()
     717            except AttributeError:
     718                prec = 53
    716719            if prec != 53:
    717                 raise ValueError("for the Maxima algorithm the precision must "
    718                                  "be 53")
     720                raise ValueError("precision must be 53 "
     721                                 "for algorithm=maxima")
    719722            return RDF(meval("airy_dbi({})".format(RDF(x))))
    720         else:
    721             raise ValueError("unknown algorithm")
     723
     724        import mpmath
     725        from sage.libs.mpmath import utils as mpmath_utils
     726        return mpmath_utils.call(mpmath.airybi, x, derivative=1,
     727                                 parent=parent)
    722728
    723729airy_bi_general = FunctionAiryBiGeneral()
    724730airy_bi_simple = FunctionAiryBiSimple()
     
    834840                         "({} given)").format(len(args) + 3))
    835841
    836842    # We take care of all other cases.
     843    if not alpha in ZZ and not isinstance(alpha, Expression):
     844        return airy_bi_general(alpha, x, **kwds)
    837845    if hold_derivative:
    838846        return airy_bi_general(alpha, x, **kwds)
    839847    elif alpha == 0:
     
    846854        # which would return 0. What we want is the value of
    847855        # the derivative at the value and not the derivative of
    848856        # a particular value of the function.
    849         v = var('v')
    850         return derivative(airy_bi_simple(v, **kwds), v, alpha).subs(v=x)
     857        v = SR.symbol()
     858        return derivative(airy_bi_simple(v, **kwds), v, alpha).subs({v: x})
    851859    else:
    852860        return airy_bi_general(alpha, x, **kwds)