|
|
"""
This module contains SymPy functions mathcin corresponding to special math functions in the C standard library (since C99, also available in C++11).
The functions defined in this module allows the user to express functions such as ``expm1`` as a SymPy function for symbolic manipulation.
"""
from sympy.core.function import ArgumentIndexError, Function from sympy.core.numbers import Rational from sympy.core.power import Pow from sympy.core.singleton import S from sympy.functions.elementary.exponential import exp, log from sympy.functions.elementary.miscellaneous import sqrt
def _expm1(x): return exp(x) - S.One
class expm1(Function): """
Represents the exponential function minus one.
Explanation ===========
The benefit of using ``expm1(x)`` over ``exp(x) - 1`` is that the latter is prone to cancellation under finite precision arithmetic when x is close to zero.
Examples ========
>>> from sympy.abc import x >>> from sympy.codegen.cfunctions import expm1 >>> '%.0e' % expm1(1e-99).evalf() '1e-99' >>> from math import exp >>> exp(1e-99) - 1 0.0 >>> expm1(x).diff(x) exp(x)
See Also ========
log1p """
nargs = 1
def fdiff(self, argindex=1): """
Returns the first derivative of this function. """
if argindex == 1: return exp(*self.args) else: raise ArgumentIndexError(self, argindex)
def _eval_expand_func(self, **hints): return _expm1(*self.args)
def _eval_rewrite_as_exp(self, arg, **kwargs): return exp(arg) - S.One
_eval_rewrite_as_tractable = _eval_rewrite_as_exp
@classmethod def eval(cls, arg): exp_arg = exp.eval(arg) if exp_arg is not None: return exp_arg - S.One
def _eval_is_real(self): return self.args[0].is_real
def _eval_is_finite(self): return self.args[0].is_finite
def _log1p(x): return log(x + S.One)
class log1p(Function): """
Represents the natural logarithm of a number plus one.
Explanation ===========
The benefit of using ``log1p(x)`` over ``log(x + 1)`` is that the latter is prone to cancellation under finite precision arithmetic when x is close to zero.
Examples ========
>>> from sympy.abc import x >>> from sympy.codegen.cfunctions import log1p >>> from sympy import expand_log >>> '%.0e' % expand_log(log1p(1e-99)).evalf() '1e-99' >>> from math import log >>> log(1 + 1e-99) 0.0 >>> log1p(x).diff(x) 1/(x + 1)
See Also ========
expm1 """
nargs = 1
def fdiff(self, argindex=1): """
Returns the first derivative of this function. """
if argindex == 1: return S.One/(self.args[0] + S.One) else: raise ArgumentIndexError(self, argindex)
def _eval_expand_func(self, **hints): return _log1p(*self.args)
def _eval_rewrite_as_log(self, arg, **kwargs): return _log1p(arg)
_eval_rewrite_as_tractable = _eval_rewrite_as_log
@classmethod def eval(cls, arg): if arg.is_Rational: return log(arg + S.One) elif not arg.is_Float: # not safe to add 1 to Float return log.eval(arg + S.One) elif arg.is_number: return log(Rational(arg) + S.One)
def _eval_is_real(self): return (self.args[0] + S.One).is_nonnegative
def _eval_is_finite(self): if (self.args[0] + S.One).is_zero: return False return self.args[0].is_finite
def _eval_is_positive(self): return self.args[0].is_positive
def _eval_is_zero(self): return self.args[0].is_zero
def _eval_is_nonnegative(self): return self.args[0].is_nonnegative
_Two = S(2)
def _exp2(x): return Pow(_Two, x)
class exp2(Function): """
Represents the exponential function with base two.
Explanation ===========
The benefit of using ``exp2(x)`` over ``2**x`` is that the latter is not as efficient under finite precision arithmetic.
Examples ========
>>> from sympy.abc import x >>> from sympy.codegen.cfunctions import exp2 >>> exp2(2).evalf() == 4 True >>> exp2(x).diff(x) log(2)*exp2(x)
See Also ========
log2 """
nargs = 1
def fdiff(self, argindex=1): """
Returns the first derivative of this function. """
if argindex == 1: return self*log(_Two) else: raise ArgumentIndexError(self, argindex)
def _eval_rewrite_as_Pow(self, arg, **kwargs): return _exp2(arg)
_eval_rewrite_as_tractable = _eval_rewrite_as_Pow
def _eval_expand_func(self, **hints): return _exp2(*self.args)
@classmethod def eval(cls, arg): if arg.is_number: return _exp2(arg)
def _log2(x): return log(x)/log(_Two)
class log2(Function): """
Represents the logarithm function with base two.
Explanation ===========
The benefit of using ``log2(x)`` over ``log(x)/log(2)`` is that the latter is not as efficient under finite precision arithmetic.
Examples ========
>>> from sympy.abc import x >>> from sympy.codegen.cfunctions import log2 >>> log2(4).evalf() == 2 True >>> log2(x).diff(x) 1/(x*log(2))
See Also ========
exp2 log10 """
nargs = 1
def fdiff(self, argindex=1): """
Returns the first derivative of this function. """
if argindex == 1: return S.One/(log(_Two)*self.args[0]) else: raise ArgumentIndexError(self, argindex)
@classmethod def eval(cls, arg): if arg.is_number: result = log.eval(arg, base=_Two) if result.is_Atom: return result elif arg.is_Pow and arg.base == _Two: return arg.exp
def _eval_evalf(self, *args, **kwargs): return self.rewrite(log).evalf(*args, **kwargs)
def _eval_expand_func(self, **hints): return _log2(*self.args)
def _eval_rewrite_as_log(self, arg, **kwargs): return _log2(arg)
_eval_rewrite_as_tractable = _eval_rewrite_as_log
def _fma(x, y, z): return x*y + z
class fma(Function): """
Represents "fused multiply add".
Explanation ===========
The benefit of using ``fma(x, y, z)`` over ``x*y + z`` is that, under finite precision arithmetic, the former is supported by special instructions on some CPUs.
Examples ========
>>> from sympy.abc import x, y, z >>> from sympy.codegen.cfunctions import fma >>> fma(x, y, z).diff(x) y
"""
nargs = 3
def fdiff(self, argindex=1): """
Returns the first derivative of this function. """
if argindex in (1, 2): return self.args[2 - argindex] elif argindex == 3: return S.One else: raise ArgumentIndexError(self, argindex)
def _eval_expand_func(self, **hints): return _fma(*self.args)
def _eval_rewrite_as_tractable(self, arg, limitvar=None, **kwargs): return _fma(arg)
_Ten = S(10)
def _log10(x): return log(x)/log(_Ten)
class log10(Function): """
Represents the logarithm function with base ten.
Examples ========
>>> from sympy.abc import x >>> from sympy.codegen.cfunctions import log10 >>> log10(100).evalf() == 2 True >>> log10(x).diff(x) 1/(x*log(10))
See Also ========
log2 """
nargs = 1
def fdiff(self, argindex=1): """
Returns the first derivative of this function. """
if argindex == 1: return S.One/(log(_Ten)*self.args[0]) else: raise ArgumentIndexError(self, argindex)
@classmethod def eval(cls, arg): if arg.is_number: result = log.eval(arg, base=_Ten) if result.is_Atom: return result elif arg.is_Pow and arg.base == _Ten: return arg.exp
def _eval_expand_func(self, **hints): return _log10(*self.args)
def _eval_rewrite_as_log(self, arg, **kwargs): return _log10(arg)
_eval_rewrite_as_tractable = _eval_rewrite_as_log
def _Sqrt(x): return Pow(x, S.Half)
class Sqrt(Function): # 'sqrt' already defined in sympy.functions.elementary.miscellaneous """
Represents the square root function.
Explanation ===========
The reason why one would use ``Sqrt(x)`` over ``sqrt(x)`` is that the latter is internally represented as ``Pow(x, S.Half)`` which may not be what one wants when doing code-generation.
Examples ========
>>> from sympy.abc import x >>> from sympy.codegen.cfunctions import Sqrt >>> Sqrt(x) Sqrt(x) >>> Sqrt(x).diff(x) 1/(2*sqrt(x))
See Also ========
Cbrt """
nargs = 1
def fdiff(self, argindex=1): """
Returns the first derivative of this function. """
if argindex == 1: return Pow(self.args[0], Rational(-1, 2))/_Two else: raise ArgumentIndexError(self, argindex)
def _eval_expand_func(self, **hints): return _Sqrt(*self.args)
def _eval_rewrite_as_Pow(self, arg, **kwargs): return _Sqrt(arg)
_eval_rewrite_as_tractable = _eval_rewrite_as_Pow
def _Cbrt(x): return Pow(x, Rational(1, 3))
class Cbrt(Function): # 'cbrt' already defined in sympy.functions.elementary.miscellaneous """
Represents the cube root function.
Explanation ===========
The reason why one would use ``Cbrt(x)`` over ``cbrt(x)`` is that the latter is internally represented as ``Pow(x, Rational(1, 3))`` which may not be what one wants when doing code-generation.
Examples ========
>>> from sympy.abc import x >>> from sympy.codegen.cfunctions import Cbrt >>> Cbrt(x) Cbrt(x) >>> Cbrt(x).diff(x) 1/(3*x**(2/3))
See Also ========
Sqrt """
nargs = 1
def fdiff(self, argindex=1): """
Returns the first derivative of this function. """
if argindex == 1: return Pow(self.args[0], Rational(-_Two/3))/3 else: raise ArgumentIndexError(self, argindex)
def _eval_expand_func(self, **hints): return _Cbrt(*self.args)
def _eval_rewrite_as_Pow(self, arg, **kwargs): return _Cbrt(arg)
_eval_rewrite_as_tractable = _eval_rewrite_as_Pow
def _hypot(x, y): return sqrt(Pow(x, 2) + Pow(y, 2))
class hypot(Function): """
Represents the hypotenuse function.
Explanation ===========
The hypotenuse function is provided by e.g. the math library in the C99 standard, hence one may want to represent the function symbolically when doing code-generation.
Examples ========
>>> from sympy.abc import x, y >>> from sympy.codegen.cfunctions import hypot >>> hypot(3, 4).evalf() == 5 True >>> hypot(x, y) hypot(x, y) >>> hypot(x, y).diff(x) x/hypot(x, y)
"""
nargs = 2
def fdiff(self, argindex=1): """
Returns the first derivative of this function. """
if argindex in (1, 2): return 2*self.args[argindex-1]/(_Two*self.func(*self.args)) else: raise ArgumentIndexError(self, argindex)
def _eval_expand_func(self, **hints): return _hypot(*self.args)
def _eval_rewrite_as_Pow(self, arg, **kwargs): return _hypot(arg)
_eval_rewrite_as_tractable = _eval_rewrite_as_Pow
|