[pypy-commit] pypy numpypy-complex2: start to test binary complex functions in rcomplex
mattip
noreply at buildbot.pypy.org
Tue Sep 18 21:31:58 CEST 2012
Author: mattip <matti.picus at gmail.com>
Branch: numpypy-complex2
Changeset: r57375:7f7b6d547027
Date: 2012-09-18 22:25 +0300
http://bitbucket.org/pypy/pypy/changeset/7f7b6d547027/
Log: start to test binary complex functions in rcomplex
diff --git a/pypy/rlib/test/rcomplex_testcases.txt b/pypy/rlib/test/rcomplex_testcases.txt
--- a/pypy/rlib/test/rcomplex_testcases.txt
+++ b/pypy/rlib/test/rcomplex_testcases.txt
@@ -1,4 +1,4 @@
--- Testcases for functions in cmath.
+-- Testcases for functions in rcomplex, copied from cpython's cmath.
--
-- Each line takes the form:
--
diff --git a/pypy/rlib/test/rcomplex_testcases2.txt b/pypy/rlib/test/rcomplex_testcases2.txt
new file mode 100644
--- /dev/null
+++ b/pypy/rlib/test/rcomplex_testcases2.txt
@@ -0,0 +1,87 @@
+-- Testcases for functions in rcomplex, based on syntax of cpython's
+-- cmath tests.
+--
+-- Each line takes the form:
+--
+-- <testid> <function> <input_value> [<input_value>] -> <output_value> <flags>
+--
+-- where:
+--
+-- <testid> is a short name identifying the test,
+--
+-- <function> is the function to be tested (exp, cos, asinh, ...),
+--
+-- <input_value> is either a pair or a quad of values separated by whitespace
+-- representing real and imaginary parts of a complex number, and
+--
+-- <output_value> is the expected (ideal) output value, again
+-- represented as a pair of values.
+--
+-- The values used may be a hex representation of a float beginning with
+-- '0x' or '0X' or a decimal representation of a float.
+--
+-- <flags> is a list of the floating-point flags required by C99
+--
+-- The possible flags are:
+--
+-- divide-by-zero : raised when a finite input gives a
+-- mathematically infinite result.
+--
+-- overflow : raised when a finite input gives a finite result whose
+-- real or imaginary part is too large to fit in the usual range
+-- of an IEEE 754 double.
+--
+-- invalid : raised for invalid inputs.
+--
+-- ignore-real-sign : indicates that the sign of the real part of
+-- the result is unspecified; if the real part of the result is
+-- given as inf, then both -inf and inf should be accepted as
+-- correct.
+--
+-- ignore-imag-sign : indicates that the sign of the imaginary part
+-- of the result is unspecified.
+--
+-- Flags may appear in any order.
+--
+-- Lines beginning with '--' (like this one) start a comment, and are
+-- ignored. Blank lines, or lines containing only whitespace, are also
+-- ignored.
+--
+-- These tests are designed to excercise interesting values of functions,
+-- includind special values (+inf, -inf, nan, +0, -0, min_mantissa,
+-- min_exponent, max_mantissa, max_exponent) in both input and output,
+-- random values, and any branch cuts implicit in the function
+-- (non-continuities in function value)
+
+
+-----------------------
+-- pow: power --
+-----------------------
+-- if x is 1.0, result is 1.0
+pow0000 pow 1.0 0.0 0.0 0.0 -> 1.0 0.0
+pow0001 pow 1.0 0.0 2.0 0.0 -> 1.0 0.0
+pow0002 pow 1.0 0.0 0.0 2.0 -> 1.0 0.0
+pow0003 pow 1.0 0.0 2.0 2.0 -> 1.0 0.0
+pow0004 pow 1.0 0.0 inf 0.0 -> 1.0 0.0
+pow0005 pow 1.0 0.0 0.0 inf -> 1.0 0.0
+pow0006 pow 1.0 0.0 inf inf -> 1.0 0.0
+pow0007 pow 1.0 0.0 -inf 0.0 -> 1.0 0.0
+pow0008 pow 1.0 0.0 0.0 -inf -> 1.0 0.0
+pow0009 pow 1.0 0.0 -inf -inf -> 1.0 0.0
+pow0010 pow 1.0 0.0 nan 0.0 -> 1.0 0.0
+pow0011 pow 1.0 0.0 0.0 nan -> 1.0 0.0
+pow0012 pow 1.0 0.0 nan nan -> 1.0 0.0
+-- if y is 0.0, result is 1.0
+pow0020 pow 0.0 0.0 1.0 0.0 -> 1.0 0.0
+pow0021 pow 2.0 0.0 1.0 0.0 -> 1.0 0.0
+pow0022 pow 0.0 2.0 1.0 0.0 -> 1.0 0.0
+pow0023 pow 2.0 2.0 1.0 0.0 -> 1.0 0.0
+pow0024 pow inf 0.0 1.0 0.0 -> 1.0 0.0
+pow0025 pow 0.0 inf 1.0 0.0 -> 1.0 0.0
+pow0026 pow inf inf 1.0 0.0 -> 1.0 0.0
+pow0027 pow -inf 0.0 1.0 0.0 -> 1.0 0.0
+pow0028 pow 0.0 -inf 1.0 0.0 -> 1.0 0.0
+pow0029 pow -inf -inf 1.0 0.0 -> 1.0 0.0
+pow0030 pow nan 0.0 1.0 0.0 -> 1.0 0.0
+pow0031 pow 0.0 nan 1.0 0.0 -> 1.0 0.0
+pow0032 pow nan nan 1.0 0.0 -> 1.0 0.0
diff --git a/pypy/rlib/test/test_rcomplex.py b/pypy/rlib/test/test_rcomplex.py
--- a/pypy/rlib/test/test_rcomplex.py
+++ b/pypy/rlib/test/test_rcomplex.py
@@ -2,7 +2,7 @@
import pypy.rlib.rcomplex as c
from pypy.rlib.rfloat import copysign, isnan, isinf
-import os, sys, math
+import os, sys, math, struct
def test_add():
@@ -33,6 +33,47 @@
]:
assert c.c_mul(c1, c2) == result
+def parse_testfile2(fname):
+ """Parse a file with test values
+
+ Empty lines or lines starting with -- are ignored
+ yields id, fn, arg1_real, arg1_imag, arg2_real, arg2_imag,
+ exp_real, exp_imag where numbers in file may be expressed as floating point or hex
+ """
+ fname = os.path.join(os.path.dirname(__file__), fname)
+ with open(fname) as fp:
+ for line in fp:
+ # skip comment lines and blank lines
+ if line.startswith('--') or not line.strip():
+ continue
+
+ lhs, rhs = line.split('->')
+ lhs_pieces = lhs.split()
+ rhs_pieces = rhs.split()
+ for i in range(2, len(lhs_pieces)):
+ if lhs_pieces[i].lower().startswith('0x'):
+ lhs_pieces[i] = struct.unpack('d',
+ struct.pack('q',int(lhs_pieces[i])))
+ else:
+ lhs_pieces[i] = float(lhs_pieces[i])
+ for i in range(2):
+ if rhs_pieces[i].lower().startswith('0x'):
+ rhs_pieces[i] = struct.unpack('d',
+ struct.pack('l',int(rhs_pieces[i])))
+ else:
+ rhs_pieces[i] = float(rhs_pieces[i])
+ #id, fn, arg1_real, arg1_imag arg2_real, arg2_imag =
+ #exp_real, exp_imag = rhs_pieces[0], rhs_pieces[1]
+ flags = rhs_pieces[2:]
+ id_f, fn = lhs_pieces[:2]
+ if len(lhs_pieces)>4:
+ args = (lhs_pieces[2:4], lhs_pieces[4:])
+ else:
+ args = lhs_pieces[2:]
+ yield id_f, fn, args, rhs_pieces[:2], flags
+
+
+
def parse_testfile(fname):
"""Parse a file with test values
@@ -58,6 +99,13 @@
flags
)
+def args_to_str(args):
+ if isinstance(args[0],(list, tuple)):
+ return '(complex(%r, %r), complex(%r, %r))' % \
+ (args[0][0], args[0][1], args[1][0], args[1][1])
+ else:
+ return '(complex(%r, %r))' % (args[0], args[1])
+
def rAssertAlmostEqual(a, b, rel_err = 2e-15, abs_err = 5e-323, msg=''):
"""Fail if the two floating-point numbers are not almost equal.
@@ -111,9 +159,7 @@
#if not float.__getformat__("double").startswith("IEEE"):
# return
- for id, fn, ar, ai, er, ei, flags in parse_testfile('rcomplex_testcases.txt'):
- arg = (ar, ai)
- expected = (er, ei)
+ for id, fn, arg, expected, flags in parse_testfile2('rcomplex_testcases.txt'):
function = getattr(c, 'c_' + fn)
#
if 'divide-by-zero' in flags or 'invalid' in flags:
@@ -123,8 +169,7 @@
continue
else:
raise AssertionError('ValueError not raised in test '
- '%s: %s(complex(%r, %r))' % (id, fn,
- ar, ai))
+ '%s: %s%s' % (id, fn, args_to_str(arg)))
if 'overflow' in flags:
try:
actual = function(*arg)
@@ -132,8 +177,7 @@
continue
else:
raise AssertionError('OverflowError not raised in test '
- '%s: %s(complex(%r, %r))' % (id, fn,
- ar, ai))
+ '%s: %s%s' % (id, fn, args_to_str(arg)))
actual = function(*arg)
if 'ignore-real-sign' in flags:
@@ -151,10 +195,10 @@
real_abs_err = 5e-323
error_message = (
- '%s: %s(complex(%r, %r))\n'
+ '%s: %s%s\n'
'Expected: complex(%r, %r)\n'
'Received: complex(%r, %r)\n'
- ) % (id, fn, ar, ai,
+ ) % (id, fn, args_to_str(arg),
expected[0], expected[1],
actual[0], actual[1])
@@ -162,4 +206,54 @@
abs_err=real_abs_err,
msg=error_message)
rAssertAlmostEqual(expected[1], actual[1],
+ abs_err=real_abs_err,
msg=error_message)
+
+ for id, fn, a, expected, flags in parse_testfile2('rcomplex_testcases2.txt'):
+ function = getattr(c, 'c_' + fn)
+ #
+ if 'divide-by-zero' in flags or 'invalid' in flags:
+ try:
+ actual = function(*a)
+ except ValueError:
+ continue
+ else:
+ raise AssertionError('ValueError not raised in test '
+ '%s: %s%s' % (id, fn, args_to_str(a)))
+ if 'overflow' in flags:
+ try:
+ actual = function(*a)
+ except OverflowError:
+ continue
+ else:
+ raise AssertionError('OverflowError not raised in test '
+ '%s: %s%s' % (id, fn, args_to_str(a)))
+ actual = function(*a)
+
+ if 'ignore-real-sign' in flags:
+ actual = (abs(actual[0]), actual[1])
+ expected = (abs(expected[0]), expected[1])
+ if 'ignore-imag-sign' in flags:
+ actual = (actual[0], abs(actual[1]))
+ expected = (expected[0], abs(expected[1]))
+
+ # for the real part of the log function, we allow an
+ # absolute error of up to 2e-15.
+ if fn in ('log', 'log10'):
+ real_abs_err = 2e-15
+ else:
+ real_abs_err = 5e-323
+ error_message = (
+ '%s: %s%s\n'
+ 'Expected: complex(%r, %r)\n'
+ 'Received: complex(%r, %r)\n'
+ ) % (id, fn, args_to_str(a),
+ expected[0], expected[1],
+ actual[0], actual[1])
+
+ rAssertAlmostEqual(expected[0], actual[0],
+ abs_err=real_abs_err,
+ msg=error_message)
+ rAssertAlmostEqual(expected[1], actual[1],
+ abs_err=real_abs_err,
+ msg=error_message)
More information about the pypy-commit
mailing list