123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532 |
- """
- 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
|