diff options
author | Mark Dickinson <dickinsm@gmail.com> | 2009-09-28 19:21:11 (GMT) |
---|---|---|
committer | Mark Dickinson <dickinsm@gmail.com> | 2009-09-28 19:21:11 (GMT) |
commit | 12c4bdb0e8d96640423bd6878dac2aecacb2d741 (patch) | |
tree | 87890d9a18bc8ddf348f4b7764d0418b003b4b1b /Lib/test/test_math.py | |
parent | 40af630672b8d7d71f7ebf70ae9d4a133210cfb1 (diff) | |
download | cpython-12c4bdb0e8d96640423bd6878dac2aecacb2d741.zip cpython-12c4bdb0e8d96640423bd6878dac2aecacb2d741.tar.gz cpython-12c4bdb0e8d96640423bd6878dac2aecacb2d741.tar.bz2 |
Merged revisions 75117 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk
........
r75117 | mark.dickinson | 2009-09-28 19:54:55 +0100 (Mon, 28 Sep 2009) | 3 lines
Issue #3366: Add gamma function to math module.
(lgamma, erf and erfc to follow).
........
Diffstat (limited to 'Lib/test/test_math.py')
-rw-r--r-- | Lib/test/test_math.py | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/Lib/test/test_math.py b/Lib/test/test_math.py index 6f15782..f29bddd 100644 --- a/Lib/test/test_math.py +++ b/Lib/test/test_math.py @@ -7,6 +7,7 @@ import math import os import sys import random +import struct eps = 1E-05 NAN = float('nan') @@ -29,8 +30,50 @@ if __name__ == '__main__': else: file = __file__ test_dir = os.path.dirname(file) or os.curdir +math_testcases = os.path.join(test_dir, 'math_testcases.txt') test_file = os.path.join(test_dir, 'cmath_testcases.txt') +def to_ulps(x): + """Convert a non-NaN float x to an integer, in such a way that + adjacent floats are converted to adjacent integers. Then + abs(ulps(x) - ulps(y)) gives the difference in ulps between two + floats. + + The results from this function will only make sense on platforms + where C doubles are represented in IEEE 754 binary64 format. + + """ + n = struct.unpack('q', struct.pack('<d', x))[0] + if n < 0: + n = ~(n+2**63) + return n + + +def parse_mtestfile(fname): + """Parse a file with test values + + -- starts a comment + blank lines, or lines containing only a comment, are ignored + other lines are expected to have the form + id fn arg -> expected [flag]* + + """ + with open(fname) as fp: + for line in fp: + # strip comments, and skip blank lines + if '--' in line: + line = line[:line.index('--')] + if not line.strip(): + continue + + lhs, rhs = line.split('->') + id, fn, arg = lhs.split() + rhs_pieces = rhs.split() + exp = rhs_pieces[0] + flags = rhs_pieces[1:] + + yield (id, fn, float(arg), float(exp), flags) + def parse_testfile(fname): """Parse a file with test values @@ -884,6 +927,51 @@ class MathTests(unittest.TestCase): self.fail(message) self.ftest("%s:%s(%r)" % (id, fn, ar), result, er) + @unittest.skipUnless(float.__getformat__("double").startswith("IEEE"), + "test requires IEEE 754 doubles") + def test_mtestfile(self): + ALLOWED_ERROR = 20 # permitted error, in ulps + fail_fmt = "{}:{}({!r}): expected {!r}, got {!r}" + + failures = [] + for id, fn, arg, expected, flags in parse_mtestfile(math_testcases): + func = getattr(math, fn) + + if 'invalid' in flags or 'divide-by-zero' in flags: + expected = 'ValueError' + elif 'overflow' in flags: + expected = 'OverflowError' + + try: + got = func(arg) + except ValueError: + got = 'ValueError' + except OverflowError: + got = 'OverflowError' + + diff_ulps = None + if isinstance(got, float) and isinstance(expected, float): + if math.isnan(expected) and math.isnan(got): + continue + if not math.isnan(expected) and not math.isnan(got): + diff_ulps = to_ulps(expected) - to_ulps(got) + if diff_ulps <= ALLOWED_ERROR: + continue + + if isinstance(got, str) and isinstance(expected, str): + if got == expected: + continue + + fail_msg = fail_fmt.format(id, fn, arg, expected, got) + if diff_ulps is not None: + fail_msg += ' ({} ulps)'.format(diff_ulps) + failures.append(fail_msg) + + if failures: + self.fail('Failures in test_mtestfile:\n ' + + '\n '.join(failures)) + + def test_main(): from doctest import DocFileSuite suite = unittest.TestSuite() |