1"""Tests for Lib/fractions.py."""
2
3from decimal import Decimal
4from test.support import requires_IEEE_754
5import math
6import numbers
7import operator
8import fractions
9import functools
10import sys
11import typing
12import unittest
13from copy import copy, deepcopy
14import pickle
15from pickle import dumps, loads
16F = fractions.Fraction
17
18
19class DummyFloat(object):
20    """Dummy float class for testing comparisons with Fractions"""
21
22    def __init__(self, value):
23        if not isinstance(value, float):
24            raise TypeError("DummyFloat can only be initialized from float")
25        self.value = value
26
27    def _richcmp(self, other, op):
28        if isinstance(other, numbers.Rational):
29            return op(F.from_float(self.value), other)
30        elif isinstance(other, DummyFloat):
31            return op(self.value, other.value)
32        else:
33            return NotImplemented
34
35    def __eq__(self, other): return self._richcmp(other, operator.eq)
36    def __le__(self, other): return self._richcmp(other, operator.le)
37    def __lt__(self, other): return self._richcmp(other, operator.lt)
38    def __ge__(self, other): return self._richcmp(other, operator.ge)
39    def __gt__(self, other): return self._richcmp(other, operator.gt)
40
41    # shouldn't be calling __float__ at all when doing comparisons
42    def __float__(self):
43        assert False, "__float__ should not be invoked for comparisons"
44
45    # same goes for subtraction
46    def __sub__(self, other):
47        assert False, "__sub__ should not be invoked for comparisons"
48    __rsub__ = __sub__
49
50
51class DummyRational(object):
52    """Test comparison of Fraction with a naive rational implementation."""
53
54    def __init__(self, num, den):
55        g = math.gcd(num, den)
56        self.num = num // g
57        self.den = den // g
58
59    def __eq__(self, other):
60        if isinstance(other, fractions.Fraction):
61            return (self.num == other._numerator and
62                    self.den == other._denominator)
63        else:
64            return NotImplemented
65
66    def __lt__(self, other):
67        return(self.num * other._denominator < self.den * other._numerator)
68
69    def __gt__(self, other):
70        return(self.num * other._denominator > self.den * other._numerator)
71
72    def __le__(self, other):
73        return(self.num * other._denominator <= self.den * other._numerator)
74
75    def __ge__(self, other):
76        return(self.num * other._denominator >= self.den * other._numerator)
77
78    # this class is for testing comparisons; conversion to float
79    # should never be used for a comparison, since it loses accuracy
80    def __float__(self):
81        assert False, "__float__ should not be invoked"
82
83class DummyFraction(fractions.Fraction):
84    """Dummy Fraction subclass for copy and deepcopy testing."""
85
86
87def _components(r):
88    return (r.numerator, r.denominator)
89
90
91class FractionTest(unittest.TestCase):
92
93    def assertTypedEquals(self, expected, actual):
94        """Asserts that both the types and values are the same."""
95        self.assertEqual(type(expected), type(actual))
96        self.assertEqual(expected, actual)
97
98    def assertTypedTupleEquals(self, expected, actual):
99        """Asserts that both the types and values in the tuples are the same."""
100        self.assertTupleEqual(expected, actual)
101        self.assertListEqual(list(map(type, expected)), list(map(type, actual)))
102
103    def assertRaisesMessage(self, exc_type, message,
104                            callable, *args, **kwargs):
105        """Asserts that callable(*args, **kwargs) raises exc_type(message)."""
106        try:
107            callable(*args, **kwargs)
108        except exc_type as e:
109            self.assertEqual(message, str(e))
110        else:
111            self.fail("%s not raised" % exc_type.__name__)
112
113    def testInit(self):
114        self.assertEqual((0, 1), _components(F()))
115        self.assertEqual((7, 1), _components(F(7)))
116        self.assertEqual((7, 3), _components(F(F(7, 3))))
117
118        self.assertEqual((-1, 1), _components(F(-1, 1)))
119        self.assertEqual((-1, 1), _components(F(1, -1)))
120        self.assertEqual((1, 1), _components(F(-2, -2)))
121        self.assertEqual((1, 2), _components(F(5, 10)))
122        self.assertEqual((7, 15), _components(F(7, 15)))
123        self.assertEqual((10**23, 1), _components(F(10**23)))
124
125        self.assertEqual((3, 77), _components(F(F(3, 7), 11)))
126        self.assertEqual((-9, 5), _components(F(2, F(-10, 9))))
127        self.assertEqual((2486, 2485), _components(F(F(22, 7), F(355, 113))))
128
129        self.assertRaisesMessage(ZeroDivisionError, "Fraction(12, 0)",
130                                 F, 12, 0)
131        self.assertRaises(TypeError, F, 1.5 + 3j)
132
133        self.assertRaises(TypeError, F, "3/2", 3)
134        self.assertRaises(TypeError, F, 3, 0j)
135        self.assertRaises(TypeError, F, 3, 1j)
136        self.assertRaises(TypeError, F, 1, 2, 3)
137
138    @requires_IEEE_754
139    def testInitFromFloat(self):
140        self.assertEqual((5, 2), _components(F(2.5)))
141        self.assertEqual((0, 1), _components(F(-0.0)))
142        self.assertEqual((3602879701896397, 36028797018963968),
143                         _components(F(0.1)))
144        # bug 16469: error types should be consistent with float -> int
145        self.assertRaises(ValueError, F, float('nan'))
146        self.assertRaises(OverflowError, F, float('inf'))
147        self.assertRaises(OverflowError, F, float('-inf'))
148
149    def testInitFromDecimal(self):
150        self.assertEqual((11, 10),
151                         _components(F(Decimal('1.1'))))
152        self.assertEqual((7, 200),
153                         _components(F(Decimal('3.5e-2'))))
154        self.assertEqual((0, 1),
155                         _components(F(Decimal('.000e20'))))
156        # bug 16469: error types should be consistent with decimal -> int
157        self.assertRaises(ValueError, F, Decimal('nan'))
158        self.assertRaises(ValueError, F, Decimal('snan'))
159        self.assertRaises(OverflowError, F, Decimal('inf'))
160        self.assertRaises(OverflowError, F, Decimal('-inf'))
161
162    def testFromString(self):
163        self.assertEqual((5, 1), _components(F("5")))
164        self.assertEqual((3, 2), _components(F("3/2")))
165        self.assertEqual((3, 2), _components(F(" \n  +3/2")))
166        self.assertEqual((-3, 2), _components(F("-3/2  ")))
167        self.assertEqual((13, 2), _components(F("    013/02 \n  ")))
168        self.assertEqual((16, 5), _components(F(" 3.2 ")))
169        self.assertEqual((-16, 5), _components(F(" -3.2 ")))
170        self.assertEqual((-3, 1), _components(F(" -3. ")))
171        self.assertEqual((3, 5), _components(F(" .6 ")))
172        self.assertEqual((1, 3125), _components(F("32.e-5")))
173        self.assertEqual((1000000, 1), _components(F("1E+06")))
174        self.assertEqual((-12300, 1), _components(F("-1.23e4")))
175        self.assertEqual((0, 1), _components(F(" .0e+0\t")))
176        self.assertEqual((0, 1), _components(F("-0.000e0")))
177        self.assertEqual((123, 1), _components(F("1_2_3")))
178        self.assertEqual((41, 107), _components(F("1_2_3/3_2_1")))
179        self.assertEqual((6283, 2000), _components(F("3.14_15")))
180        self.assertEqual((6283, 2*10**13), _components(F("3.14_15e-1_0")))
181        self.assertEqual((101, 100), _components(F("1.01")))
182        self.assertEqual((101, 100), _components(F("1.0_1")))
183
184        self.assertRaisesMessage(
185            ZeroDivisionError, "Fraction(3, 0)",
186            F, "3/0")
187        self.assertRaisesMessage(
188            ValueError, "Invalid literal for Fraction: '3/'",
189            F, "3/")
190        self.assertRaisesMessage(
191            ValueError, "Invalid literal for Fraction: '/2'",
192            F, "/2")
193        self.assertRaisesMessage(
194            ValueError, "Invalid literal for Fraction: '3 /2'",
195            F, "3 /2")
196        self.assertRaisesMessage(
197            # Denominators don't need a sign.
198            ValueError, "Invalid literal for Fraction: '3/+2'",
199            F, "3/+2")
200        self.assertRaisesMessage(
201            # Imitate float's parsing.
202            ValueError, "Invalid literal for Fraction: '+ 3/2'",
203            F, "+ 3/2")
204        self.assertRaisesMessage(
205            # Avoid treating '.' as a regex special character.
206            ValueError, "Invalid literal for Fraction: '3a2'",
207            F, "3a2")
208        self.assertRaisesMessage(
209            # Don't accept combinations of decimals and rationals.
210            ValueError, "Invalid literal for Fraction: '3/7.2'",
211            F, "3/7.2")
212        self.assertRaisesMessage(
213            # Don't accept combinations of decimals and rationals.
214            ValueError, "Invalid literal for Fraction: '3.2/7'",
215            F, "3.2/7")
216        self.assertRaisesMessage(
217            # Allow 3. and .3, but not .
218            ValueError, "Invalid literal for Fraction: '.'",
219            F, ".")
220        self.assertRaisesMessage(
221            ValueError, "Invalid literal for Fraction: '_'",
222            F, "_")
223        self.assertRaisesMessage(
224            ValueError, "Invalid literal for Fraction: '_1'",
225            F, "_1")
226        self.assertRaisesMessage(
227            ValueError, "Invalid literal for Fraction: '1__2'",
228            F, "1__2")
229        self.assertRaisesMessage(
230            ValueError, "Invalid literal for Fraction: '/_'",
231            F, "/_")
232        self.assertRaisesMessage(
233            ValueError, "Invalid literal for Fraction: '1_/'",
234            F, "1_/")
235        self.assertRaisesMessage(
236            ValueError, "Invalid literal for Fraction: '_1/'",
237            F, "_1/")
238        self.assertRaisesMessage(
239            ValueError, "Invalid literal for Fraction: '1__2/'",
240            F, "1__2/")
241        self.assertRaisesMessage(
242            ValueError, "Invalid literal for Fraction: '1/_'",
243            F, "1/_")
244        self.assertRaisesMessage(
245            ValueError, "Invalid literal for Fraction: '1/_1'",
246            F, "1/_1")
247        self.assertRaisesMessage(
248            ValueError, "Invalid literal for Fraction: '1/1__2'",
249            F, "1/1__2")
250        self.assertRaisesMessage(
251            ValueError, "Invalid literal for Fraction: '1._111'",
252            F, "1._111")
253        self.assertRaisesMessage(
254            ValueError, "Invalid literal for Fraction: '1.1__1'",
255            F, "1.1__1")
256        self.assertRaisesMessage(
257            ValueError, "Invalid literal for Fraction: '1.1e+_1'",
258            F, "1.1e+_1")
259        self.assertRaisesMessage(
260            ValueError, "Invalid literal for Fraction: '1.1e+1__1'",
261            F, "1.1e+1__1")
262        # Test catastrophic backtracking.
263        val = "9"*50 + "_"
264        self.assertRaisesMessage(
265            ValueError, "Invalid literal for Fraction: '" + val + "'",
266            F, val)
267        self.assertRaisesMessage(
268            ValueError, "Invalid literal for Fraction: '1/" + val + "'",
269            F, "1/" + val)
270        self.assertRaisesMessage(
271            ValueError, "Invalid literal for Fraction: '1." + val + "'",
272            F, "1." + val)
273        self.assertRaisesMessage(
274            ValueError, "Invalid literal for Fraction: '1.1+e" + val + "'",
275            F, "1.1+e" + val)
276
277    def testImmutable(self):
278        r = F(7, 3)
279        r.__init__(2, 15)
280        self.assertEqual((7, 3), _components(r))
281
282        self.assertRaises(AttributeError, setattr, r, 'numerator', 12)
283        self.assertRaises(AttributeError, setattr, r, 'denominator', 6)
284        self.assertEqual((7, 3), _components(r))
285
286        # But if you _really_ need to:
287        r._numerator = 4
288        r._denominator = 2
289        self.assertEqual((4, 2), _components(r))
290        # Which breaks some important operations:
291        self.assertNotEqual(F(4, 2), r)
292
293    def testFromFloat(self):
294        self.assertRaises(TypeError, F.from_float, 3+4j)
295        self.assertEqual((10, 1), _components(F.from_float(10)))
296        bigint = 1234567890123456789
297        self.assertEqual((bigint, 1), _components(F.from_float(bigint)))
298        self.assertEqual((0, 1), _components(F.from_float(-0.0)))
299        self.assertEqual((10, 1), _components(F.from_float(10.0)))
300        self.assertEqual((-5, 2), _components(F.from_float(-2.5)))
301        self.assertEqual((99999999999999991611392, 1),
302                         _components(F.from_float(1e23)))
303        self.assertEqual(float(10**23), float(F.from_float(1e23)))
304        self.assertEqual((3602879701896397, 1125899906842624),
305                         _components(F.from_float(3.2)))
306        self.assertEqual(3.2, float(F.from_float(3.2)))
307
308        inf = 1e1000
309        nan = inf - inf
310        # bug 16469: error types should be consistent with float -> int
311        self.assertRaisesMessage(
312            OverflowError, "cannot convert Infinity to integer ratio",
313            F.from_float, inf)
314        self.assertRaisesMessage(
315            OverflowError, "cannot convert Infinity to integer ratio",
316            F.from_float, -inf)
317        self.assertRaisesMessage(
318            ValueError, "cannot convert NaN to integer ratio",
319            F.from_float, nan)
320
321    def testFromDecimal(self):
322        self.assertRaises(TypeError, F.from_decimal, 3+4j)
323        self.assertEqual(F(10, 1), F.from_decimal(10))
324        self.assertEqual(F(0), F.from_decimal(Decimal("-0")))
325        self.assertEqual(F(5, 10), F.from_decimal(Decimal("0.5")))
326        self.assertEqual(F(5, 1000), F.from_decimal(Decimal("5e-3")))
327        self.assertEqual(F(5000), F.from_decimal(Decimal("5e3")))
328        self.assertEqual(1 - F(1, 10**30),
329                         F.from_decimal(Decimal("0." + "9" * 30)))
330
331        # bug 16469: error types should be consistent with decimal -> int
332        self.assertRaisesMessage(
333            OverflowError, "cannot convert Infinity to integer ratio",
334            F.from_decimal, Decimal("inf"))
335        self.assertRaisesMessage(
336            OverflowError, "cannot convert Infinity to integer ratio",
337            F.from_decimal, Decimal("-inf"))
338        self.assertRaisesMessage(
339            ValueError, "cannot convert NaN to integer ratio",
340            F.from_decimal, Decimal("nan"))
341        self.assertRaisesMessage(
342            ValueError, "cannot convert NaN to integer ratio",
343            F.from_decimal, Decimal("snan"))
344
345    def test_as_integer_ratio(self):
346        self.assertEqual(F(4, 6).as_integer_ratio(), (2, 3))
347        self.assertEqual(F(-4, 6).as_integer_ratio(), (-2, 3))
348        self.assertEqual(F(4, -6).as_integer_ratio(), (-2, 3))
349        self.assertEqual(F(0, 6).as_integer_ratio(), (0, 1))
350
351    def testLimitDenominator(self):
352        rpi = F('3.1415926535897932')
353        self.assertEqual(rpi.limit_denominator(10000), F(355, 113))
354        self.assertEqual(-rpi.limit_denominator(10000), F(-355, 113))
355        self.assertEqual(rpi.limit_denominator(113), F(355, 113))
356        self.assertEqual(rpi.limit_denominator(112), F(333, 106))
357        self.assertEqual(F(201, 200).limit_denominator(100), F(1))
358        self.assertEqual(F(201, 200).limit_denominator(101), F(102, 101))
359        self.assertEqual(F(0).limit_denominator(10000), F(0))
360        for i in (0, -1):
361            self.assertRaisesMessage(
362                ValueError, "max_denominator should be at least 1",
363                F(1).limit_denominator, i)
364
365    def testConversions(self):
366        self.assertTypedEquals(-1, math.trunc(F(-11, 10)))
367        self.assertTypedEquals(1, math.trunc(F(11, 10)))
368        self.assertTypedEquals(-2, math.floor(F(-11, 10)))
369        self.assertTypedEquals(-1, math.ceil(F(-11, 10)))
370        self.assertTypedEquals(-1, math.ceil(F(-10, 10)))
371        self.assertTypedEquals(-1, int(F(-11, 10)))
372        self.assertTypedEquals(0, round(F(-1, 10)))
373        self.assertTypedEquals(0, round(F(-5, 10)))
374        self.assertTypedEquals(-2, round(F(-15, 10)))
375        self.assertTypedEquals(-1, round(F(-7, 10)))
376
377        self.assertEqual(False, bool(F(0, 1)))
378        self.assertEqual(True, bool(F(3, 2)))
379        self.assertTypedEquals(0.1, float(F(1, 10)))
380
381        # Check that __float__ isn't implemented by converting the
382        # numerator and denominator to float before dividing.
383        self.assertRaises(OverflowError, float, int('2'*400+'7'))
384        self.assertAlmostEqual(2.0/3,
385                               float(F(int('2'*400+'7'), int('3'*400+'1'))))
386
387        self.assertTypedEquals(0.1+0j, complex(F(1,10)))
388
389    def testSupportsInt(self):
390        # See bpo-44547.
391        f = F(3, 2)
392        self.assertIsInstance(f, typing.SupportsInt)
393        self.assertEqual(int(f), 1)
394        self.assertEqual(type(int(f)), int)
395
396    def testIntGuaranteesIntReturn(self):
397        # Check that int(some_fraction) gives a result of exact type `int`
398        # even if the fraction is using some other Integral type for its
399        # numerator and denominator.
400
401        class CustomInt(int):
402            """
403            Subclass of int with just enough machinery to convince the Fraction
404            constructor to produce something with CustomInt numerator and
405            denominator.
406            """
407
408            @property
409            def numerator(self):
410                return self
411
412            @property
413            def denominator(self):
414                return CustomInt(1)
415
416            def __mul__(self, other):
417                return CustomInt(int(self) * int(other))
418
419            def __floordiv__(self, other):
420                return CustomInt(int(self) // int(other))
421
422        f = F(CustomInt(13), CustomInt(5))
423
424        self.assertIsInstance(f.numerator, CustomInt)
425        self.assertIsInstance(f.denominator, CustomInt)
426        self.assertIsInstance(f, typing.SupportsInt)
427        self.assertEqual(int(f), 2)
428        self.assertEqual(type(int(f)), int)
429
430    def testBoolGuarateesBoolReturn(self):
431        # Ensure that __bool__ is used on numerator which guarantees a bool
432        # return.  See also bpo-39274.
433        @functools.total_ordering
434        class CustomValue:
435            denominator = 1
436
437            def __init__(self, value):
438                self.value = value
439
440            def __bool__(self):
441                return bool(self.value)
442
443            @property
444            def numerator(self):
445                # required to preserve `self` during instantiation
446                return self
447
448            def __eq__(self, other):
449                raise AssertionError("Avoid comparisons in Fraction.__bool__")
450
451            __lt__ = __eq__
452
453        # We did not implement all abstract methods, so register:
454        numbers.Rational.register(CustomValue)
455
456        numerator = CustomValue(1)
457        r = F(numerator)
458        # ensure the numerator was not lost during instantiation:
459        self.assertIs(r.numerator, numerator)
460        self.assertIs(bool(r), True)
461
462        numerator = CustomValue(0)
463        r = F(numerator)
464        self.assertIs(bool(r), False)
465
466    def testRound(self):
467        self.assertTypedEquals(F(-200), round(F(-150), -2))
468        self.assertTypedEquals(F(-200), round(F(-250), -2))
469        self.assertTypedEquals(F(30), round(F(26), -1))
470        self.assertTypedEquals(F(-2, 10), round(F(-15, 100), 1))
471        self.assertTypedEquals(F(-2, 10), round(F(-25, 100), 1))
472
473    def testArithmetic(self):
474        self.assertEqual(F(1, 2), F(1, 10) + F(2, 5))
475        self.assertEqual(F(-3, 10), F(1, 10) - F(2, 5))
476        self.assertEqual(F(1, 25), F(1, 10) * F(2, 5))
477        self.assertEqual(F(5, 6), F(2, 3) * F(5, 4))
478        self.assertEqual(F(1, 4), F(1, 10) / F(2, 5))
479        self.assertEqual(F(-15, 8), F(3, 4) / F(-2, 5))
480        self.assertTypedEquals(2, F(9, 10) // F(2, 5))
481        self.assertTypedEquals(10**23, F(10**23, 1) // F(1))
482        self.assertEqual(F(5, 6), F(7, 3) % F(3, 2))
483        self.assertEqual(F(2, 3), F(-7, 3) % F(3, 2))
484        self.assertEqual((F(1), F(5, 6)), divmod(F(7, 3), F(3, 2)))
485        self.assertEqual((F(-2), F(2, 3)), divmod(F(-7, 3), F(3, 2)))
486        self.assertEqual(F(8, 27), F(2, 3) ** F(3))
487        self.assertEqual(F(27, 8), F(2, 3) ** F(-3))
488        self.assertTypedEquals(2.0, F(4) ** F(1, 2))
489        self.assertEqual(F(1, 1), +F(1, 1))
490        z = pow(F(-1), F(1, 2))
491        self.assertAlmostEqual(z.real, 0)
492        self.assertEqual(z.imag, 1)
493        # Regression test for #27539.
494        p = F(-1, 2) ** 0
495        self.assertEqual(p, F(1, 1))
496        self.assertEqual(p.numerator, 1)
497        self.assertEqual(p.denominator, 1)
498        p = F(-1, 2) ** -1
499        self.assertEqual(p, F(-2, 1))
500        self.assertEqual(p.numerator, -2)
501        self.assertEqual(p.denominator, 1)
502        p = F(-1, 2) ** -2
503        self.assertEqual(p, F(4, 1))
504        self.assertEqual(p.numerator, 4)
505        self.assertEqual(p.denominator, 1)
506
507    def testLargeArithmetic(self):
508        self.assertTypedEquals(
509            F(10101010100808080808080808101010101010000000000000000,
510              1010101010101010101010101011111111101010101010101010101010101),
511            F(10**35+1, 10**27+1) % F(10**27+1, 10**35-1)
512        )
513        self.assertTypedEquals(
514            F(7, 1901475900342344102245054808064),
515            F(-2**100, 3) % F(5, 2**100)
516        )
517        self.assertTypedTupleEquals(
518            (9999999999999999,
519             F(10101010100808080808080808101010101010000000000000000,
520               1010101010101010101010101011111111101010101010101010101010101)),
521            divmod(F(10**35+1, 10**27+1), F(10**27+1, 10**35-1))
522        )
523        self.assertTypedEquals(
524            -2 ** 200 // 15,
525            F(-2**100, 3) // F(5, 2**100)
526        )
527        self.assertTypedEquals(
528            1,
529            F(5, 2**100) // F(3, 2**100)
530        )
531        self.assertTypedEquals(
532            (1, F(2, 2**100)),
533            divmod(F(5, 2**100), F(3, 2**100))
534        )
535        self.assertTypedTupleEquals(
536            (-2 ** 200 // 15,
537             F(7, 1901475900342344102245054808064)),
538            divmod(F(-2**100, 3), F(5, 2**100))
539        )
540
541    def testMixedArithmetic(self):
542        self.assertTypedEquals(F(11, 10), F(1, 10) + 1)
543        self.assertTypedEquals(1.1, F(1, 10) + 1.0)
544        self.assertTypedEquals(1.1 + 0j, F(1, 10) + (1.0 + 0j))
545        self.assertTypedEquals(F(11, 10), 1 + F(1, 10))
546        self.assertTypedEquals(1.1, 1.0 + F(1, 10))
547        self.assertTypedEquals(1.1 + 0j, (1.0 + 0j) + F(1, 10))
548
549        self.assertTypedEquals(F(-9, 10), F(1, 10) - 1)
550        self.assertTypedEquals(-0.9, F(1, 10) - 1.0)
551        self.assertTypedEquals(-0.9 + 0j, F(1, 10) - (1.0 + 0j))
552        self.assertTypedEquals(F(9, 10), 1 - F(1, 10))
553        self.assertTypedEquals(0.9, 1.0 - F(1, 10))
554        self.assertTypedEquals(0.9 + 0j, (1.0 + 0j) - F(1, 10))
555
556        self.assertTypedEquals(F(1, 10), F(1, 10) * 1)
557        self.assertTypedEquals(0.1, F(1, 10) * 1.0)
558        self.assertTypedEquals(0.1 + 0j, F(1, 10) * (1.0 + 0j))
559        self.assertTypedEquals(F(1, 10), 1 * F(1, 10))
560        self.assertTypedEquals(0.1, 1.0 * F(1, 10))
561        self.assertTypedEquals(0.1 + 0j, (1.0 + 0j) * F(1, 10))
562
563        self.assertTypedEquals(F(1, 10), F(1, 10) / 1)
564        self.assertTypedEquals(0.1, F(1, 10) / 1.0)
565        self.assertTypedEquals(0.1 + 0j, F(1, 10) / (1.0 + 0j))
566        self.assertTypedEquals(F(10, 1), 1 / F(1, 10))
567        self.assertTypedEquals(10.0, 1.0 / F(1, 10))
568        self.assertTypedEquals(10.0 + 0j, (1.0 + 0j) / F(1, 10))
569
570        self.assertTypedEquals(0, F(1, 10) // 1)
571        self.assertTypedEquals(0.0, F(1, 10) // 1.0)
572        self.assertTypedEquals(10, 1 // F(1, 10))
573        self.assertTypedEquals(10**23, 10**22 // F(1, 10))
574        self.assertTypedEquals(1.0 // 0.1, 1.0 // F(1, 10))
575
576        self.assertTypedEquals(F(1, 10), F(1, 10) % 1)
577        self.assertTypedEquals(0.1, F(1, 10) % 1.0)
578        self.assertTypedEquals(F(0, 1), 1 % F(1, 10))
579        self.assertTypedEquals(1.0 % 0.1, 1.0 % F(1, 10))
580        self.assertTypedEquals(0.1, F(1, 10) % float('inf'))
581        self.assertTypedEquals(float('-inf'), F(1, 10) % float('-inf'))
582        self.assertTypedEquals(float('inf'), F(-1, 10) % float('inf'))
583        self.assertTypedEquals(-0.1, F(-1, 10) % float('-inf'))
584
585        self.assertTypedTupleEquals((0, F(1, 10)), divmod(F(1, 10), 1))
586        self.assertTypedTupleEquals(divmod(0.1, 1.0), divmod(F(1, 10), 1.0))
587        self.assertTypedTupleEquals((10, F(0)), divmod(1, F(1, 10)))
588        self.assertTypedTupleEquals(divmod(1.0, 0.1), divmod(1.0, F(1, 10)))
589        self.assertTypedTupleEquals(divmod(0.1, float('inf')), divmod(F(1, 10), float('inf')))
590        self.assertTypedTupleEquals(divmod(0.1, float('-inf')), divmod(F(1, 10), float('-inf')))
591        self.assertTypedTupleEquals(divmod(-0.1, float('inf')), divmod(F(-1, 10), float('inf')))
592        self.assertTypedTupleEquals(divmod(-0.1, float('-inf')), divmod(F(-1, 10), float('-inf')))
593
594        # ** has more interesting conversion rules.
595        self.assertTypedEquals(F(100, 1), F(1, 10) ** -2)
596        self.assertTypedEquals(F(100, 1), F(10, 1) ** 2)
597        self.assertTypedEquals(0.1, F(1, 10) ** 1.0)
598        self.assertTypedEquals(0.1 + 0j, F(1, 10) ** (1.0 + 0j))
599        self.assertTypedEquals(4 , 2 ** F(2, 1))
600        z = pow(-1, F(1, 2))
601        self.assertAlmostEqual(0, z.real)
602        self.assertEqual(1, z.imag)
603        self.assertTypedEquals(F(1, 4) , 2 ** F(-2, 1))
604        self.assertTypedEquals(2.0 , 4 ** F(1, 2))
605        self.assertTypedEquals(0.25, 2.0 ** F(-2, 1))
606        self.assertTypedEquals(1.0 + 0j, (1.0 + 0j) ** F(1, 10))
607        self.assertRaises(ZeroDivisionError, operator.pow,
608                          F(0, 1), -2)
609
610    def testMixingWithDecimal(self):
611        # Decimal refuses mixed arithmetic (but not mixed comparisons)
612        self.assertRaises(TypeError, operator.add,
613                          F(3,11), Decimal('3.1415926'))
614        self.assertRaises(TypeError, operator.add,
615                          Decimal('3.1415926'), F(3,11))
616
617    def testComparisons(self):
618        self.assertTrue(F(1, 2) < F(2, 3))
619        self.assertFalse(F(1, 2) < F(1, 2))
620        self.assertTrue(F(1, 2) <= F(2, 3))
621        self.assertTrue(F(1, 2) <= F(1, 2))
622        self.assertFalse(F(2, 3) <= F(1, 2))
623        self.assertTrue(F(1, 2) == F(1, 2))
624        self.assertFalse(F(1, 2) == F(1, 3))
625        self.assertFalse(F(1, 2) != F(1, 2))
626        self.assertTrue(F(1, 2) != F(1, 3))
627
628    def testComparisonsDummyRational(self):
629        self.assertTrue(F(1, 2) == DummyRational(1, 2))
630        self.assertTrue(DummyRational(1, 2) == F(1, 2))
631        self.assertFalse(F(1, 2) == DummyRational(3, 4))
632        self.assertFalse(DummyRational(3, 4) == F(1, 2))
633
634        self.assertTrue(F(1, 2) < DummyRational(3, 4))
635        self.assertFalse(F(1, 2) < DummyRational(1, 2))
636        self.assertFalse(F(1, 2) < DummyRational(1, 7))
637        self.assertFalse(F(1, 2) > DummyRational(3, 4))
638        self.assertFalse(F(1, 2) > DummyRational(1, 2))
639        self.assertTrue(F(1, 2) > DummyRational(1, 7))
640        self.assertTrue(F(1, 2) <= DummyRational(3, 4))
641        self.assertTrue(F(1, 2) <= DummyRational(1, 2))
642        self.assertFalse(F(1, 2) <= DummyRational(1, 7))
643        self.assertFalse(F(1, 2) >= DummyRational(3, 4))
644        self.assertTrue(F(1, 2) >= DummyRational(1, 2))
645        self.assertTrue(F(1, 2) >= DummyRational(1, 7))
646
647        self.assertTrue(DummyRational(1, 2) < F(3, 4))
648        self.assertFalse(DummyRational(1, 2) < F(1, 2))
649        self.assertFalse(DummyRational(1, 2) < F(1, 7))
650        self.assertFalse(DummyRational(1, 2) > F(3, 4))
651        self.assertFalse(DummyRational(1, 2) > F(1, 2))
652        self.assertTrue(DummyRational(1, 2) > F(1, 7))
653        self.assertTrue(DummyRational(1, 2) <= F(3, 4))
654        self.assertTrue(DummyRational(1, 2) <= F(1, 2))
655        self.assertFalse(DummyRational(1, 2) <= F(1, 7))
656        self.assertFalse(DummyRational(1, 2) >= F(3, 4))
657        self.assertTrue(DummyRational(1, 2) >= F(1, 2))
658        self.assertTrue(DummyRational(1, 2) >= F(1, 7))
659
660    def testComparisonsDummyFloat(self):
661        x = DummyFloat(1./3.)
662        y = F(1, 3)
663        self.assertTrue(x != y)
664        self.assertTrue(x < y or x > y)
665        self.assertFalse(x == y)
666        self.assertFalse(x <= y and x >= y)
667        self.assertTrue(y != x)
668        self.assertTrue(y < x or y > x)
669        self.assertFalse(y == x)
670        self.assertFalse(y <= x and y >= x)
671
672    def testMixedLess(self):
673        self.assertTrue(2 < F(5, 2))
674        self.assertFalse(2 < F(4, 2))
675        self.assertTrue(F(5, 2) < 3)
676        self.assertFalse(F(4, 2) < 2)
677
678        self.assertTrue(F(1, 2) < 0.6)
679        self.assertFalse(F(1, 2) < 0.4)
680        self.assertTrue(0.4 < F(1, 2))
681        self.assertFalse(0.5 < F(1, 2))
682
683        self.assertFalse(float('inf') < F(1, 2))
684        self.assertTrue(float('-inf') < F(0, 10))
685        self.assertFalse(float('nan') < F(-3, 7))
686        self.assertTrue(F(1, 2) < float('inf'))
687        self.assertFalse(F(17, 12) < float('-inf'))
688        self.assertFalse(F(144, -89) < float('nan'))
689
690    def testMixedLessEqual(self):
691        self.assertTrue(0.5 <= F(1, 2))
692        self.assertFalse(0.6 <= F(1, 2))
693        self.assertTrue(F(1, 2) <= 0.5)
694        self.assertFalse(F(1, 2) <= 0.4)
695        self.assertTrue(2 <= F(4, 2))
696        self.assertFalse(2 <= F(3, 2))
697        self.assertTrue(F(4, 2) <= 2)
698        self.assertFalse(F(5, 2) <= 2)
699
700        self.assertFalse(float('inf') <= F(1, 2))
701        self.assertTrue(float('-inf') <= F(0, 10))
702        self.assertFalse(float('nan') <= F(-3, 7))
703        self.assertTrue(F(1, 2) <= float('inf'))
704        self.assertFalse(F(17, 12) <= float('-inf'))
705        self.assertFalse(F(144, -89) <= float('nan'))
706
707    def testBigFloatComparisons(self):
708        # Because 10**23 can't be represented exactly as a float:
709        self.assertFalse(F(10**23) == float(10**23))
710        # The first test demonstrates why these are important.
711        self.assertFalse(1e23 < float(F(math.trunc(1e23) + 1)))
712        self.assertTrue(1e23 < F(math.trunc(1e23) + 1))
713        self.assertFalse(1e23 <= F(math.trunc(1e23) - 1))
714        self.assertTrue(1e23 > F(math.trunc(1e23) - 1))
715        self.assertFalse(1e23 >= F(math.trunc(1e23) + 1))
716
717    def testBigComplexComparisons(self):
718        self.assertFalse(F(10**23) == complex(10**23))
719        self.assertRaises(TypeError, operator.gt, F(10**23), complex(10**23))
720        self.assertRaises(TypeError, operator.le, F(10**23), complex(10**23))
721
722        x = F(3, 8)
723        z = complex(0.375, 0.0)
724        w = complex(0.375, 0.2)
725        self.assertTrue(x == z)
726        self.assertFalse(x != z)
727        self.assertFalse(x == w)
728        self.assertTrue(x != w)
729        for op in operator.lt, operator.le, operator.gt, operator.ge:
730            self.assertRaises(TypeError, op, x, z)
731            self.assertRaises(TypeError, op, z, x)
732            self.assertRaises(TypeError, op, x, w)
733            self.assertRaises(TypeError, op, w, x)
734
735    def testMixedEqual(self):
736        self.assertTrue(0.5 == F(1, 2))
737        self.assertFalse(0.6 == F(1, 2))
738        self.assertTrue(F(1, 2) == 0.5)
739        self.assertFalse(F(1, 2) == 0.4)
740        self.assertTrue(2 == F(4, 2))
741        self.assertFalse(2 == F(3, 2))
742        self.assertTrue(F(4, 2) == 2)
743        self.assertFalse(F(5, 2) == 2)
744        self.assertFalse(F(5, 2) == float('nan'))
745        self.assertFalse(float('nan') == F(3, 7))
746        self.assertFalse(F(5, 2) == float('inf'))
747        self.assertFalse(float('-inf') == F(2, 5))
748
749    def testStringification(self):
750        self.assertEqual("Fraction(7, 3)", repr(F(7, 3)))
751        self.assertEqual("Fraction(6283185307, 2000000000)",
752                         repr(F('3.1415926535')))
753        self.assertEqual("Fraction(-1, 100000000000000000000)",
754                         repr(F(1, -10**20)))
755        self.assertEqual("7/3", str(F(7, 3)))
756        self.assertEqual("7", str(F(7, 1)))
757
758    def testHash(self):
759        hmod = sys.hash_info.modulus
760        hinf = sys.hash_info.inf
761        self.assertEqual(hash(2.5), hash(F(5, 2)))
762        self.assertEqual(hash(10**50), hash(F(10**50)))
763        self.assertNotEqual(hash(float(10**23)), hash(F(10**23)))
764        self.assertEqual(hinf, hash(F(1, hmod)))
765        # Check that __hash__ produces the same value as hash(), for
766        # consistency with int and Decimal.  (See issue #10356.)
767        self.assertEqual(hash(F(-1)), F(-1).__hash__())
768
769    def testApproximatePi(self):
770        # Algorithm borrowed from
771        # http://docs.python.org/lib/decimal-recipes.html
772        three = F(3)
773        lasts, t, s, n, na, d, da = 0, three, 3, 1, 0, 0, 24
774        while abs(s - lasts) > F(1, 10**9):
775            lasts = s
776            n, na = n+na, na+8
777            d, da = d+da, da+32
778            t = (t * n) / d
779            s += t
780        self.assertAlmostEqual(math.pi, s)
781
782    def testApproximateCos1(self):
783        # Algorithm borrowed from
784        # http://docs.python.org/lib/decimal-recipes.html
785        x = F(1)
786        i, lasts, s, fact, num, sign = 0, 0, F(1), 1, 1, 1
787        while abs(s - lasts) > F(1, 10**9):
788            lasts = s
789            i += 2
790            fact *= i * (i-1)
791            num *= x * x
792            sign *= -1
793            s += num / fact * sign
794        self.assertAlmostEqual(math.cos(1), s)
795
796    def test_copy_deepcopy_pickle(self):
797        r = F(13, 7)
798        dr = DummyFraction(13, 7)
799        for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
800            self.assertEqual(r, loads(dumps(r, proto)))
801        self.assertEqual(id(r), id(copy(r)))
802        self.assertEqual(id(r), id(deepcopy(r)))
803        self.assertNotEqual(id(dr), id(copy(dr)))
804        self.assertNotEqual(id(dr), id(deepcopy(dr)))
805        self.assertTypedEquals(dr, copy(dr))
806        self.assertTypedEquals(dr, deepcopy(dr))
807
808    def test_slots(self):
809        # Issue 4998
810        r = F(13, 7)
811        self.assertRaises(AttributeError, setattr, r, 'a', 10)
812
813    def test_int_subclass(self):
814        class myint(int):
815            def __mul__(self, other):
816                return type(self)(int(self) * int(other))
817            def __floordiv__(self, other):
818                return type(self)(int(self) // int(other))
819            def __mod__(self, other):
820                x = type(self)(int(self) % int(other))
821                return x
822            @property
823            def numerator(self):
824                return type(self)(int(self))
825            @property
826            def denominator(self):
827                return type(self)(1)
828
829        f = fractions.Fraction(myint(1 * 3), myint(2 * 3))
830        self.assertEqual(f.numerator, 1)
831        self.assertEqual(f.denominator, 2)
832        self.assertEqual(type(f.numerator), myint)
833        self.assertEqual(type(f.denominator), myint)
834
835
836if __name__ == '__main__':
837    unittest.main()
838