Ticket #13933: 13933-slow-call.v2.patch

File 13933-slow-call.v2.patch, 6.7 KB (added by Robert Bradshaw, 10 years ago)

apply only this patch

  • sage/functions/generalized.py

    # HG changeset patch
    # User Robert Bradshaw <robertwb@math.washington.edu>
    # Date 1357804445 28800
    # Node ID 53581f55108fd7d149eb67d7ffd7f68a6a7c4ac8
    # Parent  61e2b9fe95f251269a0a672144b61ec491676f35
    Faster foo(x) -> x.foo() dispatch for builtin functions.
    
    diff --git a/sage/functions/generalized.py b/sage/functions/generalized.py
    a b  
    441441            sgn(x)
    442442        """
    443443        BuiltinFunction.__init__(self, "sgn", latex_name=r"\mathrm{sgn}",
    444                 conversions=dict(maxima='signum',mathematica='Sign',sympy='sign'))
     444                conversions=dict(maxima='signum',mathematica='Sign',sympy='sign'),
     445                alt_name="sign")
    445446
    446447    def _eval_(self, x):
    447448        """
  • sage/symbolic/function.pxd

    diff --git a/sage/symbolic/function.pxd b/sage/symbolic/function.pxd
    a b  
    2020    cdef unsigned int _serial
    2121    cdef int _nargs
    2222    cdef object _name
     23    cdef object _alt_name
    2324    cdef object _latex_name
    2425    cdef object _conversions
    2526    cdef object _evalf_params_first
  • sage/symbolic/function.pyx

    diff --git a/sage/symbolic/function.pyx b/sage/symbolic/function.pyx
    a b  
    4747    subclasses :class:`BuiltinFunction` or :class:`SymbolicFunction`.
    4848    """
    4949    def __init__(self, name, nargs, latex_name=None, conversions=None,
    50             evalf_params_first=True):
     50            evalf_params_first=True, alt_name=None):
    5151        """
    5252        This is an abstract base class. It's not possible to test it directly.
    5353
     
    8484            ValueError: eval_func parameter must be callable
    8585        """
    8686        self._name = name
     87        self._alt_name = alt_name
    8788        self._nargs = nargs
    8889        self._latex_name = latex_name
    8990        self._evalf_params_first = evalf_params_first
     
    272273            return cmp(self._serial, (<Function>other)._serial)
    273274        return False
    274275
    275     def __call__(self, *args, coerce=True, hold=False):
     276    def __call__(self, *args, bint coerce=True, bint hold=False):
    276277        """
    277278        Evaluates this function at the given arguments.
    278279       
     
    721722
    722723        g_foptions_assign(g_registered_functions().index(self._serial), opt)
    723724
    724     def __call__(self, *args, coerce=True, hold=False,
    725             dont_call_method_on_arg=False):
     725
     726cdef class BuiltinFunction(Function):
     727    """
     728    This is the base class for symbolic functions defined in Sage.
     729   
     730    If a function is provided by the Sage library, we don't need to pickle
     731    the custom methods, since we can just initialize the same library function
     732    again. This allows us to use Cython for custom methods.
     733
     734    We assume that each subclass of this class will define one symbolic
     735    function. Make sure you use subclasses and not just call the initializer
     736    of this class.
     737    """
     738    def __init__(self, name, nargs=1, latex_name=None, conversions=None,
     739            evalf_params_first=True, alt_name=None):
    726740        """
     741        TESTS::
     742
     743            sage: from sage.functions.trig import Function_cot
     744            sage: c = Function_cot() # indirect doctest
     745            sage: c(pi/2)
     746            0
     747        """
     748        Function.__init__(self, name, nargs, latex_name, conversions,
     749                evalf_params_first, alt_name = alt_name)
     750
     751    def __call__(self, *args, bint coerce=True, bint hold=False,
     752            bint dont_call_method_on_arg=False):
     753        r"""
    727754        Evaluate this function on the given arguments and return the result.
    728755
    729756        EXAMPLES::
     
    732759            e^5
    733760            sage: gamma(15)
    734761            87178291200
     762
     763        TESTS::
     764
     765            sage: from sage.symbolic.function import BuiltinFunction
     766            sage: class A:
     767            ...       def foo(self):
     768            ...           return 'foo'
     769            sage: foo = BuiltinFunction(name='foo')
     770            sage: foo(A())
     771            'foo'
     772            sage: bar = BuiltinFunction(name='bar', alt_name='foo')
     773            sage: bar(A())
     774            'foo'
    735775        """
    736         # we want to convert the result to the original parent if the input
    737         # is not exact, so we store the parent here
    738         org_parent = parent_c(args[0])
    739        
    740776        # if there is only one argument, and the argument has an attribute
    741777        # with the same name as this function, try to call it to get the result
    742778        # The argument dont_call_method_on_arg is used to prevent infinite loops
    743779        # when .exp(), .log(), etc. methods call this symbolic function on
    744780        # themselves
    745         if len(args) == 1 and not hold and not dont_call_method_on_arg and \
    746                 hasattr(args[0], self._name):
    747             return getattr(args[0], self._name)()
     781        if len(args) == 1 and not hold and not dont_call_method_on_arg:
     782            arg = args[0]
     783            method = getattr(arg, self._name, None)
     784            if method is not None:
     785                return method()
     786            elif self._alt_name is not None:
     787                method = getattr(arg, self._alt_name, None)
     788                if method is not None:
     789                    return method()
    748790
    749         res = super(GinacFunction, self).__call__(*args, coerce=coerce,
    750                 hold=hold)
     791        res = super(BuiltinFunction, self).__call__(
     792                        *args, coerce=coerce, hold=hold)
    751793
     794        # we want to convert the result to the original parent if the input
     795        # is not exact, so we store the parent here
     796        org_parent = parent_c(args[0])
     797       
    752798        # convert the result back to the original parent previously stored
    753799        # otherwise we end up with
    754800        #     sage: arctan(RR(1))
     
    778824
    779825        return res
    780826
    781 
    782 cdef class BuiltinFunction(Function):
    783     """
    784     This is the base class for symbolic functions defined in Sage.
    785    
    786     If a function is provided by the Sage library, we don't need to pickle
    787     the custom methods, since we can just initialize the same library function
    788     again. This allows us to use Cython for custom methods.
    789 
    790     We assume that each subclass of this class will define one symbolic
    791     function. Make sure you use subclasses and not just call the initializer
    792     of this class.
    793     """
    794     def __init__(self, name, nargs=1, latex_name=None, conversions=None,
    795             evalf_params_first=True):
    796         """
    797         TESTS::
    798 
    799             sage: from sage.functions.trig import Function_cot
    800             sage: c = Function_cot() # indirect doctest
    801             sage: c(pi/2)
    802             0
    803         """
    804         Function.__init__(self, name, nargs, latex_name, conversions,
    805                 evalf_params_first)
    806 
    807827    cdef _is_registered(self):
    808828        """
    809829        TESTS: