PageRenderTime 54ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 1ms

/lib-python/2.7/test/test_math.py

https://bitbucket.org/dac_io/pypy
Python | 1030 lines | 978 code | 21 blank | 31 comment | 41 complexity | 3b80c98ef401c245a0e023d1cf738c61 MD5 | raw file
  1. # Python test set -- math module
  2. # XXXX Should not do tests around zero only
  3. from test.test_support import run_unittest, verbose
  4. import unittest
  5. import math
  6. import os
  7. import sys
  8. import random
  9. import struct
  10. eps = 1E-05
  11. NAN = float('nan')
  12. INF = float('inf')
  13. NINF = float('-inf')
  14. # decorator for skipping tests on non-IEEE 754 platforms
  15. requires_IEEE_754 = unittest.skipUnless(
  16. float.__getformat__("double").startswith("IEEE"),
  17. "test requires IEEE 754 doubles")
  18. # detect evidence of double-rounding: fsum is not always correctly
  19. # rounded on machines that suffer from double rounding.
  20. x, y = 1e16, 2.9999 # use temporary values to defeat peephole optimizer
  21. HAVE_DOUBLE_ROUNDING = (x + y == 1e16 + 4)
  22. # locate file with test values
  23. if __name__ == '__main__':
  24. file = sys.argv[0]
  25. else:
  26. file = __file__
  27. test_dir = os.path.dirname(file) or os.curdir
  28. math_testcases = os.path.join(test_dir, 'math_testcases.txt')
  29. test_file = os.path.join(test_dir, 'cmath_testcases.txt')
  30. def to_ulps(x):
  31. """Convert a non-NaN float x to an integer, in such a way that
  32. adjacent floats are converted to adjacent integers. Then
  33. abs(ulps(x) - ulps(y)) gives the difference in ulps between two
  34. floats.
  35. The results from this function will only make sense on platforms
  36. where C doubles are represented in IEEE 754 binary64 format.
  37. """
  38. n = struct.unpack('<q', struct.pack('<d', x))[0]
  39. if n < 0:
  40. n = ~(n+2**63)
  41. return n
  42. def ulps_check(expected, got, ulps=20):
  43. """Given non-NaN floats `expected` and `got`,
  44. check that they're equal to within the given number of ulps.
  45. Returns None on success and an error message on failure."""
  46. ulps_error = to_ulps(got) - to_ulps(expected)
  47. if abs(ulps_error) <= ulps:
  48. return None
  49. return "error = {} ulps; permitted error = {} ulps".format(ulps_error,
  50. ulps)
  51. def acc_check(expected, got, rel_err=2e-15, abs_err = 5e-323):
  52. """Determine whether non-NaN floats a and b are equal to within a
  53. (small) rounding error. The default values for rel_err and
  54. abs_err are chosen to be suitable for platforms where a float is
  55. represented by an IEEE 754 double. They allow an error of between
  56. 9 and 19 ulps."""
  57. # need to special case infinities, since inf - inf gives nan
  58. if math.isinf(expected) and got == expected:
  59. return None
  60. error = got - expected
  61. permitted_error = max(abs_err, rel_err * abs(expected))
  62. if abs(error) < permitted_error:
  63. return None
  64. return "error = {}; permitted error = {}".format(error,
  65. permitted_error)
  66. def parse_mtestfile(fname):
  67. """Parse a file with test values
  68. -- starts a comment
  69. blank lines, or lines containing only a comment, are ignored
  70. other lines are expected to have the form
  71. id fn arg -> expected [flag]*
  72. """
  73. with open(fname) as fp:
  74. for line in fp:
  75. # strip comments, and skip blank lines
  76. if '--' in line:
  77. line = line[:line.index('--')]
  78. if not line.strip():
  79. continue
  80. lhs, rhs = line.split('->')
  81. id, fn, arg = lhs.split()
  82. rhs_pieces = rhs.split()
  83. exp = rhs_pieces[0]
  84. flags = rhs_pieces[1:]
  85. yield (id, fn, float(arg), float(exp), flags)
  86. def parse_testfile(fname):
  87. """Parse a file with test values
  88. Empty lines or lines starting with -- are ignored
  89. yields id, fn, arg_real, arg_imag, exp_real, exp_imag
  90. """
  91. with open(fname) as fp:
  92. for line in fp:
  93. # skip comment lines and blank lines
  94. if line.startswith('--') or not line.strip():
  95. continue
  96. lhs, rhs = line.split('->')
  97. id, fn, arg_real, arg_imag = lhs.split()
  98. rhs_pieces = rhs.split()
  99. exp_real, exp_imag = rhs_pieces[0], rhs_pieces[1]
  100. flags = rhs_pieces[2:]
  101. yield (id, fn,
  102. float(arg_real), float(arg_imag),
  103. float(exp_real), float(exp_imag),
  104. flags
  105. )
  106. class MathTests(unittest.TestCase):
  107. def ftest(self, name, value, expected):
  108. if abs(value-expected) > eps:
  109. # Use %r instead of %f so the error message
  110. # displays full precision. Otherwise discrepancies
  111. # in the last few bits will lead to very confusing
  112. # error messages
  113. self.fail('%s returned %r, expected %r' %
  114. (name, value, expected))
  115. def testConstants(self):
  116. self.ftest('pi', math.pi, 3.1415926)
  117. self.ftest('e', math.e, 2.7182818)
  118. def testAcos(self):
  119. self.assertRaises(TypeError, math.acos)
  120. self.ftest('acos(-1)', math.acos(-1), math.pi)
  121. self.ftest('acos(0)', math.acos(0), math.pi/2)
  122. self.ftest('acos(1)', math.acos(1), 0)
  123. self.assertRaises(ValueError, math.acos, INF)
  124. self.assertRaises(ValueError, math.acos, NINF)
  125. self.assertTrue(math.isnan(math.acos(NAN)))
  126. def testAcosh(self):
  127. self.assertRaises(TypeError, math.acosh)
  128. self.ftest('acosh(1)', math.acosh(1), 0)
  129. self.ftest('acosh(2)', math.acosh(2), 1.3169578969248168)
  130. self.assertRaises(ValueError, math.acosh, 0)
  131. self.assertRaises(ValueError, math.acosh, -1)
  132. self.assertEqual(math.acosh(INF), INF)
  133. self.assertRaises(ValueError, math.acosh, NINF)
  134. self.assertTrue(math.isnan(math.acosh(NAN)))
  135. def testAsin(self):
  136. self.assertRaises(TypeError, math.asin)
  137. self.ftest('asin(-1)', math.asin(-1), -math.pi/2)
  138. self.ftest('asin(0)', math.asin(0), 0)
  139. self.ftest('asin(1)', math.asin(1), math.pi/2)
  140. self.assertRaises(ValueError, math.asin, INF)
  141. self.assertRaises(ValueError, math.asin, NINF)
  142. self.assertTrue(math.isnan(math.asin(NAN)))
  143. def testAsinh(self):
  144. self.assertRaises(TypeError, math.asinh)
  145. self.ftest('asinh(0)', math.asinh(0), 0)
  146. self.ftest('asinh(1)', math.asinh(1), 0.88137358701954305)
  147. self.ftest('asinh(-1)', math.asinh(-1), -0.88137358701954305)
  148. self.assertEqual(math.asinh(INF), INF)
  149. self.assertEqual(math.asinh(NINF), NINF)
  150. self.assertTrue(math.isnan(math.asinh(NAN)))
  151. def testAtan(self):
  152. self.assertRaises(TypeError, math.atan)
  153. self.ftest('atan(-1)', math.atan(-1), -math.pi/4)
  154. self.ftest('atan(0)', math.atan(0), 0)
  155. self.ftest('atan(1)', math.atan(1), math.pi/4)
  156. self.ftest('atan(inf)', math.atan(INF), math.pi/2)
  157. self.ftest('atan(-inf)', math.atan(NINF), -math.pi/2)
  158. self.assertTrue(math.isnan(math.atan(NAN)))
  159. def testAtanh(self):
  160. self.assertRaises(TypeError, math.atan)
  161. self.ftest('atanh(0)', math.atanh(0), 0)
  162. self.ftest('atanh(0.5)', math.atanh(0.5), 0.54930614433405489)
  163. self.ftest('atanh(-0.5)', math.atanh(-0.5), -0.54930614433405489)
  164. self.assertRaises(ValueError, math.atanh, 1)
  165. self.assertRaises(ValueError, math.atanh, -1)
  166. self.assertRaises(ValueError, math.atanh, INF)
  167. self.assertRaises(ValueError, math.atanh, NINF)
  168. self.assertTrue(math.isnan(math.atanh(NAN)))
  169. def testAtan2(self):
  170. self.assertRaises(TypeError, math.atan2)
  171. self.ftest('atan2(-1, 0)', math.atan2(-1, 0), -math.pi/2)
  172. self.ftest('atan2(-1, 1)', math.atan2(-1, 1), -math.pi/4)
  173. self.ftest('atan2(0, 1)', math.atan2(0, 1), 0)
  174. self.ftest('atan2(1, 1)', math.atan2(1, 1), math.pi/4)
  175. self.ftest('atan2(1, 0)', math.atan2(1, 0), math.pi/2)
  176. # math.atan2(0, x)
  177. self.ftest('atan2(0., -inf)', math.atan2(0., NINF), math.pi)
  178. self.ftest('atan2(0., -2.3)', math.atan2(0., -2.3), math.pi)
  179. self.ftest('atan2(0., -0.)', math.atan2(0., -0.), math.pi)
  180. self.assertEqual(math.atan2(0., 0.), 0.)
  181. self.assertEqual(math.atan2(0., 2.3), 0.)
  182. self.assertEqual(math.atan2(0., INF), 0.)
  183. self.assertTrue(math.isnan(math.atan2(0., NAN)))
  184. # math.atan2(-0, x)
  185. self.ftest('atan2(-0., -inf)', math.atan2(-0., NINF), -math.pi)
  186. self.ftest('atan2(-0., -2.3)', math.atan2(-0., -2.3), -math.pi)
  187. self.ftest('atan2(-0., -0.)', math.atan2(-0., -0.), -math.pi)
  188. self.assertEqual(math.atan2(-0., 0.), -0.)
  189. self.assertEqual(math.atan2(-0., 2.3), -0.)
  190. self.assertEqual(math.atan2(-0., INF), -0.)
  191. self.assertTrue(math.isnan(math.atan2(-0., NAN)))
  192. # math.atan2(INF, x)
  193. self.ftest('atan2(inf, -inf)', math.atan2(INF, NINF), math.pi*3/4)
  194. self.ftest('atan2(inf, -2.3)', math.atan2(INF, -2.3), math.pi/2)
  195. self.ftest('atan2(inf, -0.)', math.atan2(INF, -0.0), math.pi/2)
  196. self.ftest('atan2(inf, 0.)', math.atan2(INF, 0.0), math.pi/2)
  197. self.ftest('atan2(inf, 2.3)', math.atan2(INF, 2.3), math.pi/2)
  198. self.ftest('atan2(inf, inf)', math.atan2(INF, INF), math.pi/4)
  199. self.assertTrue(math.isnan(math.atan2(INF, NAN)))
  200. # math.atan2(NINF, x)
  201. self.ftest('atan2(-inf, -inf)', math.atan2(NINF, NINF), -math.pi*3/4)
  202. self.ftest('atan2(-inf, -2.3)', math.atan2(NINF, -2.3), -math.pi/2)
  203. self.ftest('atan2(-inf, -0.)', math.atan2(NINF, -0.0), -math.pi/2)
  204. self.ftest('atan2(-inf, 0.)', math.atan2(NINF, 0.0), -math.pi/2)
  205. self.ftest('atan2(-inf, 2.3)', math.atan2(NINF, 2.3), -math.pi/2)
  206. self.ftest('atan2(-inf, inf)', math.atan2(NINF, INF), -math.pi/4)
  207. self.assertTrue(math.isnan(math.atan2(NINF, NAN)))
  208. # math.atan2(+finite, x)
  209. self.ftest('atan2(2.3, -inf)', math.atan2(2.3, NINF), math.pi)
  210. self.ftest('atan2(2.3, -0.)', math.atan2(2.3, -0.), math.pi/2)
  211. self.ftest('atan2(2.3, 0.)', math.atan2(2.3, 0.), math.pi/2)
  212. self.assertEqual(math.atan2(2.3, INF), 0.)
  213. self.assertTrue(math.isnan(math.atan2(2.3, NAN)))
  214. # math.atan2(-finite, x)
  215. self.ftest('atan2(-2.3, -inf)', math.atan2(-2.3, NINF), -math.pi)
  216. self.ftest('atan2(-2.3, -0.)', math.atan2(-2.3, -0.), -math.pi/2)
  217. self.ftest('atan2(-2.3, 0.)', math.atan2(-2.3, 0.), -math.pi/2)
  218. self.assertEqual(math.atan2(-2.3, INF), -0.)
  219. self.assertTrue(math.isnan(math.atan2(-2.3, NAN)))
  220. # math.atan2(NAN, x)
  221. self.assertTrue(math.isnan(math.atan2(NAN, NINF)))
  222. self.assertTrue(math.isnan(math.atan2(NAN, -2.3)))
  223. self.assertTrue(math.isnan(math.atan2(NAN, -0.)))
  224. self.assertTrue(math.isnan(math.atan2(NAN, 0.)))
  225. self.assertTrue(math.isnan(math.atan2(NAN, 2.3)))
  226. self.assertTrue(math.isnan(math.atan2(NAN, INF)))
  227. self.assertTrue(math.isnan(math.atan2(NAN, NAN)))
  228. def testCeil(self):
  229. self.assertRaises(TypeError, math.ceil)
  230. # These types will be int in py3k.
  231. self.assertEqual(float, type(math.ceil(1)))
  232. self.assertEqual(float, type(math.ceil(1L)))
  233. self.assertEqual(float, type(math.ceil(1.0)))
  234. self.ftest('ceil(0.5)', math.ceil(0.5), 1)
  235. self.ftest('ceil(1.0)', math.ceil(1.0), 1)
  236. self.ftest('ceil(1.5)', math.ceil(1.5), 2)
  237. self.ftest('ceil(-0.5)', math.ceil(-0.5), 0)
  238. self.ftest('ceil(-1.0)', math.ceil(-1.0), -1)
  239. self.ftest('ceil(-1.5)', math.ceil(-1.5), -1)
  240. self.assertEqual(math.ceil(INF), INF)
  241. self.assertEqual(math.ceil(NINF), NINF)
  242. self.assertTrue(math.isnan(math.ceil(NAN)))
  243. class TestCeil(object):
  244. def __float__(self):
  245. return 41.3
  246. class TestNoCeil(object):
  247. pass
  248. self.ftest('ceil(TestCeil())', math.ceil(TestCeil()), 42)
  249. self.assertRaises(TypeError, math.ceil, TestNoCeil())
  250. t = TestNoCeil()
  251. t.__ceil__ = lambda *args: args
  252. self.assertRaises(TypeError, math.ceil, t)
  253. self.assertRaises(TypeError, math.ceil, t, 0)
  254. @requires_IEEE_754
  255. def testCopysign(self):
  256. self.assertEqual(math.copysign(1, 42), 1.0)
  257. self.assertEqual(math.copysign(0., 42), 0.0)
  258. self.assertEqual(math.copysign(1., -42), -1.0)
  259. self.assertEqual(math.copysign(3, 0.), 3.0)
  260. self.assertEqual(math.copysign(4., -0.), -4.0)
  261. self.assertRaises(TypeError, math.copysign)
  262. # copysign should let us distinguish signs of zeros
  263. self.assertEqual(math.copysign(1., 0.), 1.)
  264. self.assertEqual(math.copysign(1., -0.), -1.)
  265. self.assertEqual(math.copysign(INF, 0.), INF)
  266. self.assertEqual(math.copysign(INF, -0.), NINF)
  267. self.assertEqual(math.copysign(NINF, 0.), INF)
  268. self.assertEqual(math.copysign(NINF, -0.), NINF)
  269. # and of infinities
  270. self.assertEqual(math.copysign(1., INF), 1.)
  271. self.assertEqual(math.copysign(1., NINF), -1.)
  272. self.assertEqual(math.copysign(INF, INF), INF)
  273. self.assertEqual(math.copysign(INF, NINF), NINF)
  274. self.assertEqual(math.copysign(NINF, INF), INF)
  275. self.assertEqual(math.copysign(NINF, NINF), NINF)
  276. self.assertTrue(math.isnan(math.copysign(NAN, 1.)))
  277. self.assertTrue(math.isnan(math.copysign(NAN, INF)))
  278. self.assertTrue(math.isnan(math.copysign(NAN, NINF)))
  279. self.assertTrue(math.isnan(math.copysign(NAN, NAN)))
  280. # copysign(INF, NAN) may be INF or it may be NINF, since
  281. # we don't know whether the sign bit of NAN is set on any
  282. # given platform.
  283. self.assertTrue(math.isinf(math.copysign(INF, NAN)))
  284. # similarly, copysign(2., NAN) could be 2. or -2.
  285. self.assertEqual(abs(math.copysign(2., NAN)), 2.)
  286. def testCos(self):
  287. self.assertRaises(TypeError, math.cos)
  288. self.ftest('cos(-pi/2)', math.cos(-math.pi/2), 0)
  289. self.ftest('cos(0)', math.cos(0), 1)
  290. self.ftest('cos(pi/2)', math.cos(math.pi/2), 0)
  291. self.ftest('cos(pi)', math.cos(math.pi), -1)
  292. try:
  293. self.assertTrue(math.isnan(math.cos(INF)))
  294. self.assertTrue(math.isnan(math.cos(NINF)))
  295. except ValueError:
  296. self.assertRaises(ValueError, math.cos, INF)
  297. self.assertRaises(ValueError, math.cos, NINF)
  298. self.assertTrue(math.isnan(math.cos(NAN)))
  299. def testCosh(self):
  300. self.assertRaises(TypeError, math.cosh)
  301. self.ftest('cosh(0)', math.cosh(0), 1)
  302. self.ftest('cosh(2)-2*cosh(1)**2', math.cosh(2)-2*math.cosh(1)**2, -1) # Thanks to Lambert
  303. self.assertEqual(math.cosh(INF), INF)
  304. self.assertEqual(math.cosh(NINF), INF)
  305. self.assertTrue(math.isnan(math.cosh(NAN)))
  306. def testDegrees(self):
  307. self.assertRaises(TypeError, math.degrees)
  308. self.ftest('degrees(pi)', math.degrees(math.pi), 180.0)
  309. self.ftest('degrees(pi/2)', math.degrees(math.pi/2), 90.0)
  310. self.ftest('degrees(-pi/4)', math.degrees(-math.pi/4), -45.0)
  311. def testExp(self):
  312. self.assertRaises(TypeError, math.exp)
  313. self.ftest('exp(-1)', math.exp(-1), 1/math.e)
  314. self.ftest('exp(0)', math.exp(0), 1)
  315. self.ftest('exp(1)', math.exp(1), math.e)
  316. self.assertEqual(math.exp(INF), INF)
  317. self.assertEqual(math.exp(NINF), 0.)
  318. self.assertTrue(math.isnan(math.exp(NAN)))
  319. def testFabs(self):
  320. self.assertRaises(TypeError, math.fabs)
  321. self.ftest('fabs(-1)', math.fabs(-1), 1)
  322. self.ftest('fabs(0)', math.fabs(0), 0)
  323. self.ftest('fabs(1)', math.fabs(1), 1)
  324. def testFactorial(self):
  325. def fact(n):
  326. result = 1
  327. for i in range(1, int(n)+1):
  328. result *= i
  329. return result
  330. values = range(10) + [50, 100, 500]
  331. random.shuffle(values)
  332. for x in values:
  333. for cast in (int, long, float):
  334. self.assertEqual(math.factorial(cast(x)), fact(x), (x, fact(x), math.factorial(x)))
  335. self.assertRaises(ValueError, math.factorial, -1)
  336. self.assertRaises(ValueError, math.factorial, math.pi)
  337. def testFloor(self):
  338. self.assertRaises(TypeError, math.floor)
  339. # These types will be int in py3k.
  340. self.assertEqual(float, type(math.floor(1)))
  341. self.assertEqual(float, type(math.floor(1L)))
  342. self.assertEqual(float, type(math.floor(1.0)))
  343. self.ftest('floor(0.5)', math.floor(0.5), 0)
  344. self.ftest('floor(1.0)', math.floor(1.0), 1)
  345. self.ftest('floor(1.5)', math.floor(1.5), 1)
  346. self.ftest('floor(-0.5)', math.floor(-0.5), -1)
  347. self.ftest('floor(-1.0)', math.floor(-1.0), -1)
  348. self.ftest('floor(-1.5)', math.floor(-1.5), -2)
  349. # pow() relies on floor() to check for integers
  350. # This fails on some platforms - so check it here
  351. self.ftest('floor(1.23e167)', math.floor(1.23e167), 1.23e167)
  352. self.ftest('floor(-1.23e167)', math.floor(-1.23e167), -1.23e167)
  353. self.assertEqual(math.ceil(INF), INF)
  354. self.assertEqual(math.ceil(NINF), NINF)
  355. self.assertTrue(math.isnan(math.floor(NAN)))
  356. class TestFloor(object):
  357. def __float__(self):
  358. return 42.3
  359. class TestNoFloor(object):
  360. pass
  361. self.ftest('floor(TestFloor())', math.floor(TestFloor()), 42)
  362. self.assertRaises(TypeError, math.floor, TestNoFloor())
  363. t = TestNoFloor()
  364. t.__floor__ = lambda *args: args
  365. self.assertRaises(TypeError, math.floor, t)
  366. self.assertRaises(TypeError, math.floor, t, 0)
  367. def testFmod(self):
  368. self.assertRaises(TypeError, math.fmod)
  369. self.ftest('fmod(10,1)', math.fmod(10,1), 0)
  370. self.ftest('fmod(10,0.5)', math.fmod(10,0.5), 0)
  371. self.ftest('fmod(10,1.5)', math.fmod(10,1.5), 1)
  372. self.ftest('fmod(-10,1)', math.fmod(-10,1), 0)
  373. self.ftest('fmod(-10,0.5)', math.fmod(-10,0.5), 0)
  374. self.ftest('fmod(-10,1.5)', math.fmod(-10,1.5), -1)
  375. self.assertTrue(math.isnan(math.fmod(NAN, 1.)))
  376. self.assertTrue(math.isnan(math.fmod(1., NAN)))
  377. self.assertTrue(math.isnan(math.fmod(NAN, NAN)))
  378. self.assertRaises(ValueError, math.fmod, 1., 0.)
  379. self.assertRaises(ValueError, math.fmod, INF, 1.)
  380. self.assertRaises(ValueError, math.fmod, NINF, 1.)
  381. self.assertRaises(ValueError, math.fmod, INF, 0.)
  382. self.assertEqual(math.fmod(3.0, INF), 3.0)
  383. self.assertEqual(math.fmod(-3.0, INF), -3.0)
  384. self.assertEqual(math.fmod(3.0, NINF), 3.0)
  385. self.assertEqual(math.fmod(-3.0, NINF), -3.0)
  386. self.assertEqual(math.fmod(0.0, 3.0), 0.0)
  387. self.assertEqual(math.fmod(0.0, NINF), 0.0)
  388. def testFrexp(self):
  389. self.assertRaises(TypeError, math.frexp)
  390. def testfrexp(name, result, expected):
  391. (mant, exp), (emant, eexp) = result, expected
  392. if abs(mant-emant) > eps or exp != eexp:
  393. self.fail('%s returned %r, expected %r'%\
  394. (name, (mant, exp), (emant,eexp)))
  395. testfrexp('frexp(-1)', math.frexp(-1), (-0.5, 1))
  396. testfrexp('frexp(0)', math.frexp(0), (0, 0))
  397. testfrexp('frexp(1)', math.frexp(1), (0.5, 1))
  398. testfrexp('frexp(2)', math.frexp(2), (0.5, 2))
  399. self.assertEqual(math.frexp(INF)[0], INF)
  400. self.assertEqual(math.frexp(NINF)[0], NINF)
  401. self.assertTrue(math.isnan(math.frexp(NAN)[0]))
  402. @requires_IEEE_754
  403. @unittest.skipIf(HAVE_DOUBLE_ROUNDING,
  404. "fsum is not exact on machines with double rounding")
  405. def testFsum(self):
  406. # math.fsum relies on exact rounding for correct operation.
  407. # There's a known problem with IA32 floating-point that causes
  408. # inexact rounding in some situations, and will cause the
  409. # math.fsum tests below to fail; see issue #2937. On non IEEE
  410. # 754 platforms, and on IEEE 754 platforms that exhibit the
  411. # problem described in issue #2937, we simply skip the whole
  412. # test.
  413. # Python version of math.fsum, for comparison. Uses a
  414. # different algorithm based on frexp, ldexp and integer
  415. # arithmetic.
  416. from sys import float_info
  417. mant_dig = float_info.mant_dig
  418. etiny = float_info.min_exp - mant_dig
  419. def msum(iterable):
  420. """Full precision summation. Compute sum(iterable) without any
  421. intermediate accumulation of error. Based on the 'lsum' function
  422. at http://code.activestate.com/recipes/393090/
  423. """
  424. tmant, texp = 0, 0
  425. for x in iterable:
  426. mant, exp = math.frexp(x)
  427. mant, exp = int(math.ldexp(mant, mant_dig)), exp - mant_dig
  428. if texp > exp:
  429. tmant <<= texp-exp
  430. texp = exp
  431. else:
  432. mant <<= exp-texp
  433. tmant += mant
  434. # Round tmant * 2**texp to a float. The original recipe
  435. # used float(str(tmant)) * 2.0**texp for this, but that's
  436. # a little unsafe because str -> float conversion can't be
  437. # relied upon to do correct rounding on all platforms.
  438. tail = max(len(bin(abs(tmant)))-2 - mant_dig, etiny - texp)
  439. if tail > 0:
  440. h = 1 << (tail-1)
  441. tmant = tmant // (2*h) + bool(tmant & h and tmant & 3*h-1)
  442. texp += tail
  443. return math.ldexp(tmant, texp)
  444. test_values = [
  445. ([], 0.0),
  446. ([0.0], 0.0),
  447. ([1e100, 1.0, -1e100, 1e-100, 1e50, -1.0, -1e50], 1e-100),
  448. ([2.0**53, -0.5, -2.0**-54], 2.0**53-1.0),
  449. ([2.0**53, 1.0, 2.0**-100], 2.0**53+2.0),
  450. ([2.0**53+10.0, 1.0, 2.0**-100], 2.0**53+12.0),
  451. ([2.0**53-4.0, 0.5, 2.0**-54], 2.0**53-3.0),
  452. ([1./n for n in range(1, 1001)],
  453. float.fromhex('0x1.df11f45f4e61ap+2')),
  454. ([(-1.)**n/n for n in range(1, 1001)],
  455. float.fromhex('-0x1.62a2af1bd3624p-1')),
  456. ([1.7**(i+1)-1.7**i for i in range(1000)] + [-1.7**1000], -1.0),
  457. ([1e16, 1., 1e-16], 10000000000000002.0),
  458. ([1e16-2., 1.-2.**-53, -(1e16-2.), -(1.-2.**-53)], 0.0),
  459. # exercise code for resizing partials array
  460. ([2.**n - 2.**(n+50) + 2.**(n+52) for n in range(-1074, 972, 2)] +
  461. [-2.**1022],
  462. float.fromhex('0x1.5555555555555p+970')),
  463. ]
  464. for i, (vals, expected) in enumerate(test_values):
  465. try:
  466. actual = math.fsum(vals)
  467. except OverflowError:
  468. self.fail("test %d failed: got OverflowError, expected %r "
  469. "for math.fsum(%.100r)" % (i, expected, vals))
  470. except ValueError:
  471. self.fail("test %d failed: got ValueError, expected %r "
  472. "for math.fsum(%.100r)" % (i, expected, vals))
  473. self.assertEqual(actual, expected)
  474. from random import random, gauss, shuffle
  475. for j in xrange(1000):
  476. vals = [7, 1e100, -7, -1e100, -9e-20, 8e-20] * 10
  477. s = 0
  478. for i in xrange(200):
  479. v = gauss(0, random()) ** 7 - s
  480. s += v
  481. vals.append(v)
  482. shuffle(vals)
  483. s = msum(vals)
  484. self.assertEqual(msum(vals), math.fsum(vals))
  485. def testHypot(self):
  486. self.assertRaises(TypeError, math.hypot)
  487. self.ftest('hypot(0,0)', math.hypot(0,0), 0)
  488. self.ftest('hypot(3,4)', math.hypot(3,4), 5)
  489. self.assertEqual(math.hypot(NAN, INF), INF)
  490. self.assertEqual(math.hypot(INF, NAN), INF)
  491. self.assertEqual(math.hypot(NAN, NINF), INF)
  492. self.assertEqual(math.hypot(NINF, NAN), INF)
  493. self.assertTrue(math.isnan(math.hypot(1.0, NAN)))
  494. self.assertTrue(math.isnan(math.hypot(NAN, -2.0)))
  495. def testLdexp(self):
  496. self.assertRaises(TypeError, math.ldexp)
  497. self.ftest('ldexp(0,1)', math.ldexp(0,1), 0)
  498. self.ftest('ldexp(1,1)', math.ldexp(1,1), 2)
  499. self.ftest('ldexp(1,-1)', math.ldexp(1,-1), 0.5)
  500. self.ftest('ldexp(-1,1)', math.ldexp(-1,1), -2)
  501. self.assertRaises(OverflowError, math.ldexp, 1., 1000000)
  502. self.assertRaises(OverflowError, math.ldexp, -1., 1000000)
  503. self.assertEqual(math.ldexp(1., -1000000), 0.)
  504. self.assertEqual(math.ldexp(-1., -1000000), -0.)
  505. self.assertEqual(math.ldexp(INF, 30), INF)
  506. self.assertEqual(math.ldexp(NINF, -213), NINF)
  507. self.assertTrue(math.isnan(math.ldexp(NAN, 0)))
  508. # large second argument
  509. for n in [10**5, 10L**5, 10**10, 10L**10, 10**20, 10**40]:
  510. self.assertEqual(math.ldexp(INF, -n), INF)
  511. self.assertEqual(math.ldexp(NINF, -n), NINF)
  512. self.assertEqual(math.ldexp(1., -n), 0.)
  513. self.assertEqual(math.ldexp(-1., -n), -0.)
  514. self.assertEqual(math.ldexp(0., -n), 0.)
  515. self.assertEqual(math.ldexp(-0., -n), -0.)
  516. self.assertTrue(math.isnan(math.ldexp(NAN, -n)))
  517. self.assertRaises(OverflowError, math.ldexp, 1., n)
  518. self.assertRaises(OverflowError, math.ldexp, -1., n)
  519. self.assertEqual(math.ldexp(0., n), 0.)
  520. self.assertEqual(math.ldexp(-0., n), -0.)
  521. self.assertEqual(math.ldexp(INF, n), INF)
  522. self.assertEqual(math.ldexp(NINF, n), NINF)
  523. self.assertTrue(math.isnan(math.ldexp(NAN, n)))
  524. def testLog(self):
  525. self.assertRaises(TypeError, math.log)
  526. self.ftest('log(1/e)', math.log(1/math.e), -1)
  527. self.ftest('log(1)', math.log(1), 0)
  528. self.ftest('log(e)', math.log(math.e), 1)
  529. self.ftest('log(32,2)', math.log(32,2), 5)
  530. self.ftest('log(10**40, 10)', math.log(10**40, 10), 40)
  531. self.ftest('log(10**40, 10**20)', math.log(10**40, 10**20), 2)
  532. self.assertEqual(math.log(INF), INF)
  533. self.assertRaises(ValueError, math.log, NINF)
  534. self.assertTrue(math.isnan(math.log(NAN)))
  535. def testLog1p(self):
  536. self.assertRaises(TypeError, math.log1p)
  537. self.ftest('log1p(1/e -1)', math.log1p(1/math.e-1), -1)
  538. self.ftest('log1p(0)', math.log1p(0), 0)
  539. self.ftest('log1p(e-1)', math.log1p(math.e-1), 1)
  540. self.ftest('log1p(1)', math.log1p(1), math.log(2))
  541. self.assertEqual(math.log1p(INF), INF)
  542. self.assertRaises(ValueError, math.log1p, NINF)
  543. self.assertTrue(math.isnan(math.log1p(NAN)))
  544. n= 2**90
  545. self.assertAlmostEqual(math.log1p(n), 62.383246250395075)
  546. self.assertAlmostEqual(math.log1p(n), math.log1p(float(n)))
  547. def testLog10(self):
  548. self.assertRaises(TypeError, math.log10)
  549. self.ftest('log10(0.1)', math.log10(0.1), -1)
  550. self.ftest('log10(1)', math.log10(1), 0)
  551. self.ftest('log10(10)', math.log10(10), 1)
  552. self.assertEqual(math.log(INF), INF)
  553. self.assertRaises(ValueError, math.log10, NINF)
  554. self.assertTrue(math.isnan(math.log10(NAN)))
  555. def testModf(self):
  556. self.assertRaises(TypeError, math.modf)
  557. def testmodf(name, result, expected):
  558. (v1, v2), (e1, e2) = result, expected
  559. if abs(v1-e1) > eps or abs(v2-e2):
  560. self.fail('%s returned %r, expected %r'%\
  561. (name, (v1,v2), (e1,e2)))
  562. testmodf('modf(1.5)', math.modf(1.5), (0.5, 1.0))
  563. testmodf('modf(-1.5)', math.modf(-1.5), (-0.5, -1.0))
  564. self.assertEqual(math.modf(INF), (0.0, INF))
  565. self.assertEqual(math.modf(NINF), (-0.0, NINF))
  566. modf_nan = math.modf(NAN)
  567. self.assertTrue(math.isnan(modf_nan[0]))
  568. self.assertTrue(math.isnan(modf_nan[1]))
  569. def testPow(self):
  570. self.assertRaises(TypeError, math.pow)
  571. self.ftest('pow(0,1)', math.pow(0,1), 0)
  572. self.ftest('pow(1,0)', math.pow(1,0), 1)
  573. self.ftest('pow(2,1)', math.pow(2,1), 2)
  574. self.ftest('pow(2,-1)', math.pow(2,-1), 0.5)
  575. self.assertEqual(math.pow(INF, 1), INF)
  576. self.assertEqual(math.pow(NINF, 1), NINF)
  577. self.assertEqual((math.pow(1, INF)), 1.)
  578. self.assertEqual((math.pow(1, NINF)), 1.)
  579. self.assertTrue(math.isnan(math.pow(NAN, 1)))
  580. self.assertTrue(math.isnan(math.pow(2, NAN)))
  581. self.assertTrue(math.isnan(math.pow(0, NAN)))
  582. self.assertEqual(math.pow(1, NAN), 1)
  583. # pow(0., x)
  584. self.assertEqual(math.pow(0., INF), 0.)
  585. self.assertEqual(math.pow(0., 3.), 0.)
  586. self.assertEqual(math.pow(0., 2.3), 0.)
  587. self.assertEqual(math.pow(0., 2.), 0.)
  588. self.assertEqual(math.pow(0., 0.), 1.)
  589. self.assertEqual(math.pow(0., -0.), 1.)
  590. self.assertRaises(ValueError, math.pow, 0., -2.)
  591. self.assertRaises(ValueError, math.pow, 0., -2.3)
  592. self.assertRaises(ValueError, math.pow, 0., -3.)
  593. self.assertRaises(ValueError, math.pow, 0., NINF)
  594. self.assertTrue(math.isnan(math.pow(0., NAN)))
  595. # pow(INF, x)
  596. self.assertEqual(math.pow(INF, INF), INF)
  597. self.assertEqual(math.pow(INF, 3.), INF)
  598. self.assertEqual(math.pow(INF, 2.3), INF)
  599. self.assertEqual(math.pow(INF, 2.), INF)
  600. self.assertEqual(math.pow(INF, 0.), 1.)
  601. self.assertEqual(math.pow(INF, -0.), 1.)
  602. self.assertEqual(math.pow(INF, -2.), 0.)
  603. self.assertEqual(math.pow(INF, -2.3), 0.)
  604. self.assertEqual(math.pow(INF, -3.), 0.)
  605. self.assertEqual(math.pow(INF, NINF), 0.)
  606. self.assertTrue(math.isnan(math.pow(INF, NAN)))
  607. # pow(-0., x)
  608. self.assertEqual(math.pow(-0., INF), 0.)
  609. self.assertEqual(math.pow(-0., 3.), -0.)
  610. self.assertEqual(math.pow(-0., 2.3), 0.)
  611. self.assertEqual(math.pow(-0., 2.), 0.)
  612. self.assertEqual(math.pow(-0., 0.), 1.)
  613. self.assertEqual(math.pow(-0., -0.), 1.)
  614. self.assertRaises(ValueError, math.pow, -0., -2.)
  615. self.assertRaises(ValueError, math.pow, -0., -2.3)
  616. self.assertRaises(ValueError, math.pow, -0., -3.)
  617. self.assertRaises(ValueError, math.pow, -0., NINF)
  618. self.assertTrue(math.isnan(math.pow(-0., NAN)))
  619. # pow(NINF, x)
  620. self.assertEqual(math.pow(NINF, INF), INF)
  621. self.assertEqual(math.pow(NINF, 3.), NINF)
  622. self.assertEqual(math.pow(NINF, 2.3), INF)
  623. self.assertEqual(math.pow(NINF, 2.), INF)
  624. self.assertEqual(math.pow(NINF, 0.), 1.)
  625. self.assertEqual(math.pow(NINF, -0.), 1.)
  626. self.assertEqual(math.pow(NINF, -2.), 0.)
  627. self.assertEqual(math.pow(NINF, -2.3), 0.)
  628. self.assertEqual(math.pow(NINF, -3.), -0.)
  629. self.assertEqual(math.pow(NINF, NINF), 0.)
  630. self.assertTrue(math.isnan(math.pow(NINF, NAN)))
  631. # pow(-1, x)
  632. self.assertEqual(math.pow(-1., INF), 1.)
  633. self.assertEqual(math.pow(-1., 3.), -1.)
  634. self.assertRaises(ValueError, math.pow, -1., 2.3)
  635. self.assertEqual(math.pow(-1., 2.), 1.)
  636. self.assertEqual(math.pow(-1., 0.), 1.)
  637. self.assertEqual(math.pow(-1., -0.), 1.)
  638. self.assertEqual(math.pow(-1., -2.), 1.)
  639. self.assertRaises(ValueError, math.pow, -1., -2.3)
  640. self.assertEqual(math.pow(-1., -3.), -1.)
  641. self.assertEqual(math.pow(-1., NINF), 1.)
  642. self.assertTrue(math.isnan(math.pow(-1., NAN)))
  643. # pow(1, x)
  644. self.assertEqual(math.pow(1., INF), 1.)
  645. self.assertEqual(math.pow(1., 3.), 1.)
  646. self.assertEqual(math.pow(1., 2.3), 1.)
  647. self.assertEqual(math.pow(1., 2.), 1.)
  648. self.assertEqual(math.pow(1., 0.), 1.)
  649. self.assertEqual(math.pow(1., -0.), 1.)
  650. self.assertEqual(math.pow(1., -2.), 1.)
  651. self.assertEqual(math.pow(1., -2.3), 1.)
  652. self.assertEqual(math.pow(1., -3.), 1.)
  653. self.assertEqual(math.pow(1., NINF), 1.)
  654. self.assertEqual(math.pow(1., NAN), 1.)
  655. # pow(x, 0) should be 1 for any x
  656. self.assertEqual(math.pow(2.3, 0.), 1.)
  657. self.assertEqual(math.pow(-2.3, 0.), 1.)
  658. self.assertEqual(math.pow(NAN, 0.), 1.)
  659. self.assertEqual(math.pow(2.3, -0.), 1.)
  660. self.assertEqual(math.pow(-2.3, -0.), 1.)
  661. self.assertEqual(math.pow(NAN, -0.), 1.)
  662. # pow(x, y) is invalid if x is negative and y is not integral
  663. self.assertRaises(ValueError, math.pow, -1., 2.3)
  664. self.assertRaises(ValueError, math.pow, -15., -3.1)
  665. # pow(x, NINF)
  666. self.assertEqual(math.pow(1.9, NINF), 0.)
  667. self.assertEqual(math.pow(1.1, NINF), 0.)
  668. self.assertEqual(math.pow(0.9, NINF), INF)
  669. self.assertEqual(math.pow(0.1, NINF), INF)
  670. self.assertEqual(math.pow(-0.1, NINF), INF)
  671. self.assertEqual(math.pow(-0.9, NINF), INF)
  672. self.assertEqual(math.pow(-1.1, NINF), 0.)
  673. self.assertEqual(math.pow(-1.9, NINF), 0.)
  674. # pow(x, INF)
  675. self.assertEqual(math.pow(1.9, INF), INF)
  676. self.assertEqual(math.pow(1.1, INF), INF)
  677. self.assertEqual(math.pow(0.9, INF), 0.)
  678. self.assertEqual(math.pow(0.1, INF), 0.)
  679. self.assertEqual(math.pow(-0.1, INF), 0.)
  680. self.assertEqual(math.pow(-0.9, INF), 0.)
  681. self.assertEqual(math.pow(-1.1, INF), INF)
  682. self.assertEqual(math.pow(-1.9, INF), INF)
  683. # pow(x, y) should work for x negative, y an integer
  684. self.ftest('(-2.)**3.', math.pow(-2.0, 3.0), -8.0)
  685. self.ftest('(-2.)**2.', math.pow(-2.0, 2.0), 4.0)
  686. self.ftest('(-2.)**1.', math.pow(-2.0, 1.0), -2.0)
  687. self.ftest('(-2.)**0.', math.pow(-2.0, 0.0), 1.0)
  688. self.ftest('(-2.)**-0.', math.pow(-2.0, -0.0), 1.0)
  689. self.ftest('(-2.)**-1.', math.pow(-2.0, -1.0), -0.5)
  690. self.ftest('(-2.)**-2.', math.pow(-2.0, -2.0), 0.25)
  691. self.ftest('(-2.)**-3.', math.pow(-2.0, -3.0), -0.125)
  692. self.assertRaises(ValueError, math.pow, -2.0, -0.5)
  693. self.assertRaises(ValueError, math.pow, -2.0, 0.5)
  694. # the following tests have been commented out since they don't
  695. # really belong here: the implementation of ** for floats is
  696. # independent of the implementation of math.pow
  697. #self.assertEqual(1**NAN, 1)
  698. #self.assertEqual(1**INF, 1)
  699. #self.assertEqual(1**NINF, 1)
  700. #self.assertEqual(1**0, 1)
  701. #self.assertEqual(1.**NAN, 1)
  702. #self.assertEqual(1.**INF, 1)
  703. #self.assertEqual(1.**NINF, 1)
  704. #self.assertEqual(1.**0, 1)
  705. def testRadians(self):
  706. self.assertRaises(TypeError, math.radians)
  707. self.ftest('radians(180)', math.radians(180), math.pi)
  708. self.ftest('radians(90)', math.radians(90), math.pi/2)
  709. self.ftest('radians(-45)', math.radians(-45), -math.pi/4)
  710. def testSin(self):
  711. self.assertRaises(TypeError, math.sin)
  712. self.ftest('sin(0)', math.sin(0), 0)
  713. self.ftest('sin(pi/2)', math.sin(math.pi/2), 1)
  714. self.ftest('sin(-pi/2)', math.sin(-math.pi/2), -1)
  715. try:
  716. self.assertTrue(math.isnan(math.sin(INF)))
  717. self.assertTrue(math.isnan(math.sin(NINF)))
  718. except ValueError:
  719. self.assertRaises(ValueError, math.sin, INF)
  720. self.assertRaises(ValueError, math.sin, NINF)
  721. self.assertTrue(math.isnan(math.sin(NAN)))
  722. def testSinh(self):
  723. self.assertRaises(TypeError, math.sinh)
  724. self.ftest('sinh(0)', math.sinh(0), 0)
  725. self.ftest('sinh(1)**2-cosh(1)**2', math.sinh(1)**2-math.cosh(1)**2, -1)
  726. self.ftest('sinh(1)+sinh(-1)', math.sinh(1)+math.sinh(-1), 0)
  727. self.assertEqual(math.sinh(INF), INF)
  728. self.assertEqual(math.sinh(NINF), NINF)
  729. self.assertTrue(math.isnan(math.sinh(NAN)))
  730. def testSqrt(self):
  731. self.assertRaises(TypeError, math.sqrt)
  732. self.ftest('sqrt(0)', math.sqrt(0), 0)
  733. self.ftest('sqrt(1)', math.sqrt(1), 1)
  734. self.ftest('sqrt(4)', math.sqrt(4), 2)
  735. self.assertEqual(math.sqrt(INF), INF)
  736. self.assertRaises(ValueError, math.sqrt, NINF)
  737. self.assertTrue(math.isnan(math.sqrt(NAN)))
  738. def testTan(self):
  739. self.assertRaises(TypeError, math.tan)
  740. self.ftest('tan(0)', math.tan(0), 0)
  741. self.ftest('tan(pi/4)', math.tan(math.pi/4), 1)
  742. self.ftest('tan(-pi/4)', math.tan(-math.pi/4), -1)
  743. try:
  744. self.assertTrue(math.isnan(math.tan(INF)))
  745. self.assertTrue(math.isnan(math.tan(NINF)))
  746. except:
  747. self.assertRaises(ValueError, math.tan, INF)
  748. self.assertRaises(ValueError, math.tan, NINF)
  749. self.assertTrue(math.isnan(math.tan(NAN)))
  750. def testTanh(self):
  751. self.assertRaises(TypeError, math.tanh)
  752. self.ftest('tanh(0)', math.tanh(0), 0)
  753. self.ftest('tanh(1)+tanh(-1)', math.tanh(1)+math.tanh(-1), 0)
  754. self.ftest('tanh(inf)', math.tanh(INF), 1)
  755. self.ftest('tanh(-inf)', math.tanh(NINF), -1)
  756. self.assertTrue(math.isnan(math.tanh(NAN)))
  757. # check that tanh(-0.) == -0. on IEEE 754 systems
  758. if float.__getformat__("double").startswith("IEEE"):
  759. self.assertEqual(math.tanh(-0.), -0.)
  760. self.assertEqual(math.copysign(1., math.tanh(-0.)),
  761. math.copysign(1., -0.))
  762. def test_trunc(self):
  763. self.assertEqual(math.trunc(1), 1)
  764. self.assertEqual(math.trunc(-1), -1)
  765. self.assertEqual(type(math.trunc(1)), int)
  766. self.assertEqual(type(math.trunc(1.5)), int)
  767. self.assertEqual(math.trunc(1.5), 1)
  768. self.assertEqual(math.trunc(-1.5), -1)
  769. self.assertEqual(math.trunc(1.999999), 1)
  770. self.assertEqual(math.trunc(-1.999999), -1)
  771. self.assertEqual(math.trunc(-0.999999), -0)
  772. self.assertEqual(math.trunc(-100.999), -100)
  773. class TestTrunc(object):
  774. def __trunc__(self):
  775. return 23
  776. class TestNoTrunc(object):
  777. pass
  778. self.assertEqual(math.trunc(TestTrunc()), 23)
  779. self.assertRaises(TypeError, math.trunc)
  780. self.assertRaises(TypeError, math.trunc, 1, 2)
  781. self.assertRaises((AttributeError, TypeError), math.trunc,
  782. TestNoTrunc())
  783. def testIsnan(self):
  784. self.assertTrue(math.isnan(float("nan")))
  785. self.assertTrue(math.isnan(float("inf")* 0.))
  786. self.assertFalse(math.isnan(float("inf")))
  787. self.assertFalse(math.isnan(0.))
  788. self.assertFalse(math.isnan(1.))
  789. def testIsinf(self):
  790. self.assertTrue(math.isinf(float("inf")))
  791. self.assertTrue(math.isinf(float("-inf")))
  792. self.assertTrue(math.isinf(1E400))
  793. self.assertTrue(math.isinf(-1E400))
  794. self.assertFalse(math.isinf(float("nan")))
  795. self.assertFalse(math.isinf(0.))
  796. self.assertFalse(math.isinf(1.))
  797. # RED_FLAG 16-Oct-2000 Tim
  798. # While 2.0 is more consistent about exceptions than previous releases, it
  799. # still fails this part of the test on some platforms. For now, we only
  800. # *run* test_exceptions() in verbose mode, so that this isn't normally
  801. # tested.
  802. if verbose:
  803. def test_exceptions(self):
  804. try:
  805. x = math.exp(-1000000000)
  806. except:
  807. # mathmodule.c is failing to weed out underflows from libm, or
  808. # we've got an fp format with huge dynamic range
  809. self.fail("underflowing exp() should not have raised "
  810. "an exception")
  811. if x != 0:
  812. self.fail("underflowing exp() should have returned 0")
  813. # If this fails, probably using a strict IEEE-754 conforming libm, and x
  814. # is +Inf afterwards. But Python wants overflows detected by default.
  815. try:
  816. x = math.exp(1000000000)
  817. except OverflowError:
  818. pass
  819. else:
  820. self.fail("overflowing exp() didn't trigger OverflowError")
  821. # If this fails, it could be a puzzle. One odd possibility is that
  822. # mathmodule.c's macros are getting confused while comparing
  823. # Inf (HUGE_VAL) to a NaN, and artificially setting errno to ERANGE
  824. # as a result (and so raising OverflowError instead).
  825. try:
  826. x = math.sqrt(-1.0)
  827. except ValueError:
  828. pass
  829. else:
  830. self.fail("sqrt(-1) didn't raise ValueError")
  831. @requires_IEEE_754
  832. def test_testfile(self):
  833. for id, fn, ar, ai, er, ei, flags in parse_testfile(test_file):
  834. # Skip if either the input or result is complex, or if
  835. # flags is nonempty
  836. if ai != 0. or ei != 0. or flags:
  837. continue
  838. if fn in ['rect', 'polar']:
  839. # no real versions of rect, polar
  840. continue
  841. func = getattr(math, fn)
  842. try:
  843. result = func(ar)
  844. except ValueError:
  845. message = ("Unexpected ValueError in " +
  846. "test %s:%s(%r)\n" % (id, fn, ar))
  847. self.fail(message)
  848. except OverflowError:
  849. message = ("Unexpected OverflowError in " +
  850. "test %s:%s(%r)\n" % (id, fn, ar))
  851. self.fail(message)
  852. self.ftest("%s:%s(%r)" % (id, fn, ar), result, er)
  853. @unittest.skipUnless(float.__getformat__("double").startswith("IEEE"),
  854. "test requires IEEE 754 doubles")
  855. def test_mtestfile(self):
  856. ALLOWED_ERROR = 20 # permitted error, in ulps
  857. fail_fmt = "{}:{}({!r}): expected {!r}, got {!r}"
  858. failures = []
  859. for id, fn, arg, expected, flags in parse_mtestfile(math_testcases):
  860. func = getattr(math, fn)
  861. if 'invalid' in flags or 'divide-by-zero' in flags:
  862. expected = 'ValueError'
  863. elif 'overflow' in flags:
  864. expected = 'OverflowError'
  865. try:
  866. got = func(arg)
  867. except ValueError:
  868. got = 'ValueError'
  869. except OverflowError:
  870. got = 'OverflowError'
  871. accuracy_failure = None
  872. if isinstance(got, float) and isinstance(expected, float):
  873. if math.isnan(expected) and math.isnan(got):
  874. continue
  875. if not math.isnan(expected) and not math.isnan(got):
  876. if fn == 'lgamma':
  877. # we use a weaker accuracy test for lgamma;
  878. # lgamma only achieves an absolute error of
  879. # a few multiples of the machine accuracy, in
  880. # general.
  881. accuracy_failure = acc_check(expected, got,
  882. rel_err = 5e-15,
  883. abs_err = 5e-15)
  884. elif fn == 'erfc':
  885. # erfc has less-than-ideal accuracy for large
  886. # arguments (x ~ 25 or so), mainly due to the
  887. # error involved in computing exp(-x*x).
  888. #
  889. # XXX Would be better to weaken this test only
  890. # for large x, instead of for all x.
  891. accuracy_failure = ulps_check(expected, got, 2000)
  892. else:
  893. accuracy_failure = ulps_check(expected, got, 20)
  894. if accuracy_failure is None:
  895. continue
  896. if isinstance(got, str) and isinstance(expected, str):
  897. if got == expected:
  898. continue
  899. fail_msg = fail_fmt.format(id, fn, arg, expected, got)
  900. if accuracy_failure is not None:
  901. fail_msg += ' ({})'.format(accuracy_failure)
  902. failures.append(fail_msg)
  903. if failures:
  904. self.fail('Failures in test_mtestfile:\n ' +
  905. '\n '.join(failures))
  906. def test_main():
  907. from doctest import DocFileSuite
  908. suite = unittest.TestSuite()
  909. suite.addTest(unittest.makeSuite(MathTests))
  910. suite.addTest(DocFileSuite("ieee754.txt"))
  911. run_unittest(suite)
  912. if __name__ == '__main__':
  913. test_main()