| /* | |
| This Software is provided under the Zope Public License (ZPL) Version 2.1. | |
| Copyright (c) 2009, 2010 by the mingw-w64 project | |
| See the AUTHORS file for the list of contributors to the mingw-w64 project. | |
| This license has been certified as open source. It has also been designated | |
| as GPL compatible by the Free Software Foundation (FSF). | |
| Redistribution and use in source and binary forms, with or without | |
| modification, are permitted provided that the following conditions are met: | |
| 1. Redistributions in source code must retain the accompanying copyright | |
| notice, this list of conditions, and the following disclaimer. | |
| 2. Redistributions in binary form must reproduce the accompanying | |
| copyright notice, this list of conditions, and the following disclaimer | |
| in the documentation and/or other materials provided with the | |
| distribution. | |
| 3. Names of the copyright holders must not be used to endorse or promote | |
| products derived from this software without prior written permission | |
| from the copyright holders. | |
| 4. The right to distribute this software or to use it for any purpose does | |
| not give you the right to use Servicemarks (sm) or Trademarks (tm) of | |
| the copyright holders. Use of them is covered by separate agreement | |
| with the copyright holders. | |
| 5. If any files are modified, you must cause the modified files to carry | |
| prominent notices stating that you changed the files and the date of | |
| any change. | |
| Disclaimer | |
| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED | |
| OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
| OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO | |
| EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, | |
| INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
| LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, | |
| OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | |
| LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | |
| NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, | |
| EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| */ | |
| /* Testsuite functions for the complex functions of C99. */ | |
| #ifndef _NEWCOMPLEX_TEST_H | |
| #define _NEWCOMPLEX_TEST_H | |
| /* Support printing of long doubles. */ | |
| #define __USE_MINGW_ANSI_STDIO 1 | |
| #include <stdio.h> | |
| #include <math.h> | |
| #include <complex.h> | |
| /* Default to double types. */ | |
| #if !(defined (_NEW_COMPLEX_FLOAT) || defined (_NEW_COMPLEX_DOUBLE) || defined (_NEW_COMPLEX_LDOUBLE)) | |
| #define _NEW_COMPLEX_DOUBLE 1 | |
| #endif | |
| /* Grab the internals for things like __FLT_PI, etc. */ | |
| #include "complex_internal.h" | |
| /* Declare comparisons etc. */ | |
| #if defined(_NEW_COMPLEX_DOUBLE) | |
| # define __FLT_CMP compare_dbl | |
| # define __FLT_CCMP compare_cdbl | |
| # define __FLT_DELTA (2.0 * __DBL_EPSILON__) | |
| # define __FLT_FMT "%0.32g" | |
| #elif defined (_NEW_COMPLEX_FLOAT) | |
| # define __FLT_CMP compare_flt | |
| # define __FLT_CCMP compare_cflt | |
| # define __FLT_DELTA (2.0F * __FLT_EPSILON__) | |
| # define __FLT_FMT "%0.32g" | |
| #elif defined (_NEW_COMPLEX_LDOUBLE) | |
| # define __FLT_CMP compare_ldbl | |
| # define __FLT_CCMP compare_cldbl | |
| # define __FLT_DELTA (2.0L * __LDBL_EPSILON__) | |
| # define __FLT_FMT "%0.32Lg" | |
| #endif | |
| struct complex_test | |
| { | |
| /* The input value to the complex function */ | |
| __FLT_TYPE input_r; | |
| __FLT_TYPE input_i; | |
| /* The expected value from the complex function */ | |
| __FLT_TYPE expected_r; | |
| __FLT_TYPE expected_i; | |
| /* Some C99 signs are +/-. When these are true, don't compare signs */ | |
| int real_sign_dontcare; | |
| int imag_sign_dontcare; | |
| }; | |
| /* Definition of the function under test. */ | |
| typedef __FLT_TYPE complex (*complex_function)(__FLT_TYPE complex z); | |
| typedef __FLT_TYPE (*real_function)(__FLT_TYPE complex z); | |
| /* Some possible behaviors of the function. */ | |
| /* func (conj (z)) = conj (func (z)) */ | |
| #define FUNC_BEHAVIOR_CONJ 0x0001 | |
| /* func (-z) = -func (z) */ | |
| #define FUNC_BEHAVIOR_ODD 0x0002 | |
| /* func (-z) = func (z) */ | |
| #define FUNC_BEHAVIOR_EVEN 0x0004 | |
| /* Structure to hold info about the complex function. */ | |
| struct test_func_desc | |
| { | |
| const char *fname; | |
| complex_function complex_test; | |
| real_function real_test; | |
| int behavior; | |
| }; | |
| /** | |
| * Compares expected and test values with a delta tolerance. | |
| * 0 for pass, 1 for fail. | |
| * TODO: | |
| * Tune comparison precision | |
| **/ | |
| static int | |
| __FLT_CMP (__FLT_TYPE expected, __FLT_TYPE in, int sign_dontcare) | |
| { | |
| int bad = 0; | |
| if (isnan (expected) || isnan (in)) | |
| { | |
| /* NaN comparisons */ | |
| bad = isnan (expected) != isnan (in); | |
| } | |
| else if (isfinite (expected) && isfinite (in)) | |
| { | |
| /* Finite value tests */ | |
| if (expected == 0 && in == 0) | |
| { | |
| /* Signed zero comparison */ | |
| bad = (sign_dontcare) ? 0 : signbit (expected) != signbit (in); | |
| } | |
| else | |
| { | |
| bad = (expected > in) ? | |
| ((expected - in) > __FLT_DELTA) : | |
| ((in - expected) > __FLT_DELTA); | |
| } | |
| } | |
| else | |
| { | |
| /* Either expected or in is an infinite */ | |
| bad = !isinf(expected) || !isinf(in); | |
| if (!bad && !sign_dontcare) | |
| bad = signbit (expected) != signbit (in); | |
| } | |
| return bad; | |
| } | |
| static int | |
| __FLT_CCMP (complex __FLT_TYPE expected, | |
| complex __FLT_TYPE in, | |
| int real_sign_dontcare, | |
| int imag_sign_dontcare) | |
| { | |
| return (__FLT_CMP (__FLT_ABI(creal)(expected), __FLT_ABI(creal)(in), real_sign_dontcare) || | |
| __FLT_CMP (__FLT_ABI(cimag)(expected), __FLT_ABI(cimag)(in), imag_sign_dontcare)); | |
| } | |
| /* Runs comparison and (DEBUG) print error. | |
| returns 1 on fail, 0 on success. */ | |
| static int | |
| error_check_test (const struct test_func_desc *fdesc, | |
| const char* testdescription, | |
| int testindex, | |
| __FLT_TYPE complex test, | |
| __FLT_TYPE complex expected, | |
| int real_sign_dontcare, | |
| int imag_sign_dontcare) | |
| { | |
| int bad = 0; | |
| __FLT_TYPE complex actual; | |
| if (fdesc->complex_test) | |
| { | |
| actual = fdesc->complex_test (test); | |
| bad = __FLT_CCMP (expected, actual, real_sign_dontcare, imag_sign_dontcare); | |
| if (bad) | |
| { | |
| printf("%s %s test index %d failed on input " __FLT_FMT " + " __FLT_FMT "i.\n" | |
| "\tExpected: " __FLT_FMT " + " __FLT_FMT "i\n" | |
| "\tActual: " __FLT_FMT " + " __FLT_FMT "i (epsilon=" __FLT_FMT ")\n", | |
| fdesc->fname, testdescription, testindex, | |
| __FLT_ABI(creal) (test), __FLT_ABI(cimag) (test), | |
| __FLT_ABI(creal) (expected), __FLT_ABI(cimag) (expected), | |
| __FLT_ABI(creal) (actual), __FLT_ABI(cimag) (actual), | |
| __FLT_DELTA); | |
| } | |
| } | |
| else | |
| { | |
| __real__ actual = fdesc->real_test (test); | |
| bad = __FLT_CMP (__real__ expected, actual, real_sign_dontcare); | |
| if (bad) | |
| { | |
| printf("%s %s test index %d failed on input " __FLT_FMT " + " __FLT_FMT "i.\n" | |
| "\tExpected: " __FLT_FMT "\n" | |
| "\tActual: " __FLT_FMT " (epsilon=" __FLT_FMT ")\n", | |
| fdesc->fname, testdescription, testindex, | |
| __FLT_ABI(creal) (test), __FLT_ABI(cimag) (test), | |
| __FLT_ABI(creal) (expected), | |
| __FLT_ABI(creal) (actual), | |
| __FLT_DELTA); | |
| } | |
| } | |
| return bad; | |
| } | |
| /* Tests of conjugates, function should satisfy | |
| func (conj (z)) = conj (func (z)). func (conj (z)) should return | |
| the conj of the expected, since expected is the expected result of | |
| func (z). */ | |
| static int | |
| conjugate_tests (const struct test_func_desc *fdesc, | |
| int testindex, | |
| __FLT_TYPE complex test, | |
| __FLT_TYPE complex expected, | |
| int real_sign_dontcare, | |
| int imag_sign_dontcare) | |
| { | |
| int ret = 0; | |
| /* Conjugate test 1: verify result of func (conj (z)) is conj (expected) */ | |
| __FLT_TYPE complex ctest = __FLT_ABI(conj) (test); | |
| __FLT_TYPE complex cexpected = __FLT_ABI(conj) (expected); | |
| ret |= error_check_test (fdesc, "Congugate of expected", testindex, ctest, cexpected, | |
| real_sign_dontcare, imag_sign_dontcare); | |
| return ret; | |
| } | |
| /* Tests of odd functions, function should satisfy | |
| func (-z) = -func (z). func (-z) should result in the -expected result, | |
| since expected is the expected result of func (z). */ | |
| static int | |
| odd_tests (const struct test_func_desc *fdesc, | |
| int testindex, | |
| __FLT_TYPE complex test, | |
| __FLT_TYPE complex expected, | |
| int real_sign_dontcare, | |
| int imag_sign_dontcare) | |
| { | |
| int ret = 0; | |
| /* Oddness test 1: verify result of func (-z) is -expected */ | |
| __FLT_TYPE complex ctest = -test; | |
| __FLT_TYPE complex cexpected = -expected; | |
| ret |= error_check_test (fdesc, "Oddness", testindex, ctest, cexpected, | |
| real_sign_dontcare, imag_sign_dontcare); | |
| /* Need to do conjugate of the odd values as well */ | |
| ret |= conjugate_tests(fdesc, testindex, ctest, cexpected, real_sign_dontcare, | |
| imag_sign_dontcare); | |
| return ret; | |
| } | |
| /* Tests of even functions, function should satisfy | |
| func (-z) = func (z). func (-z) should result in the expected result, | |
| since expected is the expected result of func (z). */ | |
| static int | |
| even_tests (const struct test_func_desc *fdesc, | |
| int testindex, | |
| __FLT_TYPE complex test, | |
| __FLT_TYPE complex expected, | |
| int real_sign_dontcare, | |
| int imag_sign_dontcare) | |
| { | |
| int ret = 0; | |
| /* Evenness test 1: verify result of func (-z) is expected */ | |
| __FLT_TYPE complex ctest = -test; | |
| __FLT_TYPE complex cexpected = expected; | |
| ret |= error_check_test (fdesc, "Evenness", testindex, ctest, cexpected, | |
| real_sign_dontcare, imag_sign_dontcare); | |
| /* Need to do conjugate of the even values as well */ | |
| ret |= conjugate_tests(fdesc, testindex, ctest, cexpected, real_sign_dontcare, | |
| imag_sign_dontcare); | |
| return ret; | |
| } | |
| /* Actually run the tests. */ | |
| static int | |
| runtests (const struct test_func_desc *testfunc, | |
| const struct complex_test *testarray, | |
| int testcount) | |
| { | |
| int i; | |
| int ret = 0; | |
| for (i = 0; i < testcount; i++) | |
| { | |
| __FLT_TYPE complex test; | |
| __FLT_TYPE complex expected; | |
| __real__ test = testarray[i].input_r; | |
| __imag__ test = testarray[i].input_i; | |
| __real__ expected = testarray[i].expected_r; | |
| __imag__ expected = testarray[i].expected_i; | |
| /* Main test --- specified in Annex G, et al. */ | |
| ret |= error_check_test (testfunc, "Annex G", i, test, expected, | |
| testarray[i].real_sign_dontcare, testarray[i].imag_sign_dontcare); | |
| if (testfunc->behavior & FUNC_BEHAVIOR_CONJ) | |
| { | |
| ret |= conjugate_tests (testfunc, i, test, expected, | |
| testarray[i].real_sign_dontcare, testarray[i].imag_sign_dontcare); | |
| } | |
| if (testfunc->behavior & FUNC_BEHAVIOR_ODD) | |
| { | |
| ret |= odd_tests (testfunc, i, test, expected, | |
| testarray[i].real_sign_dontcare, testarray[i].imag_sign_dontcare); | |
| } | |
| if (testfunc->behavior & FUNC_BEHAVIOR_EVEN) | |
| { | |
| ret |= even_tests (testfunc, i, test, expected, | |
| testarray[i].real_sign_dontcare, testarray[i].imag_sign_dontcare); | |
| } | |
| } | |
| return ret; | |
| } | |
| #define __FLT_STRING(x) #x | |
| #define __FLT_STRINGIFY(x) __FLT_STRING(x) | |
| /** | |
| * Defines the test function with a variable name to pass to RUN_TESTS. | |
| * varname is the varname to use. | |
| * funcame is the function to test. | |
| * behavior is the flags of how the function behaves. | |
| */ | |
| #define DEFINE_TEST_FUNCTION(varname, funcname, behavior) \ | |
| struct test_func_desc varname = \ | |
| { \ | |
| __FLT_STRINGIFY(__FLT_ABI(funcname)), \ | |
| __FLT_ABI(funcname), \ | |
| NULL, \ | |
| behavior \ | |
| } | |
| /** | |
| * Defines the test function with a variable name to pass to RUN_TESTS. | |
| * This version is for functions that return a real value. | |
| * varname is the varname to use. | |
| * funcame is the function to test. | |
| * behavior is the flags of how the function behaves. | |
| */ | |
| #define DEFINE_TEST_FUNCTION_REAL(varname, funcname, behavior) \ | |
| struct test_func_desc varname = \ | |
| { \ | |
| __FLT_STRINGIFY(__FLT_ABI(funcname)), \ | |
| NULL, \ | |
| __FLT_ABI(funcname), \ | |
| behavior \ | |
| } | |
| /* Do not use semicolons with these macros. */ | |
| /** | |
| * Starts a declaration of tests, with a variable name. | |
| */ | |
| #define TESTS_START(v) const struct complex_test v[] = { | |
| /** | |
| * Starts a declaration of tests, with a default variable name, for use with | |
| * RUN_DEFAULT_TESTS. | |
| */ | |
| #define DEFAULT_TESTS_START TESTS_START(_default_tests) | |
| /** | |
| * Macro to fill a complex_test structure with values while inside a | |
| * TESTS block. | |
| */ | |
| #define DEFINE_TEST(input_r, input_i, expected_r, expected_i, real_sign_dontcare, imag_sign_dontcare) \ | |
| { input_r, input_i, expected_r, expected_i, real_sign_dontcare, imag_sign_dontcare }, | |
| /** | |
| * Closes a test block opened with the TESTS_START macros. | |
| */ | |
| #define TESTS_END }; | |
| /** | |
| * Runs the tests specified in testarray using the specified test function | |
| * definition. | |
| * testfunc is the function definition specification defined by one of the | |
| * DEFINE_TEST_FUNCTION macros. | |
| * testarray is the test array defined by a TESTS_START macro. | |
| */ | |
| #define RUN_TESTS(testfunc, testarray) \ | |
| (runtests(&testfunc, testarray, (sizeof (testarray) / sizeof (*testarray)))) | |
| /** | |
| * Runs the tests specified in testarray using the test function | |
| * definition declared with DEFINE_DEFAULT_TEST_FUNCTION macros. | |
| * funcname is the function name passed to the DEFAULT_TEST_FUNCTION* macro. | |
| * testarray is the test array defined by the TESTS_START macro. | |
| */ | |
| #define RUN_FUNCTION_TESTS(funcname, testarray) \ | |
| RUN_TESTS(_test_##funcname, testarray) | |
| /** | |
| * Runs the tests specified by DEFAULT_TESTS testarray using the test function | |
| * definition declared with DEFINE_DEFAULT_TEST_FUNCTION macros. | |
| * funcname is the function name passed to the DEFAULT_TEST_FUNCTION* macro. | |
| */ | |
| #define RUN_DEFAULT_TESTS(funcname) \ | |
| RUN_TESTS(_test_##funcname, _default_tests) | |
| /** | |
| * Default test functions available. | |
| */ | |
| /** | |
| * Defines a test function with a default variable name for use with the | |
| * RUN_DEFAULT_TESTS macro. | |
| * funcname is the function family to test. | |
| * behavior is the function's behavior. | |
| */ | |
| #define _DEFINE_DEFAULT_TEST_FUNCTION(funcname, behavior) \ | |
| DEFINE_TEST_FUNCTION(_test_##funcname, funcname, behavior) | |
| /** | |
| * Defines a test function with a default variable name for use with the | |
| * RUN_DEFAULT_TESTS macro. This version is for functions that return | |
| * a real value. | |
| * funcname is the function family to test. | |
| * behavior is the function's behavior. | |
| */ | |
| #define _DEFINE_DEFAULT_TEST_FUNCTION_REAL(funcname, behavior) \ | |
| DEFINE_TEST_FUNCTION_REAL(_test_##funcname, funcname, behavior) | |
| #endif /* _NEWCOMPLEX_TEST_H */ |