Home | History | Annotate | Download | only in eigen2
      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