Ticket #13608: bug13608a.patch

File bug13608a.patch, 5.3 KB (added by Martin von Gagern, 10 years ago)

Ensure member is callable, use functions from mpmath module

  • sage/functions/log.py

    diff -r d06cf4b2215d sage/functions/log.py
    a b  
    125125            doctest:...: DeprecationWarning: The prec keyword argument is deprecated. Explicitly set the precision of the input, for example exp(RealField(300)(1)), or use the prec argument to .n() for exact inputs, e.g., exp(1).n(300), instead.
    126126            See http://trac.sagemath.org/7490 for details.
    127127            7.3890560989306502272304274606
     128
     129        Ensure that :trac:`13608` is fixed::
     130
     131            sage: import mpmath
     132            sage: exp(mpmath.mpf('0.5'))
     133            mpf('1.6487212707001282')
    128134        """
    129135        if prec is not None:
    130136            from sage.misc.superseded import deprecation
  • sage/symbolic/function.pyx

    diff -r d06cf4b2215d sage/symbolic/function.pyx
    a b  
    211211            if x.parent().is_exact():
    212212                return None
    213213        try:
    214             return getattr(x, self.name())()
     214            memberfn = getattr(x, self.name())
    215215        except AttributeError:
    216216            pass
     217        else:
     218            return memberfn()
    217219
    218220    def __hash__(self):
    219221        """
     
    360362        if self._nargs == 1:
    361363            if isinstance(args[0], FastDoubleFunc):
    362364                try:
    363                     return getattr(args[0], self._name)()
     365                    memberfn = getattr(args[0], self._name)
    364366                except AttributeError, err:
    365367                    raise TypeError, "cannot handle fast float arguments"
     368                else:
     369                    return memberfn()
    366370
    367371        # support numpy arrays as arguments
    368372        if any([type(arg).__module__ == 'numpy' for arg in args]): # avoid importing
     
    370374            # check that at least one of the arguments is a numpy array
    371375            if any([isinstance(arg, numpy.ndarray) for arg in args]):
    372376                try:
    373                     return getattr(numpy, self.name())(*args)
     377                    modulefn = getattr(numpy, self.name())
    374378                except AttributeError:
    375379                    return self._eval_numpy_(*args)
     380                else:
     381                    return modulefn(*args)
     382
     383        # support mpmath mpf and mpc numbers as arguments
     384        if any(['mpmath' in type(arg).__module__ for arg in args]): # avoid importing
     385            import mpmath
     386            # check that at least one of the arguments is an mpmath type
     387            if any([isinstance(arg, (mpmath.mpf, mpmath.mpc)) for arg in args]):
     388                try:
     389                    modulefn = getattr(mpmath, self.name())
     390                except AttributeError:
     391                    return self._eval_mpmath_(*args)
     392                else:
     393                    return modulefn(*args)
    376394
    377395        # if the given input is a symbolic expression, we don't convert it back
    378396        # to a numeric type at the end
     
    393411                #     sage: M = matrix(SR, 2, 2, [x, 0, 0, I*pi])
    394412                #     [e^x   0]
    395413                #     [  0  -1]
    396                 if len(args) == 1:
    397                     try:
    398                         return getattr(args[0], self._name)()
    399                     except AttributeError:
    400                         pass
     414                if len(args) == 1:
     415                    memberfn = getattr(args[0], self._name, None)
     416                    if callable(memberfn):
     417                        return memberfn()
    401418
    402419                # There is no natural coercion from QQbar to the symbolic ring
    403420                # in order to support
     
    634651        """
    635652        raise NotImplementedError("The Function %s does not support numpy arrays as arguments" % self.name())
    636653
     654    def _eval_mpmath_(self, *args):
     655        r"""
     656        Evaluates this function for arguments of mpmath types.
     657
     658        The default implementation casts its arguments to sage reals
     659        of the appropriate precision.
     660
     661        EXAMPLES::
     662
     663        sage: with mpmath.workprec(128): arcsin(mpmath.mpf('0.5'))
     664        ....:
     665        mpf('0.52359877559829887307710723054658381403157')
     666        """
     667        import mpmath
     668        from sage.libs.mpmath.utils import mpmath_to_sage, sage_to_mpmath
     669        prec = mpmath.mp.prec
     670        args = [mpmath_to_sage(x, prec)
     671                if isinstance(x, (mpmath.mpf, mpmath.mpc)) else x
     672                for x in args]
     673        res = self(*args)
     674        res = sage_to_mpmath(res, prec)
     675        return res
     676
    637677cdef class GinacFunction(BuiltinFunction):
    638678    """
    639679    This class provides a wrapper around symbolic functions already defined in
     
    742782        # The argument dont_call_method_on_arg is used to prevent infinite loops
    743783        # when .exp(), .log(), etc. methods call this symbolic function on
    744784        # 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)()
     785        if len(args) == 1 and not hold and not dont_call_method_on_arg:
     786            memberfn = getattr(args[0], self._name, None)
     787            if callable(memberfn):
     788                return memberfn()
    748789
    749790        res = super(GinacFunction, self).__call__(*args, coerce=coerce,
    750791                hold=hold)