summaryrefslogtreecommitdiffstats
path: root/Lib/test/test_math.py
diff options
context:
space:
mode:
authorMark Dickinson <dickinsm@gmail.com>2009-09-28 19:21:11 (GMT)
committerMark Dickinson <dickinsm@gmail.com>2009-09-28 19:21:11 (GMT)
commit12c4bdb0e8d96640423bd6878dac2aecacb2d741 (patch)
tree87890d9a18bc8ddf348f4b7764d0418b003b4b1b /Lib/test/test_math.py
parent40af630672b8d7d71f7ebf70ae9d4a133210cfb1 (diff)
downloadcpython-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.py88
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()