# 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

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)

========

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)

========

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)

========

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))

========

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):
"""

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))

========

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))

========

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))

========

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