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
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
23namespace 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
149namespace Eigen {
150
151template<typename T> inline typename NumTraits<T>::Real test_precision();
152template<> inline int test_precision<int>() { return 0; }
153template<> inline float test_precision<float>() { return 1e-3f; }
154template<> inline double test_precision<double>() { return 1e-6; }
155template<> inline float test_precision<std::complex<float> >() { return test_precision<float>(); }
156template<> inline double test_precision<std::complex<double> >() { return test_precision<double>(); }
157template<> inline long double test_precision<long double>() { return 1e-6; }
158
159inline bool test_ei_isApprox(const int& a, const int& b)
160{ return ei_isApprox(a, b, test_precision<int>()); }
161inline bool test_ei_isMuchSmallerThan(const int& a, const int& b)
162{ return ei_isMuchSmallerThan(a, b, test_precision<int>()); }
163inline bool test_ei_isApproxOrLessThan(const int& a, const int& b)
164{ return ei_isApproxOrLessThan(a, b, test_precision<int>()); }
165
166inline bool test_ei_isApprox(const float& a, const float& b)
167{ return ei_isApprox(a, b, test_precision<float>()); }
168inline bool test_ei_isMuchSmallerThan(const float& a, const float& b)
169{ return ei_isMuchSmallerThan(a, b, test_precision<float>()); }
170inline bool test_ei_isApproxOrLessThan(const float& a, const float& b)
171{ return ei_isApproxOrLessThan(a, b, test_precision<float>()); }
172
173inline bool test_ei_isApprox(const double& a, const double& b)
174{ return ei_isApprox(a, b, test_precision<double>()); }
175inline bool test_ei_isMuchSmallerThan(const double& a, const double& b)
176{ return ei_isMuchSmallerThan(a, b, test_precision<double>()); }
177inline bool test_ei_isApproxOrLessThan(const double& a, const double& b)
178{ return ei_isApproxOrLessThan(a, b, test_precision<double>()); }
179
180inline 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> >()); }
182inline 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
185inline 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> >()); }
187inline 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
190inline bool test_ei_isApprox(const long double& a, const long double& b)
191{ return ei_isApprox(a, b, test_precision<long double>()); }
192inline bool test_ei_isMuchSmallerThan(const long double& a, const long double& b)
193{ return ei_isMuchSmallerThan(a, b, test_precision<long double>()); }
194inline bool test_ei_isApproxOrLessThan(const long double& a, const long double& b)
195{ return ei_isApproxOrLessThan(a, b, test_precision<long double>()); }
196
197template<typename Type1, typename Type2>
198inline bool test_ei_isApprox(const Type1& a, const Type2& b)
199{
200  return a.isApprox(b, test_precision<typename Type1::Scalar>());
201}
202
203template<typename Derived1, typename Derived2>
204inline 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
210template<typename Derived>
211inline 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
219template<typename T> struct GetDifferentType;
220
221template<> struct GetDifferentType<float> { typedef double type; };
222template<> struct GetDifferentType<double> { typedef float type; };
223template<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
227void EI_PP_CAT(test_,EIGEN_TEST_FUNC)();
228
229using 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
329int 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