hyperbolic.py 68 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285
  1. from sympy.core import S, sympify, cacheit
  2. from sympy.core.add import Add
  3. from sympy.core.function import DefinedFunction, ArgumentIndexError
  4. from sympy.core.logic import fuzzy_or, fuzzy_and, fuzzy_not, FuzzyBool
  5. from sympy.core.numbers import I, pi, Rational
  6. from sympy.core.symbol import Dummy
  7. from sympy.functions.combinatorial.factorials import (binomial, factorial,
  8. RisingFactorial)
  9. from sympy.functions.combinatorial.numbers import bernoulli, euler, nC
  10. from sympy.functions.elementary.complexes import Abs, im, re
  11. from sympy.functions.elementary.exponential import exp, log, match_real_imag
  12. from sympy.functions.elementary.integers import floor
  13. from sympy.functions.elementary.miscellaneous import sqrt
  14. from sympy.functions.elementary.trigonometric import (
  15. acos, acot, asin, atan, cos, cot, csc, sec, sin, tan,
  16. _imaginary_unit_as_coefficient)
  17. from sympy.polys.specialpolys import symmetric_poly
  18. def _rewrite_hyperbolics_as_exp(expr):
  19. return expr.xreplace({h: h.rewrite(exp)
  20. for h in expr.atoms(HyperbolicFunction)})
  21. @cacheit
  22. def _acosh_table():
  23. return {
  24. I: log(I*(1 + sqrt(2))),
  25. -I: log(-I*(1 + sqrt(2))),
  26. S.Half: pi/3,
  27. Rational(-1, 2): pi*Rational(2, 3),
  28. sqrt(2)/2: pi/4,
  29. -sqrt(2)/2: pi*Rational(3, 4),
  30. 1/sqrt(2): pi/4,
  31. -1/sqrt(2): pi*Rational(3, 4),
  32. sqrt(3)/2: pi/6,
  33. -sqrt(3)/2: pi*Rational(5, 6),
  34. (sqrt(3) - 1)/sqrt(2**3): pi*Rational(5, 12),
  35. -(sqrt(3) - 1)/sqrt(2**3): pi*Rational(7, 12),
  36. sqrt(2 + sqrt(2))/2: pi/8,
  37. -sqrt(2 + sqrt(2))/2: pi*Rational(7, 8),
  38. sqrt(2 - sqrt(2))/2: pi*Rational(3, 8),
  39. -sqrt(2 - sqrt(2))/2: pi*Rational(5, 8),
  40. (1 + sqrt(3))/(2*sqrt(2)): pi/12,
  41. -(1 + sqrt(3))/(2*sqrt(2)): pi*Rational(11, 12),
  42. (sqrt(5) + 1)/4: pi/5,
  43. -(sqrt(5) + 1)/4: pi*Rational(4, 5)
  44. }
  45. @cacheit
  46. def _acsch_table():
  47. return {
  48. I: -pi / 2,
  49. I*(sqrt(2) + sqrt(6)): -pi / 12,
  50. I*(1 + sqrt(5)): -pi / 10,
  51. I*2 / sqrt(2 - sqrt(2)): -pi / 8,
  52. I*2: -pi / 6,
  53. I*sqrt(2 + 2/sqrt(5)): -pi / 5,
  54. I*sqrt(2): -pi / 4,
  55. I*(sqrt(5)-1): -3*pi / 10,
  56. I*2 / sqrt(3): -pi / 3,
  57. I*2 / sqrt(2 + sqrt(2)): -3*pi / 8,
  58. I*sqrt(2 - 2/sqrt(5)): -2*pi / 5,
  59. I*(sqrt(6) - sqrt(2)): -5*pi / 12,
  60. S(2): -I*log((1+sqrt(5))/2),
  61. }
  62. @cacheit
  63. def _asech_table():
  64. return {
  65. I: - (pi*I / 2) + log(1 + sqrt(2)),
  66. -I: (pi*I / 2) + log(1 + sqrt(2)),
  67. (sqrt(6) - sqrt(2)): pi / 12,
  68. (sqrt(2) - sqrt(6)): 11*pi / 12,
  69. sqrt(2 - 2/sqrt(5)): pi / 10,
  70. -sqrt(2 - 2/sqrt(5)): 9*pi / 10,
  71. 2 / sqrt(2 + sqrt(2)): pi / 8,
  72. -2 / sqrt(2 + sqrt(2)): 7*pi / 8,
  73. 2 / sqrt(3): pi / 6,
  74. -2 / sqrt(3): 5*pi / 6,
  75. (sqrt(5) - 1): pi / 5,
  76. (1 - sqrt(5)): 4*pi / 5,
  77. sqrt(2): pi / 4,
  78. -sqrt(2): 3*pi / 4,
  79. sqrt(2 + 2/sqrt(5)): 3*pi / 10,
  80. -sqrt(2 + 2/sqrt(5)): 7*pi / 10,
  81. S(2): pi / 3,
  82. -S(2): 2*pi / 3,
  83. sqrt(2*(2 + sqrt(2))): 3*pi / 8,
  84. -sqrt(2*(2 + sqrt(2))): 5*pi / 8,
  85. (1 + sqrt(5)): 2*pi / 5,
  86. (-1 - sqrt(5)): 3*pi / 5,
  87. (sqrt(6) + sqrt(2)): 5*pi / 12,
  88. (-sqrt(6) - sqrt(2)): 7*pi / 12,
  89. I*S.Infinity: -pi*I / 2,
  90. I*S.NegativeInfinity: pi*I / 2,
  91. }
  92. ###############################################################################
  93. ########################### HYPERBOLIC FUNCTIONS ##############################
  94. ###############################################################################
  95. class HyperbolicFunction(DefinedFunction):
  96. """
  97. Base class for hyperbolic functions.
  98. See Also
  99. ========
  100. sinh, cosh, tanh, coth
  101. """
  102. unbranched = True
  103. def _peeloff_ipi(arg):
  104. r"""
  105. Split ARG into two parts, a "rest" and a multiple of $I\pi$.
  106. This assumes ARG to be an ``Add``.
  107. The multiple of $I\pi$ returned in the second position is always a ``Rational``.
  108. Examples
  109. ========
  110. >>> from sympy.functions.elementary.hyperbolic import _peeloff_ipi as peel
  111. >>> from sympy import pi, I
  112. >>> from sympy.abc import x, y
  113. >>> peel(x + I*pi/2)
  114. (x, 1/2)
  115. >>> peel(x + I*2*pi/3 + I*pi*y)
  116. (x + I*pi*y + I*pi/6, 1/2)
  117. """
  118. ipi = pi*I
  119. for a in Add.make_args(arg):
  120. if a == ipi:
  121. K = S.One
  122. break
  123. elif a.is_Mul:
  124. K, p = a.as_two_terms()
  125. if p == ipi and K.is_Rational:
  126. break
  127. else:
  128. return arg, S.Zero
  129. m1 = (K % S.Half)
  130. m2 = K - m1
  131. return arg - m2*ipi, m2
  132. class sinh(HyperbolicFunction):
  133. r"""
  134. ``sinh(x)`` is the hyperbolic sine of ``x``.
  135. The hyperbolic sine function is $\frac{e^x - e^{-x}}{2}$.
  136. Examples
  137. ========
  138. >>> from sympy import sinh
  139. >>> from sympy.abc import x
  140. >>> sinh(x)
  141. sinh(x)
  142. See Also
  143. ========
  144. cosh, tanh, asinh
  145. """
  146. def fdiff(self, argindex=1):
  147. """
  148. Returns the first derivative of this function.
  149. """
  150. if argindex == 1:
  151. return cosh(self.args[0])
  152. else:
  153. raise ArgumentIndexError(self, argindex)
  154. def inverse(self, argindex=1):
  155. """
  156. Returns the inverse of this function.
  157. """
  158. return asinh
  159. @classmethod
  160. def eval(cls, arg):
  161. if arg.is_Number:
  162. if arg is S.NaN:
  163. return S.NaN
  164. elif arg is S.Infinity:
  165. return S.Infinity
  166. elif arg is S.NegativeInfinity:
  167. return S.NegativeInfinity
  168. elif arg.is_zero:
  169. return S.Zero
  170. elif arg.is_negative:
  171. return -cls(-arg)
  172. else:
  173. if arg is S.ComplexInfinity:
  174. return S.NaN
  175. i_coeff = _imaginary_unit_as_coefficient(arg)
  176. if i_coeff is not None:
  177. return I * sin(i_coeff)
  178. else:
  179. if arg.could_extract_minus_sign():
  180. return -cls(-arg)
  181. if arg.is_Add:
  182. x, m = _peeloff_ipi(arg)
  183. if m:
  184. m = m*pi*I
  185. return sinh(m)*cosh(x) + cosh(m)*sinh(x)
  186. if arg.is_zero:
  187. return S.Zero
  188. if arg.func == asinh:
  189. return arg.args[0]
  190. if arg.func == acosh:
  191. x = arg.args[0]
  192. return sqrt(x - 1) * sqrt(x + 1)
  193. if arg.func == atanh:
  194. x = arg.args[0]
  195. return x/sqrt(1 - x**2)
  196. if arg.func == acoth:
  197. x = arg.args[0]
  198. return 1/(sqrt(x - 1) * sqrt(x + 1))
  199. @staticmethod
  200. @cacheit
  201. def taylor_term(n, x, *previous_terms):
  202. """
  203. Returns the next term in the Taylor series expansion.
  204. """
  205. if n < 0 or n % 2 == 0:
  206. return S.Zero
  207. else:
  208. x = sympify(x)
  209. if len(previous_terms) > 2:
  210. p = previous_terms[-2]
  211. return p * x**2 / (n*(n - 1))
  212. else:
  213. return x**(n) / factorial(n)
  214. def _eval_conjugate(self):
  215. return self.func(self.args[0].conjugate())
  216. def as_real_imag(self, deep=True, **hints):
  217. """
  218. Returns this function as a complex coordinate.
  219. """
  220. if self.args[0].is_extended_real:
  221. if deep:
  222. hints['complex'] = False
  223. return (self.expand(deep, **hints), S.Zero)
  224. else:
  225. return (self, S.Zero)
  226. if deep:
  227. re, im = self.args[0].expand(deep, **hints).as_real_imag()
  228. else:
  229. re, im = self.args[0].as_real_imag()
  230. return (sinh(re)*cos(im), cosh(re)*sin(im))
  231. def _eval_expand_complex(self, deep=True, **hints):
  232. re_part, im_part = self.as_real_imag(deep=deep, **hints)
  233. return re_part + im_part*I
  234. def _eval_expand_trig(self, deep=True, **hints):
  235. if deep:
  236. arg = self.args[0].expand(deep, **hints)
  237. else:
  238. arg = self.args[0]
  239. x = None
  240. if arg.is_Add: # TODO, implement more if deep stuff here
  241. x, y = arg.as_two_terms()
  242. else:
  243. coeff, terms = arg.as_coeff_Mul(rational=True)
  244. if coeff is not S.One and coeff.is_Integer and terms is not S.One:
  245. x = terms
  246. y = (coeff - 1)*x
  247. if x is not None:
  248. return (sinh(x)*cosh(y) + sinh(y)*cosh(x)).expand(trig=True)
  249. return sinh(arg)
  250. def _eval_rewrite_as_tractable(self, arg, limitvar=None, **kwargs):
  251. return (exp(arg) - exp(-arg)) / 2
  252. def _eval_rewrite_as_exp(self, arg, **kwargs):
  253. return (exp(arg) - exp(-arg)) / 2
  254. def _eval_rewrite_as_sin(self, arg, **kwargs):
  255. return -I * sin(I * arg)
  256. def _eval_rewrite_as_csc(self, arg, **kwargs):
  257. return -I / csc(I * arg)
  258. def _eval_rewrite_as_cosh(self, arg, **kwargs):
  259. return -I*cosh(arg + pi*I/2)
  260. def _eval_rewrite_as_tanh(self, arg, **kwargs):
  261. tanh_half = tanh(S.Half*arg)
  262. return 2*tanh_half/(1 - tanh_half**2)
  263. def _eval_rewrite_as_coth(self, arg, **kwargs):
  264. coth_half = coth(S.Half*arg)
  265. return 2*coth_half/(coth_half**2 - 1)
  266. def _eval_rewrite_as_csch(self, arg, **kwargs):
  267. return 1 / csch(arg)
  268. def _eval_as_leading_term(self, x, logx, cdir):
  269. arg = self.args[0].as_leading_term(x, logx=logx, cdir=cdir)
  270. arg0 = arg.subs(x, 0)
  271. if arg0 is S.NaN:
  272. arg0 = arg.limit(x, 0, dir='-' if cdir.is_negative else '+')
  273. if arg0.is_zero:
  274. return arg
  275. elif arg0.is_finite:
  276. return self.func(arg0)
  277. else:
  278. return self
  279. def _eval_is_real(self):
  280. arg = self.args[0]
  281. if arg.is_real:
  282. return True
  283. # if `im` is of the form n*pi
  284. # else, check if it is a number
  285. re, im = arg.as_real_imag()
  286. return (im%pi).is_zero
  287. def _eval_is_extended_real(self):
  288. if self.args[0].is_extended_real:
  289. return True
  290. def _eval_is_positive(self):
  291. if self.args[0].is_extended_real:
  292. return self.args[0].is_positive
  293. def _eval_is_negative(self):
  294. if self.args[0].is_extended_real:
  295. return self.args[0].is_negative
  296. def _eval_is_finite(self):
  297. arg = self.args[0]
  298. return arg.is_finite
  299. def _eval_is_zero(self):
  300. rest, ipi_mult = _peeloff_ipi(self.args[0])
  301. if rest.is_zero:
  302. return ipi_mult.is_integer
  303. class cosh(HyperbolicFunction):
  304. r"""
  305. ``cosh(x)`` is the hyperbolic cosine of ``x``.
  306. The hyperbolic cosine function is $\frac{e^x + e^{-x}}{2}$.
  307. Examples
  308. ========
  309. >>> from sympy import cosh
  310. >>> from sympy.abc import x
  311. >>> cosh(x)
  312. cosh(x)
  313. See Also
  314. ========
  315. sinh, tanh, acosh
  316. """
  317. def fdiff(self, argindex=1):
  318. if argindex == 1:
  319. return sinh(self.args[0])
  320. else:
  321. raise ArgumentIndexError(self, argindex)
  322. @classmethod
  323. def eval(cls, arg):
  324. from sympy.functions.elementary.trigonometric import cos
  325. if arg.is_Number:
  326. if arg is S.NaN:
  327. return S.NaN
  328. elif arg is S.Infinity:
  329. return S.Infinity
  330. elif arg is S.NegativeInfinity:
  331. return S.Infinity
  332. elif arg.is_zero:
  333. return S.One
  334. elif arg.is_negative:
  335. return cls(-arg)
  336. else:
  337. if arg is S.ComplexInfinity:
  338. return S.NaN
  339. i_coeff = _imaginary_unit_as_coefficient(arg)
  340. if i_coeff is not None:
  341. return cos(i_coeff)
  342. else:
  343. if arg.could_extract_minus_sign():
  344. return cls(-arg)
  345. if arg.is_Add:
  346. x, m = _peeloff_ipi(arg)
  347. if m:
  348. m = m*pi*I
  349. return cosh(m)*cosh(x) + sinh(m)*sinh(x)
  350. if arg.is_zero:
  351. return S.One
  352. if arg.func == asinh:
  353. return sqrt(1 + arg.args[0]**2)
  354. if arg.func == acosh:
  355. return arg.args[0]
  356. if arg.func == atanh:
  357. return 1/sqrt(1 - arg.args[0]**2)
  358. if arg.func == acoth:
  359. x = arg.args[0]
  360. return x/(sqrt(x - 1) * sqrt(x + 1))
  361. @staticmethod
  362. @cacheit
  363. def taylor_term(n, x, *previous_terms):
  364. if n < 0 or n % 2 == 1:
  365. return S.Zero
  366. else:
  367. x = sympify(x)
  368. if len(previous_terms) > 2:
  369. p = previous_terms[-2]
  370. return p * x**2 / (n*(n - 1))
  371. else:
  372. return x**(n)/factorial(n)
  373. def _eval_conjugate(self):
  374. return self.func(self.args[0].conjugate())
  375. def as_real_imag(self, deep=True, **hints):
  376. if self.args[0].is_extended_real:
  377. if deep:
  378. hints['complex'] = False
  379. return (self.expand(deep, **hints), S.Zero)
  380. else:
  381. return (self, S.Zero)
  382. if deep:
  383. re, im = self.args[0].expand(deep, **hints).as_real_imag()
  384. else:
  385. re, im = self.args[0].as_real_imag()
  386. return (cosh(re)*cos(im), sinh(re)*sin(im))
  387. def _eval_expand_complex(self, deep=True, **hints):
  388. re_part, im_part = self.as_real_imag(deep=deep, **hints)
  389. return re_part + im_part*I
  390. def _eval_expand_trig(self, deep=True, **hints):
  391. if deep:
  392. arg = self.args[0].expand(deep, **hints)
  393. else:
  394. arg = self.args[0]
  395. x = None
  396. if arg.is_Add: # TODO, implement more if deep stuff here
  397. x, y = arg.as_two_terms()
  398. else:
  399. coeff, terms = arg.as_coeff_Mul(rational=True)
  400. if coeff is not S.One and coeff.is_Integer and terms is not S.One:
  401. x = terms
  402. y = (coeff - 1)*x
  403. if x is not None:
  404. return (cosh(x)*cosh(y) + sinh(x)*sinh(y)).expand(trig=True)
  405. return cosh(arg)
  406. def _eval_rewrite_as_tractable(self, arg, limitvar=None, **kwargs):
  407. return (exp(arg) + exp(-arg)) / 2
  408. def _eval_rewrite_as_exp(self, arg, **kwargs):
  409. return (exp(arg) + exp(-arg)) / 2
  410. def _eval_rewrite_as_cos(self, arg, **kwargs):
  411. return cos(I * arg, evaluate=False)
  412. def _eval_rewrite_as_sec(self, arg, **kwargs):
  413. return 1 / sec(I * arg, evaluate=False)
  414. def _eval_rewrite_as_sinh(self, arg, **kwargs):
  415. return -I*sinh(arg + pi*I/2, evaluate=False)
  416. def _eval_rewrite_as_tanh(self, arg, **kwargs):
  417. tanh_half = tanh(S.Half*arg)**2
  418. return (1 + tanh_half)/(1 - tanh_half)
  419. def _eval_rewrite_as_coth(self, arg, **kwargs):
  420. coth_half = coth(S.Half*arg)**2
  421. return (coth_half + 1)/(coth_half - 1)
  422. def _eval_rewrite_as_sech(self, arg, **kwargs):
  423. return 1 / sech(arg)
  424. def _eval_as_leading_term(self, x, logx, cdir):
  425. arg = self.args[0].as_leading_term(x, logx=logx, cdir=cdir)
  426. arg0 = arg.subs(x, 0)
  427. if arg0 is S.NaN:
  428. arg0 = arg.limit(x, 0, dir='-' if cdir.is_negative else '+')
  429. if arg0.is_zero:
  430. return S.One
  431. elif arg0.is_finite:
  432. return self.func(arg0)
  433. else:
  434. return self
  435. def _eval_is_real(self):
  436. arg = self.args[0]
  437. # `cosh(x)` is real for real OR purely imaginary `x`
  438. if arg.is_real or arg.is_imaginary:
  439. return True
  440. # cosh(a+ib) = cos(b)*cosh(a) + i*sin(b)*sinh(a)
  441. # the imaginary part can be an expression like n*pi
  442. # if not, check if the imaginary part is a number
  443. re, im = arg.as_real_imag()
  444. return (im%pi).is_zero
  445. def _eval_is_positive(self):
  446. # cosh(x+I*y) = cos(y)*cosh(x) + I*sin(y)*sinh(x)
  447. # cosh(z) is positive iff it is real and the real part is positive.
  448. # So we need sin(y)*sinh(x) = 0 which gives x=0 or y=n*pi
  449. # Case 1 (y=n*pi): cosh(z) = (-1)**n * cosh(x) -> positive for n even
  450. # Case 2 (x=0): cosh(z) = cos(y) -> positive when cos(y) is positive
  451. z = self.args[0]
  452. x, y = z.as_real_imag()
  453. ymod = y % (2*pi)
  454. yzero = ymod.is_zero
  455. # shortcut if ymod is zero
  456. if yzero:
  457. return True
  458. xzero = x.is_zero
  459. # shortcut x is not zero
  460. if xzero is False:
  461. return yzero
  462. return fuzzy_or([
  463. # Case 1:
  464. yzero,
  465. # Case 2:
  466. fuzzy_and([
  467. xzero,
  468. fuzzy_or([ymod < pi/2, ymod > 3*pi/2])
  469. ])
  470. ])
  471. def _eval_is_nonnegative(self):
  472. z = self.args[0]
  473. x, y = z.as_real_imag()
  474. ymod = y % (2*pi)
  475. yzero = ymod.is_zero
  476. # shortcut if ymod is zero
  477. if yzero:
  478. return True
  479. xzero = x.is_zero
  480. # shortcut x is not zero
  481. if xzero is False:
  482. return yzero
  483. return fuzzy_or([
  484. # Case 1:
  485. yzero,
  486. # Case 2:
  487. fuzzy_and([
  488. xzero,
  489. fuzzy_or([ymod <= pi/2, ymod >= 3*pi/2])
  490. ])
  491. ])
  492. def _eval_is_finite(self):
  493. arg = self.args[0]
  494. return arg.is_finite
  495. def _eval_is_zero(self):
  496. rest, ipi_mult = _peeloff_ipi(self.args[0])
  497. if ipi_mult and rest.is_zero:
  498. return (ipi_mult - S.Half).is_integer
  499. class tanh(HyperbolicFunction):
  500. r"""
  501. ``tanh(x)`` is the hyperbolic tangent of ``x``.
  502. The hyperbolic tangent function is $\frac{\sinh(x)}{\cosh(x)}$.
  503. Examples
  504. ========
  505. >>> from sympy import tanh
  506. >>> from sympy.abc import x
  507. >>> tanh(x)
  508. tanh(x)
  509. See Also
  510. ========
  511. sinh, cosh, atanh
  512. """
  513. def fdiff(self, argindex=1):
  514. if argindex == 1:
  515. return S.One - tanh(self.args[0])**2
  516. else:
  517. raise ArgumentIndexError(self, argindex)
  518. def inverse(self, argindex=1):
  519. """
  520. Returns the inverse of this function.
  521. """
  522. return atanh
  523. @classmethod
  524. def eval(cls, arg):
  525. if arg.is_Number:
  526. if arg is S.NaN:
  527. return S.NaN
  528. elif arg is S.Infinity:
  529. return S.One
  530. elif arg is S.NegativeInfinity:
  531. return S.NegativeOne
  532. elif arg.is_zero:
  533. return S.Zero
  534. elif arg.is_negative:
  535. return -cls(-arg)
  536. else:
  537. if arg is S.ComplexInfinity:
  538. return S.NaN
  539. i_coeff = _imaginary_unit_as_coefficient(arg)
  540. if i_coeff is not None:
  541. if i_coeff.could_extract_minus_sign():
  542. return -I * tan(-i_coeff)
  543. return I * tan(i_coeff)
  544. else:
  545. if arg.could_extract_minus_sign():
  546. return -cls(-arg)
  547. if arg.is_Add:
  548. x, m = _peeloff_ipi(arg)
  549. if m:
  550. tanhm = tanh(m*pi*I)
  551. if tanhm is S.ComplexInfinity:
  552. return coth(x)
  553. else: # tanhm == 0
  554. return tanh(x)
  555. if arg.is_zero:
  556. return S.Zero
  557. if arg.func == asinh:
  558. x = arg.args[0]
  559. return x/sqrt(1 + x**2)
  560. if arg.func == acosh:
  561. x = arg.args[0]
  562. return sqrt(x - 1) * sqrt(x + 1) / x
  563. if arg.func == atanh:
  564. return arg.args[0]
  565. if arg.func == acoth:
  566. return 1/arg.args[0]
  567. @staticmethod
  568. @cacheit
  569. def taylor_term(n, x, *previous_terms):
  570. if n < 0 or n % 2 == 0:
  571. return S.Zero
  572. else:
  573. x = sympify(x)
  574. a = 2**(n + 1)
  575. B = bernoulli(n + 1)
  576. F = factorial(n + 1)
  577. return a*(a - 1) * B/F * x**n
  578. def _eval_conjugate(self):
  579. return self.func(self.args[0].conjugate())
  580. def as_real_imag(self, deep=True, **hints):
  581. if self.args[0].is_extended_real:
  582. if deep:
  583. hints['complex'] = False
  584. return (self.expand(deep, **hints), S.Zero)
  585. else:
  586. return (self, S.Zero)
  587. if deep:
  588. re, im = self.args[0].expand(deep, **hints).as_real_imag()
  589. else:
  590. re, im = self.args[0].as_real_imag()
  591. denom = sinh(re)**2 + cos(im)**2
  592. return (sinh(re)*cosh(re)/denom, sin(im)*cos(im)/denom)
  593. def _eval_expand_trig(self, **hints):
  594. arg = self.args[0]
  595. if arg.is_Add:
  596. n = len(arg.args)
  597. TX = [tanh(x, evaluate=False)._eval_expand_trig()
  598. for x in arg.args]
  599. p = [0, 0] # [den, num]
  600. for i in range(n + 1):
  601. p[i % 2] += symmetric_poly(i, TX)
  602. return p[1]/p[0]
  603. elif arg.is_Mul:
  604. coeff, terms = arg.as_coeff_Mul()
  605. if coeff.is_Integer and coeff > 1:
  606. T = tanh(terms)
  607. n = [nC(range(coeff), k)*T**k for k in range(1, coeff + 1, 2)]
  608. d = [nC(range(coeff), k)*T**k for k in range(0, coeff + 1, 2)]
  609. return Add(*n)/Add(*d)
  610. return tanh(arg)
  611. def _eval_rewrite_as_tractable(self, arg, limitvar=None, **kwargs):
  612. neg_exp, pos_exp = exp(-arg), exp(arg)
  613. return (pos_exp - neg_exp)/(pos_exp + neg_exp)
  614. def _eval_rewrite_as_exp(self, arg, **kwargs):
  615. neg_exp, pos_exp = exp(-arg), exp(arg)
  616. return (pos_exp - neg_exp)/(pos_exp + neg_exp)
  617. def _eval_rewrite_as_tan(self, arg, **kwargs):
  618. return -I * tan(I * arg, evaluate=False)
  619. def _eval_rewrite_as_cot(self, arg, **kwargs):
  620. return -I / cot(I * arg, evaluate=False)
  621. def _eval_rewrite_as_sinh(self, arg, **kwargs):
  622. return I*sinh(arg)/sinh(pi*I/2 - arg, evaluate=False)
  623. def _eval_rewrite_as_cosh(self, arg, **kwargs):
  624. return I*cosh(pi*I/2 - arg, evaluate=False)/cosh(arg)
  625. def _eval_rewrite_as_coth(self, arg, **kwargs):
  626. return 1/coth(arg)
  627. def _eval_as_leading_term(self, x, logx, cdir):
  628. from sympy.series.order import Order
  629. arg = self.args[0].as_leading_term(x)
  630. if x in arg.free_symbols and Order(1, x).contains(arg):
  631. return arg
  632. else:
  633. return self.func(arg)
  634. def _eval_is_real(self):
  635. arg = self.args[0]
  636. if arg.is_real:
  637. return True
  638. re, im = arg.as_real_imag()
  639. # if denom = 0, tanh(arg) = zoo
  640. if re == 0 and im % pi == pi/2:
  641. return None
  642. # check if im is of the form n*pi/2 to make sin(2*im) = 0
  643. # if not, im could be a number, return False in that case
  644. return (im % (pi/2)).is_zero
  645. def _eval_is_extended_real(self):
  646. if self.args[0].is_extended_real:
  647. return True
  648. def _eval_is_positive(self):
  649. if self.args[0].is_extended_real:
  650. return self.args[0].is_positive
  651. def _eval_is_negative(self):
  652. if self.args[0].is_extended_real:
  653. return self.args[0].is_negative
  654. def _eval_is_finite(self):
  655. arg = self.args[0]
  656. re, im = arg.as_real_imag()
  657. denom = cos(im)**2 + sinh(re)**2
  658. if denom == 0:
  659. return False
  660. elif denom.is_number:
  661. return True
  662. if arg.is_extended_real:
  663. return True
  664. def _eval_is_zero(self):
  665. arg = self.args[0]
  666. if arg.is_zero:
  667. return True
  668. class coth(HyperbolicFunction):
  669. r"""
  670. ``coth(x)`` is the hyperbolic cotangent of ``x``.
  671. The hyperbolic cotangent function is $\frac{\cosh(x)}{\sinh(x)}$.
  672. Examples
  673. ========
  674. >>> from sympy import coth
  675. >>> from sympy.abc import x
  676. >>> coth(x)
  677. coth(x)
  678. See Also
  679. ========
  680. sinh, cosh, acoth
  681. """
  682. def fdiff(self, argindex=1):
  683. if argindex == 1:
  684. return -1/sinh(self.args[0])**2
  685. else:
  686. raise ArgumentIndexError(self, argindex)
  687. def inverse(self, argindex=1):
  688. """
  689. Returns the inverse of this function.
  690. """
  691. return acoth
  692. @classmethod
  693. def eval(cls, arg):
  694. if arg.is_Number:
  695. if arg is S.NaN:
  696. return S.NaN
  697. elif arg is S.Infinity:
  698. return S.One
  699. elif arg is S.NegativeInfinity:
  700. return S.NegativeOne
  701. elif arg.is_zero:
  702. return S.ComplexInfinity
  703. elif arg.is_negative:
  704. return -cls(-arg)
  705. else:
  706. if arg is S.ComplexInfinity:
  707. return S.NaN
  708. i_coeff = _imaginary_unit_as_coefficient(arg)
  709. if i_coeff is not None:
  710. if i_coeff.could_extract_minus_sign():
  711. return I * cot(-i_coeff)
  712. return -I * cot(i_coeff)
  713. else:
  714. if arg.could_extract_minus_sign():
  715. return -cls(-arg)
  716. if arg.is_Add:
  717. x, m = _peeloff_ipi(arg)
  718. if m:
  719. cothm = coth(m*pi*I)
  720. if cothm is S.ComplexInfinity:
  721. return coth(x)
  722. else: # cothm == 0
  723. return tanh(x)
  724. if arg.is_zero:
  725. return S.ComplexInfinity
  726. if arg.func == asinh:
  727. x = arg.args[0]
  728. return sqrt(1 + x**2)/x
  729. if arg.func == acosh:
  730. x = arg.args[0]
  731. return x/(sqrt(x - 1) * sqrt(x + 1))
  732. if arg.func == atanh:
  733. return 1/arg.args[0]
  734. if arg.func == acoth:
  735. return arg.args[0]
  736. @staticmethod
  737. @cacheit
  738. def taylor_term(n, x, *previous_terms):
  739. if n == 0:
  740. return 1 / sympify(x)
  741. elif n < 0 or n % 2 == 0:
  742. return S.Zero
  743. else:
  744. x = sympify(x)
  745. B = bernoulli(n + 1)
  746. F = factorial(n + 1)
  747. return 2**(n + 1) * B/F * x**n
  748. def _eval_conjugate(self):
  749. return self.func(self.args[0].conjugate())
  750. def as_real_imag(self, deep=True, **hints):
  751. from sympy.functions.elementary.trigonometric import (cos, sin)
  752. if self.args[0].is_extended_real:
  753. if deep:
  754. hints['complex'] = False
  755. return (self.expand(deep, **hints), S.Zero)
  756. else:
  757. return (self, S.Zero)
  758. if deep:
  759. re, im = self.args[0].expand(deep, **hints).as_real_imag()
  760. else:
  761. re, im = self.args[0].as_real_imag()
  762. denom = sinh(re)**2 + sin(im)**2
  763. return (sinh(re)*cosh(re)/denom, -sin(im)*cos(im)/denom)
  764. def _eval_rewrite_as_tractable(self, arg, limitvar=None, **kwargs):
  765. neg_exp, pos_exp = exp(-arg), exp(arg)
  766. return (pos_exp + neg_exp)/(pos_exp - neg_exp)
  767. def _eval_rewrite_as_exp(self, arg, **kwargs):
  768. neg_exp, pos_exp = exp(-arg), exp(arg)
  769. return (pos_exp + neg_exp)/(pos_exp - neg_exp)
  770. def _eval_rewrite_as_sinh(self, arg, **kwargs):
  771. return -I*sinh(pi*I/2 - arg, evaluate=False)/sinh(arg)
  772. def _eval_rewrite_as_cosh(self, arg, **kwargs):
  773. return -I*cosh(arg)/cosh(pi*I/2 - arg, evaluate=False)
  774. def _eval_rewrite_as_tanh(self, arg, **kwargs):
  775. return 1/tanh(arg)
  776. def _eval_is_positive(self):
  777. if self.args[0].is_extended_real:
  778. return self.args[0].is_positive
  779. def _eval_is_negative(self):
  780. if self.args[0].is_extended_real:
  781. return self.args[0].is_negative
  782. def _eval_as_leading_term(self, x, logx, cdir):
  783. from sympy.series.order import Order
  784. arg = self.args[0].as_leading_term(x)
  785. if x in arg.free_symbols and Order(1, x).contains(arg):
  786. return 1/arg
  787. else:
  788. return self.func(arg)
  789. def _eval_expand_trig(self, **hints):
  790. arg = self.args[0]
  791. if arg.is_Add:
  792. CX = [coth(x, evaluate=False)._eval_expand_trig() for x in arg.args]
  793. p = [[], []]
  794. n = len(arg.args)
  795. for i in range(n, -1, -1):
  796. p[(n - i) % 2].append(symmetric_poly(i, CX))
  797. return Add(*p[0])/Add(*p[1])
  798. elif arg.is_Mul:
  799. coeff, x = arg.as_coeff_Mul(rational=True)
  800. if coeff.is_Integer and coeff > 1:
  801. c = coth(x, evaluate=False)
  802. p = [[], []]
  803. for i in range(coeff, -1, -1):
  804. p[(coeff - i) % 2].append(binomial(coeff, i)*c**i)
  805. return Add(*p[0])/Add(*p[1])
  806. return coth(arg)
  807. class ReciprocalHyperbolicFunction(HyperbolicFunction):
  808. """Base class for reciprocal functions of hyperbolic functions. """
  809. #To be defined in class
  810. _reciprocal_of = None
  811. _is_even: FuzzyBool = None
  812. _is_odd: FuzzyBool = None
  813. @classmethod
  814. def eval(cls, arg):
  815. if arg.could_extract_minus_sign():
  816. if cls._is_even:
  817. return cls(-arg)
  818. if cls._is_odd:
  819. return -cls(-arg)
  820. t = cls._reciprocal_of.eval(arg)
  821. if hasattr(arg, 'inverse') and arg.inverse() == cls:
  822. return arg.args[0]
  823. return 1/t if t is not None else t
  824. def _call_reciprocal(self, method_name, *args, **kwargs):
  825. # Calls method_name on _reciprocal_of
  826. o = self._reciprocal_of(self.args[0])
  827. return getattr(o, method_name)(*args, **kwargs)
  828. def _calculate_reciprocal(self, method_name, *args, **kwargs):
  829. # If calling method_name on _reciprocal_of returns a value != None
  830. # then return the reciprocal of that value
  831. t = self._call_reciprocal(method_name, *args, **kwargs)
  832. return 1/t if t is not None else t
  833. def _rewrite_reciprocal(self, method_name, arg):
  834. # Special handling for rewrite functions. If reciprocal rewrite returns
  835. # unmodified expression, then return None
  836. t = self._call_reciprocal(method_name, arg)
  837. if t is not None and t != self._reciprocal_of(arg):
  838. return 1/t
  839. def _eval_rewrite_as_exp(self, arg, **kwargs):
  840. return self._rewrite_reciprocal("_eval_rewrite_as_exp", arg)
  841. def _eval_rewrite_as_tractable(self, arg, limitvar=None, **kwargs):
  842. return self._rewrite_reciprocal("_eval_rewrite_as_tractable", arg)
  843. def _eval_rewrite_as_tanh(self, arg, **kwargs):
  844. return self._rewrite_reciprocal("_eval_rewrite_as_tanh", arg)
  845. def _eval_rewrite_as_coth(self, arg, **kwargs):
  846. return self._rewrite_reciprocal("_eval_rewrite_as_coth", arg)
  847. def as_real_imag(self, deep = True, **hints):
  848. return (1 / self._reciprocal_of(self.args[0])).as_real_imag(deep, **hints)
  849. def _eval_conjugate(self):
  850. return self.func(self.args[0].conjugate())
  851. def _eval_expand_complex(self, deep=True, **hints):
  852. re_part, im_part = self.as_real_imag(deep=True, **hints)
  853. return re_part + I*im_part
  854. def _eval_expand_trig(self, **hints):
  855. return self._calculate_reciprocal("_eval_expand_trig", **hints)
  856. def _eval_as_leading_term(self, x, logx, cdir):
  857. return (1/self._reciprocal_of(self.args[0]))._eval_as_leading_term(x, logx=logx, cdir=cdir)
  858. def _eval_is_extended_real(self):
  859. return self._reciprocal_of(self.args[0]).is_extended_real
  860. def _eval_is_finite(self):
  861. return (1/self._reciprocal_of(self.args[0])).is_finite
  862. class csch(ReciprocalHyperbolicFunction):
  863. r"""
  864. ``csch(x)`` is the hyperbolic cosecant of ``x``.
  865. The hyperbolic cosecant function is $\frac{2}{e^x - e^{-x}}$
  866. Examples
  867. ========
  868. >>> from sympy import csch
  869. >>> from sympy.abc import x
  870. >>> csch(x)
  871. csch(x)
  872. See Also
  873. ========
  874. sinh, cosh, tanh, sech, asinh, acosh
  875. """
  876. _reciprocal_of = sinh
  877. _is_odd = True
  878. def fdiff(self, argindex=1):
  879. """
  880. Returns the first derivative of this function
  881. """
  882. if argindex == 1:
  883. return -coth(self.args[0]) * csch(self.args[0])
  884. else:
  885. raise ArgumentIndexError(self, argindex)
  886. @staticmethod
  887. @cacheit
  888. def taylor_term(n, x, *previous_terms):
  889. """
  890. Returns the next term in the Taylor series expansion
  891. """
  892. if n == 0:
  893. return 1/sympify(x)
  894. elif n < 0 or n % 2 == 0:
  895. return S.Zero
  896. else:
  897. x = sympify(x)
  898. B = bernoulli(n + 1)
  899. F = factorial(n + 1)
  900. return 2 * (1 - 2**n) * B/F * x**n
  901. def _eval_rewrite_as_sin(self, arg, **kwargs):
  902. return I / sin(I * arg, evaluate=False)
  903. def _eval_rewrite_as_csc(self, arg, **kwargs):
  904. return I * csc(I * arg, evaluate=False)
  905. def _eval_rewrite_as_cosh(self, arg, **kwargs):
  906. return I / cosh(arg + I * pi / 2, evaluate=False)
  907. def _eval_rewrite_as_sinh(self, arg, **kwargs):
  908. return 1 / sinh(arg)
  909. def _eval_is_positive(self):
  910. if self.args[0].is_extended_real:
  911. return self.args[0].is_positive
  912. def _eval_is_negative(self):
  913. if self.args[0].is_extended_real:
  914. return self.args[0].is_negative
  915. class sech(ReciprocalHyperbolicFunction):
  916. r"""
  917. ``sech(x)`` is the hyperbolic secant of ``x``.
  918. The hyperbolic secant function is $\frac{2}{e^x + e^{-x}}$
  919. Examples
  920. ========
  921. >>> from sympy import sech
  922. >>> from sympy.abc import x
  923. >>> sech(x)
  924. sech(x)
  925. See Also
  926. ========
  927. sinh, cosh, tanh, coth, csch, asinh, acosh
  928. """
  929. _reciprocal_of = cosh
  930. _is_even = True
  931. def fdiff(self, argindex=1):
  932. if argindex == 1:
  933. return - tanh(self.args[0])*sech(self.args[0])
  934. else:
  935. raise ArgumentIndexError(self, argindex)
  936. @staticmethod
  937. @cacheit
  938. def taylor_term(n, x, *previous_terms):
  939. if n < 0 or n % 2 == 1:
  940. return S.Zero
  941. else:
  942. x = sympify(x)
  943. return euler(n) / factorial(n) * x**(n)
  944. def _eval_rewrite_as_cos(self, arg, **kwargs):
  945. return 1 / cos(I * arg, evaluate=False)
  946. def _eval_rewrite_as_sec(self, arg, **kwargs):
  947. return sec(I * arg, evaluate=False)
  948. def _eval_rewrite_as_sinh(self, arg, **kwargs):
  949. return I / sinh(arg + I * pi /2, evaluate=False)
  950. def _eval_rewrite_as_cosh(self, arg, **kwargs):
  951. return 1 / cosh(arg)
  952. def _eval_is_positive(self):
  953. if self.args[0].is_extended_real:
  954. return True
  955. ###############################################################################
  956. ############################# HYPERBOLIC INVERSES #############################
  957. ###############################################################################
  958. class InverseHyperbolicFunction(DefinedFunction):
  959. """Base class for inverse hyperbolic functions."""
  960. pass
  961. class asinh(InverseHyperbolicFunction):
  962. """
  963. ``asinh(x)`` is the inverse hyperbolic sine of ``x``.
  964. The inverse hyperbolic sine function.
  965. Examples
  966. ========
  967. >>> from sympy import asinh
  968. >>> from sympy.abc import x
  969. >>> asinh(x).diff(x)
  970. 1/sqrt(x**2 + 1)
  971. >>> asinh(1)
  972. log(1 + sqrt(2))
  973. See Also
  974. ========
  975. acosh, atanh, sinh
  976. """
  977. def fdiff(self, argindex=1):
  978. if argindex == 1:
  979. return 1/sqrt(self.args[0]**2 + 1)
  980. else:
  981. raise ArgumentIndexError(self, argindex)
  982. @classmethod
  983. def eval(cls, arg):
  984. if arg.is_Number:
  985. if arg is S.NaN:
  986. return S.NaN
  987. elif arg is S.Infinity:
  988. return S.Infinity
  989. elif arg is S.NegativeInfinity:
  990. return S.NegativeInfinity
  991. elif arg.is_zero:
  992. return S.Zero
  993. elif arg is S.One:
  994. return log(sqrt(2) + 1)
  995. elif arg is S.NegativeOne:
  996. return log(sqrt(2) - 1)
  997. elif arg.is_negative:
  998. return -cls(-arg)
  999. else:
  1000. if arg is S.ComplexInfinity:
  1001. return S.ComplexInfinity
  1002. if arg.is_zero:
  1003. return S.Zero
  1004. i_coeff = _imaginary_unit_as_coefficient(arg)
  1005. if i_coeff is not None:
  1006. return I * asin(i_coeff)
  1007. else:
  1008. if arg.could_extract_minus_sign():
  1009. return -cls(-arg)
  1010. if isinstance(arg, sinh) and arg.args[0].is_number:
  1011. z = arg.args[0]
  1012. if z.is_real:
  1013. return z
  1014. r, i = match_real_imag(z)
  1015. if r is not None and i is not None:
  1016. f = floor((i + pi/2)/pi)
  1017. m = z - I*pi*f
  1018. even = f.is_even
  1019. if even is True:
  1020. return m
  1021. elif even is False:
  1022. return -m
  1023. @staticmethod
  1024. @cacheit
  1025. def taylor_term(n, x, *previous_terms):
  1026. if n < 0 or n % 2 == 0:
  1027. return S.Zero
  1028. else:
  1029. x = sympify(x)
  1030. if len(previous_terms) >= 2 and n > 2:
  1031. p = previous_terms[-2]
  1032. return -p * (n - 2)**2/(n*(n - 1)) * x**2
  1033. else:
  1034. k = (n - 1) // 2
  1035. R = RisingFactorial(S.Half, k)
  1036. F = factorial(k)
  1037. return S.NegativeOne**k * R / F * x**n / n
  1038. def _eval_as_leading_term(self, x, logx, cdir):
  1039. arg = self.args[0]
  1040. x0 = arg.subs(x, 0).cancel()
  1041. if x0.is_zero:
  1042. return arg.as_leading_term(x)
  1043. if x0 is S.NaN:
  1044. expr = self.func(arg.as_leading_term(x))
  1045. if expr.is_finite:
  1046. return expr
  1047. else:
  1048. return self
  1049. # Handling branch points
  1050. if x0 in (-I, I, S.ComplexInfinity):
  1051. return self.rewrite(log)._eval_as_leading_term(x, logx=logx, cdir=cdir)
  1052. # Handling points lying on branch cuts (-I*oo, -I) U (I, I*oo)
  1053. if (1 + x0**2).is_negative:
  1054. ndir = arg.dir(x, cdir if cdir else 1)
  1055. if re(ndir).is_positive:
  1056. if im(x0).is_negative:
  1057. return -self.func(x0) - I*pi
  1058. elif re(ndir).is_negative:
  1059. if im(x0).is_positive:
  1060. return -self.func(x0) + I*pi
  1061. else:
  1062. return self.rewrite(log)._eval_as_leading_term(x, logx=logx, cdir=cdir)
  1063. return self.func(x0)
  1064. def _eval_nseries(self, x, n, logx, cdir=0): # asinh
  1065. arg = self.args[0]
  1066. arg0 = arg.subs(x, 0)
  1067. # Handling branch points
  1068. if arg0 in (I, -I):
  1069. return self.rewrite(log)._eval_nseries(x, n, logx=logx, cdir=cdir)
  1070. res = super()._eval_nseries(x, n=n, logx=logx)
  1071. if arg0 is S.ComplexInfinity:
  1072. return res
  1073. # Handling points lying on branch cuts (-I*oo, -I) U (I, I*oo)
  1074. if (1 + arg0**2).is_negative:
  1075. ndir = arg.dir(x, cdir if cdir else 1)
  1076. if re(ndir).is_positive:
  1077. if im(arg0).is_negative:
  1078. return -res - I*pi
  1079. elif re(ndir).is_negative:
  1080. if im(arg0).is_positive:
  1081. return -res + I*pi
  1082. else:
  1083. return self.rewrite(log)._eval_nseries(x, n, logx=logx, cdir=cdir)
  1084. return res
  1085. def _eval_rewrite_as_log(self, x, **kwargs):
  1086. return log(x + sqrt(x**2 + 1))
  1087. _eval_rewrite_as_tractable = _eval_rewrite_as_log
  1088. def _eval_rewrite_as_atanh(self, x, **kwargs):
  1089. return atanh(x/sqrt(1 + x**2))
  1090. def _eval_rewrite_as_acosh(self, x, **kwargs):
  1091. ix = I*x
  1092. return I*(sqrt(1 - ix)/sqrt(ix - 1) * acosh(ix) - pi/2)
  1093. def _eval_rewrite_as_asin(self, x, **kwargs):
  1094. return -I * asin(I * x, evaluate=False)
  1095. def _eval_rewrite_as_acos(self, x, **kwargs):
  1096. return I * acos(I * x, evaluate=False) - I*pi/2
  1097. def inverse(self, argindex=1):
  1098. """
  1099. Returns the inverse of this function.
  1100. """
  1101. return sinh
  1102. def _eval_is_zero(self):
  1103. return self.args[0].is_zero
  1104. def _eval_is_extended_real(self):
  1105. return self.args[0].is_extended_real
  1106. def _eval_is_finite(self):
  1107. return self.args[0].is_finite
  1108. class acosh(InverseHyperbolicFunction):
  1109. """
  1110. ``acosh(x)`` is the inverse hyperbolic cosine of ``x``.
  1111. The inverse hyperbolic cosine function.
  1112. Examples
  1113. ========
  1114. >>> from sympy import acosh
  1115. >>> from sympy.abc import x
  1116. >>> acosh(x).diff(x)
  1117. 1/(sqrt(x - 1)*sqrt(x + 1))
  1118. >>> acosh(1)
  1119. 0
  1120. See Also
  1121. ========
  1122. asinh, atanh, cosh
  1123. """
  1124. def fdiff(self, argindex=1):
  1125. if argindex == 1:
  1126. arg = self.args[0]
  1127. return 1/(sqrt(arg - 1)*sqrt(arg + 1))
  1128. else:
  1129. raise ArgumentIndexError(self, argindex)
  1130. @classmethod
  1131. def eval(cls, arg):
  1132. if arg.is_Number:
  1133. if arg is S.NaN:
  1134. return S.NaN
  1135. elif arg is S.Infinity:
  1136. return S.Infinity
  1137. elif arg is S.NegativeInfinity:
  1138. return S.Infinity
  1139. elif arg.is_zero:
  1140. return pi*I / 2
  1141. elif arg is S.One:
  1142. return S.Zero
  1143. elif arg is S.NegativeOne:
  1144. return pi*I
  1145. if arg.is_number:
  1146. cst_table = _acosh_table()
  1147. if arg in cst_table:
  1148. if arg.is_extended_real:
  1149. return cst_table[arg]*I
  1150. return cst_table[arg]
  1151. if arg is S.ComplexInfinity:
  1152. return S.ComplexInfinity
  1153. if arg == I*S.Infinity:
  1154. return S.Infinity + I*pi/2
  1155. if arg == -I*S.Infinity:
  1156. return S.Infinity - I*pi/2
  1157. if arg.is_zero:
  1158. return pi*I*S.Half
  1159. if isinstance(arg, cosh) and arg.args[0].is_number:
  1160. z = arg.args[0]
  1161. if z.is_real:
  1162. return Abs(z)
  1163. r, i = match_real_imag(z)
  1164. if r is not None and i is not None:
  1165. f = floor(i/pi)
  1166. m = z - I*pi*f
  1167. even = f.is_even
  1168. if even is True:
  1169. if r.is_nonnegative:
  1170. return m
  1171. elif r.is_negative:
  1172. return -m
  1173. elif even is False:
  1174. m -= I*pi
  1175. if r.is_nonpositive:
  1176. return -m
  1177. elif r.is_positive:
  1178. return m
  1179. @staticmethod
  1180. @cacheit
  1181. def taylor_term(n, x, *previous_terms):
  1182. if n == 0:
  1183. return I*pi/2
  1184. elif n < 0 or n % 2 == 0:
  1185. return S.Zero
  1186. else:
  1187. x = sympify(x)
  1188. if len(previous_terms) >= 2 and n > 2:
  1189. p = previous_terms[-2]
  1190. return p * (n - 2)**2/(n*(n - 1)) * x**2
  1191. else:
  1192. k = (n - 1) // 2
  1193. R = RisingFactorial(S.Half, k)
  1194. F = factorial(k)
  1195. return -R / F * I * x**n / n
  1196. def _eval_as_leading_term(self, x, logx, cdir):
  1197. arg = self.args[0]
  1198. x0 = arg.subs(x, 0).cancel()
  1199. # Handling branch points
  1200. if x0 in (-S.One, S.Zero, S.One, S.ComplexInfinity):
  1201. return self.rewrite(log)._eval_as_leading_term(x, logx=logx, cdir=cdir)
  1202. if x0 is S.NaN:
  1203. expr = self.func(arg.as_leading_term(x))
  1204. if expr.is_finite:
  1205. return expr
  1206. else:
  1207. return self
  1208. # Handling points lying on branch cuts (-oo, 1)
  1209. if (x0 - 1).is_negative:
  1210. ndir = arg.dir(x, cdir if cdir else 1)
  1211. if im(ndir).is_negative:
  1212. if (x0 + 1).is_negative:
  1213. return self.func(x0) - 2*I*pi
  1214. return -self.func(x0)
  1215. elif not im(ndir).is_positive:
  1216. return self.rewrite(log)._eval_as_leading_term(x, logx=logx, cdir=cdir)
  1217. return self.func(x0)
  1218. def _eval_nseries(self, x, n, logx, cdir=0): # acosh
  1219. arg = self.args[0]
  1220. arg0 = arg.subs(x, 0)
  1221. # Handling branch points
  1222. if arg0 in (S.One, S.NegativeOne):
  1223. return self.rewrite(log)._eval_nseries(x, n, logx=logx, cdir=cdir)
  1224. res = super()._eval_nseries(x, n=n, logx=logx)
  1225. if arg0 is S.ComplexInfinity:
  1226. return res
  1227. # Handling points lying on branch cuts (-oo, 1)
  1228. if (arg0 - 1).is_negative:
  1229. ndir = arg.dir(x, cdir if cdir else 1)
  1230. if im(ndir).is_negative:
  1231. if (arg0 + 1).is_negative:
  1232. return res - 2*I*pi
  1233. return -res
  1234. elif not im(ndir).is_positive:
  1235. return self.rewrite(log)._eval_nseries(x, n, logx=logx, cdir=cdir)
  1236. return res
  1237. def _eval_rewrite_as_log(self, x, **kwargs):
  1238. return log(x + sqrt(x + 1) * sqrt(x - 1))
  1239. _eval_rewrite_as_tractable = _eval_rewrite_as_log
  1240. def _eval_rewrite_as_acos(self, x, **kwargs):
  1241. return sqrt(x - 1)/sqrt(1 - x) * acos(x)
  1242. def _eval_rewrite_as_asin(self, x, **kwargs):
  1243. return sqrt(x - 1)/sqrt(1 - x) * (pi/2 - asin(x))
  1244. def _eval_rewrite_as_asinh(self, x, **kwargs):
  1245. return sqrt(x - 1)/sqrt(1 - x) * (pi/2 + I*asinh(I*x, evaluate=False))
  1246. def _eval_rewrite_as_atanh(self, x, **kwargs):
  1247. sxm1 = sqrt(x - 1)
  1248. s1mx = sqrt(1 - x)
  1249. sx2m1 = sqrt(x**2 - 1)
  1250. return (pi/2*sxm1/s1mx*(1 - x * sqrt(1/x**2)) +
  1251. sxm1*sqrt(x + 1)/sx2m1 * atanh(sx2m1/x))
  1252. def inverse(self, argindex=1):
  1253. """
  1254. Returns the inverse of this function.
  1255. """
  1256. return cosh
  1257. def _eval_is_zero(self):
  1258. if (self.args[0] - 1).is_zero:
  1259. return True
  1260. def _eval_is_extended_real(self):
  1261. return fuzzy_and([self.args[0].is_extended_real, (self.args[0] - 1).is_extended_nonnegative])
  1262. def _eval_is_finite(self):
  1263. return self.args[0].is_finite
  1264. class atanh(InverseHyperbolicFunction):
  1265. """
  1266. ``atanh(x)`` is the inverse hyperbolic tangent of ``x``.
  1267. The inverse hyperbolic tangent function.
  1268. Examples
  1269. ========
  1270. >>> from sympy import atanh
  1271. >>> from sympy.abc import x
  1272. >>> atanh(x).diff(x)
  1273. 1/(1 - x**2)
  1274. See Also
  1275. ========
  1276. asinh, acosh, tanh
  1277. """
  1278. def fdiff(self, argindex=1):
  1279. if argindex == 1:
  1280. return 1/(1 - self.args[0]**2)
  1281. else:
  1282. raise ArgumentIndexError(self, argindex)
  1283. @classmethod
  1284. def eval(cls, arg):
  1285. if arg.is_Number:
  1286. if arg is S.NaN:
  1287. return S.NaN
  1288. elif arg.is_zero:
  1289. return S.Zero
  1290. elif arg is S.One:
  1291. return S.Infinity
  1292. elif arg is S.NegativeOne:
  1293. return S.NegativeInfinity
  1294. elif arg is S.Infinity:
  1295. return -I * atan(arg)
  1296. elif arg is S.NegativeInfinity:
  1297. return I * atan(-arg)
  1298. elif arg.is_negative:
  1299. return -cls(-arg)
  1300. else:
  1301. if arg is S.ComplexInfinity:
  1302. from sympy.calculus.accumulationbounds import AccumBounds
  1303. return I*AccumBounds(-pi/2, pi/2)
  1304. i_coeff = _imaginary_unit_as_coefficient(arg)
  1305. if i_coeff is not None:
  1306. return I * atan(i_coeff)
  1307. else:
  1308. if arg.could_extract_minus_sign():
  1309. return -cls(-arg)
  1310. if arg.is_zero:
  1311. return S.Zero
  1312. if isinstance(arg, tanh) and arg.args[0].is_number:
  1313. z = arg.args[0]
  1314. if z.is_real:
  1315. return z
  1316. r, i = match_real_imag(z)
  1317. if r is not None and i is not None:
  1318. f = floor(2*i/pi)
  1319. even = f.is_even
  1320. m = z - I*f*pi/2
  1321. if even is True:
  1322. return m
  1323. elif even is False:
  1324. return m - I*pi/2
  1325. @staticmethod
  1326. @cacheit
  1327. def taylor_term(n, x, *previous_terms):
  1328. if n < 0 or n % 2 == 0:
  1329. return S.Zero
  1330. else:
  1331. x = sympify(x)
  1332. return x**n / n
  1333. def _eval_as_leading_term(self, x, logx, cdir):
  1334. arg = self.args[0]
  1335. x0 = arg.subs(x, 0).cancel()
  1336. if x0.is_zero:
  1337. return arg.as_leading_term(x)
  1338. if x0 is S.NaN:
  1339. expr = self.func(arg.as_leading_term(x))
  1340. if expr.is_finite:
  1341. return expr
  1342. else:
  1343. return self
  1344. # Handling branch points
  1345. if x0 in (-S.One, S.One, S.ComplexInfinity):
  1346. return self.rewrite(log)._eval_as_leading_term(x, logx=logx, cdir=cdir)
  1347. # Handling points lying on branch cuts (-oo, -1] U [1, oo)
  1348. if (1 - x0**2).is_negative:
  1349. ndir = arg.dir(x, cdir if cdir else 1)
  1350. if im(ndir).is_negative:
  1351. if x0.is_negative:
  1352. return self.func(x0) - I*pi
  1353. elif im(ndir).is_positive:
  1354. if x0.is_positive:
  1355. return self.func(x0) + I*pi
  1356. else:
  1357. return self.rewrite(log)._eval_as_leading_term(x, logx=logx, cdir=cdir)
  1358. return self.func(x0)
  1359. def _eval_nseries(self, x, n, logx, cdir=0): # atanh
  1360. arg = self.args[0]
  1361. arg0 = arg.subs(x, 0)
  1362. # Handling branch points
  1363. if arg0 in (S.One, S.NegativeOne):
  1364. return self.rewrite(log)._eval_nseries(x, n, logx=logx, cdir=cdir)
  1365. res = super()._eval_nseries(x, n=n, logx=logx)
  1366. if arg0 is S.ComplexInfinity:
  1367. return res
  1368. # Handling points lying on branch cuts (-oo, -1] U [1, oo)
  1369. if (1 - arg0**2).is_negative:
  1370. ndir = arg.dir(x, cdir if cdir else 1)
  1371. if im(ndir).is_negative:
  1372. if arg0.is_negative:
  1373. return res - I*pi
  1374. elif im(ndir).is_positive:
  1375. if arg0.is_positive:
  1376. return res + I*pi
  1377. else:
  1378. return self.rewrite(log)._eval_nseries(x, n, logx=logx, cdir=cdir)
  1379. return res
  1380. def _eval_rewrite_as_log(self, x, **kwargs):
  1381. return (log(1 + x) - log(1 - x)) / 2
  1382. _eval_rewrite_as_tractable = _eval_rewrite_as_log
  1383. def _eval_rewrite_as_asinh(self, x, **kwargs):
  1384. f = sqrt(1/(x**2 - 1))
  1385. return (pi*x/(2*sqrt(-x**2)) -
  1386. sqrt(-x)*sqrt(1 - x**2)/sqrt(x)*f*asinh(f))
  1387. def _eval_is_zero(self):
  1388. if self.args[0].is_zero:
  1389. return True
  1390. def _eval_is_extended_real(self):
  1391. return fuzzy_and([self.args[0].is_extended_real, (1 - self.args[0]).is_nonnegative, (self.args[0] + 1).is_nonnegative])
  1392. def _eval_is_finite(self):
  1393. return fuzzy_not(fuzzy_or([(self.args[0] - 1).is_zero, (self.args[0] + 1).is_zero]))
  1394. def _eval_is_imaginary(self):
  1395. return self.args[0].is_imaginary
  1396. def inverse(self, argindex=1):
  1397. """
  1398. Returns the inverse of this function.
  1399. """
  1400. return tanh
  1401. class acoth(InverseHyperbolicFunction):
  1402. """
  1403. ``acoth(x)`` is the inverse hyperbolic cotangent of ``x``.
  1404. The inverse hyperbolic cotangent function.
  1405. Examples
  1406. ========
  1407. >>> from sympy import acoth
  1408. >>> from sympy.abc import x
  1409. >>> acoth(x).diff(x)
  1410. 1/(1 - x**2)
  1411. See Also
  1412. ========
  1413. asinh, acosh, coth
  1414. """
  1415. def fdiff(self, argindex=1):
  1416. if argindex == 1:
  1417. return 1/(1 - self.args[0]**2)
  1418. else:
  1419. raise ArgumentIndexError(self, argindex)
  1420. @classmethod
  1421. def eval(cls, arg):
  1422. if arg.is_Number:
  1423. if arg is S.NaN:
  1424. return S.NaN
  1425. elif arg is S.Infinity:
  1426. return S.Zero
  1427. elif arg is S.NegativeInfinity:
  1428. return S.Zero
  1429. elif arg.is_zero:
  1430. return pi*I / 2
  1431. elif arg is S.One:
  1432. return S.Infinity
  1433. elif arg is S.NegativeOne:
  1434. return S.NegativeInfinity
  1435. elif arg.is_negative:
  1436. return -cls(-arg)
  1437. else:
  1438. if arg is S.ComplexInfinity:
  1439. return S.Zero
  1440. i_coeff = _imaginary_unit_as_coefficient(arg)
  1441. if i_coeff is not None:
  1442. return -I * acot(i_coeff)
  1443. else:
  1444. if arg.could_extract_minus_sign():
  1445. return -cls(-arg)
  1446. if arg.is_zero:
  1447. return pi*I*S.Half
  1448. @staticmethod
  1449. @cacheit
  1450. def taylor_term(n, x, *previous_terms):
  1451. if n == 0:
  1452. return -I*pi/2
  1453. elif n < 0 or n % 2 == 0:
  1454. return S.Zero
  1455. else:
  1456. x = sympify(x)
  1457. return x**n / n
  1458. def _eval_as_leading_term(self, x, logx, cdir):
  1459. arg = self.args[0]
  1460. x0 = arg.subs(x, 0).cancel()
  1461. if x0 is S.ComplexInfinity:
  1462. return (1/arg).as_leading_term(x)
  1463. if x0 is S.NaN:
  1464. expr = self.func(arg.as_leading_term(x))
  1465. if expr.is_finite:
  1466. return expr
  1467. else:
  1468. return self
  1469. # Handling branch points
  1470. if x0 in (-S.One, S.One, S.Zero):
  1471. return self.rewrite(log)._eval_as_leading_term(x, logx=logx, cdir=cdir)
  1472. # Handling points lying on branch cuts [-1, 1]
  1473. if x0.is_real and (1 - x0**2).is_positive:
  1474. ndir = arg.dir(x, cdir if cdir else 1)
  1475. if im(ndir).is_negative:
  1476. if x0.is_positive:
  1477. return self.func(x0) + I*pi
  1478. elif im(ndir).is_positive:
  1479. if x0.is_negative:
  1480. return self.func(x0) - I*pi
  1481. else:
  1482. return self.rewrite(log)._eval_as_leading_term(x, logx=logx, cdir=cdir)
  1483. return self.func(x0)
  1484. def _eval_nseries(self, x, n, logx, cdir=0): # acoth
  1485. arg = self.args[0]
  1486. arg0 = arg.subs(x, 0)
  1487. # Handling branch points
  1488. if arg0 in (S.One, S.NegativeOne):
  1489. return self.rewrite(log)._eval_nseries(x, n, logx=logx, cdir=cdir)
  1490. res = super()._eval_nseries(x, n=n, logx=logx)
  1491. if arg0 is S.ComplexInfinity:
  1492. return res
  1493. # Handling points lying on branch cuts [-1, 1]
  1494. if arg0.is_real and (1 - arg0**2).is_positive:
  1495. ndir = arg.dir(x, cdir if cdir else 1)
  1496. if im(ndir).is_negative:
  1497. if arg0.is_positive:
  1498. return res + I*pi
  1499. elif im(ndir).is_positive:
  1500. if arg0.is_negative:
  1501. return res - I*pi
  1502. else:
  1503. return self.rewrite(log)._eval_nseries(x, n, logx=logx, cdir=cdir)
  1504. return res
  1505. def _eval_rewrite_as_log(self, x, **kwargs):
  1506. return (log(1 + 1/x) - log(1 - 1/x)) / 2
  1507. _eval_rewrite_as_tractable = _eval_rewrite_as_log
  1508. def _eval_rewrite_as_atanh(self, x, **kwargs):
  1509. return atanh(1/x)
  1510. def _eval_rewrite_as_asinh(self, x, **kwargs):
  1511. return (pi*I/2*(sqrt((x - 1)/x)*sqrt(x/(x - 1)) - sqrt(1 + 1/x)*sqrt(x/(x + 1))) +
  1512. x*sqrt(1/x**2)*asinh(sqrt(1/(x**2 - 1))))
  1513. def inverse(self, argindex=1):
  1514. """
  1515. Returns the inverse of this function.
  1516. """
  1517. return coth
  1518. def _eval_is_extended_real(self):
  1519. return fuzzy_and([self.args[0].is_extended_real, fuzzy_or([(self.args[0] - 1).is_extended_nonnegative, (self.args[0] + 1).is_extended_nonpositive])])
  1520. def _eval_is_finite(self):
  1521. return fuzzy_not(fuzzy_or([(self.args[0] - 1).is_zero, (self.args[0] + 1).is_zero]))
  1522. class asech(InverseHyperbolicFunction):
  1523. """
  1524. ``asech(x)`` is the inverse hyperbolic secant of ``x``.
  1525. The inverse hyperbolic secant function.
  1526. Examples
  1527. ========
  1528. >>> from sympy import asech, sqrt, S
  1529. >>> from sympy.abc import x
  1530. >>> asech(x).diff(x)
  1531. -1/(x*sqrt(1 - x**2))
  1532. >>> asech(1).diff(x)
  1533. 0
  1534. >>> asech(1)
  1535. 0
  1536. >>> asech(S(2))
  1537. I*pi/3
  1538. >>> asech(-sqrt(2))
  1539. 3*I*pi/4
  1540. >>> asech((sqrt(6) - sqrt(2)))
  1541. I*pi/12
  1542. See Also
  1543. ========
  1544. asinh, atanh, cosh, acoth
  1545. References
  1546. ==========
  1547. .. [1] https://en.wikipedia.org/wiki/Hyperbolic_function
  1548. .. [2] https://dlmf.nist.gov/4.37
  1549. .. [3] https://functions.wolfram.com/ElementaryFunctions/ArcSech/
  1550. """
  1551. def fdiff(self, argindex=1):
  1552. if argindex == 1:
  1553. z = self.args[0]
  1554. return -1/(z*sqrt(1 - z**2))
  1555. else:
  1556. raise ArgumentIndexError(self, argindex)
  1557. @classmethod
  1558. def eval(cls, arg):
  1559. if arg.is_Number:
  1560. if arg is S.NaN:
  1561. return S.NaN
  1562. elif arg is S.Infinity:
  1563. return pi*I / 2
  1564. elif arg is S.NegativeInfinity:
  1565. return pi*I / 2
  1566. elif arg.is_zero:
  1567. return S.Infinity
  1568. elif arg is S.One:
  1569. return S.Zero
  1570. elif arg is S.NegativeOne:
  1571. return pi*I
  1572. if arg.is_number:
  1573. cst_table = _asech_table()
  1574. if arg in cst_table:
  1575. if arg.is_extended_real:
  1576. return cst_table[arg]*I
  1577. return cst_table[arg]
  1578. if arg is S.ComplexInfinity:
  1579. from sympy.calculus.accumulationbounds import AccumBounds
  1580. return I*AccumBounds(-pi/2, pi/2)
  1581. if arg.is_zero:
  1582. return S.Infinity
  1583. @staticmethod
  1584. @cacheit
  1585. def taylor_term(n, x, *previous_terms):
  1586. if n == 0:
  1587. return log(2 / x)
  1588. elif n < 0 or n % 2 == 1:
  1589. return S.Zero
  1590. else:
  1591. x = sympify(x)
  1592. if len(previous_terms) > 2 and n > 2:
  1593. p = previous_terms[-2]
  1594. return p * ((n - 1)*(n-2)) * x**2/(4 * (n//2)**2)
  1595. else:
  1596. k = n // 2
  1597. R = RisingFactorial(S.Half, k) * n
  1598. F = factorial(k) * n // 2 * n // 2
  1599. return -1 * R / F * x**n / 4
  1600. def _eval_as_leading_term(self, x, logx, cdir):
  1601. arg = self.args[0]
  1602. x0 = arg.subs(x, 0).cancel()
  1603. # Handling branch points
  1604. if x0 in (-S.One, S.Zero, S.One, S.ComplexInfinity):
  1605. return self.rewrite(log)._eval_as_leading_term(x, logx=logx, cdir=cdir)
  1606. if x0 is S.NaN:
  1607. expr = self.func(arg.as_leading_term(x))
  1608. if expr.is_finite:
  1609. return expr
  1610. else:
  1611. return self
  1612. # Handling points lying on branch cuts (-oo, 0] U (1, oo)
  1613. if x0.is_negative or (1 - x0).is_negative:
  1614. ndir = arg.dir(x, cdir if cdir else 1)
  1615. if im(ndir).is_positive:
  1616. if x0.is_positive or (x0 + 1).is_negative:
  1617. return -self.func(x0)
  1618. return self.func(x0) - 2*I*pi
  1619. elif not im(ndir).is_negative:
  1620. return self.rewrite(log)._eval_as_leading_term(x, logx=logx, cdir=cdir)
  1621. return self.func(x0)
  1622. def _eval_nseries(self, x, n, logx, cdir=0): # asech
  1623. from sympy.series.order import O
  1624. arg = self.args[0]
  1625. arg0 = arg.subs(x, 0)
  1626. # Handling branch points
  1627. if arg0 is S.One:
  1628. t = Dummy('t', positive=True)
  1629. ser = asech(S.One - t**2).rewrite(log).nseries(t, 0, 2*n)
  1630. arg1 = S.One - self.args[0]
  1631. f = arg1.as_leading_term(x)
  1632. g = (arg1 - f)/ f
  1633. if not g.is_meromorphic(x, 0): # cannot be expanded
  1634. return O(1) if n == 0 else O(sqrt(x))
  1635. res1 = sqrt(S.One + g)._eval_nseries(x, n=n, logx=logx)
  1636. res = (res1.removeO()*sqrt(f)).expand()
  1637. return ser.removeO().subs(t, res).expand().powsimp() + O(x**n, x)
  1638. if arg0 is S.NegativeOne:
  1639. t = Dummy('t', positive=True)
  1640. ser = asech(S.NegativeOne + t**2).rewrite(log).nseries(t, 0, 2*n)
  1641. arg1 = S.One + self.args[0]
  1642. f = arg1.as_leading_term(x)
  1643. g = (arg1 - f)/ f
  1644. if not g.is_meromorphic(x, 0): # cannot be expanded
  1645. return O(1) if n == 0 else I*pi + O(sqrt(x))
  1646. res1 = sqrt(S.One + g)._eval_nseries(x, n=n, logx=logx)
  1647. res = (res1.removeO()*sqrt(f)).expand()
  1648. return ser.removeO().subs(t, res).expand().powsimp() + O(x**n, x)
  1649. res = super()._eval_nseries(x, n=n, logx=logx)
  1650. if arg0 is S.ComplexInfinity:
  1651. return res
  1652. # Handling points lying on branch cuts (-oo, 0] U (1, oo)
  1653. if arg0.is_negative or (1 - arg0).is_negative:
  1654. ndir = arg.dir(x, cdir if cdir else 1)
  1655. if im(ndir).is_positive:
  1656. if arg0.is_positive or (arg0 + 1).is_negative:
  1657. return -res
  1658. return res - 2*I*pi
  1659. elif not im(ndir).is_negative:
  1660. return self.rewrite(log)._eval_nseries(x, n, logx=logx, cdir=cdir)
  1661. return res
  1662. def inverse(self, argindex=1):
  1663. """
  1664. Returns the inverse of this function.
  1665. """
  1666. return sech
  1667. def _eval_rewrite_as_log(self, arg, **kwargs):
  1668. return log(1/arg + sqrt(1/arg - 1) * sqrt(1/arg + 1))
  1669. _eval_rewrite_as_tractable = _eval_rewrite_as_log
  1670. def _eval_rewrite_as_acosh(self, arg, **kwargs):
  1671. return acosh(1/arg)
  1672. def _eval_rewrite_as_asinh(self, arg, **kwargs):
  1673. return sqrt(1/arg - 1)/sqrt(1 - 1/arg)*(I*asinh(I/arg, evaluate=False)
  1674. + pi*S.Half)
  1675. def _eval_rewrite_as_atanh(self, x, **kwargs):
  1676. return (I*pi*(1 - sqrt(x)*sqrt(1/x) - I/2*sqrt(-x)/sqrt(x) - I/2*sqrt(x**2)/sqrt(-x**2))
  1677. + sqrt(1/(x + 1))*sqrt(x + 1)*atanh(sqrt(1 - x**2)))
  1678. def _eval_rewrite_as_acsch(self, x, **kwargs):
  1679. return sqrt(1/x - 1)/sqrt(1 - 1/x)*(pi/2 - I*acsch(I*x, evaluate=False))
  1680. def _eval_is_extended_real(self):
  1681. return fuzzy_and([self.args[0].is_extended_real, self.args[0].is_nonnegative, (1 - self.args[0]).is_nonnegative])
  1682. def _eval_is_finite(self):
  1683. return fuzzy_not(self.args[0].is_zero)
  1684. class acsch(InverseHyperbolicFunction):
  1685. """
  1686. ``acsch(x)`` is the inverse hyperbolic cosecant of ``x``.
  1687. The inverse hyperbolic cosecant function.
  1688. Examples
  1689. ========
  1690. >>> from sympy import acsch, sqrt, I
  1691. >>> from sympy.abc import x
  1692. >>> acsch(x).diff(x)
  1693. -1/(x**2*sqrt(1 + x**(-2)))
  1694. >>> acsch(1).diff(x)
  1695. 0
  1696. >>> acsch(1)
  1697. log(1 + sqrt(2))
  1698. >>> acsch(I)
  1699. -I*pi/2
  1700. >>> acsch(-2*I)
  1701. I*pi/6
  1702. >>> acsch(I*(sqrt(6) - sqrt(2)))
  1703. -5*I*pi/12
  1704. See Also
  1705. ========
  1706. asinh
  1707. References
  1708. ==========
  1709. .. [1] https://en.wikipedia.org/wiki/Hyperbolic_function
  1710. .. [2] https://dlmf.nist.gov/4.37
  1711. .. [3] https://functions.wolfram.com/ElementaryFunctions/ArcCsch/
  1712. """
  1713. def fdiff(self, argindex=1):
  1714. if argindex == 1:
  1715. z = self.args[0]
  1716. return -1/(z**2*sqrt(1 + 1/z**2))
  1717. else:
  1718. raise ArgumentIndexError(self, argindex)
  1719. @classmethod
  1720. def eval(cls, arg):
  1721. if arg.is_Number:
  1722. if arg is S.NaN:
  1723. return S.NaN
  1724. elif arg is S.Infinity:
  1725. return S.Zero
  1726. elif arg is S.NegativeInfinity:
  1727. return S.Zero
  1728. elif arg.is_zero:
  1729. return S.ComplexInfinity
  1730. elif arg is S.One:
  1731. return log(1 + sqrt(2))
  1732. elif arg is S.NegativeOne:
  1733. return - log(1 + sqrt(2))
  1734. if arg.is_number:
  1735. cst_table = _acsch_table()
  1736. if arg in cst_table:
  1737. return cst_table[arg]*I
  1738. if arg is S.ComplexInfinity:
  1739. return S.Zero
  1740. if arg.is_infinite:
  1741. return S.Zero
  1742. if arg.is_zero:
  1743. return S.ComplexInfinity
  1744. if arg.could_extract_minus_sign():
  1745. return -cls(-arg)
  1746. @staticmethod
  1747. @cacheit
  1748. def taylor_term(n, x, *previous_terms):
  1749. if n == 0:
  1750. return log(2 / x)
  1751. elif n < 0 or n % 2 == 1:
  1752. return S.Zero
  1753. else:
  1754. x = sympify(x)
  1755. if len(previous_terms) > 2 and n > 2:
  1756. p = previous_terms[-2]
  1757. return -p * ((n - 1)*(n-2)) * x**2/(4 * (n//2)**2)
  1758. else:
  1759. k = n // 2
  1760. R = RisingFactorial(S.Half, k) * n
  1761. F = factorial(k) * n // 2 * n // 2
  1762. return S.NegativeOne**(k +1) * R / F * x**n / 4
  1763. def _eval_as_leading_term(self, x, logx, cdir):
  1764. arg = self.args[0]
  1765. x0 = arg.subs(x, 0).cancel()
  1766. # Handling branch points
  1767. if x0 in (-I, I, S.Zero):
  1768. return self.rewrite(log)._eval_as_leading_term(x, logx=logx, cdir=cdir)
  1769. if x0 is S.NaN:
  1770. expr = self.func(arg.as_leading_term(x))
  1771. if expr.is_finite:
  1772. return expr
  1773. else:
  1774. return self
  1775. if x0 is S.ComplexInfinity:
  1776. return (1/arg).as_leading_term(x)
  1777. # Handling points lying on branch cuts (-I, I)
  1778. if x0.is_imaginary and (1 + x0**2).is_positive:
  1779. ndir = arg.dir(x, cdir if cdir else 1)
  1780. if re(ndir).is_positive:
  1781. if im(x0).is_positive:
  1782. return -self.func(x0) - I*pi
  1783. elif re(ndir).is_negative:
  1784. if im(x0).is_negative:
  1785. return -self.func(x0) + I*pi
  1786. else:
  1787. return self.rewrite(log)._eval_as_leading_term(x, logx=logx, cdir=cdir)
  1788. return self.func(x0)
  1789. def _eval_nseries(self, x, n, logx, cdir=0): # acsch
  1790. from sympy.series.order import O
  1791. arg = self.args[0]
  1792. arg0 = arg.subs(x, 0)
  1793. # Handling branch points
  1794. if arg0 is I:
  1795. t = Dummy('t', positive=True)
  1796. ser = acsch(I + t**2).rewrite(log).nseries(t, 0, 2*n)
  1797. arg1 = -I + self.args[0]
  1798. f = arg1.as_leading_term(x)
  1799. g = (arg1 - f)/ f
  1800. if not g.is_meromorphic(x, 0): # cannot be expanded
  1801. return O(1) if n == 0 else -I*pi/2 + O(sqrt(x))
  1802. res1 = sqrt(S.One + g)._eval_nseries(x, n=n, logx=logx)
  1803. res = (res1.removeO()*sqrt(f)).expand()
  1804. res = ser.removeO().subs(t, res).expand().powsimp() + O(x**n, x)
  1805. return res
  1806. if arg0 == S.NegativeOne*I:
  1807. t = Dummy('t', positive=True)
  1808. ser = acsch(-I + t**2).rewrite(log).nseries(t, 0, 2*n)
  1809. arg1 = I + self.args[0]
  1810. f = arg1.as_leading_term(x)
  1811. g = (arg1 - f)/ f
  1812. if not g.is_meromorphic(x, 0): # cannot be expanded
  1813. return O(1) if n == 0 else I*pi/2 + O(sqrt(x))
  1814. res1 = sqrt(S.One + g)._eval_nseries(x, n=n, logx=logx)
  1815. res = (res1.removeO()*sqrt(f)).expand()
  1816. return ser.removeO().subs(t, res).expand().powsimp() + O(x**n, x)
  1817. res = super()._eval_nseries(x, n=n, logx=logx)
  1818. if arg0 is S.ComplexInfinity:
  1819. return res
  1820. # Handling points lying on branch cuts (-I, I)
  1821. if arg0.is_imaginary and (1 + arg0**2).is_positive:
  1822. ndir = self.args[0].dir(x, cdir if cdir else 1)
  1823. if re(ndir).is_positive:
  1824. if im(arg0).is_positive:
  1825. return -res - I*pi
  1826. elif re(ndir).is_negative:
  1827. if im(arg0).is_negative:
  1828. return -res + I*pi
  1829. else:
  1830. return self.rewrite(log)._eval_nseries(x, n, logx=logx, cdir=cdir)
  1831. return res
  1832. def inverse(self, argindex=1):
  1833. """
  1834. Returns the inverse of this function.
  1835. """
  1836. return csch
  1837. def _eval_rewrite_as_log(self, arg, **kwargs):
  1838. return log(1/arg + sqrt(1/arg**2 + 1))
  1839. _eval_rewrite_as_tractable = _eval_rewrite_as_log
  1840. def _eval_rewrite_as_asinh(self, arg, **kwargs):
  1841. return asinh(1/arg)
  1842. def _eval_rewrite_as_acosh(self, arg, **kwargs):
  1843. return I*(sqrt(1 - I/arg)/sqrt(I/arg - 1)*
  1844. acosh(I/arg, evaluate=False) - pi*S.Half)
  1845. def _eval_rewrite_as_atanh(self, arg, **kwargs):
  1846. arg2 = arg**2
  1847. arg2p1 = arg2 + 1
  1848. return sqrt(-arg2)/arg*(pi*S.Half -
  1849. sqrt(-arg2p1**2)/arg2p1*atanh(sqrt(arg2p1)))
  1850. def _eval_is_zero(self):
  1851. return self.args[0].is_infinite
  1852. def _eval_is_extended_real(self):
  1853. return self.args[0].is_extended_real
  1854. def _eval_is_finite(self):
  1855. return fuzzy_not(self.args[0].is_zero)