summaryrefslogtreecommitdiffstats
path: root/Lib/test/test_math.py
diff options
context:
space:
mode:
authorMark Dickinson <dickinsm@gmail.com>2009-12-11 20:17:17 (GMT)
committerMark Dickinson <dickinsm@gmail.com>2009-12-11 20:17:17 (GMT)
commit05d2e084019d9ec67277df36acf372b81e18365f (patch)
tree7957bc8aabc2c09c7d9d39df92700f62ed474cf3 /Lib/test/test_math.py
parente62df2ffaa76a29ededa51380597bec54a1a1cc6 (diff)
downloadcpython-05d2e084019d9ec67277df36acf372b81e18365f.zip
cpython-05d2e084019d9ec67277df36acf372b81e18365f.tar.gz
cpython-05d2e084019d9ec67277df36acf372b81e18365f.tar.bz2
Merged revisions 76755 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk ........ r76755 | mark.dickinson | 2009-12-11 17:29:33 +0000 (Fri, 11 Dec 2009) | 2 lines Issue #3366: Add lgamma function to math module. ........
Diffstat (limited to 'Lib/test/test_math.py')
-rw-r--r--Lib/test/test_math.py50
1 files changed, 45 insertions, 5 deletions
diff --git a/Lib/test/test_math.py b/Lib/test/test_math.py
index 2226023..2052430 100644
--- a/Lib/test/test_math.py
+++ b/Lib/test/test_math.py
@@ -48,6 +48,36 @@ def to_ulps(x):
n = ~(n+2**63)
return n
+def ulps_check(expected, got, ulps=20):
+ """Given non-NaN floats `expected` and `got`,
+ check that they're equal to within the given number of ulps.
+
+ Returns None on success and an error message on failure."""
+
+ ulps_error = to_ulps(got) - to_ulps(expected)
+ if abs(ulps_error) <= ulps:
+ return None
+ return "error = {} ulps; permitted error = {} ulps".format(ulps_error,
+ ulps)
+
+def acc_check(expected, got, rel_err=2e-15, abs_err = 5e-323):
+ """Determine whether non-NaN floats a and b are equal to within a
+ (small) rounding error. The default values for rel_err and
+ abs_err are chosen to be suitable for platforms where a float is
+ represented by an IEEE 754 double. They allow an error of between
+ 9 and 19 ulps."""
+
+ # need to special case infinities, since inf - inf gives nan
+ if math.isinf(expected) and got == expected:
+ return None
+
+ error = got - expected
+
+ permitted_error = max(abs_err, rel_err * abs(expected))
+ if abs(error) < permitted_error:
+ return None
+ return "error = {}; permitted error = {}".format(error,
+ permitted_error)
def parse_mtestfile(fname):
"""Parse a file with test values
@@ -949,13 +979,23 @@ class MathTests(unittest.TestCase):
except OverflowError:
got = 'OverflowError'
- diff_ulps = None
+ accuracy_failure = 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 abs(diff_ulps) <= ALLOWED_ERROR:
+ # we use different closeness criteria for
+ # different functions.
+ if fn == 'gamma':
+ accuracy_failure = ulps_check(expected, got, 20)
+ elif fn == 'lgamma':
+ accuracy_failure = acc_check(expected, got,
+ rel_err = 5e-15,
+ abs_err = 5e-15)
+ else:
+ raise ValueError("don't know how to check accuracy "
+ "for this function")
+ if accuracy_failure is None:
continue
if isinstance(got, str) and isinstance(expected, str):
@@ -963,8 +1003,8 @@ class MathTests(unittest.TestCase):
continue
fail_msg = fail_fmt.format(id, fn, arg, expected, got)
- if diff_ulps is not None:
- fail_msg += ' ({} ulps)'.format(diff_ulps)
+ if accuracy_failure is not None:
+ fail_msg += ' ({})'.format(accuracy_failure)
failures.append(fail_msg)
if failures: