test_elliptic.py 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668
  1. """
  2. Limited tests of the elliptic functions module. A full suite of
  3. extensive testing can be found in elliptic_torture_tests.py
  4. Author of the first version: M.T. Taschuk
  5. References:
  6. [1] Abramowitz & Stegun. 'Handbook of Mathematical Functions, 9th Ed.',
  7. (Dover duplicate of 1972 edition)
  8. [2] Whittaker 'A Course of Modern Analysis, 4th Ed.', 1946,
  9. Cambridge University Press
  10. """
  11. import mpmath
  12. import random
  13. import pytest
  14. from mpmath import *
  15. def mpc_ae(a, b, eps=eps):
  16. res = True
  17. res = res and a.real.ae(b.real, eps)
  18. res = res and a.imag.ae(b.imag, eps)
  19. return res
  20. zero = mpf(0)
  21. one = mpf(1)
  22. jsn = ellipfun('sn')
  23. jcn = ellipfun('cn')
  24. jdn = ellipfun('dn')
  25. calculate_nome = lambda k: qfrom(k=k)
  26. def test_ellipfun():
  27. mp.dps = 15
  28. assert ellipfun('ss', 0, 0) == 1
  29. assert ellipfun('cc', 0, 0) == 1
  30. assert ellipfun('dd', 0, 0) == 1
  31. assert ellipfun('nn', 0, 0) == 1
  32. assert ellipfun('sn', 0.25, 0).ae(sin(0.25))
  33. assert ellipfun('cn', 0.25, 0).ae(cos(0.25))
  34. assert ellipfun('dn', 0.25, 0).ae(1)
  35. assert ellipfun('ns', 0.25, 0).ae(csc(0.25))
  36. assert ellipfun('nc', 0.25, 0).ae(sec(0.25))
  37. assert ellipfun('nd', 0.25, 0).ae(1)
  38. assert ellipfun('sc', 0.25, 0).ae(tan(0.25))
  39. assert ellipfun('sd', 0.25, 0).ae(sin(0.25))
  40. assert ellipfun('cd', 0.25, 0).ae(cos(0.25))
  41. assert ellipfun('cs', 0.25, 0).ae(cot(0.25))
  42. assert ellipfun('dc', 0.25, 0).ae(sec(0.25))
  43. assert ellipfun('ds', 0.25, 0).ae(csc(0.25))
  44. assert ellipfun('sn', 0.25, 1).ae(tanh(0.25))
  45. assert ellipfun('cn', 0.25, 1).ae(sech(0.25))
  46. assert ellipfun('dn', 0.25, 1).ae(sech(0.25))
  47. assert ellipfun('ns', 0.25, 1).ae(coth(0.25))
  48. assert ellipfun('nc', 0.25, 1).ae(cosh(0.25))
  49. assert ellipfun('nd', 0.25, 1).ae(cosh(0.25))
  50. assert ellipfun('sc', 0.25, 1).ae(sinh(0.25))
  51. assert ellipfun('sd', 0.25, 1).ae(sinh(0.25))
  52. assert ellipfun('cd', 0.25, 1).ae(1)
  53. assert ellipfun('cs', 0.25, 1).ae(csch(0.25))
  54. assert ellipfun('dc', 0.25, 1).ae(1)
  55. assert ellipfun('ds', 0.25, 1).ae(csch(0.25))
  56. assert ellipfun('sn', 0.25, 0.5).ae(0.24615967096986145833)
  57. assert ellipfun('cn', 0.25, 0.5).ae(0.96922928989378439337)
  58. assert ellipfun('dn', 0.25, 0.5).ae(0.98473484156599474563)
  59. assert ellipfun('ns', 0.25, 0.5).ae(4.0624038700573130369)
  60. assert ellipfun('nc', 0.25, 0.5).ae(1.0317476065024692949)
  61. assert ellipfun('nd', 0.25, 0.5).ae(1.0155017958029488665)
  62. assert ellipfun('sc', 0.25, 0.5).ae(0.25397465134058993408)
  63. assert ellipfun('sd', 0.25, 0.5).ae(0.24997558792415733063)
  64. assert ellipfun('cd', 0.25, 0.5).ae(0.98425408443195497052)
  65. assert ellipfun('cs', 0.25, 0.5).ae(3.9374008182374110826)
  66. assert ellipfun('dc', 0.25, 0.5).ae(1.0159978158253033913)
  67. assert ellipfun('ds', 0.25, 0.5).ae(4.0003906313579720593)
  68. def test_calculate_nome():
  69. mp.dps = 100
  70. q = calculate_nome(zero)
  71. assert(q == zero)
  72. mp.dps = 25
  73. # used Mathematica's EllipticNomeQ[m]
  74. math1 = [(mpf(1)/10, mpf('0.006584651553858370274473060')),
  75. (mpf(2)/10, mpf('0.01394285727531826872146409')),
  76. (mpf(3)/10, mpf('0.02227743615715350822901627')),
  77. (mpf(4)/10, mpf('0.03188334731336317755064299')),
  78. (mpf(5)/10, mpf('0.04321391826377224977441774')),
  79. (mpf(6)/10, mpf('0.05702025781460967637754953')),
  80. (mpf(7)/10, mpf('0.07468994353717944761143751')),
  81. (mpf(8)/10, mpf('0.09927369733882489703607378')),
  82. (mpf(9)/10, mpf('0.1401731269542615524091055')),
  83. (mpf(9)/10, mpf('0.1401731269542615524091055'))]
  84. for i in math1:
  85. m = i[0]
  86. q = calculate_nome(sqrt(m))
  87. assert q.ae(i[1])
  88. mp.dps = 15
  89. def test_jtheta():
  90. mp.dps = 25
  91. z = q = zero
  92. for n in range(1,5):
  93. value = jtheta(n, z, q)
  94. assert(value == (n-1)//2)
  95. for q in [one, mpf(2)]:
  96. for n in range(1,5):
  97. pytest.raises(ValueError, lambda: jtheta(n, z, q))
  98. z = one/10
  99. q = one/11
  100. # Mathematical N[EllipticTheta[1, 1/10, 1/11], 25]
  101. res = mpf('0.1069552990104042681962096')
  102. result = jtheta(1, z, q)
  103. assert(result.ae(res))
  104. # Mathematica N[EllipticTheta[2, 1/10, 1/11], 25]
  105. res = mpf('1.101385760258855791140606')
  106. result = jtheta(2, z, q)
  107. assert(result.ae(res))
  108. # Mathematica N[EllipticTheta[3, 1/10, 1/11], 25]
  109. res = mpf('1.178319743354331061795905')
  110. result = jtheta(3, z, q)
  111. assert(result.ae(res))
  112. # Mathematica N[EllipticTheta[4, 1/10, 1/11], 25]
  113. res = mpf('0.8219318954665153577314573')
  114. result = jtheta(4, z, q)
  115. assert(result.ae(res))
  116. # test for sin zeros for jtheta(1, z, q)
  117. # test for cos zeros for jtheta(2, z, q)
  118. z1 = pi
  119. z2 = pi/2
  120. for i in range(10):
  121. qstring = str(random.random())
  122. q = mpf(qstring)
  123. result = jtheta(1, z1, q)
  124. assert(result.ae(0))
  125. result = jtheta(2, z2, q)
  126. assert(result.ae(0))
  127. mp.dps = 15
  128. def test_jtheta_issue_79():
  129. # near the circle of covergence |q| = 1 the convergence slows
  130. # down; for |q| > Q_LIM the theta functions raise ValueError
  131. mp.dps = 30
  132. mp.dps += 30
  133. q = mpf(6)/10 - one/10**6 - mpf(8)/10 * j
  134. mp.dps -= 30
  135. # Mathematica run first
  136. # N[EllipticTheta[3, 1, 6/10 - 10^-6 - 8/10*I], 2000]
  137. # then it works:
  138. # N[EllipticTheta[3, 1, 6/10 - 10^-6 - 8/10*I], 30]
  139. res = mpf('32.0031009628901652627099524264') + \
  140. mpf('16.6153027998236087899308935624') * j
  141. result = jtheta(3, 1, q)
  142. # check that for abs(q) > Q_LIM a ValueError exception is raised
  143. mp.dps += 30
  144. q = mpf(6)/10 - one/10**7 - mpf(8)/10 * j
  145. mp.dps -= 30
  146. pytest.raises(ValueError, lambda: jtheta(3, 1, q))
  147. # bug reported in issue 79
  148. mp.dps = 100
  149. z = (1+j)/3
  150. q = mpf(368983957219251)/10**15 + mpf(636363636363636)/10**15 * j
  151. # Mathematica N[EllipticTheta[1, z, q], 35]
  152. res = mpf('2.4439389177990737589761828991467471') + \
  153. mpf('0.5446453005688226915290954851851490') *j
  154. mp.dps = 30
  155. result = jtheta(1, z, q)
  156. assert(result.ae(res))
  157. mp.dps = 80
  158. z = 3 + 4*j
  159. q = 0.5 + 0.5*j
  160. r1 = jtheta(1, z, q)
  161. mp.dps = 15
  162. r2 = jtheta(1, z, q)
  163. assert r1.ae(r2)
  164. mp.dps = 80
  165. z = 3 + j
  166. q1 = exp(j*3)
  167. # longer test
  168. # for n in range(1, 6)
  169. for n in range(1, 2):
  170. mp.dps = 80
  171. q = q1*(1 - mpf(1)/10**n)
  172. r1 = jtheta(1, z, q)
  173. mp.dps = 15
  174. r2 = jtheta(1, z, q)
  175. assert r1.ae(r2)
  176. mp.dps = 15
  177. # issue 79 about high derivatives
  178. assert jtheta(3, 4.5, 0.25, 9).ae(1359.04892680683)
  179. assert jtheta(3, 4.5, 0.25, 50).ae(-6.14832772630905e+33)
  180. mp.dps = 50
  181. r = jtheta(3, 4.5, 0.25, 9)
  182. assert r.ae('1359.048926806828939547859396600218966947753213803')
  183. r = jtheta(3, 4.5, 0.25, 50)
  184. assert r.ae('-6148327726309051673317975084654262.4119215720343656')
  185. def test_jtheta_identities():
  186. """
  187. Tests the some of the jacobi identidies found in Abramowitz,
  188. Sec. 16.28, Pg. 576. The identities are tested to 1 part in 10^98.
  189. """
  190. mp.dps = 110
  191. eps1 = ldexp(eps, 30)
  192. for i in range(10):
  193. qstring = str(random.random())
  194. q = mpf(qstring)
  195. zstring = str(10*random.random())
  196. z = mpf(zstring)
  197. # Abramowitz 16.28.1
  198. # v_1(z, q)**2 * v_4(0, q)**2 = v_3(z, q)**2 * v_2(0, q)**2
  199. # - v_2(z, q)**2 * v_3(0, q)**2
  200. term1 = (jtheta(1, z, q)**2) * (jtheta(4, zero, q)**2)
  201. term2 = (jtheta(3, z, q)**2) * (jtheta(2, zero, q)**2)
  202. term3 = (jtheta(2, z, q)**2) * (jtheta(3, zero, q)**2)
  203. equality = term1 - term2 + term3
  204. assert(equality.ae(0, eps1))
  205. zstring = str(100*random.random())
  206. z = mpf(zstring)
  207. # Abramowitz 16.28.2
  208. # v_2(z, q)**2 * v_4(0, q)**2 = v_4(z, q)**2 * v_2(0, q)**2
  209. # - v_1(z, q)**2 * v_3(0, q)**2
  210. term1 = (jtheta(2, z, q)**2) * (jtheta(4, zero, q)**2)
  211. term2 = (jtheta(4, z, q)**2) * (jtheta(2, zero, q)**2)
  212. term3 = (jtheta(1, z, q)**2) * (jtheta(3, zero, q)**2)
  213. equality = term1 - term2 + term3
  214. assert(equality.ae(0, eps1))
  215. # Abramowitz 16.28.3
  216. # v_3(z, q)**2 * v_4(0, q)**2 = v_4(z, q)**2 * v_3(0, q)**2
  217. # - v_1(z, q)**2 * v_2(0, q)**2
  218. term1 = (jtheta(3, z, q)**2) * (jtheta(4, zero, q)**2)
  219. term2 = (jtheta(4, z, q)**2) * (jtheta(3, zero, q)**2)
  220. term3 = (jtheta(1, z, q)**2) * (jtheta(2, zero, q)**2)
  221. equality = term1 - term2 + term3
  222. assert(equality.ae(0, eps1))
  223. # Abramowitz 16.28.4
  224. # v_4(z, q)**2 * v_4(0, q)**2 = v_3(z, q)**2 * v_3(0, q)**2
  225. # - v_2(z, q)**2 * v_2(0, q)**2
  226. term1 = (jtheta(4, z, q)**2) * (jtheta(4, zero, q)**2)
  227. term2 = (jtheta(3, z, q)**2) * (jtheta(3, zero, q)**2)
  228. term3 = (jtheta(2, z, q)**2) * (jtheta(2, zero, q)**2)
  229. equality = term1 - term2 + term3
  230. assert(equality.ae(0, eps1))
  231. # Abramowitz 16.28.5
  232. # v_2(0, q)**4 + v_4(0, q)**4 == v_3(0, q)**4
  233. term1 = (jtheta(2, zero, q))**4
  234. term2 = (jtheta(4, zero, q))**4
  235. term3 = (jtheta(3, zero, q))**4
  236. equality = term1 + term2 - term3
  237. assert(equality.ae(0, eps1))
  238. mp.dps = 15
  239. def test_jtheta_complex():
  240. mp.dps = 30
  241. z = mpf(1)/4 + j/8
  242. q = mpf(1)/3 + j/7
  243. # Mathematica N[EllipticTheta[1, 1/4 + I/8, 1/3 + I/7], 35]
  244. res = mpf('0.31618034835986160705729105731678285') + \
  245. mpf('0.07542013825835103435142515194358975') * j
  246. r = jtheta(1, z, q)
  247. assert(mpc_ae(r, res))
  248. # Mathematica N[EllipticTheta[2, 1/4 + I/8, 1/3 + I/7], 35]
  249. res = mpf('1.6530986428239765928634711417951828') + \
  250. mpf('0.2015344864707197230526742145361455') * j
  251. r = jtheta(2, z, q)
  252. assert(mpc_ae(r, res))
  253. # Mathematica N[EllipticTheta[3, 1/4 + I/8, 1/3 + I/7], 35]
  254. res = mpf('1.6520564411784228184326012700348340') + \
  255. mpf('0.1998129119671271328684690067401823') * j
  256. r = jtheta(3, z, q)
  257. assert(mpc_ae(r, res))
  258. # Mathematica N[EllipticTheta[4, 1/4 + I/8, 1/3 + I/7], 35]
  259. res = mpf('0.37619082382228348252047624089973824') - \
  260. mpf('0.15623022130983652972686227200681074') * j
  261. r = jtheta(4, z, q)
  262. assert(mpc_ae(r, res))
  263. # check some theta function identities
  264. mp.dos = 100
  265. z = mpf(1)/4 + j/8
  266. q = mpf(1)/3 + j/7
  267. mp.dps += 10
  268. a = [0,0, jtheta(2, 0, q), jtheta(3, 0, q), jtheta(4, 0, q)]
  269. t = [0, jtheta(1, z, q), jtheta(2, z, q), jtheta(3, z, q), jtheta(4, z, q)]
  270. r = [(t[2]*a[4])**2 - (t[4]*a[2])**2 + (t[1] *a[3])**2,
  271. (t[3]*a[4])**2 - (t[4]*a[3])**2 + (t[1] *a[2])**2,
  272. (t[1]*a[4])**2 - (t[3]*a[2])**2 + (t[2] *a[3])**2,
  273. (t[4]*a[4])**2 - (t[3]*a[3])**2 + (t[2] *a[2])**2,
  274. a[2]**4 + a[4]**4 - a[3]**4]
  275. mp.dps -= 10
  276. for x in r:
  277. assert(mpc_ae(x, mpc(0)))
  278. mp.dps = 15
  279. def test_djtheta():
  280. mp.dps = 30
  281. z = one/7 + j/3
  282. q = one/8 + j/5
  283. # Mathematica N[EllipticThetaPrime[1, 1/7 + I/3, 1/8 + I/5], 35]
  284. res = mpf('1.5555195883277196036090928995803201') - \
  285. mpf('0.02439761276895463494054149673076275') * j
  286. result = jtheta(1, z, q, 1)
  287. assert(mpc_ae(result, res))
  288. # Mathematica N[EllipticThetaPrime[2, 1/7 + I/3, 1/8 + I/5], 35]
  289. res = mpf('0.19825296689470982332701283509685662') - \
  290. mpf('0.46038135182282106983251742935250009') * j
  291. result = jtheta(2, z, q, 1)
  292. assert(mpc_ae(result, res))
  293. # Mathematica N[EllipticThetaPrime[3, 1/7 + I/3, 1/8 + I/5], 35]
  294. res = mpf('0.36492498415476212680896699407390026') - \
  295. mpf('0.57743812698666990209897034525640369') * j
  296. result = jtheta(3, z, q, 1)
  297. assert(mpc_ae(result, res))
  298. # Mathematica N[EllipticThetaPrime[4, 1/7 + I/3, 1/8 + I/5], 35]
  299. res = mpf('-0.38936892528126996010818803742007352') + \
  300. mpf('0.66549886179739128256269617407313625') * j
  301. result = jtheta(4, z, q, 1)
  302. assert(mpc_ae(result, res))
  303. for i in range(10):
  304. q = (one*random.random() + j*random.random())/2
  305. # identity in Wittaker, Watson &21.41
  306. a = jtheta(1, 0, q, 1)
  307. b = jtheta(2, 0, q)*jtheta(3, 0, q)*jtheta(4, 0, q)
  308. assert(a.ae(b))
  309. # test higher derivatives
  310. mp.dps = 20
  311. for q,z in [(one/3, one/5), (one/3 + j/8, one/5),
  312. (one/3, one/5 + j/8), (one/3 + j/7, one/5 + j/8)]:
  313. for n in [1, 2, 3, 4]:
  314. r = jtheta(n, z, q, 2)
  315. r1 = diff(lambda zz: jtheta(n, zz, q), z, n=2)
  316. assert r.ae(r1)
  317. r = jtheta(n, z, q, 3)
  318. r1 = diff(lambda zz: jtheta(n, zz, q), z, n=3)
  319. assert r.ae(r1)
  320. # identity in Wittaker, Watson &21.41
  321. q = one/3
  322. z = zero
  323. a = [0]*5
  324. a[1] = jtheta(1, z, q, 3)/jtheta(1, z, q, 1)
  325. for n in [2,3,4]:
  326. a[n] = jtheta(n, z, q, 2)/jtheta(n, z, q)
  327. equality = a[2] + a[3] + a[4] - a[1]
  328. assert(equality.ae(0))
  329. mp.dps = 15
  330. def test_jsn():
  331. """
  332. Test some special cases of the sn(z, q) function.
  333. """
  334. mp.dps = 100
  335. # trival case
  336. result = jsn(zero, zero)
  337. assert(result == zero)
  338. # Abramowitz Table 16.5
  339. #
  340. # sn(0, m) = 0
  341. for i in range(10):
  342. qstring = str(random.random())
  343. q = mpf(qstring)
  344. equality = jsn(zero, q)
  345. assert(equality.ae(0))
  346. # Abramowitz Table 16.6.1
  347. #
  348. # sn(z, 0) = sin(z), m == 0
  349. #
  350. # sn(z, 1) = tanh(z), m == 1
  351. #
  352. # It would be nice to test these, but I find that they run
  353. # in to numerical trouble. I'm currently treating as a boundary
  354. # case for sn function.
  355. mp.dps = 25
  356. arg = one/10
  357. #N[JacobiSN[1/10, 2^-100], 25]
  358. res = mpf('0.09983341664682815230681420')
  359. m = ldexp(one, -100)
  360. result = jsn(arg, m)
  361. assert(result.ae(res))
  362. # N[JacobiSN[1/10, 1/10], 25]
  363. res = mpf('0.09981686718599080096451168')
  364. result = jsn(arg, arg)
  365. assert(result.ae(res))
  366. mp.dps = 15
  367. def test_jcn():
  368. """
  369. Test some special cases of the cn(z, q) function.
  370. """
  371. mp.dps = 100
  372. # Abramowitz Table 16.5
  373. # cn(0, q) = 1
  374. qstring = str(random.random())
  375. q = mpf(qstring)
  376. cn = jcn(zero, q)
  377. assert(cn.ae(one))
  378. # Abramowitz Table 16.6.2
  379. #
  380. # cn(u, 0) = cos(u), m == 0
  381. #
  382. # cn(u, 1) = sech(z), m == 1
  383. #
  384. # It would be nice to test these, but I find that they run
  385. # in to numerical trouble. I'm currently treating as a boundary
  386. # case for cn function.
  387. mp.dps = 25
  388. arg = one/10
  389. m = ldexp(one, -100)
  390. #N[JacobiCN[1/10, 2^-100], 25]
  391. res = mpf('0.9950041652780257660955620')
  392. result = jcn(arg, m)
  393. assert(result.ae(res))
  394. # N[JacobiCN[1/10, 1/10], 25]
  395. res = mpf('0.9950058256237368748520459')
  396. result = jcn(arg, arg)
  397. assert(result.ae(res))
  398. mp.dps = 15
  399. def test_jdn():
  400. """
  401. Test some special cases of the dn(z, q) function.
  402. """
  403. mp.dps = 100
  404. # Abramowitz Table 16.5
  405. # dn(0, q) = 1
  406. mstring = str(random.random())
  407. m = mpf(mstring)
  408. dn = jdn(zero, m)
  409. assert(dn.ae(one))
  410. mp.dps = 25
  411. # N[JacobiDN[1/10, 1/10], 25]
  412. res = mpf('0.9995017055025556219713297')
  413. arg = one/10
  414. result = jdn(arg, arg)
  415. assert(result.ae(res))
  416. mp.dps = 15
  417. def test_sn_cn_dn_identities():
  418. """
  419. Tests the some of the jacobi elliptic function identities found
  420. on Mathworld. Haven't found in Abramowitz.
  421. """
  422. mp.dps = 100
  423. N = 5
  424. for i in range(N):
  425. qstring = str(random.random())
  426. q = mpf(qstring)
  427. zstring = str(100*random.random())
  428. z = mpf(zstring)
  429. # MathWorld
  430. # sn(z, q)**2 + cn(z, q)**2 == 1
  431. term1 = jsn(z, q)**2
  432. term2 = jcn(z, q)**2
  433. equality = one - term1 - term2
  434. assert(equality.ae(0))
  435. # MathWorld
  436. # k**2 * sn(z, m)**2 + dn(z, m)**2 == 1
  437. for i in range(N):
  438. mstring = str(random.random())
  439. m = mpf(qstring)
  440. k = m.sqrt()
  441. zstring = str(10*random.random())
  442. z = mpf(zstring)
  443. term1 = k**2 * jsn(z, m)**2
  444. term2 = jdn(z, m)**2
  445. equality = one - term1 - term2
  446. assert(equality.ae(0))
  447. for i in range(N):
  448. mstring = str(random.random())
  449. m = mpf(mstring)
  450. k = m.sqrt()
  451. zstring = str(random.random())
  452. z = mpf(zstring)
  453. # MathWorld
  454. # k**2 * cn(z, m)**2 + (1 - k**2) = dn(z, m)**2
  455. term1 = k**2 * jcn(z, m)**2
  456. term2 = 1 - k**2
  457. term3 = jdn(z, m)**2
  458. equality = term3 - term1 - term2
  459. assert(equality.ae(0))
  460. K = ellipk(k**2)
  461. # Abramowitz Table 16.5
  462. # sn(K, m) = 1; K is K(k), first complete elliptic integral
  463. r = jsn(K, m)
  464. assert(r.ae(one))
  465. # Abramowitz Table 16.5
  466. # cn(K, q) = 0; K is K(k), first complete elliptic integral
  467. equality = jcn(K, m)
  468. assert(equality.ae(0))
  469. # Abramowitz Table 16.6.3
  470. # dn(z, 0) = 1, m == 0
  471. z = m
  472. value = jdn(z, zero)
  473. assert(value.ae(one))
  474. mp.dps = 15
  475. def test_sn_cn_dn_complex():
  476. mp.dps = 30
  477. # N[JacobiSN[1/4 + I/8, 1/3 + I/7], 35] in Mathematica
  478. res = mpf('0.2495674401066275492326652143537') + \
  479. mpf('0.12017344422863833381301051702823') * j
  480. u = mpf(1)/4 + j/8
  481. m = mpf(1)/3 + j/7
  482. r = jsn(u, m)
  483. assert(mpc_ae(r, res))
  484. #N[JacobiCN[1/4 + I/8, 1/3 + I/7], 35]
  485. res = mpf('0.9762691700944007312693721148331') - \
  486. mpf('0.0307203994181623243583169154824')*j
  487. r = jcn(u, m)
  488. #assert r.real.ae(res.real)
  489. #assert r.imag.ae(res.imag)
  490. assert(mpc_ae(r, res))
  491. #N[JacobiDN[1/4 + I/8, 1/3 + I/7], 35]
  492. res = mpf('0.99639490163039577560547478589753039') - \
  493. mpf('0.01346296520008176393432491077244994')*j
  494. r = jdn(u, m)
  495. assert(mpc_ae(r, res))
  496. mp.dps = 15
  497. def test_elliptic_integrals():
  498. # Test cases from Carlson's paper
  499. mp.dps = 15
  500. assert elliprd(0,2,1).ae(1.7972103521033883112)
  501. assert elliprd(2,3,4).ae(0.16510527294261053349)
  502. assert elliprd(j,-j,2).ae(0.65933854154219768919)
  503. assert elliprd(0,j,-j).ae(1.2708196271909686299 + 2.7811120159520578777j)
  504. assert elliprd(0,j-1,j).ae(-1.8577235439239060056 - 0.96193450888838559989j)
  505. assert elliprd(-2-j,-j,-1+j).ae(1.8249027393703805305 - 1.2218475784827035855j)
  506. # extra test cases
  507. assert elliprg(0,0,0) == 0
  508. assert elliprg(0,0,16).ae(2)
  509. assert elliprg(0,16,0).ae(2)
  510. assert elliprg(16,0,0).ae(2)
  511. assert elliprg(1,4,0).ae(1.2110560275684595248036)
  512. assert elliprg(1,0,4).ae(1.2110560275684595248036)
  513. assert elliprg(0,4,1).ae(1.2110560275684595248036)
  514. # should be symmetric -- fixes a bug present in the paper
  515. x,y,z = 1,1j,-1+1j
  516. assert elliprg(x,y,z).ae(0.64139146875812627545 + 0.58085463774808290907j)
  517. assert elliprg(x,z,y).ae(0.64139146875812627545 + 0.58085463774808290907j)
  518. assert elliprg(y,x,z).ae(0.64139146875812627545 + 0.58085463774808290907j)
  519. assert elliprg(y,z,x).ae(0.64139146875812627545 + 0.58085463774808290907j)
  520. assert elliprg(z,x,y).ae(0.64139146875812627545 + 0.58085463774808290907j)
  521. assert elliprg(z,y,x).ae(0.64139146875812627545 + 0.58085463774808290907j)
  522. for n in [5, 15, 30, 60, 100]:
  523. mp.dps = n
  524. assert elliprf(1,2,0).ae('1.3110287771460599052324197949455597068413774757158115814084108519003952935352071251151477664807145467230678763')
  525. assert elliprf(0.5,1,0).ae('1.854074677301371918433850347195260046217598823521766905585928045056021776838119978357271861650371897277771871')
  526. assert elliprf(j,-j,0).ae('1.854074677301371918433850347195260046217598823521766905585928045056021776838119978357271861650371897277771871')
  527. assert elliprf(j-1,j,0).ae(mpc('0.79612586584233913293056938229563057846592264089185680214929401744498956943287031832657642790719940442165621412',
  528. '-1.2138566698364959864300942567386038975419875860741507618279563735753073152507112254567291141460317931258599889'))
  529. assert elliprf(2,3,4).ae('0.58408284167715170669284916892566789240351359699303216166309375305508295130412919665541330837704050454472379308')
  530. assert elliprf(j,-j,2).ae('1.0441445654064360931078658361850779139591660747973017593275012615517220315993723776182276555339288363064476126')
  531. assert elliprf(j-1,j,1-j).ae(mpc('0.93912050218619371196624617169781141161485651998254431830645241993282941057500174238125105410055253623847335313',
  532. '-0.53296252018635269264859303449447908970360344322834582313172115220559316331271520508208025270300138589669326136'))
  533. assert elliprc(0,0.25).ae(+pi)
  534. assert elliprc(2.25,2).ae(+ln2)
  535. assert elliprc(0,j).ae(mpc('1.1107207345395915617539702475151734246536554223439225557713489017391086982748684776438317336911913093408525532',
  536. '-1.1107207345395915617539702475151734246536554223439225557713489017391086982748684776438317336911913093408525532'))
  537. assert elliprc(-j,j).ae(mpc('1.2260849569072198222319655083097718755633725139745941606203839524036426936825652935738621522906572884239069297',
  538. '-0.34471136988767679699935618332997956653521218571295874986708834375026550946053920574015526038040124556716711353'))
  539. assert elliprc(0.25,-2).ae(ln2/3)
  540. assert elliprc(j,-1).ae(mpc('0.77778596920447389875196055840799837589537035343923012237628610795937014001905822029050288316217145443865649819',
  541. '0.1983248499342877364755170948292130095921681309577950696116251029742793455964385947473103628983664877025779304'))
  542. assert elliprj(0,1,2,3).ae('0.77688623778582332014190282640545501102298064276022952731669118325952563819813258230708177398475643634103990878')
  543. assert elliprj(2,3,4,5).ae('0.14297579667156753833233879421985774801466647854232626336218889885463800128817976132826443904216546421431528308')
  544. assert elliprj(2,3,4,-1+j).ae(mpc('0.13613945827770535203521374457913768360237593025944342652613569368333226052158214183059386307242563164036672709',
  545. '-0.38207561624427164249600936454845112611060375760094156571007648297226090050927156176977091273224510621553615189'))
  546. assert elliprj(j,-j,0,2).ae('1.6490011662710884518243257224860232300246792717163891216346170272567376981346412066066050103935109581019055806')
  547. assert elliprj(-1+j,-1-j,1,2).ae('0.94148358841220238083044612133767270187474673547917988681610772381758628963408843935027667916713866133196845063')
  548. assert elliprj(j,-j,0,1-j).ae(mpc('1.8260115229009316249372594065790946657011067182850435297162034335356430755397401849070610280860044610878657501',
  549. '1.2290661908643471500163617732957042849283739403009556715926326841959667290840290081010472716420690899886276961'))
  550. assert elliprj(-1+j,-1-j,1,-3+j).ae(mpc('-0.61127970812028172123588152373622636829986597243716610650831553882054127570542477508023027578037045504958619422',
  551. '-1.0684038390006807880182112972232562745485871763154040245065581157751693730095703406209466903752930797510491155'))
  552. assert elliprj(-1+j,-2-j,-j,-1+j).ae(mpc('1.8249027393703805304622013339009022294368078659619988943515764258335975852685224202567854526307030593012768954',
  553. '-1.2218475784827035854568450371590419833166777535029296025352291308244564398645467465067845461070602841312456831'))
  554. assert elliprg(0,16,16).ae(+pi)
  555. assert elliprg(2,3,4).ae('1.7255030280692277601061148835701141842692457170470456590515892070736643637303053506944907685301315299153040991')
  556. assert elliprg(0,j,-j).ae('0.42360654239698954330324956174109581824072295516347109253028968632986700241706737986160014699730561497106114281')
  557. assert elliprg(j-1,j,0).ae(mpc('0.44660591677018372656731970402124510811555212083508861036067729944477855594654762496407405328607219895053798354',
  558. '0.70768352357515390073102719507612395221369717586839400605901402910893345301718731499237159587077682267374159282'))
  559. assert elliprg(-j,j-1,j).ae(mpc('0.36023392184473309033675652092928695596803358846377334894215349632203382573844427952830064383286995172598964266',
  560. '0.40348623401722113740956336997761033878615232917480045914551915169013722542827052849476969199578321834819903921'))
  561. assert elliprg(0, mpf('0.0796'), 4).ae('1.0284758090288040009838871385180217366569777284430590125081211090574701293154645750017813190805144572673802094')
  562. mp.dps = 15
  563. # more test cases for the branch of ellippi / elliprj
  564. assert elliprj(-1-0.5j, -10-6j, -10-3j, -5+10j).ae(0.128470516743927699 + 0.102175950778504625j, abs_eps=1e-8)
  565. assert elliprj(1.987, 4.463 - 1.614j, 0, -3.965).ae(-0.341575118513811305 - 0.394703757004268486j, abs_eps=1e-8)
  566. assert elliprj(0.3068, -4.037+0.632j, 1.654, -0.9609).ae(-1.14735199581485639 - 0.134450158867472264j, abs_eps=1e-8)
  567. assert elliprj(0.3068, -4.037-0.632j, 1.654, -0.9609).ae(1.758765901861727 - 0.161002343366626892j, abs_eps=1e-5)
  568. assert elliprj(0.3068, -4.037+0.0632j, 1.654, -0.9609).ae(-1.17157627949475577 - 0.069182614173988811j, abs_eps=1e-8)
  569. assert elliprj(0.3068, -4.037+0.00632j, 1.654, -0.9609).ae(-1.17337595670549633 - 0.0623069224526925j, abs_eps=1e-8)
  570. # these don't work because of inaccurate integration
  571. # assert elliprj(0.3068, -4.037-0.0632j, 1.654, -0.9609).ae(1.77940452391261626 + 0.0388711305592447234j, abs_eps=1e-8)
  572. # assert elliprj(0.3068, -4.037-0.00632j, 1.654, -0.9609).ae(1.77806722756403055 + 0.0592749824572262329j, abs_eps=1e-8)
  573. assert ellippi(2.0-1.0j, 2.0+1.0j).ae(1.8578723151271115 - 1.18642180609983531j)
  574. assert ellippi(2.0-0.5j, 0.5+1.0j).ae(0.936761970766645807 - 1.61876787838890786j)
  575. assert ellippi(2.0, 1.0+1.0j).ae(0.999881420735506708 - 2.4139272867045391j)
  576. assert ellippi(2.0+1.0j, 2.0-1.0j).ae(1.8578723151271115 + 1.18642180609983531j)
  577. assert ellippi(2.0+1.0j, 2.0).ae(2.78474654927885845 + 2.02204728966993314j)
  578. def test_issue_238():
  579. assert isnan(qfrom(m=nan))