elliptic.py 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431
  1. r"""
  2. Elliptic functions historically comprise the elliptic integrals
  3. and their inverses, and originate from the problem of computing the
  4. arc length of an ellipse. From a more modern point of view,
  5. an elliptic function is defined as a doubly periodic function, i.e.
  6. a function which satisfies
  7. .. math ::
  8. f(z + 2 \omega_1) = f(z + 2 \omega_2) = f(z)
  9. for some half-periods `\omega_1, \omega_2` with
  10. `\mathrm{Im}[\omega_1 / \omega_2] > 0`. The canonical elliptic
  11. functions are the Jacobi elliptic functions. More broadly, this section
  12. includes quasi-doubly periodic functions (such as the Jacobi theta
  13. functions) and other functions useful in the study of elliptic functions.
  14. Many different conventions for the arguments of
  15. elliptic functions are in use. It is even standard to use
  16. different parameterizations for different functions in the same
  17. text or software (and mpmath is no exception).
  18. The usual parameters are the elliptic nome `q`, which usually
  19. must satisfy `|q| < 1`; the elliptic parameter `m` (an arbitrary
  20. complex number); the elliptic modulus `k` (an arbitrary complex
  21. number); and the half-period ratio `\tau`, which usually must
  22. satisfy `\mathrm{Im}[\tau] > 0`.
  23. These quantities can be expressed in terms of each other
  24. using the following relations:
  25. .. math ::
  26. m = k^2
  27. .. math ::
  28. \tau = i \frac{K(1-m)}{K(m)}
  29. .. math ::
  30. q = e^{i \pi \tau}
  31. .. math ::
  32. k = \frac{\vartheta_2^2(q)}{\vartheta_3^2(q)}
  33. In addition, an alternative definition is used for the nome in
  34. number theory, which we here denote by q-bar:
  35. .. math ::
  36. \bar{q} = q^2 = e^{2 i \pi \tau}
  37. For convenience, mpmath provides functions to convert
  38. between the various parameters (:func:`~mpmath.qfrom`, :func:`~mpmath.mfrom`,
  39. :func:`~mpmath.kfrom`, :func:`~mpmath.taufrom`, :func:`~mpmath.qbarfrom`).
  40. **References**
  41. 1. [AbramowitzStegun]_
  42. 2. [WhittakerWatson]_
  43. """
  44. from .functions import defun, defun_wrapped
  45. @defun_wrapped
  46. def eta(ctx, tau):
  47. r"""
  48. Returns the Dedekind eta function of tau in the upper half-plane.
  49. >>> from mpmath import *
  50. >>> mp.dps = 25; mp.pretty = True
  51. >>> eta(1j); gamma(0.25) / (2*pi**0.75)
  52. (0.7682254223260566590025942 + 0.0j)
  53. 0.7682254223260566590025942
  54. >>> tau = sqrt(2) + sqrt(5)*1j
  55. >>> eta(-1/tau); sqrt(-1j*tau) * eta(tau)
  56. (0.9022859908439376463573294 + 0.07985093673948098408048575j)
  57. (0.9022859908439376463573295 + 0.07985093673948098408048575j)
  58. >>> eta(tau+1); exp(pi*1j/12) * eta(tau)
  59. (0.4493066139717553786223114 + 0.3290014793877986663915939j)
  60. (0.4493066139717553786223114 + 0.3290014793877986663915939j)
  61. >>> f = lambda z: diff(eta, z) / eta(z)
  62. >>> chop(36*diff(f,tau)**2 - 24*diff(f,tau,2)*f(tau) + diff(f,tau,3))
  63. 0.0
  64. """
  65. if ctx.im(tau) <= 0.0:
  66. raise ValueError("eta is only defined in the upper half-plane")
  67. q = ctx.expjpi(tau/12)
  68. return q * ctx.qp(q**24)
  69. def nome(ctx, m):
  70. m = ctx.convert(m)
  71. if not m:
  72. return m
  73. if m == ctx.one:
  74. return m
  75. if ctx.isnan(m):
  76. return m
  77. if ctx.isinf(m):
  78. if m == ctx.ninf:
  79. return type(m)(-1)
  80. else:
  81. return ctx.mpc(-1)
  82. a = ctx.ellipk(ctx.one-m)
  83. b = ctx.ellipk(m)
  84. v = ctx.exp(-ctx.pi*a/b)
  85. if not ctx._im(m) and ctx._re(m) < 1:
  86. if ctx._is_real_type(m):
  87. return v.real
  88. else:
  89. return v.real + 0j
  90. elif m == 2:
  91. v = ctx.mpc(0, v.imag)
  92. return v
  93. @defun_wrapped
  94. def qfrom(ctx, q=None, m=None, k=None, tau=None, qbar=None):
  95. r"""
  96. Returns the elliptic nome `q`, given any of `q, m, k, \tau, \bar{q}`::
  97. >>> from mpmath import *
  98. >>> mp.dps = 25; mp.pretty = True
  99. >>> qfrom(q=0.25)
  100. 0.25
  101. >>> qfrom(m=mfrom(q=0.25))
  102. 0.25
  103. >>> qfrom(k=kfrom(q=0.25))
  104. 0.25
  105. >>> qfrom(tau=taufrom(q=0.25))
  106. (0.25 + 0.0j)
  107. >>> qfrom(qbar=qbarfrom(q=0.25))
  108. 0.25
  109. """
  110. if q is not None:
  111. return ctx.convert(q)
  112. if m is not None:
  113. return nome(ctx, m)
  114. if k is not None:
  115. return nome(ctx, ctx.convert(k)**2)
  116. if tau is not None:
  117. return ctx.expjpi(tau)
  118. if qbar is not None:
  119. return ctx.sqrt(qbar)
  120. @defun_wrapped
  121. def qbarfrom(ctx, q=None, m=None, k=None, tau=None, qbar=None):
  122. r"""
  123. Returns the number-theoretic nome `\bar q`, given any of
  124. `q, m, k, \tau, \bar{q}`::
  125. >>> from mpmath import *
  126. >>> mp.dps = 25; mp.pretty = True
  127. >>> qbarfrom(qbar=0.25)
  128. 0.25
  129. >>> qbarfrom(q=qfrom(qbar=0.25))
  130. 0.25
  131. >>> qbarfrom(m=extraprec(20)(mfrom)(qbar=0.25)) # ill-conditioned
  132. 0.25
  133. >>> qbarfrom(k=extraprec(20)(kfrom)(qbar=0.25)) # ill-conditioned
  134. 0.25
  135. >>> qbarfrom(tau=taufrom(qbar=0.25))
  136. (0.25 + 0.0j)
  137. """
  138. if qbar is not None:
  139. return ctx.convert(qbar)
  140. if q is not None:
  141. return ctx.convert(q) ** 2
  142. if m is not None:
  143. return nome(ctx, m) ** 2
  144. if k is not None:
  145. return nome(ctx, ctx.convert(k)**2) ** 2
  146. if tau is not None:
  147. return ctx.expjpi(2*tau)
  148. @defun_wrapped
  149. def taufrom(ctx, q=None, m=None, k=None, tau=None, qbar=None):
  150. r"""
  151. Returns the elliptic half-period ratio `\tau`, given any of
  152. `q, m, k, \tau, \bar{q}`::
  153. >>> from mpmath import *
  154. >>> mp.dps = 25; mp.pretty = True
  155. >>> taufrom(tau=0.5j)
  156. (0.0 + 0.5j)
  157. >>> taufrom(q=qfrom(tau=0.5j))
  158. (0.0 + 0.5j)
  159. >>> taufrom(m=mfrom(tau=0.5j))
  160. (0.0 + 0.5j)
  161. >>> taufrom(k=kfrom(tau=0.5j))
  162. (0.0 + 0.5j)
  163. >>> taufrom(qbar=qbarfrom(tau=0.5j))
  164. (0.0 + 0.5j)
  165. """
  166. if tau is not None:
  167. return ctx.convert(tau)
  168. if m is not None:
  169. m = ctx.convert(m)
  170. return ctx.j*ctx.ellipk(1-m)/ctx.ellipk(m)
  171. if k is not None:
  172. k = ctx.convert(k)
  173. return ctx.j*ctx.ellipk(1-k**2)/ctx.ellipk(k**2)
  174. if q is not None:
  175. return ctx.log(q) / (ctx.pi*ctx.j)
  176. if qbar is not None:
  177. qbar = ctx.convert(qbar)
  178. return ctx.log(qbar) / (2*ctx.pi*ctx.j)
  179. @defun_wrapped
  180. def kfrom(ctx, q=None, m=None, k=None, tau=None, qbar=None):
  181. r"""
  182. Returns the elliptic modulus `k`, given any of
  183. `q, m, k, \tau, \bar{q}`::
  184. >>> from mpmath import *
  185. >>> mp.dps = 25; mp.pretty = True
  186. >>> kfrom(k=0.25)
  187. 0.25
  188. >>> kfrom(m=mfrom(k=0.25))
  189. 0.25
  190. >>> kfrom(q=qfrom(k=0.25))
  191. 0.25
  192. >>> kfrom(tau=taufrom(k=0.25))
  193. (0.25 + 0.0j)
  194. >>> kfrom(qbar=qbarfrom(k=0.25))
  195. 0.25
  196. As `q \to 1` and `q \to -1`, `k` rapidly approaches
  197. `1` and `i \infty` respectively::
  198. >>> kfrom(q=0.75)
  199. 0.9999999999999899166471767
  200. >>> kfrom(q=-0.75)
  201. (0.0 + 7041781.096692038332790615j)
  202. >>> kfrom(q=1)
  203. 1
  204. >>> kfrom(q=-1)
  205. (0.0 + +infj)
  206. """
  207. if k is not None:
  208. return ctx.convert(k)
  209. if m is not None:
  210. return ctx.sqrt(m)
  211. if tau is not None:
  212. q = ctx.expjpi(tau)
  213. if qbar is not None:
  214. q = ctx.sqrt(qbar)
  215. if q == 1:
  216. return q
  217. if q == -1:
  218. return ctx.mpc(0,'inf')
  219. return (ctx.jtheta(2,0,q)/ctx.jtheta(3,0,q))**2
  220. @defun_wrapped
  221. def mfrom(ctx, q=None, m=None, k=None, tau=None, qbar=None):
  222. r"""
  223. Returns the elliptic parameter `m`, given any of
  224. `q, m, k, \tau, \bar{q}`::
  225. >>> from mpmath import *
  226. >>> mp.dps = 25; mp.pretty = True
  227. >>> mfrom(m=0.25)
  228. 0.25
  229. >>> mfrom(q=qfrom(m=0.25))
  230. 0.25
  231. >>> mfrom(k=kfrom(m=0.25))
  232. 0.25
  233. >>> mfrom(tau=taufrom(m=0.25))
  234. (0.25 + 0.0j)
  235. >>> mfrom(qbar=qbarfrom(m=0.25))
  236. 0.25
  237. As `q \to 1` and `q \to -1`, `m` rapidly approaches
  238. `1` and `-\infty` respectively::
  239. >>> mfrom(q=0.75)
  240. 0.9999999999999798332943533
  241. >>> mfrom(q=-0.75)
  242. -49586681013729.32611558353
  243. >>> mfrom(q=1)
  244. 1.0
  245. >>> mfrom(q=-1)
  246. -inf
  247. The inverse nome as a function of `q` has an integer
  248. Taylor series expansion::
  249. >>> taylor(lambda q: mfrom(q), 0, 7)
  250. [0.0, 16.0, -128.0, 704.0, -3072.0, 11488.0, -38400.0, 117632.0]
  251. """
  252. if m is not None:
  253. return m
  254. if k is not None:
  255. return k**2
  256. if tau is not None:
  257. q = ctx.expjpi(tau)
  258. if qbar is not None:
  259. q = ctx.sqrt(qbar)
  260. if q == 1:
  261. return ctx.convert(q)
  262. if q == -1:
  263. return q*ctx.inf
  264. v = (ctx.jtheta(2,0,q)/ctx.jtheta(3,0,q))**4
  265. if ctx._is_real_type(q) and q < 0:
  266. v = v.real
  267. return v
  268. jacobi_spec = {
  269. 'sn' : ([3],[2],[1],[4], 'sin', 'tanh'),
  270. 'cn' : ([4],[2],[2],[4], 'cos', 'sech'),
  271. 'dn' : ([4],[3],[3],[4], '1', 'sech'),
  272. 'ns' : ([2],[3],[4],[1], 'csc', 'coth'),
  273. 'nc' : ([2],[4],[4],[2], 'sec', 'cosh'),
  274. 'nd' : ([3],[4],[4],[3], '1', 'cosh'),
  275. 'sc' : ([3],[4],[1],[2], 'tan', 'sinh'),
  276. 'sd' : ([3,3],[2,4],[1],[3], 'sin', 'sinh'),
  277. 'cd' : ([3],[2],[2],[3], 'cos', '1'),
  278. 'cs' : ([4],[3],[2],[1], 'cot', 'csch'),
  279. 'dc' : ([2],[3],[3],[2], 'sec', '1'),
  280. 'ds' : ([2,4],[3,3],[3],[1], 'csc', 'csch'),
  281. 'cc' : None,
  282. 'ss' : None,
  283. 'nn' : None,
  284. 'dd' : None
  285. }
  286. @defun
  287. def ellipfun(ctx, kind, u=None, m=None, q=None, k=None, tau=None):
  288. try:
  289. S = jacobi_spec[kind]
  290. except KeyError:
  291. raise ValueError("First argument must be a two-character string "
  292. "containing 's', 'c', 'd' or 'n', e.g.: 'sn'")
  293. if u is None:
  294. def f(*args, **kwargs):
  295. return ctx.ellipfun(kind, *args, **kwargs)
  296. f.__name__ = kind
  297. return f
  298. prec = ctx.prec
  299. try:
  300. ctx.prec += 10
  301. u = ctx.convert(u)
  302. q = ctx.qfrom(m=m, q=q, k=k, tau=tau)
  303. if S is None:
  304. v = ctx.one + 0*q*u
  305. elif q == ctx.zero:
  306. if S[4] == '1': v = ctx.one
  307. else: v = getattr(ctx, S[4])(u)
  308. v += 0*q*u
  309. elif q == ctx.one:
  310. if S[5] == '1': v = ctx.one
  311. else: v = getattr(ctx, S[5])(u)
  312. v += 0*q*u
  313. else:
  314. t = u / ctx.jtheta(3, 0, q)**2
  315. v = ctx.one
  316. for a in S[0]: v *= ctx.jtheta(a, 0, q)
  317. for b in S[1]: v /= ctx.jtheta(b, 0, q)
  318. for c in S[2]: v *= ctx.jtheta(c, t, q)
  319. for d in S[3]: v /= ctx.jtheta(d, t, q)
  320. finally:
  321. ctx.prec = prec
  322. return +v
  323. @defun_wrapped
  324. def kleinj(ctx, tau=None, **kwargs):
  325. r"""
  326. Evaluates the Klein j-invariant, which is a modular function defined for
  327. `\tau` in the upper half-plane as
  328. .. math ::
  329. J(\tau) = \frac{g_2^3(\tau)}{g_2^3(\tau) - 27 g_3^2(\tau)}
  330. where `g_2` and `g_3` are the modular invariants of the Weierstrass
  331. elliptic function,
  332. .. math ::
  333. g_2(\tau) = 60 \sum_{(m,n) \in \mathbb{Z}^2 \setminus (0,0)} (m \tau+n)^{-4}
  334. g_3(\tau) = 140 \sum_{(m,n) \in \mathbb{Z}^2 \setminus (0,0)} (m \tau+n)^{-6}.
  335. An alternative, common notation is that of the j-function
  336. `j(\tau) = 1728 J(\tau)`.
  337. **Plots**
  338. .. literalinclude :: /plots/kleinj.py
  339. .. image :: /plots/kleinj.png
  340. .. literalinclude :: /plots/kleinj2.py
  341. .. image :: /plots/kleinj2.png
  342. **Examples**
  343. Verifying the functional equation `J(\tau) = J(\tau+1) = J(-\tau^{-1})`::
  344. >>> from mpmath import *
  345. >>> mp.dps = 25; mp.pretty = True
  346. >>> tau = 0.625+0.75*j
  347. >>> tau = 0.625+0.75*j
  348. >>> kleinj(tau)
  349. (-0.1507492166511182267125242 + 0.07595948379084571927228948j)
  350. >>> kleinj(tau+1)
  351. (-0.1507492166511182267125242 + 0.07595948379084571927228948j)
  352. >>> kleinj(-1/tau)
  353. (-0.1507492166511182267125242 + 0.07595948379084571927228946j)
  354. The j-function has a famous Laurent series expansion in terms of the nome
  355. `\bar{q}`, `j(\tau) = \bar{q}^{-1} + 744 + 196884\bar{q} + \ldots`::
  356. >>> mp.dps = 15
  357. >>> taylor(lambda q: 1728*q*kleinj(qbar=q), 0, 5, singular=True)
  358. [1.0, 744.0, 196884.0, 21493760.0, 864299970.0, 20245856256.0]
  359. The j-function admits exact evaluation at special algebraic points
  360. related to the Heegner numbers 1, 2, 3, 7, 11, 19, 43, 67, 163::
  361. >>> @extraprec(10)
  362. ... def h(n):
  363. ... v = (1+sqrt(n)*j)
  364. ... if n > 2:
  365. ... v *= 0.5
  366. ... return v
  367. ...
  368. >>> mp.dps = 25
  369. >>> for n in [1,2,3,7,11,19,43,67,163]:
  370. ... n, chop(1728*kleinj(h(n)))
  371. ...
  372. (1, 1728.0)
  373. (2, 8000.0)
  374. (3, 0.0)
  375. (7, -3375.0)
  376. (11, -32768.0)
  377. (19, -884736.0)
  378. (43, -884736000.0)
  379. (67, -147197952000.0)
  380. (163, -262537412640768000.0)
  381. Also at other special points, the j-function assumes explicit
  382. algebraic values, e.g.::
  383. >>> chop(1728*kleinj(j*sqrt(5)))
  384. 1264538.909475140509320227
  385. >>> identify(cbrt(_)) # note: not simplified
  386. '((100+sqrt(13520))/2)'
  387. >>> (50+26*sqrt(5))**3
  388. 1264538.909475140509320227
  389. """
  390. q = ctx.qfrom(tau=tau, **kwargs)
  391. t2 = ctx.jtheta(2,0,q)
  392. t3 = ctx.jtheta(3,0,q)
  393. t4 = ctx.jtheta(4,0,q)
  394. P = (t2**8 + t3**8 + t4**8)**3
  395. Q = 54*(t2*t3*t4)**8
  396. return P/Q
  397. def RF_calc(ctx, x, y, z, r):
  398. if y == z: return RC_calc(ctx, x, y, r)
  399. if x == z: return RC_calc(ctx, y, x, r)
  400. if x == y: return RC_calc(ctx, z, x, r)
  401. if not (ctx.isnormal(x) and ctx.isnormal(y) and ctx.isnormal(z)):
  402. if ctx.isnan(x) or ctx.isnan(y) or ctx.isnan(z):
  403. return x*y*z
  404. if ctx.isinf(x) or ctx.isinf(y) or ctx.isinf(z):
  405. return ctx.zero
  406. xm,ym,zm = x,y,z
  407. A0 = Am = (x+y+z)/3
  408. Q = ctx.root(3*r, -6) * max(abs(A0-x),abs(A0-y),abs(A0-z))
  409. g = ctx.mpf(0.25)
  410. pow4 = ctx.one
  411. while 1:
  412. xs = ctx.sqrt(xm)
  413. ys = ctx.sqrt(ym)
  414. zs = ctx.sqrt(zm)
  415. lm = xs*ys + xs*zs + ys*zs
  416. Am1 = (Am+lm)*g
  417. xm, ym, zm = (xm+lm)*g, (ym+lm)*g, (zm+lm)*g
  418. if pow4 * Q < abs(Am):
  419. break
  420. Am = Am1
  421. pow4 *= g
  422. t = pow4/Am
  423. X = (A0-x)*t
  424. Y = (A0-y)*t
  425. Z = -X-Y
  426. E2 = X*Y-Z**2
  427. E3 = X*Y*Z
  428. return ctx.power(Am,-0.5) * (9240-924*E2+385*E2**2+660*E3-630*E2*E3)/9240
  429. def RC_calc(ctx, x, y, r, pv=True):
  430. if not (ctx.isnormal(x) and ctx.isnormal(y)):
  431. if ctx.isinf(x) or ctx.isinf(y):
  432. return 1/(x*y)
  433. if y == 0:
  434. return ctx.inf
  435. if x == 0:
  436. return ctx.pi / ctx.sqrt(y) / 2
  437. raise ValueError
  438. # Cauchy principal value
  439. if pv and ctx._im(y) == 0 and ctx._re(y) < 0:
  440. return ctx.sqrt(x/(x-y)) * RC_calc(ctx, x-y, -y, r)
  441. if x == y:
  442. return 1/ctx.sqrt(x)
  443. extraprec = 2*max(0,-ctx.mag(x-y)+ctx.mag(x))
  444. ctx.prec += extraprec
  445. if ctx._is_real_type(x) and ctx._is_real_type(y):
  446. x = ctx._re(x)
  447. y = ctx._re(y)
  448. a = ctx.sqrt(x/y)
  449. if x < y:
  450. b = ctx.sqrt(y-x)
  451. v = ctx.acos(a)/b
  452. else:
  453. b = ctx.sqrt(x-y)
  454. v = ctx.acosh(a)/b
  455. else:
  456. sx = ctx.sqrt(x)
  457. sy = ctx.sqrt(y)
  458. v = ctx.acos(sx/sy)/(ctx.sqrt((1-x/y))*sy)
  459. ctx.prec -= extraprec
  460. return v
  461. def RJ_calc(ctx, x, y, z, p, r, integration):
  462. """
  463. With integration == 0, computes RJ only using Carlson's algorithm
  464. (may be wrong for some values).
  465. With integration == 1, uses an initial integration to make sure
  466. Carlson's algorithm is correct.
  467. With integration == 2, uses only integration.
  468. """
  469. if not (ctx.isnormal(x) and ctx.isnormal(y) and \
  470. ctx.isnormal(z) and ctx.isnormal(p)):
  471. if ctx.isnan(x) or ctx.isnan(y) or ctx.isnan(z) or ctx.isnan(p):
  472. return x*y*z
  473. if ctx.isinf(x) or ctx.isinf(y) or ctx.isinf(z) or ctx.isinf(p):
  474. return ctx.zero
  475. if not p:
  476. return ctx.inf
  477. if (not x) + (not y) + (not z) > 1:
  478. return ctx.inf
  479. # Check conditions and fall back on integration for argument
  480. # reduction if needed. The following conditions might be needlessly
  481. # restrictive.
  482. initial_integral = ctx.zero
  483. if integration >= 1:
  484. ok = (x.real >= 0 and y.real >= 0 and z.real >= 0 and p.real > 0)
  485. if not ok:
  486. if x == p or y == p or z == p:
  487. ok = True
  488. if not ok:
  489. if p.imag != 0 or p.real >= 0:
  490. if (x.imag == 0 and x.real >= 0 and ctx.conj(y) == z):
  491. ok = True
  492. if (y.imag == 0 and y.real >= 0 and ctx.conj(x) == z):
  493. ok = True
  494. if (z.imag == 0 and z.real >= 0 and ctx.conj(x) == y):
  495. ok = True
  496. if not ok or (integration == 2):
  497. N = ctx.ceil(-min(x.real, y.real, z.real, p.real)) + 1
  498. # Integrate around any singularities
  499. if all((t.imag >= 0 or t.real > 0) for t in [x, y, z, p]):
  500. margin = ctx.j
  501. elif all((t.imag < 0 or t.real > 0) for t in [x, y, z, p]):
  502. margin = -ctx.j
  503. else:
  504. margin = 1
  505. # Go through the upper half-plane, but low enough that any
  506. # parameter starting in the lower plane doesn't cross the
  507. # branch cut
  508. for t in [x, y, z, p]:
  509. if t.imag >= 0 or t.real > 0:
  510. continue
  511. margin = min(margin, abs(t.imag) * 0.5)
  512. margin *= ctx.j
  513. N += margin
  514. F = lambda t: 1/(ctx.sqrt(t+x)*ctx.sqrt(t+y)*ctx.sqrt(t+z)*(t+p))
  515. if integration == 2:
  516. return 1.5 * ctx.quadsubdiv(F, [0, N, ctx.inf])
  517. initial_integral = 1.5 * ctx.quadsubdiv(F, [0, N])
  518. x += N; y += N; z += N; p += N
  519. xm,ym,zm,pm = x,y,z,p
  520. A0 = Am = (x + y + z + 2*p)/5
  521. delta = (p-x)*(p-y)*(p-z)
  522. Q = ctx.root(0.25*r, -6) * max(abs(A0-x),abs(A0-y),abs(A0-z),abs(A0-p))
  523. g = ctx.mpf(0.25)
  524. pow4 = ctx.one
  525. S = 0
  526. while 1:
  527. sx = ctx.sqrt(xm)
  528. sy = ctx.sqrt(ym)
  529. sz = ctx.sqrt(zm)
  530. sp = ctx.sqrt(pm)
  531. lm = sx*sy + sx*sz + sy*sz
  532. Am1 = (Am+lm)*g
  533. xm = (xm+lm)*g; ym = (ym+lm)*g; zm = (zm+lm)*g; pm = (pm+lm)*g
  534. dm = (sp+sx) * (sp+sy) * (sp+sz)
  535. em = delta * pow4**3 / dm**2
  536. if pow4 * Q < abs(Am):
  537. break
  538. T = RC_calc(ctx, ctx.one, ctx.one+em, r) * pow4 / dm
  539. S += T
  540. pow4 *= g
  541. Am = Am1
  542. t = pow4 / Am
  543. X = (A0-x)*t
  544. Y = (A0-y)*t
  545. Z = (A0-z)*t
  546. P = (-X-Y-Z)/2
  547. E2 = X*Y + X*Z + Y*Z - 3*P**2
  548. E3 = X*Y*Z + 2*E2*P + 4*P**3
  549. E4 = (2*X*Y*Z + E2*P + 3*P**3)*P
  550. E5 = X*Y*Z*P**2
  551. P = 24024 - 5148*E2 + 2457*E2**2 + 4004*E3 - 4158*E2*E3 - 3276*E4 + 2772*E5
  552. Q = 24024
  553. v1 = pow4 * ctx.power(Am, -1.5) * P/Q
  554. v2 = 6*S
  555. return initial_integral + v1 + v2
  556. @defun
  557. def elliprf(ctx, x, y, z):
  558. r"""
  559. Evaluates the Carlson symmetric elliptic integral of the first kind
  560. .. math ::
  561. R_F(x,y,z) = \frac{1}{2}
  562. \int_0^{\infty} \frac{dt}{\sqrt{(t+x)(t+y)(t+z)}}
  563. which is defined for `x,y,z \notin (-\infty,0)`, and with
  564. at most one of `x,y,z` being zero.
  565. For real `x,y,z \ge 0`, the principal square root is taken in the integrand.
  566. For complex `x,y,z`, the principal square root is taken as `t \to \infty`
  567. and as `t \to 0` non-principal branches are chosen as necessary so as to
  568. make the integrand continuous.
  569. **Examples**
  570. Some basic values and limits::
  571. >>> from mpmath import *
  572. >>> mp.dps = 25; mp.pretty = True
  573. >>> elliprf(0,1,1); pi/2
  574. 1.570796326794896619231322
  575. 1.570796326794896619231322
  576. >>> elliprf(0,1,inf)
  577. 0.0
  578. >>> elliprf(1,1,1)
  579. 1.0
  580. >>> elliprf(2,2,2)**2
  581. 0.5
  582. >>> elliprf(1,0,0); elliprf(0,0,1); elliprf(0,1,0); elliprf(0,0,0)
  583. +inf
  584. +inf
  585. +inf
  586. +inf
  587. Representing complete elliptic integrals in terms of `R_F`::
  588. >>> m = mpf(0.75)
  589. >>> ellipk(m); elliprf(0,1-m,1)
  590. 2.156515647499643235438675
  591. 2.156515647499643235438675
  592. >>> ellipe(m); elliprf(0,1-m,1)-m*elliprd(0,1-m,1)/3
  593. 1.211056027568459524803563
  594. 1.211056027568459524803563
  595. Some symmetries and argument transformations::
  596. >>> x,y,z = 2,3,4
  597. >>> elliprf(x,y,z); elliprf(y,x,z); elliprf(z,y,x)
  598. 0.5840828416771517066928492
  599. 0.5840828416771517066928492
  600. 0.5840828416771517066928492
  601. >>> k = mpf(100000)
  602. >>> elliprf(k*x,k*y,k*z); k**(-0.5) * elliprf(x,y,z)
  603. 0.001847032121923321253219284
  604. 0.001847032121923321253219284
  605. >>> l = sqrt(x*y) + sqrt(y*z) + sqrt(z*x)
  606. >>> elliprf(x,y,z); 2*elliprf(x+l,y+l,z+l)
  607. 0.5840828416771517066928492
  608. 0.5840828416771517066928492
  609. >>> elliprf((x+l)/4,(y+l)/4,(z+l)/4)
  610. 0.5840828416771517066928492
  611. Comparing with numerical integration::
  612. >>> x,y,z = 2,3,4
  613. >>> elliprf(x,y,z)
  614. 0.5840828416771517066928492
  615. >>> f = lambda t: 0.5*((t+x)*(t+y)*(t+z))**(-0.5)
  616. >>> q = extradps(25)(quad)
  617. >>> q(f, [0,inf])
  618. 0.5840828416771517066928492
  619. With the following arguments, the square root in the integrand becomes
  620. discontinuous at `t = 1/2` if the principal branch is used. To obtain
  621. the right value, `-\sqrt{r}` must be taken instead of `\sqrt{r}`
  622. on `t \in (0, 1/2)`::
  623. >>> x,y,z = j-1,j,0
  624. >>> elliprf(x,y,z)
  625. (0.7961258658423391329305694 - 1.213856669836495986430094j)
  626. >>> -q(f, [0,0.5]) + q(f, [0.5,inf])
  627. (0.7961258658423391329305694 - 1.213856669836495986430094j)
  628. The so-called *first lemniscate constant*, a transcendental number::
  629. >>> elliprf(0,1,2)
  630. 1.31102877714605990523242
  631. >>> extradps(25)(quad)(lambda t: 1/sqrt(1-t**4), [0,1])
  632. 1.31102877714605990523242
  633. >>> gamma('1/4')**2/(4*sqrt(2*pi))
  634. 1.31102877714605990523242
  635. **References**
  636. 1. [Carlson]_
  637. 2. [DLMF]_ Chapter 19. Elliptic Integrals
  638. """
  639. x = ctx.convert(x)
  640. y = ctx.convert(y)
  641. z = ctx.convert(z)
  642. prec = ctx.prec
  643. try:
  644. ctx.prec += 20
  645. tol = ctx.eps * 2**10
  646. v = RF_calc(ctx, x, y, z, tol)
  647. finally:
  648. ctx.prec = prec
  649. return +v
  650. @defun
  651. def elliprc(ctx, x, y, pv=True):
  652. r"""
  653. Evaluates the degenerate Carlson symmetric elliptic integral
  654. of the first kind
  655. .. math ::
  656. R_C(x,y) = R_F(x,y,y) =
  657. \frac{1}{2} \int_0^{\infty} \frac{dt}{(t+y) \sqrt{(t+x)}}.
  658. If `y \in (-\infty,0)`, either a value defined by continuity,
  659. or with *pv=True* the Cauchy principal value, can be computed.
  660. If `x \ge 0, y > 0`, the value can be expressed in terms of
  661. elementary functions as
  662. .. math ::
  663. R_C(x,y) =
  664. \begin{cases}
  665. \dfrac{1}{\sqrt{y-x}}
  666. \cos^{-1}\left(\sqrt{\dfrac{x}{y}}\right), & x < y \\
  667. \dfrac{1}{\sqrt{y}}, & x = y \\
  668. \dfrac{1}{\sqrt{x-y}}
  669. \cosh^{-1}\left(\sqrt{\dfrac{x}{y}}\right), & x > y \\
  670. \end{cases}.
  671. **Examples**
  672. Some special values and limits::
  673. >>> from mpmath import *
  674. >>> mp.dps = 25; mp.pretty = True
  675. >>> elliprc(1,2)*4; elliprc(0,1)*2; +pi
  676. 3.141592653589793238462643
  677. 3.141592653589793238462643
  678. 3.141592653589793238462643
  679. >>> elliprc(1,0)
  680. +inf
  681. >>> elliprc(5,5)**2
  682. 0.2
  683. >>> elliprc(1,inf); elliprc(inf,1); elliprc(inf,inf)
  684. 0.0
  685. 0.0
  686. 0.0
  687. Comparing with the elementary closed-form solution::
  688. >>> elliprc('1/3', '1/5'); sqrt(7.5)*acosh(sqrt('5/3'))
  689. 2.041630778983498390751238
  690. 2.041630778983498390751238
  691. >>> elliprc('1/5', '1/3'); sqrt(7.5)*acos(sqrt('3/5'))
  692. 1.875180765206547065111085
  693. 1.875180765206547065111085
  694. Comparing with numerical integration::
  695. >>> q = extradps(25)(quad)
  696. >>> elliprc(2, -3, pv=True)
  697. 0.3333969101113672670749334
  698. >>> elliprc(2, -3, pv=False)
  699. (0.3333969101113672670749334 + 0.7024814731040726393156375j)
  700. >>> 0.5*q(lambda t: 1/(sqrt(t+2)*(t-3)), [0,3-j,6,inf])
  701. (0.3333969101113672670749334 + 0.7024814731040726393156375j)
  702. """
  703. x = ctx.convert(x)
  704. y = ctx.convert(y)
  705. prec = ctx.prec
  706. try:
  707. ctx.prec += 20
  708. tol = ctx.eps * 2**10
  709. v = RC_calc(ctx, x, y, tol, pv)
  710. finally:
  711. ctx.prec = prec
  712. return +v
  713. @defun
  714. def elliprj(ctx, x, y, z, p, integration=1):
  715. r"""
  716. Evaluates the Carlson symmetric elliptic integral of the third kind
  717. .. math ::
  718. R_J(x,y,z,p) = \frac{3}{2}
  719. \int_0^{\infty} \frac{dt}{(t+p)\sqrt{(t+x)(t+y)(t+z)}}.
  720. Like :func:`~mpmath.elliprf`, the branch of the square root in the integrand
  721. is defined so as to be continuous along the path of integration for
  722. complex values of the arguments.
  723. **Examples**
  724. Some values and limits::
  725. >>> from mpmath import *
  726. >>> mp.dps = 25; mp.pretty = True
  727. >>> elliprj(1,1,1,1)
  728. 1.0
  729. >>> elliprj(2,2,2,2); 1/(2*sqrt(2))
  730. 0.3535533905932737622004222
  731. 0.3535533905932737622004222
  732. >>> elliprj(0,1,2,2)
  733. 1.067937989667395702268688
  734. >>> 3*(2*gamma('5/4')**2-pi**2/gamma('1/4')**2)/(sqrt(2*pi))
  735. 1.067937989667395702268688
  736. >>> elliprj(0,1,1,2); 3*pi*(2-sqrt(2))/4
  737. 1.380226776765915172432054
  738. 1.380226776765915172432054
  739. >>> elliprj(1,3,2,0); elliprj(0,1,1,0); elliprj(0,0,0,0)
  740. +inf
  741. +inf
  742. +inf
  743. >>> elliprj(1,inf,1,0); elliprj(1,1,1,inf)
  744. 0.0
  745. 0.0
  746. >>> chop(elliprj(1+j, 1-j, 1, 1))
  747. 0.8505007163686739432927844
  748. Scale transformation::
  749. >>> x,y,z,p = 2,3,4,5
  750. >>> k = mpf(100000)
  751. >>> elliprj(k*x,k*y,k*z,k*p); k**(-1.5)*elliprj(x,y,z,p)
  752. 4.521291677592745527851168e-9
  753. 4.521291677592745527851168e-9
  754. Comparing with numerical integration::
  755. >>> elliprj(1,2,3,4)
  756. 0.2398480997495677621758617
  757. >>> f = lambda t: 1/((t+4)*sqrt((t+1)*(t+2)*(t+3)))
  758. >>> 1.5*quad(f, [0,inf])
  759. 0.2398480997495677621758617
  760. >>> elliprj(1,2+1j,3,4-2j)
  761. (0.216888906014633498739952 + 0.04081912627366673332369512j)
  762. >>> f = lambda t: 1/((t+4-2j)*sqrt((t+1)*(t+2+1j)*(t+3)))
  763. >>> 1.5*quad(f, [0,inf])
  764. (0.216888906014633498739952 + 0.04081912627366673332369511j)
  765. """
  766. x = ctx.convert(x)
  767. y = ctx.convert(y)
  768. z = ctx.convert(z)
  769. p = ctx.convert(p)
  770. prec = ctx.prec
  771. try:
  772. ctx.prec += 20
  773. tol = ctx.eps * 2**10
  774. v = RJ_calc(ctx, x, y, z, p, tol, integration)
  775. finally:
  776. ctx.prec = prec
  777. return +v
  778. @defun
  779. def elliprd(ctx, x, y, z):
  780. r"""
  781. Evaluates the degenerate Carlson symmetric elliptic integral
  782. of the third kind or Carlson elliptic integral of the
  783. second kind `R_D(x,y,z) = R_J(x,y,z,z)`.
  784. See :func:`~mpmath.elliprj` for additional information.
  785. **Examples**
  786. >>> from mpmath import *
  787. >>> mp.dps = 25; mp.pretty = True
  788. >>> elliprd(1,2,3)
  789. 0.2904602810289906442326534
  790. >>> elliprj(1,2,3,3)
  791. 0.2904602810289906442326534
  792. The so-called *second lemniscate constant*, a transcendental number::
  793. >>> elliprd(0,2,1)/3
  794. 0.5990701173677961037199612
  795. >>> extradps(25)(quad)(lambda t: t**2/sqrt(1-t**4), [0,1])
  796. 0.5990701173677961037199612
  797. >>> gamma('3/4')**2/sqrt(2*pi)
  798. 0.5990701173677961037199612
  799. """
  800. return ctx.elliprj(x,y,z,z)
  801. @defun
  802. def elliprg(ctx, x, y, z):
  803. r"""
  804. Evaluates the Carlson completely symmetric elliptic integral
  805. of the second kind
  806. .. math ::
  807. R_G(x,y,z) = \frac{1}{4} \int_0^{\infty}
  808. \frac{t}{\sqrt{(t+x)(t+y)(t+z)}}
  809. \left( \frac{x}{t+x} + \frac{y}{t+y} + \frac{z}{t+z}\right) dt.
  810. **Examples**
  811. Evaluation for real and complex arguments::
  812. >>> from mpmath import *
  813. >>> mp.dps = 25; mp.pretty = True
  814. >>> elliprg(0,1,1)*4; +pi
  815. 3.141592653589793238462643
  816. 3.141592653589793238462643
  817. >>> elliprg(0,0.5,1)
  818. 0.6753219405238377512600874
  819. >>> chop(elliprg(1+j, 1-j, 2))
  820. 1.172431327676416604532822
  821. A double integral that can be evaluated in terms of `R_G`::
  822. >>> x,y,z = 2,3,4
  823. >>> def f(t,u):
  824. ... st = fp.sin(t); ct = fp.cos(t)
  825. ... su = fp.sin(u); cu = fp.cos(u)
  826. ... return (x*(st*cu)**2 + y*(st*su)**2 + z*ct**2)**0.5 * st
  827. ...
  828. >>> nprint(mpf(fp.quad(f, [0,fp.pi], [0,2*fp.pi])/(4*fp.pi)), 13)
  829. 1.725503028069
  830. >>> nprint(elliprg(x,y,z), 13)
  831. 1.725503028069
  832. """
  833. x = ctx.convert(x)
  834. y = ctx.convert(y)
  835. z = ctx.convert(z)
  836. zeros = (not x) + (not y) + (not z)
  837. if zeros == 3:
  838. return (x+y+z)*0
  839. if zeros == 2:
  840. if x: return 0.5*ctx.sqrt(x)
  841. if y: return 0.5*ctx.sqrt(y)
  842. return 0.5*ctx.sqrt(z)
  843. if zeros == 1:
  844. if not z:
  845. x, z = z, x
  846. def terms():
  847. T1 = 0.5*z*ctx.elliprf(x,y,z)
  848. T2 = -0.5*(x-z)*(y-z)*ctx.elliprd(x,y,z)/3
  849. T3 = 0.5*ctx.sqrt(x)*ctx.sqrt(y)/ctx.sqrt(z)
  850. return T1,T2,T3
  851. return ctx.sum_accurately(terms)
  852. @defun_wrapped
  853. def ellipf(ctx, phi, m):
  854. r"""
  855. Evaluates the Legendre incomplete elliptic integral of the first kind
  856. .. math ::
  857. F(\phi,m) = \int_0^{\phi} \frac{dt}{\sqrt{1-m \sin^2 t}}
  858. or equivalently
  859. .. math ::
  860. F(\phi,m) = \int_0^{\sin \phi}
  861. \frac{dt}{\left(\sqrt{1-t^2}\right)\left(\sqrt{1-mt^2}\right)}.
  862. The function reduces to a complete elliptic integral of the first kind
  863. (see :func:`~mpmath.ellipk`) when `\phi = \frac{\pi}{2}`; that is,
  864. .. math ::
  865. F\left(\frac{\pi}{2}, m\right) = K(m).
  866. In the defining integral, it is assumed that the principal branch
  867. of the square root is taken and that the path of integration avoids
  868. crossing any branch cuts. Outside `-\pi/2 \le \Re(\phi) \le \pi/2`,
  869. the function extends quasi-periodically as
  870. .. math ::
  871. F(\phi + n \pi, m) = 2 n K(m) + F(\phi,m), n \in \mathbb{Z}.
  872. **Plots**
  873. .. literalinclude :: /plots/ellipf.py
  874. .. image :: /plots/ellipf.png
  875. **Examples**
  876. Basic values and limits::
  877. >>> from mpmath import *
  878. >>> mp.dps = 25; mp.pretty = True
  879. >>> ellipf(0,1)
  880. 0.0
  881. >>> ellipf(0,0)
  882. 0.0
  883. >>> ellipf(1,0); ellipf(2+3j,0)
  884. 1.0
  885. (2.0 + 3.0j)
  886. >>> ellipf(1,1); log(sec(1)+tan(1))
  887. 1.226191170883517070813061
  888. 1.226191170883517070813061
  889. >>> ellipf(pi/2, -0.5); ellipk(-0.5)
  890. 1.415737208425956198892166
  891. 1.415737208425956198892166
  892. >>> ellipf(pi/2+eps, 1); ellipf(-pi/2-eps, 1)
  893. +inf
  894. +inf
  895. >>> ellipf(1.5, 1)
  896. 3.340677542798311003320813
  897. Comparing with numerical integration::
  898. >>> z,m = 0.5, 1.25
  899. >>> ellipf(z,m)
  900. 0.5287219202206327872978255
  901. >>> quad(lambda t: (1-m*sin(t)**2)**(-0.5), [0,z])
  902. 0.5287219202206327872978255
  903. The arguments may be complex numbers::
  904. >>> ellipf(3j, 0.5)
  905. (0.0 + 1.713602407841590234804143j)
  906. >>> ellipf(3+4j, 5-6j)
  907. (1.269131241950351323305741 - 0.3561052815014558335412538j)
  908. >>> z,m = 2+3j, 1.25
  909. >>> k = 1011
  910. >>> ellipf(z+pi*k,m); ellipf(z,m) + 2*k*ellipk(m)
  911. (4086.184383622179764082821 - 3003.003538923749396546871j)
  912. (4086.184383622179764082821 - 3003.003538923749396546871j)
  913. For `|\Re(z)| < \pi/2`, the function can be expressed as a
  914. hypergeometric series of two variables
  915. (see :func:`~mpmath.appellf1`)::
  916. >>> z,m = 0.5, 0.25
  917. >>> ellipf(z,m)
  918. 0.5050887275786480788831083
  919. >>> sin(z)*appellf1(0.5,0.5,0.5,1.5,sin(z)**2,m*sin(z)**2)
  920. 0.5050887275786480788831083
  921. """
  922. z = phi
  923. if not (ctx.isnormal(z) and ctx.isnormal(m)):
  924. if m == 0:
  925. return z + m
  926. if z == 0:
  927. return z * m
  928. if m == ctx.inf or m == ctx.ninf: return z/m
  929. raise ValueError
  930. x = z.real
  931. ctx.prec += max(0, ctx.mag(x))
  932. pi = +ctx.pi
  933. away = abs(x) > pi/2
  934. if m == 1:
  935. if away:
  936. return ctx.inf
  937. if away:
  938. d = ctx.nint(x/pi)
  939. z = z-pi*d
  940. P = 2*d*ctx.ellipk(m)
  941. else:
  942. P = 0
  943. c, s = ctx.cos_sin(z)
  944. return s * ctx.elliprf(c**2, 1-m*s**2, 1) + P
  945. @defun_wrapped
  946. def ellipe(ctx, *args):
  947. r"""
  948. Called with a single argument `m`, evaluates the Legendre complete
  949. elliptic integral of the second kind, `E(m)`, defined by
  950. .. math :: E(m) = \int_0^{\pi/2} \sqrt{1-m \sin^2 t} \, dt \,=\,
  951. \frac{\pi}{2}
  952. \,_2F_1\left(\frac{1}{2}, -\frac{1}{2}, 1, m\right).
  953. Called with two arguments `\phi, m`, evaluates the incomplete elliptic
  954. integral of the second kind
  955. .. math ::
  956. E(\phi,m) = \int_0^{\phi} \sqrt{1-m \sin^2 t} \, dt =
  957. \int_0^{\sin z}
  958. \frac{\sqrt{1-mt^2}}{\sqrt{1-t^2}} \, dt.
  959. The incomplete integral reduces to a complete integral when
  960. `\phi = \frac{\pi}{2}`; that is,
  961. .. math ::
  962. E\left(\frac{\pi}{2}, m\right) = E(m).
  963. In the defining integral, it is assumed that the principal branch
  964. of the square root is taken and that the path of integration avoids
  965. crossing any branch cuts. Outside `-\pi/2 \le \Re(z) \le \pi/2`,
  966. the function extends quasi-periodically as
  967. .. math ::
  968. E(\phi + n \pi, m) = 2 n E(m) + E(\phi,m), n \in \mathbb{Z}.
  969. **Plots**
  970. .. literalinclude :: /plots/ellipe.py
  971. .. image :: /plots/ellipe.png
  972. **Examples for the complete integral**
  973. Basic values and limits::
  974. >>> from mpmath import *
  975. >>> mp.dps = 25; mp.pretty = True
  976. >>> ellipe(0)
  977. 1.570796326794896619231322
  978. >>> ellipe(1)
  979. 1.0
  980. >>> ellipe(-1)
  981. 1.910098894513856008952381
  982. >>> ellipe(2)
  983. (0.5990701173677961037199612 + 0.5990701173677961037199612j)
  984. >>> ellipe(inf)
  985. (0.0 + +infj)
  986. >>> ellipe(-inf)
  987. +inf
  988. Verifying the defining integral and hypergeometric
  989. representation::
  990. >>> ellipe(0.5)
  991. 1.350643881047675502520175
  992. >>> quad(lambda t: sqrt(1-0.5*sin(t)**2), [0, pi/2])
  993. 1.350643881047675502520175
  994. >>> pi/2*hyp2f1(0.5,-0.5,1,0.5)
  995. 1.350643881047675502520175
  996. Evaluation is supported for arbitrary complex `m`::
  997. >>> ellipe(0.5+0.25j)
  998. (1.360868682163129682716687 - 0.1238733442561786843557315j)
  999. >>> ellipe(3+4j)
  1000. (1.499553520933346954333612 - 1.577879007912758274533309j)
  1001. A definite integral::
  1002. >>> quad(ellipe, [0,1])
  1003. 1.333333333333333333333333
  1004. **Examples for the incomplete integral**
  1005. Basic values and limits::
  1006. >>> ellipe(0,1)
  1007. 0.0
  1008. >>> ellipe(0,0)
  1009. 0.0
  1010. >>> ellipe(1,0)
  1011. 1.0
  1012. >>> ellipe(2+3j,0)
  1013. (2.0 + 3.0j)
  1014. >>> ellipe(1,1); sin(1)
  1015. 0.8414709848078965066525023
  1016. 0.8414709848078965066525023
  1017. >>> ellipe(pi/2, -0.5); ellipe(-0.5)
  1018. 1.751771275694817862026502
  1019. 1.751771275694817862026502
  1020. >>> ellipe(pi/2, 1); ellipe(-pi/2, 1)
  1021. 1.0
  1022. -1.0
  1023. >>> ellipe(1.5, 1)
  1024. 0.9974949866040544309417234
  1025. Comparing with numerical integration::
  1026. >>> z,m = 0.5, 1.25
  1027. >>> ellipe(z,m)
  1028. 0.4740152182652628394264449
  1029. >>> quad(lambda t: sqrt(1-m*sin(t)**2), [0,z])
  1030. 0.4740152182652628394264449
  1031. The arguments may be complex numbers::
  1032. >>> ellipe(3j, 0.5)
  1033. (0.0 + 7.551991234890371873502105j)
  1034. >>> ellipe(3+4j, 5-6j)
  1035. (24.15299022574220502424466 + 75.2503670480325997418156j)
  1036. >>> k = 35
  1037. >>> z,m = 2+3j, 1.25
  1038. >>> ellipe(z+pi*k,m); ellipe(z,m) + 2*k*ellipe(m)
  1039. (48.30138799412005235090766 + 17.47255216721987688224357j)
  1040. (48.30138799412005235090766 + 17.47255216721987688224357j)
  1041. For `|\Re(z)| < \pi/2`, the function can be expressed as a
  1042. hypergeometric series of two variables
  1043. (see :func:`~mpmath.appellf1`)::
  1044. >>> z,m = 0.5, 0.25
  1045. >>> ellipe(z,m)
  1046. 0.4950017030164151928870375
  1047. >>> sin(z)*appellf1(0.5,0.5,-0.5,1.5,sin(z)**2,m*sin(z)**2)
  1048. 0.4950017030164151928870376
  1049. """
  1050. if len(args) == 1:
  1051. return ctx._ellipe(args[0])
  1052. else:
  1053. phi, m = args
  1054. z = phi
  1055. if not (ctx.isnormal(z) and ctx.isnormal(m)):
  1056. if m == 0:
  1057. return z + m
  1058. if z == 0:
  1059. return z * m
  1060. if m == ctx.inf or m == ctx.ninf:
  1061. return ctx.inf
  1062. raise ValueError
  1063. x = z.real
  1064. ctx.prec += max(0, ctx.mag(x))
  1065. pi = +ctx.pi
  1066. away = abs(x) > pi/2
  1067. if away:
  1068. d = ctx.nint(x/pi)
  1069. z = z-pi*d
  1070. P = 2*d*ctx.ellipe(m)
  1071. else:
  1072. P = 0
  1073. def terms():
  1074. c, s = ctx.cos_sin(z)
  1075. x = c**2
  1076. y = 1-m*s**2
  1077. RF = ctx.elliprf(x, y, 1)
  1078. RD = ctx.elliprd(x, y, 1)
  1079. return s*RF, -m*s**3*RD/3
  1080. return ctx.sum_accurately(terms) + P
  1081. @defun_wrapped
  1082. def ellippi(ctx, *args):
  1083. r"""
  1084. Called with three arguments `n, \phi, m`, evaluates the Legendre
  1085. incomplete elliptic integral of the third kind
  1086. .. math ::
  1087. \Pi(n; \phi, m) = \int_0^{\phi}
  1088. \frac{dt}{(1-n \sin^2 t) \sqrt{1-m \sin^2 t}} =
  1089. \int_0^{\sin \phi}
  1090. \frac{dt}{(1-nt^2) \sqrt{1-t^2} \sqrt{1-mt^2}}.
  1091. Called with two arguments `n, m`, evaluates the complete
  1092. elliptic integral of the third kind
  1093. `\Pi(n,m) = \Pi(n; \frac{\pi}{2},m)`.
  1094. In the defining integral, it is assumed that the principal branch
  1095. of the square root is taken and that the path of integration avoids
  1096. crossing any branch cuts. Outside `-\pi/2 \le \Re(\phi) \le \pi/2`,
  1097. the function extends quasi-periodically as
  1098. .. math ::
  1099. \Pi(n,\phi+k\pi,m) = 2k\Pi(n,m) + \Pi(n,\phi,m), k \in \mathbb{Z}.
  1100. **Plots**
  1101. .. literalinclude :: /plots/ellippi.py
  1102. .. image :: /plots/ellippi.png
  1103. **Examples for the complete integral**
  1104. Some basic values and limits::
  1105. >>> from mpmath import *
  1106. >>> mp.dps = 25; mp.pretty = True
  1107. >>> ellippi(0,-5); ellipk(-5)
  1108. 0.9555039270640439337379334
  1109. 0.9555039270640439337379334
  1110. >>> ellippi(inf,2)
  1111. 0.0
  1112. >>> ellippi(2,inf)
  1113. 0.0
  1114. >>> abs(ellippi(1,5))
  1115. +inf
  1116. >>> abs(ellippi(0.25,1))
  1117. +inf
  1118. Evaluation in terms of simpler functions::
  1119. >>> ellippi(0.25,0.25); ellipe(0.25)/(1-0.25)
  1120. 1.956616279119236207279727
  1121. 1.956616279119236207279727
  1122. >>> ellippi(3,0); pi/(2*sqrt(-2))
  1123. (0.0 - 1.11072073453959156175397j)
  1124. (0.0 - 1.11072073453959156175397j)
  1125. >>> ellippi(-3,0); pi/(2*sqrt(4))
  1126. 0.7853981633974483096156609
  1127. 0.7853981633974483096156609
  1128. **Examples for the incomplete integral**
  1129. Basic values and limits::
  1130. >>> ellippi(0.25,-0.5); ellippi(0.25,pi/2,-0.5)
  1131. 1.622944760954741603710555
  1132. 1.622944760954741603710555
  1133. >>> ellippi(1,0,1)
  1134. 0.0
  1135. >>> ellippi(inf,0,1)
  1136. 0.0
  1137. >>> ellippi(0,0.25,0.5); ellipf(0.25,0.5)
  1138. 0.2513040086544925794134591
  1139. 0.2513040086544925794134591
  1140. >>> ellippi(1,1,1); (log(sec(1)+tan(1))+sec(1)*tan(1))/2
  1141. 2.054332933256248668692452
  1142. 2.054332933256248668692452
  1143. >>> ellippi(0.25, 53*pi/2, 0.75); 53*ellippi(0.25,0.75)
  1144. 135.240868757890840755058
  1145. 135.240868757890840755058
  1146. >>> ellippi(0.5,pi/4,0.5); 2*ellipe(pi/4,0.5)-1/sqrt(3)
  1147. 0.9190227391656969903987269
  1148. 0.9190227391656969903987269
  1149. Complex arguments are supported::
  1150. >>> ellippi(0.5, 5+6j-2*pi, -7-8j)
  1151. (-0.3612856620076747660410167 + 0.5217735339984807829755815j)
  1152. Some degenerate cases::
  1153. >>> ellippi(1,1)
  1154. +inf
  1155. >>> ellippi(1,0)
  1156. +inf
  1157. >>> ellippi(1,2,0)
  1158. +inf
  1159. >>> ellippi(1,2,1)
  1160. +inf
  1161. >>> ellippi(1,0,1)
  1162. 0.0
  1163. """
  1164. if len(args) == 2:
  1165. n, m = args
  1166. complete = True
  1167. z = phi = ctx.pi/2
  1168. else:
  1169. n, phi, m = args
  1170. complete = False
  1171. z = phi
  1172. if not (ctx.isnormal(n) and ctx.isnormal(z) and ctx.isnormal(m)):
  1173. if ctx.isnan(n) or ctx.isnan(z) or ctx.isnan(m):
  1174. raise ValueError
  1175. if complete:
  1176. if m == 0:
  1177. if n == 1:
  1178. return ctx.inf
  1179. return ctx.pi/(2*ctx.sqrt(1-n))
  1180. if n == 0: return ctx.ellipk(m)
  1181. if ctx.isinf(n) or ctx.isinf(m): return ctx.zero
  1182. else:
  1183. if z == 0: return z
  1184. if ctx.isinf(n): return ctx.zero
  1185. if ctx.isinf(m): return ctx.zero
  1186. if ctx.isinf(n) or ctx.isinf(z) or ctx.isinf(m):
  1187. raise ValueError
  1188. if complete:
  1189. if m == 1:
  1190. if n == 1:
  1191. return ctx.inf
  1192. return -ctx.inf/ctx.sign(n-1)
  1193. away = False
  1194. else:
  1195. x = z.real
  1196. ctx.prec += max(0, ctx.mag(x))
  1197. pi = +ctx.pi
  1198. away = abs(x) > pi/2
  1199. if away:
  1200. d = ctx.nint(x/pi)
  1201. z = z-pi*d
  1202. P = 2*d*ctx.ellippi(n,m)
  1203. if ctx.isinf(P):
  1204. return ctx.inf
  1205. else:
  1206. P = 0
  1207. def terms():
  1208. if complete:
  1209. c, s = ctx.zero, ctx.one
  1210. else:
  1211. c, s = ctx.cos_sin(z)
  1212. x = c**2
  1213. y = 1-m*s**2
  1214. RF = ctx.elliprf(x, y, 1)
  1215. RJ = ctx.elliprj(x, y, 1, 1-n*s**2)
  1216. return s*RF, n*s**3*RJ/3
  1217. return ctx.sum_accurately(terms) + P