PageRenderTime 1670ms CodeModel.GetById 162ms app.highlight 1259ms RepoModel.GetById 240ms app.codeStats 0ms

/Lib/test/test_float.py

http://unladen-swallow.googlecode.com/
Python | 793 lines | 737 code | 45 blank | 11 comment | 16 complexity | 2ffa5657a2b9c1f4cf32d916b9d0639b MD5 | raw file
  1
  2import unittest, struct
  3import os
  4from test import test_support
  5import math
  6from math import isinf, isnan, copysign, ldexp
  7import operator
  8import random, fractions
  9
 10INF = float("inf")
 11NAN = float("nan")
 12
 13class GeneralFloatCases(unittest.TestCase):
 14
 15    def test_float(self):
 16        self.assertEqual(float(3.14), 3.14)
 17        self.assertEqual(float(314), 314.0)
 18        self.assertEqual(float(314L), 314.0)
 19        self.assertEqual(float("  3.14  "), 3.14)
 20        self.assertRaises(ValueError, float, "  0x3.1  ")
 21        self.assertRaises(ValueError, float, "  -0x3.p-1  ")
 22        self.assertRaises(ValueError, float, "  +0x3.p-1  ")
 23        self.assertRaises(ValueError, float, "++3.14")
 24        self.assertRaises(ValueError, float, "+-3.14")
 25        self.assertRaises(ValueError, float, "-+3.14")
 26        self.assertRaises(ValueError, float, "--3.14")
 27        if test_support.have_unicode:
 28            self.assertEqual(float(unicode("  3.14  ")), 3.14)
 29            self.assertEqual(float(unicode("  \u0663.\u0661\u0664  ",'raw-unicode-escape')), 3.14)
 30            # Implementation limitation in PyFloat_FromString()
 31            self.assertRaises(ValueError, float, unicode("1"*10000))
 32
 33    @test_support.run_with_locale('LC_NUMERIC', 'fr_FR', 'de_DE')
 34    def test_float_with_comma(self):
 35        # set locale to something that doesn't use '.' for the decimal point
 36        # float must not accept the locale specific decimal point but
 37        # it still has to accept the normal python syntac
 38        import locale
 39        if not locale.localeconv()['decimal_point'] == ',':
 40            return
 41
 42        self.assertEqual(float("  3.14  "), 3.14)
 43        self.assertEqual(float("+3.14  "), 3.14)
 44        self.assertEqual(float("-3.14  "), -3.14)
 45        self.assertEqual(float(".14  "), .14)
 46        self.assertEqual(float("3.  "), 3.0)
 47        self.assertEqual(float("3.e3  "), 3000.0)
 48        self.assertEqual(float("3.2e3  "), 3200.0)
 49        self.assertEqual(float("2.5e-1  "), 0.25)
 50        self.assertEqual(float("5e-1"), 0.5)
 51        self.assertRaises(ValueError, float, "  3,14  ")
 52        self.assertRaises(ValueError, float, "  +3,14  ")
 53        self.assertRaises(ValueError, float, "  -3,14  ")
 54        self.assertRaises(ValueError, float, "  0x3.1  ")
 55        self.assertRaises(ValueError, float, "  -0x3.p-1  ")
 56        self.assertRaises(ValueError, float, "  +0x3.p-1  ")
 57        self.assertEqual(float("  25.e-1  "), 2.5)
 58        self.assertEqual(test_support.fcmp(float("  .25e-1  "), .025), 0)
 59
 60    def test_floatconversion(self):
 61        # Make sure that calls to __float__() work properly
 62        class Foo0:
 63            def __float__(self):
 64                return 42.
 65
 66        class Foo1(object):
 67            def __float__(self):
 68                return 42.
 69
 70        class Foo2(float):
 71            def __float__(self):
 72                return 42.
 73
 74        class Foo3(float):
 75            def __new__(cls, value=0.):
 76                return float.__new__(cls, 2*value)
 77
 78            def __float__(self):
 79                return self
 80
 81        class Foo4(float):
 82            def __float__(self):
 83                return 42
 84
 85        # Issue 5759: __float__ not called on str subclasses (though it is on
 86        # unicode subclasses).
 87        class FooStr(str):
 88            def __float__(self):
 89                return float(str(self)) + 1
 90
 91        class FooUnicode(unicode):
 92            def __float__(self):
 93                return float(unicode(self)) + 1
 94
 95        self.assertAlmostEqual(float(Foo0()), 42.)
 96        self.assertAlmostEqual(float(Foo1()), 42.)
 97        self.assertAlmostEqual(float(Foo2()), 42.)
 98        self.assertAlmostEqual(float(Foo3(21)), 42.)
 99        self.assertRaises(TypeError, float, Foo4(42))
