torture.py 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. """
  2. Torture tests for asymptotics and high precision evaluation of
  3. special functions.
  4. (Other torture tests may also be placed here.)
  5. Running this file (gmpy recommended!) takes several CPU minutes.
  6. With Python 2.6+, multiprocessing is used automatically to run tests
  7. in parallel if many cores are available. (A single test may take between
  8. a second and several minutes; possibly more.)
  9. The idea:
  10. * We evaluate functions at positive, negative, imaginary, 45- and 135-degree
  11. complex values with magnitudes between 10^-20 to 10^20, at precisions between
  12. 5 and 150 digits (we can go even higher for fast functions).
  13. * Comparing the result from two different precision levels provides
  14. a strong consistency check (particularly for functions that use
  15. different algorithms at different precision levels).
  16. * That the computation finishes at all (without failure), within reasonable
  17. time, provides a check that evaluation works at all: that the code runs,
  18. that it doesn't get stuck in an infinite loop, and that it doesn't use
  19. some extremely slowly algorithm where it could use a faster one.
  20. TODO:
  21. * Speed up those functions that take long to finish!
  22. * Generalize to test more cases; more options.
  23. * Implement a timeout mechanism.
  24. * Some functions are notably absent, including the following:
  25. * inverse trigonometric functions (some become inaccurate for complex arguments)
  26. * ci, si (not implemented properly for large complex arguments)
  27. * zeta functions (need to modify test not to try too large imaginary values)
  28. * and others...
  29. """
  30. import sys, os
  31. from timeit import default_timer as clock
  32. if "-nogmpy" in sys.argv:
  33. sys.argv.remove('-nogmpy')
  34. os.environ['MPMATH_NOGMPY'] = 'Y'
  35. filt = ''
  36. if not sys.argv[-1].endswith(".py"):
  37. filt = sys.argv[-1]
  38. from mpmath import *
  39. from mpmath.libmp.backend import exec_
  40. def test_asymp(f, maxdps=150, verbose=False, huge_range=False):
  41. dps = [5,15,25,50,90,150,500,1500,5000,10000]
  42. dps = [p for p in dps if p <= maxdps]
  43. def check(x,y,p,inpt):
  44. if abs(x-y)/abs(y) < workprec(20)(power)(10, -p+1):
  45. return
  46. print()
  47. print("Error!")
  48. print("Input:", inpt)
  49. print("dps =", p)
  50. print("Result 1:", x)
  51. print("Result 2:", y)
  52. print("Absolute error:", abs(x-y))
  53. print("Relative error:", abs(x-y)/abs(y))
  54. raise AssertionError
  55. exponents = range(-20,20)
  56. if huge_range:
  57. exponents += [-1000, -100, -50, 50, 100, 1000]
  58. for n in exponents:
  59. if verbose:
  60. sys.stdout.write(". ")
  61. mp.dps = 25
  62. xpos = mpf(10)**n / 1.1287
  63. xneg = -xpos
  64. ximag = xpos*j
  65. xcomplex1 = xpos*(1+j)
  66. xcomplex2 = xpos*(-1+j)
  67. for i in range(len(dps)):
  68. if verbose:
  69. print("Testing dps = %s" % dps[i])
  70. mp.dps = dps[i]
  71. new = f(xpos), f(xneg), f(ximag), f(xcomplex1), f(xcomplex2)
  72. if i != 0:
  73. p = dps[i-1]
  74. check(prev[0], new[0], p, xpos)
  75. check(prev[1], new[1], p, xneg)
  76. check(prev[2], new[2], p, ximag)
  77. check(prev[3], new[3], p, xcomplex1)
  78. check(prev[4], new[4], p, xcomplex2)
  79. prev = new
  80. if verbose:
  81. print()
  82. a1, a2, a3, a4, a5 = 1.5, -2.25, 3.125, 4, 2
  83. def test_bernoulli_huge():
  84. p, q = bernfrac(9000)
  85. assert p % 10**10 == 9636701091
  86. assert q == 4091851784687571609141381951327092757255270
  87. mp.dps = 15
  88. assert str(bernoulli(10**100)) == '-2.58183325604736e+987675256497386331227838638980680030172857347883537824464410652557820800494271520411283004120790908623'
  89. mp.dps = 50
  90. assert str(bernoulli(10**100)) == '-2.5818332560473632073252488656039475548106223822913e+987675256497386331227838638980680030172857347883537824464410652557820800494271520411283004120790908623'
  91. mp.dps = 15
  92. cases = """\
  93. test_bernoulli_huge()
  94. test_asymp(lambda z: +pi, maxdps=10000)
  95. test_asymp(lambda z: +e, maxdps=10000)
  96. test_asymp(lambda z: +ln2, maxdps=10000)
  97. test_asymp(lambda z: +ln10, maxdps=10000)
  98. test_asymp(lambda z: +phi, maxdps=10000)
  99. test_asymp(lambda z: +catalan, maxdps=5000)
  100. test_asymp(lambda z: +euler, maxdps=5000)
  101. test_asymp(lambda z: +glaisher, maxdps=1000)
  102. test_asymp(lambda z: +khinchin, maxdps=1000)
  103. test_asymp(lambda z: +twinprime, maxdps=150)
  104. test_asymp(lambda z: stieltjes(2), maxdps=150)
  105. test_asymp(lambda z: +mertens, maxdps=150)
  106. test_asymp(lambda z: +apery, maxdps=5000)
  107. test_asymp(sqrt, maxdps=10000, huge_range=True)
  108. test_asymp(cbrt, maxdps=5000, huge_range=True)
  109. test_asymp(lambda z: root(z,4), maxdps=5000, huge_range=True)
  110. test_asymp(lambda z: root(z,-5), maxdps=5000, huge_range=True)
  111. test_asymp(exp, maxdps=5000, huge_range=True)
  112. test_asymp(expm1, maxdps=1500)
  113. test_asymp(ln, maxdps=5000, huge_range=True)
  114. test_asymp(cosh, maxdps=5000)
  115. test_asymp(sinh, maxdps=5000)
  116. test_asymp(tanh, maxdps=1500)
  117. test_asymp(sin, maxdps=5000, huge_range=True)
  118. test_asymp(cos, maxdps=5000, huge_range=True)
  119. test_asymp(tan, maxdps=1500)
  120. test_asymp(agm, maxdps=1500, huge_range=True)
  121. test_asymp(ellipk, maxdps=1500)
  122. test_asymp(ellipe, maxdps=1500)
  123. test_asymp(lambertw, huge_range=True)
  124. test_asymp(lambda z: lambertw(z,-1))
  125. test_asymp(lambda z: lambertw(z,1))
  126. test_asymp(lambda z: lambertw(z,4))
  127. test_asymp(gamma)
  128. test_asymp(loggamma) # huge_range=True ?
  129. test_asymp(ei)
  130. test_asymp(e1)
  131. test_asymp(li, huge_range=True)
  132. test_asymp(ci)
  133. test_asymp(si)
  134. test_asymp(chi)
  135. test_asymp(shi)
  136. test_asymp(erf)
  137. test_asymp(erfc)
  138. test_asymp(erfi)
  139. test_asymp(lambda z: besselj(2, z))
  140. test_asymp(lambda z: bessely(2, z))
  141. test_asymp(lambda z: besseli(2, z))
  142. test_asymp(lambda z: besselk(2, z))
  143. test_asymp(lambda z: besselj(-2.25, z))
  144. test_asymp(lambda z: bessely(-2.25, z))
  145. test_asymp(lambda z: besseli(-2.25, z))
  146. test_asymp(lambda z: besselk(-2.25, z))
  147. test_asymp(airyai)
  148. test_asymp(airybi)
  149. test_asymp(lambda z: hyp0f1(a1, z))
  150. test_asymp(lambda z: hyp1f1(a1, a2, z))
  151. test_asymp(lambda z: hyp1f2(a1, a2, a3, z))
  152. test_asymp(lambda z: hyp2f0(a1, a2, z))
  153. test_asymp(lambda z: hyperu(a1, a2, z))
  154. test_asymp(lambda z: hyp2f1(a1, a2, a3, z))
  155. test_asymp(lambda z: hyp2f2(a1, a2, a3, a4, z))
  156. test_asymp(lambda z: hyp2f3(a1, a2, a3, a4, a5, z))
  157. test_asymp(lambda z: coulombf(a1, a2, z))
  158. test_asymp(lambda z: coulombg(a1, a2, z))
  159. test_asymp(lambda z: polylog(2,z))
  160. test_asymp(lambda z: polylog(3,z))
  161. test_asymp(lambda z: polylog(-2,z))
  162. test_asymp(lambda z: expint(4, z))
  163. test_asymp(lambda z: expint(-4, z))
  164. test_asymp(lambda z: expint(2.25, z))
  165. test_asymp(lambda z: gammainc(2.5, z, 5))
  166. test_asymp(lambda z: gammainc(2.5, 5, z))
  167. test_asymp(lambda z: hermite(3, z))
  168. test_asymp(lambda z: hermite(2.5, z))
  169. test_asymp(lambda z: legendre(3, z))
  170. test_asymp(lambda z: legendre(4, z))
  171. test_asymp(lambda z: legendre(2.5, z))
  172. test_asymp(lambda z: legenp(a1, a2, z))
  173. test_asymp(lambda z: legenq(a1, a2, z), maxdps=90) # abnormally slow
  174. test_asymp(lambda z: jtheta(1, z, 0.5))
  175. test_asymp(lambda z: jtheta(2, z, 0.5))
  176. test_asymp(lambda z: jtheta(3, z, 0.5))
  177. test_asymp(lambda z: jtheta(4, z, 0.5))
  178. test_asymp(lambda z: jtheta(1, z, 0.5, 1))
  179. test_asymp(lambda z: jtheta(2, z, 0.5, 1))
  180. test_asymp(lambda z: jtheta(3, z, 0.5, 1))
  181. test_asymp(lambda z: jtheta(4, z, 0.5, 1))
  182. test_asymp(barnesg, maxdps=90)
  183. """
  184. def testit(line):
  185. if filt in line:
  186. print(line)
  187. t1 = clock()
  188. exec_(line, globals(), locals())
  189. t2 = clock()
  190. elapsed = t2-t1
  191. print("Time:", elapsed, "for", line, "(OK)")
  192. if __name__ == '__main__':
  193. try:
  194. from multiprocessing import Pool
  195. mapf = Pool(None).map
  196. print("Running tests with multiprocessing")
  197. except ImportError:
  198. print("Not using multiprocessing")
  199. mapf = map
  200. t1 = clock()
  201. tasks = cases.splitlines()
  202. mapf(testit, tasks)
  203. t2 = clock()
  204. print("Cumulative wall time:", t2-t1)