cfunctions.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532
  1. """
  2. This module contains SymPy functions mathcin corresponding to special math functions in the
  3. C standard library (since C99, also available in C++11).
  4. The functions defined in this module allows the user to express functions such as ``expm1``
  5. as a SymPy function for symbolic manipulation.
  6. """
  7. from sympy.core.function import ArgumentIndexError, Function
  8. from sympy.core.numbers import Rational
  9. from sympy.core.power import Pow
  10. from sympy.core.singleton import S
  11. from sympy.functions.elementary.exponential import exp, log
  12. from sympy.functions.elementary.miscellaneous import sqrt
  13. def _expm1(x):
  14. return exp(x) - S.One
  15. class expm1(Function):
  16. """
  17. Represents the exponential function minus one.
  18. Explanation
  19. ===========
  20. The benefit of using ``expm1(x)`` over ``exp(x) - 1``
  21. is that the latter is prone to cancellation under finite precision
  22. arithmetic when x is close to zero.
  23. Examples
  24. ========
  25. >>> from sympy.abc import x
  26. >>> from sympy.codegen.cfunctions import expm1
  27. >>> '%.0e' % expm1(1e-99).evalf()
  28. '1e-99'
  29. >>> from math import exp
  30. >>> exp(1e-99) - 1
  31. 0.0
  32. >>> expm1(x).diff(x)
  33. exp(x)
  34. See Also
  35. ========
  36. log1p
  37. """
  38. nargs = 1
  39. def fdiff(self, argindex=1):
  40. """
  41. Returns the first derivative of this function.
  42. """
  43. if argindex == 1:
  44. return exp(*self.args)
  45. else:
  46. raise ArgumentIndexError(self, argindex)
  47. def _eval_expand_func(self, **hints):
  48. return _expm1(*self.args)
  49. def _eval_rewrite_as_exp(self, arg, **kwargs):
  50. return exp(arg) - S.One
  51. _eval_rewrite_as_tractable = _eval_rewrite_as_exp
  52. @classmethod
  53. def eval(cls, arg):
  54. exp_arg = exp.eval(arg)
  55. if exp_arg is not None:
  56. return exp_arg - S.One
  57. def _eval_is_real(self):
  58. return self.args[0].is_real
  59. def _eval_is_finite(self):
  60. return self.args[0].is_finite
  61. def _log1p(x):
  62. return log(x + S.One)
  63. class log1p(Function):
  64. """
  65. Represents the natural logarithm of a number plus one.
  66. Explanation
  67. ===========
  68. The benefit of using ``log1p(x)`` over ``log(x + 1)``
  69. is that the latter is prone to cancellation under finite precision
  70. arithmetic when x is close to zero.
  71. Examples
  72. ========
  73. >>> from sympy.abc import x
  74. >>> from sympy.codegen.cfunctions import log1p
  75. >>> from sympy import expand_log
  76. >>> '%.0e' % expand_log(log1p(1e-99)).evalf()
  77. '1e-99'
  78. >>> from math import log
  79. >>> log(1 + 1e-99)
  80. 0.0
  81. >>> log1p(x).diff(x)
  82. 1/(x + 1)
  83. See Also
  84. ========
  85. expm1
  86. """
  87. nargs = 1
  88. def fdiff(self, argindex=1):
  89. """
  90. Returns the first derivative of this function.
  91. """
  92. if argindex == 1:
  93. return S.One/(self.args[0] + S.One)
  94. else:
  95. raise ArgumentIndexError(self, argindex)
  96. def _eval_expand_func(self, **hints):
  97. return _log1p(*self.args)
  98. def _eval_rewrite_as_log(self, arg, **kwargs):
  99. return _log1p(arg)
  100. _eval_rewrite_as_tractable = _eval_rewrite_as_log
  101. @classmethod
  102. def eval(cls, arg):
  103. if arg.is_Rational:
  104. return log(arg + S.One)
  105. elif not arg.is_Float: # not safe to add 1 to Float
  106. return log.eval(arg + S.One)
  107. elif arg.is_number:
  108. return log(Rational(arg) + S.One)
  109. def _eval_is_real(self):
  110. return (self.args[0] + S.One).is_nonnegative
  111. def _eval_is_finite(self):
  112. if (self.args[0] + S.One).is_zero:
  113. return False
  114. return self.args[0].is_finite
  115. def _eval_is_positive(self):
  116. return self.args[0].is_positive
  117. def _eval_is_zero(self):
  118. return self.args[0].is_zero
  119. def _eval_is_nonnegative(self):
  120. return self.args[0].is_nonnegative
  121. _Two = S(2)
  122. def _exp2(x):
  123. return Pow(_Two, x)
  124. class exp2(Function):
  125. """
  126. Represents the exponential function with base two.
  127. Explanation
  128. ===========
  129. The benefit of using ``exp2(x)`` over ``2**x``
  130. is that the latter is not as efficient under finite precision
  131. arithmetic.
  132. Examples
  133. ========
  134. >>> from sympy.abc import x
  135. >>> from sympy.codegen.cfunctions import exp2
  136. >>> exp2(2).evalf() == 4
  137. True
  138. >>> exp2(x).diff(x)
  139. log(2)*exp2(x)
  140. See Also
  141. ========
  142. log2
  143. """
  144. nargs = 1
  145. def fdiff(self, argindex=1):
  146. """
  147. Returns the first derivative of this function.
  148. """
  149. if argindex == 1:
  150. return self*log(_Two)
  151. else:
  152. raise ArgumentIndexError(self, argindex)
  153. def _eval_rewrite_as_Pow(self, arg, **kwargs):
  154. return _exp2(arg)
  155. _eval_rewrite_as_tractable = _eval_rewrite_as_Pow
  156. def _eval_expand_func(self, **hints):
  157. return _exp2(*self.args)
  158. @classmethod
  159. def eval(cls, arg):
  160. if arg.is_number:
  161. return _exp2(arg)
  162. def _log2(x):
  163. return log(x)/log(_Two)
  164. class log2(Function):
  165. """
  166. Represents the logarithm function with base two.
  167. Explanation
  168. ===========
  169. The benefit of using ``log2(x)`` over ``log(x)/log(2)``
  170. is that the latter is not as efficient under finite precision
  171. arithmetic.
  172. Examples
  173. ========
  174. >>> from sympy.abc import x
  175. >>> from sympy.codegen.cfunctions import log2
  176. >>> log2(4).evalf() == 2
  177. True
  178. >>> log2(x).diff(x)
  179. 1/(x*log(2))
  180. See Also
  181. ========
  182. exp2
  183. log10
  184. """
  185. nargs = 1
  186. def fdiff(self, argindex=1):
  187. """
  188. Returns the first derivative of this function.
  189. """
  190. if argindex == 1:
  191. return S.One/(log(_Two)*self.args[0])
  192. else:
  193. raise ArgumentIndexError(self, argindex)
  194. @classmethod
  195. def eval(cls, arg):
  196. if arg.is_number:
  197. result = log.eval(arg, base=_Two)
  198. if result.is_Atom:
  199. return result
  200. elif arg.is_Pow and arg.base == _Two:
  201. return arg.exp
  202. def _eval_evalf(self, *args, **kwargs):
  203. return self.rewrite(log).evalf(*args, **kwargs)
  204. def _eval_expand_func(self, **hints):
  205. return _log2(*self.args)
  206. def _eval_rewrite_as_log(self, arg, **kwargs):
  207. return _log2(arg)
  208. _eval_rewrite_as_tractable = _eval_rewrite_as_log
  209. def _fma(x, y, z):
  210. return x*y + z
  211. class fma(Function):
  212. """
  213. Represents "fused multiply add".
  214. Explanation
  215. ===========
  216. The benefit of using ``fma(x, y, z)`` over ``x*y + z``
  217. is that, under finite precision arithmetic, the former is
  218. supported by special instructions on some CPUs.
  219. Examples
  220. ========
  221. >>> from sympy.abc import x, y, z
  222. >>> from sympy.codegen.cfunctions import fma
  223. >>> fma(x, y, z).diff(x)
  224. y
  225. """
  226. nargs = 3
  227. def fdiff(self, argindex=1):
  228. """
  229. Returns the first derivative of this function.
  230. """
  231. if argindex in (1, 2):
  232. return self.args[2 - argindex]
  233. elif argindex == 3:
  234. return S.One
  235. else:
  236. raise ArgumentIndexError(self, argindex)
  237. def _eval_expand_func(self, **hints):
  238. return _fma(*self.args)
  239. def _eval_rewrite_as_tractable(self, arg, limitvar=None, **kwargs):
  240. return _fma(arg)
  241. _Ten = S(10)
  242. def _log10(x):
  243. return log(x)/log(_Ten)
  244. class log10(Function):
  245. """
  246. Represents the logarithm function with base ten.
  247. Examples
  248. ========
  249. >>> from sympy.abc import x
  250. >>> from sympy.codegen.cfunctions import log10
  251. >>> log10(100).evalf() == 2
  252. True
  253. >>> log10(x).diff(x)
  254. 1/(x*log(10))
  255. See Also
  256. ========
  257. log2
  258. """
  259. nargs = 1
  260. def fdiff(self, argindex=1):
  261. """
  262. Returns the first derivative of this function.
  263. """
  264. if argindex == 1:
  265. return S.One/(log(_Ten)*self.args[0])
  266. else:
  267. raise ArgumentIndexError(self, argindex)
  268. @classmethod
  269. def eval(cls, arg):
  270. if arg.is_number:
  271. result = log.eval(arg, base=_Ten)
  272. if result.is_Atom:
  273. return result
  274. elif arg.is_Pow and arg.base == _Ten:
  275. return arg.exp
  276. def _eval_expand_func(self, **hints):
  277. return _log10(*self.args)
  278. def _eval_rewrite_as_log(self, arg, **kwargs):
  279. return _log10(arg)
  280. _eval_rewrite_as_tractable = _eval_rewrite_as_log
  281. def _Sqrt(x):
  282. return Pow(x, S.Half)
  283. class Sqrt(Function): # 'sqrt' already defined in sympy.functions.elementary.miscellaneous
  284. """
  285. Represents the square root function.
  286. Explanation
  287. ===========
  288. The reason why one would use ``Sqrt(x)`` over ``sqrt(x)``
  289. is that the latter is internally represented as ``Pow(x, S.Half)`` which
  290. may not be what one wants when doing code-generation.
  291. Examples
  292. ========
  293. >>> from sympy.abc import x
  294. >>> from sympy.codegen.cfunctions import Sqrt
  295. >>> Sqrt(x)
  296. Sqrt(x)
  297. >>> Sqrt(x).diff(x)
  298. 1/(2*sqrt(x))
  299. See Also
  300. ========
  301. Cbrt
  302. """
  303. nargs = 1
  304. def fdiff(self, argindex=1):
  305. """
  306. Returns the first derivative of this function.
  307. """
  308. if argindex == 1:
  309. return Pow(self.args[0], Rational(-1, 2))/_Two
  310. else:
  311. raise ArgumentIndexError(self, argindex)
  312. def _eval_expand_func(self, **hints):
  313. return _Sqrt(*self.args)
  314. def _eval_rewrite_as_Pow(self, arg, **kwargs):
  315. return _Sqrt(arg)
  316. _eval_rewrite_as_tractable = _eval_rewrite_as_Pow
  317. def _Cbrt(x):
  318. return Pow(x, Rational(1, 3))
  319. class Cbrt(Function): # 'cbrt' already defined in sympy.functions.elementary.miscellaneous
  320. """
  321. Represents the cube root function.
  322. Explanation
  323. ===========
  324. The reason why one would use ``Cbrt(x)`` over ``cbrt(x)``
  325. is that the latter is internally represented as ``Pow(x, Rational(1, 3))`` which
  326. may not be what one wants when doing code-generation.
  327. Examples
  328. ========
  329. >>> from sympy.abc import x
  330. >>> from sympy.codegen.cfunctions import Cbrt
  331. >>> Cbrt(x)
  332. Cbrt(x)
  333. >>> Cbrt(x).diff(x)
  334. 1/(3*x**(2/3))
  335. See Also
  336. ========
  337. Sqrt
  338. """
  339. nargs = 1
  340. def fdiff(self, argindex=1):
  341. """
  342. Returns the first derivative of this function.
  343. """
  344. if argindex == 1:
  345. return Pow(self.args[0], Rational(-_Two/3))/3
  346. else:
  347. raise ArgumentIndexError(self, argindex)
  348. def _eval_expand_func(self, **hints):
  349. return _Cbrt(*self.args)
  350. def _eval_rewrite_as_Pow(self, arg, **kwargs):
  351. return _Cbrt(arg)
  352. _eval_rewrite_as_tractable = _eval_rewrite_as_Pow
  353. def _hypot(x, y):
  354. return sqrt(Pow(x, 2) + Pow(y, 2))
  355. class hypot(Function):
  356. """
  357. Represents the hypotenuse function.
  358. Explanation
  359. ===========
  360. The hypotenuse function is provided by e.g. the math library
  361. in the C99 standard, hence one may want to represent the function
  362. symbolically when doing code-generation.
  363. Examples
  364. ========
  365. >>> from sympy.abc import x, y
  366. >>> from sympy.codegen.cfunctions import hypot
  367. >>> hypot(3, 4).evalf() == 5
  368. True
  369. >>> hypot(x, y)
  370. hypot(x, y)
  371. >>> hypot(x, y).diff(x)
  372. x/hypot(x, y)
  373. """
  374. nargs = 2
  375. def fdiff(self, argindex=1):
  376. """
  377. Returns the first derivative of this function.
  378. """
  379. if argindex in (1, 2):
  380. return 2*self.args[argindex-1]/(_Two*self.func(*self.args))
  381. else:
  382. raise ArgumentIndexError(self, argindex)
  383. def _eval_expand_func(self, **hints):
  384. return _hypot(*self.args)
  385. def _eval_rewrite_as_Pow(self, arg, **kwargs):
  386. return _hypot(arg)
  387. _eval_rewrite_as_tractable = _eval_rewrite_as_Pow