100        self.assertAlmostEqual(float(FooUnicode('8')), 9.)
101        self.assertAlmostEqual(float(FooStr('8')), 9.)
102
103    def test_floatasratio(self):
104        for f, ratio in [
105                (0.875, (7, 8)),
106                (-0.875, (-7, 8)),
107                (0.0, (0, 1)),
108                (11.5, (23, 2)),
109            ]:
110            self.assertEqual(f.as_integer_ratio(), ratio)
111
112        for i in range(10000):
113            f = random.random()
114            f *= 10 ** random.randint(-100, 100)
115            n, d = f.as_integer_ratio()
116            self.assertEqual(float(n).__truediv__(d), f)
117
118        R = fractions.Fraction
119        self.assertEqual(R(0, 1),
120                         R(*float(0.0).as_integer_ratio()))
121        self.assertEqual(R(5, 2),
122                         R(*float(2.5).as_integer_ratio()))
123        self.assertEqual(R(1, 2),
124                         R(*float(0.5).as_integer_ratio()))
125        self.assertEqual(R(4728779608739021, 2251799813685248),
126                         R(*float(2.1).as_integer_ratio()))
127        self.assertEqual(R(-4728779608739021, 2251799813685248),
128                         R(*float(-2.1).as_integer_ratio()))
129        self.assertEqual(R(-2100, 1),
130                         R(*float(-2100.0).as_integer_ratio()))
131
132        self.assertRaises(OverflowError, float('inf').as_integer_ratio)
133        self.assertRaises(OverflowError, float('-inf').as_integer_ratio)
134        self.assertRaises(ValueError, float('nan').as_integer_ratio)
135
136class FormatFunctionsTestCase(unittest.TestCase):
137
138    def setUp(self):
139        self.save_formats = {'double':float.__getformat__('double'),
140                             'float':float.__getformat__('float')}
141
142    def tearDown(self):
143        float.__setformat__('double', self.save_formats['double'])
144        float.__setformat__('float', self.save_formats['float'])
145
146    def test_getformat(self):
147        self.assert_(float.__getformat__('double') in
148                     ['unknown', 'IEEE, big-endian', 'IEEE, little-endian'])
149        self.assert_(float.__getformat__('float') in
150                     ['unknown', 'IEEE, big-endian', 'IEEE, little-endian'])
151        self.assertRaises(ValueError, float.__getformat__, 'chicken')
152        self.assertRaises(TypeError, float.__getformat__, 1)
153
154    def test_setformat(self):
155        for t in 'double', 'float':
156            float.__setformat__(t, 'unknown')
157            if self.save_formats[t] == 'IEEE, big-endian':
158                self.assertRaises(ValueError, float.__setformat__,
159                                  t, 'IEEE, little-endian')
160            elif self.save_formats[t] == 'IEEE, little-endian':
161                self.assertRaises(ValueError, float.__setformat__,
162                                  t, 'IEEE, big-endian')
163            else:
164                self.assertRaises(ValueError, float.__setformat__,
165                                  t, 'IEEE, big-endian')
166                self.assertRaises(ValueError, float.__setformat__,
167                                  t, 'IEEE, little-endian')
168            self.assertRaises(ValueError, float.__setformat__,
169                              t, 'chicken')
170        self.assertRaises(ValueError, float.__setformat__,
171                          'chicken', 'unknown')
172
173BE_DOUBLE_INF = '\x7f\xf0\x00\x00\x00\x00\x00\x00'
174LE_DOUBLE_INF = ''.join(reversed(BE_DOUBLE_INF))
175BE_DOUBLE_NAN = '\x7f\xf8\x00\x00\x00\x00\x00\x00'
176LE_DOUBLE_NAN = ''.join(reversed(BE_DOUBLE_NAN))
177
178BE_FLOAT_INF = '\x7f\x80\x00\x00'
179LE_FLOAT_INF = ''.join(reversed(BE_FLOAT_INF))
180BE_FLOAT_NAN = '\x7f\xc0\x00\x00'
181LE_FLOAT_NAN = ''.join(reversed(BE_FLOAT_NAN))
182
183# on non-IEEE platforms, attempting to unpack a bit pattern
184# representing an infinity or a NaN should raise an exception.
185
186class UnknownFormatTestCase(unittest.TestCase):
187    def setUp(self):
188        self.save_formats = {'double':float.__getformat__('double'),
189                             'float':float.__getformat__('float')}
190        float.__setformat__('double', 'unknown')
191        float.__setformat__('float', 'unknown')
192
193    def tearDown(self):
194        float.__setformat__('double', self.save_formats['double'])
195        float.__setformat__('float', self.save_formats['float'])
196
197    def test_double_specials_dont_unpack(self):
198        for fmt, data in [('>d', BE_DOUBLE_INF),
199                          ('>d', BE_DOUBLE_NAN),
200                          ('<d', LE_DOUBLE_INF),
201                          ('<d', LE_DOUBLE_NAN)]:
202            self.assertRaises(ValueError, struct.unpack, fmt, data)
203
204    def test_float_specials_dont_unpack(self):
205        for fmt, data in [('>f', BE_FLOAT_INF),
206                          ('>f', BE_FLOAT_NAN),
207                          ('<f', LE_FLOAT_INF),
208                          ('<f', LE_FLOAT_NAN)]:
209            self.assertRaises(ValueError, struct.unpack, fmt, data)
210
211
212# on an IEEE platform, all we guarantee is that bit patterns
213# representing infinities or NaNs do not raise an exception; all else
214# is accident (today).
215# let's also try to guarantee that -0.0 and 0.0 don't get confused.
216
217class IEEEFormatTestCase(unittest.TestCase):
218    if float.__getformat__("double").startswith("IEEE"):
219        def test_double_specials_do_unpack(self):
220            for fmt, data in [('>d', BE_DOUBLE_INF),
221                              ('>d', BE_DOUBLE_NAN),
222                              ('<d', LE_DOUBLE_INF),
223                              ('<d', LE_DOUBLE_NAN)]:
224                struct.unpack(fmt, data)
225
226    if float.__getformat__("float").startswith("IEEE"):
227        def test_float_specials_do_unpack(self):
228            for fmt, data in [('>f', BE_FLOAT_INF),
229                              ('>f', BE_FLOAT_NAN),
230                              ('<f', LE_FLOAT_INF),
231                              ('<f', LE_FLOAT_NAN)]:
232                struct.unpack(fmt, data)
233
234    if float.__getformat__("double").startswith("IEEE"):
235        def test_negative_zero(self):
236            import math
237            def pos_pos():
238                return 0.0, math.atan2(0.0, -1)
239            def pos_neg():
240                return 0.0, math.atan2(-0.0, -1)
241            def neg_pos():
242                return -0.0, math.atan2(0.0, -1)
243            def neg_neg():
244                return -0.0, math.atan2(-0.0, -1)
245            self.assertEquals(pos_pos(), neg_pos())
246            self.assertEquals(pos_neg(), neg_neg())
247
248    if float.__getformat__("double").startswith("IEEE"):
249        def test_underflow_sign(self):
250            import math
251            # check that -1e-1000 gives -0.0, not 0.0
252            self.assertEquals(math.atan2(-1e-1000, -1), math.atan2(-0.0, -1))
253            self.assertEquals(math.atan2(float('-1e-1000'), -1),
254                              math.atan2(-0.0, -1))
255
256class ReprTestCase(unittest.TestCase):
257    def test_repr(self):
258        floats_file = open(os.path.join(os.path.split(__file__)[0],
259                           'floating_points.txt'))
260        for line in floats_file:
261            line = line.strip()
262            if not line or line.startswith('#'):
263                continue
264            v = eval(line)
265            self.assertEqual(v, eval(repr(v)))
266        floats_file.close()
267
268# Beginning with Python 2.6 float has cross platform compatible
269# ways to create and represent inf and nan
270class InfNanTest(unittest.TestCase):
271    def test_inf_from_str(self):
272        self.assert_(isinf(float("inf")))
273        self.assert_(isinf(float("+inf")))
274        self.assert_(isinf(float("-inf")))
275        self.assert_(isinf(float("infinity")))
276        self.assert_(isinf(float("+infinity")))
277        self.assert_(isinf(float("-infinity")))
278
279        self.assertEqual(repr(float("inf")), "inf")
280        self.assertEqual(repr(float("+inf")), "inf")
281        self.assertEqual(repr(float("-inf")), "-inf")
282        self.assertEqual(repr(float("infinity")), "inf")
283        self.assertEqual(repr(float("+infinity")), "inf")
284        self.assertEqual(repr(float("-infinity")), "-inf")
285
286        self.assertEqual(repr(float("INF")), "inf")
287        self.assertEqual(repr(float("+Inf")), "inf")
288        self.assertEqual(repr(float("-iNF")), "-inf")
289        self.assertEqual(repr(float("Infinity")), "inf")
290        self.assertEqual(repr(float("+iNfInItY")), "inf")
291        self.assertEqual(repr(float("-INFINITY")), "-inf")
292
293        self.assertEqual(str(float("inf")), "inf")
294        self.assertEqual(str(float("+inf")), "inf")
295        self.assertEqual(str(float("-inf")), "-inf")
296        self.assertEqual(str(float("infinity")), "inf")
297        self.assertEqual(str(float("+infinity")), "inf")
298        self.assertEqual(str(float("-infinity")), "-inf")
299
300        self.assertRaises(ValueError, float, "info")
301        self.assertRaises(ValueError, float, "+info")
302        self.assertRaises(ValueError, float, "-info")
303        self.assertRaises(ValueError, float, "in")
304        self.assertRaises(ValueError, float, "+in")
305        self.assertRaises(ValueError, float, "-in")
306        self.assertRaises(ValueError, float, "infinit")
307        self.assertRaises(ValueError, float, "+Infin")
308        self.assertRaises(ValueError, float, "-INFI")
309        self.assertRaises(ValueError, float, "infinitys")
310
311    def test_inf_as_str(self):
312        self.assertEqual(repr(1e300 * 1e300), "inf")
313        self.assertEqual(repr(-1e300 * 1e300), "-inf")
314
315        self.assertEqual(str(1e300 * 1e300), "inf")
316        self.assertEqual(str(-1e300 * 1e300), "-inf")
317
318    def test_nan_from_str(self):
319        self.assert_(isnan(float("nan")))
320        self.assert_(isnan(float("+nan")))
321        self.assert_(isnan(float("-nan")))
322
323        self.assertEqual(repr(float("nan")), "nan")
324        self.assertEqual(repr(float("+nan")), "nan")
325        self.assertEqual(repr(float("-nan")), "nan")
326
327        self.assertEqual(repr(float("NAN")), "nan")
328        self.assertEqual(repr(float("+NAn")), "nan")
329        self.assertEqual(repr(float("-NaN")), "nan")
330
331        self.assertEqual(str(float("nan")), "nan")
332        self.assertEqual(str(float("+nan")), "nan")
333        self.assertEqual(str(float("-nan")), "nan")
334
335        self.assertRaises(ValueError, float, "nana")
336        self.assertRaises(ValueError, float, "+nana")
337        self.assertRaises(ValueError, float, "-nana")
338        self.assertRaises(ValueError, float, "na")
339        self.assertRaises(ValueError, float, "+na")
340        self.assertRaises(ValueError, float, "-na")
341
342    def test_nan_as_str(self):
343        self.assertEqual(repr(1e300 * 1e300 * 0), "nan")
344        self.assertEqual(repr(-1e300 * 1e300 * 0), "nan")
345
346        self.assertEqual(str(1e300 * 1e300 * 0), "nan")
347        self.assertEqual(str(-1e300 * 1e300 * 0), "nan")
348
349    def notest_float_nan(self):
350        self.assert_(NAN.is_nan())
351        self.failIf(INF.is_nan())
352        self.failIf((0.).is_nan())
353
354    def notest_float_inf(self):
355        self.assert_(INF.is_inf())
356        self.failIf(NAN.is_inf())
357        self.failIf((0.).is_inf())
358
359fromHex = float.fromhex
360toHex = float.hex
361class HexFloatTestCase(unittest.TestCase):
362    MAX = fromHex('0x.fffffffffffff8p+1024')  # max normal
363    MIN = fromHex('0x1p-1022')                # min normal
364    TINY = fromHex('0x0.0000000000001p-1022') # min subnormal
365    EPS = fromHex('0x0.0000000000001p0') # diff between 1.0 and next float up
366
367    def identical(self, x, y):
368        # check that floats x and y are identical, or that both
369        # are NaNs
370        if isnan(x) or isnan(y):
371            if isnan(x) == isnan(y):
372                return
373        elif x == y and (x != 0.0 or copysign(1.0, x) == copysign(1.0, y)):
374            return
375        self.fail('%r not identical to %r' % (x, y))
376
377    def test_ends(self):
378        self.identical(self.MIN, ldexp(1.0, -1022))
379        self.identical(self.TINY, ldexp(1.0, -1074))
380        self.identical(self.EPS, ldexp(1.0, -52))
381        self.identical(self.MAX, 2.*(ldexp(1.0, 1023) - ldexp(1.0, 970)))
382
383    def test_invalid_inputs(self):
384        invalid_inputs = [
385            'infi',   # misspelt infinities and nans
386            '-Infinit',
387            '++inf',
388            '-+Inf',
389            '--nan',
390            '+-NaN',
391            'snan',
392            'NaNs',
393            'nna',
394            'an',
395            'nf',
396            'nfinity',
397            'inity',
398            'iinity',
399            '0xnan',
400            '',
401            ' ',
402            'x1.0p0',
403            '0xX1.0p0',
404            '+ 0x1.0p0', # internal whitespace
405            '- 0x1.0p0',
406            '0 x1.0p0',
407            '0x 1.0p0',
408            '0x1 2.0p0',
409            '+0x1 .0p0',
410            '0x1. 0p0',
411            '-0x1.0 1p0',
412            '-0x1.0 p0',
413            '+0x1.0p +0',
414            '0x1.0p -0',
415            '0x1.0p 0',
416            '+0x1.0p+ 0',
417            '-0x1.0p- 0',
418            '++0x1.0p-0', # double signs
419            '--0x1.0p0',
420            '+-0x1.0p+0',
421            '-+0x1.0p0',
422            '0x1.0p++0',
423            '+0x1.0p+-0',
424            '-0x1.0p-+0',
425            '0x1.0p--0',
426            '0x1.0.p0',
427            '0x.p0', # no hex digits before or after point
428            '0x1,p0', # wrong decimal point character
429            '0x1pa',
430            u'0x1p\uff10',  # fullwidth Unicode digits
431            u'\uff10x1p0',
432            u'0x\uff11p0',
433            u'0x1.\uff10p0',
434            '0x1p0 \n 0x2p0',
435            '0x1p0\0 0x1p0',  # embedded null byte is not end of string
436            ]
437        for x in invalid_inputs:
438            try:
439                result = fromHex(x)
440            except ValueError:
441                pass
442            else:
443                self.fail('Expected float.fromhex(%r) to raise ValueError; '
444                          'got %r instead' % (x, result))
445
446
447    def test_whitespace(self):
448        value_pairs = [
449            ('inf', INF),
450            ('-Infinity', -INF),
451            ('nan', NAN),
452            ('1.0', 1.0),
453            ('-0x.2', -0.125),
454            ('-0.0', -0.0)
455            ]
456        whitespace = [
457            '',
458            ' ',
459            '\t',
460            '\n',
461            '\n \t',
462            '\f',
463            '\v',
464            '\r'
465            ]
466        for inp, expected in value_pairs:
467            for lead in whitespace:
468                for trail in whitespace:
469                    got = fromHex(lead + inp + trail)
470                    self.identical(got, expected)
471
472
473    def test_from_hex(self):
474        MIN = self.MIN;
475        MAX = self.MAX;
476        TINY = self.TINY;
477        EPS = self.EPS;
478
479        # two spellings of infinity, with optional signs; case-insensitive
480        self.identical(fromHex('inf'), INF)
481        self.identical(fromHex('+Inf'), INF)
482        self.identical(fromHex('-INF'), -INF)
483        self.identical(fromHex('iNf'), INF)
484        self.identical(fromHex('Infinity'), INF)
485        self.identical(fromHex('+INFINITY'), INF)
486        self.identical(fromHex('-infinity'), -INF)
487        self.identical(fromHex('-iNFiNitY'), -INF)
488
489        # nans with optional sign; case insensitive
490        self.identical(fromHex('nan'), NAN)
491        self.identical(fromHex('+NaN'), NAN)
492        self.identical(fromHex('-NaN'), NAN)
493        self.identical(fromHex('-nAN'), NAN)
494
495        # variations in input format
496        self.identical(fromHex('1'), 1.0)
497        self.identical(fromHex('+1'), 1.0)
498        self.identical(fromHex('1.'), 1.0)
499        self.identical(fromHex('1.0'), 1.0)
500        self.identical(fromHex('1.0p0'), 1.0)
501        self.identical(fromHex('01'), 1.0)
502        self.identical(fromHex('01.'), 1.0)
503        self.identical(fromHex('0x1'), 1.0)
504        self.identical(fromHex('0x1.'), 1.0)
505        self.identical(fromHex('0x1.0'), 1.0)
506        self.identical(fromHex('+0x1.0'), 1.0)
507        self.identical(fromHex('0x1p0'), 1.0)
508        self.identical(fromHex('0X1p0'), 1.0)
509        self.identical(fromHex('0X1P0'), 1.0)
510        self.identical(fromHex('0x1P0'), 1.0)
511        self.identical(fromHex('0x1.p0'), 1.0)
512        self.identical(fromHex('0x1.0p0'), 1.0)
513        self.identical(fromHex('0x.1p4'), 1.0)
514        self.identical(fromHex('0x.1p04'), 1.0)
515        self.identical(fromHex('0x.1p004'), 1.0)
516        self.identical(fromHex('0x1p+0'), 1.0)
517        self.identical(fromHex('0x1P-0'), 1.0)
518        self.identical(fromHex('+0x1p0'), 1.0)
519        self.identical(fromHex('0x01p0'), 1.0)
520        self.identical(fromHex('0x1p00'), 1.0)
521        self.identical(fromHex(u'0x1p0'), 1.0)
522        self.identical(fromHex(' 0x1p0 '), 1.0)
523        self.identical(fromHex('\n 0x1p0'), 1.0)
524        self.identical(fromHex('0x1p0 \t'), 1.0)
525        self.identical(fromHex('0xap0'), 10.0)
526        self.identical(fromHex('0xAp0'), 10.0)
527        self.identical(fromHex('0xaP0'), 10.0)
528        self.identical(fromHex('0xAP0'), 10.0)
529        self.identical(fromHex('0xbep0'), 190.0)
530        self.identical(fromHex('0xBep0'), 190.0)
531        self.identical(fromHex('0xbEp0'), 190.0)
532        self.identical(fromHex('0XBE0P-4'), 190.0)
533        self.identical(fromHex('0xBEp0'), 190.0)
534        self.identical(fromHex('0xB.Ep4'), 190.0)
535        self.identical(fromHex('0x.BEp8'), 190.0)
536        self.identical(fromHex('0x.0BEp12'), 190.0)
537
538        # moving the point around
539        pi = fromHex('0x1.921fb54442d18p1')
540        self.identical(fromHex('0x.006487ed5110b46p11'), pi)
541        self.identical(fromHex('0x.00c90fdaa22168cp10'), pi)
542        self.identical(fromHex('0x.01921fb54442d18p9'), pi)
543        self.identical(fromHex('0x.03243f6a8885a3p8'), pi)
544        self.identical(fromHex('0x.06487ed5110b46p7'), pi)
545        self.identical(fromHex('0x.0c90fdaa22168cp6'), pi)
546        self.identical(fromHex('0x.1921fb54442d18p5'), pi)
547        self.identical(fromHex('0x.3243f6a8885a3p4'), pi)
548        self.identical(fromHex('0x.6487ed5110b46p3'), pi)
549        self.identical(fromHex('0x.c90fdaa22168cp2'), pi)
550        self.identical(fromHex('0x1.921fb54442d18p1'), pi)
551        self.identical(fromHex('0x3.243f6a8885a3p0'), pi)
552        self.identical(fromHex('0x6.487ed5110b46p-1'), pi)
553        self.identical(fromHex('0xc.90fdaa22168cp-2'), pi)
554        self.identical(fromHex('0x19.21fb54442d18p-3'), pi)
555        self.identical(fromHex('0x32.43f6a8885a3p-4'), pi)
556        self.identical(fromHex('0x64.87ed5110b46p-5'), pi)
557        self.identical(fromHex('0xc9.0fdaa22168cp-6'), pi)
558        self.identical(fromHex('0x192.1fb54442d18p-7'), pi)
559        self.identical(fromHex('0x324.3f6a8885a3p-8'), pi)
560        self.identical(fromHex('0x648.7ed5110b46p-9'), pi)
561        self.identical(fromHex('0xc90.fdaa22168cp-10'), pi)
562        self.identical(fromHex('0x1921.fb54442d18p-11'), pi)
563        # ...
564        self.identical(fromHex('0x1921fb54442d1.8p-47'), pi)
565        self.identical(fromHex('0x3243f6a8885a3p-48'), pi)
566        self.identical(fromHex('0x6487ed5110b46p-49'), pi)
567        self.identical(fromHex('0xc90fdaa22168cp-50'), pi)
568        self.identical(fromHex('0x1921fb54442d18p-51'), pi)
569        self.identical(fromHex('0x3243f6a8885a30p-52'), pi)
570        self.identical(fromHex('0x6487ed5110b460p-53'), pi)
571        self.identical(fromHex('0xc90fdaa22168c0p-54'), pi)
572        self.identical(fromHex('0x1921fb54442d180p-55'), pi)
573
574
575        # results that should overflow...
576        self.assertRaises(OverflowError, fromHex, '-0x1p1024')
577        self.assertRaises(OverflowError, fromHex, '0x1p+1025')
578        self.assertRaises(OverflowError, fromHex, '+0X1p1030')
579        self.assertRaises(OverflowError, fromHex, '-0x1p+1100')
580        self.assertRaises(OverflowError, fromHex, '0X1p123456789123456789')
581        self.assertRaises(OverflowError, fromHex, '+0X.8p+1025')
582        self.assertRaises(OverflowError, fromHex, '+0x0.8p1025')
583        self.assertRaises(OverflowError, fromHex, '-0x0.4p1026')
584        self.assertRaises(OverflowError, fromHex, '0X2p+1023')
585        self.assertRaises(OverflowError, fromHex, '0x2.p1023')
586        self.assertRaises(OverflowError, fromHex, '-0x2.0p+1023')
587        self.assertRaises(OverflowError, fromHex, '+0X4p+1022')
588        self.assertRaises(OverflowError, fromHex, '0x1.ffffffffffffffp+1023')
589        self.assertRaises(OverflowError, fromHex, '-0X1.fffffffffffff9p1023')
590        self.assertRaises(OverflowError, fromHex, '0X1.fffffffffffff8p1023')
591        self.assertRaises(OverflowError, fromHex, '+0x3.fffffffffffffp1022')
592        self.assertRaises(OverflowError, fromHex, '0x3fffffffffffffp+970')
593        self.assertRaises(OverflowError, fromHex, '0x10000000000000000p960')
594        self.assertRaises(OverflowError, fromHex, '-0Xffffffffffffffffp960')
595
596        # ...and those that round to +-max float
597        self.identical(fromHex('+0x1.fffffffffffffp+1023'), MAX)
598        self.identical(fromHex('-0X1.fffffffffffff7p1023'), -MAX)
599        self.identical(fromHex('0X1.fffffffffffff7fffffffffffffp1023'), MAX)
600
601        # zeros
602        self.identical(fromHex('0x0p0'), 0.0)
603        self.identical(fromHex('0x0p1000'), 0.0)
604        self.identical(fromHex('-0x0p1023'), -0.0)
605        self.identical(fromHex('0X0p1024'), 0.0)
606        self.identical(fromHex('-0x0p1025'), -0.0)
607        self.identical(fromHex('0X0p2000'), 0.0)
608        self.identical(fromHex('0x0p123456789123456789'), 0.0)
609        self.identical(fromHex('-0X0p-0'), -0.0)
610        self.identical(fromHex('-0X0p-1000'), -0.0)
611        self.identical(fromHex('0x0p-1023'), 0.0)
612        self.identical(fromHex('-0X0p-1024'), -0.0)
613        self.identical(fromHex('-0x0p-1025'), -0.0)
614        self.identical(fromHex('-0x0p-1072'), -0.0)
615        self.identical(fromHex('0X0p-1073'), 0.0)
616        self.identical(fromHex('-0x0p-1074'), -0.0)
617        self.identical(fromHex('0x0p-1075'), 0.0)
618        self.identical(fromHex('0X0p-1076'), 0.0)
619        self.identical(fromHex('-0X0p-2000'), -0.0)
620        self.identical(fromHex('-0x0p-123456789123456789'), -0.0)
621
622        # values that should underflow to 0
623        self.identical(fromHex('0X1p-1075'), 0.0)
624        self.identical(fromHex('-0X1p-1075'), -0.0)
625        self.identical(fromHex('-0x1p-123456789123456789'), -0.0)
626        self.identical(fromHex('0x1.00000000000000001p-1075'), TINY)
627        self.identical(fromHex('-0x1.1p-1075'), -TINY)
628        self.identical(fromHex('0x1.fffffffffffffffffp-1075'), TINY)
629
630        # check round-half-even is working correctly near 0 ...
631        self.identical(fromHex('0x1p-1076'), 0.0)
632        self.identical(fromHex('0X2p-1076'), 0.0)
633        self.identical(fromHex('0X3p-1076'), TINY)
634        self.identical(fromHex('0x4p-1076'), TINY)
635        self.identical(fromHex('0X5p-1076'), TINY)
636        self.identical(fromHex('0X6p-1076'), 2*TINY)
637        self.identical(fromHex('0x7p-1076'), 2*TINY)
638        self.identical(fromHex('0X8p-1076'), 2*TINY)
639        self.identical(fromHex('0X9p-1076'), 2*TINY)
640        self.identical(fromHex('0xap-1076'), 2*TINY)
641        self.identical(fromHex('0Xbp-1076'), 3*TINY)
642        self.identical(fromHex('0xcp-1076'), 3*TINY)
643        self.identical(fromHex('0Xdp-1076'), 3*TINY)
644        self.identical(fromHex('0Xep-1076'), 4*TINY)
645        self.identical(fromHex('0xfp-1076'), 4*TINY)
646        self.identical(fromHex('0x10p-1076'), 4*TINY)
647        self.identical(fromHex('-0x1p-1076'), -0.0)
648        self.identical(fromHex('-0X2p-1076'), -0.0)
649        self.identical(fromHex('-0x3p-1076'), -TINY)
650        self.identical(fromHex('-0X4p-1076'), -TINY)
651        self.identical(fromHex('-0x5p-1076'), -TINY)
652        self.identical(fromHex('-0x6p-1076'), -2*TINY)
653        self.identical(fromHex('-0X7p-1076'), -2*TINY)
654        self.identical(fromHex('-0X8p-1076'), -2*TINY)
655        self.identical(fromHex('-0X9p-1076'), -2*TINY)
656        self.identical(fromHex('-0Xap-1076'), -2*TINY)
657        self.identical(fromHex('-0xbp-1076'), -3*TINY)
658        self.identical(fromHex('-0xcp-1076'), -3*TINY)
659        self.identical(fromHex('-0Xdp-1076'), -3*TINY)
660        self.identical(fromHex('-0xep-1076'), -4*TINY)
661        self.identical(fromHex('-0Xfp-1076'), -4*TINY)
662        self.identical(fromHex('-0X10p-1076'), -4*TINY)
663
664        # ... and near MIN ...
665        self.identical(fromHex('0x0.ffffffffffffd6p-1022'), MIN-3*TINY)
666        self.identical(fromHex('0x0.ffffffffffffd8p-1022'), MIN-2*TINY)
667        self.identical(fromHex('0x0.ffffffffffffdap-1022'), MIN-2*TINY)
668        self.identical(fromHex('0x0.ffffffffffffdcp-1022'), MIN-2*TINY)
669        self.identical(fromHex('0x0.ffffffffffffdep-1022'), MIN-2*TINY)
670        self.identical(fromHex('0x0.ffffffffffffe0p-1022'), MIN-2*TINY)
671        self.identical(fromHex('0x0.ffffffffffffe2p-1022'), MIN-2*TINY)
672        self.identical(fromHex('0x0.ffffffffffffe4p-1022'), MIN-2*TINY)
673        self.identical(fromHex('0x0.ffffffffffffe6p-1022'), MIN-2*TINY)
674        self.identical(fromHex('0x0.ffffffffffffe8p-1022'), MIN-2*TINY)
675        self.identical(fromHex('0x0.ffffffffffffeap-1022'), MIN-TINY)
676        self.identical(fromHex('0x0.ffffffffffffecp-1022'), MIN-TINY)
677        self.identical(fromHex('0x0.ffffffffffffeep-1022'), MIN-TINY)
678        self.identical(fromHex('0x0.fffffffffffff0p-1022'), MIN-TINY)
679        self.identical(fromHex('0x0.fffffffffffff2p-1022'), MIN-TINY)
680        self.identical(fromHex('0x0.fffffffffffff4p-1022'), MIN-TINY)
681        self.identical(fromHex('0x0.fffffffffffff6p-1022'), MIN-TINY)
682        self.identical(fromHex('0x0.fffffffffffff8p-1022'), MIN)
683        self.identical(fromHex('0x0.fffffffffffffap-1022'), MIN)
684        self.identical(fromHex('0x0.fffffffffffffcp-1022'), MIN)
685        self.identical(fromHex('0x0.fffffffffffffep-1022'), MIN)
686        self.identical(fromHex('0x1.00000000000000p-1022'), MIN)
687        self.identical(fromHex('0x1.00000000000002p-1022'), MIN)
688        self.identical(fromHex('0x1.00000000000004p-1022'), MIN)
689        self.identical(fromHex('0x1.00000000000006p-1022'), MIN)
690        self.identical(fromHex('0x1.00000000000008p-1022'), MIN)
691        self.identical(fromHex('0x1.0000000000000ap-1022'), MIN+TINY)
692        self.identical(fromHex('0x1.0000000000000cp-1022'), MIN+TINY)
693        self.identical(fromHex('0x1.0000000000000ep-1022'), MIN+TINY)
694        self.identical(fromHex('0x1.00000000000010p-1022'), MIN+TINY)
695        self.identical(fromHex('0x1.00000000000012p-1022'), MIN+TINY)
696        self.identical(fromHex('0x1.00000000000014p-1022'), MIN+TINY)
697        self.identical(fromHex('0x1.00000000000016p-1022'), MIN+TINY)
698        self.identical(fromHex('0x1.00000000000018p-1022'), MIN+2*TINY)
699
700        # ... and near 1.0.
701        self.identical(fromHex('0x0.fffffffffffff0p0'), 1.0-EPS)
702        self.identical(fromHex('0x0.fffffffffffff1p0'), 1.0-EPS)
703        self.identical(fromHex('0X0.fffffffffffff2p0'), 1.0-EPS)
704        self.identical(fromHex('0x0.fffffffffffff3p0'), 1.0-EPS)
705        self.identical(fromHex('0X0.fffffffffffff4p0'), 1.0-EPS)
706        self.identical(fromHex('0X0.fffffffffffff5p0'), 1.0-EPS/2)
707        self.identical(fromHex('0X0.fffffffffffff6p0'), 1.0-EPS/2)
708        self.identical(fromHex('0x0.fffffffffffff7p0'), 1.0-EPS/2)
709        self.identical(fromHex('0x0.fffffffffffff8p0'), 1.0-EPS/2)
710        self.identical(fromHex('0X0.fffffffffffff9p0'), 1.0-EPS/2)
711        self.identical(fromHex('0X0.fffffffffffffap0'), 1.0-EPS/2)
712        self.identical(fromHex('0x0.fffffffffffffbp0'), 1.0-EPS/2)
713        self.identical(fromHex('0X0.fffffffffffffcp0'), 1.0)
714        self.identical(fromHex('0x0.fffffffffffffdp0'), 1.0)
715        self.identical(fromHex('0X0.fffffffffffffep0'), 1.0)
716        self.identical(fromHex('0x0.ffffffffffffffp0'), 1.0)
717        self.identical(fromHex('0X1.00000000000000p0'), 1.0)
718        self.identical(fromHex('0X1.00000000000001p0'), 1.0)
719        self.identical(fromHex('0x1.00000000000002p0'), 1.0)
720        self.identical(fromHex('0X1.00000000000003p0'), 1.0)
721        self.identical(fromHex('0x1.00000000000004p0'), 1.0)
722        self.identical(fromHex('0X1.00000000000005p0'), 1.0)
723        self.identical(fromHex('0X1.00000000000006p0'), 1.0)
724        self.identical(fromHex('0X1.00000000000007p0'), 1.0)
725        self.identical(fromHex('0x1.00000000000007ffffffffffffffffffffp0'),
726                       1.0)
727        self.identical(fromHex('0x1.00000000000008p0'), 1.0)
728        self.identical(fromHex('0x1.00000000000008000000000000000001p0'),
729                       1+EPS)
730        self.identical(fromHex('0X1.00000000000009p0'), 1.0+EPS)
731        self.identical(fromHex('0x1.0000000000000ap0'), 1.0+EPS)
732        self.identical(fromHex('0x1.0000000000000bp0'), 1.0+EPS)
733        self.identical(fromHex('0X1.0000000000000cp0'), 1.0+EPS)
734        self.identical(fromHex('0x1.0000000000000dp0'), 1.0+EPS)
735        self.identical(fromHex('0x1.0000000000000ep0'), 1.0+EPS)
736        self.identical(fromHex('0X1.0000000000000fp0'), 1.0+EPS)
737        self.identical(fromHex('0x1.00000000000010p0'), 1.0+EPS)
738        self.identical(fromHex('0X1.00000000000011p0'), 1.0+EPS)
739        self.identical(fromHex('0x1.00000000000012p0'), 1.0+EPS)
740        self.identical(fromHex('0X1.00000000000013p0'), 1.0+EPS)
741        self.identical(fromHex('0X1.00000000000014p0'), 1.0+EPS)
742        self.identical(fromHex('0x1.00000000000015p0'), 1.0+EPS)
743        self.identical(fromHex('0x1.00000000000016p0'), 1.0+EPS)
744        self.identical(fromHex('0X1.00000000000017p0'), 1.0+EPS)
745        self.identical(fromHex('0x1.00000000000017ffffffffffffffffffffp0'),
746                       1.0+EPS)
747        self.identical(fromHex('0x1.00000000000018p0'), 1.0+2*EPS)
748        self.identical(fromHex('0X1.00000000000018000000000000000001p0'),
749                       1.0+2*EPS)
750        self.identical(fromHex('0x1.00000000000019p0'), 1.0+2*EPS)
751        self.identical(fromHex('0X1.0000000000001ap0'), 1.0+2*EPS)
752        self.identical(fromHex('0X1.0000000000001bp0'), 1.0+2*EPS)
753        self.identical(fromHex('0x1.0000000000001cp0'), 1.0+2*EPS)
754        self.identical(fromHex('0x1.0000000000001dp0'), 1.0+2*EPS)
755        self.identical(fromHex('0x1.0000000000001ep0'), 1.0+2*EPS)
756        self.identical(fromHex('0X1.0000000000001fp0'), 1.0+2*EPS)
757        self.identical(fromHex('0x1.00000000000020p0'), 1.0+2*EPS)
758
759    def test_roundtrip(self):
760        def roundtrip(x):
761            return fromHex(toHex(x))
762
763        for x in [NAN, INF, self.MAX, self.MIN, self.MIN-self.TINY, self.TINY, 0.0]:
764            self.identical(x, roundtrip(x))
765            self.identical(-x, roundtrip(-x))
766
767        # fromHex(toHex(x)) should exactly recover x, for any non-NaN float x.
768        import random
769        for i in xrange(10000):
770            e = random.randrange(-1200, 1200)
771            m = random.random()
772            s = random.choice([1.0, -1.0])
773            try:
774                x = s*ldexp(m, e)
775            except OverflowError:
776                pass
777            else:
778                self.identical(x, fromHex(toHex(x)))
779
780
781def test_main():
782    test_support.run_unittest(
783        GeneralFloatCases,
784        FormatFunctionsTestCase,
785        UnknownFormatTestCase,
786        IEEEFormatTestCase,
787        ReprTestCase,
788        InfNanTest,
789        HexFloatTestCase,
790        )
791
792if __name__ == '__main__':
793    test_main()