Home | History | Annotate | Download | only in test
      1 # Python test set -- math module
      2 # XXXX Should not do tests around zero only
      3 
      4 from test.test_support import run_unittest, verbose
      5 import unittest
      6 import math
      7 import os
      8 import sys
      9 import random
     10 import struct
     11 
     12 eps = 1E-05
     13 NAN = float('nan')
     14 INF = float('inf')
     15 NINF = float('-inf')
     16 
     17 # decorator for skipping tests on non-IEEE 754 platforms
     18 requires_IEEE_754 = unittest.skipUnless(
     19     float.__getformat__("double").startswith("IEEE"),
     20     "test requires IEEE 754 doubles")
     21 
     22 # detect evidence of double-rounding: fsum is not always correctly
     23 # rounded on machines that suffer from double rounding.
     24 x, y = 1e16, 2.9999 # use temporary values to defeat peephole optimizer
     25 HAVE_DOUBLE_ROUNDING = (x + y == 1e16 + 4)
     26 
     27 # locate file with test values
     28 if __name__ == '__main__':
     29     file = sys.argv[0]
     30 else:
     31     file = __file__
     32 test_dir = os.path.dirname(file) or os.curdir
     33 math_testcases = os.path.join(test_dir, 'math_testcases.txt')
     34 test_file = os.path.join(test_dir, 'cmath_testcases.txt')
     35 
     36 def to_ulps(x):
     37     """Convert a non-NaN float x to an integer, in such a way that
     38     adjacent floats are converted to adjacent integers.  Then
     39     abs(ulps(x) - ulps(y)) gives the difference in ulps between two
     40     floats.
     41 
     42     The results from this function will only make sense on platforms
     43     where C doubles are represented in IEEE 754 binary64 format.
     44 
     45     """
     46     n = struct.unpack('<q', struct.pack('<d', x))[0]
     47     if n < 0:
     48         n = ~(n+2**63)
     49     return n
     50 
     51 def ulps_check(expected, got, ulps=20):
     52     """Given non-NaN floats `expected` and `got`,
     53     check that they're equal to within the given number of ulps.
     54 
     55     Returns None on success and an error message on failure."""
     56 
     57     ulps_error = to_ulps(got) - to_ulps(expected)
     58     if abs(ulps_error) <= ulps:
     59         return None
     60     return "error = {} ulps; permitted error = {} ulps".format(ulps_error,
     61                                                                ulps)
     62 
     63 def acc_check(expected, got, rel_err=2e-15, abs_err = 5e-323):
     64     """Determine whether non-NaN floats a and b are equal to within a
     65     (small) rounding error.  The default values for rel_err and
     66     abs_err are chosen to be suitable for platforms where a float is
     67     represented by an IEEE 754 double.  They allow an error of between
     68     9 and 19 ulps."""
     69 
     70     # need to special case infinities, since inf - inf gives nan
     71     if math.isinf(expected) and got == expected:
     72         return None
     73 
     74     error = got - expected
     75 
     76     permitted_error = max(abs_err, rel_err * abs(expected))
     77     if abs(error) < permitted_error:
     78         return None
     79     return "error = {}; permitted error = {}".format(error,
     80                                                      permitted_error)
     81 
     82 def parse_mtestfile(fname):
     83     """Parse a file with test values
     84 
     85     -- starts a comment
     86     blank lines, or lines containing only a comment, are ignored
     87     other lines are expected to have the form
     88       id fn arg -> expected [flag]*
     89 
     90     """
     91     with open(fname) as fp:
     92         for line in fp:
     93             # strip comments, and skip blank lines
     94             if '--' in line:
     95                 line = line[:line.index('--')]
     96             if not line.strip():
     97                 continue
     98 
     99             lhs, rhs = line.split('->')
    100             id, fn, arg = lhs.split()
    101             rhs_pieces = rhs.split()
    102             exp = rhs_pieces[0]
    103             flags = rhs_pieces[1:]
    104 
    105             yield (id, fn, float(arg), float(exp), flags)
    106 
    107 def parse_testfile(fname):
    108     """Parse a file with test values
    109 
    110     Empty lines or lines starting with -- are ignored
    111     yields id, fn, arg_real, arg_imag, exp_real, exp_imag
    112     """
    113     with open(fname) as fp:
    114         for line in fp:
    115             # skip comment lines and blank lines
    116             if line.startswith('--') or not line.strip():
    117                 continue
    118 
    119             lhs, rhs = line.split('->')
    120             id, fn, arg_real, arg_imag = lhs.split()
    121             rhs_pieces = rhs.split()
    122             exp_real, exp_imag = rhs_pieces[0], rhs_pieces[1]
    123             flags = rhs_pieces[2:]
    124 
    125             yield (id, fn,
    126                    float(arg_real), float(arg_imag),
    127                    float(exp_real), float(exp_imag),
    128                    flags
    129                   )
    130 
    131 class MathTests(unittest.TestCase):
    132 
    133     def ftest(self, name, value, expected):
    134         if abs(value-expected) > eps:
    135             # Use %r instead of %f so the error message
    136             # displays full precision. Otherwise discrepancies
    137             # in the last few bits will lead to very confusing
    138             # error messages
    139             self.fail('%s returned %r, expected %r' %
    140                       (name, value, expected))
    141 
    142     def testConstants(self):
    143         self.ftest('pi', math.pi, 3.1415926)
    144         self.ftest('e', math.e, 2.7182818)
    145 
    146     def testAcos(self):
    147         self.assertRaises(TypeError, math.acos)
    148         self.ftest('acos(-1)', math.acos(-1), math.pi)
    149         self.ftest('acos(0)', math.acos(0), math.pi/2)
    150         self.ftest('acos(1)', math.acos(1), 0)
    151         self.assertRaises(ValueError, math.acos, INF)
    152         self.assertRaises(ValueError, math.acos, NINF)
    153         self.assertTrue(math.isnan(math.acos(NAN)))
    154 
    155     def testAcosh(self):
    156         self.assertRaises(TypeError, math.acosh)
    157         self.ftest('acosh(1)', math.acosh(1), 0)
    158         self.ftest('acosh(2)', math.acosh(2), 1.3169578969248168)
    159         self.assertRaises(ValueError, math.acosh, 0)
    160         self.assertRaises(ValueError, math.acosh, -1)
    161         self.assertEqual(math.acosh(INF), INF)
    162         self.assertRaises(ValueError, math.acosh, NINF)
    163         self.assertTrue(math.isnan(math.acosh(NAN)))
    164 
    165     def testAsin(self):
    166         self.assertRaises(TypeError, math.asin)
    167         self.ftest('asin(-1)', math.asin(-1), -math.pi/2)
    168         self.ftest('asin(0)', math.asin(0), 0)
    169         self.ftest('asin(1)', math.asin(1), math.pi/2)
    170         self.assertRaises(ValueError, math.asin, INF)
    171         self.assertRaises(ValueError, math.asin, NINF)
    172         self.assertTrue(math.isnan(math.asin(NAN)))
    173 
    174     def testAsinh(self):
    175         self.assertRaises(TypeError, math.asinh)
    176         self.ftest('asinh(0)', math.asinh(0), 0)
    177         self.ftest('asinh(1)', math.asinh(1), 0.88137358701954305)
    178         self.ftest('asinh(-1)', math.asinh(-1), -0.88137358701954305)
    179         self.assertEqual(math.asinh(INF), INF)
    180         self.assertEqual(math.asinh(NINF), NINF)
    181         self.assertTrue(math.isnan(math.asinh(NAN)))
    182 
    183     def testAtan(self):
    184         self.assertRaises(TypeError, math.atan)
    185         self.ftest('atan(-1)', math.atan(-1), -math.pi/4)
    186         self.ftest('atan(0)', math.atan(0), 0)
    187         self.ftest('atan(1)', math.atan(1), math.pi/4)
    188         self.ftest('atan(inf)', math.atan(INF), math.pi/2)
    189         self.ftest('atan(-inf)', math.atan(NINF), -math.pi/2)
    190         self.assertTrue(math.isnan(math.atan(NAN)))
    191 
    192     def testAtanh(self):
    193         self.assertRaises(TypeError, math.atan)
    194         self.ftest('atanh(0)', math.atanh(0), 0)
    195         self.ftest('atanh(0.5)', math.atanh(0.5), 0.54930614433405489)
    196         self.ftest('atanh(-0.5)', math.atanh(-0.5), -0.54930614433405489)
    197         self.assertRaises(ValueError, math.atanh, 1)
    198         self.assertRaises(ValueError, math.atanh, -1)
    199         self.assertRaises(ValueError, math.atanh, INF)
    200         self.assertRaises(ValueError, math.atanh, NINF)
    201         self.assertTrue(math.isnan(math.atanh(NAN)))
    202 
    203     def testAtan2(self):
    204         self.assertRaises(TypeError, math.atan2)
    205         self.ftest('atan2(-1, 0)', math.atan2(-1, 0), -math.pi/2)
    206         self.ftest('atan2(-1, 1)', math.atan2(-1, 1), -math.pi/4)
    207         self.ftest('atan2(0, 1)', math.atan2(0, 1), 0)
    208         self.ftest('atan2(1, 1)', math.atan2(1, 1), math.pi/4)
    209         self.ftest('atan2(1, 0)', math.atan2(1, 0), math.pi/2)
    210 
    211         # math.atan2(0, x)
    212         self.ftest('atan2(0., -inf)', math.atan2(0., NINF), math.pi)
    213         self.ftest('atan2(0., -2.3)', math.atan2(0., -2.3), math.pi)
    214         self.ftest('atan2(0., -0.)', math.atan2(0., -0.), math.pi)
    215         self.assertEqual(math.atan2(0., 0.), 0.)
    216         self.assertEqual(math.atan2(0., 2.3), 0.)
    217         self.assertEqual(math.atan2(0., INF), 0.)
    218         self.assertTrue(math.isnan(math.atan2(0., NAN)))
    219         # math.atan2(-0, x)
    220         self.ftest('atan2(-0., -inf)', math.atan2(-0., NINF), -math.pi)
    221         self.ftest('atan2(-0., -2.3)', math.atan2(-0., -2.3), -math.pi)
    222         self.ftest('atan2(-0., -0.)', math.atan2(-0., -0.), -math.pi)
    223         self.assertEqual(math.atan2(-0., 0.), -0.)
    224         self.assertEqual(math.atan2(-0., 2.3), -0.)
    225         self.assertEqual(math.atan2(-0., INF), -0.)
    226         self.assertTrue(math.isnan(math.atan2(-0., NAN)))
    227         # math.atan2(INF, x)
    228         self.ftest('atan2(inf, -inf)', math.atan2(INF, NINF), math.pi*3/4)
    229         self.ftest('atan2(inf, -2.3)', math.atan2(INF, -2.3), math.pi/2)
    230         self.ftest('atan2(inf, -0.)', math.atan2(INF, -0.0), math.pi/2)
    231         self.ftest('atan2(inf, 0.)', math.atan2(INF, 0.0), math.pi/2)
    232         self.ftest('atan2(inf, 2.3)', math.atan2(INF, 2.3), math.pi/2)
    233         self.ftest('atan2(inf, inf)', math.atan2(INF, INF), math.pi/4)
    234         self.assertTrue(math.isnan(math.atan2(INF, NAN)))
    235         # math.atan2(NINF, x)
    236         self.ftest('atan2(-inf, -inf)', math.atan2(NINF, NINF), -math.pi*3/4)
    237         self.ftest('atan2(-inf, -2.3)', math.atan2(NINF, -2.3), -math.pi/2)
    238         self.ftest('atan2(-inf, -0.)', math.atan2(NINF, -0.0), -math.pi/2)
    239         self.ftest('atan2(-inf, 0.)', math.atan2(NINF, 0.0), -math.pi/2)
    240         self.ftest('atan2(-inf, 2.3)', math.atan2(NINF, 2.3), -math.pi/2)
    241         self.ftest('atan2(-inf, inf)', math.atan2(NINF, INF), -math.pi/4)
    242         self.assertTrue(math.isnan(math.atan2(NINF, NAN)))
    243         # math.atan2(+finite, x)
    244         self.ftest('atan2(2.3, -inf)', math.atan2(2.3, NINF), math.pi)
    245         self.ftest('atan2(2.3, -0.)', math.atan2(2.3, -0.), math.pi/2)
    246         self.ftest('atan2(2.3, 0.)', math.atan2(2.3, 0.), math.pi/2)
    247         self.assertEqual(math.atan2(2.3, INF), 0.)
    248         self.assertTrue(math.isnan(math.atan2(2.3, NAN)))
    249         # math.atan2(-finite, x)
    250         self.ftest('atan2(-2.3, -inf)', math.atan2(-2.3, NINF), -math.pi)
    251         self.ftest('atan2(-2.3, -0.)', math.atan2(-2.3, -0.), -math.pi/2)
    252         self.ftest('atan2(-2.3, 0.)', math.atan2(-2.3, 0.), -math.pi/2)
    253         self.assertEqual(math.atan2(-2.3, INF), -0.)
    254         self.assertTrue(math.isnan(math.atan2(-2.3, NAN)))
    255         # math.atan2(NAN, x)
    256         self.assertTrue(math.isnan(math.atan2(NAN, NINF)))
    257         self.assertTrue(math.isnan(math.atan2(NAN, -2.3)))
    258         self.assertTrue(math.isnan(math.atan2(NAN, -0.)))
    259         self.assertTrue(math.isnan(math.atan2(NAN, 0.)))
    260         self.assertTrue(math.isnan(math.atan2(NAN, 2.3)))
    261         self.assertTrue(math.isnan(math.atan2(NAN, INF)))
    262         self.assertTrue(math.isnan(math.atan2(NAN, NAN)))
    263 
    264     def testCeil(self):
    265         self.assertRaises(TypeError, math.ceil)
    266         # These types will be int in py3k.
    267         self.assertEqual(float, type(math.ceil(1)))
    268         self.assertEqual(float, type(math.ceil(1L)))
    269         self.assertEqual(float, type(math.ceil(1.0)))
    270         self.ftest('ceil(0.5)', math.ceil(0.5), 1)
    271         self.ftest('ceil(1.0)', math.ceil(1.0), 1)
    272         self.ftest('ceil(1.5)', math.ceil(1.5), 2)
    273         self.ftest('ceil(-0.5)', math.ceil(-0.5), 0)
    274         self.ftest('ceil(-1.0)', math.ceil(-1.0), -1)
    275         self.ftest('ceil(-1.5)', math.ceil(-1.5), -1)
    276         self.assertEqual(math.ceil(INF), INF)
    277         self.assertEqual(math.ceil(NINF), NINF)
    278         self.assertTrue(math.isnan(math.ceil(NAN)))
    279 
    280         class TestCeil(object):
    281             def __float__(self):
    282                 return 41.3
    283         class TestNoCeil(object):
    284             pass
    285         self.ftest('ceil(TestCeil())', math.ceil(TestCeil()), 42)
    286         self.assertRaises(TypeError, math.ceil, TestNoCeil())
    287 
    288         t = TestNoCeil()
    289         t.__ceil__ = lambda *args: args
    290         self.assertRaises(TypeError, math.ceil, t)
    291         self.assertRaises(TypeError, math.ceil, t, 0)
    292 
    293     @requires_IEEE_754
    294     def testCopysign(self):
    295         self.assertEqual(math.copysign(1, 42), 1.0)
    296         self.assertEqual(math.copysign(0., 42), 0.0)
    297         self.assertEqual(math.copysign(1., -42), -1.0)
    298         self.assertEqual(math.copysign(3, 0.), 3.0)
    299         self.assertEqual(math.copysign(4., -0.), -4.0)
    300 
    301         self.assertRaises(TypeError, math.copysign)
    302         # copysign should let us distinguish signs of zeros
    303         self.assertEqual(math.copysign(1., 0.), 1.)
    304         self.assertEqual(math.copysign(1., -0.), -1.)
    305         self.assertEqual(math.copysign(INF, 0.), INF)
    306         self.assertEqual(math.copysign(INF, -0.), NINF)
    307         self.assertEqual(math.copysign(NINF, 0.), INF)
    308         self.assertEqual(math.copysign(NINF, -0.), NINF)
    309         # and of infinities
    310         self.assertEqual(math.copysign(1., INF), 1.)
    311         self.assertEqual(math.copysign(1., NINF), -1.)
    312         self.assertEqual(math.copysign(INF, INF), INF)
    313         self.assertEqual(math.copysign(INF, NINF), NINF)
    314         self.assertEqual(math.copysign(NINF, INF), INF)
    315         self.assertEqual(math.copysign(NINF, NINF), NINF)
    316         self.assertTrue(math.isnan(math.copysign(NAN, 1.)))
    317         self.assertTrue(math.isnan(math.copysign(NAN, INF)))
    318         self.assertTrue(math.isnan(math.copysign(NAN, NINF)))
    319         self.assertTrue(math.isnan(math.copysign(NAN, NAN)))
    320         # copysign(INF, NAN) may be INF or it may be NINF, since
    321         # we don't know whether the sign bit of NAN is set on any
    322         # given platform.
    323         self.assertTrue(math.isinf(math.copysign(INF, NAN)))
    324         # similarly, copysign(2., NAN) could be 2. or -2.
    325         self.assertEqual(abs(math.copysign(2., NAN)), 2.)
    326 
    327     def testCos(self):
    328         self.assertRaises(TypeError, math.cos)
    329         self.ftest('cos(-pi/2)', math.cos(-math.pi/2), 0)
    330         self.ftest('cos(0)', math.cos(0), 1)
    331         self.ftest('cos(pi/2)', math.cos(math.pi/2), 0)
    332         self.ftest('cos(pi)', math.cos(math.pi), -1)
    333         try:
    334             self.assertTrue(math.isnan(math.cos(INF)))
    335             self.assertTrue(math.isnan(math.cos(NINF)))
    336         except ValueError:
    337             self.assertRaises(ValueError, math.cos, INF)
    338             self.assertRaises(ValueError, math.cos, NINF)
    339         self.assertTrue(math.isnan(math.cos(NAN)))
    340 
    341     def testCosh(self):
    342         self.assertRaises(TypeError, math.cosh)
    343         self.ftest('cosh(0)', math.cosh(0), 1)
    344         self.ftest('cosh(2)-2*cosh(1)**2', math.cosh(2)-2*math.cosh(1)**2, -1) # Thanks to Lambert
    345         self.assertEqual(math.cosh(INF), INF)
    346         self.assertEqual(math.cosh(NINF), INF)
    347         self.assertTrue(math.isnan(math.cosh(NAN)))
    348 
    349     def testDegrees(self):
    350         self.assertRaises(TypeError, math.degrees)
    351         self.ftest('degrees(pi)', math.degrees(math.pi), 180.0)
    352         self.ftest('degrees(pi/2)', math.degrees(math.pi/2), 90.0)
    353         self.ftest('degrees(-pi/4)', math.degrees(-math.pi/4), -45.0)
    354 
    355     def testExp(self):
    356         self.assertRaises(TypeError, math.exp)
    357         self.ftest('exp(-1)', math.exp(-1), 1/math.e)
    358         self.ftest('exp(0)', math.exp(0), 1)
    359         self.ftest('exp(1)', math.exp(1), math.e)
    360         self.assertEqual(math.exp(INF), INF)
    361         self.assertEqual(math.exp(NINF), 0.)
    362         self.assertTrue(math.isnan(math.exp(NAN)))
    363 
    364     def testFabs(self):
    365         self.assertRaises(TypeError, math.fabs)
    366         self.ftest('fabs(-1)', math.fabs(-1), 1)
    367         self.ftest('fabs(0)', math.fabs(0), 0)
    368         self.ftest('fabs(1)', math.fabs(1), 1)
    369 
    370     def testFactorial(self):
    371         def fact(n):
    372             result = 1
    373             for i in range(1, int(n)+1):
    374                 result *= i
    375             return result
    376         values = range(10) + [50, 100, 500]
    377         random.shuffle(values)
    378         for x in values:
    379             for cast in (int, long, float):
    380                 self.assertEqual(math.factorial(cast(x)), fact(x), (x, fact(x), math.factorial(x)))
    381         self.assertRaises(ValueError, math.factorial, -1)
    382         self.assertRaises(ValueError, math.factorial, math.pi)
    383 
    384     def testFloor(self):
    385         self.assertRaises(TypeError, math.floor)
    386         # These types will be int in py3k.
    387         self.assertEqual(float, type(math.floor(1)))
    388         self.assertEqual(float, type(math.floor(1L)))
    389         self.assertEqual(float, type(math.floor(1.0)))
    390         self.ftest('floor(0.5)', math.floor(0.5), 0)
    391         self.ftest('floor(1.0)', math.floor(1.0), 1)
    392         self.ftest('floor(1.5)', math.floor(1.5), 1)
    393         self.ftest('floor(-0.5)', math.floor(-0.5), -1)
    394         self.ftest('floor(-1.0)', math.floor(-1.0), -1)
    395         self.ftest('floor(-1.5)', math.floor(-1.5), -2)
    396         # pow() relies on floor() to check for integers
    397         # This fails on some platforms - so check it here
    398         self.ftest('floor(1.23e167)', math.floor(1.23e167), 1.23e167)
    399         self.ftest('floor(-1.23e167)', math.floor(-1.23e167), -1.23e167)
    400         self.assertEqual(math.ceil(INF), INF)
    401         self.assertEqual(math.ceil(NINF), NINF)
    402         self.assertTrue(math.isnan(math.floor(NAN)))
    403 
    404         class TestFloor(object):
    405             def __float__(self):
    406                 return 42.3
    407         class TestNoFloor(object):
    408             pass
    409         self.ftest('floor(TestFloor())', math.floor(TestFloor()), 42)
    410         self.assertRaises(TypeError, math.floor, TestNoFloor())
    411 
    412         t = TestNoFloor()
    413         t.__floor__ = lambda *args: args
    414         self.assertRaises(TypeError, math.floor, t)
    415         self.assertRaises(TypeError, math.floor, t, 0)
    416 
    417     def testFmod(self):
    418         self.assertRaises(TypeError, math.fmod)
    419         self.ftest('fmod(10,1)', math.fmod(10,1), 0)
    420         self.ftest('fmod(10,0.5)', math.fmod(10,0.5), 0)
    421         self.ftest('fmod(10,1.5)', math.fmod(10,1.5), 1)
    422         self.ftest('fmod(-10,1)', math.fmod(-10,1), 0)
    423         self.ftest('fmod(-10,0.5)', math.fmod(-10,0.5), 0)
    424         self.ftest('fmod(-10,1.5)', math.fmod(-10,1.5), -1)
    425         self.assertTrue(math.isnan(math.fmod(NAN, 1.)))
    426         self.assertTrue(math.isnan(math.fmod(1., NAN)))
    427         self.assertTrue(math.isnan(math.fmod(NAN, NAN)))
    428         self.assertRaises(ValueError, math.fmod, 1., 0.)
    429         self.assertRaises(ValueError, math.fmod, INF, 1.)
    430         self.assertRaises(ValueError, math.fmod, NINF, 1.)
    431         self.assertRaises(ValueError, math.fmod, INF, 0.)
    432         self.assertEqual(math.fmod(3.0, INF), 3.0)
    433         self.assertEqual(math.fmod(-3.0, INF), -3.0)
    434         self.assertEqual(math.fmod(3.0, NINF), 3.0)
    435         self.assertEqual(math.fmod(-3.0, NINF), -3.0)
    436         self.assertEqual(math.fmod(0.0, 3.0), 0.0)
    437         self.assertEqual(math.fmod(0.0, NINF), 0.0)
    438 
    439     def testFrexp(self):
    440         self.assertRaises(TypeError, math.frexp)
    441 
    442         def testfrexp(name, result, expected):
    443             (mant, exp), (emant, eexp) = result, expected
    444             if abs(mant-emant) > eps or exp != eexp:
    445                 self.fail('%s returned %r, expected %r'%\
    446                           (name, (mant, exp), (emant,eexp)))
    447 
    448         testfrexp('frexp(-1)', math.frexp(-1), (-0.5, 1))
    449         testfrexp('frexp(0)', math.frexp(0), (0, 0))
    450         testfrexp('frexp(1)', math.frexp(1), (0.5, 1))
    451         testfrexp('frexp(2)', math.frexp(2), (0.5, 2))
    452 
    453         self.assertEqual(math.frexp(INF)[0], INF)
    454         self.assertEqual(math.frexp(NINF)[0], NINF)
    455         self.assertTrue(math.isnan(math.frexp(NAN)[0]))
    456 
    457     @requires_IEEE_754
    458     @unittest.skipIf(HAVE_DOUBLE_ROUNDING,
    459                          "fsum is not exact on machines with double rounding")
    460     def testFsum(self):
    461         # math.fsum relies on exact rounding for correct operation.
    462         # There's a known problem with IA32 floating-point that causes
    463         # inexact rounding in some situations, and will cause the
    464         # math.fsum tests below to fail; see issue #2937.  On non IEEE
    465         # 754 platforms, and on IEEE 754 platforms that exhibit the
    466         # problem described in issue #2937, we simply skip the whole
    467         # test.
    468 
    469         # Python version of math.fsum, for comparison.  Uses a
    470         # different algorithm based on frexp, ldexp and integer
    471         # arithmetic.
    472         from sys import float_info
    473         mant_dig = float_info.mant_dig
    474         etiny = float_info.min_exp - mant_dig
    475 
    476         def msum(iterable):
    477             """Full precision summation.  Compute sum(iterable) without any
    478             intermediate accumulation of error.  Based on the 'lsum' function
    479             at http://code.activestate.com/recipes/393090/
    480 
    481             """
    482             tmant, texp = 0, 0
    483             for x in iterable:
    484                 mant, exp = math.frexp(x)
    485                 mant, exp = int(math.ldexp(mant, mant_dig)), exp - mant_dig
    486                 if texp > exp:
    487                     tmant <<= texp-exp
    488                     texp = exp
    489                 else:
    490                     mant <<= exp-texp
    491                 tmant += mant
    492             # Round tmant * 2**texp to a float.  The original recipe
    493             # used float(str(tmant)) * 2.0**texp for this, but that's
    494             # a little unsafe because str -> float conversion can't be
    495             # relied upon to do correct rounding on all platforms.
    496             tail = max(len(bin(abs(tmant)))-2 - mant_dig, etiny - texp)
    497             if tail > 0:
    498                 h = 1 << (tail-1)
    499                 tmant = tmant // (2*h) + bool(tmant & h and tmant & 3*h-1)
    500                 texp += tail
    501             return math.ldexp(tmant, texp)
    502 
    503         test_values = [
    504             ([], 0.0),
    505             ([0.0], 0.0),
    506             ([1e100, 1.0, -1e100, 1e-100, 1e50, -1.0, -1e50], 1e-100),
    507             ([2.0**53, -0.5, -2.0**-54], 2.0**53-1.0),
    508             ([2.0**53, 1.0, 2.0**-100], 2.0**53+2.0),
    509             ([2.0**53+10.0, 1.0, 2.0**-100], 2.0**53+12.0),
    510             ([2.0**53-4.0, 0.5, 2.0**-54], 2.0**53-3.0),
    511             ([1./n for n in range(1, 1001)],
    512              float.fromhex('0x1.df11f45f4e61ap+2')),
    513             ([(-1.)**n/n for n in range(1, 1001)],
    514              float.fromhex('-0x1.62a2af1bd3624p-1')),
    515             ([1.7**(i+1)-1.7**i for i in range(1000)] + [-1.7**1000], -1.0),
    516             ([1e16, 1., 1e-16], 10000000000000002.0),
    517             ([1e16-2., 1.-2.**-53, -(1e16-2.), -(1.-2.**-53)], 0.0),
    518             # exercise code for resizing partials array
    519             ([2.**n - 2.**(n+50) + 2.**(n+52) for n in range(-1074, 972, 2)] +
    520              [-2.**1022],
    521              float.fromhex('0x1.5555555555555p+970')),
    522             ]
    523 
    524         for i, (vals, expected) in enumerate(test_values):
    525             try:
    526                 actual = math.fsum(vals)
    527             except OverflowError:
    528                 self.fail("test %d failed: got OverflowError, expected %r "
    529                           "for math.fsum(%.100r)" % (i, expected, vals))
    530             except ValueError:
    531                 self.fail("test %d failed: got ValueError, expected %r "
    532                           "for math.fsum(%.100r)" % (i, expected, vals))
    533             self.assertEqual(actual, expected)
    534 
    535         from random import random, gauss, shuffle
    536         for j in xrange(1000):
    537             vals = [7, 1e100, -7, -1e100, -9e-20, 8e-20] * 10
    538             s = 0
    539             for i in xrange(200):
    540                 v = gauss(0, random()) ** 7 - s
    541                 s += v
    542                 vals.append(v)
    543             shuffle(vals)
    544 
    545             s = msum(vals)
    546             self.assertEqual(msum(vals), math.fsum(vals))
    547 
    548     def testHypot(self):
    549         self.assertRaises(TypeError, math.hypot)
    550         self.ftest('hypot(0,0)', math.hypot(0,0), 0)
    551         self.ftest('hypot(3,4)', math.hypot(3,4), 5)
    552         self.assertEqual(math.hypot(NAN, INF), INF)
    553         self.assertEqual(math.hypot(INF, NAN), INF)
    554         self.assertEqual(math.hypot(NAN, NINF), INF)
    555         self.assertEqual(math.hypot(NINF, NAN), INF)
    556         self.assertTrue(math.isnan(math.hypot(1.0, NAN)))
    557         self.assertTrue(math.isnan(math.hypot(NAN, -2.0)))
    558 
    559     def testLdexp(self):
    560         self.assertRaises(TypeError, math.ldexp)
    561         self.ftest('ldexp(0,1)', math.ldexp(0,1), 0)
    562         self.ftest('ldexp(1,1)', math.ldexp(1,1), 2)
    563         self.ftest('ldexp(1,-1)', math.ldexp(1,-1), 0.5)
    564         self.ftest('ldexp(-1,1)', math.ldexp(-1,1), -2)
    565         self.assertRaises(OverflowError, math.ldexp, 1., 1000000)
    566         self.assertRaises(OverflowError, math.ldexp, -1., 1000000)
    567         self.assertEqual(math.ldexp(1., -1000000), 0.)
    568         self.assertEqual(math.ldexp(-1., -1000000), -0.)
    569         self.assertEqual(math.ldexp(INF, 30), INF)
    570         self.assertEqual(math.ldexp(NINF, -213), NINF)
    571         self.assertTrue(math.isnan(math.ldexp(NAN, 0)))
    572 
    573         # large second argument
    574         for n in [10**5, 10L**5, 10**10, 10L**10, 10**20, 10**40]:
    575             self.assertEqual(math.ldexp(INF, -n), INF)
    576             self.assertEqual(math.ldexp(NINF, -n), NINF)
    577             self.assertEqual(math.ldexp(1., -n), 0.)
    578             self.assertEqual(math.ldexp(-1., -n), -0.)
    579             self.assertEqual(math.ldexp(0., -n), 0.)
    580             self.assertEqual(math.ldexp(-0., -n), -0.)
    581             self.assertTrue(math.isnan(math.ldexp(NAN, -n)))
    582 
    583             self.assertRaises(OverflowError, math.ldexp, 1., n)
    584             self.assertRaises(OverflowError, math.ldexp, -1., n)
    585             self.assertEqual(math.ldexp(0., n), 0.)
    586             self.assertEqual(math.ldexp(-0., n), -0.)
    587             self.assertEqual(math.ldexp(INF, n), INF)
    588             self.assertEqual(math.ldexp(NINF, n), NINF)
    589             self.assertTrue(math.isnan(math.ldexp(NAN, n)))
    590 
    591     def testLog(self):
    592         self.assertRaises(TypeError, math.log)
    593         self.ftest('log(1/e)', math.log(1/math.e), -1)
    594         self.ftest('log(1)', math.log(1), 0)
    595         self.ftest('log(e)', math.log(math.e), 1)
    596         self.ftest('log(32,2)', math.log(32,2), 5)
    597         self.ftest('log(10**40, 10)', math.log(10**40, 10), 40)
    598         self.ftest('log(10**40, 10**20)', math.log(10**40, 10**20), 2)
    599         self.assertEqual(math.log(INF), INF)
    600         self.assertRaises(ValueError, math.log, NINF)
    601         self.assertTrue(math.isnan(math.log(NAN)))
    602 
    603     def testLog1p(self):
    604         self.assertRaises(TypeError, math.log1p)
    605         self.ftest('log1p(1/e -1)', math.log1p(1/math.e-1), -1)
    606         self.ftest('log1p(0)', math.log1p(0), 0)
    607         self.ftest('log1p(e-1)', math.log1p(math.e-1), 1)
    608         self.ftest('log1p(1)', math.log1p(1), math.log(2))
    609         self.assertEqual(math.log1p(INF), INF)
    610         self.assertRaises(ValueError, math.log1p, NINF)
    611         self.assertTrue(math.isnan(math.log1p(NAN)))
    612         n= 2**90
    613         self.assertAlmostEqual(math.log1p(n), 62.383246250395075)
    614         self.assertAlmostEqual(math.log1p(n), math.log1p(float(n)))
    615 
    616     def testLog10(self):
    617         self.assertRaises(TypeError, math.log10)
    618         self.ftest('log10(0.1)', math.log10(0.1), -1)
    619         self.ftest('log10(1)', math.log10(1), 0)
    620         self.ftest('log10(10)', math.log10(10), 1)
    621         self.assertEqual(math.log(INF), INF)
    622         self.assertRaises(ValueError, math.log10, NINF)
    623         self.assertTrue(math.isnan(math.log10(NAN)))
    624 
    625     def testModf(self):
    626         self.assertRaises(TypeError, math.modf)
    627 
    628         def testmodf(name, result, expected):
    629             (v1, v2), (e1, e2) = result, expected
    630             if abs(v1-e1) > eps or abs(v2-e2):
    631                 self.fail('%s returned %r, expected %r'%\
    632                           (name, (v1,v2), (e1,e2)))
    633 
    634         testmodf('modf(1.5)', math.modf(1.5), (0.5, 1.0))
    635         testmodf('modf(-1.5)', math.modf(-1.5), (-0.5, -1.0))
    636 
    637         self.assertEqual(math.modf(INF), (0.0, INF))
    638         self.assertEqual(math.modf(NINF), (-0.0, NINF))
    639 
    640         modf_nan = math.modf(NAN)
    641         self.assertTrue(math.isnan(modf_nan[0]))
    642         self.assertTrue(math.isnan(modf_nan[1]))
    643 
    644     def testPow(self):
    645         self.assertRaises(TypeError, math.pow)
    646         self.ftest('pow(0,1)', math.pow(0,1), 0)
    647         self.ftest('pow(1,0)', math.pow(1,0), 1)
    648         self.ftest('pow(2,1)', math.pow(2,1), 2)
    649         self.ftest('pow(2,-1)', math.pow(2,-1), 0.5)
    650         self.assertEqual(math.pow(INF, 1), INF)
    651         self.assertEqual(math.pow(NINF, 1), NINF)
    652         self.assertEqual((math.pow(1, INF)), 1.)
    653         self.assertEqual((math.pow(1, NINF)), 1.)
    654         self.assertTrue(math.isnan(math.pow(NAN, 1)))
    655         self.assertTrue(math.isnan(math.pow(2, NAN)))
    656         self.assertTrue(math.isnan(math.pow(0, NAN)))
    657         self.assertEqual(math.pow(1, NAN), 1)
    658 
    659         # pow(0., x)
    660         self.assertEqual(math.pow(0., INF), 0.)
    661         self.assertEqual(math.pow(0., 3.), 0.)
    662         self.assertEqual(math.pow(0., 2.3), 0.)
    663         self.assertEqual(math.pow(0., 2.), 0.)
    664         self.assertEqual(math.pow(0., 0.), 1.)
    665         self.assertEqual(math.pow(0., -0.), 1.)
    666         self.assertRaises(ValueError, math.pow, 0., -2.)
    667         self.assertRaises(ValueError, math.pow, 0., -2.3)
    668         self.assertRaises(ValueError, math.pow, 0., -3.)
    669         self.assertRaises(ValueError, math.pow, 0., NINF)
    670         self.assertTrue(math.isnan(math.pow(0., NAN)))
    671 
    672         # pow(INF, x)
    673         self.assertEqual(math.pow(INF, INF), INF)
    674         self.assertEqual(math.pow(INF, 3.), INF)
    675         self.assertEqual(math.pow(INF, 2.3), INF)
    676         self.assertEqual(math.pow(INF, 2.), INF)
    677         self.assertEqual(math.pow(INF, 0.), 1.)
    678         self.assertEqual(math.pow(INF, -0.), 1.)
    679         self.assertEqual(math.pow(INF, -2.), 0.)
    680         self.assertEqual(math.pow(INF, -2.3), 0.)
    681         self.assertEqual(math.pow(INF, -3.), 0.)
    682         self.assertEqual(math.pow(INF, NINF), 0.)
    683         self.assertTrue(math.isnan(math.pow(INF, NAN)))
    684 
    685         # pow(-0., x)
    686         self.assertEqual(math.pow(-0., INF), 0.)
    687         self.assertEqual(math.pow(-0., 3.), -0.)
    688         self.assertEqual(math.pow(-0., 2.3), 0.)
    689         self.assertEqual(math.pow(-0., 2.), 0.)
    690         self.assertEqual(math.pow(-0., 0.), 1.)
    691         self.assertEqual(math.pow(-0., -0.), 1.)
    692         self.assertRaises(ValueError, math.pow, -0., -2.)
    693         self.assertRaises(ValueError, math.pow, -0., -2.3)
    694         self.assertRaises(ValueError, math.pow, -0., -3.)
    695         self.assertRaises(ValueError, math.pow, -0., NINF)
    696         self.assertTrue(math.isnan(math.pow(-0., NAN)))
    697 
    698         # pow(NINF, x)
    699         self.assertEqual(math.pow(NINF, INF), INF)
    700         self.assertEqual(math.pow(NINF, 3.), NINF)
    701         self.assertEqual(math.pow(NINF, 2.3), INF)
    702         self.assertEqual(math.pow(NINF, 2.), INF)
    703         self.assertEqual(math.pow(NINF, 0.), 1.)
    704         self.assertEqual(math.pow(NINF, -0.), 1.)
    705         self.assertEqual(math.pow(NINF, -2.), 0.)
    706         self.assertEqual(math.pow(NINF, -2.3), 0.)
    707         self.assertEqual(math.pow(NINF, -3.), -0.)
    708         self.assertEqual(math.pow(NINF, NINF), 0.)
    709         self.assertTrue(math.isnan(math.pow(NINF, NAN)))
    710 
    711         # pow(-1, x)
    712         self.assertEqual(math.pow(-1., INF), 1.)
    713         self.assertEqual(math.pow(-1., 3.), -1.)
    714         self.assertRaises(ValueError, math.pow, -1., 2.3)
    715         self.assertEqual(math.pow(-1., 2.), 1.)
    716         self.assertEqual(math.pow(-1., 0.), 1.)
    717         self.assertEqual(math.pow(-1., -0.), 1.)
    718         self.assertEqual(math.pow(-1., -2.), 1.)
    719         self.assertRaises(ValueError, math.pow, -1., -2.3)
    720         self.assertEqual(math.pow(-1., -3.), -1.)
    721         self.assertEqual(math.pow(-1., NINF), 1.)
    722         self.assertTrue(math.isnan(math.pow(-1., NAN)))
    723 
    724         # pow(1, x)
    725         self.assertEqual(math.pow(1., INF), 1.)
    726         self.assertEqual(math.pow(1., 3.), 1.)
    727         self.assertEqual(math.pow(1., 2.3), 1.)
    728         self.assertEqual(math.pow(1., 2.), 1.)
    729         self.assertEqual(math.pow(1., 0.), 1.)
    730         self.assertEqual(math.pow(1., -0.), 1.)
    731         self.assertEqual(math.pow(1., -2.), 1.)
    732         self.assertEqual(math.pow(1., -2.3), 1.)
    733         self.assertEqual(math.pow(1., -3.), 1.)
    734         self.assertEqual(math.pow(1., NINF), 1.)
    735         self.assertEqual(math.pow(1., NAN), 1.)
    736 
    737         # pow(x, 0) should be 1 for any x
    738         self.assertEqual(math.pow(2.3, 0.), 1.)
    739         self.assertEqual(math.pow(-2.3, 0.), 1.)
    740         self.assertEqual(math.pow(NAN, 0.), 1.)
    741         self.assertEqual(math.pow(2.3, -0.), 1.)
    742         self.assertEqual(math.pow(-2.3, -0.), 1.)
    743         self.assertEqual(math.pow(NAN, -0.), 1.)
    744 
    745         # pow(x, y) is invalid if x is negative and y is not integral
    746         self.assertRaises(ValueError, math.pow, -1., 2.3)
    747         self.assertRaises(ValueError, math.pow, -15., -3.1)
    748 
    749         # pow(x, NINF)
    750         self.assertEqual(math.pow(1.9, NINF), 0.)
    751         self.assertEqual(math.pow(1.1, NINF), 0.)
    752         self.assertEqual(math.pow(0.9, NINF), INF)
    753         self.assertEqual(math.pow(0.1, NINF), INF)
    754         self.assertEqual(math.pow(-0.1, NINF), INF)
    755         self.assertEqual(math.pow(-0.9, NINF), INF)
    756         self.assertEqual(math.pow(-1.1, NINF), 0.)
    757         self.assertEqual(math.pow(-1.9, NINF), 0.)
    758 
    759         # pow(x, INF)
    760         self.assertEqual(math.pow(1.9, INF), INF)
    761         self.assertEqual(math.pow(1.1, INF), INF)
    762         self.assertEqual(math.pow(0.9, INF), 0.)
    763         self.assertEqual(math.pow(0.1, INF), 0.)
    764         self.assertEqual(math.pow(-0.1, INF), 0.)
    765         self.assertEqual(math.pow(-0.9, INF), 0.)
    766         self.assertEqual(math.pow(-1.1, INF), INF)
    767         self.assertEqual(math.pow(-1.9, INF), INF)
    768 
    769         # pow(x, y) should work for x negative, y an integer
    770         self.ftest('(-2.)**3.', math.pow(-2.0, 3.0), -8.0)
    771         self.ftest('(-2.)**2.', math.pow(-2.0, 2.0), 4.0)
    772         self.ftest('(-2.)**1.', math.pow(-2.0, 1.0), -2.0)
    773         self.ftest('(-2.)**0.', math.pow(-2.0, 0.0), 1.0)
    774         self.ftest('(-2.)**-0.', math.pow(-2.0, -0.0), 1.0)
    775         self.ftest('(-2.)**-1.', math.pow(-2.0, -1.0), -0.5)
    776         self.ftest('(-2.)**-2.', math.pow(-2.0, -2.0), 0.25)
    777         self.ftest('(-2.)**-3.', math.pow(-2.0, -3.0), -0.125)
    778         self.assertRaises(ValueError, math.pow, -2.0, -0.5)
    779         self.assertRaises(ValueError, math.pow, -2.0, 0.5)
    780 
    781         # the following tests have been commented out since they don't
    782         # really belong here:  the implementation of ** for floats is
    783         # independent of the implementation of math.pow
    784         #self.assertEqual(1**NAN, 1)
    785         #self.assertEqual(1**INF, 1)
    786         #self.assertEqual(1**NINF, 1)
    787         #self.assertEqual(1**0, 1)
    788         #self.assertEqual(1.**NAN, 1)
    789         #self.assertEqual(1.**INF, 1)
    790         #self.assertEqual(1.**NINF, 1)
    791         #self.assertEqual(1.**0, 1)
    792 
    793     def testRadians(self):
    794         self.assertRaises(TypeError, math.radians)
    795         self.ftest('radians(180)', math.radians(180), math.pi)
    796         self.ftest('radians(90)', math.radians(90), math.pi/2)
    797         self.ftest('radians(-45)', math.radians(-45), -math.pi/4)
    798 
    799     def testSin(self):
    800         self.assertRaises(TypeError, math.sin)
    801         self.ftest('sin(0)', math.sin(0), 0)
    802         self.ftest('sin(pi/2)', math.sin(math.pi/2), 1)
    803         self.ftest('sin(-pi/2)', math.sin(-math.pi/2), -1)
    804         try:
    805             self.assertTrue(math.isnan(math.sin(INF)))
    806             self.assertTrue(math.isnan(math.sin(NINF)))
    807         except ValueError:
    808             self.assertRaises(ValueError, math.sin, INF)
    809             self.assertRaises(ValueError, math.sin, NINF)
    810         self.assertTrue(math.isnan(math.sin(NAN)))
    811 
    812     def testSinh(self):
    813         self.assertRaises(TypeError, math.sinh)
    814         self.ftest('sinh(0)', math.sinh(0), 0)
    815         self.ftest('sinh(1)**2-cosh(1)**2', math.sinh(1)**2-math.cosh(1)**2, -1)
    816         self.ftest('sinh(1)+sinh(-1)', math.sinh(1)+math.sinh(-1), 0)
    817         self.assertEqual(math.sinh(INF), INF)
    818         self.assertEqual(math.sinh(NINF), NINF)
    819         self.assertTrue(math.isnan(math.sinh(NAN)))
    820 
    821     def testSqrt(self):
    822         self.assertRaises(TypeError, math.sqrt)
    823         self.ftest('sqrt(0)', math.sqrt(0), 0)
    824         self.ftest('sqrt(1)', math.sqrt(1), 1)
    825         self.ftest('sqrt(4)', math.sqrt(4), 2)
    826         self.assertEqual(math.sqrt(INF), INF)
    827         self.assertRaises(ValueError, math.sqrt, NINF)
    828         self.assertTrue(math.isnan(math.sqrt(NAN)))
    829 
    830     def testTan(self):
    831         self.assertRaises(TypeError, math.tan)
    832         self.ftest('tan(0)', math.tan(0), 0)
    833         self.ftest('tan(pi/4)', math.tan(math.pi/4), 1)
    834         self.ftest('tan(-pi/4)', math.tan(-math.pi/4), -1)
    835         try:
    836             self.assertTrue(math.isnan(math.tan(INF)))
    837             self.assertTrue(math.isnan(math.tan(NINF)))
    838         except:
    839             self.assertRaises(ValueError, math.tan, INF)
    840             self.assertRaises(ValueError, math.tan, NINF)
    841         self.assertTrue(math.isnan(math.tan(NAN)))
    842 
    843     def testTanh(self):
    844         self.assertRaises(TypeError, math.tanh)
    845         self.ftest('tanh(0)', math.tanh(0), 0)
    846         self.ftest('tanh(1)+tanh(-1)', math.tanh(1)+math.tanh(-1), 0)
    847         self.ftest('tanh(inf)', math.tanh(INF), 1)
    848         self.ftest('tanh(-inf)', math.tanh(NINF), -1)
    849         self.assertTrue(math.isnan(math.tanh(NAN)))
    850         # check that tanh(-0.) == -0. on IEEE 754 systems
    851         if float.__getformat__("double").startswith("IEEE"):
    852             self.assertEqual(math.tanh(-0.), -0.)
    853             self.assertEqual(math.copysign(1., math.tanh(-0.)),
    854                              math.copysign(1., -0.))
    855 
    856     def test_trunc(self):
    857         self.assertEqual(math.trunc(1), 1)
    858         self.assertEqual(math.trunc(-1), -1)
    859         self.assertEqual(type(math.trunc(1)), int)
    860         self.assertEqual(type(math.trunc(1.5)), int)
    861         self.assertEqual(math.trunc(1.5), 1)
    862         self.assertEqual(math.trunc(-1.5), -1)
    863         self.assertEqual(math.trunc(1.999999), 1)
    864         self.assertEqual(math.trunc(-1.999999), -1)
    865         self.assertEqual(math.trunc(-0.999999), -0)
    866         self.assertEqual(math.trunc(-100.999), -100)
    867 
    868         class TestTrunc(object):
    869             def __trunc__(self):
    870                 return 23
    871 
    872         class TestNoTrunc(object):
    873             pass
    874 
    875         self.assertEqual(math.trunc(TestTrunc()), 23)
    876 
    877         self.assertRaises(TypeError, math.trunc)
    878         self.assertRaises(TypeError, math.trunc, 1, 2)
    879         self.assertRaises((AttributeError, TypeError), math.trunc,
    880                           TestNoTrunc())
    881 
    882     def testIsnan(self):
    883         self.assertTrue(math.isnan(float("nan")))
    884         self.assertTrue(math.isnan(float("inf")* 0.))
    885         self.assertFalse(math.isnan(float("inf")))
    886         self.assertFalse(math.isnan(0.))
    887         self.assertFalse(math.isnan(1.))
    888 
    889     def testIsinf(self):
    890         self.assertTrue(math.isinf(float("inf")))
    891         self.assertTrue(math.isinf(float("-inf")))
    892         self.assertTrue(math.isinf(1E400))
    893         self.assertTrue(math.isinf(-1E400))
    894         self.assertFalse(math.isinf(float("nan")))
    895         self.assertFalse(math.isinf(0.))
    896         self.assertFalse(math.isinf(1.))
    897 
    898     # RED_FLAG 16-Oct-2000 Tim
    899     # While 2.0 is more consistent about exceptions than previous releases, it
    900     # still fails this part of the test on some platforms.  For now, we only
    901     # *run* test_exceptions() in verbose mode, so that this isn't normally
    902     # tested.
    903 
    904     if verbose:
    905         def test_exceptions(self):
    906             try:
    907                 x = math.exp(-1000000000)
    908             except:
    909                 # mathmodule.c is failing to weed out underflows from libm, or
    910                 # we've got an fp format with huge dynamic range
    911                 self.fail("underflowing exp() should not have raised "
    912                           "an exception")
    913             if x != 0:
    914                 self.fail("underflowing exp() should have returned 0")
    915 
    916             # If this fails, probably using a strict IEEE-754 conforming libm, and x
    917             # is +Inf afterwards.  But Python wants overflows detected by default.
    918             try:
    919                 x = math.exp(1000000000)
    920             except OverflowError:
    921                 pass
    922             else:
    923                 self.fail("overflowing exp() didn't trigger OverflowError")
    924 
    925             # If this fails, it could be a puzzle.  One odd possibility is that
    926             # mathmodule.c's macros are getting confused while comparing
    927             # Inf (HUGE_VAL) to a NaN, and artificially setting errno to ERANGE
    928             # as a result (and so raising OverflowError instead).
    929             try:
    930                 x = math.sqrt(-1.0)
    931             except ValueError:
    932                 pass
    933             else:
    934                 self.fail("sqrt(-1) didn't raise ValueError")
    935 
    936     @requires_IEEE_754
    937     def test_testfile(self):
    938         for id, fn, ar, ai, er, ei, flags in parse_testfile(test_file):
    939             # Skip if either the input or result is complex, or if
    940             # flags is nonempty
    941             if ai != 0. or ei != 0. or flags:
    942                 continue
    943             if fn in ['rect', 'polar']:
    944                 # no real versions of rect, polar
    945                 continue
    946             func = getattr(math, fn)
    947             try:
    948                 result = func(ar)
    949             except ValueError:
    950                 message = ("Unexpected ValueError in " +
    951                            "test %s:%s(%r)\n" % (id, fn, ar))
    952                 self.fail(message)
    953             except OverflowError:
    954                 message = ("Unexpected OverflowError in " +
    955                            "test %s:%s(%r)\n" % (id, fn, ar))
    956                 self.fail(message)
    957             self.ftest("%s:%s(%r)" % (id, fn, ar), result, er)
    958 
    959     @unittest.skipUnless(float.__getformat__("double").startswith("IEEE"),
    960                          "test requires IEEE 754 doubles")
    961     def test_mtestfile(self):
    962         ALLOWED_ERROR = 20  # permitted error, in ulps
    963         fail_fmt = "{}:{}({!r}): expected {!r}, got {!r}"
    964 
    965         failures = []
    966         for id, fn, arg, expected, flags in parse_mtestfile(math_testcases):
    967             func = getattr(math, fn)
    968 
    969             if 'invalid' in flags or 'divide-by-zero' in flags:
    970                 expected = 'ValueError'
    971             elif 'overflow' in flags:
    972                 expected = 'OverflowError'
    973 
    974             try:
    975                 got = func(arg)
    976             except ValueError:
    977                 got = 'ValueError'
    978             except OverflowError:
    979                 got = 'OverflowError'
    980 
    981             accuracy_failure = None
    982             if isinstance(got, float) and isinstance(expected, float):
    983                 if math.isnan(expected) and math.isnan(got):
    984                     continue
    985                 if not math.isnan(expected) and not math.isnan(got):
    986                     if fn == 'lgamma':
    987                         # we use a weaker accuracy test for lgamma;
    988                         # lgamma only achieves an absolute error of
    989                         # a few multiples of the machine accuracy, in
    990                         # general.
    991                         accuracy_failure = acc_check(expected, got,
    992                                                   rel_err = 5e-15,
    993                                                   abs_err = 5e-15)
    994                     elif fn == 'erfc':
    995                         # erfc has less-than-ideal accuracy for large
    996                         # arguments (x ~ 25 or so), mainly due to the
    997                         # error involved in computing exp(-x*x).
    998                         #
    999                         # XXX Would be better to weaken this test only
   1000                         # for large x, instead of for all x.
   1001                         accuracy_failure = ulps_check(expected, got, 2000)
   1002 
   1003                     else:
   1004                         accuracy_failure = ulps_check(expected, got, 20)
   1005                     if accuracy_failure is None:
   1006                         continue
   1007 
   1008             if isinstance(got, str) and isinstance(expected, str):
   1009                 if got == expected:
   1010                     continue
   1011 
   1012             fail_msg = fail_fmt.format(id, fn, arg, expected, got)
   1013             if accuracy_failure is not None:
   1014                 fail_msg += ' ({})'.format(accuracy_failure)
   1015             failures.append(fail_msg)
   1016 
   1017         if failures:
   1018             self.fail('Failures in test_mtestfile:\n  ' +
   1019                       '\n  '.join(failures))
   1020 
   1021 
   1022 def test_main():
   1023     from doctest import DocFileSuite
   1024     suite = unittest.TestSuite()
   1025     suite.addTest(unittest.makeSuite(MathTests))
   1026     suite.addTest(DocFileSuite("ieee754.txt"))
   1027     run_unittest(suite)
   1028 
   1029 if __name__ == '__main__':
   1030     test_main()
   1031