1 // This file is part of Eigen, a lightweight C++ template library 2 // for linear algebra. Eigen itself is part of the KDE project. 3 // 4 // Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1 (at) gmail.com> 5 // Copyright (C) 2008 Gael Guennebaud <g.gael (at) free.fr> 6 // 7 // This Source Code Form is subject to the terms of the Mozilla 8 // Public License v. 2.0. If a copy of the MPL was not distributed 9 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. 10 11 #include <cstdlib> 12 #include <ctime> 13 #include <iostream> 14 #include <string> 15 #include <vector> 16 17 #ifndef EIGEN_TEST_FUNC 18 #error EIGEN_TEST_FUNC must be defined 19 #endif 20 21 #define DEFAULT_REPEAT 10 22 23 namespace Eigen 24 { 25 static std::vector<std::string> g_test_stack; 26 static int g_repeat; 27 } 28 29 #define EI_PP_MAKE_STRING2(S) #S 30 #define EI_PP_MAKE_STRING(S) EI_PP_MAKE_STRING2(S) 31 32 #define EI_PP_CAT2(a,b) a ## b 33 #define EI_PP_CAT(a,b) EI_PP_CAT2(a,b) 34 35 #ifndef EIGEN_NO_ASSERTION_CHECKING 36 37 namespace Eigen 38 { 39 static const bool should_raise_an_assert = false; 40 41 // Used to avoid to raise two exceptions at a time in which 42 // case the exception is not properly caught. 43 // This may happen when a second exceptions is raise in a destructor. 44 static bool no_more_assert = false; 45 46 struct eigen_assert_exception 47 { 48 eigen_assert_exception(void) {} 49 ~eigen_assert_exception() { Eigen::no_more_assert = false; } 50 }; 51 } 52 53 // If EIGEN_DEBUG_ASSERTS is defined and if no assertion is raised while 54 // one should have been, then the list of excecuted assertions is printed out. 55 // 56 // EIGEN_DEBUG_ASSERTS is not enabled by default as it 57 // significantly increases the compilation time 58 // and might even introduce side effects that would hide 59 // some memory errors. 60 #ifdef EIGEN_DEBUG_ASSERTS 61 62 namespace Eigen 63 { 64 static bool ei_push_assert = false; 65 static std::vector<std::string> eigen_assert_list; 66 } 67 68 #define eigen_assert(a) \ 69 if( (!(a)) && (!no_more_assert) ) \ 70 { \ 71 Eigen::no_more_assert = true; \ 72 throw Eigen::eigen_assert_exception(); \ 73 } \ 74 else if (Eigen::ei_push_assert) \ 75 { \ 76 eigen_assert_list.push_back(std::string(EI_PP_MAKE_STRING(__FILE__)" ("EI_PP_MAKE_STRING(__LINE__)") : "#a) ); \ 77 } 78 79 #define VERIFY_RAISES_ASSERT(a) \ 80 { \ 81 Eigen::no_more_assert = false; \ 82 try { \ 83 Eigen::eigen_assert_list.clear(); \ 84 Eigen::ei_push_assert = true; \ 85 a; \ 86 Eigen::ei_push_assert = false; \ 87 std::cerr << "One of the following asserts should have been raised:\n"; \ 88 for (uint ai=0 ; ai<eigen_assert_list.size() ; ++ai) \ 89 std::cerr << " " << eigen_assert_list[ai] << "\n"; \ 90 VERIFY(Eigen::should_raise_an_assert && # a); \ 91 } catch (Eigen::eigen_assert_exception e) { \ 92 Eigen::ei_push_assert = false; VERIFY(true); \ 93 } \ 94 } 95 96 #else // EIGEN_DEBUG_ASSERTS 97 98 #undef eigen_assert 99 100 // see bug 89. The copy_bool here is working around a bug in gcc <= 4.3 101 #define eigen_assert(a) \ 102 if( (!Eigen::internal::copy_bool(a)) && (!no_more_assert) ) \ 103 { \ 104 Eigen::no_more_assert = true; \ 105 throw Eigen::eigen_assert_exception(); \ 106 } 107 108 #define VERIFY_RAISES_ASSERT(a) { \ 109 Eigen::no_more_assert = false; \ 110 try { a; VERIFY(Eigen::should_raise_an_assert && # a); } \ 111 catch (Eigen::eigen_assert_exception e) { VERIFY(true); } \ 112 } 113 114 #endif // EIGEN_DEBUG_ASSERTS 115 116 #define EIGEN_USE_CUSTOM_ASSERT 117 118 #else // EIGEN_NO_ASSERTION_CHECKING 119 120 #define VERIFY_RAISES_ASSERT(a) {} 121 122 #endif // EIGEN_NO_ASSERTION_CHECKING 123 124 125 #define EIGEN_INTERNAL_DEBUGGING 126 #define EIGEN_NICE_RANDOM 127 #include <Eigen/Array> 128 129 130 #define VERIFY(a) do { if (!(a)) { \ 131 std::cerr << "Test " << g_test_stack.back() << " failed in "EI_PP_MAKE_STRING(__FILE__) << " (" << EI_PP_MAKE_STRING(__LINE__) << ")" \ 132 << std::endl << " " << EI_PP_MAKE_STRING(a) << std::endl << std::endl; \ 133 abort(); \ 134 } } while (0) 135 136 #define VERIFY_IS_APPROX(a, b) VERIFY(test_ei_isApprox(a, b)) 137 #define VERIFY_IS_NOT_APPROX(a, b) VERIFY(!test_ei_isApprox(a, b)) 138 #define VERIFY_IS_MUCH_SMALLER_THAN(a, b) VERIFY(test_ei_isMuchSmallerThan(a, b)) 139 #define VERIFY_IS_NOT_MUCH_SMALLER_THAN(a, b) VERIFY(!test_ei_isMuchSmallerThan(a, b)) 140 #define VERIFY_IS_APPROX_OR_LESS_THAN(a, b) VERIFY(test_ei_isApproxOrLessThan(a, b)) 141 #define VERIFY_IS_NOT_APPROX_OR_LESS_THAN(a, b) VERIFY(!test_ei_isApproxOrLessThan(a, b)) 142 143 #define CALL_SUBTEST(FUNC) do { \ 144 g_test_stack.push_back(EI_PP_MAKE_STRING(FUNC)); \ 145 FUNC; \ 146 g_test_stack.pop_back(); \ 147 } while (0) 148 149 namespace Eigen { 150 151 template<typename T> inline typename NumTraits<T>::Real test_precision(); 152 template<> inline int test_precision<int>() { return 0; } 153 template<> inline float test_precision<float>() { return 1e-3f; } 154 template<> inline double test_precision<double>() { return 1e-6; } 155 template<> inline float test_precision<std::complex<float> >() { return test_precision<float>(); } 156 template<> inline double test_precision<std::complex<double> >() { return test_precision<double>(); } 157 template<> inline long double test_precision<long double>() { return 1e-6; } 158 159 inline bool test_ei_isApprox(const int& a, const int& b) 160 { return ei_isApprox(a, b, test_precision<int>()); } 161 inline bool test_ei_isMuchSmallerThan(const int& a, const int& b) 162 { return ei_isMuchSmallerThan(a, b, test_precision<int>()); } 163 inline bool test_ei_isApproxOrLessThan(const int& a, const int& b) 164 { return ei_isApproxOrLessThan(a, b, test_precision<int>()); } 165 166 inline bool test_ei_isApprox(const float& a, const float& b) 167 { return ei_isApprox(a, b, test_precision<float>()); } 168 inline bool test_ei_isMuchSmallerThan(const float& a, const float& b) 169 { return ei_isMuchSmallerThan(a, b, test_precision<float>()); } 170 inline bool test_ei_isApproxOrLessThan(const float& a, const float& b) 171 { return ei_isApproxOrLessThan(a, b, test_precision<float>()); } 172 173 inline bool test_ei_isApprox(const double& a, const double& b) 174 { return ei_isApprox(a, b, test_precision<double>()); } 175 inline bool test_ei_isMuchSmallerThan(const double& a, const double& b) 176 { return ei_isMuchSmallerThan(a, b, test_precision<double>()); } 177 inline bool test_ei_isApproxOrLessThan(const double& a, const double& b) 178 { return ei_isApproxOrLessThan(a, b, test_precision<double>()); } 179 180 inline bool test_ei_isApprox(const std::complex<float>& a, const std::complex<float>& b) 181 { return ei_isApprox(a, b, test_precision<std::complex<float> >()); } 182 inline bool test_ei_isMuchSmallerThan(const std::complex<float>& a, const std::complex<float>& b) 183 { return ei_isMuchSmallerThan(a, b, test_precision<std::complex<float> >()); } 184 185 inline bool test_ei_isApprox(const std::complex<double>& a, const std::complex<double>& b) 186 { return ei_isApprox(a, b, test_precision<std::complex<double> >()); } 187 inline bool test_ei_isMuchSmallerThan(const std::complex<double>& a, const std::complex<double>& b) 188 { return ei_isMuchSmallerThan(a, b, test_precision<std::complex<double> >()); } 189 190 inline bool test_ei_isApprox(const long double& a, const long double& b) 191 { return ei_isApprox(a, b, test_precision<long double>()); } 192 inline bool test_ei_isMuchSmallerThan(const long double& a, const long double& b) 193 { return ei_isMuchSmallerThan(a, b, test_precision<long double>()); } 194 inline bool test_ei_isApproxOrLessThan(const long double& a, const long double& b) 195 { return ei_isApproxOrLessThan(a, b, test_precision<long double>()); } 196 197 template<typename Type1, typename Type2> 198 inline bool test_ei_isApprox(const Type1& a, const Type2& b) 199 { 200 return a.isApprox(b, test_precision<typename Type1::Scalar>()); 201 } 202 203 template<typename Derived1, typename Derived2> 204 inline bool test_ei_isMuchSmallerThan(const MatrixBase<Derived1>& m1, 205 const MatrixBase<Derived2>& m2) 206 { 207 return m1.isMuchSmallerThan(m2, test_precision<typename ei_traits<Derived1>::Scalar>()); 208 } 209 210 template<typename Derived> 211 inline bool test_ei_isMuchSmallerThan(const MatrixBase<Derived>& m, 212 const typename NumTraits<typename ei_traits<Derived>::Scalar>::Real& s) 213 { 214 return m.isMuchSmallerThan(s, test_precision<typename ei_traits<Derived>::Scalar>()); 215 } 216 217 } // end namespace Eigen 218 219 template<typename T> struct GetDifferentType; 220 221 template<> struct GetDifferentType<float> { typedef double type; }; 222 template<> struct GetDifferentType<double> { typedef float type; }; 223 template<typename T> struct GetDifferentType<std::complex<T> > 224 { typedef std::complex<typename GetDifferentType<T>::type> type; }; 225 226 // forward declaration of the main test function 227 void EI_PP_CAT(test_,EIGEN_TEST_FUNC)(); 228 229 using namespace Eigen; 230 231 #ifdef EIGEN_TEST_PART_1 232 #define CALL_SUBTEST_1(FUNC) CALL_SUBTEST(FUNC) 233 #else 234 #define CALL_SUBTEST_1(FUNC) 235 #endif 236 237 #ifdef EIGEN_TEST_PART_2 238 #define CALL_SUBTEST_2(FUNC) CALL_SUBTEST(FUNC) 239 #else 240 #define CALL_SUBTEST_2(FUNC) 241 #endif 242 243 #ifdef EIGEN_TEST_PART_3 244 #define CALL_SUBTEST_3(FUNC) CALL_SUBTEST(FUNC) 245 #else 246 #define CALL_SUBTEST_3(FUNC) 247 #endif 248 249 #ifdef EIGEN_TEST_PART_4 250 #define CALL_SUBTEST_4(FUNC) CALL_SUBTEST(FUNC) 251 #else 252 #define CALL_SUBTEST_4(FUNC) 253 #endif 254 255 #ifdef EIGEN_TEST_PART_5 256 #define CALL_SUBTEST_5(FUNC) CALL_SUBTEST(FUNC) 257 #else 258 #define CALL_SUBTEST_5(FUNC) 259 #endif 260 261 #ifdef EIGEN_TEST_PART_6 262 #define CALL_SUBTEST_6(FUNC) CALL_SUBTEST(FUNC) 263 #else 264 #define CALL_SUBTEST_6(FUNC) 265 #endif 266 267 #ifdef EIGEN_TEST_PART_7 268 #define CALL_SUBTEST_7(FUNC) CALL_SUBTEST(FUNC) 269 #else 270 #define CALL_SUBTEST_7(FUNC) 271 #endif 272 273 #ifdef EIGEN_TEST_PART_8 274 #define CALL_SUBTEST_8(FUNC) CALL_SUBTEST(FUNC) 275 #else 276 #define CALL_SUBTEST_8(FUNC) 277 #endif 278 279 #ifdef EIGEN_TEST_PART_9 280 #define CALL_SUBTEST_9(FUNC) CALL_SUBTEST(FUNC) 281 #else 282 #define CALL_SUBTEST_9(FUNC) 283 #endif 284 285 #ifdef EIGEN_TEST_PART_10 286 #define CALL_SUBTEST_10(FUNC) CALL_SUBTEST(FUNC) 287 #else 288 #define CALL_SUBTEST_10(FUNC) 289 #endif 290 291 #ifdef EIGEN_TEST_PART_11 292 #define CALL_SUBTEST_11(FUNC) CALL_SUBTEST(FUNC) 293 #else 294 #define CALL_SUBTEST_11(FUNC) 295 #endif 296 297 #ifdef EIGEN_TEST_PART_12 298 #define CALL_SUBTEST_12(FUNC) CALL_SUBTEST(FUNC) 299 #else 300 #define CALL_SUBTEST_12(FUNC) 301 #endif 302 303 #ifdef EIGEN_TEST_PART_13 304 #define CALL_SUBTEST_13(FUNC) CALL_SUBTEST(FUNC) 305 #else 306 #define CALL_SUBTEST_13(FUNC) 307 #endif 308 309 #ifdef EIGEN_TEST_PART_14 310 #define CALL_SUBTEST_14(FUNC) CALL_SUBTEST(FUNC) 311 #else 312 #define CALL_SUBTEST_14(FUNC) 313 #endif 314 315 #ifdef EIGEN_TEST_PART_15 316 #define CALL_SUBTEST_15(FUNC) CALL_SUBTEST(FUNC) 317 #else 318 #define CALL_SUBTEST_15(FUNC) 319 #endif 320 321 #ifdef EIGEN_TEST_PART_16 322 #define CALL_SUBTEST_16(FUNC) CALL_SUBTEST(FUNC) 323 #else 324 #define CALL_SUBTEST_16(FUNC) 325 #endif 326 327 328 329 int main(int argc, char *argv[]) 330 { 331 bool has_set_repeat = false; 332 bool has_set_seed = false; 333 bool need_help = false; 334 unsigned int seed = 0; 335 int repeat = DEFAULT_REPEAT; 336 337 for(int i = 1; i < argc; i++) 338 { 339 if(argv[i][0] == 'r') 340 { 341 if(has_set_repeat) 342 { 343 std::cout << "Argument " << argv[i] << " conflicting with a former argument" << std::endl; 344 return 1; 345 } 346 repeat = std::atoi(argv[i]+1); 347 has_set_repeat = true; 348 if(repeat <= 0) 349 { 350 std::cout << "Invalid \'repeat\' value " << argv[i]+1 << std::endl; 351 return 1; 352 } 353 } 354 else if(argv[i][0] == 's') 355 { 356 if(has_set_seed) 357 { 358 std::cout << "Argument " << argv[i] << " conflicting with a former argument" << std::endl; 359 return 1; 360 } 361 seed = int(std::strtoul(argv[i]+1, 0, 10)); 362 has_set_seed = true; 363 bool ok = seed!=0; 364 if(!ok) 365 { 366 std::cout << "Invalid \'seed\' value " << argv[i]+1 << std::endl; 367 return 1; 368 } 369 } 370 else 371 { 372 need_help = true; 373 } 374 } 375 376 if(need_help) 377 { 378 std::cout << "This test application takes the following optional arguments:" << std::endl; 379 std::cout << " rN Repeat each test N times (default: " << DEFAULT_REPEAT << ")" << std::endl; 380 std::cout << " sN Use N as seed for random numbers (default: based on current time)" << std::endl; 381 return 1; 382 } 383 384 if(!has_set_seed) seed = (unsigned int) std::time(NULL); 385 if(!has_set_repeat) repeat = DEFAULT_REPEAT; 386 387 std::cout << "Initializing random number generator with seed " << seed << std::endl; 388 std::srand(seed); 389 std::cout << "Repeating each test " << repeat << " times" << std::endl; 390 391 Eigen::g_repeat = repeat; 392 Eigen::g_test_stack.push_back(EI_PP_MAKE_STRING(EIGEN_TEST_FUNC)); 393 394 EI_PP_CAT(test_,EIGEN_TEST_FUNC)(); 395 return 0; 396 } 397 398 399 400