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.
10 from test
.test_support
import run_unittest
12 # decorator for skipping tests on non-IEEE 754 platforms
13 requires_IEEE_754
= unittest
.skipUnless(
14 float.__getformat
__("double").startswith("IEEE"),
15 "test requires IEEE 754 doubles")
17 DBL_MAX
= sys
.float_info
.max
18 DBL_MAX_EXP
= sys
.float_info
.max_exp
19 DBL_MIN_EXP
= sys
.float_info
.min_exp
20 DBL_MANT_DIG
= sys
.float_info
.mant_dig
21 DBL_MIN_OVERFLOW
= 2**DBL_MAX_EXP
- 2**(DBL_MAX_EXP
- DBL_MANT_DIG
- 1)
23 # pure Python version of correctly-rounded true division
25 """Correctly-rounded true division for integers."""
29 # exceptions: division by zero, overflow
31 raise ZeroDivisionError("division by zero")
32 if a
>= DBL_MIN_OVERFLOW
* b
:
33 raise OverflowError("int/int too large to represent as a float")
35 # find integer d satisfying 2**(d - 1) <= a/b < 2**d
36 d
= a
.bit_length() - b
.bit_length()
37 if d
>= 0 and a
>= 2**d
* b
or d
< 0 and a
* 2**-d
>= b
:
40 # compute 2**-exp * a / b for suitable exp
41 exp
= max(d
, DBL_MIN_EXP
) - DBL_MANT_DIG
42 a
, b
= a
<< max(-exp
, 0), b
<< max(exp
, 0)
45 # round-half-to-even: fractional part is r/b, which is > 0.5 iff
46 # 2*r > b, and == 0.5 iff 2*r == b.
47 if 2*r
> b
or 2*r
== b
and q
% 2 == 1:
50 result
= math
.ldexp(float(q
), exp
)
51 return -result
if negative
else result
53 class TrueDivisionTests(unittest
.TestCase
):
57 self
.assertEqual(huge
/ huge
, 1.0)
58 self
.assertEqual(mhuge
/ mhuge
, 1.0)
59 self
.assertEqual(huge
/ mhuge
, -1.0)
60 self
.assertEqual(mhuge
/ huge
, -1.0)
61 self
.assertEqual(1 / huge
, 0.0)
62 self
.assertEqual(1L / huge
, 0.0)
63 self
.assertEqual(1 / mhuge
, 0.0)
64 self
.assertEqual(1L / mhuge
, 0.0)
65 self
.assertEqual((666 * huge
+ (huge
>> 1)) / huge
, 666.5)
66 self
.assertEqual((666 * mhuge
+ (mhuge
>> 1)) / mhuge
, 666.5)
67 self
.assertEqual((666 * huge
+ (huge
>> 1)) / mhuge
, -666.5)
68 self
.assertEqual((666 * mhuge
+ (mhuge
>> 1)) / huge
, -666.5)
69 self
.assertEqual(huge
/ (huge
<< 1), 0.5)
70 self
.assertEqual((1000000 * huge
) / huge
, 1000000)
72 namespace
= {'huge': huge
, 'mhuge': mhuge
}
74 for overflow
in ["float(huge)", "float(mhuge)",
75 "huge / 1", "huge / 2L", "huge / -1", "huge / -2L",
76 "mhuge / 100", "mhuge / 100L"]:
77 # If the "eval" does not happen in this module,
78 # true division is not enabled
79 with self
.assertRaises(OverflowError):
80 eval(overflow
, namespace
)
82 for underflow
in ["1 / huge", "2L / huge", "-1 / huge", "-2L / huge",
83 "100 / mhuge", "100L / mhuge"]:
84 result
= eval(underflow
, namespace
)
85 self
.assertEqual(result
, 0.0, 'expected underflow to 0 '
86 'from {!r}'.format(underflow
))
88 for zero
in ["huge / 0", "huge / 0L", "mhuge / 0", "mhuge / 0L"]:
89 with self
.assertRaises(ZeroDivisionError):
92 def check_truediv(self
, a
, b
, skip_small
=True):
93 """Verify that the result of a/b is correctly rounded, by
94 comparing it with a pure Python implementation of correctly
95 rounded division. b should be nonzero."""
97 a
, b
= long(a
), long(b
)
99 # skip check for small a and b: in this case, the current
100 # implementation converts the arguments to float directly and
101 # then applies a float division. This can give doubly-rounded
102 # results on x87-using machines (particularly 32-bit Linux).
103 if skip_small
and max(abs(a
), abs(b
)) < 2**DBL_MANT_DIG
:
107 # use repr so that we can distinguish between -0.0 and 0.0
108 expected
= repr(truediv(a
, b
))
109 except OverflowError:
110 expected
= 'overflow'
111 except ZeroDivisionError:
112 expected
= 'zerodivision'
116 except OverflowError:
118 except ZeroDivisionError:
121 self
.assertEqual(expected
, got
, "Incorrectly rounded division {}/{}: "
122 "expected {}, got {}".format(a
, b
, expected
, got
))
125 def test_correctly_rounded_true_division(self
):
126 # more stringent tests than those above, checking that the
127 # result of true division of ints is always correctly rounded.
128 # This test should probably be considered CPython-specific.
130 # Exercise all the code paths not involving Gb-sized ints.
131 # ... divisions involving zero
132 self
.check_truediv(123, 0)
133 self
.check_truediv(-456, 0)
134 self
.check_truediv(0, 3)
135 self
.check_truediv(0, -3)
136 self
.check_truediv(0, 0)
137 # ... overflow or underflow by large margin
138 self
.check_truediv(671 * 12345 * 2**DBL_MAX_EXP
, 12345)
139 self
.check_truediv(12345, 345678 * 2**(DBL_MANT_DIG
- DBL_MIN_EXP
))
140 # ... a much larger or smaller than b
141 self
.check_truediv(12345*2**100, 98765)
142 self
.check_truediv(12345*2**30, 98765*7**81)
143 # ... a / b near a boundary: one of 1, 2**DBL_MANT_DIG, 2**DBL_MIN_EXP,
144 # 2**DBL_MAX_EXP, 2**(DBL_MIN_EXP-DBL_MANT_DIG)
145 bases
= (0, DBL_MANT_DIG
, DBL_MIN_EXP
,
146 DBL_MAX_EXP
, DBL_MIN_EXP
- DBL_MANT_DIG
)
148 for exp
in range(base
- 15, base
+ 15):
149 self
.check_truediv(75312*2**max(exp
, 0), 69187*2**max(-exp
, 0))
150 self
.check_truediv(69187*2**max(exp
, 0), 75312*2**max(-exp
, 0))
152 # overflow corner case
153 for m
in [1, 2, 7, 17, 12345, 7**100,
154 -1, -2, -5, -23, -67891, -41**50]:
155 for n
in range(-10, 10):
156 self
.check_truediv(m
*DBL_MIN_OVERFLOW
+ n
, m
)
157 self
.check_truediv(m
*DBL_MIN_OVERFLOW
+ n
, -m
)
159 # check detection of inexactness in shifting stage
161 # (2**DBL_MANT_DIG+1)/(2**DBL_MANT_DIG) lies halfway
162 # between two representable floats, and would usually be
163 # rounded down under round-half-to-even. The tiniest of
164 # additions to the numerator should cause it to be rounded
166 self
.check_truediv((2**DBL_MANT_DIG
+ 1)*12345*2**200 + 2**n
,
167 2**DBL_MANT_DIG
*12345)
169 # 1/2731 is one of the smallest division cases that's subject
170 # to double rounding on IEEE 754 machines working internally with
171 # 64-bit precision. On such machines, the next check would fail,
172 # were it not explicitly skipped in check_truediv.
173 self
.check_truediv(1, 2731)
175 # a particularly bad case for the old algorithm: gives an
176 # error of close to 3.5 ulps.
177 self
.check_truediv(295147931372582273023, 295147932265116303360)
178 for i
in range(1000):
179 self
.check_truediv(10**(i
+1), 10**i
)
180 self
.check_truediv(10**i
, 10**(i
+1))
182 # test round-half-to-even behaviour, normal result
183 for m
in [1, 2, 4, 7, 8, 16, 17, 32, 12345, 7**100,
184 -1, -2, -5, -23, -67891, -41**50]:
185 for n
in range(-10, 10):
186 self
.check_truediv(2**DBL_MANT_DIG
*m
+ n
, m
)
188 # test round-half-to-even, subnormal result
189 for n
in range(-20, 20):
190 self
.check_truediv(n
, 2**1076)
192 # largeish random divisions: a/b where |a| <= |b| <=
193 # 2*|a|; |ans| is between 0.5 and 1.0, so error should
194 # always be bounded by 2**-54 with equality possible only
195 # if the least significant bit of q=ans*2**53 is zero.
196 for M
in [10**10, 10**100, 10**1000]:
197 for i
in range(1000):
198 a
= random
.randrange(1, M
)
199 b
= random
.randrange(a
, 2*a
+1)
200 self
.check_truediv(a
, b
)
201 self
.check_truediv(-a
, b
)
202 self
.check_truediv(a
, -b
)
203 self
.check_truediv(-a
, -b
)
205 # and some (genuinely) random tests
206 for _
in range(10000):
207 a_bits
= random
.randrange(1000)
208 b_bits
= random
.randrange(1, 1000)
209 x
= random
.randrange(2**a_bits
)
210 y
= random
.randrange(1, 2**b_bits
)
211 self
.check_truediv(x
, y
)
212 self
.check_truediv(x
, -y
)
213 self
.check_truediv(-x
, y
)
214 self
.check_truediv(-x
, -y
)
218 run_unittest(TrueDivisionTests
)
220 if __name__
== "__main__":