| 1 | // (C) Copyright John Maddock 2005. |
|---|
| 2 | // Use, modification and distribution are subject to the |
|---|
| 3 | // Boost Software License, Version 1.0. (See accompanying file |
|---|
| 4 | // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
|---|
| 5 | |
|---|
| 6 | #ifdef TEST_STD_HEADERS |
|---|
| 7 | #include <complex> |
|---|
| 8 | #else |
|---|
| 9 | #include <boost/tr1/complex.hpp> |
|---|
| 10 | #endif |
|---|
| 11 | |
|---|
| 12 | #include <boost/test/test_tools.hpp> |
|---|
| 13 | #include <boost/test/included/test_exec_monitor.hpp> |
|---|
| 14 | #include <boost/test/floating_point_comparison.hpp> |
|---|
| 15 | #include <boost/type_traits/is_same.hpp> |
|---|
| 16 | #include <boost/type_traits/is_floating_point.hpp> |
|---|
| 17 | #include <boost/mpl/if.hpp> |
|---|
| 18 | #include <boost/static_assert.hpp> |
|---|
| 19 | |
|---|
| 20 | #include <iostream> |
|---|
| 21 | #include <iomanip> |
|---|
| 22 | |
|---|
| 23 | #ifndef VERBOSE |
|---|
| 24 | #undef BOOST_MESSAGE |
|---|
| 25 | #define BOOST_MESSAGE(x) |
|---|
| 26 | #endif |
|---|
| 27 | |
|---|
| 28 | // |
|---|
| 29 | // This test verifies that the complex-algorithms that are |
|---|
| 30 | // overloaded for scalar types produce the same result as casting |
|---|
| 31 | // the argument to a complex type, and calling the complex version |
|---|
| 32 | // of the algorithm. Relative errors must be within 2e in order for |
|---|
| 33 | // the tests to pass. |
|---|
| 34 | // |
|---|
| 35 | |
|---|
| 36 | template <class T, class U> |
|---|
| 37 | void check(const T& t, const U& u) |
|---|
| 38 | { |
|---|
| 39 | static const T two = 2; |
|---|
| 40 | static const T factor = std::pow(two, 1-std::numeric_limits<T>::digits) * 200; |
|---|
| 41 | BOOST_STATIC_ASSERT((::boost::is_same<T,U>::value)); |
|---|
| 42 | BOOST_CHECK_CLOSE(t, u, factor); |
|---|
| 43 | } |
|---|
| 44 | |
|---|
| 45 | template <class T, class U> |
|---|
| 46 | void check(const std::complex<T>& t, const std::complex<U>& u) |
|---|
| 47 | { |
|---|
| 48 | BOOST_STATIC_ASSERT((::boost::is_same<T,U>::value)); |
|---|
| 49 | check(t.real(), u.real()); |
|---|
| 50 | check(t.imag(), u.imag()); |
|---|
| 51 | } |
|---|
| 52 | |
|---|
| 53 | template <class T> |
|---|
| 54 | void check_val(const T& val) |
|---|
| 55 | { |
|---|
| 56 | typedef typename boost::mpl::if_< boost::is_floating_point<T>, T, double>::type real_type; |
|---|
| 57 | typedef std::complex<real_type> complex_type; |
|---|
| 58 | |
|---|
| 59 | real_type rval = static_cast<real_type>(val); |
|---|
| 60 | complex_type cval = rval; |
|---|
| 61 | |
|---|
| 62 | if(val) |
|---|
| 63 | { |
|---|
| 64 | std::cout << " Testing std::arg.\n"; |
|---|
| 65 | check(std::arg(cval), std::arg(rval)); |
|---|
| 66 | check(std::arg(cval), std::arg(val)); |
|---|
| 67 | } |
|---|
| 68 | std::cout << " Testing std::norm.\n"; |
|---|
| 69 | check(std::norm(cval), std::norm(rval)); |
|---|
| 70 | check(std::norm(cval), std::norm(val)); |
|---|
| 71 | std::cout << " Testing std::conj.\n"; |
|---|
| 72 | check(std::conj(cval), std::conj(rval)); |
|---|
| 73 | check(std::conj(cval), std::conj(val)); |
|---|
| 74 | std::cout << " Testing std::polar.\n"; |
|---|
| 75 | check(std::polar(val), std::polar(rval)); |
|---|
| 76 | check(std::polar(val, 0), std::polar(rval, 0)); |
|---|
| 77 | check(std::polar(val, val), std::polar(rval, rval)); |
|---|
| 78 | check(std::polar(val, rval), std::polar(rval, val)); |
|---|
| 79 | std::cout << " Testing std::real.\n"; |
|---|
| 80 | check(std::real(cval), std::real(rval)); |
|---|
| 81 | check(std::real(cval), std::real(val)); |
|---|
| 82 | std::cout << " Testing std::imaj.\n"; |
|---|
| 83 | check(std::imag(cval), std::imag(rval)); |
|---|
| 84 | check(std::imag(cval), std::imag(val)); |
|---|
| 85 | if(val && !boost::is_floating_point<T>::value) |
|---|
| 86 | { |
|---|
| 87 | // |
|---|
| 88 | // Note that these tests are not run for floating point |
|---|
| 89 | // types as that would only test the std lib vendor's |
|---|
| 90 | // implementation of pow, not our additional overloads. |
|---|
| 91 | // Note that some std lib's do fail these tests, gcc on |
|---|
| 92 | // Darwin is a particularly bad example ! |
|---|
| 93 | // |
|---|
| 94 | std::cout << " Testing std::pow.\n"; |
|---|
| 95 | check(std::pow(cval, cval), std::pow(cval, val)); |
|---|
| 96 | check(std::pow(cval, cval), std::pow(cval, rval)); |
|---|
| 97 | check(std::pow(cval, cval), std::pow(val, cval)); |
|---|
| 98 | check(std::pow(cval, cval), std::pow(rval, cval)); |
|---|
| 99 | } |
|---|
| 100 | } |
|---|
| 101 | |
|---|
| 102 | void check(double i) |
|---|
| 103 | { |
|---|
| 104 | std::cout << "Checking type double with value " << i << std::endl; |
|---|
| 105 | check_val(i); |
|---|
| 106 | std::cout << "Checking type float with value " << i << std::endl; |
|---|
| 107 | check_val(static_cast<float>(i)); |
|---|
| 108 | std::cout << "Checking type long double with value " << i << std::endl; |
|---|
| 109 | check_val(static_cast<long double>(i)); |
|---|
| 110 | } |
|---|
| 111 | |
|---|
| 112 | void check(int i) |
|---|
| 113 | { |
|---|
| 114 | std::cout << "Checking type char with value " << i << std::endl; |
|---|
| 115 | check_val(static_cast<char>(i)); |
|---|
| 116 | std::cout << "Checking type unsigned char with value " << i << std::endl; |
|---|
| 117 | check_val(static_cast<unsigned char>(i)); |
|---|
| 118 | std::cout << "Checking type signed char with value " << i << std::endl; |
|---|
| 119 | check_val(static_cast<signed char>(i)); |
|---|
| 120 | std::cout << "Checking type short with value " << i << std::endl; |
|---|
| 121 | check_val(static_cast<short>(i)); |
|---|
| 122 | std::cout << "Checking type unsigned short with value " << i << std::endl; |
|---|
| 123 | check_val(static_cast<unsigned short>(i)); |
|---|
| 124 | std::cout << "Checking type int with value " << i << std::endl; |
|---|
| 125 | check_val(static_cast<int>(i)); |
|---|
| 126 | std::cout << "Checking type unsigned int with value " << i << std::endl; |
|---|
| 127 | check_val(static_cast<unsigned int>(i)); |
|---|
| 128 | std::cout << "Checking type long with value " << i << std::endl; |
|---|
| 129 | check_val(static_cast<long>(i)); |
|---|
| 130 | std::cout << "Checking type unsigned long with value " << i << std::endl; |
|---|
| 131 | check_val(static_cast<unsigned long>(i)); |
|---|
| 132 | #ifdef BOOST_HAS_LONG_LONG |
|---|
| 133 | std::cout << "Checking type long long with value " << i << std::endl; |
|---|
| 134 | check_val(static_cast<long long>(i)); |
|---|
| 135 | std::cout << "Checking type unsigned long long with value " << i << std::endl; |
|---|
| 136 | check_val(static_cast<unsigned long long>(i)); |
|---|
| 137 | #elif defined(BOOST_HAS_MS_INT64) |
|---|
| 138 | std::cout << "Checking type __int64 with value " << i << std::endl; |
|---|
| 139 | check_val(static_cast<__int64>(i)); |
|---|
| 140 | std::cout << "Checking type unsigned __int64 with value " << i << std::endl; |
|---|
| 141 | check_val(static_cast<unsigned __int64>(i)); |
|---|
| 142 | #endif |
|---|
| 143 | check(static_cast<double>(i)); |
|---|
| 144 | } |
|---|
| 145 | |
|---|
| 146 | int test_main(int, char*[]) |
|---|
| 147 | { |
|---|
| 148 | check(0); |
|---|
| 149 | check(0.0); |
|---|
| 150 | check(1); |
|---|
| 151 | check(1.5); |
|---|
| 152 | check(0.5); |
|---|
| 153 | return 0; |
|---|
| 154 | } |
|---|
| 155 | |
|---|