PageRenderTime 164ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/External.LCA_RESTRICTED/Languages/IronPython/27/Lib/test/test_long_future.py

https://github.com/jdhardy/ironpython
Python | 221 lines | 138 code | 33 blank | 50 comment | 37 complexity | 7fbd783edfe6fc828aa765abea8aeb43 MD5 | raw file
  1. from __future__ import division
  2. # When true division is the default, get rid of this and add it to
  3. # test_long.py instead. In the meantime, it's too obscure to try to
  4. # trick just part of test_long into using future division.
  5. import sys
  6. import random
  7. import math
  8. import unittest
  9. from test.test_support import run_unittest
  10. # decorator for skipping tests on non-IEEE 754 platforms
  11. requires_IEEE_754 = unittest.skipUnless(
  12. float.__getformat__("double").startswith("IEEE"),
  13. "test requires IEEE 754 doubles")
  14. DBL_MAX = sys.float_info.max
  15. DBL_MAX_EXP = sys.float_info.max_exp
  16. DBL_MIN_EXP = sys.float_info.min_exp
  17. DBL_MANT_DIG = sys.float_info.mant_dig
  18. DBL_MIN_OVERFLOW = 2**DBL_MAX_EXP - 2**(DBL_MAX_EXP - DBL_MANT_DIG - 1)
  19. # pure Python version of correctly-rounded true division
  20. def truediv(a, b):
  21. """Correctly-rounded true division for integers."""
  22. negative = a^b < 0
  23. a, b = abs(a), abs(b)
  24. # exceptions: division by zero, overflow
  25. if not b:
  26. raise ZeroDivisionError("division by zero")
  27. if a >= DBL_MIN_OVERFLOW * b:
  28. raise OverflowError("int/int too large to represent as a float")
  29. # find integer d satisfying 2**(d - 1) <= a/b < 2**d
  30. d = a.bit_length() - b.bit_length()
  31. if d >= 0 and a >= 2**d * b or d < 0 and a * 2**-d >= b:
  32. d += 1
  33. # compute 2**-exp * a / b for suitable exp
  34. exp = max(d, DBL_MIN_EXP) - DBL_MANT_DIG
  35. a, b = a << max(-exp, 0), b << max(exp, 0)
  36. q, r = divmod(a, b)
  37. # round-half-to-even: fractional part is r/b, which is > 0.5 iff
  38. # 2*r > b, and == 0.5 iff 2*r == b.
  39. if 2*r > b or 2*r == b and q % 2 == 1:
  40. q += 1
  41. result = math.ldexp(float(q), exp)
  42. return -result if negative else result
  43. class TrueDivisionTests(unittest.TestCase):
  44. def test(self):
  45. huge = 1L << 40000
  46. mhuge = -huge
  47. self.assertEqual(huge / huge, 1.0)
  48. self.assertEqual(mhuge / mhuge, 1.0)
  49. self.assertEqual(huge / mhuge, -1.0)
  50. self.assertEqual(mhuge / huge, -1.0)
  51. self.assertEqual(1 / huge, 0.0)
  52. self.assertEqual(1L / huge, 0.0)
  53. self.assertEqual(1 / mhuge, 0.0)
  54. self.assertEqual(1L / mhuge, 0.0)
  55. self.assertEqual((666 * huge + (huge >> 1)) / huge, 666.5)
  56. self.assertEqual((666 * mhuge + (mhuge >> 1)) / mhuge, 666.5)
  57. self.assertEqual((666 * huge + (huge >> 1)) / mhuge, -666.5)
  58. self.assertEqual((666 * mhuge + (mhuge >> 1)) / huge, -666.5)
  59. self.assertEqual(huge / (huge << 1), 0.5)
  60. self.assertEqual((1000000 * huge) / huge, 1000000)
  61. namespace = {'huge': huge, 'mhuge': mhuge}
  62. for overflow in ["float(huge)", "float(mhuge)",
  63. "huge / 1", "huge / 2L", "huge / -1", "huge / -2L",
  64. "mhuge / 100", "mhuge / 100L"]:
  65. # If the "eval" does not happen in this module,
  66. # true division is not enabled
  67. with self.assertRaises(OverflowError):
  68. eval(overflow, namespace)
  69. for underflow in ["1 / huge", "2L / huge", "-1 / huge", "-2L / huge",
  70. "100 / mhuge", "100L / mhuge"]:
  71. result = eval(underflow, namespace)
  72. self.assertEqual(result, 0.0, 'expected underflow to 0 '
  73. 'from {!r}'.format(underflow))
  74. for zero in ["huge / 0", "huge / 0L", "mhuge / 0", "mhuge / 0L"]:
  75. with self.assertRaises(ZeroDivisionError):
  76. eval(zero, namespace)
  77. def check_truediv(self, a, b, skip_small=True):
  78. """Verify that the result of a/b is correctly rounded, by
  79. comparing it with a pure Python implementation of correctly
  80. rounded division. b should be nonzero."""
  81. a, b = long(a), long(b)
  82. # skip check for small a and b: in this case, the current
  83. # implementation converts the arguments to float directly and
  84. # then applies a float division. This can give doubly-rounded
  85. # results on x87-using machines (particularly 32-bit Linux).
  86. if skip_small and max(abs(a), abs(b)) < 2**DBL_MANT_DIG:
  87. return
  88. try:
  89. # use repr so that we can distinguish between -0.0 and 0.0
  90. expected = repr(truediv(a, b))
  91. except OverflowError:
  92. expected = 'overflow'
  93. except ZeroDivisionError:
  94. expected = 'zerodivision'
  95. try:
  96. got = repr(a / b)
  97. except OverflowError:
  98. got = 'overflow'
  99. except ZeroDivisionError:
  100. got = 'zerodivision'
  101. self.assertEqual(expected, got, "Incorrectly rounded division {}/{}: "
  102. "expected {}, got {}".format(a, b, expected, got))
  103. @requires_IEEE_754
  104. def test_correctly_rounded_true_division(self):
  105. # more stringent tests than those above, checking that the
  106. # result of true division of ints is always correctly rounded.
  107. # This test should probably be considered CPython-specific.
  108. # Exercise all the code paths not involving Gb-sized ints.
  109. # ... divisions involving zero
  110. self.check_truediv(123, 0)
  111. self.check_truediv(-456, 0)
  112. self.check_truediv(0, 3)
  113. self.check_truediv(0, -3)
  114. self.check_truediv(0, 0)
  115. # ... overflow or underflow by large margin
  116. self.check_truediv(671 * 12345 * 2**DBL_MAX_EXP, 12345)
  117. self.check_truediv(12345, 345678 * 2**(DBL_MANT_DIG - DBL_MIN_EXP))
  118. # ... a much larger or smaller than b
  119. self.check_truediv(12345*2**100, 98765)
  120. self.check_truediv(12345*2**30, 98765*7**81)
  121. # ... a / b near a boundary: one of 1, 2**DBL_MANT_DIG, 2**DBL_MIN_EXP,
  122. # 2**DBL_MAX_EXP, 2**(DBL_MIN_EXP-DBL_MANT_DIG)
  123. bases = (0, DBL_MANT_DIG, DBL_MIN_EXP,
  124. DBL_MAX_EXP, DBL_MIN_EXP - DBL_MANT_DIG)
  125. for base in bases:
  126. for exp in range(base - 15, base + 15):
  127. self.check_truediv(75312*2**max(exp, 0), 69187*2**max(-exp, 0))
  128. self.check_truediv(69187*2**max(exp, 0), 75312*2**max(-exp, 0))
  129. # overflow corner case
  130. for m in [1, 2, 7, 17, 12345, 7**100,
  131. -1, -2, -5, -23, -67891, -41**50]:
  132. for n in range(-10, 10):
  133. self.check_truediv(m*DBL_MIN_OVERFLOW + n, m)
  134. self.check_truediv(m*DBL_MIN_OVERFLOW + n, -m)
  135. # check detection of inexactness in shifting stage
  136. for n in range(250):
  137. # (2**DBL_MANT_DIG+1)/(2**DBL_MANT_DIG) lies halfway
  138. # between two representable floats, and would usually be
  139. # rounded down under round-half-to-even. The tiniest of
  140. # additions to the numerator should cause it to be rounded
  141. # up instead.
  142. self.check_truediv((2**DBL_MANT_DIG + 1)*12345*2**200 + 2**n,
  143. 2**DBL_MANT_DIG*12345)
  144. # 1/2731 is one of the smallest division cases that's subject
  145. # to double rounding on IEEE 754 machines working internally with
  146. # 64-bit precision. On such machines, the next check would fail,
  147. # were it not explicitly skipped in check_truediv.
  148. self.check_truediv(1, 2731)
  149. # a particularly bad case for the old algorithm: gives an
  150. # error of close to 3.5 ulps.
  151. self.check_truediv(295147931372582273023, 295147932265116303360)
  152. for i in range(1000):
  153. self.check_truediv(10**(i+1), 10**i)
  154. self.check_truediv(10**i, 10**(i+1))
  155. # test round-half-to-even behaviour, normal result
  156. for m in [1, 2, 4, 7, 8, 16, 17, 32, 12345, 7**100,
  157. -1, -2, -5, -23, -67891, -41**50]:
  158. for n in range(-10, 10):
  159. self.check_truediv(2**DBL_MANT_DIG*m + n, m)
  160. # test round-half-to-even, subnormal result
  161. for n in range(-20, 20):
  162. self.check_truediv(n, 2**1076)
  163. # largeish random divisions: a/b where |a| <= |b| <=
  164. # 2*|a|; |ans| is between 0.5 and 1.0, so error should
  165. # always be bounded by 2**-54 with equality possible only
  166. # if the least significant bit of q=ans*2**53 is zero.
  167. for M in [10**10, 10**100, 10**1000]:
  168. for i in range(1000):
  169. a = random.randrange(1, M)
  170. b = random.randrange(a, 2*a+1)
  171. self.check_truediv(a, b)
  172. self.check_truediv(-a, b)
  173. self.check_truediv(a, -b)
  174. self.check_truediv(-a, -b)
  175. # and some (genuinely) random tests
  176. for _ in range(10000):
  177. a_bits = random.randrange(1000)
  178. b_bits = random.randrange(1, 1000)
  179. x = random.randrange(2**a_bits)
  180. y = random.randrange(1, 2**b_bits)
  181. self.check_truediv(x, y)
  182. self.check_truediv(x, -y)
  183. self.check_truediv(-x, y)
  184. self.check_truediv(-x, -y)
  185. def test_main():
  186. run_unittest(TrueDivisionTests)
  187. if __name__ == "__main__":
  188. test_main()