You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

399 lines
13 KiB

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