PageRenderTime 62ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/pypy/module/math/test/test_math.py

https://bitbucket.org/pypy/pypy/
Python | 207 lines | 176 code | 23 blank | 8 comment | 30 complexity | ad0833924daa59ef4fba0d39bd78e5e7 MD5 | raw file
Possible License(s): AGPL-3.0, BSD-3-Clause, Apache-2.0
  1. from __future__ import with_statement
  2. import py
  3. from pypy.interpreter.function import Function
  4. from pypy.interpreter.gateway import BuiltinCode
  5. from pypy.module.math.test import test_direct
  6. class AppTestMath:
  7. spaceconfig = {
  8. "usemodules": ['math', 'struct', 'itertools', 'time', 'binascii'],
  9. }
  10. def setup_class(cls):
  11. space = cls.space
  12. cases = []
  13. for a, b, expected in test_direct.MathTests.TESTCASES:
  14. if type(expected) is type and issubclass(expected, Exception):
  15. expected = getattr(space, "w_%s" % expected.__name__)
  16. elif callable(expected):
  17. if not cls.runappdirect:
  18. expected = cls.make_callable_wrapper(expected)
  19. else:
  20. expected = space.wrap(expected)
  21. cases.append(space.newtuple([space.wrap(a), space.wrap(b), expected]))
  22. cls.w_cases = space.newlist(cases)
  23. cls.w_consistent_host = space.wrap(test_direct.consistent_host)
  24. @classmethod
  25. def make_callable_wrapper(cls, func):
  26. def f(space, w_x):
  27. return space.wrap(func(space.unwrap(w_x)))
  28. return Function(cls.space, BuiltinCode(f))
  29. def w_ftest(self, actual, expected):
  30. assert abs(actual - expected) < 10E-5
  31. def test_all_cases(self):
  32. if not self.consistent_host:
  33. skip("please test this on top of PyPy or CPython >= 2.6")
  34. import math
  35. for fnname, args, expected in self.cases:
  36. fn = getattr(math, fnname)
  37. print fn, args
  38. try:
  39. got = fn(*args)
  40. except ValueError:
  41. assert expected == ValueError
  42. except OverflowError:
  43. assert expected == OverflowError
  44. else:
  45. if type(expected) is type(Exception):
  46. ok = False
  47. elif callable(expected):
  48. ok = expected(got)
  49. else:
  50. gotsign = expectedsign = 1
  51. if got < 0.0: gotsign = -gotsign
  52. if expected < 0.0: expectedsign = -expectedsign
  53. ok = got == expected and gotsign == expectedsign
  54. if not ok:
  55. raise AssertionError("%s(%s): got %s" % (
  56. fnname, ', '.join(map(str, args)), got))
  57. def test_ldexp(self):
  58. import math
  59. assert math.ldexp(float("inf"), -10**20) == float("inf")
  60. def test_fsum(self):
  61. import math
  62. # detect evidence of double-rounding: fsum is not always correctly
  63. # rounded on machines that suffer from double rounding.
  64. # It is a known problem with IA32 floating-point arithmetic.
  65. # It should work fine e.g. with x86-64.
  66. x, y = 1e16, 2.9999 # use temporary values to defeat peephole optimizer
  67. HAVE_DOUBLE_ROUNDING = (x + y == 1e16 + 4)
  68. if HAVE_DOUBLE_ROUNDING:
  69. skip("fsum is not exact on machines with double rounding")
  70. test_values = [
  71. ([], 0.0),
  72. ([0.0], 0.0),
  73. ([1e100, 1.0, -1e100, 1e-100, 1e50, -1.0, -1e50], 1e-100),
  74. ([2.0**53, -0.5, -2.0**-54], 2.0**53-1.0),
  75. ([2.0**53, 1.0, 2.0**-100], 2.0**53+2.0),
  76. ([2.0**53+10.0, 1.0, 2.0**-100], 2.0**53+12.0),
  77. ([2.0**53-4.0, 0.5, 2.0**-54], 2.0**53-3.0),
  78. ([1./n for n in range(1, 1001)],
  79. float.fromhex('0x1.df11f45f4e61ap+2')),
  80. ([(-1.)**n/n for n in range(1, 1001)],
  81. float.fromhex('-0x1.62a2af1bd3624p-1')),
  82. ([1.7**(i+1)-1.7**i for i in range(1000)] + [-1.7**1000], -1.0),
  83. ([1e16, 1., 1e-16], 10000000000000002.0),
  84. ([1e16-2., 1.-2.**-53, -(1e16-2.), -(1.-2.**-53)], 0.0),
  85. # exercise code for resizing partials array
  86. ([2.**n - 2.**(n+50) + 2.**(n+52) for n in range(-1074, 972, 2)] +
  87. [-2.**1022],
  88. float.fromhex('0x1.5555555555555p+970')),
  89. # infinity and nans
  90. ([float("inf")], float("inf")),
  91. ([float("-inf")], float("-inf")),
  92. ([float("nan")], float("nan")),
  93. ]
  94. for i, (vals, expected) in enumerate(test_values):
  95. try:
  96. actual = math.fsum(vals)
  97. except OverflowError:
  98. py.test.fail("test %d failed: got OverflowError, expected %r "
  99. "for math.fsum(%.100r)" % (i, expected, vals))
  100. except ValueError:
  101. py.test.fail("test %d failed: got ValueError, expected %r "
  102. "for math.fsum(%.100r)" % (i, expected, vals))
  103. assert actual == expected or (
  104. math.isnan(actual) and math.isnan(expected))
  105. def test_factorial(self):
  106. import math
  107. assert math.factorial(0) == 1
  108. assert math.factorial(1) == 1
  109. assert math.factorial(2) == 2
  110. assert math.factorial(5) == 120
  111. assert math.factorial(5.) == 120
  112. raises(ValueError, math.factorial, -1)
  113. raises(ValueError, math.factorial, -1.)
  114. raises(ValueError, math.factorial, 1.1)
  115. def test_log1p(self):
  116. import math
  117. self.ftest(math.log1p(1/math.e-1), -1)
  118. self.ftest(math.log1p(0), 0)
  119. self.ftest(math.log1p(math.e-1), 1)
  120. self.ftest(math.log1p(1), math.log(2))
  121. def test_acosh(self):
  122. import math
  123. self.ftest(math.acosh(1), 0)
  124. self.ftest(math.acosh(2), 1.3169578969248168)
  125. assert math.isinf(math.asinh(float("inf")))
  126. raises(ValueError, math.acosh, 0)
  127. def test_asinh(self):
  128. import math
  129. self.ftest(math.asinh(0), 0)
  130. self.ftest(math.asinh(1), 0.88137358701954305)
  131. self.ftest(math.asinh(-1), -0.88137358701954305)
  132. assert math.isinf(math.asinh(float("inf")))
  133. def test_atanh(self):
  134. import math
  135. self.ftest(math.atanh(0), 0)
  136. self.ftest(math.atanh(0.5), 0.54930614433405489)
  137. self.ftest(math.atanh(-0.5), -0.54930614433405489)
  138. raises(ValueError, math.atanh, 1.)
  139. assert math.isnan(math.atanh(float("nan")))
  140. def test_trunc(self):
  141. import math
  142. assert math.trunc(1.9) == 1.0
  143. raises((AttributeError, TypeError), math.trunc, 1.9j)
  144. class foo(object):
  145. def __trunc__(self):
  146. return "truncated"
  147. assert math.trunc(foo()) == "truncated"
  148. def test_copysign_nan(self):
  149. skip('sign of nan is undefined')
  150. import math
  151. assert math.copysign(1.0, float('-nan')) == -1.0
  152. def test_erf(self):
  153. import math
  154. assert math.erf(100.0) == 1.0
  155. assert math.erf(-1000.0) == -1.0
  156. assert math.erf(float("inf")) == 1.0
  157. assert math.erf(float("-inf")) == -1.0
  158. assert math.isnan(math.erf(float("nan")))
  159. # proper tests are in rpython/rlib/test/test_rfloat
  160. assert round(math.erf(1.0), 9) == 0.842700793
  161. def test_erfc(self):
  162. import math
  163. assert math.erfc(0.0) == 1.0
  164. assert math.erfc(-0.0) == 1.0
  165. assert math.erfc(float("inf")) == 0.0
  166. assert math.erfc(float("-inf")) == 2.0
  167. assert math.isnan(math.erf(float("nan")))
  168. assert math.erfc(1e-308) == 1.0
  169. def test_gamma(self):
  170. import math
  171. assert raises(ValueError, math.gamma, 0.0)
  172. assert math.gamma(5.0) == 24.0
  173. assert math.gamma(6.0) == 120.0
  174. assert raises(ValueError, math.gamma, -1)
  175. assert math.gamma(0.5) == math.pi ** 0.5
  176. def test_lgamma(self):
  177. import math
  178. math.lgamma(1.0) == 0.0
  179. math.lgamma(2.0) == 0.0
  180. # proper tests are in rpython/rlib/test/test_rfloat
  181. assert round(math.lgamma(5.0), 9) == round(math.log(24.0), 9)
  182. assert round(math.lgamma(6.0), 9) == round(math.log(120.0), 9)
  183. assert raises(ValueError, math.gamma, -1)
  184. assert round(math.lgamma(0.5), 9) == round(math.log(math.pi ** 0.5), 9)