Back to index

python3.2  3.2.2
Classes | Functions | Variables
test.test_math Namespace Reference

Classes

class  MathTests

Functions

def to_ulps
def ulps_check
def count_set_bits
def partial_product
def py_factorial
def acc_check
def parse_mtestfile
def parse_testfile
def test_main

Variables

int eps = 1
tuple NAN = float('nan')
tuple INF = float('inf')
tuple NINF = float('-inf')
tuple HAVE_DOUBLE_ROUNDING = (x + y == 1e16 + 4)
list file = sys.argv[0]
tuple test_dir = os.path.dirname(file)
tuple math_testcases = os.path.join(test_dir, 'math_testcases.txt')
tuple test_file = os.path.join(test_dir, 'cmath_testcases.txt')

Function Documentation

def test.test_math.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.

Definition at line 109 of file test_math.py.

00109 
00110 def acc_check(expected, got, rel_err=2e-15, abs_err = 5e-323):
00111     """Determine whether non-NaN floats a and b are equal to within a
00112     (small) rounding error.  The default values for rel_err and
00113     abs_err are chosen to be suitable for platforms where a float is
00114     represented by an IEEE 754 double.  They allow an error of between
00115     9 and 19 ulps."""
00116 
00117     # need to special case infinities, since inf - inf gives nan
00118     if math.isinf(expected) and got == expected:
00119         return None
00120 
00121     error = got - expected
00122 
00123     permitted_error = max(abs_err, rel_err * abs(expected))
00124     if abs(error) < permitted_error:
00125         return None
00126     return "error = {}; permitted error = {}".format(error,
00127                                                      permitted_error)

Here is the caller graph for this function:

Number of '1' bits in binary expansion of a nonnnegative integer.

Definition at line 80 of file test_math.py.

00080 
00081 def count_set_bits(n):
00082     """Number of '1' bits in binary expansion of a nonnnegative integer."""
00083     return 1 + count_set_bits(n & n - 1) if n else 0

Here is the caller graph for this function:

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]*

Definition at line 128 of file test_math.py.

00128 
00129 def parse_mtestfile(fname):
00130     """Parse a file with test values
00131 
00132     -- starts a comment
00133     blank lines, or lines containing only a comment, are ignored
00134     other lines are expected to have the form
00135       id fn arg -> expected [flag]*
00136 
00137     """
00138     with open(fname) as fp:
00139         for line in fp:
00140             # strip comments, and skip blank lines
00141             if '--' in line:
00142                 line = line[:line.index('--')]
00143             if not line.strip():
00144                 continue
00145 
00146             lhs, rhs = line.split('->')
00147             id, fn, arg = lhs.split()
00148             rhs_pieces = rhs.split()
00149             exp = rhs_pieces[0]
00150             flags = rhs_pieces[1:]
00151 
00152             yield (id, fn, float(arg), float(exp), flags)

Here is the caller graph for this function:

Parse a file with test values

Empty lines or lines starting with -- are ignored
yields id, fn, arg_real, arg_imag, exp_real, exp_imag

Definition at line 153 of file test_math.py.

00153 
00154 def parse_testfile(fname):
00155     """Parse a file with test values
00156 
00157     Empty lines or lines starting with -- are ignored
00158     yields id, fn, arg_real, arg_imag, exp_real, exp_imag
00159     """
00160     with open(fname) as fp:
00161         for line in fp:
00162             # skip comment lines and blank lines
00163             if line.startswith('--') or not line.strip():
00164                 continue
00165 
00166             lhs, rhs = line.split('->')
00167             id, fn, arg_real, arg_imag = lhs.split()
00168             rhs_pieces = rhs.split()
00169             exp_real, exp_imag = rhs_pieces[0], rhs_pieces[1]
00170             flags = rhs_pieces[2:]
00171 
00172             yield (id, fn,
00173                    float(arg_real), float(arg_imag),
00174                    float(exp_real), float(exp_imag),
00175                    flags
00176                   )

Here is the caller graph for this function:

def test.test_math.partial_product (   start,
  stop 
)
Product of integers in range(start, stop, 2), computed recursively.
start and stop should both be odd, with start <= stop.

Definition at line 84 of file test_math.py.

00084 
00085 def partial_product(start, stop):
00086     """Product of integers in range(start, stop, 2), computed recursively.
00087     start and stop should both be odd, with start <= stop.
00088 
00089     """
00090     numfactors = (stop - start) >> 1
00091     if not numfactors:
00092         return 1
00093     elif numfactors == 1:
00094         return start
00095     else:
00096         mid = (start + numfactors) | 1
00097         return partial_product(start, mid) * partial_product(mid, stop)

