trigonometric.py 113 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627
  1. from __future__ import annotations
  2. from sympy.core.add import Add
  3. from sympy.core.cache import cacheit
  4. from sympy.core.expr import Expr
  5. from sympy.core.function import DefinedFunction, ArgumentIndexError, PoleError, expand_mul
  6. from sympy.core.logic import fuzzy_not, fuzzy_or, FuzzyBool, fuzzy_and
  7. from sympy.core.mod import Mod
  8. from sympy.core.numbers import Rational, pi, Integer, Float, equal_valued
  9. from sympy.core.relational import Ne, Eq
  10. from sympy.core.singleton import S
  11. from sympy.core.symbol import Symbol, Dummy
  12. from sympy.core.sympify import sympify
  13. from sympy.functions.combinatorial.factorials import factorial, RisingFactorial
  14. from sympy.functions.combinatorial.numbers import bernoulli, euler
  15. from sympy.functions.elementary.complexes import arg as arg_f, im, re
  16. from sympy.functions.elementary.exponential import log, exp
  17. from sympy.functions.elementary.integers import floor
  18. from sympy.functions.elementary.miscellaneous import sqrt, Min, Max
  19. from sympy.functions.elementary.piecewise import Piecewise
  20. from sympy.functions.elementary._trigonometric_special import (
  21. cos_table, ipartfrac, fermat_coords)
  22. from sympy.logic.boolalg import And
  23. from sympy.ntheory import factorint
  24. from sympy.polys.specialpolys import symmetric_poly
  25. from sympy.utilities.iterables import numbered_symbols
  26. ###############################################################################
  27. ########################## UTILITIES ##########################################
  28. ###############################################################################
  29. def _imaginary_unit_as_coefficient(arg):
  30. """ Helper to extract symbolic coefficient for imaginary unit """
  31. if isinstance(arg, Float):
  32. return None
  33. else:
  34. return arg.as_coefficient(S.ImaginaryUnit)
  35. ###############################################################################
  36. ########################## TRIGONOMETRIC FUNCTIONS ############################
  37. ###############################################################################
  38. class TrigonometricFunction(DefinedFunction):
  39. """Base class for trigonometric functions. """
  40. unbranched = True
  41. _singularities = (S.ComplexInfinity,)
  42. def _eval_is_rational(self):
  43. s = self.func(*self.args)
  44. if s.func == self.func:
  45. if s.args[0].is_rational and fuzzy_not(s.args[0].is_zero):
  46. return False
  47. else:
  48. return s.is_rational
  49. def _eval_is_algebraic(self):
  50. s = self.func(*self.args)
  51. if s.func == self.func:
  52. if fuzzy_not(self.args[0].is_zero) and self.args[0].is_algebraic:
  53. return False
  54. pi_coeff = _pi_coeff(self.args[0])
  55. if pi_coeff is not None and pi_coeff.is_rational:
  56. return True
  57. else:
  58. return s.is_algebraic
  59. def _eval_expand_complex(self, deep=True, **hints):
  60. re_part, im_part = self.as_real_imag(deep=deep, **hints)
  61. return re_part + im_part*S.ImaginaryUnit
  62. def _as_real_imag(self, deep=True, **hints):
  63. if self.args[0].is_extended_real:
  64. if deep:
  65. hints['complex'] = False
  66. return (self.args[0].expand(deep, **hints), S.Zero)
  67. else:
  68. return (self.args[0], S.Zero)
  69. if deep:
  70. re, im = self.args[0].expand(deep, **hints).as_real_imag()
  71. else:
  72. re, im = self.args[0].as_real_imag()
  73. return (re, im)
  74. def _period(self, general_period, symbol=None):
  75. f = expand_mul(self.args[0])
  76. if symbol is None:
  77. symbol = tuple(f.free_symbols)[0]
  78. if not f.has(symbol):
  79. return S.Zero
  80. if f == symbol:
  81. return general_period
  82. if symbol in f.free_symbols:
  83. if f.is_Mul:
  84. g, h = f.as_independent(symbol)
  85. if h == symbol:
  86. return general_period/abs(g)
  87. if f.is_Add:
  88. a, h = f.as_independent(symbol)
  89. g, h = h.as_independent(symbol, as_Add=False)
  90. if h == symbol:
  91. return general_period/abs(g)
  92. raise NotImplementedError("Use the periodicity function instead.")
  93. @cacheit
  94. def _table2():
  95. # If nested sqrt's are worse than un-evaluation
  96. # you can require q to be in (1, 2, 3, 4, 6, 12)
  97. # q <= 12, q=15, q=20, q=24, q=30, q=40, q=60, q=120 return
  98. # expressions with 2 or fewer sqrt nestings.
  99. return {
  100. 12: (3, 4),
  101. 20: (4, 5),
  102. 30: (5, 6),
  103. 15: (6, 10),
  104. 24: (6, 8),
  105. 40: (8, 10),
  106. 60: (20, 30),
  107. 120: (40, 60)
  108. }
  109. def _peeloff_pi(arg):
  110. r"""
  111. Split ARG into two parts, a "rest" and a multiple of $\pi$.
  112. This assumes ARG to be an Add.
  113. The multiple of $\pi$ returned in the second position is always a Rational.
  114. Examples
  115. ========
  116. >>> from sympy.functions.elementary.trigonometric import _peeloff_pi
  117. >>> from sympy import pi
  118. >>> from sympy.abc import x, y
  119. >>> _peeloff_pi(x + pi/2)
  120. (x, 1/2)
  121. >>> _peeloff_pi(x + 2*pi/3 + pi*y)
  122. (x + pi*y + pi/6, 1/2)
  123. """
  124. pi_coeff = S.Zero
  125. rest_terms = []
  126. for a in Add.make_args(arg):
  127. K = a.coeff(pi)
  128. if K and K.is_rational:
  129. pi_coeff += K
  130. else:
  131. rest_terms.append(a)
  132. if pi_coeff is S.Zero:
  133. return arg, S.Zero
  134. m1 = (pi_coeff % S.Half)
  135. m2 = pi_coeff - m1
  136. if m2.is_integer or ((2*m2).is_integer and m2.is_even is False):
  137. return Add(*(rest_terms + [m1*pi])), m2
  138. return arg, S.Zero
  139. def _pi_coeff(arg: Expr, cycles: int = 1) -> Expr | None:
  140. r"""
  141. When arg is a Number times $\pi$ (e.g. $3\pi/2$) then return the Number
  142. normalized to be in the range $[0, 2]$, else `None`.
  143. When an even multiple of $\pi$ is encountered, if it is multiplying
  144. something with known parity then the multiple is returned as 0 otherwise
  145. as 2.
  146. Examples
  147. ========
  148. >>> from sympy.functions.elementary.trigonometric import _pi_coeff
  149. >>> from sympy import pi, Dummy
  150. >>> from sympy.abc import x
  151. >>> _pi_coeff(3*x*pi)
  152. 3*x
  153. >>> _pi_coeff(11*pi/7)
  154. 11/7
  155. >>> _pi_coeff(-11*pi/7)
  156. 3/7
  157. >>> _pi_coeff(4*pi)
  158. 0
  159. >>> _pi_coeff(5*pi)
  160. 1
  161. >>> _pi_coeff(5.0*pi)
  162. 1
  163. >>> _pi_coeff(5.5*pi)
  164. 3/2
  165. >>> _pi_coeff(2 + pi)
  166. >>> _pi_coeff(2*Dummy(integer=True)*pi)
  167. 2
  168. >>> _pi_coeff(2*Dummy(even=True)*pi)
  169. 0
  170. """
  171. if arg is pi:
  172. return S.One
  173. elif not arg:
  174. return S.Zero
  175. elif arg.is_Mul:
  176. cx = arg.coeff(pi)
  177. if cx:
  178. c, x = cx.as_coeff_Mul() # pi is not included as coeff
  179. if c.is_Float:
  180. # recast exact binary fractions to Rationals
  181. f = abs(c) % 1
  182. if f != 0:
  183. p = -int(round(log(f, 2).evalf()))
  184. m = 2**p
  185. cm = c*m
  186. i = int(cm)
  187. if equal_valued(i, cm):
  188. c = Rational(i, m)
  189. cx = c*x
  190. else:
  191. c = Rational(int(c))
  192. cx = c*x
  193. if x.is_integer:
  194. c2 = c % 2
  195. if c2 == 1:
  196. return x
  197. elif not c2:
  198. if x.is_even is not None: # known parity
  199. return S.Zero
  200. return Integer(2)
  201. else:
  202. return c2*x
  203. return cx
  204. elif arg.is_zero:
  205. return S.Zero
  206. return None
  207. class sin(TrigonometricFunction):
  208. r"""
  209. The sine function.
  210. Returns the sine of x (measured in radians).
  211. Explanation
  212. ===========
  213. This function will evaluate automatically in the
  214. case $x/\pi$ is some rational number [4]_. For example,
  215. if $x$ is a multiple of $\pi$, $\pi/2$, $\pi/3$, $\pi/4$, and $\pi/6$.
  216. Examples
  217. ========
  218. >>> from sympy import sin, pi
  219. >>> from sympy.abc import x
  220. >>> sin(x**2).diff(x)
  221. 2*x*cos(x**2)
  222. >>> sin(1).diff(x)
  223. 0
  224. >>> sin(pi)
  225. 0
  226. >>> sin(pi/2)
  227. 1
  228. >>> sin(pi/6)
  229. 1/2
  230. >>> sin(pi/12)
  231. -sqrt(2)/4 + sqrt(6)/4
  232. See Also
  233. ========
  234. csc, cos, sec, tan, cot
  235. asin, acsc, acos, asec, atan, acot, atan2
  236. References
  237. ==========
  238. .. [1] https://en.wikipedia.org/wiki/Trigonometric_functions
  239. .. [2] https://dlmf.nist.gov/4.14
  240. .. [3] https://functions.wolfram.com/ElementaryFunctions/Sin
  241. .. [4] https://mathworld.wolfram.com/TrigonometryAngles.html
  242. """
  243. def period(self, symbol=None):
  244. return self._period(2*pi, symbol)
  245. def fdiff(self, argindex=1):
  246. if argindex == 1:
  247. return cos(self.args[0])
  248. else:
  249. raise ArgumentIndexError(self, argindex)
  250. @classmethod
  251. def eval(cls, arg):
  252. from sympy.calculus.accumulationbounds import AccumBounds
  253. from sympy.sets.setexpr import SetExpr
  254. if arg.is_Number:
  255. if arg is S.NaN:
  256. return S.NaN
  257. elif arg.is_zero:
  258. return S.Zero
  259. elif arg in (S.Infinity, S.NegativeInfinity):
  260. return AccumBounds(-1, 1)
  261. if arg is S.ComplexInfinity:
  262. return S.NaN
  263. if isinstance(arg, AccumBounds):
  264. from sympy.sets.sets import FiniteSet
  265. min, max = arg.min, arg.max
  266. d = floor(min/(2*pi))
  267. if min is not S.NegativeInfinity:
  268. min = min - d*2*pi
  269. if max is not S.Infinity:
  270. max = max - d*2*pi
  271. if AccumBounds(min, max).intersection(FiniteSet(pi/2, pi*Rational(5, 2))) \
  272. is not S.EmptySet and \
  273. AccumBounds(min, max).intersection(FiniteSet(pi*Rational(3, 2),
  274. pi*Rational(7, 2))) is not S.EmptySet:
  275. return AccumBounds(-1, 1)
  276. elif AccumBounds(min, max).intersection(FiniteSet(pi/2, pi*Rational(5, 2))) \
  277. is not S.EmptySet:
  278. return AccumBounds(Min(sin(min), sin(max)), 1)
  279. elif AccumBounds(min, max).intersection(FiniteSet(pi*Rational(3, 2), pi*Rational(8, 2))) \
  280. is not S.EmptySet:
  281. return AccumBounds(-1, Max(sin(min), sin(max)))
  282. else:
  283. return AccumBounds(Min(sin(min), sin(max)),
  284. Max(sin(min), sin(max)))
  285. elif isinstance(arg, SetExpr):
  286. return arg._eval_func(cls)
  287. if arg.could_extract_minus_sign():
  288. return -cls(-arg)
  289. i_coeff = _imaginary_unit_as_coefficient(arg)
  290. if i_coeff is not None:
  291. from sympy.functions.elementary.hyperbolic import sinh
  292. return S.ImaginaryUnit*sinh(i_coeff)
  293. pi_coeff = _pi_coeff(arg)
  294. if pi_coeff is not None:
  295. if pi_coeff.is_integer:
  296. return S.Zero
  297. if (2*pi_coeff).is_integer:
  298. # is_even-case handled above as then pi_coeff.is_integer,
  299. # so check if known to be not even
  300. if pi_coeff.is_even is False:
  301. return S.NegativeOne**(pi_coeff - S.Half)
  302. if not pi_coeff.is_Rational:
  303. narg = pi_coeff*pi
  304. if narg != arg:
  305. return cls(narg)
  306. return None
  307. # https://github.com/sympy/sympy/issues/6048
  308. # transform a sine to a cosine, to avoid redundant code
  309. if pi_coeff.is_Rational:
  310. x = pi_coeff % 2
  311. if x > 1:
  312. return -cls((x % 1)*pi)
  313. if 2*x > 1:
  314. return cls((1 - x)*pi)
  315. narg = ((pi_coeff + Rational(3, 2)) % 2)*pi
  316. result = cos(narg)
  317. if not isinstance(result, cos):
  318. return result
  319. if pi_coeff*pi != arg:
  320. return cls(pi_coeff*pi)
  321. return None
  322. if arg.is_Add:
  323. x, m = _peeloff_pi(arg)
  324. if m:
  325. m = m*pi
  326. return sin(m)*cos(x) + cos(m)*sin(x)
  327. if arg.is_zero:
  328. return S.Zero
  329. if isinstance(arg, asin):
  330. return arg.args[0]
  331. if isinstance(arg, atan):
  332. x = arg.args[0]
  333. return x/sqrt(1 + x**2)
  334. if isinstance(arg, atan2):
  335. y, x = arg.args
  336. return y/sqrt(x**2 + y**2)
  337. if isinstance(arg, acos):
  338. x = arg.args[0]
  339. return sqrt(1 - x**2)
  340. if isinstance(arg, acot):
  341. x = arg.args[0]
  342. return 1/(sqrt(1 + 1/x**2)*x)
  343. if isinstance(arg, acsc):
  344. x = arg.args[0]
  345. return 1/x
  346. if isinstance(arg, asec):
  347. x = arg.args[0]
  348. return sqrt(1 - 1/x**2)
  349. @staticmethod
  350. @cacheit
  351. def taylor_term(n, x, *previous_terms):
  352. if n < 0 or n % 2 == 0:
  353. return S.Zero
  354. else:
  355. x = sympify(x)
  356. if len(previous_terms) > 2:
  357. p = previous_terms[-2]
  358. return -p*x**2/(n*(n - 1))
  359. else:
  360. return S.NegativeOne**(n//2)*x**n/factorial(n)
  361. def _eval_nseries(self, x, n, logx, cdir=0):
  362. arg = self.args[0]
  363. if logx is not None:
  364. arg = arg.subs(log(x), logx)
  365. if arg.subs(x, 0).has(S.NaN, S.ComplexInfinity):
  366. raise PoleError("Cannot expand %s around 0" % (self))
  367. return super()._eval_nseries(x, n=n, logx=logx, cdir=cdir)
  368. def _eval_rewrite_as_exp(self, arg, **kwargs):
  369. from sympy.functions.elementary.hyperbolic import HyperbolicFunction
  370. I = S.ImaginaryUnit
  371. if isinstance(arg, (TrigonometricFunction, HyperbolicFunction)):
  372. arg = arg.func(arg.args[0]).rewrite(exp)
  373. return (exp(arg*I) - exp(-arg*I))/(2*I)
  374. def _eval_rewrite_as_Pow(self, arg, **kwargs):
  375. if isinstance(arg, log):
  376. I = S.ImaginaryUnit
  377. x = arg.args[0]
  378. return I*x**-I/2 - I*x**I /2
  379. def _eval_rewrite_as_cos(self, arg, **kwargs):
  380. return cos(arg - pi/2, evaluate=False)
  381. def _eval_rewrite_as_tan(self, arg, **kwargs):
  382. tan_half = tan(S.Half*arg)
  383. return 2*tan_half/(1 + tan_half**2)
  384. def _eval_rewrite_as_sincos(self, arg, **kwargs):
  385. return sin(arg)*cos(arg)/cos(arg)
  386. def _eval_rewrite_as_cot(self, arg, **kwargs):
  387. cot_half = cot(S.Half*arg)
  388. return Piecewise((0, And(Eq(im(arg), 0), Eq(Mod(arg, pi), 0))),
  389. (2*cot_half/(1 + cot_half**2), True))
  390. def _eval_rewrite_as_pow(self, arg, **kwargs):
  391. return self.rewrite(cos, **kwargs).rewrite(pow, **kwargs)
  392. def _eval_rewrite_as_sqrt(self, arg, **kwargs):
  393. return self.rewrite(cos, **kwargs).rewrite(sqrt, **kwargs)
  394. def _eval_rewrite_as_csc(self, arg, **kwargs):
  395. return 1/csc(arg)
  396. def _eval_rewrite_as_sec(self, arg, **kwargs):
  397. return 1/sec(arg - pi/2, evaluate=False)
  398. def _eval_rewrite_as_sinc(self, arg, **kwargs):
  399. return arg*sinc(arg)
  400. def _eval_rewrite_as_besselj(self, arg, **kwargs):
  401. from sympy.functions.special.bessel import besselj
  402. return sqrt(pi*arg/2)*besselj(S.Half, arg)
  403. def _eval_conjugate(self):
  404. return self.func(self.args[0].conjugate())
  405. def as_real_imag(self, deep=True, **hints):
  406. from sympy.functions.elementary.hyperbolic import cosh, sinh
  407. re, im = self._as_real_imag(deep=deep, **hints)
  408. return (sin(re)*cosh(im), cos(re)*sinh(im))
  409. def _eval_expand_trig(self, **hints):
  410. from sympy.functions.special.polynomials import chebyshevt, chebyshevu
  411. arg = self.args[0]
  412. x = None
  413. if arg.is_Add: # TODO, implement more if deep stuff here
  414. # TODO: Do this more efficiently for more than two terms
  415. x, y = arg.as_two_terms()
  416. sx = sin(x, evaluate=False)._eval_expand_trig()
  417. sy = sin(y, evaluate=False)._eval_expand_trig()
  418. cx = cos(x, evaluate=False)._eval_expand_trig()
  419. cy = cos(y, evaluate=False)._eval_expand_trig()
  420. return sx*cy + sy*cx
  421. elif arg.is_Mul:
  422. n, x = arg.as_coeff_Mul(rational=True)
  423. if n.is_Integer: # n will be positive because of .eval
  424. # canonicalization
  425. # See https://mathworld.wolfram.com/Multiple-AngleFormulas.html
  426. if n.is_odd:
  427. return S.NegativeOne**((n - 1)/2)*chebyshevt(n, sin(x))
  428. else:
  429. return expand_mul(S.NegativeOne**(n/2 - 1)*cos(x)*
  430. chebyshevu(n - 1, sin(x)), deep=False)
  431. return sin(arg)
  432. def _eval_as_leading_term(self, x, logx, cdir):
  433. from sympy.calculus.accumulationbounds import AccumBounds
  434. arg = self.args[0]
  435. x0 = arg.subs(x, 0).cancel()
  436. n = x0/pi
  437. if n.is_integer:
  438. lt = (arg - n*pi).as_leading_term(x)
  439. return (S.NegativeOne**n)*lt
  440. if x0 is S.ComplexInfinity:
  441. x0 = arg.limit(x, 0, dir='-' if re(cdir).is_negative else '+')
  442. if x0 in [S.Infinity, S.NegativeInfinity]:
  443. return AccumBounds(-1, 1)
  444. return self.func(x0) if x0.is_finite else self
  445. def _eval_is_extended_real(self):
  446. if self.args[0].is_extended_real:
  447. return True
  448. def _eval_is_finite(self):
  449. arg = self.args[0]
  450. if arg.is_extended_real:
  451. return True
  452. def _eval_is_zero(self):
  453. rest, pi_mult = _peeloff_pi(self.args[0])
  454. if rest.is_zero:
  455. return pi_mult.is_integer
  456. def _eval_is_complex(self):
  457. if self.args[0].is_extended_real \
  458. or self.args[0].is_complex:
  459. return True
  460. class cos(TrigonometricFunction):
  461. """
  462. The cosine function.
  463. Returns the cosine of x (measured in radians).
  464. Explanation
  465. ===========
  466. See :func:`sin` for notes about automatic evaluation.
  467. Examples
  468. ========
  469. >>> from sympy import cos, pi
  470. >>> from sympy.abc import x
  471. >>> cos(x**2).diff(x)
  472. -2*x*sin(x**2)
  473. >>> cos(1).diff(x)
  474. 0
  475. >>> cos(pi)
  476. -1
  477. >>> cos(pi/2)
  478. 0
  479. >>> cos(2*pi/3)
  480. -1/2
  481. >>> cos(pi/12)
  482. sqrt(2)/4 + sqrt(6)/4
  483. See Also
  484. ========
  485. sin, csc, sec, tan, cot
  486. asin, acsc, acos, asec, atan, acot, atan2
  487. References
  488. ==========
  489. .. [1] https://en.wikipedia.org/wiki/Trigonometric_functions
  490. .. [2] https://dlmf.nist.gov/4.14
  491. .. [3] https://functions.wolfram.com/ElementaryFunctions/Cos
  492. """
  493. def period(self, symbol=None):
  494. return self._period(2*pi, symbol)
  495. def fdiff(self, argindex=1):
  496. if argindex == 1:
  497. return -sin(self.args[0])
  498. else:
  499. raise ArgumentIndexError(self, argindex)
  500. @classmethod
  501. def eval(cls, arg):
  502. from sympy.functions.special.polynomials import chebyshevt
  503. from sympy.calculus.accumulationbounds import AccumBounds
  504. from sympy.sets.setexpr import SetExpr
  505. if arg.is_Number:
  506. if arg is S.NaN:
  507. return S.NaN
  508. elif arg.is_zero:
  509. return S.One
  510. elif arg in (S.Infinity, S.NegativeInfinity):
  511. # In this case it is better to return AccumBounds(-1, 1)
  512. # rather than returning S.NaN, since AccumBounds(-1, 1)
  513. # preserves the information that sin(oo) is between
  514. # -1 and 1, where S.NaN does not do that.
  515. return AccumBounds(-1, 1)
  516. if arg is S.ComplexInfinity:
  517. return S.NaN
  518. if isinstance(arg, AccumBounds):
  519. return sin(arg + pi/2)
  520. elif isinstance(arg, SetExpr):
  521. return arg._eval_func(cls)
  522. if arg.is_extended_real and arg.is_finite is False:
  523. return AccumBounds(-1, 1)
  524. if arg.could_extract_minus_sign():
  525. return cls(-arg)
  526. i_coeff = _imaginary_unit_as_coefficient(arg)
  527. if i_coeff is not None:
  528. from sympy.functions.elementary.hyperbolic import cosh
  529. return cosh(i_coeff)
  530. pi_coeff = _pi_coeff(arg)
  531. if pi_coeff is not None:
  532. if pi_coeff.is_integer:
  533. return (S.NegativeOne)**pi_coeff
  534. if (2*pi_coeff).is_integer:
  535. # is_even-case handled above as then pi_coeff.is_integer,
  536. # so check if known to be not even
  537. if pi_coeff.is_even is False:
  538. return S.Zero
  539. if not pi_coeff.is_Rational:
  540. narg = pi_coeff*pi
  541. if narg != arg:
  542. return cls(narg)
  543. return None
  544. # cosine formula #####################
  545. # https://github.com/sympy/sympy/issues/6048
  546. # explicit calculations are performed for
  547. # cos(k pi/n) for n = 8,10,12,15,20,24,30,40,60,120
  548. # Some other exact values like cos(k pi/240) can be
  549. # calculated using a partial-fraction decomposition
  550. # by calling cos( X ).rewrite(sqrt)
  551. if pi_coeff.is_Rational:
  552. q = pi_coeff.q
  553. p = pi_coeff.p % (2*q)
  554. if p > q:
  555. narg = (pi_coeff - 1)*pi
  556. return -cls(narg)
  557. if 2*p > q:
  558. narg = (1 - pi_coeff)*pi
  559. return -cls(narg)
  560. # If nested sqrt's are worse than un-evaluation
  561. # you can require q to be in (1, 2, 3, 4, 6, 12)
  562. # q <= 12, q=15, q=20, q=24, q=30, q=40, q=60, q=120 return
  563. # expressions with 2 or fewer sqrt nestings.
  564. table2 = _table2()
  565. if q in table2:
  566. a, b = table2[q]
  567. a, b = p*pi/a, p*pi/b
  568. nvala, nvalb = cls(a), cls(b)
  569. if None in (nvala, nvalb):
  570. return None
  571. return nvala*nvalb + cls(pi/2 - a)*cls(pi/2 - b)
  572. if q > 12:
  573. return None
  574. cst_table_some = {
  575. 3: S.Half,
  576. 5: (sqrt(5) + 1) / 4,
  577. }
  578. if q in cst_table_some:
  579. cts = cst_table_some[pi_coeff.q]
  580. return chebyshevt(pi_coeff.p, cts).expand()
  581. if 0 == q % 2:
  582. narg = (pi_coeff*2)*pi
  583. nval = cls(narg)
  584. if None == nval:
  585. return None
  586. x = (2*pi_coeff + 1)/2
  587. sign_cos = (-1)**((-1 if x < 0 else 1)*int(abs(x)))
  588. return sign_cos*sqrt( (1 + nval)/2 )
  589. return None
  590. if arg.is_Add:
  591. x, m = _peeloff_pi(arg)
  592. if m:
  593. m = m*pi
  594. return cos(m)*cos(x) - sin(m)*sin(x)
  595. if arg.is_zero:
  596. return S.One
  597. if isinstance(arg, acos):
  598. return arg.args[0]
  599. if isinstance(arg, atan):
  600. x = arg.args[0]
  601. return 1/sqrt(1 + x**2)
  602. if isinstance(arg, atan2):
  603. y, x = arg.args
  604. return x/sqrt(x**2 + y**2)
  605. if isinstance(arg, asin):
  606. x = arg.args[0]
  607. return sqrt(1 - x ** 2)
  608. if isinstance(arg, acot):
  609. x = arg.args[0]
  610. return 1/sqrt(1 + 1/x**2)
  611. if isinstance(arg, acsc):
  612. x = arg.args[0]
  613. return sqrt(1 - 1/x**2)
  614. if isinstance(arg, asec):
  615. x = arg.args[0]
  616. return 1/x
  617. @staticmethod
  618. @cacheit
  619. def taylor_term(n, x, *previous_terms):
  620. if n < 0 or n % 2 == 1:
  621. return S.Zero
  622. else:
  623. x = sympify(x)
  624. if len(previous_terms) > 2:
  625. p = previous_terms[-2]
  626. return -p*x**2/(n*(n - 1))
  627. else:
  628. return S.NegativeOne**(n//2)*x**n/factorial(n)
  629. def _eval_nseries(self, x, n, logx, cdir=0):
  630. arg = self.args[0]
  631. if logx is not None:
  632. arg = arg.subs(log(x), logx)
  633. if arg.subs(x, 0).has(S.NaN, S.ComplexInfinity):
  634. raise PoleError("Cannot expand %s around 0" % (self))
  635. return super()._eval_nseries(x, n=n, logx=logx, cdir=cdir)
  636. def _eval_rewrite_as_exp(self, arg, **kwargs):
  637. I = S.ImaginaryUnit
  638. from sympy.functions.elementary.hyperbolic import HyperbolicFunction
  639. if isinstance(arg, (TrigonometricFunction, HyperbolicFunction)):
  640. arg = arg.func(arg.args[0]).rewrite(exp, **kwargs)
  641. return (exp(arg*I) + exp(-arg*I))/2
  642. def _eval_rewrite_as_Pow(self, arg, **kwargs):
  643. if isinstance(arg, log):
  644. I = S.ImaginaryUnit
  645. x = arg.args[0]
  646. return x**I/2 + x**-I/2
  647. def _eval_rewrite_as_sin(self, arg, **kwargs):
  648. return sin(arg + pi/2, evaluate=False)
  649. def _eval_rewrite_as_tan(self, arg, **kwargs):
  650. tan_half = tan(S.Half*arg)**2
  651. return (1 - tan_half)/(1 + tan_half)
  652. def _eval_rewrite_as_sincos(self, arg, **kwargs):
  653. return sin(arg)*cos(arg)/sin(arg)
  654. def _eval_rewrite_as_cot(self, arg, **kwargs):
  655. cot_half = cot(S.Half*arg)**2
  656. return Piecewise((1, And(Eq(im(arg), 0), Eq(Mod(arg, 2*pi), 0))),
  657. ((cot_half - 1)/(cot_half + 1), True))
  658. def _eval_rewrite_as_pow(self, arg, **kwargs):
  659. return self._eval_rewrite_as_sqrt(arg, **kwargs)
  660. def _eval_rewrite_as_sqrt(self, arg: Expr, **kwargs):
  661. from sympy.functions.special.polynomials import chebyshevt
  662. pi_coeff = _pi_coeff(arg)
  663. if pi_coeff is None:
  664. return None
  665. if isinstance(pi_coeff, Integer):
  666. return None
  667. if not isinstance(pi_coeff, Rational):
  668. return None
  669. cst_table_some = cos_table()
  670. if pi_coeff.q in cst_table_some:
  671. rv = chebyshevt(pi_coeff.p, cst_table_some[pi_coeff.q]())
  672. if pi_coeff.q < 257:
  673. rv = rv.expand()
  674. return rv
  675. if not pi_coeff.q % 2: # recursively remove factors of 2
  676. pico2 = pi_coeff * 2
  677. nval = cos(pico2 * pi).rewrite(sqrt, **kwargs)
  678. x = (pico2 + 1) / 2
  679. sign_cos = -1 if int(x) % 2 else 1
  680. return sign_cos * sqrt((1 + nval) / 2)
  681. FC = fermat_coords(pi_coeff.q)
  682. if FC:
  683. denoms = FC
  684. else:
  685. denoms = [b**e for b, e in factorint(pi_coeff.q).items()]
  686. apart = ipartfrac(*denoms)
  687. decomp = (pi_coeff.p * Rational(n, d) for n, d in zip(apart, denoms))
  688. X = [(x[1], x[0]*pi) for x in zip(decomp, numbered_symbols('z'))]
  689. pcls = cos(sum(x[0] for x in X))._eval_expand_trig().subs(X)
  690. if not FC or len(FC) == 1:
  691. return pcls
  692. return pcls.rewrite(sqrt, **kwargs)
  693. def _eval_rewrite_as_sec(self, arg, **kwargs):
  694. return 1/sec(arg)
  695. def _eval_rewrite_as_csc(self, arg, **kwargs):
  696. return 1/sec(arg).rewrite(csc, **kwargs)
  697. def _eval_rewrite_as_besselj(self, arg, **kwargs):
  698. from sympy.functions.special.bessel import besselj
  699. return Piecewise(
  700. (sqrt(pi*arg/2)*besselj(-S.Half, arg), Ne(arg, 0)),
  701. (1, True)
  702. )
  703. def _eval_conjugate(self):
  704. return self.func(self.args[0].conjugate())
  705. def as_real_imag(self, deep=True, **hints):
  706. from sympy.functions.elementary.hyperbolic import cosh, sinh
  707. re, im = self._as_real_imag(deep=deep, **hints)
  708. return (cos(re)*cosh(im), -sin(re)*sinh(im))
  709. def _eval_expand_trig(self, **hints):
  710. from sympy.functions.special.polynomials import chebyshevt
  711. arg = self.args[0]
  712. x = None
  713. if arg.is_Add: # TODO: Do this more efficiently for more than two terms
  714. x, y = arg.as_two_terms()
  715. sx = sin(x, evaluate=False)._eval_expand_trig()
  716. sy = sin(y, evaluate=False)._eval_expand_trig()
  717. cx = cos(x, evaluate=False)._eval_expand_trig()
  718. cy = cos(y, evaluate=False)._eval_expand_trig()
  719. return cx*cy - sx*sy
  720. elif arg.is_Mul:
  721. coeff, terms = arg.as_coeff_Mul(rational=True)
  722. if coeff.is_Integer:
  723. return chebyshevt(coeff, cos(terms))
  724. return cos(arg)
  725. def _eval_as_leading_term(self, x, logx, cdir):
  726. from sympy.calculus.accumulationbounds import AccumBounds
  727. arg = self.args[0]
  728. x0 = arg.subs(x, 0).cancel()
  729. n = (x0 + pi/2)/pi
  730. if n.is_integer:
  731. lt = (arg - n*pi + pi/2).as_leading_term(x)
  732. return (S.NegativeOne**n)*lt
  733. if x0 is S.ComplexInfinity:
  734. x0 = arg.limit(x, 0, dir='-' if re(cdir).is_negative else '+')
  735. if x0 in [S.Infinity, S.NegativeInfinity]:
  736. return AccumBounds(-1, 1)
  737. return self.func(x0) if x0.is_finite else self
  738. def _eval_is_extended_real(self):
  739. if self.args[0].is_extended_real:
  740. return True
  741. def _eval_is_finite(self):
  742. arg = self.args[0]
  743. if arg.is_extended_real:
  744. return True
  745. def _eval_is_complex(self):
  746. if self.args[0].is_extended_real \
  747. or self.args[0].is_complex:
  748. return True
  749. def _eval_is_zero(self):
  750. rest, pi_mult = _peeloff_pi(self.args[0])
  751. if rest.is_zero and pi_mult:
  752. return (pi_mult - S.Half).is_integer
  753. class tan(TrigonometricFunction):
  754. """
  755. The tangent function.
  756. Returns the tangent of x (measured in radians).
  757. Explanation
  758. ===========
  759. See :class:`sin` for notes about automatic evaluation.
  760. Examples
  761. ========
  762. >>> from sympy import tan, pi
  763. >>> from sympy.abc import x
  764. >>> tan(x**2).diff(x)
  765. 2*x*(tan(x**2)**2 + 1)
  766. >>> tan(1).diff(x)
  767. 0
  768. >>> tan(pi/8).expand()
  769. -1 + sqrt(2)
  770. See Also
  771. ========
  772. sin, csc, cos, sec, cot
  773. asin, acsc, acos, asec, atan, acot, atan2
  774. References
  775. ==========
  776. .. [1] https://en.wikipedia.org/wiki/Trigonometric_functions
  777. .. [2] https://dlmf.nist.gov/4.14
  778. .. [3] https://functions.wolfram.com/ElementaryFunctions/Tan
  779. """
  780. def period(self, symbol=None):
  781. return self._period(pi, symbol)
  782. def fdiff(self, argindex=1):
  783. if argindex == 1:
  784. return S.One + self**2
  785. else:
  786. raise ArgumentIndexError(self, argindex)
  787. def inverse(self, argindex=1):
  788. """
  789. Returns the inverse of this function.
  790. """
  791. return atan
  792. @classmethod
  793. def eval(cls, arg):
  794. from sympy.calculus.accumulationbounds import AccumBounds
  795. if arg.is_Number:
  796. if arg is S.NaN:
  797. return S.NaN
  798. elif arg.is_zero:
  799. return S.Zero
  800. elif arg in (S.Infinity, S.NegativeInfinity):
  801. return AccumBounds(S.NegativeInfinity, S.Infinity)
  802. if arg is S.ComplexInfinity:
  803. return S.NaN
  804. if isinstance(arg, AccumBounds):
  805. min, max = arg.min, arg.max
  806. d = floor(min/pi)
  807. if min is not S.NegativeInfinity:
  808. min = min - d*pi
  809. if max is not S.Infinity:
  810. max = max - d*pi
  811. from sympy.sets.sets import FiniteSet
  812. if AccumBounds(min, max).intersection(FiniteSet(pi/2, pi*Rational(3, 2))):
  813. return AccumBounds(S.NegativeInfinity, S.Infinity)
  814. else:
  815. return AccumBounds(tan(min), tan(max))
  816. if arg.could_extract_minus_sign():
  817. return -cls(-arg)
  818. i_coeff = _imaginary_unit_as_coefficient(arg)
  819. if i_coeff is not None:
  820. from sympy.functions.elementary.hyperbolic import tanh
  821. return S.ImaginaryUnit*tanh(i_coeff)
  822. pi_coeff = _pi_coeff(arg, 2)
  823. if pi_coeff is not None:
  824. if pi_coeff.is_integer:
  825. return S.Zero
  826. if not pi_coeff.is_Rational:
  827. narg = pi_coeff*pi
  828. if narg != arg:
  829. return cls(narg)
  830. return None
  831. if pi_coeff.is_Rational:
  832. q = pi_coeff.q
  833. p = pi_coeff.p % q
  834. # ensure simplified results are returned for n*pi/5, n*pi/10
  835. table10 = {
  836. 1: sqrt(1 - 2*sqrt(5)/5),
  837. 2: sqrt(5 - 2*sqrt(5)),
  838. 3: sqrt(1 + 2*sqrt(5)/5),
  839. 4: sqrt(5 + 2*sqrt(5))
  840. }
  841. if q in (5, 10):
  842. n = 10*p/q
  843. if n > 5:
  844. n = 10 - n
  845. return -table10[n]
  846. else:
  847. return table10[n]
  848. if not pi_coeff.q % 2:
  849. narg = pi_coeff*pi*2
  850. cresult, sresult = cos(narg), cos(narg - pi/2)
  851. if not isinstance(cresult, cos) \
  852. and not isinstance(sresult, cos):
  853. if sresult == 0:
  854. return S.ComplexInfinity
  855. return 1/sresult - cresult/sresult
  856. table2 = _table2()
  857. if q in table2:
  858. a, b = table2[q]
  859. nvala, nvalb = cls(p*pi/a), cls(p*pi/b)
  860. if None in (nvala, nvalb):
  861. return None
  862. return (nvala - nvalb)/(1 + nvala*nvalb)
  863. narg = ((pi_coeff + S.Half) % 1 - S.Half)*pi
  864. # see cos() to specify which expressions should be
  865. # expanded automatically in terms of radicals
  866. cresult, sresult = cos(narg), cos(narg - pi/2)
  867. if not isinstance(cresult, cos) \
  868. and not isinstance(sresult, cos):
  869. if cresult == 0:
  870. return S.ComplexInfinity
  871. return (sresult/cresult)
  872. if narg != arg:
  873. return cls(narg)
  874. if arg.is_Add:
  875. x, m = _peeloff_pi(arg)
  876. if m:
  877. tanm = tan(m*pi)
  878. if tanm is S.ComplexInfinity:
  879. return -cot(x)
  880. else: # tanm == 0
  881. return tan(x)
  882. if arg.is_zero:
  883. return S.Zero
  884. if isinstance(arg, atan):
  885. return arg.args[0]
  886. if isinstance(arg, atan2):
  887. y, x = arg.args
  888. return y/x
  889. if isinstance(arg, asin):
  890. x = arg.args[0]
  891. return x/sqrt(1 - x**2)
  892. if isinstance(arg, acos):
  893. x = arg.args[0]
  894. return sqrt(1 - x**2)/x
  895. if isinstance(arg, acot):
  896. x = arg.args[0]
  897. return 1/x
  898. if isinstance(arg, acsc):
  899. x = arg.args[0]
  900. return 1/(sqrt(1 - 1/x**2)*x)
  901. if isinstance(arg, asec):
  902. x = arg.args[0]
  903. return sqrt(1 - 1/x**2)*x
  904. @staticmethod
  905. @cacheit
  906. def taylor_term(n, x, *previous_terms):
  907. if n < 0 or n % 2 == 0:
  908. return S.Zero
  909. else:
  910. x = sympify(x)
  911. a, b = ((n - 1)//2), 2**(n + 1)
  912. B = bernoulli(n + 1)
  913. F = factorial(n + 1)
  914. return S.NegativeOne**a*b*(b - 1)*B/F*x**n
  915. def _eval_nseries(self, x, n, logx, cdir=0):
  916. i = self.args[0].limit(x, 0)*2/pi
  917. if i and i.is_Integer:
  918. return self.rewrite(cos)._eval_nseries(x, n=n, logx=logx)
  919. return super()._eval_nseries(x, n=n, logx=logx)
  920. def _eval_rewrite_as_Pow(self, arg, **kwargs):
  921. if isinstance(arg, log):
  922. I = S.ImaginaryUnit
  923. x = arg.args[0]
  924. return I*(x**-I - x**I)/(x**-I + x**I)
  925. def _eval_conjugate(self):
  926. return self.func(self.args[0].conjugate())
  927. def as_real_imag(self, deep=True, **hints):
  928. re, im = self._as_real_imag(deep=deep, **hints)
  929. if im:
  930. from sympy.functions.elementary.hyperbolic import cosh, sinh
  931. denom = cos(2*re) + cosh(2*im)
  932. return (sin(2*re)/denom, sinh(2*im)/denom)
  933. else:
  934. return (self.func(re), S.Zero)
  935. def _eval_expand_trig(self, **hints):
  936. arg = self.args[0]
  937. x = None
  938. if arg.is_Add:
  939. n = len(arg.args)
  940. TX = []
  941. for x in arg.args:
  942. tx = tan(x, evaluate=False)._eval_expand_trig()
  943. TX.append(tx)
  944. Yg = numbered_symbols('Y')
  945. Y = [ next(Yg) for i in range(n) ]
  946. p = [0, 0]
  947. for i in range(n + 1):
  948. p[1 - i % 2] += symmetric_poly(i, Y)*(-1)**((i % 4)//2)
  949. return (p[0]/p[1]).subs(list(zip(Y, TX)))
  950. elif arg.is_Mul:
  951. coeff, terms = arg.as_coeff_Mul(rational=True)
  952. if coeff.is_Integer and coeff > 1:
  953. I = S.ImaginaryUnit
  954. z = Symbol('dummy', real=True)
  955. P = ((1 + I*z)**coeff).expand()
  956. return (im(P)/re(P)).subs([(z, tan(terms))])
  957. return tan(arg)
  958. def _eval_rewrite_as_exp(self, arg, **kwargs):
  959. I = S.ImaginaryUnit
  960. from sympy.functions.elementary.hyperbolic import HyperbolicFunction
  961. if isinstance(arg, (TrigonometricFunction, HyperbolicFunction)):
  962. arg = arg.func(arg.args[0]).rewrite(exp)
  963. neg_exp, pos_exp = exp(-arg*I), exp(arg*I)
  964. return I*(neg_exp - pos_exp)/(neg_exp + pos_exp)
  965. def _eval_rewrite_as_sin(self, x, **kwargs):
  966. return 2*sin(x)**2/sin(2*x)
  967. def _eval_rewrite_as_cos(self, x, **kwargs):
  968. return cos(x - pi/2, evaluate=False)/cos(x)
  969. def _eval_rewrite_as_sincos(self, arg, **kwargs):
  970. return sin(arg)/cos(arg)
  971. def _eval_rewrite_as_cot(self, arg, **kwargs):
  972. return 1/cot(arg)
  973. def _eval_rewrite_as_sec(self, arg, **kwargs):
  974. sin_in_sec_form = sin(arg).rewrite(sec, **kwargs)
  975. cos_in_sec_form = cos(arg).rewrite(sec, **kwargs)
  976. return sin_in_sec_form/cos_in_sec_form
  977. def _eval_rewrite_as_csc(self, arg, **kwargs):
  978. sin_in_csc_form = sin(arg).rewrite(csc, **kwargs)
  979. cos_in_csc_form = cos(arg).rewrite(csc, **kwargs)
  980. return sin_in_csc_form/cos_in_csc_form
  981. def _eval_rewrite_as_pow(self, arg, **kwargs):
  982. y = self.rewrite(cos, **kwargs).rewrite(pow, **kwargs)
  983. if y.has(cos):
  984. return None
  985. return y
  986. def _eval_rewrite_as_sqrt(self, arg, **kwargs):
  987. y = self.rewrite(cos, **kwargs).rewrite(sqrt, **kwargs)
  988. if y.has(cos):
  989. return None
  990. return y
  991. def _eval_rewrite_as_besselj(self, arg, **kwargs):
  992. from sympy.functions.special.bessel import besselj
  993. return besselj(S.Half, arg)/besselj(-S.Half, arg)
  994. def _eval_as_leading_term(self, x, logx, cdir):
  995. from sympy.calculus.accumulationbounds import AccumBounds
  996. from sympy.functions.elementary.complexes import re
  997. arg = self.args[0]
  998. x0 = arg.subs(x, 0).cancel()
  999. n = 2*x0/pi
  1000. if n.is_integer:
  1001. lt = (arg - n*pi/2).as_leading_term(x)
  1002. return lt if n.is_even else -1/lt
  1003. if x0 is S.ComplexInfinity:
  1004. x0 = arg.limit(x, 0, dir='-' if re(cdir).is_negative else '+')
  1005. if x0 in (S.Infinity, S.NegativeInfinity):
  1006. return AccumBounds(S.NegativeInfinity, S.Infinity)
  1007. return self.func(x0) if x0.is_finite else self
  1008. def _eval_is_extended_real(self):
  1009. # FIXME: currently tan(pi/2) return zoo
  1010. return self.args[0].is_extended_real
  1011. def _eval_is_real(self):
  1012. arg = self.args[0]
  1013. if arg.is_real and (arg/pi - S.Half).is_integer is False:
  1014. return True
  1015. def _eval_is_finite(self):
  1016. arg = self.args[0]
  1017. if arg.is_real and (arg/pi - S.Half).is_integer is False:
  1018. return True
  1019. if arg.is_imaginary:
  1020. return True
  1021. def _eval_is_zero(self):
  1022. rest, pi_mult = _peeloff_pi(self.args[0])
  1023. if rest.is_zero:
  1024. return pi_mult.is_integer
  1025. def _eval_is_complex(self):
  1026. arg = self.args[0]
  1027. if arg.is_real and (arg/pi - S.Half).is_integer is False:
  1028. return True
  1029. class cot(TrigonometricFunction):
  1030. """
  1031. The cotangent function.
  1032. Returns the cotangent of x (measured in radians).
  1033. Explanation
  1034. ===========
  1035. See :class:`sin` for notes about automatic evaluation.
  1036. Examples
  1037. ========
  1038. >>> from sympy import cot, pi
  1039. >>> from sympy.abc import x
  1040. >>> cot(x**2).diff(x)
  1041. 2*x*(-cot(x**2)**2 - 1)
  1042. >>> cot(1).diff(x)
  1043. 0
  1044. >>> cot(pi/12)
  1045. sqrt(3) + 2
  1046. See Also
  1047. ========
  1048. sin, csc, cos, sec, tan
  1049. asin, acsc, acos, asec, atan, acot, atan2
  1050. References
  1051. ==========
  1052. .. [1] https://en.wikipedia.org/wiki/Trigonometric_functions
  1053. .. [2] https://dlmf.nist.gov/4.14
  1054. .. [3] https://functions.wolfram.com/ElementaryFunctions/Cot
  1055. """
  1056. def period(self, symbol=None):
  1057. return self._period(pi, symbol)
  1058. def fdiff(self, argindex=1):
  1059. if argindex == 1:
  1060. return S.NegativeOne - self**2
  1061. else:
  1062. raise ArgumentIndexError(self, argindex)
  1063. def inverse(self, argindex=1):
  1064. """
  1065. Returns the inverse of this function.
  1066. """
  1067. return acot
  1068. @classmethod
  1069. def eval(cls, arg):
  1070. from sympy.calculus.accumulationbounds import AccumBounds
  1071. if arg.is_Number:
  1072. if arg is S.NaN:
  1073. return S.NaN
  1074. if arg.is_zero:
  1075. return S.ComplexInfinity
  1076. elif arg in (S.Infinity, S.NegativeInfinity):
  1077. return AccumBounds(S.NegativeInfinity, S.Infinity)
  1078. if arg is S.ComplexInfinity:
  1079. return S.NaN
  1080. if isinstance(arg, AccumBounds):
  1081. return -tan(arg + pi/2)
  1082. if arg.could_extract_minus_sign():
  1083. return -cls(-arg)
  1084. i_coeff = _imaginary_unit_as_coefficient(arg)
  1085. if i_coeff is not None:
  1086. from sympy.functions.elementary.hyperbolic import coth
  1087. return -S.ImaginaryUnit*coth(i_coeff)
  1088. pi_coeff = _pi_coeff(arg, 2)
  1089. if pi_coeff is not None:
  1090. if pi_coeff.is_integer:
  1091. return S.ComplexInfinity
  1092. if not pi_coeff.is_Rational:
  1093. narg = pi_coeff*pi
  1094. if narg != arg:
  1095. return cls(narg)
  1096. return None
  1097. if pi_coeff.is_Rational:
  1098. if pi_coeff.q in (5, 10):
  1099. return tan(pi/2 - arg)
  1100. if pi_coeff.q > 2 and not pi_coeff.q % 2:
  1101. narg = pi_coeff*pi*2
  1102. cresult, sresult = cos(narg), cos(narg - pi/2)
  1103. if not isinstance(cresult, cos) \
  1104. and not isinstance(sresult, cos):
  1105. return 1/sresult + cresult/sresult
  1106. q = pi_coeff.q
  1107. p = pi_coeff.p % q
  1108. table2 = _table2()
  1109. if q in table2:
  1110. a, b = table2[q]
  1111. nvala, nvalb = cls(p*pi/a), cls(p*pi/b)
  1112. if None in (nvala, nvalb):
  1113. return None
  1114. return (1 + nvala*nvalb)/(nvalb - nvala)
  1115. narg = (((pi_coeff + S.Half) % 1) - S.Half)*pi
  1116. # see cos() to specify which expressions should be
  1117. # expanded automatically in terms of radicals
  1118. cresult, sresult = cos(narg), cos(narg - pi/2)
  1119. if not isinstance(cresult, cos) \
  1120. and not isinstance(sresult, cos):
  1121. if sresult == 0:
  1122. return S.ComplexInfinity
  1123. return cresult/sresult
  1124. if narg != arg:
  1125. return cls(narg)
  1126. if arg.is_Add:
  1127. x, m = _peeloff_pi(arg)
  1128. if m:
  1129. cotm = cot(m*pi)
  1130. if cotm is S.ComplexInfinity:
  1131. return cot(x)
  1132. else: # cotm == 0
  1133. return -tan(x)
  1134. if arg.is_zero:
  1135. return S.ComplexInfinity
  1136. if isinstance(arg, acot):
  1137. return arg.args[0]
  1138. if isinstance(arg, atan):
  1139. x = arg.args[0]
  1140. return 1/x
  1141. if isinstance(arg, atan2):
  1142. y, x = arg.args
  1143. return x/y
  1144. if isinstance(arg, asin):
  1145. x = arg.args[0]
  1146. return sqrt(1 - x**2)/x
  1147. if isinstance(arg, acos):
  1148. x = arg.args[0]
  1149. return x/sqrt(1 - x**2)
  1150. if isinstance(arg, acsc):
  1151. x = arg.args[0]
  1152. return sqrt(1 - 1/x**2)*x
  1153. if isinstance(arg, asec):
  1154. x = arg.args[0]
  1155. return 1/(sqrt(1 - 1/x**2)*x)
  1156. @staticmethod
  1157. @cacheit
  1158. def taylor_term(n, x, *previous_terms):
  1159. if n == 0:
  1160. return 1/sympify(x)
  1161. elif n < 0 or n % 2 == 0:
  1162. return S.Zero
  1163. else:
  1164. x = sympify(x)
  1165. B = bernoulli(n + 1)
  1166. F = factorial(n + 1)
  1167. return S.NegativeOne**((n + 1)//2)*2**(n + 1)*B/F*x**n
  1168. def _eval_nseries(self, x, n, logx, cdir=0):
  1169. i = self.args[0].limit(x, 0)/pi
  1170. if i and i.is_Integer:
  1171. return self.rewrite(cos)._eval_nseries(x, n=n, logx=logx)
  1172. return self.rewrite(tan)._eval_nseries(x, n=n, logx=logx)
  1173. def _eval_conjugate(self):
  1174. return self.func(self.args[0].conjugate())
  1175. def as_real_imag(self, deep=True, **hints):
  1176. re, im = self._as_real_imag(deep=deep, **hints)
  1177. if im:
  1178. from sympy.functions.elementary.hyperbolic import cosh, sinh
  1179. denom = cos(2*re) - cosh(2*im)
  1180. return (-sin(2*re)/denom, sinh(2*im)/denom)
  1181. else:
  1182. return (self.func(re), S.Zero)
  1183. def _eval_rewrite_as_exp(self, arg, **kwargs):
  1184. from sympy.functions.elementary.hyperbolic import HyperbolicFunction
  1185. I = S.ImaginaryUnit
  1186. if isinstance(arg, (TrigonometricFunction, HyperbolicFunction)):
  1187. arg = arg.func(arg.args[0]).rewrite(exp, **kwargs)
  1188. neg_exp, pos_exp = exp(-arg*I), exp(arg*I)
  1189. return I*(pos_exp + neg_exp)/(pos_exp - neg_exp)
  1190. def _eval_rewrite_as_Pow(self, arg, **kwargs):
  1191. if isinstance(arg, log):
  1192. I = S.ImaginaryUnit
  1193. x = arg.args[0]
  1194. return -I*(x**-I + x**I)/(x**-I - x**I)
  1195. def _eval_rewrite_as_sin(self, x, **kwargs):
  1196. return sin(2*x)/(2*(sin(x)**2))
  1197. def _eval_rewrite_as_cos(self, x, **kwargs):
  1198. return cos(x)/cos(x - pi/2, evaluate=False)
  1199. def _eval_rewrite_as_sincos(self, arg, **kwargs):
  1200. return cos(arg)/sin(arg)
  1201. def _eval_rewrite_as_tan(self, arg, **kwargs):
  1202. return 1/tan(arg)
  1203. def _eval_rewrite_as_sec(self, arg, **kwargs):
  1204. cos_in_sec_form = cos(arg).rewrite(sec, **kwargs)
  1205. sin_in_sec_form = sin(arg).rewrite(sec, **kwargs)
  1206. return cos_in_sec_form/sin_in_sec_form
  1207. def _eval_rewrite_as_csc(self, arg, **kwargs):
  1208. cos_in_csc_form = cos(arg).rewrite(csc, **kwargs)
  1209. sin_in_csc_form = sin(arg).rewrite(csc, **kwargs)
  1210. return cos_in_csc_form/sin_in_csc_form
  1211. def _eval_rewrite_as_pow(self, arg, **kwargs):
  1212. y = self.rewrite(cos, **kwargs).rewrite(pow, **kwargs)
  1213. if y.has(cos):
  1214. return None
  1215. return y
  1216. def _eval_rewrite_as_sqrt(self, arg, **kwargs):
  1217. y = self.rewrite(cos, **kwargs).rewrite(sqrt, **kwargs)
  1218. if y.has(cos):
  1219. return None
  1220. return y
  1221. def _eval_rewrite_as_besselj(self, arg, **kwargs):
  1222. from sympy.functions.special.bessel import besselj
  1223. return besselj(-S.Half, arg)/besselj(S.Half, arg)
  1224. def _eval_as_leading_term(self, x, logx, cdir):
  1225. from sympy.calculus.accumulationbounds import AccumBounds
  1226. from sympy.functions.elementary.complexes import re
  1227. arg = self.args[0]
  1228. x0 = arg.subs(x, 0).cancel()
  1229. n = 2*x0/pi
  1230. if n.is_integer:
  1231. lt = (arg - n*pi/2).as_leading_term(x)
  1232. return 1/lt if n.is_even else -lt
  1233. if x0 is S.ComplexInfinity:
  1234. x0 = arg.limit(x, 0, dir='-' if re(cdir).is_negative else '+')
  1235. if x0 in (S.Infinity, S.NegativeInfinity):
  1236. return AccumBounds(S.NegativeInfinity, S.Infinity)
  1237. return self.func(x0) if x0.is_finite else self
  1238. def _eval_is_extended_real(self):
  1239. return self.args[0].is_extended_real
  1240. def _eval_expand_trig(self, **hints):
  1241. arg = self.args[0]
  1242. x = None
  1243. if arg.is_Add:
  1244. n = len(arg.args)
  1245. CX = []
  1246. for x in arg.args:
  1247. cx = cot(x, evaluate=False)._eval_expand_trig()
  1248. CX.append(cx)
  1249. Yg = numbered_symbols('Y')
  1250. Y = [ next(Yg) for i in range(n) ]
  1251. p = [0, 0]
  1252. for i in range(n, -1, -1):
  1253. p[(n - i) % 2] += symmetric_poly(i, Y)*(-1)**(((n - i) % 4)//2)
  1254. return (p[0]/p[1]).subs(list(zip(Y, CX)))
  1255. elif arg.is_Mul:
  1256. coeff, terms = arg.as_coeff_Mul(rational=True)
  1257. if coeff.is_Integer and coeff > 1:
  1258. I = S.ImaginaryUnit
  1259. z = Symbol('dummy', real=True)
  1260. P = ((z + I)**coeff).expand()
  1261. return (re(P)/im(P)).subs([(z, cot(terms))])
  1262. return cot(arg) # XXX sec and csc return 1/cos and 1/sin
  1263. def _eval_is_finite(self):
  1264. arg = self.args[0]
  1265. if arg.is_real and (arg/pi).is_integer is False:
  1266. return True
  1267. if arg.is_imaginary:
  1268. return True
  1269. def _eval_is_real(self):
  1270. arg = self.args[0]
  1271. if arg.is_real and (arg/pi).is_integer is False:
  1272. return True
  1273. def _eval_is_complex(self):
  1274. arg = self.args[0]
  1275. if arg.is_real and (arg/pi).is_integer is False:
  1276. return True
  1277. def _eval_is_zero(self):
  1278. rest, pimult = _peeloff_pi(self.args[0])
  1279. if pimult and rest.is_zero:
  1280. return (pimult - S.Half).is_integer
  1281. def _eval_subs(self, old, new):
  1282. arg = self.args[0]
  1283. argnew = arg.subs(old, new)
  1284. if arg != argnew and (argnew/pi).is_integer:
  1285. return S.ComplexInfinity
  1286. return cot(argnew)
  1287. class ReciprocalTrigonometricFunction(TrigonometricFunction):
  1288. """Base class for reciprocal functions of trigonometric functions. """
  1289. _reciprocal_of = None # mandatory, to be defined in subclass
  1290. _singularities = (S.ComplexInfinity,)
  1291. # _is_even and _is_odd are used for correct evaluation of csc(-x), sec(-x)
  1292. # TODO refactor into TrigonometricFunction common parts of
  1293. # trigonometric functions eval() like even/odd, func(x+2*k*pi), etc.
  1294. # optional, to be defined in subclasses:
  1295. _is_even: FuzzyBool = None
  1296. _is_odd: FuzzyBool = None
  1297. @classmethod
  1298. def eval(cls, arg):
  1299. if arg.could_extract_minus_sign():
  1300. if cls._is_even:
  1301. return cls(-arg)
  1302. if cls._is_odd:
  1303. return -cls(-arg)
  1304. pi_coeff = _pi_coeff(arg)
  1305. if (pi_coeff is not None
  1306. and not (2*pi_coeff).is_integer
  1307. and pi_coeff.is_Rational):
  1308. q = pi_coeff.q
  1309. p = pi_coeff.p % (2*q)
  1310. if p > q:
  1311. narg = (pi_coeff - 1)*pi
  1312. return -cls(narg)
  1313. if 2*p > q:
  1314. narg = (1 - pi_coeff)*pi
  1315. if cls._is_odd:
  1316. return cls(narg)
  1317. elif cls._is_even:
  1318. return -cls(narg)
  1319. if hasattr(arg, 'inverse') and arg.inverse() == cls:
  1320. return arg.args[0]
  1321. t = cls._reciprocal_of.eval(arg)
  1322. if t is None:
  1323. return t
  1324. elif any(isinstance(i, cos) for i in (t, -t)):
  1325. return (1/t).rewrite(sec)
  1326. elif any(isinstance(i, sin) for i in (t, -t)):
  1327. return (1/t).rewrite(csc)
  1328. else:
  1329. return 1/t
  1330. def _call_reciprocal(self, method_name, *args, **kwargs):
  1331. # Calls method_name on _reciprocal_of
  1332. o = self._reciprocal_of(self.args[0])
  1333. return getattr(o, method_name)(*args, **kwargs)
  1334. def _calculate_reciprocal(self, method_name, *args, **kwargs):
  1335. # If calling method_name on _reciprocal_of returns a value != None
  1336. # then return the reciprocal of that value
  1337. t = self._call_reciprocal(method_name, *args, **kwargs)
  1338. return 1/t if t is not None else t
  1339. def _rewrite_reciprocal(self, method_name, arg):
  1340. # Special handling for rewrite functions. If reciprocal rewrite returns
  1341. # unmodified expression, then return None
  1342. t = self._call_reciprocal(method_name, arg)
  1343. if t is not None and t != self._reciprocal_of(arg):
  1344. return 1/t
  1345. def _period(self, symbol):
  1346. f = expand_mul(self.args[0])
  1347. return self._reciprocal_of(f).period(symbol)
  1348. def fdiff(self, argindex=1):
  1349. return -self._calculate_reciprocal("fdiff", argindex)/self**2
  1350. def _eval_rewrite_as_exp(self, arg, **kwargs):
  1351. return self._rewrite_reciprocal("_eval_rewrite_as_exp", arg)
  1352. def _eval_rewrite_as_Pow(self, arg, **kwargs):
  1353. return self._rewrite_reciprocal("_eval_rewrite_as_Pow", arg)
  1354. def _eval_rewrite_as_sin(self, arg, **kwargs):
  1355. return self._rewrite_reciprocal("_eval_rewrite_as_sin", arg)
  1356. def _eval_rewrite_as_cos(self, arg, **kwargs):
  1357. return self._rewrite_reciprocal("_eval_rewrite_as_cos", arg)
  1358. def _eval_rewrite_as_tan(self, arg, **kwargs):
  1359. return self._rewrite_reciprocal("_eval_rewrite_as_tan", arg)
  1360. def _eval_rewrite_as_pow(self, arg, **kwargs):
  1361. return self._rewrite_reciprocal("_eval_rewrite_as_pow", arg)
  1362. def _eval_rewrite_as_sqrt(self, arg, **kwargs):
  1363. return self._rewrite_reciprocal("_eval_rewrite_as_sqrt", arg)
  1364. def _eval_conjugate(self):
  1365. return self.func(self.args[0].conjugate())
  1366. def as_real_imag(self, deep=True, **hints):
  1367. return (1/self._reciprocal_of(self.args[0])).as_real_imag(deep,
  1368. **hints)
  1369. def _eval_expand_trig(self, **hints):
  1370. return self._calculate_reciprocal("_eval_expand_trig", **hints)
  1371. def _eval_is_extended_real(self):
  1372. return self._reciprocal_of(self.args[0])._eval_is_extended_real()
  1373. def _eval_as_leading_term(self, x, logx, cdir):
  1374. return (1/self._reciprocal_of(self.args[0]))._eval_as_leading_term(x, logx=logx, cdir=cdir)
  1375. def _eval_is_finite(self):
  1376. return (1/self._reciprocal_of(self.args[0])).is_finite
  1377. def _eval_nseries(self, x, n, logx, cdir=0):
  1378. return (1/self._reciprocal_of(self.args[0]))._eval_nseries(x, n, logx)
  1379. class sec(ReciprocalTrigonometricFunction):
  1380. """
  1381. The secant function.
  1382. Returns the secant of x (measured in radians).
  1383. Explanation
  1384. ===========
  1385. See :class:`sin` for notes about automatic evaluation.
  1386. Examples
  1387. ========
  1388. >>> from sympy import sec
  1389. >>> from sympy.abc import x
  1390. >>> sec(x**2).diff(x)
  1391. 2*x*tan(x**2)*sec(x**2)
  1392. >>> sec(1).diff(x)
  1393. 0
  1394. See Also
  1395. ========
  1396. sin, csc, cos, tan, cot
  1397. asin, acsc, acos, asec, atan, acot, atan2
  1398. References
  1399. ==========
  1400. .. [1] https://en.wikipedia.org/wiki/Trigonometric_functions
  1401. .. [2] https://dlmf.nist.gov/4.14
  1402. .. [3] https://functions.wolfram.com/ElementaryFunctions/Sec
  1403. """
  1404. _reciprocal_of = cos
  1405. _is_even = True
  1406. def period(self, symbol=None):
  1407. return self._period(symbol)
  1408. def _eval_rewrite_as_cot(self, arg, **kwargs):
  1409. cot_half_sq = cot(arg/2)**2
  1410. return (cot_half_sq + 1)/(cot_half_sq - 1)
  1411. def _eval_rewrite_as_cos(self, arg, **kwargs):
  1412. return (1/cos(arg))
  1413. def _eval_rewrite_as_sincos(self, arg, **kwargs):
  1414. return sin(arg)/(cos(arg)*sin(arg))
  1415. def _eval_rewrite_as_sin(self, arg, **kwargs):
  1416. return (1/cos(arg).rewrite(sin, **kwargs))
  1417. def _eval_rewrite_as_tan(self, arg, **kwargs):
  1418. return (1/cos(arg).rewrite(tan, **kwargs))
  1419. def _eval_rewrite_as_csc(self, arg, **kwargs):
  1420. return csc(pi/2 - arg, evaluate=False)
  1421. def fdiff(self, argindex=1):
  1422. if argindex == 1:
  1423. return tan(self.args[0])*sec(self.args[0])
  1424. else:
  1425. raise ArgumentIndexError(self, argindex)
  1426. def _eval_rewrite_as_besselj(self, arg, **kwargs):
  1427. from sympy.functions.special.bessel import besselj
  1428. return Piecewise(
  1429. (1/(sqrt(pi*arg)/(sqrt(2))*besselj(-S.Half, arg)), Ne(arg, 0)),
  1430. (1, True)
  1431. )
  1432. def _eval_is_complex(self):
  1433. arg = self.args[0]
  1434. if arg.is_complex and (arg/pi - S.Half).is_integer is False:
  1435. return True
  1436. @staticmethod
  1437. @cacheit
  1438. def taylor_term(n, x, *previous_terms):
  1439. # Reference Formula:
  1440. # https://functions.wolfram.com/ElementaryFunctions/Sec/06/01/02/01/
  1441. if n < 0 or n % 2 == 1:
  1442. return S.Zero
  1443. else:
  1444. x = sympify(x)
  1445. k = n//2
  1446. return S.NegativeOne**k*euler(2*k)/factorial(2*k)*x**(2*k)
  1447. def _eval_as_leading_term(self, x, logx, cdir):
  1448. from sympy.calculus.accumulationbounds import AccumBounds
  1449. from sympy.functions.elementary.complexes import re
  1450. arg = self.args[0]
  1451. x0 = arg.subs(x, 0).cancel()
  1452. n = (x0 + pi/2)/pi
  1453. if n.is_integer:
  1454. lt = (arg - n*pi + pi/2).as_leading_term(x)
  1455. return (S.NegativeOne**n)/lt
  1456. if x0 is S.ComplexInfinity:
  1457. x0 = arg.limit(x, 0, dir='-' if re(cdir).is_negative else '+')
  1458. if x0 in (S.Infinity, S.NegativeInfinity):
  1459. return AccumBounds(S.NegativeInfinity, S.Infinity)
  1460. return self.func(x0) if x0.is_finite else self
  1461. class csc(ReciprocalTrigonometricFunction):
  1462. """
  1463. The cosecant function.
  1464. Returns the cosecant of x (measured in radians).
  1465. Explanation
  1466. ===========
  1467. See :func:`sin` for notes about automatic evaluation.
  1468. Examples
  1469. ========
  1470. >>> from sympy import csc
  1471. >>> from sympy.abc import x
  1472. >>> csc(x**2).diff(x)
  1473. -2*x*cot(x**2)*csc(x**2)
  1474. >>> csc(1).diff(x)
  1475. 0
  1476. See Also
  1477. ========
  1478. sin, cos, sec, tan, cot
  1479. asin, acsc, acos, asec, atan, acot, atan2
  1480. References
  1481. ==========
  1482. .. [1] https://en.wikipedia.org/wiki/Trigonometric_functions
  1483. .. [2] https://dlmf.nist.gov/4.14
  1484. .. [3] https://functions.wolfram.com/ElementaryFunctions/Csc
  1485. """
  1486. _reciprocal_of = sin
  1487. _is_odd = True
  1488. def period(self, symbol=None):
  1489. return self._period(symbol)
  1490. def _eval_rewrite_as_sin(self, arg, **kwargs):
  1491. return (1/sin(arg))
  1492. def _eval_rewrite_as_sincos(self, arg, **kwargs):
  1493. return cos(arg)/(sin(arg)*cos(arg))
  1494. def _eval_rewrite_as_cot(self, arg, **kwargs):
  1495. cot_half = cot(arg/2)
  1496. return (1 + cot_half**2)/(2*cot_half)
  1497. def _eval_rewrite_as_cos(self, arg, **kwargs):
  1498. return 1/sin(arg).rewrite(cos, **kwargs)
  1499. def _eval_rewrite_as_sec(self, arg, **kwargs):
  1500. return sec(pi/2 - arg, evaluate=False)
  1501. def _eval_rewrite_as_tan(self, arg, **kwargs):
  1502. return (1/sin(arg).rewrite(tan, **kwargs))
  1503. def _eval_rewrite_as_besselj(self, arg, **kwargs):
  1504. from sympy.functions.special.bessel import besselj
  1505. return sqrt(2/pi)*(1/(sqrt(arg)*besselj(S.Half, arg)))
  1506. def fdiff(self, argindex=1):
  1507. if argindex == 1:
  1508. return -cot(self.args[0])*csc(self.args[0])
  1509. else:
  1510. raise ArgumentIndexError(self, argindex)
  1511. def _eval_is_complex(self):
  1512. arg = self.args[0]
  1513. if arg.is_real and (arg/pi).is_integer is False:
  1514. return True
  1515. @staticmethod
  1516. @cacheit
  1517. def taylor_term(n, x, *previous_terms):
  1518. if n == 0:
  1519. return 1/sympify(x)
  1520. elif n < 0 or n % 2 == 0:
  1521. return S.Zero
  1522. else:
  1523. x = sympify(x)
  1524. k = n//2 + 1
  1525. return (S.NegativeOne**(k - 1)*2*(2**(2*k - 1) - 1)*
  1526. bernoulli(2*k)*x**(2*k - 1)/factorial(2*k))
  1527. def _eval_as_leading_term(self, x, logx, cdir):
  1528. from sympy.calculus.accumulationbounds import AccumBounds
  1529. from sympy.functions.elementary.complexes import re
  1530. arg = self.args[0]
  1531. x0 = arg.subs(x, 0).cancel()
  1532. n = x0/pi
  1533. if n.is_integer:
  1534. lt = (arg - n*pi).as_leading_term(x)
  1535. return (S.NegativeOne**n)/lt
  1536. if x0 is S.ComplexInfinity:
  1537. x0 = arg.limit(x, 0, dir='-' if re(cdir).is_negative else '+')
  1538. if x0 in (S.Infinity, S.NegativeInfinity):
  1539. return AccumBounds(S.NegativeInfinity, S.Infinity)
  1540. return self.func(x0) if x0.is_finite else self
  1541. class sinc(DefinedFunction):
  1542. r"""
  1543. Represents an unnormalized sinc function:
  1544. .. math::
  1545. \operatorname{sinc}(x) =
  1546. \begin{cases}
  1547. \frac{\sin x}{x} & \qquad x \neq 0 \\
  1548. 1 & \qquad x = 0
  1549. \end{cases}
  1550. Examples
  1551. ========
  1552. >>> from sympy import sinc, oo, jn
  1553. >>> from sympy.abc import x
  1554. >>> sinc(x)
  1555. sinc(x)
  1556. * Automated Evaluation
  1557. >>> sinc(0)
  1558. 1
  1559. >>> sinc(oo)
  1560. 0
  1561. * Differentiation
  1562. >>> sinc(x).diff()
  1563. cos(x)/x - sin(x)/x**2
  1564. * Series Expansion
  1565. >>> sinc(x).series()
  1566. 1 - x**2/6 + x**4/120 + O(x**6)
  1567. * As zero'th order spherical Bessel Function
  1568. >>> sinc(x).rewrite(jn)
  1569. jn(0, x)
  1570. See also
  1571. ========
  1572. sin
  1573. References
  1574. ==========
  1575. .. [1] https://en.wikipedia.org/wiki/Sinc_function
  1576. """
  1577. _singularities = (S.ComplexInfinity,)
  1578. def fdiff(self, argindex=1):
  1579. x = self.args[0]
  1580. if argindex == 1:
  1581. # We would like to return the Piecewise here, but Piecewise.diff
  1582. # currently can't handle removable singularities, meaning things
  1583. # like sinc(x).diff(x, 2) give the wrong answer at x = 0. See
  1584. # https://github.com/sympy/sympy/issues/11402.
  1585. #
  1586. # return Piecewise(((x*cos(x) - sin(x))/x**2, Ne(x, S.Zero)), (S.Zero, S.true))
  1587. return cos(x)/x - sin(x)/x**2
  1588. else:
  1589. raise ArgumentIndexError(self, argindex)
  1590. @classmethod
  1591. def eval(cls, arg):
  1592. if arg.is_zero:
  1593. return S.One
  1594. if arg.is_Number:
  1595. if arg in [S.Infinity, S.NegativeInfinity]:
  1596. return S.Zero
  1597. elif arg is S.NaN:
  1598. return S.NaN
  1599. if arg is S.ComplexInfinity:
  1600. return S.NaN
  1601. if arg.could_extract_minus_sign():
  1602. return cls(-arg)
  1603. pi_coeff = _pi_coeff(arg)
  1604. if pi_coeff is not None:
  1605. if pi_coeff.is_integer:
  1606. if fuzzy_not(arg.is_zero):
  1607. return S.Zero
  1608. elif (2*pi_coeff).is_integer:
  1609. return S.NegativeOne**(pi_coeff - S.Half)/arg
  1610. def _eval_nseries(self, x, n, logx, cdir=0):
  1611. x = self.args[0]
  1612. return (sin(x)/x)._eval_nseries(x, n, logx)
  1613. def _eval_rewrite_as_jn(self, arg, **kwargs):
  1614. from sympy.functions.special.bessel import jn
  1615. return jn(0, arg)
  1616. def _eval_rewrite_as_sin(self, arg, **kwargs):
  1617. return Piecewise((sin(arg)/arg, Ne(arg, S.Zero)), (S.One, S.true))
  1618. def _eval_is_zero(self):
  1619. if self.args[0].is_infinite:
  1620. return True
  1621. rest, pi_mult = _peeloff_pi(self.args[0])
  1622. if rest.is_zero:
  1623. return fuzzy_and([pi_mult.is_integer, pi_mult.is_nonzero])
  1624. if rest.is_Number and pi_mult.is_integer:
  1625. return False
  1626. def _eval_is_real(self):
  1627. if self.args[0].is_extended_real or self.args[0].is_imaginary:
  1628. return True
  1629. _eval_is_finite = _eval_is_real
  1630. ###############################################################################
  1631. ########################### TRIGONOMETRIC INVERSES ############################
  1632. ###############################################################################
  1633. class InverseTrigonometricFunction(DefinedFunction):
  1634. """Base class for inverse trigonometric functions."""
  1635. _singularities: tuple[Expr, ...] = (S.One, S.NegativeOne, S.Zero, S.ComplexInfinity)
  1636. @staticmethod
  1637. @cacheit
  1638. def _asin_table():
  1639. # Only keys with could_extract_minus_sign() == False
  1640. # are actually needed.
  1641. return {
  1642. sqrt(3)/2: pi/3,
  1643. sqrt(2)/2: pi/4,
  1644. 1/sqrt(2): pi/4,
  1645. sqrt((5 - sqrt(5))/8): pi/5,
  1646. sqrt(2)*sqrt(5 - sqrt(5))/4: pi/5,
  1647. sqrt((5 + sqrt(5))/8): pi*Rational(2, 5),
  1648. sqrt(2)*sqrt(5 + sqrt(5))/4: pi*Rational(2, 5),
  1649. S.Half: pi/6,
  1650. sqrt(2 - sqrt(2))/2: pi/8,
  1651. sqrt(S.Half - sqrt(2)/4): pi/8,
  1652. sqrt(2 + sqrt(2))/2: pi*Rational(3, 8),
  1653. sqrt(S.Half + sqrt(2)/4): pi*Rational(3, 8),
  1654. (sqrt(5) - 1)/4: pi/10,
  1655. (1 - sqrt(5))/4: -pi/10,
  1656. (sqrt(5) + 1)/4: pi*Rational(3, 10),
  1657. sqrt(6)/4 - sqrt(2)/4: pi/12,
  1658. -sqrt(6)/4 + sqrt(2)/4: -pi/12,
  1659. (sqrt(3) - 1)/sqrt(8): pi/12,
  1660. (1 - sqrt(3))/sqrt(8): -pi/12,
  1661. sqrt(6)/4 + sqrt(2)/4: pi*Rational(5, 12),
  1662. (1 + sqrt(3))/sqrt(8): pi*Rational(5, 12)
  1663. }
  1664. @staticmethod
  1665. @cacheit
  1666. def _atan_table():
  1667. # Only keys with could_extract_minus_sign() == False
  1668. # are actually needed.
  1669. return {
  1670. sqrt(3)/3: pi/6,
  1671. 1/sqrt(3): pi/6,
  1672. sqrt(3): pi/3,
  1673. sqrt(2) - 1: pi/8,
  1674. 1 - sqrt(2): -pi/8,
  1675. 1 + sqrt(2): pi*Rational(3, 8),
  1676. sqrt(5 - 2*sqrt(5)): pi/5,
  1677. sqrt(5 + 2*sqrt(5)): pi*Rational(2, 5),
  1678. sqrt(1 - 2*sqrt(5)/5): pi/10,
  1679. sqrt(1 + 2*sqrt(5)/5): pi*Rational(3, 10),
  1680. 2 - sqrt(3): pi/12,
  1681. -2 + sqrt(3): -pi/12,
  1682. 2 + sqrt(3): pi*Rational(5, 12)
  1683. }
  1684. @staticmethod
  1685. @cacheit
  1686. def _acsc_table():
  1687. # Keys for which could_extract_minus_sign()
  1688. # will obviously return True are omitted.
  1689. return {
  1690. 2*sqrt(3)/3: pi/3,
  1691. sqrt(2): pi/4,
  1692. sqrt(2 + 2*sqrt(5)/5): pi/5,
  1693. 1/sqrt(Rational(5, 8) - sqrt(5)/8): pi/5,
  1694. sqrt(2 - 2*sqrt(5)/5): pi*Rational(2, 5),
  1695. 1/sqrt(Rational(5, 8) + sqrt(5)/8): pi*Rational(2, 5),
  1696. 2: pi/6,
  1697. sqrt(4 + 2*sqrt(2)): pi/8,
  1698. 2/sqrt(2 - sqrt(2)): pi/8,
  1699. sqrt(4 - 2*sqrt(2)): pi*Rational(3, 8),
  1700. 2/sqrt(2 + sqrt(2)): pi*Rational(3, 8),
  1701. 1 + sqrt(5): pi/10,
  1702. sqrt(5) - 1: pi*Rational(3, 10),
  1703. -(sqrt(5) - 1): pi*Rational(-3, 10),
  1704. sqrt(6) + sqrt(2): pi/12,
  1705. sqrt(6) - sqrt(2): pi*Rational(5, 12),
  1706. -(sqrt(6) - sqrt(2)): pi*Rational(-5, 12)
  1707. }
  1708. class asin(InverseTrigonometricFunction):
  1709. r"""
  1710. The inverse sine function.
  1711. Returns the arcsine of x in radians.
  1712. Explanation
  1713. ===========
  1714. ``asin(x)`` will evaluate automatically in the cases
  1715. $x \in \{\infty, -\infty, 0, 1, -1\}$ and for some instances when the
  1716. result is a rational multiple of $\pi$ (see the ``eval`` class method).
  1717. A purely imaginary argument will lead to an asinh expression.
  1718. Examples
  1719. ========
  1720. >>> from sympy import asin, oo
  1721. >>> asin(1)
  1722. pi/2
  1723. >>> asin(-1)
  1724. -pi/2
  1725. >>> asin(-oo)
  1726. oo*I
  1727. >>> asin(oo)
  1728. -oo*I
  1729. See Also
  1730. ========
  1731. sin, csc, cos, sec, tan, cot
  1732. acsc, acos, asec, atan, acot, atan2
  1733. References
  1734. ==========
  1735. .. [1] https://en.wikipedia.org/wiki/Inverse_trigonometric_functions
  1736. .. [2] https://dlmf.nist.gov/4.23
  1737. .. [3] https://functions.wolfram.com/ElementaryFunctions/ArcSin
  1738. """
  1739. def fdiff(self, argindex=1):
  1740. if argindex == 1:
  1741. return 1/sqrt(1 - self.args[0]**2)
  1742. else:
  1743. raise ArgumentIndexError(self, argindex)
  1744. def _eval_is_rational(self):
  1745. s = self.func(*self.args)
  1746. if s.func == self.func:
  1747. if s.args[0].is_rational:
  1748. return False
  1749. else:
  1750. return s.is_rational
  1751. def _eval_is_positive(self):
  1752. return self._eval_is_extended_real() and self.args[0].is_positive
  1753. def _eval_is_negative(self):
  1754. return self._eval_is_extended_real() and self.args[0].is_negative
  1755. @classmethod
  1756. def eval(cls, arg):
  1757. if arg.is_Number:
  1758. if arg is S.NaN:
  1759. return S.NaN
  1760. elif arg is S.Infinity:
  1761. return S.NegativeInfinity*S.ImaginaryUnit
  1762. elif arg is S.NegativeInfinity:
  1763. return S.Infinity*S.ImaginaryUnit
  1764. elif arg.is_zero:
  1765. return S.Zero
  1766. elif arg is S.One:
  1767. return pi/2
  1768. elif arg is S.NegativeOne:
  1769. return -pi/2
  1770. if arg is S.ComplexInfinity:
  1771. return S.ComplexInfinity
  1772. if arg.could_extract_minus_sign():
  1773. return -cls(-arg)
  1774. if arg.is_number:
  1775. asin_table = cls._asin_table()
  1776. if arg in asin_table:
  1777. return asin_table[arg]
  1778. i_coeff = _imaginary_unit_as_coefficient(arg)
  1779. if i_coeff is not None:
  1780. from sympy.functions.elementary.hyperbolic import asinh
  1781. return S.ImaginaryUnit*asinh(i_coeff)
  1782. if arg.is_zero:
  1783. return S.Zero
  1784. if isinstance(arg, sin):
  1785. ang = arg.args[0]
  1786. if ang.is_comparable:
  1787. ang %= 2*pi # restrict to [0,2*pi)
  1788. if ang > pi: # restrict to (-pi,pi]
  1789. ang = pi - ang
  1790. # restrict to [-pi/2,pi/2]
  1791. if ang > pi/2:
  1792. ang = pi - ang
  1793. if ang < -pi/2:
  1794. ang = -pi - ang
  1795. return ang
  1796. if isinstance(arg, cos): # acos(x) + asin(x) = pi/2
  1797. ang = arg.args[0]
  1798. if ang.is_comparable:
  1799. return pi/2 - acos(arg)
  1800. @staticmethod
  1801. @cacheit
  1802. def taylor_term(n, x, *previous_terms):
  1803. if n < 0 or n % 2 == 0:
  1804. return S.Zero
  1805. else:
  1806. x = sympify(x)
  1807. if len(previous_terms) >= 2 and n > 2:
  1808. p = previous_terms[-2]
  1809. return p*(n - 2)**2/(n*(n - 1))*x**2
  1810. else:
  1811. k = (n - 1) // 2
  1812. R = RisingFactorial(S.Half, k)
  1813. F = factorial(k)
  1814. return R/F*x**n/n
  1815. def _eval_as_leading_term(self, x, logx, cdir):
  1816. arg = self.args[0]
  1817. x0 = arg.subs(x, 0).cancel()
  1818. if x0 is S.NaN:
  1819. return self.func(arg.as_leading_term(x))
  1820. if x0.is_zero:
  1821. return arg.as_leading_term(x)
  1822. # Handling branch points
  1823. if x0 in (-S.One, S.One, S.ComplexInfinity):
  1824. return self.rewrite(log)._eval_as_leading_term(x, logx=logx, cdir=cdir).expand()
  1825. # Handling points lying on branch cuts (-oo, -1) U (1, oo)
  1826. if (1 - x0**2).is_negative:
  1827. ndir = arg.dir(x, cdir if cdir else 1)
  1828. if im(ndir).is_negative:
  1829. if x0.is_negative:
  1830. return -pi - self.func(x0)
  1831. elif im(ndir).is_positive:
  1832. if x0.is_positive:
  1833. return pi - self.func(x0)
  1834. else:
  1835. return self.rewrite(log)._eval_as_leading_term(x, logx=logx, cdir=cdir).expand()
  1836. return self.func(x0)
  1837. def _eval_nseries(self, x, n, logx, cdir=0): # asin
  1838. from sympy.series.order import O
  1839. arg0 = self.args[0].subs(x, 0)
  1840. # Handling branch points
  1841. if arg0 is S.One:
  1842. t = Dummy('t', positive=True)
  1843. ser = asin(S.One - t**2).rewrite(log).nseries(t, 0, 2*n)
  1844. arg1 = S.One - self.args[0]
  1845. f = arg1.as_leading_term(x)
  1846. g = (arg1 - f)/ f
  1847. if not g.is_meromorphic(x, 0): # cannot be expanded
  1848. return O(1) if n == 0 else pi/2 + O(sqrt(x))
  1849. res1 = sqrt(S.One + g)._eval_nseries(x, n=n, logx=logx)
  1850. res = (res1.removeO()*sqrt(f)).expand()
  1851. return ser.removeO().subs(t, res).expand().powsimp() + O(x**n, x)
  1852. if arg0 is S.NegativeOne:
  1853. t = Dummy('t', positive=True)
  1854. ser = asin(S.NegativeOne + t**2).rewrite(log).nseries(t, 0, 2*n)
  1855. arg1 = S.One + self.args[0]
  1856. f = arg1.as_leading_term(x)
  1857. g = (arg1 - f)/ f
  1858. if not g.is_meromorphic(x, 0): # cannot be expanded
  1859. return O(1) if n == 0 else -pi/2 + O(sqrt(x))
  1860. res1 = sqrt(S.One + g)._eval_nseries(x, n=n, logx=logx)
  1861. res = (res1.removeO()*sqrt(f)).expand()
  1862. return ser.removeO().subs(t, res).expand().powsimp() + O(x**n, x)
  1863. res = super()._eval_nseries(x, n=n, logx=logx)
  1864. if arg0 is S.ComplexInfinity:
  1865. return res
  1866. # Handling points lying on branch cuts (-oo, -1) U (1, oo)
  1867. if (1 - arg0**2).is_negative:
  1868. ndir = self.args[0].dir(x, cdir if cdir else 1)
  1869. if im(ndir).is_negative:
  1870. if arg0.is_negative:
  1871. return -pi - res
  1872. elif im(ndir).is_positive:
  1873. if arg0.is_positive:
  1874. return pi - res
  1875. else:
  1876. return self.rewrite(log)._eval_nseries(x, n, logx=logx, cdir=cdir)
  1877. return res
  1878. def _eval_rewrite_as_acos(self, x, **kwargs):
  1879. return pi/2 - acos(x)
  1880. def _eval_rewrite_as_atan(self, x, **kwargs):
  1881. return 2*atan(x/(1 + sqrt(1 - x**2)))
  1882. def _eval_rewrite_as_log(self, x, **kwargs):
  1883. return -S.ImaginaryUnit*log(S.ImaginaryUnit*x + sqrt(1 - x**2))
  1884. _eval_rewrite_as_tractable = _eval_rewrite_as_log
  1885. def _eval_rewrite_as_acot(self, arg, **kwargs):
  1886. return 2*acot((1 + sqrt(1 - arg**2))/arg)
  1887. def _eval_rewrite_as_asec(self, arg, **kwargs):
  1888. return pi/2 - asec(1/arg)
  1889. def _eval_rewrite_as_acsc(self, arg, **kwargs):
  1890. return acsc(1/arg)
  1891. def _eval_is_extended_real(self):
  1892. x = self.args[0]
  1893. return x.is_extended_real and (1 - abs(x)).is_nonnegative
  1894. def inverse(self, argindex=1):
  1895. """
  1896. Returns the inverse of this function.
  1897. """
  1898. return sin
  1899. class acos(InverseTrigonometricFunction):
  1900. r"""
  1901. The inverse cosine function.
  1902. Explanation
  1903. ===========
  1904. Returns the arc cosine of x (measured in radians).
  1905. ``acos(x)`` will evaluate automatically in the cases
  1906. $x \in \{\infty, -\infty, 0, 1, -1\}$ and for some instances when
  1907. the result is a rational multiple of $\pi$ (see the eval class method).
  1908. ``acos(zoo)`` evaluates to ``zoo``
  1909. (see note in :class:`sympy.functions.elementary.trigonometric.asec`)
  1910. A purely imaginary argument will be rewritten to asinh.
  1911. Examples
  1912. ========
  1913. >>> from sympy import acos, oo
  1914. >>> acos(1)
  1915. 0
  1916. >>> acos(0)
  1917. pi/2
  1918. >>> acos(oo)
  1919. oo*I
  1920. See Also
  1921. ========
  1922. sin, csc, cos, sec, tan, cot
  1923. asin, acsc, asec, atan, acot, atan2
  1924. References
  1925. ==========
  1926. .. [1] https://en.wikipedia.org/wiki/Inverse_trigonometric_functions
  1927. .. [2] https://dlmf.nist.gov/4.23
  1928. .. [3] https://functions.wolfram.com/ElementaryFunctions/ArcCos
  1929. """
  1930. def fdiff(self, argindex=1):
  1931. if argindex == 1:
  1932. return -1/sqrt(1 - self.args[0]**2)
  1933. else:
  1934. raise ArgumentIndexError(self, argindex)
  1935. def _eval_is_rational(self):
  1936. s = self.func(*self.args)
  1937. if s.func == self.func:
  1938. if s.args[0].is_rational:
  1939. return False
  1940. else:
  1941. return s.is_rational
  1942. @classmethod
  1943. def eval(cls, arg):
  1944. if arg.is_Number:
  1945. if arg is S.NaN:
  1946. return S.NaN
  1947. elif arg is S.Infinity:
  1948. return S.Infinity*S.ImaginaryUnit
  1949. elif arg is S.NegativeInfinity:
  1950. return S.NegativeInfinity*S.ImaginaryUnit
  1951. elif arg.is_zero:
  1952. return pi/2
  1953. elif arg is S.One:
  1954. return S.Zero
  1955. elif arg is S.NegativeOne:
  1956. return pi
  1957. if arg is S.ComplexInfinity:
  1958. return S.ComplexInfinity
  1959. if arg.is_number:
  1960. asin_table = cls._asin_table()
  1961. if arg in asin_table:
  1962. return pi/2 - asin_table[arg]
  1963. elif -arg in asin_table:
  1964. return pi/2 + asin_table[-arg]
  1965. i_coeff = _imaginary_unit_as_coefficient(arg)
  1966. if i_coeff is not None:
  1967. return pi/2 - asin(arg)
  1968. if arg.is_Mul and len(arg.args) == 2 and arg.args[0] == -1:
  1969. narg = arg.args[1]
  1970. minus = True
  1971. else:
  1972. narg = arg
  1973. minus = False
  1974. if isinstance(narg, cos):
  1975. # acos(cos(x)) = x or acos(-cos(x)) = pi - x
  1976. ang = narg.args[0]
  1977. if ang.is_comparable:
  1978. if minus:
  1979. ang = pi - ang
  1980. ang %= 2*pi # restrict to [0,2*pi)
  1981. if ang > pi: # restrict to [0,pi]
  1982. ang = 2*pi - ang
  1983. return ang
  1984. if isinstance(narg, sin): # acos(x) + asin(x) = pi/2
  1985. ang = narg.args[0]
  1986. if ang.is_comparable:
  1987. if minus:
  1988. return pi/2 + asin(narg)
  1989. return pi/2 - asin(narg)
  1990. @staticmethod
  1991. @cacheit
  1992. def taylor_term(n, x, *previous_terms):
  1993. if n == 0:
  1994. return pi/2
  1995. elif n < 0 or n % 2 == 0:
  1996. return S.Zero
  1997. else:
  1998. x = sympify(x)
  1999. if len(previous_terms) >= 2 and n > 2:
  2000. p = previous_terms[-2]
  2001. return p*(n - 2)**2/(n*(n - 1))*x**2
  2002. else:
  2003. k = (n - 1) // 2
  2004. R = RisingFactorial(S.Half, k)
  2005. F = factorial(k)
  2006. return -R/F*x**n/n
  2007. def _eval_as_leading_term(self, x, logx, cdir):
  2008. arg = self.args[0]
  2009. x0 = arg.subs(x, 0).cancel()
  2010. if x0 is S.NaN:
  2011. return self.func(arg.as_leading_term(x))
  2012. # Handling branch points
  2013. if x0 == 1:
  2014. return sqrt(2)*sqrt((S.One - arg).as_leading_term(x))
  2015. if x0 in (-S.One, S.ComplexInfinity):
  2016. return self.rewrite(log)._eval_as_leading_term(x, logx=logx, cdir=cdir)
  2017. # Handling points lying on branch cuts (-oo, -1) U (1, oo)
  2018. if (1 - x0**2).is_negative:
  2019. ndir = arg.dir(x, cdir if cdir else 1)
  2020. if im(ndir).is_negative:
  2021. if x0.is_negative:
  2022. return 2*pi - self.func(x0)
  2023. elif im(ndir).is_positive:
  2024. if x0.is_positive:
  2025. return -self.func(x0)
  2026. else:
  2027. return self.rewrite(log)._eval_as_leading_term(x, logx=logx, cdir=cdir).expand()
  2028. return self.func(x0)
  2029. def _eval_is_extended_real(self):
  2030. x = self.args[0]
  2031. return x.is_extended_real and (1 - abs(x)).is_nonnegative
  2032. def _eval_is_nonnegative(self):
  2033. return self._eval_is_extended_real()
  2034. def _eval_nseries(self, x, n, logx, cdir=0): # acos
  2035. from sympy.series.order import O
  2036. arg0 = self.args[0].subs(x, 0)
  2037. # Handling branch points
  2038. if arg0 is S.One:
  2039. t = Dummy('t', positive=True)
  2040. ser = acos(S.One - t**2).rewrite(log).nseries(t, 0, 2*n)
  2041. arg1 = S.One - self.args[0]
  2042. f = arg1.as_leading_term(x)
  2043. g = (arg1 - f)/ f
  2044. if not g.is_meromorphic(x, 0): # cannot be expanded
  2045. return O(1) if n == 0 else O(sqrt(x))
  2046. res1 = sqrt(S.One + g)._eval_nseries(x, n=n, logx=logx)
  2047. res = (res1.removeO()*sqrt(f)).expand()
  2048. return ser.removeO().subs(t, res).expand().powsimp() + O(x**n, x)
  2049. if arg0 is S.NegativeOne:
  2050. t = Dummy('t', positive=True)
  2051. ser = acos(S.NegativeOne + t**2).rewrite(log).nseries(t, 0, 2*n)
  2052. arg1 = S.One + self.args[0]
  2053. f = arg1.as_leading_term(x)
  2054. g = (arg1 - f)/ f
  2055. if not g.is_meromorphic(x, 0): # cannot be expanded
  2056. return O(1) if n == 0 else pi + O(sqrt(x))
  2057. res1 = sqrt(S.One + g)._eval_nseries(x, n=n, logx=logx)
  2058. res = (res1.removeO()*sqrt(f)).expand()
  2059. return ser.removeO().subs(t, res).expand().powsimp() + O(x**n, x)
  2060. res = super()._eval_nseries(x, n=n, logx=logx)
  2061. if arg0 is S.ComplexInfinity:
  2062. return res
  2063. # Handling points lying on branch cuts (-oo, -1) U (1, oo)
  2064. if (1 - arg0**2).is_negative:
  2065. ndir = self.args[0].dir(x, cdir if cdir else 1)
  2066. if im(ndir).is_negative:
  2067. if arg0.is_negative:
  2068. return 2*pi - res
  2069. elif im(ndir).is_positive:
  2070. if arg0.is_positive:
  2071. return -res
  2072. else:
  2073. return self.rewrite(log)._eval_nseries(x, n, logx=logx, cdir=cdir)
  2074. return res
  2075. def _eval_rewrite_as_log(self, x, **kwargs):
  2076. return pi/2 + S.ImaginaryUnit*\
  2077. log(S.ImaginaryUnit*x + sqrt(1 - x**2))
  2078. _eval_rewrite_as_tractable = _eval_rewrite_as_log
  2079. def _eval_rewrite_as_asin(self, x, **kwargs):
  2080. return pi/2 - asin(x)
  2081. def _eval_rewrite_as_atan(self, x, **kwargs):
  2082. return atan(sqrt(1 - x**2)/x) + (pi/2)*(1 - x*sqrt(1/x**2))
  2083. def inverse(self, argindex=1):
  2084. """
  2085. Returns the inverse of this function.
  2086. """
  2087. return cos
  2088. def _eval_rewrite_as_acot(self, arg, **kwargs):
  2089. return pi/2 - 2*acot((1 + sqrt(1 - arg**2))/arg)
  2090. def _eval_rewrite_as_asec(self, arg, **kwargs):
  2091. return asec(1/arg)
  2092. def _eval_rewrite_as_acsc(self, arg, **kwargs):
  2093. return pi/2 - acsc(1/arg)
  2094. def _eval_conjugate(self):
  2095. z = self.args[0]
  2096. r = self.func(self.args[0].conjugate())
  2097. if z.is_extended_real is False:
  2098. return r
  2099. elif z.is_extended_real and (z + 1).is_nonnegative and (z - 1).is_nonpositive:
  2100. return r
  2101. class atan(InverseTrigonometricFunction):
  2102. r"""
  2103. The inverse tangent function.
  2104. Returns the arc tangent of x (measured in radians).
  2105. Explanation
  2106. ===========
  2107. ``atan(x)`` will evaluate automatically in the cases
  2108. $x \in \{\infty, -\infty, 0, 1, -1\}$ and for some instances when the
  2109. result is a rational multiple of $\pi$ (see the eval class method).
  2110. Examples
  2111. ========
  2112. >>> from sympy import atan, oo
  2113. >>> atan(0)
  2114. 0
  2115. >>> atan(1)
  2116. pi/4
  2117. >>> atan(oo)
  2118. pi/2
  2119. See Also
  2120. ========
  2121. sin, csc, cos, sec, tan, cot
  2122. asin, acsc, acos, asec, acot, atan2
  2123. References
  2124. ==========
  2125. .. [1] https://en.wikipedia.org/wiki/Inverse_trigonometric_functions
  2126. .. [2] https://dlmf.nist.gov/4.23
  2127. .. [3] https://functions.wolfram.com/ElementaryFunctions/ArcTan
  2128. """
  2129. args: tuple[Expr]
  2130. _singularities = (S.ImaginaryUnit, -S.ImaginaryUnit)
  2131. def fdiff(self, argindex=1):
  2132. if argindex == 1:
  2133. return 1/(1 + self.args[0]**2)
  2134. else:
  2135. raise ArgumentIndexError(self, argindex)
  2136. def _eval_is_rational(self):
  2137. s = self.func(*self.args)
  2138. if s.func == self.func:
  2139. if s.args[0].is_rational:
  2140. return False
  2141. else:
  2142. return s.is_rational
  2143. def _eval_is_positive(self):
  2144. return self.args[0].is_extended_positive
  2145. def _eval_is_nonnegative(self):
  2146. return self.args[0].is_extended_nonnegative
  2147. def _eval_is_zero(self):
  2148. return self.args[0].is_zero
  2149. def _eval_is_real(self):
  2150. return self.args[0].is_extended_real
  2151. @classmethod
  2152. def eval(cls, arg):
  2153. if arg.is_Number:
  2154. if arg is S.NaN:
  2155. return S.NaN
  2156. elif arg is S.Infinity:
  2157. return pi/2
  2158. elif arg is S.NegativeInfinity:
  2159. return -pi/2
  2160. elif arg.is_zero:
  2161. return S.Zero
  2162. elif arg is S.One:
  2163. return pi/4
  2164. elif arg is S.NegativeOne:
  2165. return -pi/4
  2166. if arg is S.ComplexInfinity:
  2167. from sympy.calculus.accumulationbounds import AccumBounds
  2168. return AccumBounds(-pi/2, pi/2)
  2169. if arg.could_extract_minus_sign():
  2170. return -cls(-arg)
  2171. if arg.is_number:
  2172. atan_table = cls._atan_table()
  2173. if arg in atan_table:
  2174. return atan_table[arg]
  2175. i_coeff = _imaginary_unit_as_coefficient(arg)
  2176. if i_coeff is not None:
  2177. from sympy.functions.elementary.hyperbolic import atanh
  2178. return S.ImaginaryUnit*atanh(i_coeff)
  2179. if arg.is_zero:
  2180. return S.Zero
  2181. if isinstance(arg, tan):
  2182. ang = arg.args[0]
  2183. if ang.is_comparable:
  2184. ang %= pi # restrict to [0,pi)
  2185. if ang > pi/2: # restrict to [-pi/2,pi/2]
  2186. ang -= pi
  2187. return ang
  2188. if isinstance(arg, cot): # atan(x) + acot(x) = pi/2
  2189. ang = arg.args[0]
  2190. if ang.is_comparable:
  2191. ang = pi/2 - acot(arg)
  2192. if ang > pi/2: # restrict to [-pi/2,pi/2]
  2193. ang -= pi
  2194. return ang
  2195. @staticmethod
  2196. @cacheit
  2197. def taylor_term(n, x, *previous_terms):
  2198. if n < 0 or n % 2 == 0:
  2199. return S.Zero
  2200. else:
  2201. x = sympify(x)
  2202. return S.NegativeOne**((n - 1)//2)*x**n/n
  2203. def _eval_as_leading_term(self, x, logx, cdir):
  2204. arg = self.args[0]
  2205. x0 = arg.subs(x, 0).cancel()
  2206. if x0 is S.NaN:
  2207. return self.func(arg.as_leading_term(x))
  2208. if x0.is_zero:
  2209. return arg.as_leading_term(x)
  2210. # Handling branch points
  2211. if x0 in (-S.ImaginaryUnit, S.ImaginaryUnit, S.ComplexInfinity):
  2212. return self.rewrite(log)._eval_as_leading_term(x, logx=logx, cdir=cdir).expand()
  2213. # Handling points lying on branch cuts (-I*oo, -I) U (I, I*oo)
  2214. if (1 + x0**2).is_negative:
  2215. ndir = arg.dir(x, cdir if cdir else 1)
  2216. if re(ndir).is_negative:
  2217. if im(x0).is_positive:
  2218. return self.func(x0) - pi
  2219. elif re(ndir).is_positive:
  2220. if im(x0).is_negative:
  2221. return self.func(x0) + pi
  2222. else:
  2223. return self.rewrite(log)._eval_as_leading_term(x, logx=logx, cdir=cdir).expand()
  2224. return self.func(x0)
  2225. def _eval_nseries(self, x, n, logx, cdir=0): # atan
  2226. arg0 = self.args[0].subs(x, 0)
  2227. # Handling branch points
  2228. if arg0 in (S.ImaginaryUnit, S.NegativeOne*S.ImaginaryUnit):
  2229. return self.rewrite(log)._eval_nseries(x, n, logx=logx, cdir=cdir)
  2230. res = super()._eval_nseries(x, n=n, logx=logx)
  2231. ndir = self.args[0].dir(x, cdir if cdir else 1)
  2232. if arg0 is S.ComplexInfinity:
  2233. if re(ndir) > 0:
  2234. return res - pi
  2235. return res
  2236. # Handling points lying on branch cuts (-I*oo, -I) U (I, I*oo)
  2237. if (1 + arg0**2).is_negative:
  2238. if re(ndir).is_negative:
  2239. if im(arg0).is_positive:
  2240. return res - pi
  2241. elif re(ndir).is_positive:
  2242. if im(arg0).is_negative:
  2243. return res + pi
  2244. else:
  2245. return self.rewrite(log)._eval_nseries(x, n, logx=logx, cdir=cdir)
  2246. return res
  2247. def _eval_rewrite_as_log(self, x, **kwargs):
  2248. return S.ImaginaryUnit/2*(log(S.One - S.ImaginaryUnit*x)
  2249. - log(S.One + S.ImaginaryUnit*x))
  2250. _eval_rewrite_as_tractable = _eval_rewrite_as_log
  2251. def _eval_aseries(self, n, args0, x, logx):
  2252. if args0[0] in [S.Infinity, S.NegativeInfinity]:
  2253. return (pi/2 - atan(1/self.args[0]))._eval_nseries(x, n, logx)
  2254. else:
  2255. return super()._eval_aseries(n, args0, x, logx)
  2256. def inverse(self, argindex=1):
  2257. """
  2258. Returns the inverse of this function.
  2259. """
  2260. return tan
  2261. def _eval_rewrite_as_asin(self, arg, **kwargs):
  2262. return sqrt(arg**2)/arg*(pi/2 - asin(1/sqrt(1 + arg**2)))
  2263. def _eval_rewrite_as_acos(self, arg, **kwargs):
  2264. return sqrt(arg**2)/arg*acos(1/sqrt(1 + arg**2))
  2265. def _eval_rewrite_as_acot(self, arg, **kwargs):
  2266. return acot(1/arg)
  2267. def _eval_rewrite_as_asec(self, arg, **kwargs):
  2268. return sqrt(arg**2)/arg*asec(sqrt(1 + arg**2))
  2269. def _eval_rewrite_as_acsc(self, arg, **kwargs):
  2270. return sqrt(arg**2)/arg*(pi/2 - acsc(sqrt(1 + arg**2)))
  2271. class acot(InverseTrigonometricFunction):
  2272. r"""
  2273. The inverse cotangent function.
  2274. Returns the arc cotangent of x (measured in radians).
  2275. Explanation
  2276. ===========
  2277. ``acot(x)`` will evaluate automatically in the cases
  2278. $x \in \{\infty, -\infty, \tilde{\infty}, 0, 1, -1\}$
  2279. and for some instances when the result is a rational multiple of $\pi$
  2280. (see the eval class method).
  2281. A purely imaginary argument will lead to an ``acoth`` expression.
  2282. ``acot(x)`` has a branch cut along $(-i, i)$, hence it is discontinuous
  2283. at 0. Its range for real $x$ is $(-\frac{\pi}{2}, \frac{\pi}{2}]$.
  2284. Examples
  2285. ========
  2286. >>> from sympy import acot, sqrt
  2287. >>> acot(0)
  2288. pi/2
  2289. >>> acot(1)
  2290. pi/4
  2291. >>> acot(sqrt(3) - 2)
  2292. -5*pi/12
  2293. See Also
  2294. ========
  2295. sin, csc, cos, sec, tan, cot
  2296. asin, acsc, acos, asec, atan, atan2
  2297. References
  2298. ==========
  2299. .. [1] https://dlmf.nist.gov/4.23
  2300. .. [2] https://functions.wolfram.com/ElementaryFunctions/ArcCot
  2301. """
  2302. _singularities = (S.ImaginaryUnit, -S.ImaginaryUnit)
  2303. def fdiff(self, argindex=1):
  2304. if argindex == 1:
  2305. return -1/(1 + self.args[0]**2)
  2306. else:
  2307. raise ArgumentIndexError(self, argindex)
  2308. def _eval_is_rational(self):
  2309. s = self.func(*self.args)
  2310. if s.func == self.func:
  2311. if s.args[0].is_rational:
  2312. return False
  2313. else:
  2314. return s.is_rational
  2315. def _eval_is_positive(self):
  2316. return self.args[0].is_nonnegative
  2317. def _eval_is_negative(self):
  2318. return self.args[0].is_negative
  2319. def _eval_is_extended_real(self):
  2320. return self.args[0].is_extended_real
  2321. @classmethod
  2322. def eval(cls, arg):
  2323. if arg.is_Number:
  2324. if arg is S.NaN:
  2325. return S.NaN
  2326. elif arg is S.Infinity:
  2327. return S.Zero
  2328. elif arg is S.NegativeInfinity:
  2329. return S.Zero
  2330. elif arg.is_zero:
  2331. return pi/ 2
  2332. elif arg is S.One:
  2333. return pi/4
  2334. elif arg is S.NegativeOne:
  2335. return -pi/4
  2336. if arg is S.ComplexInfinity:
  2337. return S.Zero
  2338. if arg.could_extract_minus_sign():
  2339. return -cls(-arg)
  2340. if arg.is_number:
  2341. atan_table = cls._atan_table()
  2342. if arg in atan_table:
  2343. ang = pi/2 - atan_table[arg]
  2344. if ang > pi/2: # restrict to (-pi/2,pi/2]
  2345. ang -= pi
  2346. return ang
  2347. i_coeff = _imaginary_unit_as_coefficient(arg)
  2348. if i_coeff is not None:
  2349. from sympy.functions.elementary.hyperbolic import acoth
  2350. return -S.ImaginaryUnit*acoth(i_coeff)
  2351. if arg.is_zero:
  2352. return pi*S.Half
  2353. if isinstance(arg, cot):
  2354. ang = arg.args[0]
  2355. if ang.is_comparable:
  2356. ang %= pi # restrict to [0,pi)
  2357. if ang > pi/2: # restrict to (-pi/2,pi/2]
  2358. ang -= pi
  2359. return ang
  2360. if isinstance(arg, tan): # atan(x) + acot(x) = pi/2
  2361. ang = arg.args[0]
  2362. if ang.is_comparable:
  2363. ang = pi/2 - atan(arg)
  2364. if ang > pi/2: # restrict to (-pi/2,pi/2]
  2365. ang -= pi
  2366. return ang
  2367. @staticmethod
  2368. @cacheit
  2369. def taylor_term(n, x, *previous_terms):
  2370. if n == 0:
  2371. return pi/2 # FIX THIS
  2372. elif n < 0 or n % 2 == 0:
  2373. return S.Zero
  2374. else:
  2375. x = sympify(x)
  2376. return S.NegativeOne**((n + 1)//2)*x**n/n
  2377. def _eval_as_leading_term(self, x, logx, cdir):
  2378. arg = self.args[0]
  2379. x0 = arg.subs(x, 0).cancel()
  2380. if x0 is S.NaN:
  2381. return self.func(arg.as_leading_term(x))
  2382. if x0 is S.ComplexInfinity:
  2383. return (1/arg).as_leading_term(x)
  2384. # Handling branch points
  2385. if x0 in (-S.ImaginaryUnit, S.ImaginaryUnit, S.Zero):
  2386. return self.rewrite(log)._eval_as_leading_term(x, logx=logx, cdir=cdir).expand()
  2387. # Handling points lying on branch cuts [-I, I]
  2388. if x0.is_imaginary and (1 + x0**2).is_positive:
  2389. ndir = arg.dir(x, cdir if cdir else 1)
  2390. if re(ndir).is_positive:
  2391. if im(x0).is_positive:
  2392. return self.func(x0) + pi
  2393. elif re(ndir).is_negative:
  2394. if im(x0).is_negative:
  2395. return self.func(x0) - pi
  2396. else:
  2397. return self.rewrite(log)._eval_as_leading_term(x, logx=logx, cdir=cdir).expand()
  2398. return self.func(x0)
  2399. def _eval_nseries(self, x, n, logx, cdir=0): # acot
  2400. arg0 = self.args[0].subs(x, 0)
  2401. # Handling branch points
  2402. if arg0 in (S.ImaginaryUnit, S.NegativeOne*S.ImaginaryUnit):
  2403. return self.rewrite(log)._eval_nseries(x, n, logx=logx, cdir=cdir)
  2404. res = super()._eval_nseries(x, n=n, logx=logx)
  2405. if arg0 is S.ComplexInfinity:
  2406. return res
  2407. ndir = self.args[0].dir(x, cdir if cdir else 1)
  2408. if arg0.is_zero:
  2409. if re(ndir) < 0:
  2410. return res - pi
  2411. return res
  2412. # Handling points lying on branch cuts [-I, I]
  2413. if arg0.is_imaginary and (1 + arg0**2).is_positive:
  2414. if re(ndir).is_positive:
  2415. if im(arg0).is_positive:
  2416. return res + pi
  2417. elif re(ndir).is_negative:
  2418. if im(arg0).is_negative:
  2419. return res - pi
  2420. else:
  2421. return self.rewrite(log)._eval_nseries(x, n, logx=logx, cdir=cdir)
  2422. return res
  2423. def _eval_aseries(self, n, args0, x, logx):
  2424. if args0[0] in [S.Infinity, S.NegativeInfinity]:
  2425. return atan(1/self.args[0])._eval_nseries(x, n, logx)
  2426. else:
  2427. return super()._eval_aseries(n, args0, x, logx)
  2428. def _eval_rewrite_as_log(self, x, **kwargs):
  2429. return S.ImaginaryUnit/2*(log(1 - S.ImaginaryUnit/x)
  2430. - log(1 + S.ImaginaryUnit/x))
  2431. _eval_rewrite_as_tractable = _eval_rewrite_as_log
  2432. def inverse(self, argindex=1):
  2433. """
  2434. Returns the inverse of this function.
  2435. """
  2436. return cot
  2437. def _eval_rewrite_as_asin(self, arg, **kwargs):
  2438. return (arg*sqrt(1/arg**2)*
  2439. (pi/2 - asin(sqrt(-arg**2)/sqrt(-arg**2 - 1))))
  2440. def _eval_rewrite_as_acos(self, arg, **kwargs):
  2441. return arg*sqrt(1/arg**2)*acos(sqrt(-arg**2)/sqrt(-arg**2 - 1))
  2442. def _eval_rewrite_as_atan(self, arg, **kwargs):
  2443. return atan(1/arg)
  2444. def _eval_rewrite_as_asec(self, arg, **kwargs):
  2445. return arg*sqrt(1/arg**2)*asec(sqrt((1 + arg**2)/arg**2))
  2446. def _eval_rewrite_as_acsc(self, arg, **kwargs):
  2447. return arg*sqrt(1/arg**2)*(pi/2 - acsc(sqrt((1 + arg**2)/arg**2)))
  2448. class asec(InverseTrigonometricFunction):
  2449. r"""
  2450. The inverse secant function.
  2451. Returns the arc secant of x (measured in radians).
  2452. Explanation
  2453. ===========
  2454. ``asec(x)`` will evaluate automatically in the cases
  2455. $x \in \{\infty, -\infty, 0, 1, -1\}$ and for some instances when the
  2456. result is a rational multiple of $\pi$ (see the eval class method).
  2457. ``asec(x)`` has branch cut in the interval $[-1, 1]$. For complex arguments,
  2458. it can be defined [4]_ as
  2459. .. math::
  2460. \operatorname{sec^{-1}}(z) = -i\frac{\log\left(\sqrt{1 - z^2} + 1\right)}{z}
  2461. At ``x = 0``, for positive branch cut, the limit evaluates to ``zoo``. For
  2462. negative branch cut, the limit
  2463. .. math::
  2464. \lim_{z \to 0}-i\frac{\log\left(-\sqrt{1 - z^2} + 1\right)}{z}
  2465. simplifies to :math:`-i\log\left(z/2 + O\left(z^3\right)\right)` which
  2466. ultimately evaluates to ``zoo``.
  2467. As ``acos(x) = asec(1/x)``, a similar argument can be given for
  2468. ``acos(x)``.
  2469. Examples
  2470. ========
  2471. >>> from sympy import asec, oo
  2472. >>> asec(1)
  2473. 0
  2474. >>> asec(-1)
  2475. pi
  2476. >>> asec(0)
  2477. zoo
  2478. >>> asec(-oo)
  2479. pi/2
  2480. See Also
  2481. ========
  2482. sin, csc, cos, sec, tan, cot
  2483. asin, acsc, acos, atan, acot, atan2
  2484. References
  2485. ==========
  2486. .. [1] https://en.wikipedia.org/wiki/Inverse_trigonometric_functions
  2487. .. [2] https://dlmf.nist.gov/4.23
  2488. .. [3] https://functions.wolfram.com/ElementaryFunctions/ArcSec
  2489. .. [4] https://reference.wolfram.com/language/ref/ArcSec.html
  2490. """
  2491. @classmethod
  2492. def eval(cls, arg):
  2493. if arg.is_zero:
  2494. return S.ComplexInfinity
  2495. if arg.is_Number:
  2496. if arg is S.NaN:
  2497. return S.NaN
  2498. elif arg is S.One:
  2499. return S.Zero
  2500. elif arg is S.NegativeOne:
  2501. return pi
  2502. if arg in [S.Infinity, S.NegativeInfinity, S.ComplexInfinity]:
  2503. return pi/2
  2504. if arg.is_number:
  2505. acsc_table = cls._acsc_table()
  2506. if arg in acsc_table:
  2507. return pi/2 - acsc_table[arg]
  2508. elif -arg in acsc_table:
  2509. return pi/2 + acsc_table[-arg]
  2510. if arg.is_infinite:
  2511. return pi/2
  2512. if arg.is_Mul and len(arg.args) == 2 and arg.args[0] == -1:
  2513. narg = arg.args[1]
  2514. minus = True
  2515. else:
  2516. narg = arg
  2517. minus = False
  2518. if isinstance(narg, sec):
  2519. # asec(sec(x)) = x or asec(-sec(x)) = pi - x
  2520. ang = narg.args[0]
  2521. if ang.is_comparable:
  2522. if minus:
  2523. ang = pi - ang
  2524. ang %= 2*pi # restrict to [0,2*pi)
  2525. if ang > pi: # restrict to [0,pi]
  2526. ang = 2*pi - ang
  2527. return ang
  2528. if isinstance(narg, csc): # asec(x) + acsc(x) = pi/2
  2529. ang = narg.args[0]
  2530. if ang.is_comparable:
  2531. if minus:
  2532. pi/2 + acsc(narg)
  2533. return pi/2 - acsc(narg)
  2534. def fdiff(self, argindex=1):
  2535. if argindex == 1:
  2536. return 1/(self.args[0]**2*sqrt(1 - 1/self.args[0]**2))
  2537. else:
  2538. raise ArgumentIndexError(self, argindex)
  2539. def inverse(self, argindex=1):
  2540. """
  2541. Returns the inverse of this function.
  2542. """
  2543. return sec
  2544. @staticmethod
  2545. @cacheit
  2546. def taylor_term(n, x, *previous_terms):
  2547. if n == 0:
  2548. return S.ImaginaryUnit*log(2 / x)
  2549. elif n < 0 or n % 2 == 1:
  2550. return S.Zero
  2551. else:
  2552. x = sympify(x)
  2553. if len(previous_terms) > 2 and n > 2:
  2554. p = previous_terms[-2]
  2555. return p * ((n - 1)*(n-2)) * x**2/(4 * (n//2)**2)
  2556. else:
  2557. k = n // 2
  2558. R = RisingFactorial(S.Half, k) * n
  2559. F = factorial(k) * n // 2 * n // 2
  2560. return -S.ImaginaryUnit * R / F * x**n / 4
  2561. def _eval_as_leading_term(self, x, logx, cdir):
  2562. arg = self.args[0]
  2563. x0 = arg.subs(x, 0).cancel()
  2564. if x0 is S.NaN:
  2565. return self.func(arg.as_leading_term(x))
  2566. # Handling branch points
  2567. if x0 == 1:
  2568. return sqrt(2)*sqrt((arg - S.One).as_leading_term(x))
  2569. if x0 in (-S.One, S.Zero):
  2570. return self.rewrite(log)._eval_as_leading_term(x, logx=logx, cdir=cdir)
  2571. # Handling points lying on branch cuts (-1, 1)
  2572. if x0.is_real and (1 - x0**2).is_positive:
  2573. ndir = arg.dir(x, cdir if cdir else 1)
  2574. if im(ndir).is_negative:
  2575. if x0.is_positive:
  2576. return -self.func(x0)
  2577. elif im(ndir).is_positive:
  2578. if x0.is_negative:
  2579. return 2*pi - self.func(x0)
  2580. else:
  2581. return self.rewrite(log)._eval_as_leading_term(x, logx=logx, cdir=cdir).expand()
  2582. return self.func(x0)
  2583. def _eval_nseries(self, x, n, logx, cdir=0): # asec
  2584. from sympy.series.order import O
  2585. arg0 = self.args[0].subs(x, 0)
  2586. # Handling branch points
  2587. if arg0 is S.One:
  2588. t = Dummy('t', positive=True)
  2589. ser = asec(S.One + t**2).rewrite(log).nseries(t, 0, 2*n)
  2590. arg1 = S.NegativeOne + self.args[0]
  2591. f = arg1.as_leading_term(x)
  2592. g = (arg1 - f)/ f
  2593. res1 = sqrt(S.One + g)._eval_nseries(x, n=n, logx=logx)
  2594. res = (res1.removeO()*sqrt(f)).expand()
  2595. return ser.removeO().subs(t, res).expand().powsimp() + O(x**n, x)
  2596. if arg0 is S.NegativeOne:
  2597. t = Dummy('t', positive=True)
  2598. ser = asec(S.NegativeOne - t**2).rewrite(log).nseries(t, 0, 2*n)
  2599. arg1 = S.NegativeOne - self.args[0]
  2600. f = arg1.as_leading_term(x)
  2601. g = (arg1 - f)/ f
  2602. res1 = sqrt(S.One + g)._eval_nseries(x, n=n, logx=logx)
  2603. res = (res1.removeO()*sqrt(f)).expand()
  2604. return ser.removeO().subs(t, res).expand().powsimp() + O(x**n, x)
  2605. res = super()._eval_nseries(x, n=n, logx=logx)
  2606. if arg0 is S.ComplexInfinity:
  2607. return res
  2608. # Handling points lying on branch cuts (-1, 1)
  2609. if arg0.is_real and (1 - arg0**2).is_positive:
  2610. ndir = self.args[0].dir(x, cdir if cdir else 1)
  2611. if im(ndir).is_negative:
  2612. if arg0.is_positive:
  2613. return -res
  2614. elif im(ndir).is_positive:
  2615. if arg0.is_negative:
  2616. return 2*pi - res
  2617. else:
  2618. return self.rewrite(log)._eval_nseries(x, n, logx=logx, cdir=cdir)
  2619. return res
  2620. def _eval_is_extended_real(self):
  2621. x = self.args[0]
  2622. if x.is_extended_real is False:
  2623. return False
  2624. return fuzzy_or(((x - 1).is_nonnegative, (-x - 1).is_nonnegative))
  2625. def _eval_rewrite_as_log(self, arg, **kwargs):
  2626. return pi/2 + S.ImaginaryUnit*log(S.ImaginaryUnit/arg + sqrt(1 - 1/arg**2))
  2627. _eval_rewrite_as_tractable = _eval_rewrite_as_log
  2628. def _eval_rewrite_as_asin(self, arg, **kwargs):
  2629. return pi/2 - asin(1/arg)
  2630. def _eval_rewrite_as_acos(self, arg, **kwargs):
  2631. return acos(1/arg)
  2632. def _eval_rewrite_as_atan(self, x, **kwargs):
  2633. sx2x = sqrt(x**2)/x
  2634. return pi/2*(1 - sx2x) + sx2x*atan(sqrt(x**2 - 1))
  2635. def _eval_rewrite_as_acot(self, x, **kwargs):
  2636. sx2x = sqrt(x**2)/x
  2637. return pi/2*(1 - sx2x) + sx2x*acot(1/sqrt(x**2 - 1))
  2638. def _eval_rewrite_as_acsc(self, arg, **kwargs):
  2639. return pi/2 - acsc(arg)
  2640. class acsc(InverseTrigonometricFunction):
  2641. r"""
  2642. The inverse cosecant function.
  2643. Returns the arc cosecant of x (measured in radians).
  2644. Explanation
  2645. ===========
  2646. ``acsc(x)`` will evaluate automatically in the cases
  2647. $x \in \{\infty, -\infty, 0, 1, -1\}$` and for some instances when the
  2648. result is a rational multiple of $\pi$ (see the ``eval`` class method).
  2649. Examples
  2650. ========
  2651. >>> from sympy import acsc, oo
  2652. >>> acsc(1)
  2653. pi/2
  2654. >>> acsc(-1)
  2655. -pi/2
  2656. >>> acsc(oo)
  2657. 0
  2658. >>> acsc(-oo) == acsc(oo)
  2659. True
  2660. >>> acsc(0)
  2661. zoo
  2662. See Also
  2663. ========
  2664. sin, csc, cos, sec, tan, cot
  2665. asin, acos, asec, atan, acot, atan2
  2666. References
  2667. ==========
  2668. .. [1] https://en.wikipedia.org/wiki/Inverse_trigonometric_functions
  2669. .. [2] https://dlmf.nist.gov/4.23
  2670. .. [3] https://functions.wolfram.com/ElementaryFunctions/ArcCsc
  2671. """
  2672. @classmethod
  2673. def eval(cls, arg):
  2674. if arg.is_zero:
  2675. return S.ComplexInfinity
  2676. if arg.is_Number:
  2677. if arg is S.NaN:
  2678. return S.NaN
  2679. elif arg is S.One:
  2680. return pi/2
  2681. elif arg is S.NegativeOne:
  2682. return -pi/2
  2683. if arg in [S.Infinity, S.NegativeInfinity, S.ComplexInfinity]:
  2684. return S.Zero
  2685. if arg.could_extract_minus_sign():
  2686. return -cls(-arg)
  2687. if arg.is_infinite:
  2688. return S.Zero
  2689. if arg.is_number:
  2690. acsc_table = cls._acsc_table()
  2691. if arg in acsc_table:
  2692. return acsc_table[arg]
  2693. if isinstance(arg, csc):
  2694. ang = arg.args[0]
  2695. if ang.is_comparable:
  2696. ang %= 2*pi # restrict to [0,2*pi)
  2697. if ang > pi: # restrict to (-pi,pi]
  2698. ang = pi - ang
  2699. # restrict to [-pi/2,pi/2]
  2700. if ang > pi/2:
  2701. ang = pi - ang
  2702. if ang < -pi/2:
  2703. ang = -pi - ang
  2704. return ang
  2705. if isinstance(arg, sec): # asec(x) + acsc(x) = pi/2
  2706. ang = arg.args[0]
  2707. if ang.is_comparable:
  2708. return pi/2 - asec(arg)
  2709. def fdiff(self, argindex=1):
  2710. if argindex == 1:
  2711. return -1/(self.args[0]**2*sqrt(1 - 1/self.args[0]**2))
  2712. else:
  2713. raise ArgumentIndexError(self, argindex)
  2714. def inverse(self, argindex=1):
  2715. """
  2716. Returns the inverse of this function.
  2717. """
  2718. return csc
  2719. @staticmethod
  2720. @cacheit
  2721. def taylor_term(n, x, *previous_terms):
  2722. if n == 0:
  2723. return pi/2 - S.ImaginaryUnit*log(2) + S.ImaginaryUnit*log(x)
  2724. elif n < 0 or n % 2 == 1:
  2725. return S.Zero
  2726. else:
  2727. x = sympify(x)
  2728. if len(previous_terms) > 2 and n > 2:
  2729. p = previous_terms[-2]
  2730. return p * ((n - 1)*(n-2)) * x**2/(4 * (n//2)**2)
  2731. else:
  2732. k = n // 2
  2733. R = RisingFactorial(S.Half, k) * n
  2734. F = factorial(k) * n // 2 * n // 2
  2735. return S.ImaginaryUnit * R / F * x**n / 4
  2736. def _eval_as_leading_term(self, x, logx, cdir):
  2737. arg = self.args[0]
  2738. x0 = arg.subs(x, 0).cancel()
  2739. if x0 is S.NaN:
  2740. return self.func(arg.as_leading_term(x))
  2741. # Handling branch points
  2742. if x0 in (-S.One, S.One, S.Zero):
  2743. return self.rewrite(log)._eval_as_leading_term(x, logx=logx, cdir=cdir).expand()
  2744. if x0 is S.ComplexInfinity:
  2745. return (1/arg).as_leading_term(x)
  2746. # Handling points lying on branch cuts (-1, 1)
  2747. if x0.is_real and (1 - x0**2).is_positive:
  2748. ndir = arg.dir(x, cdir if cdir else 1)
  2749. if im(ndir).is_negative:
  2750. if x0.is_positive:
  2751. return pi - self.func(x0)
  2752. elif im(ndir).is_positive:
  2753. if x0.is_negative:
  2754. return -pi - self.func(x0)
  2755. else:
  2756. return self.rewrite(log)._eval_as_leading_term(x, logx=logx, cdir=cdir).expand()
  2757. return self.func(x0)
  2758. def _eval_nseries(self, x, n, logx, cdir=0): # acsc
  2759. from sympy.series.order import O
  2760. arg0 = self.args[0].subs(x, 0)
  2761. # Handling branch points
  2762. if arg0 is S.One:
  2763. t = Dummy('t', positive=True)
  2764. ser = acsc(S.One + t**2).rewrite(log).nseries(t, 0, 2*n)
  2765. arg1 = S.NegativeOne + self.args[0]
  2766. f = arg1.as_leading_term(x)
  2767. g = (arg1 - f)/ f
  2768. res1 = sqrt(S.One + g)._eval_nseries(x, n=n, logx=logx)
  2769. res = (res1.removeO()*sqrt(f)).expand()
  2770. return ser.removeO().subs(t, res).expand().powsimp() + O(x**n, x)
  2771. if arg0 is S.NegativeOne:
  2772. t = Dummy('t', positive=True)
  2773. ser = acsc(S.NegativeOne - t**2).rewrite(log).nseries(t, 0, 2*n)
  2774. arg1 = S.NegativeOne - self.args[0]
  2775. f = arg1.as_leading_term(x)
  2776. g = (arg1 - f)/ f
  2777. res1 = sqrt(S.One + g)._eval_nseries(x, n=n, logx=logx)
  2778. res = (res1.removeO()*sqrt(f)).expand()
  2779. return ser.removeO().subs(t, res).expand().powsimp() + O(x**n, x)
  2780. res = super()._eval_nseries(x, n=n, logx=logx)
  2781. if arg0 is S.ComplexInfinity:
  2782. return res
  2783. # Handling points lying on branch cuts (-1, 1)
  2784. if arg0.is_real and (1 - arg0**2).is_positive:
  2785. ndir = self.args[0].dir(x, cdir if cdir else 1)
  2786. if im(ndir).is_negative:
  2787. if arg0.is_positive:
  2788. return pi - res
  2789. elif im(ndir).is_positive:
  2790. if arg0.is_negative:
  2791. return -pi - res
  2792. else:
  2793. return self.rewrite(log)._eval_nseries(x, n, logx=logx, cdir=cdir)
  2794. return res
  2795. def _eval_rewrite_as_log(self, arg, **kwargs):
  2796. return -S.ImaginaryUnit*log(S.ImaginaryUnit/arg + sqrt(1 - 1/arg**2))
  2797. _eval_rewrite_as_tractable = _eval_rewrite_as_log
  2798. def _eval_rewrite_as_asin(self, arg, **kwargs):
  2799. return asin(1/arg)
  2800. def _eval_rewrite_as_acos(self, arg, **kwargs):
  2801. return pi/2 - acos(1/arg)
  2802. def _eval_rewrite_as_atan(self, x, **kwargs):
  2803. return sqrt(x**2)/x*(pi/2 - atan(sqrt(x**2 - 1)))
  2804. def _eval_rewrite_as_acot(self, arg, **kwargs):
  2805. return sqrt(arg**2)/arg*(pi/2 - acot(1/sqrt(arg**2 - 1)))
  2806. def _eval_rewrite_as_asec(self, arg, **kwargs):
  2807. return pi/2 - asec(arg)
  2808. class atan2(InverseTrigonometricFunction):
  2809. r"""
  2810. The function ``atan2(y, x)`` computes `\operatorname{atan}(y/x)` taking
  2811. two arguments `y` and `x`. Signs of both `y` and `x` are considered to
  2812. determine the appropriate quadrant of `\operatorname{atan}(y/x)`.
  2813. The range is `(-\pi, \pi]`. The complete definition reads as follows:
  2814. .. math::
  2815. \operatorname{atan2}(y, x) =
  2816. \begin{cases}
  2817. \arctan\left(\frac y x\right) & \qquad x > 0 \\
  2818. \arctan\left(\frac y x\right) + \pi& \qquad y \ge 0, x < 0 \\
  2819. \arctan\left(\frac y x\right) - \pi& \qquad y < 0, x < 0 \\
  2820. +\frac{\pi}{2} & \qquad y > 0, x = 0 \\
  2821. -\frac{\pi}{2} & \qquad y < 0, x = 0 \\
  2822. \text{undefined} & \qquad y = 0, x = 0
  2823. \end{cases}
  2824. Attention: Note the role reversal of both arguments. The `y`-coordinate
  2825. is the first argument and the `x`-coordinate the second.
  2826. If either `x` or `y` is complex:
  2827. .. math::
  2828. \operatorname{atan2}(y, x) =
  2829. -i\log\left(\frac{x + iy}{\sqrt{x^2 + y^2}}\right)
  2830. Examples
  2831. ========
  2832. Going counter-clock wise around the origin we find the
  2833. following angles:
  2834. >>> from sympy import atan2
  2835. >>> atan2(0, 1)
  2836. 0
  2837. >>> atan2(1, 1)
  2838. pi/4
  2839. >>> atan2(1, 0)
  2840. pi/2
  2841. >>> atan2(1, -1)
  2842. 3*pi/4
  2843. >>> atan2(0, -1)
  2844. pi
  2845. >>> atan2(-1, -1)
  2846. -3*pi/4
  2847. >>> atan2(-1, 0)
  2848. -pi/2
  2849. >>> atan2(-1, 1)
  2850. -pi/4
  2851. which are all correct. Compare this to the results of the ordinary
  2852. `\operatorname{atan}` function for the point `(x, y) = (-1, 1)`
  2853. >>> from sympy import atan, S
  2854. >>> atan(S(1)/-1)
  2855. -pi/4
  2856. >>> atan2(1, -1)
  2857. 3*pi/4
  2858. where only the `\operatorname{atan2}` function returns what we expect.
  2859. We can differentiate the function with respect to both arguments:
  2860. >>> from sympy import diff
  2861. >>> from sympy.abc import x, y
  2862. >>> diff(atan2(y, x), x)
  2863. -y/(x**2 + y**2)
  2864. >>> diff(atan2(y, x), y)
  2865. x/(x**2 + y**2)
  2866. We can express the `\operatorname{atan2}` function in terms of
  2867. complex logarithms:
  2868. >>> from sympy import log
  2869. >>> atan2(y, x).rewrite(log)
  2870. -I*log((x + I*y)/sqrt(x**2 + y**2))
  2871. and in terms of `\operatorname(atan)`:
  2872. >>> from sympy import atan
  2873. >>> atan2(y, x).rewrite(atan)
  2874. Piecewise((2*atan(y/(x + sqrt(x**2 + y**2))), Ne(y, 0)), (pi, re(x) < 0), (0, Ne(x, 0)), (nan, True))
  2875. but note that this form is undefined on the negative real axis.
  2876. See Also
  2877. ========
  2878. sin, csc, cos, sec, tan, cot
  2879. asin, acsc, acos, asec, atan, acot
  2880. References
  2881. ==========
  2882. .. [1] https://en.wikipedia.org/wiki/Inverse_trigonometric_functions
  2883. .. [2] https://en.wikipedia.org/wiki/Atan2
  2884. .. [3] https://functions.wolfram.com/ElementaryFunctions/ArcTan2
  2885. """
  2886. @classmethod
  2887. def eval(cls, y, x):
  2888. from sympy.functions.special.delta_functions import Heaviside
  2889. if x is S.NegativeInfinity:
  2890. if y.is_zero:
  2891. # Special case y = 0 because we define Heaviside(0) = 1/2
  2892. return pi
  2893. return 2*pi*(Heaviside(re(y))) - pi
  2894. elif x is S.Infinity:
  2895. return S.Zero
  2896. elif x.is_imaginary and y.is_imaginary and x.is_number and y.is_number:
  2897. x = im(x)
  2898. y = im(y)
  2899. if x.is_extended_real and y.is_extended_real:
  2900. if x.is_positive:
  2901. return atan(y/x)
  2902. elif x.is_negative:
  2903. if y.is_negative:
  2904. return atan(y/x) - pi
  2905. elif y.is_nonnegative:
  2906. return atan(y/x) + pi
  2907. elif x.is_zero:
  2908. if y.is_positive:
  2909. return pi/2
  2910. elif y.is_negative:
  2911. return -pi/2
  2912. elif y.is_zero:
  2913. return S.NaN
  2914. if y.is_zero:
  2915. if x.is_extended_nonzero:
  2916. return pi*(S.One - Heaviside(x))
  2917. if x.is_number:
  2918. return Piecewise((pi, re(x) < 0),
  2919. (0, Ne(x, 0)),
  2920. (S.NaN, True))
  2921. if x.is_number and y.is_number:
  2922. return -S.ImaginaryUnit*log(
  2923. (x + S.ImaginaryUnit*y)/sqrt(x**2 + y**2))
  2924. def _eval_rewrite_as_log(self, y, x, **kwargs):
  2925. return -S.ImaginaryUnit*log((x + S.ImaginaryUnit*y)/sqrt(x**2 + y**2))
  2926. def _eval_rewrite_as_atan(self, y, x, **kwargs):
  2927. return Piecewise((2*atan(y/(x + sqrt(x**2 + y**2))), Ne(y, 0)),
  2928. (pi, re(x) < 0),
  2929. (0, Ne(x, 0)),
  2930. (S.NaN, True))
  2931. def _eval_rewrite_as_arg(self, y, x, **kwargs):
  2932. if x.is_extended_real and y.is_extended_real:
  2933. return arg_f(x + y*S.ImaginaryUnit)
  2934. n = x + S.ImaginaryUnit*y
  2935. d = x**2 + y**2
  2936. return arg_f(n/sqrt(d)) - S.ImaginaryUnit*log(abs(n)/sqrt(abs(d)))
  2937. def _eval_is_extended_real(self):
  2938. return self.args[0].is_extended_real and self.args[1].is_extended_real
  2939. def _eval_conjugate(self):
  2940. return self.func(self.args[0].conjugate(), self.args[1].conjugate())
  2941. def fdiff(self, argindex):
  2942. y, x = self.args
  2943. if argindex == 1:
  2944. # Diff wrt y
  2945. return x/(x**2 + y**2)
  2946. elif argindex == 2:
  2947. # Diff wrt x
  2948. return -y/(x**2 + y**2)
  2949. else:
  2950. raise ArgumentIndexError(self, argindex)
  2951. def _eval_evalf(self, prec):
  2952. y, x = self.args
  2953. if x.is_extended_real and y.is_extended_real:
  2954. return super()._eval_evalf(prec)