main.h
Go to the documentation of this file.
00001 // This file is part of Eigen, a lightweight C++ template library
00002 // for linear algebra.
00003 //
00004 // Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
00005 // Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
00006 //
00007 // Eigen is free software; you can redistribute it and/or
00008 // modify it under the terms of the GNU Lesser General Public
00009 // License as published by the Free Software Foundation; either
00010 // version 3 of the License, or (at your option) any later version.
00011 //
00012 // Alternatively, you can redistribute it and/or
00013 // modify it under the terms of the GNU General Public License as
00014 // published by the Free Software Foundation; either version 2 of
00015 // the License, or (at your option) any later version.
00016 //
00017 // Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
00018 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00019 // FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
00020 // GNU General Public License for more details.
00021 //
00022 // You should have received a copy of the GNU Lesser General Public
00023 // License and a copy of the GNU General Public License along with
00024 // Eigen. If not, see <http://www.gnu.org/licenses/>.
00025 
00026 #include <cstdlib>
00027 #include <cerrno>
00028 #include <ctime>
00029 #include <iostream>
00030 #include <string>
00031 #include <vector>
00032 #include <typeinfo>
00033 
00034 #ifdef NDEBUG
00035 #undef NDEBUG
00036 #endif
00037 
00038 // bounds integer values for AltiVec
00039 #ifdef __ALTIVEC__
00040 #define EIGEN_MAKING_DOCS
00041 #endif
00042 
00043 #ifndef EIGEN_TEST_FUNC
00044 #error EIGEN_TEST_FUNC must be defined
00045 #endif
00046 
00047 #define DEFAULT_REPEAT 10
00048 
00049 #ifdef __ICC
00050 // disable warning #279: controlling expression is constant
00051 #pragma warning disable 279
00052 #endif
00053 
00054 namespace Eigen
00055 {
00056   static std::vector<std::string> g_test_stack;
00057   static int g_repeat;
00058   static unsigned int g_seed;
00059   static bool g_has_set_repeat, g_has_set_seed;
00060 }
00061 
00062 #define EI_PP_MAKE_STRING2(S) #S
00063 #define EI_PP_MAKE_STRING(S) EI_PP_MAKE_STRING2(S)
00064 
00065 #define EIGEN_DEFAULT_IO_FORMAT IOFormat(4, 0, "  ", "\n", "", "", "", "")
00066 
00067 #ifndef EIGEN_NO_ASSERTION_CHECKING
00068 
00069   namespace Eigen
00070   {
00071     static const bool should_raise_an_assert = false;
00072 
00073     // Used to avoid to raise two exceptions at a time in which
00074     // case the exception is not properly caught.
00075     // This may happen when a second exceptions is triggered in a destructor.
00076     static bool no_more_assert = false;
00077     static bool report_on_cerr_on_assert_failure = true;
00078 
00079     struct eigen_assert_exception
00080     {
00081       eigen_assert_exception(void) {}
00082       ~eigen_assert_exception() { Eigen::no_more_assert = false; }
00083     };
00084   }
00085   // If EIGEN_DEBUG_ASSERTS is defined and if no assertion is triggered while
00086   // one should have been, then the list of excecuted assertions is printed out.
00087   //
00088   // EIGEN_DEBUG_ASSERTS is not enabled by default as it
00089   // significantly increases the compilation time
00090   // and might even introduce side effects that would hide
00091   // some memory errors.
00092   #ifdef EIGEN_DEBUG_ASSERTS
00093 
00094     namespace Eigen
00095     {
00096       namespace internal
00097       {
00098         static bool push_assert = false;
00099       }
00100       static std::vector<std::string> eigen_assert_list;
00101     }
00102     #define eigen_assert(a)                       \
00103       if( (!(a)) && (!no_more_assert) )     \
00104       { \
00105         if(report_on_cerr_on_assert_failure) \
00106           std::cerr <<  #a << " " __FILE__ << "(" << __LINE__ << ")\n"; \
00107         Eigen::no_more_assert = true;       \
00108         throw Eigen::eigen_assert_exception(); \
00109       }                                     \
00110       else if (Eigen::internal::push_assert)       \
00111       {                                     \
00112         eigen_assert_list.push_back(std::string(EI_PP_MAKE_STRING(__FILE__)" ("EI_PP_MAKE_STRING(__LINE__)") : "#a) ); \
00113       }
00114 
00115     #define VERIFY_RAISES_ASSERT(a)                                                   \
00116       {                                                                               \
00117         Eigen::no_more_assert = false;                                                \
00118         Eigen::eigen_assert_list.clear();                                                \
00119         Eigen::internal::push_assert = true;                                                 \
00120         Eigen::report_on_cerr_on_assert_failure = false;                              \
00121         try {                                                                         \
00122           a;                                                                          \
00123           std::cerr << "One of the following asserts should have been triggered:\n";  \
00124           for (uint ai=0 ; ai<eigen_assert_list.size() ; ++ai)                           \
00125             std::cerr << "  " << eigen_assert_list[ai] << "\n";                          \
00126           VERIFY(Eigen::should_raise_an_assert && # a);                               \
00127         } catch (Eigen::eigen_assert_exception) {                                        \
00128           Eigen::internal::push_assert = false; VERIFY(true);                                \
00129         }                                                                             \
00130         Eigen::report_on_cerr_on_assert_failure = true;                               \
00131         Eigen::internal::push_assert = false;                                                \
00132       }
00133 
00134   #else // EIGEN_DEBUG_ASSERTS
00135     // see bug 89. The copy_bool here is working around a bug in gcc <= 4.3
00136     #define eigen_assert(a) \
00137       if( (!Eigen::internal::copy_bool(a)) && (!no_more_assert) )\
00138       {                                       \
00139         Eigen::no_more_assert = true;         \
00140         if(report_on_cerr_on_assert_failure)  \
00141           eigen_plain_assert(a);              \
00142         else                                  \
00143           throw Eigen::eigen_assert_exception(); \
00144       }
00145     #define VERIFY_RAISES_ASSERT(a) {                             \
00146         Eigen::no_more_assert = false;                            \
00147         Eigen::report_on_cerr_on_assert_failure = false;          \
00148         try {                                                     \
00149           a;                                                      \
00150           VERIFY(Eigen::should_raise_an_assert && # a);           \
00151         }                                                         \
00152         catch (Eigen::eigen_assert_exception&) { VERIFY(true); }     \
00153         Eigen::report_on_cerr_on_assert_failure = true;           \
00154       }
00155 
00156   #endif // EIGEN_DEBUG_ASSERTS
00157 
00158   #define EIGEN_USE_CUSTOM_ASSERT
00159 
00160 #else // EIGEN_NO_ASSERTION_CHECKING
00161 
00162   #define VERIFY_RAISES_ASSERT(a) {}
00163 
00164 #endif // EIGEN_NO_ASSERTION_CHECKING
00165 
00166 
00167 #define EIGEN_INTERNAL_DEBUGGING
00168 #include <Eigen/QR> // required for createRandomPIMatrixOfRank
00169 
00170 static void verify_impl(bool condition, const char *testname, const char *file, int line, const char *condition_as_string)
00171 {
00172   if (!condition)
00173   {
00174     std::cerr << "Test " << testname << " failed in " << file << " (" << line << ")" \
00175       << std::endl << "    " << condition_as_string << std::endl << std::endl; \
00176     abort();
00177   }
00178 }
00179 
00180 #define VERIFY(a) verify_impl(a, g_test_stack.back().c_str(), __FILE__, __LINE__, EI_PP_MAKE_STRING(a))
00181 
00182 #define VERIFY_IS_EQUAL(a, b) VERIFY(test_is_equal(a, b))
00183 #define VERIFY_IS_APPROX(a, b) VERIFY(test_isApprox(a, b))
00184 #define VERIFY_IS_NOT_APPROX(a, b) VERIFY(!test_isApprox(a, b))
00185 #define VERIFY_IS_MUCH_SMALLER_THAN(a, b) VERIFY(test_isMuchSmallerThan(a, b))
00186 #define VERIFY_IS_NOT_MUCH_SMALLER_THAN(a, b) VERIFY(!test_isMuchSmallerThan(a, b))
00187 #define VERIFY_IS_APPROX_OR_LESS_THAN(a, b) VERIFY(test_isApproxOrLessThan(a, b))
00188 #define VERIFY_IS_NOT_APPROX_OR_LESS_THAN(a, b) VERIFY(!test_isApproxOrLessThan(a, b))
00189 
00190 #define VERIFY_IS_UNITARY(a) VERIFY(test_isUnitary(a))
00191 
00192 #define CALL_SUBTEST(FUNC) do { \
00193     g_test_stack.push_back(EI_PP_MAKE_STRING(FUNC)); \
00194     FUNC; \
00195     g_test_stack.pop_back(); \
00196   } while (0)
00197 
00198 #ifdef EIGEN_TEST_PART_1
00199 #define CALL_SUBTEST_1(FUNC) CALL_SUBTEST(FUNC)
00200 #else
00201 #define CALL_SUBTEST_1(FUNC)
00202 #endif
00203 
00204 #ifdef EIGEN_TEST_PART_2
00205 #define CALL_SUBTEST_2(FUNC) CALL_SUBTEST(FUNC)
00206 #else
00207 #define CALL_SUBTEST_2(FUNC)
00208 #endif
00209 
00210 #ifdef EIGEN_TEST_PART_3
00211 #define CALL_SUBTEST_3(FUNC) CALL_SUBTEST(FUNC)
00212 #else
00213 #define CALL_SUBTEST_3(FUNC)
00214 #endif
00215 
00216 #ifdef EIGEN_TEST_PART_4
00217 #define CALL_SUBTEST_4(FUNC) CALL_SUBTEST(FUNC)
00218 #else
00219 #define CALL_SUBTEST_4(FUNC)
00220 #endif
00221 
00222 #ifdef EIGEN_TEST_PART_5
00223 #define CALL_SUBTEST_5(FUNC) CALL_SUBTEST(FUNC)
00224 #else
00225 #define CALL_SUBTEST_5(FUNC)
00226 #endif
00227 
00228 #ifdef EIGEN_TEST_PART_6
00229 #define CALL_SUBTEST_6(FUNC) CALL_SUBTEST(FUNC)
00230 #else
00231 #define CALL_SUBTEST_6(FUNC)
00232 #endif
00233 
00234 #ifdef EIGEN_TEST_PART_7
00235 #define CALL_SUBTEST_7(FUNC) CALL_SUBTEST(FUNC)
00236 #else
00237 #define CALL_SUBTEST_7(FUNC)
00238 #endif
00239 
00240 #ifdef EIGEN_TEST_PART_8
00241 #define CALL_SUBTEST_8(FUNC) CALL_SUBTEST(FUNC)
00242 #else
00243 #define CALL_SUBTEST_8(FUNC)
00244 #endif
00245 
00246 #ifdef EIGEN_TEST_PART_9
00247 #define CALL_SUBTEST_9(FUNC) CALL_SUBTEST(FUNC)
00248 #else
00249 #define CALL_SUBTEST_9(FUNC)
00250 #endif
00251 
00252 #ifdef EIGEN_TEST_PART_10
00253 #define CALL_SUBTEST_10(FUNC) CALL_SUBTEST(FUNC)
00254 #else
00255 #define CALL_SUBTEST_10(FUNC)
00256 #endif
00257 
00258 #ifdef EIGEN_TEST_PART_11
00259 #define CALL_SUBTEST_11(FUNC) CALL_SUBTEST(FUNC)
00260 #else
00261 #define CALL_SUBTEST_11(FUNC)
00262 #endif
00263 
00264 #ifdef EIGEN_TEST_PART_12
00265 #define CALL_SUBTEST_12(FUNC) CALL_SUBTEST(FUNC)
00266 #else
00267 #define CALL_SUBTEST_12(FUNC)
00268 #endif
00269 
00270 #ifdef EIGEN_TEST_PART_13
00271 #define CALL_SUBTEST_13(FUNC) CALL_SUBTEST(FUNC)
00272 #else
00273 #define CALL_SUBTEST_13(FUNC)
00274 #endif
00275 
00276 #ifdef EIGEN_TEST_PART_14
00277 #define CALL_SUBTEST_14(FUNC) CALL_SUBTEST(FUNC)
00278 #else
00279 #define CALL_SUBTEST_14(FUNC)
00280 #endif
00281 
00282 #ifdef EIGEN_TEST_PART_15
00283 #define CALL_SUBTEST_15(FUNC) CALL_SUBTEST(FUNC)
00284 #else
00285 #define CALL_SUBTEST_15(FUNC)
00286 #endif
00287 
00288 #ifdef EIGEN_TEST_PART_16
00289 #define CALL_SUBTEST_16(FUNC) CALL_SUBTEST(FUNC)
00290 #else
00291 #define CALL_SUBTEST_16(FUNC)
00292 #endif
00293 
00294 namespace Eigen {
00295 
00296 template<typename T> inline typename NumTraits<T>::Real test_precision() { return NumTraits<T>::dummy_precision(); }
00297 template<> inline float test_precision<float>() { return 1e-3f; }
00298 template<> inline double test_precision<double>() { return 1e-6; }
00299 template<> inline float test_precision<std::complex<float> >() { return test_precision<float>(); }
00300 template<> inline double test_precision<std::complex<double> >() { return test_precision<double>(); }
00301 template<> inline long double test_precision<long double>() { return 1e-6; }
00302 
00303 inline bool test_isApprox(const int& a, const int& b)
00304 { return internal::isApprox(a, b, test_precision<int>()); }
00305 inline bool test_isMuchSmallerThan(const int& a, const int& b)
00306 { return internal::isMuchSmallerThan(a, b, test_precision<int>()); }
00307 inline bool test_isApproxOrLessThan(const int& a, const int& b)
00308 { return internal::isApproxOrLessThan(a, b, test_precision<int>()); }
00309 
00310 inline bool test_isApprox(const float& a, const float& b)
00311 { return internal::isApprox(a, b, test_precision<float>()); }
00312 inline bool test_isMuchSmallerThan(const float& a, const float& b)
00313 { return internal::isMuchSmallerThan(a, b, test_precision<float>()); }
00314 inline bool test_isApproxOrLessThan(const float& a, const float& b)
00315 { return internal::isApproxOrLessThan(a, b, test_precision<float>()); }
00316 inline bool test_isApprox(const double& a, const double& b)
00317 { return internal::isApprox(a, b, test_precision<double>()); }
00318 
00319 inline bool test_isMuchSmallerThan(const double& a, const double& b)
00320 { return internal::isMuchSmallerThan(a, b, test_precision<double>()); }
00321 inline bool test_isApproxOrLessThan(const double& a, const double& b)
00322 { return internal::isApproxOrLessThan(a, b, test_precision<double>()); }
00323 
00324 inline bool test_isApprox(const std::complex<float>& a, const std::complex<float>& b)
00325 { return internal::isApprox(a, b, test_precision<std::complex<float> >()); }
00326 inline bool test_isMuchSmallerThan(const std::complex<float>& a, const std::complex<float>& b)
00327 { return internal::isMuchSmallerThan(a, b, test_precision<std::complex<float> >()); }
00328 
00329 inline bool test_isApprox(const std::complex<double>& a, const std::complex<double>& b)
00330 { return internal::isApprox(a, b, test_precision<std::complex<double> >()); }
00331 inline bool test_isMuchSmallerThan(const std::complex<double>& a, const std::complex<double>& b)
00332 { return internal::isMuchSmallerThan(a, b, test_precision<std::complex<double> >()); }
00333 
00334 inline bool test_isApprox(const long double& a, const long double& b)
00335 {
00336     bool ret = internal::isApprox(a, b, test_precision<long double>());
00337     if (!ret) std::cerr
00338         << std::endl << "    actual   = " << a
00339         << std::endl << "    expected = " << b << std::endl << std::endl;
00340     return ret;
00341 }
00342 
00343 inline bool test_isMuchSmallerThan(const long double& a, const long double& b)
00344 { return internal::isMuchSmallerThan(a, b, test_precision<long double>()); }
00345 inline bool test_isApproxOrLessThan(const long double& a, const long double& b)
00346 { return internal::isApproxOrLessThan(a, b, test_precision<long double>()); }
00347 
00348 template<typename Type1, typename Type2>
00349 inline bool test_isApprox(const Type1& a, const Type2& b)
00350 {
00351   return a.isApprox(b, test_precision<typename Type1::Scalar>());
00352 }
00353 
00354 // The idea behind this function is to compare the two scalars a and b where
00355 // the scalar ref is a hint about the expected order of magnitude of a and b.
00356 // Therefore, if for some reason a and b are very small compared to ref,
00357 // we won't issue a false negative.
00358 // This test could be: abs(a-b) <= eps * ref
00359 // However, it seems that simply comparing a+ref and b+ref is more sensitive to true error.
00360 template<typename Scalar,typename ScalarRef>
00361 inline bool test_isApproxWithRef(const Scalar& a, const Scalar& b, const ScalarRef& ref)
00362 {
00363   return test_isApprox(a+ref, b+ref);
00364 }
00365 
00366 template<typename Derived1, typename Derived2>
00367 inline bool test_isMuchSmallerThan(const MatrixBase<Derived1>& m1,
00368                                    const MatrixBase<Derived2>& m2)
00369 {
00370   return m1.isMuchSmallerThan(m2, test_precision<typename internal::traits<Derived1>::Scalar>());
00371 }
00372 
00373 template<typename Derived>
00374 inline bool test_isMuchSmallerThan(const MatrixBase<Derived>& m,
00375                                    const typename NumTraits<typename internal::traits<Derived>::Scalar>::Real& s)
00376 {
00377   return m.isMuchSmallerThan(s, test_precision<typename internal::traits<Derived>::Scalar>());
00378 }
00379 
00380 template<typename Derived>
00381 inline bool test_isUnitary(const MatrixBase<Derived>& m)
00382 {
00383   return m.isUnitary(test_precision<typename internal::traits<Derived>::Scalar>());
00384 }
00385 
00386 template<typename T, typename U>
00387 bool test_is_equal(const T& actual, const U& expected)
00388 {
00389     if (actual==expected)
00390         return true;
00391     // false:
00392     std::cerr
00393         << std::endl << "    actual   = " << actual
00394         << std::endl << "    expected = " << expected << std::endl << std::endl;
00395     return false;
00396 }
00397 
00403 template<typename MatrixType>
00404 void createRandomPIMatrixOfRank(typename MatrixType::Index desired_rank, typename MatrixType::Index rows, typename MatrixType::Index cols, MatrixType& m)
00405 {
00406   typedef typename internal::traits<MatrixType>::Index Index;
00407   typedef typename internal::traits<MatrixType>::Scalar Scalar;
00408   enum { Rows = MatrixType::RowsAtCompileTime, Cols = MatrixType::ColsAtCompileTime };
00409 
00410   typedef Matrix<Scalar, Dynamic, 1> VectorType;
00411   typedef Matrix<Scalar, Rows, Rows> MatrixAType;
00412   typedef Matrix<Scalar, Cols, Cols> MatrixBType;
00413 
00414   if(desired_rank == 0)
00415   {
00416     m.setZero(rows,cols);
00417     return;
00418   }
00419 
00420   if(desired_rank == 1)
00421   {
00422     // here we normalize the vectors to get a partial isometry
00423     m = VectorType::Random(rows).normalized() * VectorType::Random(cols).normalized().transpose();
00424     return;
00425   }
00426 
00427   MatrixAType a = MatrixAType::Random(rows,rows);
00428   MatrixType d = MatrixType::Identity(rows,cols);
00429   MatrixBType  b = MatrixBType::Random(cols,cols);
00430 
00431   // set the diagonal such that only desired_rank non-zero entries reamain
00432   const Index diag_size = std::min(d.rows(),d.cols());
00433   if(diag_size != desired_rank)
00434     d.diagonal().segment(desired_rank, diag_size-desired_rank) = VectorType::Zero(diag_size-desired_rank);
00435 
00436   HouseholderQR<MatrixAType> qra(a);
00437   HouseholderQR<MatrixBType> qrb(b);
00438   m = qra.householderQ() * d * qrb.householderQ();
00439 }
00440 
00441 } // end namespace Eigen
00442 
00443 template<typename T> struct GetDifferentType;
00444 
00445 template<> struct GetDifferentType<float> { typedef double type; };
00446 template<> struct GetDifferentType<double> { typedef float type; };
00447 template<typename T> struct GetDifferentType<std::complex<T> >
00448 { typedef std::complex<typename GetDifferentType<T>::type> type; };
00449 
00450 template<typename T> std::string type_name() { return "other"; }
00451 template<> std::string type_name<float>() { return "float"; }
00452 template<> std::string type_name<double>() { return "double"; }
00453 template<> std::string type_name<int>() { return "int"; }
00454 template<> std::string type_name<std::complex<float> >() { return "complex<float>"; }
00455 template<> std::string type_name<std::complex<double> >() { return "complex<double>"; }
00456 template<> std::string type_name<std::complex<int> >() { return "complex<int>"; }
00457 
00458 // forward declaration of the main test function
00459 void EIGEN_CAT(test_,EIGEN_TEST_FUNC)();
00460 
00461 using namespace Eigen;
00462 
00463 void set_repeat_from_string(const char *str)
00464 {
00465   errno = 0;
00466   g_repeat = int(strtoul(str, 0, 10));
00467   if(errno || g_repeat <= 0)
00468   {
00469     std::cout << "Invalid repeat value " << str << std::endl;
00470     exit(EXIT_FAILURE);
00471   }
00472   g_has_set_repeat = true;
00473 }
00474 
00475 void set_seed_from_string(const char *str)
00476 {
00477   errno = 0;
00478   g_seed = strtoul(str, 0, 10);
00479   if(errno || g_seed == 0)
00480   {
00481     std::cout << "Invalid seed value " << str << std::endl;
00482     exit(EXIT_FAILURE);
00483   }
00484   g_has_set_seed = true;
00485 }
00486 
00487 int main(int argc, char *argv[])
00488 {
00489     g_has_set_repeat = false;
00490     g_has_set_seed = false;
00491     bool need_help = false;
00492 
00493     for(int i = 1; i < argc; i++)
00494     {
00495       if(argv[i][0] == 'r')
00496       {
00497         if(g_has_set_repeat)
00498         {
00499           std::cout << "Argument " << argv[i] << " conflicting with a former argument" << std::endl;
00500           return 1;
00501         }
00502         set_repeat_from_string(argv[i]+1);
00503       }
00504       else if(argv[i][0] == 's')
00505       {
00506         if(g_has_set_seed)
00507         {
00508           std::cout << "Argument " << argv[i] << " conflicting with a former argument" << std::endl;
00509           return 1;
00510         }
00511          set_seed_from_string(argv[i]+1);
00512       }
00513       else
00514       {
00515         need_help = true;
00516       }
00517     }
00518 
00519     if(need_help)
00520     {
00521       std::cout << "This test application takes the following optional arguments:" << std::endl;
00522       std::cout << "  rN     Repeat each test N times (default: " << DEFAULT_REPEAT << ")" << std::endl;
00523       std::cout << "  sN     Use N as seed for random numbers (default: based on current time)" << std::endl;
00524       std::cout << std::endl;
00525       std::cout << "If defined, the environment variables EIGEN_REPEAT and EIGEN_SEED" << std::endl;
00526       std::cout << "will be used as default values for these parameters." << std::endl;
00527       return 1;
00528     }
00529 
00530     char *env_EIGEN_REPEAT = getenv("EIGEN_REPEAT");
00531     if(!g_has_set_repeat && env_EIGEN_REPEAT)
00532       set_repeat_from_string(env_EIGEN_REPEAT);
00533     char *env_EIGEN_SEED = getenv("EIGEN_SEED");
00534     if(!g_has_set_seed && env_EIGEN_SEED)
00535       set_seed_from_string(env_EIGEN_SEED);
00536 
00537     if(!g_has_set_seed) g_seed = (unsigned int) time(NULL);
00538     if(!g_has_set_repeat) g_repeat = DEFAULT_REPEAT;
00539 
00540     std::cout << "Initializing random number generator with seed " << g_seed << std::endl;
00541     srand(g_seed);
00542     std::cout << "Repeating each test " << g_repeat << " times" << std::endl;
00543 
00544     Eigen::g_test_stack.push_back(EI_PP_MAKE_STRING(EIGEN_TEST_FUNC));
00545 
00546     EIGEN_CAT(test_,EIGEN_TEST_FUNC)();
00547     return 0;
00548 }


re_vision
Author(s): Dorian Galvez-Lopez
autogenerated on Sun Jan 5 2014 11:31:44