Here is the caller graph for this function:

Factorial of nonnegative integer n, via "Binary Split Factorial Formula"
described at http://www.luschny.de/math/factorial/binarysplitfact.html

Definition at line 98 of file test_math.py.

00098 
00099 def py_factorial(n):
00100     """Factorial of nonnegative integer n, via "Binary Split Factorial Formula"
00101     described at http://www.luschny.de/math/factorial/binarysplitfact.html
00102 
00103     """
00104     inner = outer = 1
00105     for i in reversed(range(n.bit_length())):
00106         inner *= partial_product((n >> i + 1) + 1 | 1, (n >> i) + 1 | 1)
00107         outer *= inner
00108     return outer << (n - count_set_bits(n))

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1073 of file test_math.py.

01073 
01074 def test_main():
01075     from doctest import DocFileSuite
01076     suite = unittest.TestSuite()
01077     suite.addTest(unittest.makeSuite(MathTests))
01078     suite.addTest(DocFileSuite("ieee754.txt"))
01079     run_unittest(suite)

Here is the call graph for this function:

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.

Definition at line 32 of file test_math.py.

00032 
00033 def to_ulps(x):
00034     """Convert a non-NaN float x to an integer, in such a way that
00035     adjacent floats are converted to adjacent integers.  Then
00036     abs(ulps(x) - ulps(y)) gives the difference in ulps between two
00037     floats.
00038 
00039     The results from this function will only make sense on platforms
00040     where C doubles are represented in IEEE 754 binary64 format.
00041 
00042     """
00043     n = struct.unpack('<q', struct.pack('<d', x))[0]
00044     if n < 0:
00045         n = ~(n+2**63)
00046     return n

Here is the caller graph for this function:

def test.test_math.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.

Definition at line 47 of file test_math.py.

00047 
00048 def ulps_check(expected, got, ulps=20):
00049     """Given non-NaN floats `expected` and `got`,
00050     check that they're equal to within the given number of ulps.
00051 
00052     Returns None on success and an error message on failure."""
00053 
00054     ulps_error = to_ulps(got) - to_ulps(expected)
00055     if abs(ulps_error) <= ulps:
00056         return None
00057     return "error = {} ulps; permitted error = {} ulps".format(ulps_error,
00058                                                                ulps)
00059 
00060 # Here's a pure Python version of the math.factorial algorithm, for
00061 # documentation and comparison purposes.
00062 #
00063 # Formula:
00064 #
00065 #   factorial(n) = factorial_odd_part(n) << (n - count_set_bits(n))
00066 #
00067 # where
00068 #
00069 #   factorial_odd_part(n) = product_{i >= 0} product_{0 < j <= n >> i; j odd} j
00070 #
00071 # The outer product above is an infinite product, but once i >= n.bit_length,
00072 # (n >> i) < 1 and the corresponding term of the product is empty.  So only the
00073 # finitely many terms for 0 <= i < n.bit_length() contribute anything.
00074 #
00075 # We iterate downwards from i == n.bit_length() - 1 to i == 0.  The inner
00076 # product in the formula above starts at 1 for i == n.bit_length(); for each i
00077 # < n.bit_length() we get the inner product for i from that for i + 1 by
00078 # multiplying by all j in {n >> i+1 < j <= n >> i; j odd}.  In Python terms,
00079 # this set is range((n >> i+1) + 1 | 1, (n >> i) + 1 | 1, 2).

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

Definition at line 13 of file test_math.py.

Definition at line 25 of file test_math.py.

tuple test.test_math.HAVE_DOUBLE_ROUNDING = (x + y == 1e16 + 4)

Definition at line 21 of file test_math.py.

tuple test.test_math.INF = float('inf')

Definition at line 15 of file test_math.py.

tuple test.test_math.math_testcases = os.path.join(test_dir, 'math_testcases.txt')

Definition at line 29 of file test_math.py.

tuple test.test_math.NAN = float('nan')

Definition at line 14 of file test_math.py.

tuple test.test_math.NINF = float('-inf')

Definition at line 16 of file test_math.py.

tuple test.test_math.test_dir = os.path.dirname(file)

Definition at line 28 of file test_math.py.

tuple test.test_math.test_file = os.path.join(test_dir, 'cmath_testcases.txt')

Definition at line 30 of file test_math.py.