Source code for sympy.codegen.cfunctions

"""
Functions with corresponding implementations in C.

The functions defined in this module allows the user to express functions such as ``expm1``
as a SymPy function for symbolic manipulation.

"""

import math
from sympy.core.singleton import S
from sympy.core.numbers import Rational
from sympy.core.function import ArgumentIndexError, Function, Lambda
from sympy.core.power import Pow
from sympy.functions.elementary.miscellaneous import sqrt
from sympy.functions.elementary.exponential import exp, log
from .ast import Attribute

restrict = Attribute('restrict')  # guarantees no pointer aliasing
volatile = Attribute('volatile')
static = Attribute('static')

def _expm1(x):
    return exp(x) - S.One


[docs]class expm1(Function): """ Represents the exponential function minus one. 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
[docs] 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): 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)
[docs]class log1p(Function): """ Represents the natural logarithm of a number plus one. 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 >>> '%.0e' % 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
[docs] 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): return _log1p(arg) _eval_rewrite_as_tractable = _eval_rewrite_as_log @classmethod def eval(cls, arg): if not arg.is_Float: # not safe to add 1 to Float return log.eval(arg + S.One) elif arg.is_number: return log.eval(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)
[docs]class exp2(Function): """ Represents the exponential function with base two. 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
[docs] 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): 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)
[docs]class log2(Function): """ Represents the logarithm function with base two. 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
[docs] 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_expand_func(self, **hints): return _log2(*self.args) def _eval_rewrite_as_log(self, arg): return _log2(arg) _eval_rewrite_as_tractable = _eval_rewrite_as_log
def _fma(x, y, z): return x*y + z
[docs]class fma(Function): """ Represents "fused multiply add". 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
[docs] 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): return _fma(arg)
_Ten = S(10) def _log10(x): return log(x)/log(_Ten)
[docs]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
[docs] 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): return _log10(arg) _eval_rewrite_as_tractable = _eval_rewrite_as_log
def _Sqrt(x): return Pow(x, S.Half)
[docs]class Sqrt(Function): # 'sqrt' already defined in sympy.functions.elementary.miscellaneous """ Represents the square root function. 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
[docs] def fdiff(self, argindex=1): """ Returns the first derivative of this function. """ if argindex == 1: return Pow(self.args[0], -S.Half)/_Two else: raise ArgumentIndexError(self, argindex)
def _eval_expand_func(self, **hints): return _Sqrt(*self.args) def _eval_rewrite_as_Pow(self, arg): return _Sqrt(arg) _eval_rewrite_as_tractable = _eval_rewrite_as_Pow
def _Cbrt(x): return Pow(x, Rational(1, 3))
[docs]class Cbrt(Function): # 'cbrt' already defined in sympy.functions.elementary.miscellaneous """ Represents the cube root function. 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
[docs] 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): return _Cbrt(arg) _eval_rewrite_as_tractable = _eval_rewrite_as_Pow
def _hypot(x, y): return sqrt(Pow(x, 2) + Pow(y, 2))
[docs]class hypot(Function): """ Represents the hypotenuse function. 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
[docs] 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): return _hypot(arg) _eval_rewrite_as_tractable = _eval_rewrite_as_Pow