2007-10-12 13:15:25 +08:00
// This file is part of Eigen, a lightweight C++ template library
2009-05-23 02:25:33 +08:00
// for linear algebra.
2007-09-05 18:42:15 +08:00
//
2008-11-24 21:40:43 +08:00
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
2010-06-25 05:21:58 +08:00
// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
2007-09-05 18:42:15 +08:00
//
2012-07-14 02:42:47 +08:00
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
2007-09-05 18:42:15 +08:00
2007-09-09 17:41:15 +08:00
# include <cstdlib>
2009-12-03 01:07:47 +08:00
# include <cerrno>
2007-09-09 17:41:15 +08:00
# include <ctime>
2008-03-13 02:10:52 +08:00
# include <iostream>
2011-12-09 06:27:10 +08:00
# include <fstream>
2008-05-22 20:18:55 +08:00
# include <string>
2013-02-25 08:46:59 +08:00
# include <sstream>
2008-05-22 20:18:55 +08:00
# include <vector>
2009-07-13 20:55:03 +08:00
# include <typeinfo>
2014-08-29 16:41:05 +08:00
// The following includes of STL headers have to be done _before_ the
// definition of macros min() and max(). The reason is that many STL
// implementations will not work properly as the min and max symbols collide
// with the STL functions std:min() and std::max(). The STL headers may check
// for the macro definition of min/max and issue a warning or undefine the
// macros.
//
// Still, Windows defines min() and max() in windef.h as part of the regular
// Windows system interfaces and many other Windows APIs depend on these
// macros being available. To prevent the macro expansion of min/max and to
// make Eigen compatible with the Windows environment all function calls of
// std::min() and std::max() have to be written with parenthesis around the
// function name.
//
// All STL headers used by Eigen should be included here. Because main.h is
// included before any Eigen header and because the STL headers are guarded
// against multiple inclusions, no STL header will see our own min/max macro
// definitions.
2011-08-19 20:18:05 +08:00
# include <limits>
# include <algorithm>
# include <complex>
# include <deque>
# include <queue>
2014-08-29 16:41:05 +08:00
# include <list>
2015-02-28 05:38:00 +08:00
# if __cplusplus >= 201103L
# include <random>
# ifdef EIGEN_USE_THREADS
# include <future>
# endif
# endif
2011-08-19 20:18:05 +08:00
2014-08-29 16:41:05 +08:00
// To test that all calls from Eigen code to std::min() and std::max() are
// protected by parenthesis against macro expansion, the min()/max() macros
// are defined here and any not-parenthesized min/max call will cause a
// compiler error.
2015-02-28 05:38:00 +08:00
# define min(A,B) please_protect_your_min_with_parentheses
# define max(A,B) please_protect_your_max_with_parentheses
2015-08-14 23:32:34 +08:00
# define isnan(X) please_protect_your_isnan_with_parentheses
# define isinf(X) please_protect_your_isinf_with_parentheses
# define isfinite(X) please_protect_your_isfinite_with_parentheses
2016-03-23 22:37:45 +08:00
# ifdef M_PI
# undef M_PI
# endif
# define M_PI please_use_EIGEN_PI_instead_of_M_PI
2008-05-22 20:18:55 +08:00
2011-10-31 22:44:06 +08:00
# define FORBIDDEN_IDENTIFIER (this_identifier_is_forbidden_to_avoid_clashes) this_identifier_is_forbidden_to_avoid_clashes
// B0 is defined in POSIX header termios.h
# define B0 FORBIDDEN_IDENTIFIER
2014-04-25 17:04:02 +08:00
// Unit tests calling Eigen's blas library must preserve the default blocking size
// to avoid troubles.
# ifndef EIGEN_NO_DEBUG_SMALL_PRODUCT_BLOCKS
2014-04-17 22:27:58 +08:00
# define EIGEN_DEBUG_SMALL_PRODUCT_BLOCKS
2014-04-25 17:04:02 +08:00
# endif
2013-06-25 17:42:04 +08:00
// shuts down ICC's remark #593: variable "XXX" was set but never used
2014-10-24 19:18:23 +08:00
# define TEST_SET_BUT_UNUSED_VARIABLE(X) EIGEN_UNUSED_VARIABLE(X)
2013-06-25 17:42:04 +08:00
2015-06-19 22:38:26 +08:00
# ifdef TEST_ENABLE_TEMPORARY_TRACKING
static long int nb_temporaries ;
inline void on_temporary_creation ( long int size ) {
// here's a great place to set a breakpoint when debugging failures in this test!
if ( size ! = 0 ) nb_temporaries + + ;
}
# define EIGEN_DENSE_STORAGE_CTOR_PLUGIN { on_temporary_creation(size); }
# define VERIFY_EVALUATION_COUNT(XPR,N) {\
nb_temporaries = 0 ; \
XPR ; \
if ( nb_temporaries ! = N ) std : : cerr < < " nb_temporaries == " < < nb_temporaries < < " \n " ; \
VERIFY ( ( # XPR ) & & nb_temporaries = = N ) ; \
}
# endif
2011-03-28 23:39:05 +08:00
// the following file is automatically generated by cmake
# include "split_test_helper.h"
2009-09-02 05:15:30 +08:00
# ifdef NDEBUG
# undef NDEBUG
# endif
2013-07-01 19:47:25 +08:00
// On windows CE, NDEBUG is automatically defined <assert.h> if NDEBUG is not defined.
# ifndef DEBUG
# define DEBUG
# endif
2011-02-24 05:22:53 +08:00
// bounds integer values for AltiVec
2014-08-30 04:03:49 +08:00
# if defined(__ALTIVEC__) || defined(__VSX__)
2011-02-24 05:22:53 +08:00
# define EIGEN_MAKING_DOCS
# endif
2008-05-22 20:18:55 +08:00
# ifndef EIGEN_TEST_FUNC
# error EIGEN_TEST_FUNC must be defined
# endif
2007-09-05 18:42:15 +08:00
2008-04-27 04:28:27 +08:00
# define DEFAULT_REPEAT 10
2007-12-03 16:35:23 +08:00
2008-05-22 20:18:55 +08:00
namespace Eigen
{
static std : : vector < std : : string > g_test_stack ;
2015-03-24 20:39:14 +08:00
// level == 0 <=> abort if test fail
// level >= 1 <=> warning message to std::cerr if test fail
static int g_test_level = 0 ;
2008-05-22 20:18:55 +08:00
static int g_repeat ;
2009-12-03 01:07:47 +08:00
static unsigned int g_seed ;
static bool g_has_set_repeat , g_has_set_seed ;
2008-05-22 20:18:55 +08:00
}
2013-12-04 00:17:53 +08:00
# define TRACK std::cerr << __FILE__ << " " << __LINE__ << std::endl
2014-07-22 18:54:03 +08:00
// #define TRACK while()
2013-12-04 00:17:53 +08:00
2008-05-22 20:18:55 +08:00
# define EI_PP_MAKE_STRING2(S) #S
# define EI_PP_MAKE_STRING(S) EI_PP_MAKE_STRING2(S)
2009-08-15 16:18:05 +08:00
# define EIGEN_DEFAULT_IO_FORMAT IOFormat(4, 0, " ", "\n", "", "", "", "")
2008-05-22 20:18:55 +08:00
2014-08-20 22:39:25 +08:00
# if (defined(_CPPUNWIND) || defined(__EXCEPTIONS)) && !defined(__CUDA_ARCH__)
# define EIGEN_EXCEPTIONS
# endif
2008-03-09 03:02:24 +08:00
# ifndef EIGEN_NO_ASSERTION_CHECKING
namespace Eigen
{
static const bool should_raise_an_assert = false ;
2008-03-13 02:10:52 +08:00
2008-06-02 22:54:52 +08:00
// Used to avoid to raise two exceptions at a time in which
2008-08-31 21:32:29 +08:00
// case the exception is not properly caught.
2010-07-20 18:54:53 +08:00
// This may happen when a second exceptions is triggered in a destructor.
2008-03-13 02:10:52 +08:00
static bool no_more_assert = false ;
2010-05-31 04:00:09 +08:00
static bool report_on_cerr_on_assert_failure = true ;
2008-03-13 02:10:52 +08:00
2010-10-25 22:15:22 +08:00
struct eigen_assert_exception
2008-03-13 02:44:42 +08:00
{
2010-10-25 22:15:22 +08:00
eigen_assert_exception ( void ) { }
~ eigen_assert_exception ( ) { Eigen : : no_more_assert = false ; }
2008-03-13 02:44:42 +08:00
} ;
2008-03-09 03:02:24 +08:00
}
2010-07-20 18:54:53 +08:00
// If EIGEN_DEBUG_ASSERTS is defined and if no assertion is triggered while
2008-03-09 03:02:24 +08:00
// one should have been, then the list of excecuted assertions is printed out.
//
// EIGEN_DEBUG_ASSERTS is not enabled by default as it
// significantly increases the compilation time
// and might even introduce side effects that would hide
// some memory errors.
# ifdef EIGEN_DEBUG_ASSERTS
namespace Eigen
{
2010-11-26 22:21:57 +08:00
namespace internal
{
2011-02-16 21:50:19 +08:00
static bool push_assert = false ;
2010-11-26 22:21:57 +08:00
}
2010-10-25 22:15:22 +08:00
static std : : vector < std : : string > eigen_assert_list ;
2008-03-09 03:02:24 +08:00
}
2010-10-25 22:15:22 +08:00
# define eigen_assert(a) \
2008-03-13 17:51:18 +08:00
if ( ( ! ( a ) ) & & ( ! no_more_assert ) ) \
2010-05-31 04:00:09 +08:00
{ \
if ( report_on_cerr_on_assert_failure ) \
2010-03-08 12:46:26 +08:00
std : : cerr < < # a < < " " __FILE__ < < " ( " < < __LINE__ < < " ) \n " ; \
2008-03-13 17:51:18 +08:00
Eigen : : no_more_assert = true ; \
2014-07-22 19:16:44 +08:00
EIGEN_THROW_X ( Eigen : : eigen_assert_exception ( ) ) ; \
2008-03-13 17:51:18 +08:00
} \
2010-10-25 22:15:22 +08:00
else if ( Eigen : : internal : : push_assert ) \
2008-03-13 17:51:18 +08:00
{ \
2011-11-28 04:27:25 +08:00
eigen_assert_list . push_back ( std : : string ( EI_PP_MAKE_STRING ( __FILE__ ) " ( " EI_PP_MAKE_STRING ( __LINE__ ) " ) : " # a ) ) ; \
2008-03-13 17:51:18 +08:00
}
2014-07-22 19:16:44 +08:00
# ifdef EIGEN_EXCEPTIONS
2010-07-20 18:54:53 +08:00
# define VERIFY_RAISES_ASSERT(a) \
{ \
Eigen : : no_more_assert = false ; \
2015-02-20 16:28:34 +08:00
Eigen : : eigen_assert_list . clear ( ) ; \
Eigen : : internal : : push_assert = true ; \
2010-07-20 18:54:53 +08:00
Eigen : : report_on_cerr_on_assert_failure = false ; \
try { \
a ; \
std : : cerr < < " One of the following asserts should have been triggered: \n " ; \
2015-02-20 16:28:34 +08:00
for ( uint ai = 0 ; ai < eigen_assert_list . size ( ) ; + + ai ) \
std : : cerr < < " " < < eigen_assert_list [ ai ] < < " \n " ; \
2010-07-20 18:54:53 +08:00
VERIFY ( Eigen : : should_raise_an_assert & & # a ) ; \
2015-02-20 16:28:34 +08:00
} catch ( Eigen : : eigen_assert_exception ) { \
Eigen : : internal : : push_assert = false ; VERIFY ( true ) ; \
2010-07-20 18:54:53 +08:00
} \
Eigen : : report_on_cerr_on_assert_failure = true ; \
2015-02-20 16:28:34 +08:00
Eigen : : internal : : push_assert = false ; \
2008-03-13 17:51:18 +08:00
}
2014-07-22 19:16:44 +08:00
# endif //EIGEN_EXCEPTIONS
2008-03-09 03:02:24 +08:00
2013-11-05 22:41:45 +08:00
# elif !defined(__CUDACC__) // EIGEN_DEBUG_ASSERTS
2011-02-16 21:50:19 +08:00
// see bug 89. The copy_bool here is working around a bug in gcc <= 4.3
2010-10-25 22:15:22 +08:00
# define eigen_assert(a) \
2011-02-16 21:50:19 +08:00
if ( ( ! Eigen : : internal : : copy_bool ( a ) ) & & ( ! no_more_assert ) ) \
2010-07-20 18:54:53 +08:00
{ \
Eigen : : no_more_assert = true ; \
if ( report_on_cerr_on_assert_failure ) \
2011-02-16 21:50:19 +08:00
eigen_plain_assert ( a ) ; \
2010-07-20 18:54:53 +08:00
else \
2014-07-22 19:16:44 +08:00
EIGEN_THROW_X ( Eigen : : eigen_assert_exception ( ) ) ; \
2008-03-13 02:10:52 +08:00
}
2014-07-22 19:16:44 +08:00
# ifdef EIGEN_EXCEPTIONS
# define VERIFY_RAISES_ASSERT(a) { \
2008-06-02 22:54:52 +08:00
Eigen : : no_more_assert = false ; \
2010-07-20 18:54:53 +08:00
Eigen : : report_on_cerr_on_assert_failure = false ; \
try { \
a ; \
VERIFY ( Eigen : : should_raise_an_assert & & # a ) ; \
} \
2015-02-20 16:28:34 +08:00
catch ( Eigen : : eigen_assert_exception & ) { VERIFY ( true ) ; } \
2010-07-20 18:54:53 +08:00
Eigen : : report_on_cerr_on_assert_failure = true ; \
2008-03-13 17:51:18 +08:00
}
2014-07-22 19:16:44 +08:00
# endif //EIGEN_EXCEPTIONS
2008-03-09 03:02:24 +08:00
# endif // EIGEN_DEBUG_ASSERTS
2014-07-22 19:16:44 +08:00
# ifndef VERIFY_RAISES_ASSERT
# define VERIFY_RAISES_ASSERT(a) \
2014-08-20 22:39:25 +08:00
std : : cout < < " Can't VERIFY_RAISES_ASSERT( " # a " ) with exceptions disabled \n " ;
2014-07-22 19:16:44 +08:00
# endif
2013-11-05 22:41:45 +08:00
# if !defined(__CUDACC__)
2008-03-26 17:13:11 +08:00
# define EIGEN_USE_CUSTOM_ASSERT
2013-11-05 22:41:45 +08:00
# endif
2008-03-09 03:02:24 +08:00
# else // EIGEN_NO_ASSERTION_CHECKING
# define VERIFY_RAISES_ASSERT(a) {}
# endif // EIGEN_NO_ASSERTION_CHECKING
# define EIGEN_INTERNAL_DEBUGGING
2010-02-24 04:40:24 +08:00
# include <Eigen/QR> // required for createRandomPIMatrixOfRank
2008-03-09 03:02:24 +08:00
2013-06-24 01:11:32 +08:00
inline void verify_impl ( bool condition , const char * testname , const char * file , int line , const char * condition_as_string )
2010-10-29 22:27:20 +08:00
{
if ( ! condition )
{
2015-03-24 20:39:14 +08:00
if ( Eigen : : g_test_level > 0 )
std : : cerr < < " WARNING: " ;
2013-02-25 08:46:59 +08:00
std : : cerr < < " Test " < < testname < < " failed in " < < file < < " ( " < < line < < " ) "
< < std : : endl < < " " < < condition_as_string < < std : : endl ;
std : : cerr < < " Stack: \n " ;
2013-02-28 17:15:19 +08:00
const int test_stack_size = static_cast < int > ( Eigen : : g_test_stack . size ( ) ) ;
for ( int i = test_stack_size - 1 ; i > = 0 ; - - i )
2013-02-25 08:46:59 +08:00
std : : cerr < < " - " < < Eigen : : g_test_stack [ i ] < < " \n " ;
std : : cerr < < " \n " ;
2015-03-24 20:39:14 +08:00
if ( Eigen : : g_test_level = = 0 )
abort ( ) ;
2010-10-29 22:27:20 +08:00
}
}
2012-01-25 22:45:01 +08:00
# define VERIFY(a) ::verify_impl(a, g_test_stack.back().c_str(), __FILE__, __LINE__, EI_PP_MAKE_STRING(a))
2008-05-22 20:18:55 +08:00
2016-04-15 07:44:10 +08:00
# define VERIFY_GE(a, b) ::verify_impl(a >= b, g_test_stack.back().c_str(), __FILE__, __LINE__, EI_PP_MAKE_STRING(a >= b))
# define VERIFY_LE(a, b) ::verify_impl(a <= b, g_test_stack.back().c_str(), __FILE__, __LINE__, EI_PP_MAKE_STRING(a <= b))
2016-05-12 01:40:45 +08:00
# define VERIFY_IS_EQUAL(a, b) VERIFY(test_is_equal(a, b, true))
# define VERIFY_IS_NOT_EQUAL(a, b) VERIFY(test_is_equal(a, b, false))
2015-06-15 21:03:19 +08:00
# define VERIFY_IS_APPROX(a, b) VERIFY(verifyIsApprox(a, b))
2010-10-25 22:15:22 +08:00
# define VERIFY_IS_NOT_APPROX(a, b) VERIFY(!test_isApprox(a, b))
# define VERIFY_IS_MUCH_SMALLER_THAN(a, b) VERIFY(test_isMuchSmallerThan(a, b))
# define VERIFY_IS_NOT_MUCH_SMALLER_THAN(a, b) VERIFY(!test_isMuchSmallerThan(a, b))
# define VERIFY_IS_APPROX_OR_LESS_THAN(a, b) VERIFY(test_isApproxOrLessThan(a, b))
# define VERIFY_IS_NOT_APPROX_OR_LESS_THAN(a, b) VERIFY(!test_isApproxOrLessThan(a, b))
2008-05-22 20:18:55 +08:00
2009-09-01 10:08:43 +08:00
# define VERIFY_IS_UNITARY(a) VERIFY(test_isUnitary(a))
2008-05-22 20:18:55 +08:00
# define CALL_SUBTEST(FUNC) do { \
g_test_stack . push_back ( EI_PP_MAKE_STRING ( FUNC ) ) ; \
FUNC ; \
g_test_stack . pop_back ( ) ; \
} while ( 0 )
2007-12-05 15:22:22 +08:00
2009-10-20 02:40:35 +08:00
2007-12-03 02:32:59 +08:00
namespace Eigen {
2007-09-05 18:42:15 +08:00
2010-07-15 04:50:03 +08:00
template < typename T > inline typename NumTraits < T > : : Real test_precision ( ) { return NumTraits < T > : : dummy_precision ( ) ; }
2008-12-19 04:36:25 +08:00
template < > inline float test_precision < float > ( ) { return 1e-3 f ; }
2008-08-23 01:48:36 +08:00
template < > inline double test_precision < double > ( ) { return 1e-6 ; }
2016-05-06 23:15:12 +08:00
template < > inline long double test_precision < long double > ( ) { return 1e-6l ; }
2007-12-03 18:23:08 +08:00
template < > inline float test_precision < std : : complex < float > > ( ) { return test_precision < float > ( ) ; }
template < > inline double test_precision < std : : complex < double > > ( ) { return test_precision < double > ( ) ; }
2015-07-22 04:22:12 +08:00
template < > inline long double test_precision < std : : complex < long double > > ( ) { return test_precision < long double > ( ) ; }
2007-12-03 18:23:08 +08:00
2010-10-25 22:15:22 +08:00
inline bool test_isApprox ( const int & a , const int & b )
{ return internal : : isApprox ( a , b , test_precision < int > ( ) ) ; }
inline bool test_isMuchSmallerThan ( const int & a , const int & b )
{ return internal : : isMuchSmallerThan ( a , b , test_precision < int > ( ) ) ; }
inline bool test_isApproxOrLessThan ( const int & a , const int & b )
{ return internal : : isApproxOrLessThan ( a , b , test_precision < int > ( ) ) ; }
inline bool test_isApprox ( const float & a , const float & b )
{ return internal : : isApprox ( a , b , test_precision < float > ( ) ) ; }
inline bool test_isMuchSmallerThan ( const float & a , const float & b )
{ return internal : : isMuchSmallerThan ( a , b , test_precision < float > ( ) ) ; }
inline bool test_isApproxOrLessThan ( const float & a , const float & b )
{ return internal : : isApproxOrLessThan ( a , b , test_precision < float > ( ) ) ; }
2016-04-15 01:25:50 +08:00
2010-10-25 22:15:22 +08:00
inline bool test_isApprox ( const double & a , const double & b )
2010-12-17 01:53:02 +08:00
{ return internal : : isApprox ( a , b , test_precision < double > ( ) ) ; }
2010-10-25 22:15:22 +08:00
inline bool test_isMuchSmallerThan ( const double & a , const double & b )
{ return internal : : isMuchSmallerThan ( a , b , test_precision < double > ( ) ) ; }
inline bool test_isApproxOrLessThan ( const double & a , const double & b )
{ return internal : : isApproxOrLessThan ( a , b , test_precision < double > ( ) ) ; }
2008-02-28 20:38:12 +08:00
2013-11-05 22:41:45 +08:00
# ifndef EIGEN_TEST_NO_COMPLEX
2010-10-25 22:15:22 +08:00
inline bool test_isApprox ( const std : : complex < float > & a , const std : : complex < float > & b )
{ return internal : : isApprox ( a , b , test_precision < std : : complex < float > > ( ) ) ; }
inline bool test_isMuchSmallerThan ( const std : : complex < float > & a , const std : : complex < float > & b )
{ return internal : : isMuchSmallerThan ( a , b , test_precision < std : : complex < float > > ( ) ) ; }
2008-02-28 20:38:12 +08:00
2010-10-25 22:15:22 +08:00
inline bool test_isApprox ( const std : : complex < double > & a , const std : : complex < double > & b )
{ return internal : : isApprox ( a , b , test_precision < std : : complex < double > > ( ) ) ; }
inline bool test_isMuchSmallerThan ( const std : : complex < double > & a , const std : : complex < double > & b )
{ return internal : : isMuchSmallerThan ( a , b , test_precision < std : : complex < double > > ( ) ) ; }
2015-07-22 04:22:12 +08:00
2016-03-23 07:53:57 +08:00
# ifndef EIGEN_TEST_NO_LONGDOUBLE
2015-07-22 04:22:12 +08:00
inline bool test_isApprox ( const std : : complex < long double > & a , const std : : complex < long double > & b )
{ return internal : : isApprox ( a , b , test_precision < std : : complex < long double > > ( ) ) ; }
inline bool test_isMuchSmallerThan ( const std : : complex < long double > & a , const std : : complex < long double > & b )
{ return internal : : isMuchSmallerThan ( a , b , test_precision < std : : complex < long double > > ( ) ) ; }
2013-11-05 22:41:45 +08:00
# endif
2016-03-23 07:53:57 +08:00
# endif
2007-12-03 18:23:08 +08:00
2013-11-05 22:41:45 +08:00
# ifndef EIGEN_TEST_NO_LONGDOUBLE
2010-10-25 22:15:22 +08:00
inline bool test_isApprox ( const long double & a , const long double & b )
2010-05-21 08:13:50 +08:00
{
2010-10-25 22:15:22 +08:00
bool ret = internal : : isApprox ( a , b , test_precision < long double > ( ) ) ;
2010-05-21 08:13:50 +08:00
if ( ! ret ) std : : cerr
< < std : : endl < < " actual = " < < a
< < std : : endl < < " expected = " < < b < < std : : endl < < std : : endl ;
return ret ;
}
2010-10-25 22:15:22 +08:00
inline bool test_isMuchSmallerThan ( const long double & a , const long double & b )
{ return internal : : isMuchSmallerThan ( a , b , test_precision < long double > ( ) ) ; }
inline bool test_isApproxOrLessThan ( const long double & a , const long double & b )
{ return internal : : isApproxOrLessThan ( a , b , test_precision < long double > ( ) ) ; }
2013-11-05 22:41:45 +08:00
# endif // EIGEN_TEST_NO_LONGDOUBLE
2008-09-14 19:59:10 +08:00
2016-04-15 01:25:50 +08:00
inline bool test_isApprox ( const half & a , const half & b )
{ return internal : : isApprox ( a , b , test_precision < half > ( ) ) ; }
inline bool test_isMuchSmallerThan ( const half & a , const half & b )
{ return internal : : isMuchSmallerThan ( a , b , test_precision < half > ( ) ) ; }
inline bool test_isApproxOrLessThan ( const half & a , const half & b )
{ return internal : : isApproxOrLessThan ( a , b , test_precision < half > ( ) ) ; }
2015-06-15 21:03:19 +08:00
// test_relative_error returns the relative difference between a and b as a real scalar as used in isApprox.
template < typename T1 , typename T2 >
typename T1 : : RealScalar test_relative_error ( const EigenBase < T1 > & a , const EigenBase < T2 > & b )
{
2015-07-22 04:22:12 +08:00
using std : : sqrt ;
2015-06-15 21:03:19 +08:00
typedef typename T1 : : RealScalar RealScalar ;
typename internal : : nested_eval < T1 , 2 > : : type ea ( a . derived ( ) ) ;
typename internal : : nested_eval < T2 , 2 > : : type eb ( b . derived ( ) ) ;
2015-07-22 04:22:12 +08:00
return sqrt ( RealScalar ( ( ea - eb ) . cwiseAbs2 ( ) . sum ( ) ) / RealScalar ( ( std : : min ) ( eb . cwiseAbs2 ( ) . sum ( ) , ea . cwiseAbs2 ( ) . sum ( ) ) ) ) ;
2015-06-15 21:03:19 +08:00
}
template < typename T1 , typename T2 >
typename T1 : : RealScalar test_relative_error ( const T1 & a , const T2 & b , const typename T1 : : Coefficients * = 0 )
{
return test_relative_error ( a . coeffs ( ) , b . coeffs ( ) ) ;
}
template < typename T1 , typename T2 >
typename T1 : : Scalar test_relative_error ( const T1 & a , const T2 & b , const typename T1 : : MatrixType * = 0 )
{
return test_relative_error ( a . matrix ( ) , b . matrix ( ) ) ;
}
template < typename S , int D >
S test_relative_error ( const Translation < S , D > & a , const Translation < S , D > & b )
{
return test_relative_error ( a . vector ( ) , b . vector ( ) ) ;
}
template < typename S , int D , int O >
S test_relative_error ( const ParametrizedLine < S , D , O > & a , const ParametrizedLine < S , D , O > & b )
{
return ( std : : max ) ( test_relative_error ( a . origin ( ) , b . origin ( ) ) , test_relative_error ( a . origin ( ) , b . origin ( ) ) ) ;
}
template < typename S , int D >
S test_relative_error ( const AlignedBox < S , D > & a , const AlignedBox < S , D > & b )
{
return ( std : : max ) ( test_relative_error ( ( a . min ) ( ) , ( b . min ) ( ) ) , test_relative_error ( ( a . max ) ( ) , ( b . max ) ( ) ) ) ;
}
template < typename Derived > class SparseMatrixBase ;
template < typename T1 , typename T2 >
typename T1 : : RealScalar test_relative_error ( const MatrixBase < T1 > & a , const SparseMatrixBase < T2 > & b )
{
return test_relative_error ( a , b . toDense ( ) ) ;
}
template < typename Derived > class SparseMatrixBase ;
template < typename T1 , typename T2 >
typename T1 : : RealScalar test_relative_error ( const SparseMatrixBase < T1 > & a , const MatrixBase < T2 > & b )
{
return test_relative_error ( a . toDense ( ) , b ) ;
}
template < typename Derived > class SparseMatrixBase ;
template < typename T1 , typename T2 >
typename T1 : : RealScalar test_relative_error ( const SparseMatrixBase < T1 > & a , const SparseMatrixBase < T2 > & b )
{
return test_relative_error ( a . toDense ( ) , b . toDense ( ) ) ;
}
template < typename T1 , typename T2 >
typename NumTraits < T1 > : : Real test_relative_error ( const T1 & a , const T2 & b , typename internal : : enable_if < internal : : is_arithmetic < typename NumTraits < T1 > : : Real > : : value , T1 > : : type * = 0 )
{
typedef typename NumTraits < T1 > : : Real RealScalar ;
2016-04-15 01:25:50 +08:00
return numext : : sqrt ( RealScalar ( numext : : abs2 ( a - b ) ) / RealScalar ( ( numext : : mini ) ( numext : : abs2 ( a ) , numext : : abs2 ( b ) ) ) ) ;
2015-06-15 21:03:19 +08:00
}
template < typename T >
T test_relative_error ( const Rotation2D < T > & a , const Rotation2D < T > & b )
{
return test_relative_error ( a . angle ( ) , b . angle ( ) ) ;
}
template < typename T >
T test_relative_error ( const AngleAxis < T > & a , const AngleAxis < T > & b )
{
return ( std : : max ) ( test_relative_error ( a . angle ( ) , b . angle ( ) ) , test_relative_error ( a . axis ( ) , b . axis ( ) ) ) ;
}
2008-10-26 07:10:21 +08:00
template < typename Type1 , typename Type2 >
2010-10-25 22:15:22 +08:00
inline bool test_isApprox ( const Type1 & a , const Type2 & b )
2007-12-03 18:23:08 +08:00
{
2008-10-26 07:10:21 +08:00
return a . isApprox ( b , test_precision < typename Type1 : : Scalar > ( ) ) ;
2007-12-03 18:23:08 +08:00
}
2015-06-15 21:03:19 +08:00
// get_test_precision is a small wrapper to test_precision allowing to return the scalar precision for either scalars or expressions
template < typename T >
2016-07-20 21:19:17 +08:00
typename NumTraits < typename T : : Scalar > : : Real get_test_precision ( const T * , const typename T : : Scalar * = 0 )
2015-06-15 21:03:19 +08:00
{
return test_precision < typename NumTraits < typename T : : Scalar > : : Real > ( ) ;
}
template < typename T >
2016-07-20 21:19:17 +08:00
typename NumTraits < T > : : Real get_test_precision ( const T * , typename internal : : enable_if < internal : : is_arithmetic < typename NumTraits < T > : : Real > : : value , T > : : type * = 0 )
2015-06-15 21:03:19 +08:00
{
return test_precision < typename NumTraits < T > : : Real > ( ) ;
}
// verifyIsApprox is a wrapper to test_isApprox that outputs the relative difference magnitude if the test fails.
template < typename Type1 , typename Type2 >
inline bool verifyIsApprox ( const Type1 & a , const Type2 & b )
{
bool ret = test_isApprox ( a , b ) ;
if ( ! ret )
{
2016-07-20 21:19:17 +08:00
std : : cerr < < " Difference too large wrt tolerance " < < get_test_precision ( static_cast < Type1 * > ( 0 ) ) < < " , relative error is: " < < test_relative_error ( a , b ) < < std : : endl ;
2015-06-15 21:03:19 +08:00
}
return ret ;
}
2011-02-19 00:39:04 +08:00
// The idea behind this function is to compare the two scalars a and b where
// the scalar ref is a hint about the expected order of magnitude of a and b.
2013-07-16 03:21:14 +08:00
// WARNING: the scalar a and b must be positive
2011-02-19 00:39:04 +08:00
// Therefore, if for some reason a and b are very small compared to ref,
// we won't issue a false negative.
// This test could be: abs(a-b) <= eps * ref
// However, it seems that simply comparing a+ref and b+ref is more sensitive to true error.
template < typename Scalar , typename ScalarRef >
inline bool test_isApproxWithRef ( const Scalar & a , const Scalar & b , const ScalarRef & ref )
{
return test_isApprox ( a + ref , b + ref ) ;
}
2008-03-11 01:23:11 +08:00
template < typename Derived1 , typename Derived2 >
2010-10-25 22:15:22 +08:00
inline bool test_isMuchSmallerThan ( const MatrixBase < Derived1 > & m1 ,
2008-03-11 01:23:11 +08:00
const MatrixBase < Derived2 > & m2 )
2007-12-03 18:23:08 +08:00
{
2010-10-25 22:15:22 +08:00
return m1 . isMuchSmallerThan ( m2 , test_precision < typename internal : : traits < Derived1 > : : Scalar > ( ) ) ;
2007-12-03 18:23:08 +08:00
}
2008-03-11 01:23:11 +08:00
template < typename Derived >
2010-10-25 22:15:22 +08:00
inline bool test_isMuchSmallerThan ( const MatrixBase < Derived > & m ,
const typename NumTraits < typename internal : : traits < Derived > : : Scalar > : : Real & s )
2007-12-03 18:23:08 +08:00
{
2010-10-25 22:15:22 +08:00
return m . isMuchSmallerThan ( s , test_precision < typename internal : : traits < Derived > : : Scalar > ( ) ) ;
2007-12-03 18:23:08 +08:00
}
2009-09-01 10:08:43 +08:00
template < typename Derived >
inline bool test_isUnitary ( const MatrixBase < Derived > & m )
{
2010-10-25 22:15:22 +08:00
return m . isUnitary ( test_precision < typename internal : : traits < Derived > : : Scalar > ( ) ) ;
2009-09-01 10:08:43 +08:00
}
2013-06-28 04:30:46 +08:00
// Forward declaration to avoid ICC warning
2010-05-31 04:00:09 +08:00
template < typename T , typename U >
2016-05-12 01:40:45 +08:00
bool test_is_equal ( const T & actual , const U & expected , bool expect_equal = true ) ;
2013-06-28 04:30:46 +08:00
template < typename T , typename U >
2016-05-12 01:40:45 +08:00
bool test_is_equal ( const T & actual , const U & expected , bool expect_equal )
2010-02-28 00:56:22 +08:00
{
2016-05-12 01:40:45 +08:00
if ( ( actual = = expected ) = = expect_equal )
2010-02-28 00:56:22 +08:00
return true ;
// false:
std : : cerr
2016-05-12 01:40:45 +08:00
< < " \n actual = " < < actual
< < " \n expected " < < ( expect_equal ? " = " : " != " ) < < expected < < " \n \n " ;
2010-02-28 00:56:22 +08:00
return false ;
}
2010-02-24 04:40:24 +08:00
/** Creates a random Partial Isometry matrix of given rank.
*
* A partial isometry is a matrix all of whose singular values are either 0 or 1.
* This is very useful to test rank - revealing algorithms .
*/
2013-06-24 01:11:32 +08:00
// Forward declaration to avoid ICC warning
2009-08-20 13:29:38 +08:00
template < typename MatrixType >
2014-12-05 05:48:53 +08:00
void createRandomPIMatrixOfRank ( Index desired_rank , Index rows , Index cols , MatrixType & m ) ;
2013-06-24 01:11:32 +08:00
template < typename MatrixType >
2014-12-05 05:48:53 +08:00
void createRandomPIMatrixOfRank ( Index desired_rank , Index rows , Index cols , MatrixType & m )
2009-05-17 22:07:12 +08:00
{
2010-10-25 22:15:22 +08:00
typedef typename internal : : traits < MatrixType > : : Scalar Scalar ;
2009-09-28 21:40:18 +08:00
enum { Rows = MatrixType : : RowsAtCompileTime , Cols = MatrixType : : ColsAtCompileTime } ;
2009-08-24 05:33:31 +08:00
typedef Matrix < Scalar , Dynamic , 1 > VectorType ;
2009-09-28 21:40:18 +08:00
typedef Matrix < Scalar , Rows , Rows > MatrixAType ;
typedef Matrix < Scalar , Cols , Cols > MatrixBType ;
2009-05-17 22:07:12 +08:00
2009-12-10 01:43:25 +08:00
if ( desired_rank = = 0 )
{
m . setZero ( rows , cols ) ;
return ;
}
if ( desired_rank = = 1 )
{
2010-02-24 04:40:24 +08:00
// here we normalize the vectors to get a partial isometry
m = VectorType : : Random ( rows ) . normalized ( ) * VectorType : : Random ( cols ) . normalized ( ) . transpose ( ) ;
2009-12-10 01:43:25 +08:00
return ;
}
2009-09-28 21:40:18 +08:00
MatrixAType a = MatrixAType : : Random ( rows , rows ) ;
2009-05-17 22:07:12 +08:00
MatrixType d = MatrixType : : Identity ( rows , cols ) ;
2009-09-28 21:40:18 +08:00
MatrixBType b = MatrixBType : : Random ( cols , cols ) ;
2009-05-17 22:07:12 +08:00
// set the diagonal such that only desired_rank non-zero entries reamain
2011-07-21 17:19:36 +08:00
const Index diag_size = ( std : : min ) ( d . rows ( ) , d . cols ( ) ) ;
2009-12-10 01:43:25 +08:00
if ( diag_size ! = desired_rank )
d . diagonal ( ) . segment ( desired_rank , diag_size - desired_rank ) = VectorType : : Zero ( diag_size - desired_rank ) ;
2009-05-17 22:07:12 +08:00
2009-09-28 21:40:18 +08:00
HouseholderQR < MatrixAType > qra ( a ) ;
HouseholderQR < MatrixBType > qrb ( b ) ;
2009-12-03 00:11:09 +08:00
m = qra . householderQ ( ) * d * qrb . householderQ ( ) ;
2009-05-17 22:07:12 +08:00
}
2013-06-24 01:11:32 +08:00
// Forward declaration to avoid ICC warning
template < typename PermutationVectorType >
2014-12-05 05:48:53 +08:00
void randomPermutationVector ( PermutationVectorType & v , Index size ) ;
2011-10-11 19:45:27 +08:00
template < typename PermutationVectorType >
2014-12-05 05:48:53 +08:00
void randomPermutationVector ( PermutationVectorType & v , Index size )
2011-10-11 19:45:27 +08:00
{
typedef typename PermutationVectorType : : Scalar Scalar ;
v . resize ( size ) ;
for ( Index i = 0 ; i < size ; + + i ) v ( i ) = Scalar ( i ) ;
if ( size = = 1 ) return ;
for ( Index n = 0 ; n < 3 * size ; + + n )
{
Index i = internal : : random < Index > ( 0 , size - 1 ) ;
Index j ;
do j = internal : : random < Index > ( 0 , size - 1 ) ; while ( j = = i ) ;
std : : swap ( v ( i ) , v ( j ) ) ;
}
}
2014-10-20 17:38:51 +08:00
template < typename T > bool isNotNaN ( const T & x )
{
return x = = x ;
}
2015-03-17 20:39:51 +08:00
template < typename T > bool isPlusInf ( const T & x )
2014-10-20 17:38:51 +08:00
{
return x > NumTraits < T > : : highest ( ) ;
}
template < typename T > bool isMinusInf ( const T & x )
{
return x < NumTraits < T > : : lowest ( ) ;
}
2008-05-22 20:18:55 +08:00
} // end namespace Eigen
2008-10-26 07:10:21 +08:00
template < typename T > struct GetDifferentType ;
template < > struct GetDifferentType < float > { typedef double type ; } ;
template < > struct GetDifferentType < double > { typedef float type ; } ;
template < typename T > struct GetDifferentType < std : : complex < T > >
{ typedef std : : complex < typename GetDifferentType < T > : : type > type ; } ;
2008-05-22 20:18:55 +08:00
2013-06-22 16:51:45 +08:00
// Forward declaration to avoid ICC warning
template < typename T > std : : string type_name ( ) ;
2015-07-22 04:22:12 +08:00
template < typename T > std : : string type_name ( ) { return " other " ; }
template < > std : : string type_name < float > ( ) { return " float " ; }
template < > std : : string type_name < double > ( ) { return " double " ; }
template < > std : : string type_name < long double > ( ) { return " long double " ; }
template < > std : : string type_name < int > ( ) { return " int " ; }
template < > std : : string type_name < std : : complex < float > > ( ) { return " complex<float> " ; }
template < > std : : string type_name < std : : complex < double > > ( ) { return " complex<double> " ; }
template < > std : : string type_name < std : : complex < long double > > ( ) { return " complex<long double> " ; }
template < > std : : string type_name < std : : complex < int > > ( ) { return " complex<int> " ; }
2009-11-23 23:13:21 +08:00
2008-05-22 20:18:55 +08:00
// forward declaration of the main test function
2009-01-28 03:08:20 +08:00
void EIGEN_CAT ( test_ , EIGEN_TEST_FUNC ) ( ) ;
2008-05-22 20:18:55 +08:00
using namespace Eigen ;
2013-06-24 01:11:32 +08:00
inline void set_repeat_from_string ( const char * str )
2009-12-03 01:07:47 +08:00
{
errno = 0 ;
g_repeat = int ( strtoul ( str , 0 , 10 ) ) ;
if ( errno | | g_repeat < = 0 )
{
std : : cout < < " Invalid repeat value " < < str < < std : : endl ;
exit ( EXIT_FAILURE ) ;
}
g_has_set_repeat = true ;
}
2013-06-24 01:11:32 +08:00
inline void set_seed_from_string ( const char * str )
2009-12-03 01:07:47 +08:00
{
errno = 0 ;
2013-04-09 15:43:00 +08:00
g_seed = int ( strtoul ( str , 0 , 10 ) ) ;
2009-12-03 01:07:47 +08:00
if ( errno | | g_seed = = 0 )
{
std : : cout < < " Invalid seed value " < < str < < std : : endl ;
exit ( EXIT_FAILURE ) ;
}
g_has_set_seed = true ;
}
2008-05-22 20:18:55 +08:00
int main ( int argc , char * argv [ ] )
2007-09-05 18:42:15 +08:00
{
2009-12-03 01:07:47 +08:00
g_has_set_repeat = false ;
g_has_set_seed = false ;
2008-05-22 20:18:55 +08:00
bool need_help = false ;
2008-05-29 11:37:16 +08:00
for ( int i = 1 ; i < argc ; i + + )
2008-05-22 20:18:55 +08:00
{
2008-05-29 11:37:16 +08:00
if ( argv [ i ] [ 0 ] = = ' r ' )
2008-05-22 20:18:55 +08:00
{
2009-12-03 01:07:47 +08:00
if ( g_has_set_repeat )
2008-05-22 20:18:55 +08:00
{
2008-09-04 06:35:45 +08:00
std : : cout < < " Argument " < < argv [ i ] < < " conflicting with a former argument " < < std : : endl ;
2008-05-22 20:18:55 +08:00
return 1 ;
}
2009-12-03 01:07:47 +08:00
set_repeat_from_string ( argv [ i ] + 1 ) ;
2008-05-22 20:18:55 +08:00
}
2008-05-29 11:37:16 +08:00
else if ( argv [ i ] [ 0 ] = = ' s ' )
2008-05-22 20:18:55 +08:00
{
2009-12-03 01:07:47 +08:00
if ( g_has_set_seed )
2008-05-22 20:18:55 +08:00
{
2008-09-04 06:35:45 +08:00
std : : cout < < " Argument " < < argv [ i ] < < " conflicting with a former argument " < < std : : endl ;
2008-05-22 20:18:55 +08:00
return 1 ;
}
2009-12-03 01:07:47 +08:00
set_seed_from_string ( argv [ i ] + 1 ) ;
2008-05-22 20:18:55 +08:00
}
else
{
need_help = true ;
}
}
if ( need_help )
{
2008-09-04 06:35:45 +08:00
std : : cout < < " This test application takes the following optional arguments: " < < std : : endl ;
std : : cout < < " rN Repeat each test N times (default: " < < DEFAULT_REPEAT < < " ) " < < std : : endl ;
std : : cout < < " sN Use N as seed for random numbers (default: based on current time) " < < std : : endl ;
2009-12-03 01:07:47 +08:00
std : : cout < < std : : endl ;
std : : cout < < " If defined, the environment variables EIGEN_REPEAT and EIGEN_SEED " < < std : : endl ;
std : : cout < < " will be used as default values for these parameters. " < < std : : endl ;
2008-05-22 20:18:55 +08:00
return 1 ;
}
2009-12-03 01:07:47 +08:00
char * env_EIGEN_REPEAT = getenv ( " EIGEN_REPEAT " ) ;
if ( ! g_has_set_repeat & & env_EIGEN_REPEAT )
set_repeat_from_string ( env_EIGEN_REPEAT ) ;
char * env_EIGEN_SEED = getenv ( " EIGEN_SEED " ) ;
if ( ! g_has_set_seed & & env_EIGEN_SEED )
set_seed_from_string ( env_EIGEN_SEED ) ;
if ( ! g_has_set_seed ) g_seed = ( unsigned int ) time ( NULL ) ;
if ( ! g_has_set_repeat ) g_repeat = DEFAULT_REPEAT ;
2008-05-22 20:18:55 +08:00
2009-12-03 01:07:47 +08:00
std : : cout < < " Initializing random number generator with seed " < < g_seed < < std : : endl ;
2013-02-25 08:46:59 +08:00
std : : stringstream ss ;
ss < < " Seed: " < < g_seed ;
g_test_stack . push_back ( ss . str ( ) ) ;
2009-12-03 01:07:47 +08:00
srand ( g_seed ) ;
std : : cout < < " Repeating each test " < < g_repeat < < " times " < < std : : endl ;
2008-05-22 20:18:55 +08:00
2013-06-22 16:19:50 +08:00
Eigen : : g_test_stack . push_back ( std : : string ( EI_PP_MAKE_STRING ( EIGEN_TEST_FUNC ) ) ) ;
2008-05-22 20:18:55 +08:00
2009-01-28 03:08:20 +08:00
EIGEN_CAT ( test_ , EIGEN_TEST_FUNC ) ( ) ;
2008-05-22 20:18:55 +08:00
return 0 ;
2009-12-02 06:37:33 +08:00
}
2013-06-22 16:19:50 +08:00
// These warning are disabled here such that they are still ON when parsing Eigen's header files.
# if defined __INTEL_COMPILER
// remark #383: value copied to temporary, reference to temporary used
// -> this warning is raised even for legal usage as: g_test_stack.push_back("foo"); where g_test_stack is a std::vector<std::string>
// remark #1418: external function definition with no prior declaration
// -> this warning is raised for all our test functions. Declaring them static would fix the issue.
2013-06-24 01:11:32 +08:00
// warning #279: controlling expression is constant
// remark #1572: floating-point equality and inequality comparisons are unreliable
# pragma warning disable 279 383 1418 1572
2013-06-22 16:19:50 +08:00
# endif
2016-06-02 20:48:38 +08:00
# ifdef _MSC_VER
// 4503 - decorated name length exceeded, name was truncated
# pragma warning( disable : 4503)
# endif