mirror of
https://gitlab.com/libeigen/eigen.git
synced 2026-04-10 11:34:33 +08:00
Compare commits
106 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1c9aa054c7 | ||
|
|
e01d70e94e | ||
|
|
be55ce03e0 | ||
|
|
91b2fa2985 | ||
|
|
f7ddd033e1 | ||
|
|
046850e1d0 | ||
|
|
d7769cc3bd | ||
|
|
459dc4684e | ||
|
|
a60d71b840 | ||
|
|
fb81e4ab79 | ||
|
|
0e42db7cab | ||
|
|
67ce7ee5c4 | ||
|
|
9661180a4d | ||
|
|
ef7230c229 | ||
|
|
1cc2788047 | ||
|
|
7cfcaaf328 | ||
|
|
3745f0808c | ||
|
|
ab2a3e3c1c | ||
|
|
c40006d0b9 | ||
|
|
c1f217bbef | ||
|
|
3e2684986b | ||
|
|
5ed7b37b8f | ||
|
|
009a69fbf4 | ||
|
|
15cebe2ecc | ||
|
|
756024825d | ||
|
|
ec6ca4eae9 | ||
|
|
eb7863ebd0 | ||
|
|
aa0d407f2e | ||
|
|
dc2f92ba4a | ||
|
|
2eb8b99a32 | ||
|
|
83c726b343 | ||
|
|
473e70e8be | ||
|
|
80e72a2653 | ||
|
|
201a317912 | ||
|
|
2a3680da3d | ||
|
|
4f7baefa81 | ||
|
|
38b9ff8b6f | ||
|
|
87112908be | ||
|
|
d5c2a01031 | ||
|
|
4c8f0cbc1f | ||
|
|
538bc98b33 | ||
|
|
29f5f098cc | ||
|
|
c21f2cde34 | ||
|
|
909747d6b2 | ||
|
|
1cff196837 | ||
|
|
4ecd782c31 | ||
|
|
84a65f996f | ||
|
|
17c40e5524 | ||
|
|
51f763eaba | ||
|
|
f5e01a2cde | ||
|
|
8d16e2aa27 | ||
|
|
547a3c0d28 | ||
|
|
a432b017fb | ||
|
|
b4669f9036 | ||
|
|
4854326ae8 | ||
|
|
ea12669f7a | ||
|
|
b4388ee38b | ||
|
|
04d9fe13c6 | ||
|
|
4bf0765d71 | ||
|
|
0e35730e0b | ||
|
|
2f9b1bf398 | ||
|
|
18a13c65fe | ||
|
|
bd6e042f49 | ||
|
|
b71ee76d8d | ||
|
|
8d4d85161e | ||
|
|
e4ed2566d5 | ||
|
|
8fb4069b2a | ||
|
|
ed48e38578 | ||
|
|
83f2c809ed | ||
|
|
c090c6544b | ||
|
|
bb0fad0c70 | ||
|
|
a87cd61c13 | ||
|
|
3b29688ca2 | ||
|
|
f32ad79b41 | ||
|
|
d039c88096 | ||
|
|
cc26185d91 | ||
|
|
e6fd3fa177 | ||
|
|
249d2f360b | ||
|
|
34da70e0ce | ||
|
|
55565a0da4 | ||
|
|
4daa1292d7 | ||
|
|
c47fb1f35f | ||
|
|
2ee4b8e945 | ||
|
|
81912b3c41 | ||
|
|
efc7c2121a | ||
|
|
f22036f5f8 | ||
|
|
14fcbfb009 | ||
|
|
0b18ffe175 | ||
|
|
0f20aa3073 | ||
|
|
2de7f0f97a | ||
|
|
2c329453b1 | ||
|
|
2beec14503 | ||
|
|
5f35869461 | ||
|
|
c134d75351 | ||
|
|
092681132c | ||
|
|
0d807dce07 | ||
|
|
e8559eaed6 | ||
|
|
ffadb5b9b0 | ||
|
|
fa30d77188 | ||
|
|
7dc0c4e8f6 | ||
|
|
b3b9d7a14c | ||
|
|
32f0c782c3 | ||
|
|
7031f4e783 | ||
|
|
deea165867 | ||
|
|
406a7889b3 | ||
|
|
2f41f887d0 |
@@ -1,6 +1,5 @@
|
|||||||
project(Eigen)
|
project(Eigen)
|
||||||
|
cmake_minimum_required(VERSION 2.8.5)
|
||||||
cmake_minimum_required(VERSION 2.8.2)
|
|
||||||
|
|
||||||
# guard against in-source builds
|
# guard against in-source builds
|
||||||
|
|
||||||
@@ -55,6 +54,7 @@ endif(EIGEN_HG_CHANGESET)
|
|||||||
|
|
||||||
|
|
||||||
include(CheckCXXCompilerFlag)
|
include(CheckCXXCompilerFlag)
|
||||||
|
include(GNUInstallDirs)
|
||||||
|
|
||||||
set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
|
set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
|
||||||
|
|
||||||
@@ -288,25 +288,26 @@ option(EIGEN_TEST_C++0x "Enables all C++0x features." OFF)
|
|||||||
|
|
||||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
|
include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
|
||||||
|
|
||||||
# the user modifiable install path for header files
|
# Backward compatibility support for EIGEN_INCLUDE_INSTALL_DIR
|
||||||
set(EIGEN_INCLUDE_INSTALL_DIR ${EIGEN_INCLUDE_INSTALL_DIR} CACHE PATH "The directory where we install the header files (optional)")
|
if(EIGEN_INCLUDE_INSTALL_DIR AND NOT INCLUDE_INSTALL_DIR)
|
||||||
|
set(INCLUDE_INSTALL_DIR ${EIGEN_INCLUDE_INSTALL_DIR}
|
||||||
# set the internal install path for header files which depends on wether the user modifiable
|
CACHE PATH "The directory relative to CMAKE_PREFIX_PATH where Eigen header files are installed")
|
||||||
# EIGEN_INCLUDE_INSTALL_DIR has been set by the user or not.
|
|
||||||
if(EIGEN_INCLUDE_INSTALL_DIR)
|
|
||||||
set(INCLUDE_INSTALL_DIR
|
|
||||||
${EIGEN_INCLUDE_INSTALL_DIR}
|
|
||||||
CACHE INTERNAL
|
|
||||||
"The directory where we install the header files (internal)"
|
|
||||||
)
|
|
||||||
else()
|
else()
|
||||||
set(INCLUDE_INSTALL_DIR
|
set(INCLUDE_INSTALL_DIR
|
||||||
"include/eigen3"
|
"${CMAKE_INSTALL_INCLUDEDIR}/eigen3"
|
||||||
CACHE INTERNAL
|
CACHE PATH "The directory relative to CMAKE_PREFIX_PATH where Eigen header files are installed"
|
||||||
"The directory where we install the header files (internal)"
|
)
|
||||||
)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
set(CMAKEPACKAGE_INSTALL_DIR
|
||||||
|
"${CMAKE_INSTALL_LIBDIR}/cmake/eigen3"
|
||||||
|
CACHE PATH "The directory relative to CMAKE_PREFIX_PATH where Eigen3Config.cmake is installed"
|
||||||
|
)
|
||||||
|
set(PKGCONFIG_INSTALL_DIR
|
||||||
|
"${CMAKE_INSTALL_DATADIR}/pkgconfig"
|
||||||
|
CACHE PATH "The directory relative to CMAKE_PREFIX_PATH where eigen3.pc is installed"
|
||||||
|
)
|
||||||
|
|
||||||
# similar to set_target_properties but append the property instead of overwriting it
|
# similar to set_target_properties but append the property instead of overwriting it
|
||||||
macro(ei_add_target_property target prop value)
|
macro(ei_add_target_property target prop value)
|
||||||
|
|
||||||
@@ -324,21 +325,9 @@ install(FILES
|
|||||||
)
|
)
|
||||||
|
|
||||||
if(EIGEN_BUILD_PKGCONFIG)
|
if(EIGEN_BUILD_PKGCONFIG)
|
||||||
SET(path_separator ":")
|
configure_file(eigen3.pc.in eigen3.pc @ONLY)
|
||||||
STRING(REPLACE ${path_separator} ";" pkg_config_libdir_search "$ENV{PKG_CONFIG_LIBDIR}")
|
|
||||||
message(STATUS "searching for 'pkgconfig' directory in PKG_CONFIG_LIBDIR ( $ENV{PKG_CONFIG_LIBDIR} ), ${CMAKE_INSTALL_PREFIX}/share, and ${CMAKE_INSTALL_PREFIX}/lib")
|
|
||||||
FIND_PATH(pkg_config_libdir pkgconfig ${pkg_config_libdir_search} ${CMAKE_INSTALL_PREFIX}/share ${CMAKE_INSTALL_PREFIX}/lib ${pkg_config_libdir_search})
|
|
||||||
if(pkg_config_libdir)
|
|
||||||
SET(pkg_config_install_dir ${pkg_config_libdir})
|
|
||||||
message(STATUS "found ${pkg_config_libdir}/pkgconfig" )
|
|
||||||
else(pkg_config_libdir)
|
|
||||||
SET(pkg_config_install_dir ${CMAKE_INSTALL_PREFIX}/share)
|
|
||||||
message(STATUS "pkgconfig not found; installing in ${pkg_config_install_dir}" )
|
|
||||||
endif(pkg_config_libdir)
|
|
||||||
|
|
||||||
configure_file(eigen3.pc.in eigen3.pc)
|
|
||||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/eigen3.pc
|
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/eigen3.pc
|
||||||
DESTINATION ${pkg_config_install_dir}/pkgconfig
|
DESTINATION ${PKGCONFIG_INSTALL_DIR}
|
||||||
)
|
)
|
||||||
endif(EIGEN_BUILD_PKGCONFIG)
|
endif(EIGEN_BUILD_PKGCONFIG)
|
||||||
|
|
||||||
@@ -401,12 +390,15 @@ if(cmake_generator_tolower MATCHES "makefile")
|
|||||||
message(STATUS "--------------+--------------------------------------------------------------")
|
message(STATUS "--------------+--------------------------------------------------------------")
|
||||||
message(STATUS "Command | Description")
|
message(STATUS "Command | Description")
|
||||||
message(STATUS "--------------+--------------------------------------------------------------")
|
message(STATUS "--------------+--------------------------------------------------------------")
|
||||||
message(STATUS "make install | Install to ${CMAKE_INSTALL_PREFIX}. To change that:")
|
message(STATUS "make install | Install Eigen. Headers will be installed to:")
|
||||||
message(STATUS " | cmake . -DCMAKE_INSTALL_PREFIX=yourpath")
|
message(STATUS " | <CMAKE_INSTALL_PREFIX>/<INCLUDE_INSTALL_DIR>")
|
||||||
message(STATUS " | Eigen headers will then be installed to:")
|
message(STATUS " | Using the following values:")
|
||||||
message(STATUS " | ${CMAKE_INSTALL_PREFIX}/${INCLUDE_INSTALL_DIR}")
|
message(STATUS " | CMAKE_INSTALL_PREFIX: ${CMAKE_INSTALL_PREFIX}")
|
||||||
message(STATUS " | To install Eigen headers to a separate location, do:")
|
message(STATUS " | INCLUDE_INSTALL_DIR: ${INCLUDE_INSTALL_DIR}")
|
||||||
message(STATUS " | cmake . -DEIGEN_INCLUDE_INSTALL_DIR=yourpath")
|
message(STATUS " | Change the install location of Eigen headers using:")
|
||||||
|
message(STATUS " | cmake . -DCMAKE_INSTALL_PREFIX=yourprefix")
|
||||||
|
message(STATUS " | Or:")
|
||||||
|
message(STATUS " | cmake . -DINCLUDE_INSTALL_DIR=yourdir")
|
||||||
message(STATUS "make doc | Generate the API documentation, requires Doxygen & LaTeX")
|
message(STATUS "make doc | Generate the API documentation, requires Doxygen & LaTeX")
|
||||||
message(STATUS "make check | Build and run the unit-tests. Read this page:")
|
message(STATUS "make check | Build and run the unit-tests. Read this page:")
|
||||||
message(STATUS " | http://eigen.tuxfamily.org/index.php?title=Tests")
|
message(STATUS " | http://eigen.tuxfamily.org/index.php?title=Tests")
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ extern "C" {
|
|||||||
/** \ingroup Support_modules
|
/** \ingroup Support_modules
|
||||||
* \defgroup CholmodSupport_Module CholmodSupport module
|
* \defgroup CholmodSupport_Module CholmodSupport module
|
||||||
*
|
*
|
||||||
* This module provides an interface to the Cholmod library which is part of the <a href="http://www.cise.ufl.edu/research/sparse/SuiteSparse/">suitesparse</a> package.
|
* This module provides an interface to the Cholmod library which is part of the <a href="http://www.suitesparse.com">suitesparse</a> package.
|
||||||
* It provides the two following main factorization classes:
|
* It provides the two following main factorization classes:
|
||||||
* - class CholmodSupernodalLLT: a supernodal LLT Cholesky factorization.
|
* - class CholmodSupernodalLLT: a supernodal LLT Cholesky factorization.
|
||||||
* - class CholmodDecomposiiton: a general L(D)LT Cholesky factorization with automatic or explicit runtime selection of the underlying factorization method (supernodal or simplicial).
|
* - class CholmodDecomposiiton: a general L(D)LT Cholesky factorization with automatic or explicit runtime selection of the underlying factorization method (supernodal or simplicial).
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
/** \ingroup Support_modules
|
/** \ingroup Support_modules
|
||||||
* \defgroup SPQRSupport_Module SuiteSparseQR module
|
* \defgroup SPQRSupport_Module SuiteSparseQR module
|
||||||
*
|
*
|
||||||
* This module provides an interface to the SPQR library, which is part of the <a href="http://www.cise.ufl.edu/research/sparse/SuiteSparse/">suitesparse</a> package.
|
* This module provides an interface to the SPQR library, which is part of the <a href="http://www.suitesparse.com">suitesparse</a> package.
|
||||||
*
|
*
|
||||||
* \code
|
* \code
|
||||||
* #include <Eigen/SPQRSupport>
|
* #include <Eigen/SPQRSupport>
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ extern "C" {
|
|||||||
/** \ingroup Support_modules
|
/** \ingroup Support_modules
|
||||||
* \defgroup UmfPackSupport_Module UmfPackSupport module
|
* \defgroup UmfPackSupport_Module UmfPackSupport module
|
||||||
*
|
*
|
||||||
* This module provides an interface to the UmfPack library which is part of the <a href="http://www.cise.ufl.edu/research/sparse/SuiteSparse/">suitesparse</a> package.
|
* This module provides an interface to the UmfPack library which is part of the <a href="http://www.suitesparse.com">suitesparse</a> package.
|
||||||
* It provides the following factorization class:
|
* It provides the following factorization class:
|
||||||
* - class UmfPackLU: a multifrontal sequential LU factorization.
|
* - class UmfPackLU: a multifrontal sequential LU factorization.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -66,9 +66,8 @@ struct traits<Block<XprType, BlockRows, BlockCols, InnerPanel> > : traits<XprTyp
|
|||||||
: ColsAtCompileTime != Dynamic ? int(ColsAtCompileTime)
|
: ColsAtCompileTime != Dynamic ? int(ColsAtCompileTime)
|
||||||
: int(traits<XprType>::MaxColsAtCompileTime),
|
: int(traits<XprType>::MaxColsAtCompileTime),
|
||||||
XprTypeIsRowMajor = (int(traits<XprType>::Flags)&RowMajorBit) != 0,
|
XprTypeIsRowMajor = (int(traits<XprType>::Flags)&RowMajorBit) != 0,
|
||||||
IsDense = is_same<StorageKind,Dense>::value,
|
IsRowMajor = (MaxRowsAtCompileTime==1&&MaxColsAtCompileTime!=1) ? 1
|
||||||
IsRowMajor = (IsDense&&MaxRowsAtCompileTime==1&&MaxColsAtCompileTime!=1) ? 1
|
: (MaxColsAtCompileTime==1&&MaxRowsAtCompileTime!=1) ? 0
|
||||||
: (IsDense&&MaxColsAtCompileTime==1&&MaxRowsAtCompileTime!=1) ? 0
|
|
||||||
: XprTypeIsRowMajor,
|
: XprTypeIsRowMajor,
|
||||||
HasSameStorageOrderAsXprType = (IsRowMajor == XprTypeIsRowMajor),
|
HasSameStorageOrderAsXprType = (IsRowMajor == XprTypeIsRowMajor),
|
||||||
InnerSize = IsRowMajor ? int(ColsAtCompileTime) : int(RowsAtCompileTime),
|
InnerSize = IsRowMajor ? int(ColsAtCompileTime) : int(RowsAtCompileTime),
|
||||||
|
|||||||
@@ -76,9 +76,7 @@ struct CommaInitializer
|
|||||||
template<typename OtherDerived>
|
template<typename OtherDerived>
|
||||||
CommaInitializer& operator,(const DenseBase<OtherDerived>& other)
|
CommaInitializer& operator,(const DenseBase<OtherDerived>& other)
|
||||||
{
|
{
|
||||||
if(other.cols()==0 || other.rows()==0)
|
if (m_col==m_xpr.cols() && (other.cols()!=0 || other.rows()!=m_currentBlockRows))
|
||||||
return *this;
|
|
||||||
if (m_col==m_xpr.cols())
|
|
||||||
{
|
{
|
||||||
m_row+=m_currentBlockRows;
|
m_row+=m_currentBlockRows;
|
||||||
m_col = 0;
|
m_col = 0;
|
||||||
@@ -86,24 +84,18 @@ struct CommaInitializer
|
|||||||
eigen_assert(m_row+m_currentBlockRows<=m_xpr.rows()
|
eigen_assert(m_row+m_currentBlockRows<=m_xpr.rows()
|
||||||
&& "Too many rows passed to comma initializer (operator<<)");
|
&& "Too many rows passed to comma initializer (operator<<)");
|
||||||
}
|
}
|
||||||
eigen_assert(m_col<m_xpr.cols()
|
eigen_assert((m_col + other.cols() <= m_xpr.cols())
|
||||||
&& "Too many coefficients passed to comma initializer (operator<<)");
|
&& "Too many coefficients passed to comma initializer (operator<<)");
|
||||||
eigen_assert(m_currentBlockRows==other.rows());
|
eigen_assert(m_currentBlockRows==other.rows());
|
||||||
if (OtherDerived::SizeAtCompileTime != Dynamic)
|
m_xpr.template block<OtherDerived::RowsAtCompileTime, OtherDerived::ColsAtCompileTime>
|
||||||
m_xpr.template block<OtherDerived::RowsAtCompileTime != Dynamic ? OtherDerived::RowsAtCompileTime : 1,
|
(m_row, m_col, other.rows(), other.cols()) = other;
|
||||||
OtherDerived::ColsAtCompileTime != Dynamic ? OtherDerived::ColsAtCompileTime : 1>
|
|
||||||
(m_row, m_col) = other;
|
|
||||||
else
|
|
||||||
m_xpr.block(m_row, m_col, other.rows(), other.cols()) = other;
|
|
||||||
m_col += other.cols();
|
m_col += other.cols();
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline ~CommaInitializer()
|
inline ~CommaInitializer()
|
||||||
{
|
{
|
||||||
eigen_assert((m_row+m_currentBlockRows) == m_xpr.rows()
|
finished();
|
||||||
&& m_col == m_xpr.cols()
|
|
||||||
&& "Too few coefficients passed to comma initializer (operator<<)");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** \returns the built matrix once all its coefficients have been set.
|
/** \returns the built matrix once all its coefficients have been set.
|
||||||
@@ -113,7 +105,12 @@ struct CommaInitializer
|
|||||||
* quaternion.fromRotationMatrix((Matrix3f() << axis0, axis1, axis2).finished());
|
* quaternion.fromRotationMatrix((Matrix3f() << axis0, axis1, axis2).finished());
|
||||||
* \endcode
|
* \endcode
|
||||||
*/
|
*/
|
||||||
inline XprType& finished() { return m_xpr; }
|
inline XprType& finished() {
|
||||||
|
eigen_assert(((m_row+m_currentBlockRows) == m_xpr.rows() || m_xpr.cols() == 0)
|
||||||
|
&& m_col == m_xpr.cols()
|
||||||
|
&& "Too few coefficients passed to comma initializer (operator<<)");
|
||||||
|
return m_xpr;
|
||||||
|
}
|
||||||
|
|
||||||
XprType& m_xpr; // target expression
|
XprType& m_xpr; // target expression
|
||||||
Index m_row; // current row id
|
Index m_row; // current row id
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ struct traits<CwiseUnaryView<ViewOp, MatrixType> >
|
|||||||
typedef typename remove_all<MatrixTypeNested>::type _MatrixTypeNested;
|
typedef typename remove_all<MatrixTypeNested>::type _MatrixTypeNested;
|
||||||
enum {
|
enum {
|
||||||
Flags = (traits<_MatrixTypeNested>::Flags & (HereditaryBits | LvalueBit | LinearAccessBit | DirectAccessBit)),
|
Flags = (traits<_MatrixTypeNested>::Flags & (HereditaryBits | LvalueBit | LinearAccessBit | DirectAccessBit)),
|
||||||
CoeffReadCost = traits<_MatrixTypeNested>::CoeffReadCost + functor_traits<ViewOp>::Cost,
|
CoeffReadCost = EIGEN_ADD_COST(traits<_MatrixTypeNested>::CoeffReadCost, functor_traits<ViewOp>::Cost),
|
||||||
MatrixTypeInnerStride = inner_stride_at_compile_time<MatrixType>::ret,
|
MatrixTypeInnerStride = inner_stride_at_compile_time<MatrixType>::ret,
|
||||||
// need to cast the sizeof's from size_t to int explicitly, otherwise:
|
// need to cast the sizeof's from size_t to int explicitly, otherwise:
|
||||||
// "error: no integral type can represent all of the enumerator values
|
// "error: no integral type can represent all of the enumerator values
|
||||||
|
|||||||
@@ -44,10 +44,10 @@ class DiagonalBase : public EigenBase<Derived>
|
|||||||
template<typename DenseDerived>
|
template<typename DenseDerived>
|
||||||
void evalTo(MatrixBase<DenseDerived> &other) const;
|
void evalTo(MatrixBase<DenseDerived> &other) const;
|
||||||
template<typename DenseDerived>
|
template<typename DenseDerived>
|
||||||
void addTo(MatrixBase<DenseDerived> &other) const
|
inline void addTo(MatrixBase<DenseDerived> &other) const
|
||||||
{ other.diagonal() += diagonal(); }
|
{ other.diagonal() += diagonal(); }
|
||||||
template<typename DenseDerived>
|
template<typename DenseDerived>
|
||||||
void subTo(MatrixBase<DenseDerived> &other) const
|
inline void subTo(MatrixBase<DenseDerived> &other) const
|
||||||
{ other.diagonal() -= diagonal(); }
|
{ other.diagonal() -= diagonal(); }
|
||||||
|
|
||||||
inline const DiagonalVectorType& diagonal() const { return derived().diagonal(); }
|
inline const DiagonalVectorType& diagonal() const { return derived().diagonal(); }
|
||||||
@@ -98,7 +98,7 @@ class DiagonalBase : public EigenBase<Derived>
|
|||||||
|
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
template<typename DenseDerived>
|
template<typename DenseDerived>
|
||||||
void DiagonalBase<Derived>::evalTo(MatrixBase<DenseDerived> &other) const
|
inline void DiagonalBase<Derived>::evalTo(MatrixBase<DenseDerived> &other) const
|
||||||
{
|
{
|
||||||
other.setZero();
|
other.setZero();
|
||||||
other.diagonal() = diagonal();
|
other.diagonal() = diagonal();
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ struct dot_nocheck<T, U, true>
|
|||||||
*/
|
*/
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
template<typename OtherDerived>
|
template<typename OtherDerived>
|
||||||
typename internal::scalar_product_traits<typename internal::traits<Derived>::Scalar,typename internal::traits<OtherDerived>::Scalar>::ReturnType
|
inline typename internal::scalar_product_traits<typename internal::traits<Derived>::Scalar,typename internal::traits<OtherDerived>::Scalar>::ReturnType
|
||||||
MatrixBase<Derived>::dot(const MatrixBase<OtherDerived>& other) const
|
MatrixBase<Derived>::dot(const MatrixBase<OtherDerived>& other) const
|
||||||
{
|
{
|
||||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
|
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
|
||||||
|
|||||||
@@ -969,6 +969,8 @@ template<typename T>
|
|||||||
struct functor_traits<std::not_equal_to<T> >
|
struct functor_traits<std::not_equal_to<T> >
|
||||||
{ enum { Cost = 1, PacketAccess = false }; };
|
{ enum { Cost = 1, PacketAccess = false }; };
|
||||||
|
|
||||||
|
#if(__cplusplus < 201103L)
|
||||||
|
// std::binder* are deprecated since c++11 and will be removed in c++17
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct functor_traits<std::binder2nd<T> >
|
struct functor_traits<std::binder2nd<T> >
|
||||||
{ enum { Cost = functor_traits<T>::Cost, PacketAccess = false }; };
|
{ enum { Cost = functor_traits<T>::Cost, PacketAccess = false }; };
|
||||||
@@ -976,6 +978,7 @@ struct functor_traits<std::binder2nd<T> >
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
struct functor_traits<std::binder1st<T> >
|
struct functor_traits<std::binder1st<T> >
|
||||||
{ enum { Cost = functor_traits<T>::Cost, PacketAccess = false }; };
|
{ enum { Cost = functor_traits<T>::Cost, PacketAccess = false }; };
|
||||||
|
#endif
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct functor_traits<std::unary_negate<T> >
|
struct functor_traits<std::unary_negate<T> >
|
||||||
|
|||||||
@@ -205,9 +205,6 @@ class GeneralProduct<Lhs, Rhs, InnerProduct>
|
|||||||
public:
|
public:
|
||||||
GeneralProduct(const Lhs& lhs, const Rhs& rhs)
|
GeneralProduct(const Lhs& lhs, const Rhs& rhs)
|
||||||
{
|
{
|
||||||
EIGEN_STATIC_ASSERT((internal::is_same<typename Lhs::RealScalar, typename Rhs::RealScalar>::value),
|
|
||||||
YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
|
|
||||||
|
|
||||||
Base::coeffRef(0,0) = (lhs.transpose().cwiseProduct(rhs)).sum();
|
Base::coeffRef(0,0) = (lhs.transpose().cwiseProduct(rhs)).sum();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -264,8 +261,6 @@ class GeneralProduct<Lhs, Rhs, OuterProduct>
|
|||||||
|
|
||||||
GeneralProduct(const Lhs& lhs, const Rhs& rhs) : Base(lhs,rhs)
|
GeneralProduct(const Lhs& lhs, const Rhs& rhs) : Base(lhs,rhs)
|
||||||
{
|
{
|
||||||
EIGEN_STATIC_ASSERT((internal::is_same<typename Lhs::RealScalar, typename Rhs::RealScalar>::value),
|
|
||||||
YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct set { template<typename Dst, typename Src> void operator()(const Dst& dst, const Src& src) const { dst.const_cast_derived() = src; } };
|
struct set { template<typename Dst, typename Src> void operator()(const Dst& dst, const Src& src) const { dst.const_cast_derived() = src; } };
|
||||||
@@ -425,15 +420,18 @@ template<> struct gemv_selector<OnTheRight,ColMajor,true>
|
|||||||
ResScalar actualAlpha = alpha * LhsBlasTraits::extractScalarFactor(prod.lhs())
|
ResScalar actualAlpha = alpha * LhsBlasTraits::extractScalarFactor(prod.lhs())
|
||||||
* RhsBlasTraits::extractScalarFactor(prod.rhs());
|
* RhsBlasTraits::extractScalarFactor(prod.rhs());
|
||||||
|
|
||||||
|
// make sure Dest is a compile-time vector type (bug 1166)
|
||||||
|
typedef typename conditional<Dest::IsVectorAtCompileTime, Dest, typename Dest::ColXpr>::type ActualDest;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
// FIXME find a way to allow an inner stride on the result if packet_traits<Scalar>::size==1
|
// FIXME find a way to allow an inner stride on the result if packet_traits<Scalar>::size==1
|
||||||
// on, the other hand it is good for the cache to pack the vector anyways...
|
// on, the other hand it is good for the cache to pack the vector anyways...
|
||||||
EvalToDestAtCompileTime = Dest::InnerStrideAtCompileTime==1,
|
EvalToDestAtCompileTime = (ActualDest::InnerStrideAtCompileTime==1),
|
||||||
ComplexByReal = (NumTraits<LhsScalar>::IsComplex) && (!NumTraits<RhsScalar>::IsComplex),
|
ComplexByReal = (NumTraits<LhsScalar>::IsComplex) && (!NumTraits<RhsScalar>::IsComplex),
|
||||||
MightCannotUseDest = (Dest::InnerStrideAtCompileTime!=1) || ComplexByReal
|
MightCannotUseDest = (ActualDest::InnerStrideAtCompileTime!=1) || ComplexByReal
|
||||||
};
|
};
|
||||||
|
|
||||||
gemv_static_vector_if<ResScalar,Dest::SizeAtCompileTime,Dest::MaxSizeAtCompileTime,MightCannotUseDest> static_dest;
|
gemv_static_vector_if<ResScalar,ActualDest::SizeAtCompileTime,ActualDest::MaxSizeAtCompileTime,MightCannotUseDest> static_dest;
|
||||||
|
|
||||||
bool alphaIsCompatible = (!ComplexByReal) || (numext::imag(actualAlpha)==RealScalar(0));
|
bool alphaIsCompatible = (!ComplexByReal) || (numext::imag(actualAlpha)==RealScalar(0));
|
||||||
bool evalToDest = EvalToDestAtCompileTime && alphaIsCompatible;
|
bool evalToDest = EvalToDestAtCompileTime && alphaIsCompatible;
|
||||||
@@ -522,7 +520,7 @@ template<> struct gemv_selector<OnTheRight,RowMajor,true>
|
|||||||
actualLhs.rows(), actualLhs.cols(),
|
actualLhs.rows(), actualLhs.cols(),
|
||||||
actualLhs.data(), actualLhs.outerStride(),
|
actualLhs.data(), actualLhs.outerStride(),
|
||||||
actualRhsPtr, 1,
|
actualRhsPtr, 1,
|
||||||
dest.data(), dest.innerStride(),
|
dest.data(), dest.col(0).innerStride(), //NOTE if dest is not a vector at compile-time, then dest.innerStride() might be wrong. (bug 1166)
|
||||||
actualAlpha);
|
actualAlpha);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -183,8 +183,8 @@ template<typename Scalar, typename Packet> inline void pstoreu(Scalar* to, const
|
|||||||
/** \internal tries to do cache prefetching of \a addr */
|
/** \internal tries to do cache prefetching of \a addr */
|
||||||
template<typename Scalar> inline void prefetch(const Scalar* addr)
|
template<typename Scalar> inline void prefetch(const Scalar* addr)
|
||||||
{
|
{
|
||||||
#if !defined(_MSC_VER)
|
#if (!EIGEN_COMP_MSVC) && (EIGEN_COMP_GNUC || EIGEN_COMP_CLANG || EIGEN_COMP_ICC)
|
||||||
__builtin_prefetch(addr);
|
__builtin_prefetch(addr);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -149,6 +149,10 @@ template<typename Derived> class MapBase<Derived, ReadOnlyAccessors>
|
|||||||
checkSanity();
|
checkSanity();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef EIGEN_MAPBASE_PLUGIN
|
||||||
|
#include EIGEN_MAPBASE_PLUGIN
|
||||||
|
#endif
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
void checkSanity() const
|
void checkSanity() const
|
||||||
|
|||||||
@@ -218,8 +218,8 @@ struct conj_retval
|
|||||||
* Implementation of abs2 *
|
* Implementation of abs2 *
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
template<typename Scalar>
|
template<typename Scalar,bool IsComplex>
|
||||||
struct abs2_impl
|
struct abs2_impl_default
|
||||||
{
|
{
|
||||||
typedef typename NumTraits<Scalar>::Real RealScalar;
|
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||||
static inline RealScalar run(const Scalar& x)
|
static inline RealScalar run(const Scalar& x)
|
||||||
@@ -228,15 +228,26 @@ struct abs2_impl
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename RealScalar>
|
template<typename Scalar>
|
||||||
struct abs2_impl<std::complex<RealScalar> >
|
struct abs2_impl_default<Scalar, true> // IsComplex
|
||||||
{
|
{
|
||||||
static inline RealScalar run(const std::complex<RealScalar>& x)
|
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||||
|
static inline RealScalar run(const Scalar& x)
|
||||||
{
|
{
|
||||||
return real(x)*real(x) + imag(x)*imag(x);
|
return real(x)*real(x) + imag(x)*imag(x);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename Scalar>
|
||||||
|
struct abs2_impl
|
||||||
|
{
|
||||||
|
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||||
|
static inline RealScalar run(const Scalar& x)
|
||||||
|
{
|
||||||
|
return abs2_impl_default<Scalar,NumTraits<Scalar>::IsComplex>::run(x);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template<typename Scalar>
|
template<typename Scalar>
|
||||||
struct abs2_retval
|
struct abs2_retval
|
||||||
{
|
{
|
||||||
@@ -496,11 +507,24 @@ struct floor_log2<n, lower, upper, floor_log2_bogus>
|
|||||||
template<typename Scalar>
|
template<typename Scalar>
|
||||||
struct random_default_impl<Scalar, false, true>
|
struct random_default_impl<Scalar, false, true>
|
||||||
{
|
{
|
||||||
typedef typename NumTraits<Scalar>::NonInteger NonInteger;
|
|
||||||
|
|
||||||
static inline Scalar run(const Scalar& x, const Scalar& y)
|
static inline Scalar run(const Scalar& x, const Scalar& y)
|
||||||
{
|
{
|
||||||
return x + Scalar((NonInteger(y)-x+1) * std::rand() / (RAND_MAX + NonInteger(1)));
|
typedef typename conditional<NumTraits<Scalar>::IsSigned,std::ptrdiff_t,std::size_t>::type ScalarX;
|
||||||
|
if(y<x)
|
||||||
|
return x;
|
||||||
|
// the following difference might overflow on a 32 bits system,
|
||||||
|
// but since y>=x the result converted to an unsigned long is still correct.
|
||||||
|
std::size_t range = ScalarX(y)-ScalarX(x);
|
||||||
|
std::size_t offset = 0;
|
||||||
|
// rejection sampling
|
||||||
|
std::size_t divisor = 1;
|
||||||
|
std::size_t multiplier = 1;
|
||||||
|
if(range<RAND_MAX) divisor = (std::size_t(RAND_MAX)+1)/(range+1);
|
||||||
|
else multiplier = 1 + range/(std::size_t(RAND_MAX)+1);
|
||||||
|
do {
|
||||||
|
offset = (std::size_t(std::rand()) * multiplier) / divisor;
|
||||||
|
} while (offset > range);
|
||||||
|
return Scalar(ScalarX(x) + offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline Scalar run()
|
static inline Scalar run()
|
||||||
@@ -707,21 +731,21 @@ struct scalar_fuzzy_impl : scalar_fuzzy_default_impl<Scalar, NumTraits<Scalar>::
|
|||||||
|
|
||||||
template<typename Scalar, typename OtherScalar>
|
template<typename Scalar, typename OtherScalar>
|
||||||
inline bool isMuchSmallerThan(const Scalar& x, const OtherScalar& y,
|
inline bool isMuchSmallerThan(const Scalar& x, const OtherScalar& y,
|
||||||
typename NumTraits<Scalar>::Real precision = NumTraits<Scalar>::dummy_precision())
|
const typename NumTraits<Scalar>::Real &precision = NumTraits<Scalar>::dummy_precision())
|
||||||
{
|
{
|
||||||
return scalar_fuzzy_impl<Scalar>::template isMuchSmallerThan<OtherScalar>(x, y, precision);
|
return scalar_fuzzy_impl<Scalar>::template isMuchSmallerThan<OtherScalar>(x, y, precision);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Scalar>
|
template<typename Scalar>
|
||||||
inline bool isApprox(const Scalar& x, const Scalar& y,
|
inline bool isApprox(const Scalar& x, const Scalar& y,
|
||||||
typename NumTraits<Scalar>::Real precision = NumTraits<Scalar>::dummy_precision())
|
const typename NumTraits<Scalar>::Real &precision = NumTraits<Scalar>::dummy_precision())
|
||||||
{
|
{
|
||||||
return scalar_fuzzy_impl<Scalar>::isApprox(x, y, precision);
|
return scalar_fuzzy_impl<Scalar>::isApprox(x, y, precision);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Scalar>
|
template<typename Scalar>
|
||||||
inline bool isApproxOrLessThan(const Scalar& x, const Scalar& y,
|
inline bool isApproxOrLessThan(const Scalar& x, const Scalar& y,
|
||||||
typename NumTraits<Scalar>::Real precision = NumTraits<Scalar>::dummy_precision())
|
const typename NumTraits<Scalar>::Real &precision = NumTraits<Scalar>::dummy_precision())
|
||||||
{
|
{
|
||||||
return scalar_fuzzy_impl<Scalar>::isApproxOrLessThan(x, y, precision);
|
return scalar_fuzzy_impl<Scalar>::isApproxOrLessThan(x, y, precision);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -584,10 +584,11 @@ struct permut_matrix_product_retval
|
|||||||
const Index n = Side==OnTheLeft ? rows() : cols();
|
const Index n = Side==OnTheLeft ? rows() : cols();
|
||||||
// FIXME we need an is_same for expression that is not sensitive to constness. For instance
|
// FIXME we need an is_same for expression that is not sensitive to constness. For instance
|
||||||
// is_same_xpr<Block<const Matrix>, Block<Matrix> >::value should be true.
|
// is_same_xpr<Block<const Matrix>, Block<Matrix> >::value should be true.
|
||||||
|
const typename Dest::Scalar *dst_data = internal::extract_data(dst);
|
||||||
if( is_same<MatrixTypeNestedCleaned,Dest>::value
|
if( is_same<MatrixTypeNestedCleaned,Dest>::value
|
||||||
&& blas_traits<MatrixTypeNestedCleaned>::HasUsableDirectAccess
|
&& blas_traits<MatrixTypeNestedCleaned>::HasUsableDirectAccess
|
||||||
&& blas_traits<Dest>::HasUsableDirectAccess
|
&& blas_traits<Dest>::HasUsableDirectAccess
|
||||||
&& extract_data(dst) == extract_data(m_matrix))
|
&& dst_data!=0 && dst_data == extract_data(m_matrix))
|
||||||
{
|
{
|
||||||
// apply the permutation inplace
|
// apply the permutation inplace
|
||||||
Matrix<bool,PermutationType::RowsAtCompileTime,1,0,PermutationType::MaxRowsAtCompileTime> mask(m_permutation.size());
|
Matrix<bool,PermutationType::RowsAtCompileTime,1,0,PermutationType::MaxRowsAtCompileTime> mask(m_permutation.size());
|
||||||
|
|||||||
@@ -315,8 +315,8 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
|
|||||||
EIGEN_STRONG_INLINE void resizeLike(const EigenBase<OtherDerived>& _other)
|
EIGEN_STRONG_INLINE void resizeLike(const EigenBase<OtherDerived>& _other)
|
||||||
{
|
{
|
||||||
const OtherDerived& other = _other.derived();
|
const OtherDerived& other = _other.derived();
|
||||||
internal::check_rows_cols_for_overflow<MaxSizeAtCompileTime>::run(other.rows(), other.cols());
|
internal::check_rows_cols_for_overflow<MaxSizeAtCompileTime>::run(Index(other.rows()), Index(other.cols()));
|
||||||
const Index othersize = other.rows()*other.cols();
|
const Index othersize = Index(other.rows())*Index(other.cols());
|
||||||
if(RowsAtCompileTime == 1)
|
if(RowsAtCompileTime == 1)
|
||||||
{
|
{
|
||||||
eigen_assert(other.rows() == 1 || other.cols() == 1);
|
eigen_assert(other.rows() == 1 || other.cols() == 1);
|
||||||
@@ -487,7 +487,7 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
|
|||||||
/** \sa MatrixBase::operator=(const EigenBase<OtherDerived>&) */
|
/** \sa MatrixBase::operator=(const EigenBase<OtherDerived>&) */
|
||||||
template<typename OtherDerived>
|
template<typename OtherDerived>
|
||||||
EIGEN_STRONG_INLINE PlainObjectBase(const EigenBase<OtherDerived> &other)
|
EIGEN_STRONG_INLINE PlainObjectBase(const EigenBase<OtherDerived> &other)
|
||||||
: m_storage(other.derived().rows() * other.derived().cols(), other.derived().rows(), other.derived().cols())
|
: m_storage(Index(other.derived().rows()) * Index(other.derived().cols()), other.derived().rows(), other.derived().cols())
|
||||||
{
|
{
|
||||||
_check_template_params();
|
_check_template_params();
|
||||||
internal::check_rows_cols_for_overflow<MaxSizeAtCompileTime>::run(other.derived().rows(), other.derived().cols());
|
internal::check_rows_cols_for_overflow<MaxSizeAtCompileTime>::run(other.derived().rows(), other.derived().cols());
|
||||||
|
|||||||
@@ -76,9 +76,23 @@ template<typename MatrixType, int Direction> class Reverse
|
|||||||
EIGEN_DENSE_PUBLIC_INTERFACE(Reverse)
|
EIGEN_DENSE_PUBLIC_INTERFACE(Reverse)
|
||||||
using Base::IsRowMajor;
|
using Base::IsRowMajor;
|
||||||
|
|
||||||
// next line is necessary because otherwise const version of operator()
|
// The following two operators are provided to worarkound
|
||||||
// is hidden by non-const version defined in this file
|
// a MSVC 2013 issue. In theory, we could simply do:
|
||||||
using Base::operator();
|
// using Base::operator();
|
||||||
|
// to make const version of operator() visible.
|
||||||
|
// Otheriwse, they would be hidden by the non-const versions defined in this file
|
||||||
|
|
||||||
|
inline CoeffReturnType operator()(Index row, Index col) const
|
||||||
|
{
|
||||||
|
eigen_assert(row >= 0 && row < rows() && col >= 0 && col < cols());
|
||||||
|
return coeff(row, col);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline CoeffReturnType operator()(Index index) const
|
||||||
|
{
|
||||||
|
eigen_assert(index >= 0 && index < m_matrix.size());
|
||||||
|
return coeff(index);
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
enum {
|
enum {
|
||||||
|
|||||||
@@ -116,17 +116,17 @@ template<typename Lhs, typename Rhs, int Mode, int Index, int Size>
|
|||||||
struct triangular_solver_unroller<Lhs,Rhs,Mode,Index,Size,false> {
|
struct triangular_solver_unroller<Lhs,Rhs,Mode,Index,Size,false> {
|
||||||
enum {
|
enum {
|
||||||
IsLower = ((Mode&Lower)==Lower),
|
IsLower = ((Mode&Lower)==Lower),
|
||||||
I = IsLower ? Index : Size - Index - 1,
|
RowIndex = IsLower ? Index : Size - Index - 1,
|
||||||
S = IsLower ? 0 : I+1
|
S = IsLower ? 0 : RowIndex+1
|
||||||
};
|
};
|
||||||
static void run(const Lhs& lhs, Rhs& rhs)
|
static void run(const Lhs& lhs, Rhs& rhs)
|
||||||
{
|
{
|
||||||
if (Index>0)
|
if (Index>0)
|
||||||
rhs.coeffRef(I) -= lhs.row(I).template segment<Index>(S).transpose()
|
rhs.coeffRef(RowIndex) -= lhs.row(RowIndex).template segment<Index>(S).transpose()
|
||||||
.cwiseProduct(rhs.template segment<Index>(S)).sum();
|
.cwiseProduct(rhs.template segment<Index>(S)).sum();
|
||||||
|
|
||||||
if(!(Mode & UnitDiag))
|
if(!(Mode & UnitDiag))
|
||||||
rhs.coeffRef(I) /= lhs.coeff(I,I);
|
rhs.coeffRef(RowIndex) /= lhs.coeff(RowIndex,RowIndex);
|
||||||
|
|
||||||
triangular_solver_unroller<Lhs,Rhs,Mode,Index+1,Size>::run(lhs,rhs);
|
triangular_solver_unroller<Lhs,Rhs,Mode,Index+1,Size>::run(lhs,rhs);
|
||||||
}
|
}
|
||||||
@@ -243,7 +243,8 @@ template<int Side, typename TriangularType, typename Rhs> struct triangular_solv
|
|||||||
|
|
||||||
template<typename Dest> inline void evalTo(Dest& dst) const
|
template<typename Dest> inline void evalTo(Dest& dst) const
|
||||||
{
|
{
|
||||||
if(!(is_same<RhsNestedCleaned,Dest>::value && extract_data(dst) == extract_data(m_rhs)))
|
const typename Dest::Scalar *dst_data = internal::extract_data(dst);
|
||||||
|
if(!(is_same<RhsNestedCleaned,Dest>::value && dst_data!=0 && extract_data(dst) == extract_data(m_rhs)))
|
||||||
dst = m_rhs;
|
dst = m_rhs;
|
||||||
m_triangularMatrix.template solveInPlace<Side>(dst);
|
m_triangularMatrix.template solveInPlace<Side>(dst);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -331,11 +331,11 @@ inline void MatrixBase<Derived>::adjointInPlace()
|
|||||||
|
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
template<typename BinOp,typename NestedXpr,typename Rhs>
|
template<typename BinOp,typename Xpr,typename Rhs>
|
||||||
struct blas_traits<SelfCwiseBinaryOp<BinOp,NestedXpr,Rhs> >
|
struct blas_traits<SelfCwiseBinaryOp<BinOp,Xpr,Rhs> >
|
||||||
: blas_traits<NestedXpr>
|
: blas_traits<typename internal::remove_all<typename Xpr::Nested>::type>
|
||||||
{
|
{
|
||||||
typedef SelfCwiseBinaryOp<BinOp,NestedXpr,Rhs> XprType;
|
typedef SelfCwiseBinaryOp<BinOp,Xpr,Rhs> XprType;
|
||||||
static inline const XprType extract(const XprType& x) { return x; }
|
static inline const XprType extract(const XprType& x) { return x; }
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -392,7 +392,6 @@ struct checkTransposeAliasing_impl
|
|||||||
::run(extract_data(dst), other))
|
::run(extract_data(dst), other))
|
||||||
&& "aliasing detected during transposition, use transposeInPlace() "
|
&& "aliasing detected during transposition, use transposeInPlace() "
|
||||||
"or evaluate the rhs into a temporary using .eval()");
|
"or evaluate the rhs into a temporary using .eval()");
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -376,7 +376,8 @@ struct transposition_matrix_product_retval
|
|||||||
const int size = m_transpositions.size();
|
const int size = m_transpositions.size();
|
||||||
Index j = 0;
|
Index j = 0;
|
||||||
|
|
||||||
if(!(is_same<MatrixTypeNestedCleaned,Dest>::value && extract_data(dst) == extract_data(m_matrix)))
|
const typename Dest::Scalar *dst_data = internal::extract_data(dst);
|
||||||
|
if(!(is_same<MatrixTypeNestedCleaned,Dest>::value && dst_data!=0 && dst_data == extract_data(m_matrix)))
|
||||||
dst = m_matrix;
|
dst = m_matrix;
|
||||||
|
|
||||||
for(int k=(Transposed?size-1:0) ; Transposed?k>=0:k<size ; Transposed?--k:++k)
|
for(int k=(Transposed?size-1:0) ; Transposed?k>=0:k<size ; Transposed?--k:++k)
|
||||||
|
|||||||
@@ -76,14 +76,17 @@ template<typename Derived>
|
|||||||
template<typename Visitor>
|
template<typename Visitor>
|
||||||
void DenseBase<Derived>::visit(Visitor& visitor) const
|
void DenseBase<Derived>::visit(Visitor& visitor) const
|
||||||
{
|
{
|
||||||
|
typedef typename internal::remove_all<typename Derived::Nested>::type ThisNested;
|
||||||
|
typename Derived::Nested thisNested(derived());
|
||||||
|
|
||||||
enum { unroll = SizeAtCompileTime != Dynamic
|
enum { unroll = SizeAtCompileTime != Dynamic
|
||||||
&& CoeffReadCost != Dynamic
|
&& CoeffReadCost != Dynamic
|
||||||
&& (SizeAtCompileTime == 1 || internal::functor_traits<Visitor>::Cost != Dynamic)
|
&& (SizeAtCompileTime == 1 || internal::functor_traits<Visitor>::Cost != Dynamic)
|
||||||
&& SizeAtCompileTime * CoeffReadCost + (SizeAtCompileTime-1) * internal::functor_traits<Visitor>::Cost
|
&& SizeAtCompileTime * CoeffReadCost + (SizeAtCompileTime-1) * internal::functor_traits<Visitor>::Cost
|
||||||
<= EIGEN_UNROLLING_LIMIT };
|
<= EIGEN_UNROLLING_LIMIT };
|
||||||
return internal::visitor_impl<Visitor, Derived,
|
return internal::visitor_impl<Visitor, ThisNested,
|
||||||
unroll ? int(SizeAtCompileTime) : Dynamic
|
unroll ? int(SizeAtCompileTime) : Dynamic
|
||||||
>::run(derived(), visitor);
|
>::run(thisNested, visitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|||||||
@@ -235,63 +235,27 @@ template<> EIGEN_STRONG_INLINE Packet4i pload<Packet4i>(const int* from) { E
|
|||||||
return _mm_loadu_ps(from);
|
return _mm_loadu_ps(from);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
template<> EIGEN_STRONG_INLINE Packet2d ploadu<Packet2d>(const double* from) { EIGEN_DEBUG_UNALIGNED_LOAD return _mm_loadu_pd(from); }
|
|
||||||
template<> EIGEN_STRONG_INLINE Packet4i ploadu<Packet4i>(const int* from) { EIGEN_DEBUG_UNALIGNED_LOAD return _mm_loadu_si128(reinterpret_cast<const Packet4i*>(from)); }
|
|
||||||
#else
|
#else
|
||||||
// Fast unaligned loads. Note that here we cannot directly use intrinsics: this would
|
|
||||||
// require pointer casting to incompatible pointer types and leads to invalid code
|
|
||||||
// because of the strict aliasing rule. The "dummy" stuff are required to enforce
|
|
||||||
// a correct instruction dependency.
|
|
||||||
// TODO: do the same for MSVC (ICC is compatible)
|
|
||||||
// NOTE: with the code below, MSVC's compiler crashes!
|
// NOTE: with the code below, MSVC's compiler crashes!
|
||||||
|
|
||||||
#if defined(__GNUC__) && defined(__i386__)
|
|
||||||
// bug 195: gcc/i386 emits weird x87 fldl/fstpl instructions for _mm_load_sd
|
|
||||||
#define EIGEN_AVOID_CUSTOM_UNALIGNED_LOADS 1
|
|
||||||
#elif defined(__clang__)
|
|
||||||
// bug 201: Segfaults in __mm_loadh_pd with clang 2.8
|
|
||||||
#define EIGEN_AVOID_CUSTOM_UNALIGNED_LOADS 1
|
|
||||||
#else
|
|
||||||
#define EIGEN_AVOID_CUSTOM_UNALIGNED_LOADS 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
template<> EIGEN_STRONG_INLINE Packet4f ploadu<Packet4f>(const float* from)
|
template<> EIGEN_STRONG_INLINE Packet4f ploadu<Packet4f>(const float* from)
|
||||||
{
|
{
|
||||||
EIGEN_DEBUG_UNALIGNED_LOAD
|
EIGEN_DEBUG_UNALIGNED_LOAD
|
||||||
#if EIGEN_AVOID_CUSTOM_UNALIGNED_LOADS
|
|
||||||
return _mm_loadu_ps(from);
|
return _mm_loadu_ps(from);
|
||||||
#else
|
|
||||||
__m128d res;
|
|
||||||
res = _mm_load_sd((const double*)(from)) ;
|
|
||||||
res = _mm_loadh_pd(res, (const double*)(from+2)) ;
|
|
||||||
return _mm_castpd_ps(res);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
template<> EIGEN_STRONG_INLINE Packet2d ploadu<Packet2d>(const double* from)
|
template<> EIGEN_STRONG_INLINE Packet2d ploadu<Packet2d>(const double* from)
|
||||||
{
|
{
|
||||||
EIGEN_DEBUG_UNALIGNED_LOAD
|
EIGEN_DEBUG_UNALIGNED_LOAD
|
||||||
#if EIGEN_AVOID_CUSTOM_UNALIGNED_LOADS
|
|
||||||
return _mm_loadu_pd(from);
|
return _mm_loadu_pd(from);
|
||||||
#else
|
|
||||||
__m128d res;
|
|
||||||
res = _mm_load_sd(from) ;
|
|
||||||
res = _mm_loadh_pd(res,from+1);
|
|
||||||
return res;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
template<> EIGEN_STRONG_INLINE Packet4i ploadu<Packet4i>(const int* from)
|
template<> EIGEN_STRONG_INLINE Packet4i ploadu<Packet4i>(const int* from)
|
||||||
{
|
{
|
||||||
EIGEN_DEBUG_UNALIGNED_LOAD
|
EIGEN_DEBUG_UNALIGNED_LOAD
|
||||||
#if EIGEN_AVOID_CUSTOM_UNALIGNED_LOADS
|
return _mm_loadu_si128(reinterpret_cast<const __m128i*>(from));
|
||||||
return _mm_loadu_si128(reinterpret_cast<const Packet4i*>(from));
|
|
||||||
#else
|
|
||||||
__m128d res;
|
|
||||||
res = _mm_load_sd((const double*)(from)) ;
|
|
||||||
res = _mm_loadh_pd(res, (const double*)(from+2)) ;
|
|
||||||
return _mm_castpd_si128(res);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
template<> EIGEN_STRONG_INLINE Packet4f ploaddup<Packet4f>(const float* from)
|
template<> EIGEN_STRONG_INLINE Packet4f ploaddup<Packet4f>(const float* from)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -140,8 +140,10 @@ static void run(Index rows, Index cols, Index depth,
|
|||||||
// Release all the sub blocks B'_j of B' for the current thread,
|
// Release all the sub blocks B'_j of B' for the current thread,
|
||||||
// i.e., we simply decrement the number of users by 1
|
// i.e., we simply decrement the number of users by 1
|
||||||
for(Index j=0; j<threads; ++j)
|
for(Index j=0; j<threads; ++j)
|
||||||
|
{
|
||||||
#pragma omp atomic
|
#pragma omp atomic
|
||||||
--(info[j].users);
|
info[j].users -= 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -390,13 +392,17 @@ class GeneralProduct<Lhs, Rhs, GemmProduct>
|
|||||||
|
|
||||||
GeneralProduct(const Lhs& lhs, const Rhs& rhs) : Base(lhs,rhs)
|
GeneralProduct(const Lhs& lhs, const Rhs& rhs) : Base(lhs,rhs)
|
||||||
{
|
{
|
||||||
|
#if !(defined(EIGEN_NO_STATIC_ASSERT) && defined(EIGEN_NO_DEBUG))
|
||||||
typedef internal::scalar_product_op<LhsScalar,RhsScalar> BinOp;
|
typedef internal::scalar_product_op<LhsScalar,RhsScalar> BinOp;
|
||||||
EIGEN_CHECK_BINARY_COMPATIBILIY(BinOp,LhsScalar,RhsScalar);
|
EIGEN_CHECK_BINARY_COMPATIBILIY(BinOp,LhsScalar,RhsScalar);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Dest> void scaleAndAddTo(Dest& dst, const Scalar& alpha) const
|
template<typename Dest> void scaleAndAddTo(Dest& dst, const Scalar& alpha) const
|
||||||
{
|
{
|
||||||
eigen_assert(dst.rows()==m_lhs.rows() && dst.cols()==m_rhs.cols());
|
eigen_assert(dst.rows()==m_lhs.rows() && dst.cols()==m_rhs.cols());
|
||||||
|
if(m_lhs.cols()==0 || m_lhs.rows()==0 || m_rhs.cols()==0)
|
||||||
|
return;
|
||||||
|
|
||||||
typename internal::add_const_on_value_type<ActualLhsType>::type lhs = LhsBlasTraits::extract(m_lhs);
|
typename internal::add_const_on_value_type<ActualLhsType>::type lhs = LhsBlasTraits::extract(m_lhs);
|
||||||
typename internal::add_const_on_value_type<ActualRhsType>::type rhs = RhsBlasTraits::extract(m_rhs);
|
typename internal::add_const_on_value_type<ActualRhsType>::type rhs = RhsBlasTraits::extract(m_rhs);
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ EIGEN_DONT_INLINE void triangular_solve_matrix<Scalar,Index,OnTheLeft,Mode,Conju
|
|||||||
// coherence when accessing the rhs elements
|
// coherence when accessing the rhs elements
|
||||||
std::ptrdiff_t l1, l2;
|
std::ptrdiff_t l1, l2;
|
||||||
manage_caching_sizes(GetAction, &l1, &l2);
|
manage_caching_sizes(GetAction, &l1, &l2);
|
||||||
Index subcols = cols>0 ? l2/(4 * sizeof(Scalar) * otherStride) : 0;
|
Index subcols = cols>0 ? l2/(4 * sizeof(Scalar) * std::max<Index>(otherStride,size)) : 0;
|
||||||
subcols = std::max<Index>((subcols/Traits::nr)*Traits::nr, Traits::nr);
|
subcols = std::max<Index>((subcols/Traits::nr)*Traits::nr, Traits::nr);
|
||||||
|
|
||||||
for(Index k2=IsLower ? 0 : size;
|
for(Index k2=IsLower ? 0 : size;
|
||||||
@@ -115,8 +115,9 @@ EIGEN_DONT_INLINE void triangular_solve_matrix<Scalar,Index,OnTheLeft,Mode,Conju
|
|||||||
{
|
{
|
||||||
// TODO write a small kernel handling this (can be shared with trsv)
|
// TODO write a small kernel handling this (can be shared with trsv)
|
||||||
Index i = IsLower ? k2+k1+k : k2-k1-k-1;
|
Index i = IsLower ? k2+k1+k : k2-k1-k-1;
|
||||||
Index s = IsLower ? k2+k1 : i+1;
|
|
||||||
Index rs = actualPanelWidth - k - 1; // remaining size
|
Index rs = actualPanelWidth - k - 1; // remaining size
|
||||||
|
Index s = TriStorageOrder==RowMajor ? (IsLower ? k2+k1 : i+1)
|
||||||
|
: IsLower ? i+1 : i-rs;
|
||||||
|
|
||||||
Scalar a = (Mode & UnitDiag) ? Scalar(1) : Scalar(1)/conj(tri(i,i));
|
Scalar a = (Mode & UnitDiag) ? Scalar(1) : Scalar(1)/conj(tri(i,i));
|
||||||
for (Index j=j2; j<j2+actual_cols; ++j)
|
for (Index j=j2; j<j2+actual_cols; ++j)
|
||||||
@@ -133,7 +134,6 @@ EIGEN_DONT_INLINE void triangular_solve_matrix<Scalar,Index,OnTheLeft,Mode,Conju
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Index s = IsLower ? i+1 : i-rs;
|
|
||||||
Scalar b = (other(i,j) *= a);
|
Scalar b = (other(i,j) *= a);
|
||||||
Scalar* r = &other(s,j);
|
Scalar* r = &other(s,j);
|
||||||
const Scalar* l = &tri(s,i);
|
const Scalar* l = &tri(s,i);
|
||||||
|
|||||||
@@ -42,16 +42,29 @@ template<bool Conjugate> struct conj_if;
|
|||||||
|
|
||||||
template<> struct conj_if<true> {
|
template<> struct conj_if<true> {
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline T operator()(const T& x) { return numext::conj(x); }
|
inline T operator()(const T& x) const { return numext::conj(x); }
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline T pconj(const T& x) { return internal::pconj(x); }
|
inline T pconj(const T& x) const { return internal::pconj(x); }
|
||||||
};
|
};
|
||||||
|
|
||||||
template<> struct conj_if<false> {
|
template<> struct conj_if<false> {
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline const T& operator()(const T& x) { return x; }
|
inline const T& operator()(const T& x) const { return x; }
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline const T& pconj(const T& x) { return x; }
|
inline const T& pconj(const T& x) const { return x; }
|
||||||
|
};
|
||||||
|
|
||||||
|
// Generic implementation for custom complex types.
|
||||||
|
template<typename LhsScalar, typename RhsScalar, bool ConjLhs, bool ConjRhs>
|
||||||
|
struct conj_helper
|
||||||
|
{
|
||||||
|
typedef typename scalar_product_traits<LhsScalar,RhsScalar>::ReturnType Scalar;
|
||||||
|
|
||||||
|
EIGEN_STRONG_INLINE Scalar pmadd(const LhsScalar& x, const RhsScalar& y, const Scalar& c) const
|
||||||
|
{ return padd(c, pmul(x,y)); }
|
||||||
|
|
||||||
|
EIGEN_STRONG_INLINE Scalar pmul(const LhsScalar& x, const RhsScalar& y) const
|
||||||
|
{ return conj_if<ConjLhs>()(x) * conj_if<ConjRhs>()(y); }
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Scalar> struct conj_helper<Scalar,Scalar,false,false>
|
template<typename Scalar> struct conj_helper<Scalar,Scalar,false,false>
|
||||||
@@ -171,12 +184,13 @@ template<typename XprType> struct blas_traits
|
|||||||
};
|
};
|
||||||
|
|
||||||
// pop conjugate
|
// pop conjugate
|
||||||
template<typename Scalar, typename NestedXpr>
|
template<typename Scalar, typename Xpr>
|
||||||
struct blas_traits<CwiseUnaryOp<scalar_conjugate_op<Scalar>, NestedXpr> >
|
struct blas_traits<CwiseUnaryOp<scalar_conjugate_op<Scalar>, Xpr> >
|
||||||
: blas_traits<NestedXpr>
|
: blas_traits<typename internal::remove_all<typename Xpr::Nested>::type>
|
||||||
{
|
{
|
||||||
|
typedef typename internal::remove_all<typename Xpr::Nested>::type NestedXpr;
|
||||||
typedef blas_traits<NestedXpr> Base;
|
typedef blas_traits<NestedXpr> Base;
|
||||||
typedef CwiseUnaryOp<scalar_conjugate_op<Scalar>, NestedXpr> XprType;
|
typedef CwiseUnaryOp<scalar_conjugate_op<Scalar>, Xpr> XprType;
|
||||||
typedef typename Base::ExtractType ExtractType;
|
typedef typename Base::ExtractType ExtractType;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
@@ -188,12 +202,13 @@ struct blas_traits<CwiseUnaryOp<scalar_conjugate_op<Scalar>, NestedXpr> >
|
|||||||
};
|
};
|
||||||
|
|
||||||
// pop scalar multiple
|
// pop scalar multiple
|
||||||
template<typename Scalar, typename NestedXpr>
|
template<typename Scalar, typename Xpr>
|
||||||
struct blas_traits<CwiseUnaryOp<scalar_multiple_op<Scalar>, NestedXpr> >
|
struct blas_traits<CwiseUnaryOp<scalar_multiple_op<Scalar>, Xpr> >
|
||||||
: blas_traits<NestedXpr>
|
: blas_traits<typename internal::remove_all<typename Xpr::Nested>::type>
|
||||||
{
|
{
|
||||||
|
typedef typename internal::remove_all<typename Xpr::Nested>::type NestedXpr;
|
||||||
typedef blas_traits<NestedXpr> Base;
|
typedef blas_traits<NestedXpr> Base;
|
||||||
typedef CwiseUnaryOp<scalar_multiple_op<Scalar>, NestedXpr> XprType;
|
typedef CwiseUnaryOp<scalar_multiple_op<Scalar>, Xpr> XprType;
|
||||||
typedef typename Base::ExtractType ExtractType;
|
typedef typename Base::ExtractType ExtractType;
|
||||||
static inline ExtractType extract(const XprType& x) { return Base::extract(x.nestedExpression()); }
|
static inline ExtractType extract(const XprType& x) { return Base::extract(x.nestedExpression()); }
|
||||||
static inline Scalar extractScalarFactor(const XprType& x)
|
static inline Scalar extractScalarFactor(const XprType& x)
|
||||||
@@ -201,12 +216,13 @@ struct blas_traits<CwiseUnaryOp<scalar_multiple_op<Scalar>, NestedXpr> >
|
|||||||
};
|
};
|
||||||
|
|
||||||
// pop opposite
|
// pop opposite
|
||||||
template<typename Scalar, typename NestedXpr>
|
template<typename Scalar, typename Xpr>
|
||||||
struct blas_traits<CwiseUnaryOp<scalar_opposite_op<Scalar>, NestedXpr> >
|
struct blas_traits<CwiseUnaryOp<scalar_opposite_op<Scalar>, Xpr> >
|
||||||
: blas_traits<NestedXpr>
|
: blas_traits<typename internal::remove_all<typename Xpr::Nested>::type>
|
||||||
{
|
{
|
||||||
|
typedef typename internal::remove_all<typename Xpr::Nested>::type NestedXpr;
|
||||||
typedef blas_traits<NestedXpr> Base;
|
typedef blas_traits<NestedXpr> Base;
|
||||||
typedef CwiseUnaryOp<scalar_opposite_op<Scalar>, NestedXpr> XprType;
|
typedef CwiseUnaryOp<scalar_opposite_op<Scalar>, Xpr> XprType;
|
||||||
typedef typename Base::ExtractType ExtractType;
|
typedef typename Base::ExtractType ExtractType;
|
||||||
static inline ExtractType extract(const XprType& x) { return Base::extract(x.nestedExpression()); }
|
static inline ExtractType extract(const XprType& x) { return Base::extract(x.nestedExpression()); }
|
||||||
static inline Scalar extractScalarFactor(const XprType& x)
|
static inline Scalar extractScalarFactor(const XprType& x)
|
||||||
@@ -214,13 +230,14 @@ struct blas_traits<CwiseUnaryOp<scalar_opposite_op<Scalar>, NestedXpr> >
|
|||||||
};
|
};
|
||||||
|
|
||||||
// pop/push transpose
|
// pop/push transpose
|
||||||
template<typename NestedXpr>
|
template<typename Xpr>
|
||||||
struct blas_traits<Transpose<NestedXpr> >
|
struct blas_traits<Transpose<Xpr> >
|
||||||
: blas_traits<NestedXpr>
|
: blas_traits<typename internal::remove_all<typename Xpr::Nested>::type>
|
||||||
{
|
{
|
||||||
|
typedef typename internal::remove_all<typename Xpr::Nested>::type NestedXpr;
|
||||||
typedef typename NestedXpr::Scalar Scalar;
|
typedef typename NestedXpr::Scalar Scalar;
|
||||||
typedef blas_traits<NestedXpr> Base;
|
typedef blas_traits<NestedXpr> Base;
|
||||||
typedef Transpose<NestedXpr> XprType;
|
typedef Transpose<Xpr> XprType;
|
||||||
typedef Transpose<const typename Base::_ExtractType> ExtractType; // const to get rid of a compile error; anyway blas traits are only used on the RHS
|
typedef Transpose<const typename Base::_ExtractType> ExtractType; // const to get rid of a compile error; anyway blas traits are only used on the RHS
|
||||||
typedef Transpose<const typename Base::_ExtractType> _ExtractType;
|
typedef Transpose<const typename Base::_ExtractType> _ExtractType;
|
||||||
typedef typename conditional<bool(Base::HasUsableDirectAccess),
|
typedef typename conditional<bool(Base::HasUsableDirectAccess),
|
||||||
|
|||||||
@@ -162,7 +162,7 @@ const unsigned int HereditaryBits = RowMajorBit
|
|||||||
/** \ingroup enums
|
/** \ingroup enums
|
||||||
* Enum containing possible values for the \p Mode parameter of
|
* Enum containing possible values for the \p Mode parameter of
|
||||||
* MatrixBase::selfadjointView() and MatrixBase::triangularView(). */
|
* MatrixBase::selfadjointView() and MatrixBase::triangularView(). */
|
||||||
enum {
|
enum UpLoType {
|
||||||
/** View matrix as a lower triangular matrix. */
|
/** View matrix as a lower triangular matrix. */
|
||||||
Lower=0x1,
|
Lower=0x1,
|
||||||
/** View matrix as an upper triangular matrix. */
|
/** View matrix as an upper triangular matrix. */
|
||||||
@@ -187,7 +187,7 @@ enum {
|
|||||||
|
|
||||||
/** \ingroup enums
|
/** \ingroup enums
|
||||||
* Enum for indicating whether an object is aligned or not. */
|
* Enum for indicating whether an object is aligned or not. */
|
||||||
enum {
|
enum AlignmentType {
|
||||||
/** Object is not correctly aligned for vectorization. */
|
/** Object is not correctly aligned for vectorization. */
|
||||||
Unaligned=0,
|
Unaligned=0,
|
||||||
/** Object is aligned for vectorization. */
|
/** Object is aligned for vectorization. */
|
||||||
@@ -217,7 +217,7 @@ enum DirectionType {
|
|||||||
|
|
||||||
/** \internal \ingroup enums
|
/** \internal \ingroup enums
|
||||||
* Enum to specify how to traverse the entries of a matrix. */
|
* Enum to specify how to traverse the entries of a matrix. */
|
||||||
enum {
|
enum TraversalType {
|
||||||
/** \internal Default traversal, no vectorization, no index-based access */
|
/** \internal Default traversal, no vectorization, no index-based access */
|
||||||
DefaultTraversal,
|
DefaultTraversal,
|
||||||
/** \internal No vectorization, use index-based access to have only one for loop instead of 2 nested loops */
|
/** \internal No vectorization, use index-based access to have only one for loop instead of 2 nested loops */
|
||||||
@@ -239,7 +239,7 @@ enum {
|
|||||||
|
|
||||||
/** \internal \ingroup enums
|
/** \internal \ingroup enums
|
||||||
* Enum to specify whether to unroll loops when traversing over the entries of a matrix. */
|
* Enum to specify whether to unroll loops when traversing over the entries of a matrix. */
|
||||||
enum {
|
enum UnrollingType {
|
||||||
/** \internal Do not unroll loops. */
|
/** \internal Do not unroll loops. */
|
||||||
NoUnrolling,
|
NoUnrolling,
|
||||||
/** \internal Unroll only the inner loop, but not the outer loop. */
|
/** \internal Unroll only the inner loop, but not the outer loop. */
|
||||||
@@ -251,7 +251,7 @@ enum {
|
|||||||
|
|
||||||
/** \internal \ingroup enums
|
/** \internal \ingroup enums
|
||||||
* Enum to specify whether to use the default (built-in) implementation or the specialization. */
|
* Enum to specify whether to use the default (built-in) implementation or the specialization. */
|
||||||
enum {
|
enum SpecializedType {
|
||||||
Specialized,
|
Specialized,
|
||||||
BuiltIn
|
BuiltIn
|
||||||
};
|
};
|
||||||
@@ -259,7 +259,7 @@ enum {
|
|||||||
/** \ingroup enums
|
/** \ingroup enums
|
||||||
* Enum containing possible values for the \p _Options template parameter of
|
* Enum containing possible values for the \p _Options template parameter of
|
||||||
* Matrix, Array and BandMatrix. */
|
* Matrix, Array and BandMatrix. */
|
||||||
enum {
|
enum StorageOptions {
|
||||||
/** Storage order is column major (see \ref TopicStorageOrders). */
|
/** Storage order is column major (see \ref TopicStorageOrders). */
|
||||||
ColMajor = 0,
|
ColMajor = 0,
|
||||||
/** Storage order is row major (see \ref TopicStorageOrders). */
|
/** Storage order is row major (see \ref TopicStorageOrders). */
|
||||||
@@ -272,7 +272,7 @@ enum {
|
|||||||
|
|
||||||
/** \ingroup enums
|
/** \ingroup enums
|
||||||
* Enum for specifying whether to apply or solve on the left or right. */
|
* Enum for specifying whether to apply or solve on the left or right. */
|
||||||
enum {
|
enum SideType {
|
||||||
/** Apply transformation on the left. */
|
/** Apply transformation on the left. */
|
||||||
OnTheLeft = 1,
|
OnTheLeft = 1,
|
||||||
/** Apply transformation on the right. */
|
/** Apply transformation on the right. */
|
||||||
@@ -418,7 +418,7 @@ namespace Architecture
|
|||||||
|
|
||||||
/** \internal \ingroup enums
|
/** \internal \ingroup enums
|
||||||
* Enum used as template parameter in GeneralProduct. */
|
* Enum used as template parameter in GeneralProduct. */
|
||||||
enum { CoeffBasedProductMode, LazyCoeffBasedProductMode, OuterProduct, InnerProduct, GemvProduct, GemmProduct };
|
enum ProductImplType { CoeffBasedProductMode, LazyCoeffBasedProductMode, OuterProduct, InnerProduct, GemvProduct, GemmProduct };
|
||||||
|
|
||||||
/** \internal \ingroup enums
|
/** \internal \ingroup enums
|
||||||
* Enum used in experimental parallel implementation. */
|
* Enum used in experimental parallel implementation. */
|
||||||
|
|||||||
@@ -35,6 +35,14 @@
|
|||||||
#pragma clang diagnostic push
|
#pragma clang diagnostic push
|
||||||
#endif
|
#endif
|
||||||
#pragma clang diagnostic ignored "-Wconstant-logical-operand"
|
#pragma clang diagnostic ignored "-Wconstant-logical-operand"
|
||||||
|
|
||||||
|
#elif defined __GNUC__ && __GNUC__>=6
|
||||||
|
|
||||||
|
#ifndef EIGEN_PERMANENTLY_DISABLE_STUPID_WARNINGS
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
#endif
|
||||||
|
#pragma GCC diagnostic ignored "-Wignored-attributes"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif // not EIGEN_WARNINGS_DISABLED
|
#endif // not EIGEN_WARNINGS_DISABLED
|
||||||
|
|||||||
@@ -13,23 +13,292 @@
|
|||||||
|
|
||||||
#define EIGEN_WORLD_VERSION 3
|
#define EIGEN_WORLD_VERSION 3
|
||||||
#define EIGEN_MAJOR_VERSION 2
|
#define EIGEN_MAJOR_VERSION 2
|
||||||
#define EIGEN_MINOR_VERSION 7
|
#define EIGEN_MINOR_VERSION 10
|
||||||
|
|
||||||
#define EIGEN_VERSION_AT_LEAST(x,y,z) (EIGEN_WORLD_VERSION>x || (EIGEN_WORLD_VERSION>=x && \
|
#define EIGEN_VERSION_AT_LEAST(x,y,z) (EIGEN_WORLD_VERSION>x || (EIGEN_WORLD_VERSION>=x && \
|
||||||
(EIGEN_MAJOR_VERSION>y || (EIGEN_MAJOR_VERSION>=y && \
|
(EIGEN_MAJOR_VERSION>y || (EIGEN_MAJOR_VERSION>=y && \
|
||||||
EIGEN_MINOR_VERSION>=z))))
|
EIGEN_MINOR_VERSION>=z))))
|
||||||
|
|
||||||
|
|
||||||
|
// Compiler identification, EIGEN_COMP_*
|
||||||
|
|
||||||
|
/// \internal EIGEN_COMP_GNUC set to 1 for all compilers compatible with GCC
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
|
#define EIGEN_COMP_GNUC 1
|
||||||
|
#else
|
||||||
|
#define EIGEN_COMP_GNUC 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// \internal EIGEN_COMP_CLANG set to 1 if the compiler is clang (alias for __clang__)
|
||||||
|
#if defined(__clang__)
|
||||||
|
#define EIGEN_COMP_CLANG 1
|
||||||
|
#else
|
||||||
|
#define EIGEN_COMP_CLANG 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/// \internal EIGEN_COMP_LLVM set to 1 if the compiler backend is llvm
|
||||||
|
#if defined(__llvm__)
|
||||||
|
#define EIGEN_COMP_LLVM 1
|
||||||
|
#else
|
||||||
|
#define EIGEN_COMP_LLVM 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// \internal EIGEN_COMP_ICC set to __INTEL_COMPILER if the compiler is Intel compiler, 0 otherwise
|
||||||
|
#if defined(__INTEL_COMPILER)
|
||||||
|
#define EIGEN_COMP_ICC __INTEL_COMPILER
|
||||||
|
#else
|
||||||
|
#define EIGEN_COMP_ICC 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// \internal EIGEN_COMP_MINGW set to 1 if the compiler is mingw
|
||||||
|
#if defined(__MINGW32__)
|
||||||
|
#define EIGEN_COMP_MINGW 1
|
||||||
|
#else
|
||||||
|
#define EIGEN_COMP_MINGW 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// \internal EIGEN_COMP_SUNCC set to 1 if the compiler is Solaris Studio
|
||||||
|
#if defined(__SUNPRO_CC)
|
||||||
|
#define EIGEN_COMP_SUNCC 1
|
||||||
|
#else
|
||||||
|
#define EIGEN_COMP_SUNCC 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// \internal EIGEN_COMP_MSVC set to _MSC_VER if the compiler is Microsoft Visual C++, 0 otherwise.
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#define EIGEN_COMP_MSVC _MSC_VER
|
||||||
|
#else
|
||||||
|
#define EIGEN_COMP_MSVC 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// \internal EIGEN_COMP_MSVC_STRICT set to 1 if the compiler is really Microsoft Visual C++ and not ,e.g., ICC
|
||||||
|
#if EIGEN_COMP_MSVC && !(EIGEN_COMP_ICC)
|
||||||
|
#define EIGEN_COMP_MSVC_STRICT _MSC_VER
|
||||||
|
#else
|
||||||
|
#define EIGEN_COMP_MSVC_STRICT 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// \internal EIGEN_COMP_IBM set to 1 if the compiler is IBM XL C++
|
||||||
|
#if defined(__IBMCPP__) || defined(__xlc__)
|
||||||
|
#define EIGEN_COMP_IBM 1
|
||||||
|
#else
|
||||||
|
#define EIGEN_COMP_IBM 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// \internal EIGEN_COMP_PGI set to 1 if the compiler is Portland Group Compiler
|
||||||
|
#if defined(__PGI)
|
||||||
|
#define EIGEN_COMP_PGI 1
|
||||||
|
#else
|
||||||
|
#define EIGEN_COMP_PGI 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// \internal EIGEN_COMP_ARM set to 1 if the compiler is ARM Compiler
|
||||||
|
#if defined(__CC_ARM) || defined(__ARMCC_VERSION)
|
||||||
|
#define EIGEN_COMP_ARM 1
|
||||||
|
#else
|
||||||
|
#define EIGEN_COMP_ARM 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/// \internal EIGEN_GNUC_STRICT set to 1 if the compiler is really GCC and not a compatible compiler (e.g., ICC, clang, mingw, etc.)
|
||||||
|
#if EIGEN_COMP_GNUC && !(EIGEN_COMP_CLANG || EIGEN_COMP_ICC || EIGEN_COMP_MINGW || EIGEN_COMP_PGI || EIGEN_COMP_IBM || EIGEN_COMP_ARM )
|
||||||
|
#define EIGEN_COMP_GNUC_STRICT 1
|
||||||
|
#else
|
||||||
|
#define EIGEN_COMP_GNUC_STRICT 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if EIGEN_COMP_GNUC
|
||||||
#define EIGEN_GNUC_AT_LEAST(x,y) ((__GNUC__==x && __GNUC_MINOR__>=y) || __GNUC__>x)
|
#define EIGEN_GNUC_AT_LEAST(x,y) ((__GNUC__==x && __GNUC_MINOR__>=y) || __GNUC__>x)
|
||||||
|
#define EIGEN_GNUC_AT_MOST(x,y) ((__GNUC__==x && __GNUC_MINOR__<=y) || __GNUC__<x)
|
||||||
|
#define EIGEN_GNUC_AT(x,y) ( __GNUC__==x && __GNUC_MINOR__==y )
|
||||||
#else
|
#else
|
||||||
#define EIGEN_GNUC_AT_LEAST(x,y) 0
|
#define EIGEN_GNUC_AT_LEAST(x,y) 0
|
||||||
|
#define EIGEN_GNUC_AT_MOST(x,y) 0
|
||||||
|
#define EIGEN_GNUC_AT(x,y) 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __GNUC__
|
// FIXME: could probably be removed as we do not support gcc 3.x anymore
|
||||||
#define EIGEN_GNUC_AT_MOST(x,y) ((__GNUC__==x && __GNUC_MINOR__<=y) || __GNUC__<x)
|
#if EIGEN_COMP_GNUC && (__GNUC__ <= 3)
|
||||||
|
#define EIGEN_GCC3_OR_OLDER 1
|
||||||
#else
|
#else
|
||||||
#define EIGEN_GNUC_AT_MOST(x,y) 0
|
#define EIGEN_GCC3_OR_OLDER 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
// Architecture identification, EIGEN_ARCH_*
|
||||||
|
|
||||||
|
#if defined(__x86_64__) || defined(_M_X64) || defined(__amd64)
|
||||||
|
#define EIGEN_ARCH_x86_64 1
|
||||||
|
#else
|
||||||
|
#define EIGEN_ARCH_x86_64 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__i386__) || defined(_M_IX86) || defined(_X86_) || defined(__i386)
|
||||||
|
#define EIGEN_ARCH_i386 1
|
||||||
|
#else
|
||||||
|
#define EIGEN_ARCH_i386 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if EIGEN_ARCH_x86_64 || EIGEN_ARCH_i386
|
||||||
|
#define EIGEN_ARCH_i386_OR_x86_64 1
|
||||||
|
#else
|
||||||
|
#define EIGEN_ARCH_i386_OR_x86_64 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// \internal EIGEN_ARCH_ARM set to 1 if the architecture is ARM
|
||||||
|
#if defined(__arm__)
|
||||||
|
#define EIGEN_ARCH_ARM 1
|
||||||
|
#else
|
||||||
|
#define EIGEN_ARCH_ARM 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// \internal EIGEN_ARCH_ARM64 set to 1 if the architecture is ARM64
|
||||||
|
#if defined(__aarch64__)
|
||||||
|
#define EIGEN_ARCH_ARM64 1
|
||||||
|
#else
|
||||||
|
#define EIGEN_ARCH_ARM64 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if EIGEN_ARCH_ARM || EIGEN_ARCH_ARM64
|
||||||
|
#define EIGEN_ARCH_ARM_OR_ARM64 1
|
||||||
|
#else
|
||||||
|
#define EIGEN_ARCH_ARM_OR_ARM64 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// \internal EIGEN_ARCH_MIPS set to 1 if the architecture is MIPS
|
||||||
|
#if defined(__mips__) || defined(__mips)
|
||||||
|
#define EIGEN_ARCH_MIPS 1
|
||||||
|
#else
|
||||||
|
#define EIGEN_ARCH_MIPS 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// \internal EIGEN_ARCH_SPARC set to 1 if the architecture is SPARC
|
||||||
|
#if defined(__sparc__) || defined(__sparc)
|
||||||
|
#define EIGEN_ARCH_SPARC 1
|
||||||
|
#else
|
||||||
|
#define EIGEN_ARCH_SPARC 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// \internal EIGEN_ARCH_IA64 set to 1 if the architecture is Intel Itanium
|
||||||
|
#if defined(__ia64__)
|
||||||
|
#define EIGEN_ARCH_IA64 1
|
||||||
|
#else
|
||||||
|
#define EIGEN_ARCH_IA64 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// \internal EIGEN_ARCH_PPC set to 1 if the architecture is PowerPC
|
||||||
|
#if defined(__powerpc__) || defined(__ppc__) || defined(_M_PPC)
|
||||||
|
#define EIGEN_ARCH_PPC 1
|
||||||
|
#else
|
||||||
|
#define EIGEN_ARCH_PPC 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Operating system identification, EIGEN_OS_*
|
||||||
|
|
||||||
|
/// \internal EIGEN_OS_UNIX set to 1 if the OS is a unix variant
|
||||||
|
#if defined(__unix__) || defined(__unix)
|
||||||
|
#define EIGEN_OS_UNIX 1
|
||||||
|
#else
|
||||||
|
#define EIGEN_OS_UNIX 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// \internal EIGEN_OS_LINUX set to 1 if the OS is based on Linux kernel
|
||||||
|
#if defined(__linux__)
|
||||||
|
#define EIGEN_OS_LINUX 1
|
||||||
|
#else
|
||||||
|
#define EIGEN_OS_LINUX 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// \internal EIGEN_OS_ANDROID set to 1 if the OS is Android
|
||||||
|
// note: ANDROID is defined when using ndk_build, __ANDROID__ is defined when using a standalone toolchain.
|
||||||
|
#if defined(__ANDROID__) || defined(ANDROID)
|
||||||
|
#define EIGEN_OS_ANDROID 1
|
||||||
|
#else
|
||||||
|
#define EIGEN_OS_ANDROID 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// \internal EIGEN_OS_GNULINUX set to 1 if the OS is GNU Linux and not Linux-based OS (e.g., not android)
|
||||||
|
#if defined(__gnu_linux__) && !(EIGEN_OS_ANDROID)
|
||||||
|
#define EIGEN_OS_GNULINUX 1
|
||||||
|
#else
|
||||||
|
#define EIGEN_OS_GNULINUX 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// \internal EIGEN_OS_BSD set to 1 if the OS is a BSD variant
|
||||||
|
#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__) || defined(__DragonFly__)
|
||||||
|
#define EIGEN_OS_BSD 1
|
||||||
|
#else
|
||||||
|
#define EIGEN_OS_BSD 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// \internal EIGEN_OS_MAC set to 1 if the OS is MacOS
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
#define EIGEN_OS_MAC 1
|
||||||
|
#else
|
||||||
|
#define EIGEN_OS_MAC 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// \internal EIGEN_OS_QNX set to 1 if the OS is QNX
|
||||||
|
#if defined(__QNX__)
|
||||||
|
#define EIGEN_OS_QNX 1
|
||||||
|
#else
|
||||||
|
#define EIGEN_OS_QNX 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// \internal EIGEN_OS_WIN set to 1 if the OS is Windows based
|
||||||
|
#if defined(_WIN32)
|
||||||
|
#define EIGEN_OS_WIN 1
|
||||||
|
#else
|
||||||
|
#define EIGEN_OS_WIN 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// \internal EIGEN_OS_WIN64 set to 1 if the OS is Windows 64bits
|
||||||
|
#if defined(_WIN64)
|
||||||
|
#define EIGEN_OS_WIN64 1
|
||||||
|
#else
|
||||||
|
#define EIGEN_OS_WIN64 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// \internal EIGEN_OS_WINCE set to 1 if the OS is Windows CE
|
||||||
|
#if defined(_WIN32_WCE)
|
||||||
|
#define EIGEN_OS_WINCE 1
|
||||||
|
#else
|
||||||
|
#define EIGEN_OS_WINCE 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// \internal EIGEN_OS_CYGWIN set to 1 if the OS is Windows/Cygwin
|
||||||
|
#if defined(__CYGWIN__)
|
||||||
|
#define EIGEN_OS_CYGWIN 1
|
||||||
|
#else
|
||||||
|
#define EIGEN_OS_CYGWIN 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// \internal EIGEN_OS_WIN_STRICT set to 1 if the OS is really Windows and not some variants
|
||||||
|
#if EIGEN_OS_WIN && !( EIGEN_OS_WINCE || EIGEN_OS_CYGWIN )
|
||||||
|
#define EIGEN_OS_WIN_STRICT 1
|
||||||
|
#else
|
||||||
|
#define EIGEN_OS_WIN_STRICT 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// \internal EIGEN_OS_SUN set to 1 if the OS is SUN
|
||||||
|
#if (defined(sun) || defined(__sun)) && !(defined(__SVR4) || defined(__svr4__))
|
||||||
|
#define EIGEN_OS_SUN 1
|
||||||
|
#else
|
||||||
|
#define EIGEN_OS_SUN 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// \internal EIGEN_OS_SOLARIS set to 1 if the OS is Solaris
|
||||||
|
#if (defined(sun) || defined(__sun)) && (defined(__SVR4) || defined(__svr4__))
|
||||||
|
#define EIGEN_OS_SOLARIS 1
|
||||||
|
#else
|
||||||
|
#define EIGEN_OS_SOLARIS 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#if EIGEN_GNUC_AT_MOST(4,3) && !defined(__clang__)
|
#if EIGEN_GNUC_AT_MOST(4,3) && !defined(__clang__)
|
||||||
// see bug 89
|
// see bug 89
|
||||||
#define EIGEN_SAFE_TO_USE_STANDARD_ASSERT_MACRO 0
|
#define EIGEN_SAFE_TO_USE_STANDARD_ASSERT_MACRO 0
|
||||||
@@ -37,12 +306,6 @@
|
|||||||
#define EIGEN_SAFE_TO_USE_STANDARD_ASSERT_MACRO 1
|
#define EIGEN_SAFE_TO_USE_STANDARD_ASSERT_MACRO 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__GNUC__) && (__GNUC__ <= 3)
|
|
||||||
#define EIGEN_GCC3_OR_OLDER 1
|
|
||||||
#else
|
|
||||||
#define EIGEN_GCC3_OR_OLDER 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// 16 byte alignment is only useful for vectorization. Since it affects the ABI, we need to enable
|
// 16 byte alignment is only useful for vectorization. Since it affects the ABI, we need to enable
|
||||||
// 16 byte alignment on all platforms where vectorization might be enabled. In theory we could always
|
// 16 byte alignment on all platforms where vectorization might be enabled. In theory we could always
|
||||||
// enable alignment, but it can be a cause of problems on some platforms, so we just disable it in
|
// enable alignment, but it can be a cause of problems on some platforms, so we just disable it in
|
||||||
@@ -104,7 +367,7 @@
|
|||||||
|
|
||||||
// Do we support r-value references?
|
// Do we support r-value references?
|
||||||
#if (__has_feature(cxx_rvalue_references) || \
|
#if (__has_feature(cxx_rvalue_references) || \
|
||||||
defined(__GXX_EXPERIMENTAL_CXX0X__) || \
|
(defined(__cplusplus) && __cplusplus >= 201103L) || \
|
||||||
(defined(_MSC_VER) && _MSC_VER >= 1600))
|
(defined(_MSC_VER) && _MSC_VER >= 1600))
|
||||||
#define EIGEN_HAVE_RVALUE_REFERENCES
|
#define EIGEN_HAVE_RVALUE_REFERENCES
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -507,7 +507,12 @@ template<typename T> void smart_copy(const T* start, const T* end, T* target)
|
|||||||
|
|
||||||
template<typename T> struct smart_copy_helper<T,true> {
|
template<typename T> struct smart_copy_helper<T,true> {
|
||||||
static inline void run(const T* start, const T* end, T* target)
|
static inline void run(const T* start, const T* end, T* target)
|
||||||
{ memcpy(target, start, std::ptrdiff_t(end)-std::ptrdiff_t(start)); }
|
{
|
||||||
|
std::ptrdiff_t size = std::ptrdiff_t(end)-std::ptrdiff_t(start);
|
||||||
|
if(size==0) return;
|
||||||
|
eigen_internal_assert(start!=0 && end!=0 && target!=0);
|
||||||
|
memcpy(target, start, size);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T> struct smart_copy_helper<T,false> {
|
template<typename T> struct smart_copy_helper<T,false> {
|
||||||
@@ -515,7 +520,6 @@ template<typename T> struct smart_copy_helper<T,false> {
|
|||||||
{ std::copy(start, end, target); }
|
{ std::copy(start, end, target); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
*** Implementation of runtime stack allocation (falling back to malloc) ***
|
*** Implementation of runtime stack allocation (falling back to malloc) ***
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
@@ -630,6 +634,8 @@ template<typename T> class aligned_stack_memory_handler
|
|||||||
} \
|
} \
|
||||||
void operator delete(void * ptr) throw() { Eigen::internal::conditional_aligned_free<NeedsToAlign>(ptr); } \
|
void operator delete(void * ptr) throw() { Eigen::internal::conditional_aligned_free<NeedsToAlign>(ptr); } \
|
||||||
void operator delete[](void * ptr) throw() { Eigen::internal::conditional_aligned_free<NeedsToAlign>(ptr); } \
|
void operator delete[](void * ptr) throw() { Eigen::internal::conditional_aligned_free<NeedsToAlign>(ptr); } \
|
||||||
|
void operator delete(void * ptr, std::size_t /* sz */) throw() { Eigen::internal::conditional_aligned_free<NeedsToAlign>(ptr); } \
|
||||||
|
void operator delete[](void * ptr, std::size_t /* sz */) throw() { Eigen::internal::conditional_aligned_free<NeedsToAlign>(ptr); } \
|
||||||
/* in-place new and delete. since (at least afaik) there is no actual */ \
|
/* in-place new and delete. since (at least afaik) there is no actual */ \
|
||||||
/* memory allocated we can safely let the default implementation handle */ \
|
/* memory allocated we can safely let the default implementation handle */ \
|
||||||
/* this particular case. */ \
|
/* this particular case. */ \
|
||||||
@@ -653,99 +659,60 @@ template<typename T> class aligned_stack_memory_handler
|
|||||||
|
|
||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
/** \class aligned_allocator
|
/** \class aligned_allocator
|
||||||
* \ingroup Core_Module
|
* \ingroup Core_Module
|
||||||
*
|
*
|
||||||
* \brief STL compatible allocator to use with with 16 byte aligned types
|
* \brief STL compatible allocator to use with with 16 byte aligned types
|
||||||
*
|
*
|
||||||
* Example:
|
* Example:
|
||||||
* \code
|
* \code
|
||||||
* // Matrix4f requires 16 bytes alignment:
|
* // Matrix4f requires 16 bytes alignment:
|
||||||
* std::map< int, Matrix4f, std::less<int>,
|
* std::map< int, Matrix4f, std::less<int>,
|
||||||
* aligned_allocator<std::pair<const int, Matrix4f> > > my_map_mat4;
|
* aligned_allocator<std::pair<const int, Matrix4f> > > my_map_mat4;
|
||||||
* // Vector3f does not require 16 bytes alignment, no need to use Eigen's allocator:
|
* // Vector3f does not require 16 bytes alignment, no need to use Eigen's allocator:
|
||||||
* std::map< int, Vector3f > my_map_vec3;
|
* std::map< int, Vector3f > my_map_vec3;
|
||||||
* \endcode
|
* \endcode
|
||||||
*
|
*
|
||||||
* \sa \ref TopicStlContainers.
|
* \sa \blank \ref TopicStlContainers.
|
||||||
*/
|
*/
|
||||||
template<class T>
|
template<class T>
|
||||||
class aligned_allocator
|
class aligned_allocator : public std::allocator<T>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef size_t size_type;
|
typedef size_t size_type;
|
||||||
typedef std::ptrdiff_t difference_type;
|
typedef std::ptrdiff_t difference_type;
|
||||||
typedef T* pointer;
|
typedef T* pointer;
|
||||||
typedef const T* const_pointer;
|
typedef const T* const_pointer;
|
||||||
typedef T& reference;
|
typedef T& reference;
|
||||||
typedef const T& const_reference;
|
typedef const T& const_reference;
|
||||||
typedef T value_type;
|
typedef T value_type;
|
||||||
|
|
||||||
template<class U>
|
template<class U>
|
||||||
struct rebind
|
struct rebind
|
||||||
{
|
{
|
||||||
typedef aligned_allocator<U> other;
|
typedef aligned_allocator<U> other;
|
||||||
};
|
};
|
||||||
|
|
||||||
pointer address( reference value ) const
|
aligned_allocator() : std::allocator<T>() {}
|
||||||
{
|
|
||||||
return &value;
|
|
||||||
}
|
|
||||||
|
|
||||||
const_pointer address( const_reference value ) const
|
aligned_allocator(const aligned_allocator& other) : std::allocator<T>(other) {}
|
||||||
{
|
|
||||||
return &value;
|
|
||||||
}
|
|
||||||
|
|
||||||
aligned_allocator()
|
template<class U>
|
||||||
{
|
aligned_allocator(const aligned_allocator<U>& other) : std::allocator<T>(other) {}
|
||||||
}
|
|
||||||
|
|
||||||
aligned_allocator( const aligned_allocator& )
|
~aligned_allocator() {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class U>
|
pointer allocate(size_type num, const void* /*hint*/ = 0)
|
||||||
aligned_allocator( const aligned_allocator<U>& )
|
{
|
||||||
{
|
internal::check_size_for_overflow<T>(num);
|
||||||
}
|
return static_cast<pointer>( internal::aligned_malloc(num * sizeof(T)) );
|
||||||
|
}
|
||||||
|
|
||||||
~aligned_allocator()
|
void deallocate(pointer p, size_type /*num*/)
|
||||||
{
|
{
|
||||||
}
|
internal::aligned_free(p);
|
||||||
|
}
|
||||||
size_type max_size() const
|
|
||||||
{
|
|
||||||
return (std::numeric_limits<size_type>::max)();
|
|
||||||
}
|
|
||||||
|
|
||||||
pointer allocate( size_type num, const void* hint = 0 )
|
|
||||||
{
|
|
||||||
EIGEN_UNUSED_VARIABLE(hint);
|
|
||||||
internal::check_size_for_overflow<T>(num);
|
|
||||||
return static_cast<pointer>( internal::aligned_malloc( num * sizeof(T) ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
void construct( pointer p, const T& value )
|
|
||||||
{
|
|
||||||
::new( p ) T( value );
|
|
||||||
}
|
|
||||||
|
|
||||||
void destroy( pointer p )
|
|
||||||
{
|
|
||||||
p->~T();
|
|
||||||
}
|
|
||||||
|
|
||||||
void deallocate( pointer p, size_type /*num*/ )
|
|
||||||
{
|
|
||||||
internal::aligned_free( p );
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator!=(const aligned_allocator<T>& ) const
|
|
||||||
{ return false; }
|
|
||||||
|
|
||||||
bool operator==(const aligned_allocator<T>& ) const
|
|
||||||
{ return true; }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//---------- Cache sizes ----------
|
//---------- Cache sizes ----------
|
||||||
|
|||||||
@@ -8,7 +8,10 @@
|
|||||||
#pragma warning pop
|
#pragma warning pop
|
||||||
#elif defined __clang__
|
#elif defined __clang__
|
||||||
#pragma clang diagnostic pop
|
#pragma clang diagnostic pop
|
||||||
|
#elif defined __GNUC__ && __GNUC__>=6
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif // EIGEN_WARNINGS_DISABLED
|
#endif // EIGEN_WARNINGS_DISABLED
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
|
|
||||||
#ifndef EIGEN_NO_STATIC_ASSERT
|
#ifndef EIGEN_NO_STATIC_ASSERT
|
||||||
|
|
||||||
#if defined(__GXX_EXPERIMENTAL_CXX0X__) || (defined(_MSC_VER) && (_MSC_VER >= 1600))
|
#if __has_feature(cxx_static_assert) || (defined(__cplusplus) && __cplusplus >= 201103L) || (EIGEN_COMP_MSVC >= 1600)
|
||||||
|
|
||||||
// if native static_assert is enabled, let's use it
|
// if native static_assert is enabled, let's use it
|
||||||
#define EIGEN_STATIC_ASSERT(X,MSG) static_assert(X,#MSG);
|
#define EIGEN_STATIC_ASSERT(X,MSG) static_assert(X,#MSG);
|
||||||
|
|||||||
@@ -45,7 +45,6 @@ ComplexSchur<Matrix<EIGTYPE, Dynamic, Dynamic, EIGCOLROW> >& \
|
|||||||
ComplexSchur<Matrix<EIGTYPE, Dynamic, Dynamic, EIGCOLROW> >::compute(const Matrix<EIGTYPE, Dynamic, Dynamic, EIGCOLROW>& matrix, bool computeU) \
|
ComplexSchur<Matrix<EIGTYPE, Dynamic, Dynamic, EIGCOLROW> >::compute(const Matrix<EIGTYPE, Dynamic, Dynamic, EIGCOLROW>& matrix, bool computeU) \
|
||||||
{ \
|
{ \
|
||||||
typedef Matrix<EIGTYPE, Dynamic, Dynamic, EIGCOLROW> MatrixType; \
|
typedef Matrix<EIGTYPE, Dynamic, Dynamic, EIGCOLROW> MatrixType; \
|
||||||
typedef MatrixType::Scalar Scalar; \
|
|
||||||
typedef MatrixType::RealScalar RealScalar; \
|
typedef MatrixType::RealScalar RealScalar; \
|
||||||
typedef std::complex<RealScalar> ComplexScalar; \
|
typedef std::complex<RealScalar> ComplexScalar; \
|
||||||
\
|
\
|
||||||
|
|||||||
@@ -327,13 +327,33 @@ GeneralizedEigenSolver<MatrixType>::compute(const MatrixType& A, const MatrixTyp
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Scalar p = Scalar(0.5) * (m_matS.coeff(i, i) - m_matS.coeff(i+1, i+1));
|
// We need to extract the generalized eigenvalues of the pair of a general 2x2 block S and a triangular 2x2 block T
|
||||||
Scalar z = sqrt(abs(p * p + m_matS.coeff(i+1, i) * m_matS.coeff(i, i+1)));
|
// From the eigen decomposition of T = U * E * U^-1,
|
||||||
m_alphas.coeffRef(i) = ComplexScalar(m_matS.coeff(i+1, i+1) + p, z);
|
// we can extract the eigenvalues of (U^-1 * S * U) / E
|
||||||
m_alphas.coeffRef(i+1) = ComplexScalar(m_matS.coeff(i+1, i+1) + p, -z);
|
// Here, we can take advantage that E = diag(T), and U = [ 1 T_01 ; 0 T_11-T_00], and U^-1 = [1 -T_11/(T_11-T_00) ; 0 1/(T_11-T_00)].
|
||||||
|
// Then taking beta=T_00*T_11*(T_11-T_00), we can avoid any division, and alpha is the eigenvalues of A = (U^-1 * S * U) * diag(T_11,T_00) * (T_11-T_00):
|
||||||
|
|
||||||
|
// T = [a b ; 0 c]
|
||||||
|
// S = [e f ; g h]
|
||||||
|
RealScalar a = m_realQZ.matrixT().coeff(i, i), b = m_realQZ.matrixT().coeff(i, i+1), c = m_realQZ.matrixT().coeff(i+1, i+1);
|
||||||
|
RealScalar e = m_matS.coeff(i, i), f = m_matS.coeff(i, i+1), g = m_matS.coeff(i+1, i), h = m_matS.coeff(i+1, i+1);
|
||||||
|
RealScalar d = c-a;
|
||||||
|
RealScalar gb = g*b;
|
||||||
|
Matrix<RealScalar,2,2> A;
|
||||||
|
A << (e*d-gb)*c, ((e*b+f*d-h*b)*d-gb*b)*a,
|
||||||
|
g*c , (gb+h*d)*a;
|
||||||
|
|
||||||
|
// NOTE, we could also compute the SVD of T's block during the QZ factorization so that the respective T block is guaranteed to be diagonal,
|
||||||
|
// and then we could directly apply the formula below (while taking care of scaling S columns by T11,T00):
|
||||||
|
|
||||||
|
Scalar p = Scalar(0.5) * (A.coeff(i, i) - A.coeff(i+1, i+1));
|
||||||
|
Scalar z = sqrt(abs(p * p + A.coeff(i+1, i) * A.coeff(i, i+1)));
|
||||||
|
m_alphas.coeffRef(i) = ComplexScalar(A.coeff(i+1, i+1) + p, z);
|
||||||
|
m_alphas.coeffRef(i+1) = ComplexScalar(A.coeff(i+1, i+1) + p, -z);
|
||||||
|
|
||||||
|
m_betas.coeffRef(i) =
|
||||||
|
m_betas.coeffRef(i+1) = a*c*d;
|
||||||
|
|
||||||
m_betas.coeffRef(i) = m_realQZ.matrixT().coeff(i,i);
|
|
||||||
m_betas.coeffRef(i+1) = m_realQZ.matrixT().coeff(i,i);
|
|
||||||
i += 2;
|
i += 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,10 +44,6 @@ template<> inline \
|
|||||||
RealSchur<Matrix<EIGTYPE, Dynamic, Dynamic, EIGCOLROW> >& \
|
RealSchur<Matrix<EIGTYPE, Dynamic, Dynamic, EIGCOLROW> >& \
|
||||||
RealSchur<Matrix<EIGTYPE, Dynamic, Dynamic, EIGCOLROW> >::compute(const Matrix<EIGTYPE, Dynamic, Dynamic, EIGCOLROW>& matrix, bool computeU) \
|
RealSchur<Matrix<EIGTYPE, Dynamic, Dynamic, EIGCOLROW> >::compute(const Matrix<EIGTYPE, Dynamic, Dynamic, EIGCOLROW>& matrix, bool computeU) \
|
||||||
{ \
|
{ \
|
||||||
typedef Matrix<EIGTYPE, Dynamic, Dynamic, EIGCOLROW> MatrixType; \
|
|
||||||
typedef MatrixType::Scalar Scalar; \
|
|
||||||
typedef MatrixType::RealScalar RealScalar; \
|
|
||||||
\
|
|
||||||
eigen_assert(matrix.cols() == matrix.rows()); \
|
eigen_assert(matrix.cols() == matrix.rows()); \
|
||||||
\
|
\
|
||||||
lapack_int n = matrix.cols(), sdim, info; \
|
lapack_int n = matrix.cols(), sdim, info; \
|
||||||
|
|||||||
@@ -367,10 +367,10 @@ void tridiagonalization_inplace(MatrixType& matA, CoeffVectorType& hCoeffs)
|
|||||||
hCoeffs.tail(n-i-1).noalias() = (matA.bottomRightCorner(remainingSize,remainingSize).template selfadjointView<Lower>()
|
hCoeffs.tail(n-i-1).noalias() = (matA.bottomRightCorner(remainingSize,remainingSize).template selfadjointView<Lower>()
|
||||||
* (conj(h) * matA.col(i).tail(remainingSize)));
|
* (conj(h) * matA.col(i).tail(remainingSize)));
|
||||||
|
|
||||||
hCoeffs.tail(n-i-1) += (conj(h)*Scalar(-0.5)*(hCoeffs.tail(remainingSize).dot(matA.col(i).tail(remainingSize)))) * matA.col(i).tail(n-i-1);
|
hCoeffs.tail(n-i-1) += (conj(h)*RealScalar(-0.5)*(hCoeffs.tail(remainingSize).dot(matA.col(i).tail(remainingSize)))) * matA.col(i).tail(n-i-1);
|
||||||
|
|
||||||
matA.bottomRightCorner(remainingSize, remainingSize).template selfadjointView<Lower>()
|
matA.bottomRightCorner(remainingSize, remainingSize).template selfadjointView<Lower>()
|
||||||
.rankUpdate(matA.col(i).tail(remainingSize), hCoeffs.tail(remainingSize), -1);
|
.rankUpdate(matA.col(i).tail(remainingSize), hCoeffs.tail(remainingSize), Scalar(-1));
|
||||||
|
|
||||||
matA.col(i).coeffRef(i+1) = beta;
|
matA.col(i).coeffRef(i+1) = beta;
|
||||||
hCoeffs.coeffRef(i) = h;
|
hCoeffs.coeffRef(i) = h;
|
||||||
|
|||||||
@@ -83,10 +83,17 @@ public:
|
|||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
inline explicit AngleAxis(const MatrixBase<Derived>& m) { *this = m; }
|
inline explicit AngleAxis(const MatrixBase<Derived>& m) { *this = m; }
|
||||||
|
|
||||||
|
/** \returns the value of the rotation angle in radian */
|
||||||
Scalar angle() const { return m_angle; }
|
Scalar angle() const { return m_angle; }
|
||||||
|
/** \returns a read-write reference to the stored angle in radian */
|
||||||
Scalar& angle() { return m_angle; }
|
Scalar& angle() { return m_angle; }
|
||||||
|
|
||||||
|
/** \returns the rotation axis */
|
||||||
const Vector3& axis() const { return m_axis; }
|
const Vector3& axis() const { return m_axis; }
|
||||||
|
/** \returns a read-write reference to the stored rotation axis.
|
||||||
|
*
|
||||||
|
* \warning The rotation axis must remain a \b unit vector.
|
||||||
|
*/
|
||||||
Vector3& axis() { return m_axis; }
|
Vector3& axis() { return m_axis; }
|
||||||
|
|
||||||
/** Concatenates two rotations */
|
/** Concatenates two rotations */
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ template<typename MatrixType,int _Direction> class Homogeneous
|
|||||||
inline Index rows() const { return m_matrix.rows() + (int(Direction)==Vertical ? 1 : 0); }
|
inline Index rows() const { return m_matrix.rows() + (int(Direction)==Vertical ? 1 : 0); }
|
||||||
inline Index cols() const { return m_matrix.cols() + (int(Direction)==Horizontal ? 1 : 0); }
|
inline Index cols() const { return m_matrix.cols() + (int(Direction)==Horizontal ? 1 : 0); }
|
||||||
|
|
||||||
inline Scalar coeff(Index row, Index col) const
|
inline Scalar coeff(Index row, Index col=0) const
|
||||||
{
|
{
|
||||||
if( (int(Direction)==Vertical && row==m_matrix.rows())
|
if( (int(Direction)==Vertical && row==m_matrix.rows())
|
||||||
|| (int(Direction)==Horizontal && col==m_matrix.cols()))
|
|| (int(Direction)==Horizontal && col==m_matrix.cols()))
|
||||||
|
|||||||
@@ -129,7 +129,7 @@ public:
|
|||||||
* determined by \a prec.
|
* determined by \a prec.
|
||||||
*
|
*
|
||||||
* \sa MatrixBase::isApprox() */
|
* \sa MatrixBase::isApprox() */
|
||||||
bool isApprox(const ParametrizedLine& other, typename NumTraits<Scalar>::Real prec = NumTraits<Scalar>::dummy_precision()) const
|
bool isApprox(const ParametrizedLine& other, const typename NumTraits<Scalar>::Real& prec = NumTraits<Scalar>::dummy_precision()) const
|
||||||
{ return m_origin.isApprox(other.m_origin, prec) && m_direction.isApprox(other.m_direction, prec); }
|
{ return m_origin.isApprox(other.m_origin, prec) && m_direction.isApprox(other.m_direction, prec); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|||||||
@@ -276,7 +276,7 @@ public:
|
|||||||
inline Coefficients& coeffs() { return m_coeffs;}
|
inline Coefficients& coeffs() { return m_coeffs;}
|
||||||
inline const Coefficients& coeffs() const { return m_coeffs;}
|
inline const Coefficients& coeffs() const { return m_coeffs;}
|
||||||
|
|
||||||
EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(IsAligned)
|
EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(bool(IsAligned))
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Coefficients m_coeffs;
|
Coefficients m_coeffs;
|
||||||
|
|||||||
@@ -102,15 +102,15 @@ template<int Mode> struct transform_make_affine;
|
|||||||
*
|
*
|
||||||
* However, unlike a plain matrix, the Transform class provides many features
|
* However, unlike a plain matrix, the Transform class provides many features
|
||||||
* simplifying both its assembly and usage. In particular, it can be composed
|
* simplifying both its assembly and usage. In particular, it can be composed
|
||||||
* with any other transformations (Transform,Translation,RotationBase,Matrix)
|
* with any other transformations (Transform,Translation,RotationBase,DiagonalMatrix)
|
||||||
* and can be directly used to transform implicit homogeneous vectors. All these
|
* and can be directly used to transform implicit homogeneous vectors. All these
|
||||||
* operations are handled via the operator*. For the composition of transformations,
|
* operations are handled via the operator*. For the composition of transformations,
|
||||||
* its principle consists to first convert the right/left hand sides of the product
|
* its principle consists to first convert the right/left hand sides of the product
|
||||||
* to a compatible (Dim+1)^2 matrix and then perform a pure matrix product.
|
* to a compatible (Dim+1)^2 matrix and then perform a pure matrix product.
|
||||||
* Of course, internally, operator* tries to perform the minimal number of operations
|
* Of course, internally, operator* tries to perform the minimal number of operations
|
||||||
* according to the nature of each terms. Likewise, when applying the transform
|
* according to the nature of each terms. Likewise, when applying the transform
|
||||||
* to non homogeneous vectors, the latters are automatically promoted to homogeneous
|
* to points, the latters are automatically promoted to homogeneous vectors
|
||||||
* one before doing the matrix product. The convertions to homogeneous representations
|
* before doing the matrix product. The conventions to homogeneous representations
|
||||||
* are performed as follow:
|
* are performed as follow:
|
||||||
*
|
*
|
||||||
* \b Translation t (Dim)x(1):
|
* \b Translation t (Dim)x(1):
|
||||||
@@ -124,7 +124,7 @@ template<int Mode> struct transform_make_affine;
|
|||||||
* R & 0\\
|
* R & 0\\
|
||||||
* 0\,...\,0 & 1
|
* 0\,...\,0 & 1
|
||||||
* \end{array} \right) \f$
|
* \end{array} \right) \f$
|
||||||
*
|
*<!--
|
||||||
* \b Linear \b Matrix L (Dim)x(Dim):
|
* \b Linear \b Matrix L (Dim)x(Dim):
|
||||||
* \f$ \left( \begin{array}{cc}
|
* \f$ \left( \begin{array}{cc}
|
||||||
* L & 0\\
|
* L & 0\\
|
||||||
@@ -136,14 +136,20 @@ template<int Mode> struct transform_make_affine;
|
|||||||
* A\\
|
* A\\
|
||||||
* 0\,...\,0\,1
|
* 0\,...\,0\,1
|
||||||
* \end{array} \right) \f$
|
* \end{array} \right) \f$
|
||||||
|
*-->
|
||||||
|
* \b Scaling \b DiagonalMatrix S (Dim)x(Dim):
|
||||||
|
* \f$ \left( \begin{array}{cc}
|
||||||
|
* S & 0\\
|
||||||
|
* 0\,...\,0 & 1
|
||||||
|
* \end{array} \right) \f$
|
||||||
*
|
*
|
||||||
* \b Column \b vector v (Dim)x(1):
|
* \b Column \b point v (Dim)x(1):
|
||||||
* \f$ \left( \begin{array}{c}
|
* \f$ \left( \begin{array}{c}
|
||||||
* v\\
|
* v\\
|
||||||
* 1
|
* 1
|
||||||
* \end{array} \right) \f$
|
* \end{array} \right) \f$
|
||||||
*
|
*
|
||||||
* \b Set \b of \b column \b vectors V1...Vn (Dim)x(n):
|
* \b Set \b of \b column \b points V1...Vn (Dim)x(n):
|
||||||
* \f$ \left( \begin{array}{ccc}
|
* \f$ \left( \begin{array}{ccc}
|
||||||
* v_1 & ... & v_n\\
|
* v_1 & ... & v_n\\
|
||||||
* 1 & ... & 1
|
* 1 & ... & 1
|
||||||
@@ -384,26 +390,39 @@ public:
|
|||||||
/** \returns a writable expression of the translation vector of the transformation */
|
/** \returns a writable expression of the translation vector of the transformation */
|
||||||
inline TranslationPart translation() { return TranslationPart(m_matrix,0,Dim); }
|
inline TranslationPart translation() { return TranslationPart(m_matrix,0,Dim); }
|
||||||
|
|
||||||
/** \returns an expression of the product between the transform \c *this and a matrix expression \a other
|
/** \returns an expression of the product between the transform \c *this and a matrix expression \a other.
|
||||||
*
|
*
|
||||||
* The right hand side \a other might be either:
|
* The right-hand-side \a other can be either:
|
||||||
* \li a vector of size Dim,
|
|
||||||
* \li an homogeneous vector of size Dim+1,
|
* \li an homogeneous vector of size Dim+1,
|
||||||
* \li a set of vectors of size Dim x Dynamic,
|
* \li a set of homogeneous vectors of size Dim+1 x N,
|
||||||
* \li a set of homogeneous vectors of size Dim+1 x Dynamic,
|
|
||||||
* \li a linear transformation matrix of size Dim x Dim,
|
|
||||||
* \li an affine transformation matrix of size Dim x Dim+1,
|
|
||||||
* \li a transformation matrix of size Dim+1 x Dim+1.
|
* \li a transformation matrix of size Dim+1 x Dim+1.
|
||||||
|
*
|
||||||
|
* Moreover, if \c *this represents an affine transformation (i.e., Mode!=Projective), then \a other can also be:
|
||||||
|
* \li a point of size Dim (computes: \code this->linear() * other + this->translation()\endcode),
|
||||||
|
* \li a set of N points as a Dim x N matrix (computes: \code (this->linear() * other).colwise() + this->translation()\endcode),
|
||||||
|
*
|
||||||
|
* In all cases, the return type is a matrix or vector of same sizes as the right-hand-side \a other.
|
||||||
|
*
|
||||||
|
* If you want to interpret \a other as a linear or affine transformation, then first convert it to a Transform<> type,
|
||||||
|
* or do your own cooking.
|
||||||
|
*
|
||||||
|
* Finally, if you want to apply Affine transformations to vectors, then explicitly apply the linear part only:
|
||||||
|
* \code
|
||||||
|
* Affine3f A;
|
||||||
|
* Vector3f v1, v2;
|
||||||
|
* v2 = A.linear() * v1;
|
||||||
|
* \endcode
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
// note: this function is defined here because some compilers cannot find the respective declaration
|
// note: this function is defined here because some compilers cannot find the respective declaration
|
||||||
template<typename OtherDerived>
|
template<typename OtherDerived>
|
||||||
EIGEN_STRONG_INLINE const typename internal::transform_right_product_impl<Transform, OtherDerived>::ResultType
|
EIGEN_STRONG_INLINE const typename OtherDerived::PlainObject
|
||||||
operator * (const EigenBase<OtherDerived> &other) const
|
operator * (const EigenBase<OtherDerived> &other) const
|
||||||
{ return internal::transform_right_product_impl<Transform, OtherDerived>::run(*this,other.derived()); }
|
{ return internal::transform_right_product_impl<Transform, OtherDerived>::run(*this,other.derived()); }
|
||||||
|
|
||||||
/** \returns the product expression of a transformation matrix \a a times a transform \a b
|
/** \returns the product expression of a transformation matrix \a a times a transform \a b
|
||||||
*
|
*
|
||||||
* The left hand side \a other might be either:
|
* The left hand side \a other can be either:
|
||||||
* \li a linear transformation matrix of size Dim x Dim,
|
* \li a linear transformation matrix of size Dim x Dim,
|
||||||
* \li an affine transformation matrix of size Dim x Dim+1,
|
* \li an affine transformation matrix of size Dim x Dim+1,
|
||||||
* \li a general transformation matrix of size Dim+1 x Dim+1.
|
* \li a general transformation matrix of size Dim+1 x Dim+1.
|
||||||
@@ -424,7 +443,7 @@ public:
|
|||||||
operator * (const DiagonalBase<DiagonalDerived> &b) const
|
operator * (const DiagonalBase<DiagonalDerived> &b) const
|
||||||
{
|
{
|
||||||
TransformTimeDiagonalReturnType res(*this);
|
TransformTimeDiagonalReturnType res(*this);
|
||||||
res.linear() *= b;
|
res.linearExt() *= b;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -538,7 +557,7 @@ public:
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Transform& operator*=(const DiagonalMatrix<Scalar,Dim>& s) { linear() *= s; return *this; }
|
inline Transform& operator*=(const DiagonalMatrix<Scalar,Dim>& s) { linearExt() *= s; return *this; }
|
||||||
|
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
inline Transform& operator=(const RotationBase<Derived,Dim>& r);
|
inline Transform& operator=(const RotationBase<Derived,Dim>& r);
|
||||||
@@ -809,7 +828,7 @@ Transform<Scalar,Dim,Mode,Options>::prescale(const MatrixBase<OtherDerived> &oth
|
|||||||
{
|
{
|
||||||
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim))
|
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim))
|
||||||
EIGEN_STATIC_ASSERT(Mode!=int(Isometry), THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS)
|
EIGEN_STATIC_ASSERT(Mode!=int(Isometry), THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS)
|
||||||
m_matrix.template block<Dim,HDim>(0,0).noalias() = (other.asDiagonal() * m_matrix.template block<Dim,HDim>(0,0));
|
affine().noalias() = (other.asDiagonal() * affine());
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1029,7 +1048,7 @@ void Transform<Scalar,Dim,Mode,Options>::computeRotationScaling(RotationMatrixTy
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** decomposes the linear part of the transformation as a product rotation x scaling, the scaling being
|
/** decomposes the linear part of the transformation as a product scaling x rotation, the scaling being
|
||||||
* not necessarily positive.
|
* not necessarily positive.
|
||||||
*
|
*
|
||||||
* If either pointer is zero, the corresponding computation is skipped.
|
* If either pointer is zero, the corresponding computation is skipped.
|
||||||
|
|||||||
@@ -130,8 +130,10 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Applies translation to vector */
|
/** Applies translation to vector */
|
||||||
inline VectorType operator* (const VectorType& other) const
|
template<typename Derived>
|
||||||
{ return m_coeffs + other; }
|
inline typename internal::enable_if<Derived::IsVectorAtCompileTime,VectorType>::type
|
||||||
|
operator* (const MatrixBase<Derived>& vec) const
|
||||||
|
{ return m_coeffs + vec.derived(); }
|
||||||
|
|
||||||
/** \returns the inverse translation (opposite) */
|
/** \returns the inverse translation (opposite) */
|
||||||
Translation inverse() const { return Translation(-m_coeffs); }
|
Translation inverse() const { return Translation(-m_coeffs); }
|
||||||
@@ -162,7 +164,7 @@ public:
|
|||||||
* determined by \a prec.
|
* determined by \a prec.
|
||||||
*
|
*
|
||||||
* \sa MatrixBase::isApprox() */
|
* \sa MatrixBase::isApprox() */
|
||||||
bool isApprox(const Translation& other, typename NumTraits<Scalar>::Real prec = NumTraits<Scalar>::dummy_precision()) const
|
bool isApprox(const Translation& other, const typename NumTraits<Scalar>::Real& prec = NumTraits<Scalar>::dummy_precision()) const
|
||||||
{ return m_coeffs.isApprox(other.m_coeffs, prec); }
|
{ return m_coeffs.isApprox(other.m_coeffs, prec); }
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -75,8 +75,9 @@ void MatrixBase<Derived>::makeHouseholder(
|
|||||||
|
|
||||||
RealScalar tailSqNorm = size()==1 ? RealScalar(0) : tail.squaredNorm();
|
RealScalar tailSqNorm = size()==1 ? RealScalar(0) : tail.squaredNorm();
|
||||||
Scalar c0 = coeff(0);
|
Scalar c0 = coeff(0);
|
||||||
|
const RealScalar tol = (std::numeric_limits<RealScalar>::min)();
|
||||||
|
|
||||||
if(tailSqNorm == RealScalar(0) && numext::imag(c0)==RealScalar(0))
|
if(tailSqNorm <= tol && numext::abs2(numext::imag(c0))<=tol)
|
||||||
{
|
{
|
||||||
tau = RealScalar(0);
|
tau = RealScalar(0);
|
||||||
beta = numext::real(c0);
|
beta = numext::real(c0);
|
||||||
|
|||||||
@@ -237,8 +237,9 @@ template<typename VectorsType, typename CoeffsType, int Side> class HouseholderS
|
|||||||
{
|
{
|
||||||
workspace.resize(rows());
|
workspace.resize(rows());
|
||||||
Index vecs = m_length;
|
Index vecs = m_length;
|
||||||
|
const typename Dest::Scalar *dst_data = internal::extract_data(dst);
|
||||||
if( internal::is_same<typename internal::remove_all<VectorsType>::type,Dest>::value
|
if( internal::is_same<typename internal::remove_all<VectorsType>::type,Dest>::value
|
||||||
&& internal::extract_data(dst) == internal::extract_data(m_vectors))
|
&& dst_data!=0 && dst_data == internal::extract_data(m_vectors))
|
||||||
{
|
{
|
||||||
// in-place
|
// in-place
|
||||||
dst.diagonal().setOnes();
|
dst.diagonal().setOnes();
|
||||||
|
|||||||
@@ -139,6 +139,8 @@ struct traits<ConjugateGradient<_MatrixType,_UpLo,_Preconditioner> >
|
|||||||
* By default the iterations start with x=0 as an initial guess of the solution.
|
* By default the iterations start with x=0 as an initial guess of the solution.
|
||||||
* One can control the start using the solveWithGuess() method.
|
* One can control the start using the solveWithGuess() method.
|
||||||
*
|
*
|
||||||
|
* ConjugateGradient can also be used in a matrix-free context, see the following \link MatrixfreeSolverExample example \endlink.
|
||||||
|
*
|
||||||
* \sa class SimplicialCholesky, DiagonalPreconditioner, IdentityPreconditioner
|
* \sa class SimplicialCholesky, DiagonalPreconditioner, IdentityPreconditioner
|
||||||
*/
|
*/
|
||||||
template< typename _MatrixType, int _UpLo, typename _Preconditioner>
|
template< typename _MatrixType, int _UpLo, typename _Preconditioner>
|
||||||
|
|||||||
@@ -688,7 +688,7 @@ struct solve_retval<FullPivLU<_MatrixType>, Rhs>
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
const Index rows = dec().rows(), cols = dec().cols(),
|
const Index rows = dec().rows(), cols = dec().cols(),
|
||||||
nonzero_pivots = dec().nonzeroPivots();
|
nonzero_pivots = dec().rank();
|
||||||
eigen_assert(rhs().rows() == rows);
|
eigen_assert(rhs().rows() == rows);
|
||||||
const Index smalldim = (std::min)(rows, cols);
|
const Index smalldim = (std::min)(rows, cols);
|
||||||
|
|
||||||
|
|||||||
@@ -290,7 +290,7 @@ struct inverse_impl : public ReturnByValue<inverse_impl<MatrixType> >
|
|||||||
{
|
{
|
||||||
const int Size = EIGEN_PLAIN_ENUM_MIN(MatrixType::ColsAtCompileTime,Dest::ColsAtCompileTime);
|
const int Size = EIGEN_PLAIN_ENUM_MIN(MatrixType::ColsAtCompileTime,Dest::ColsAtCompileTime);
|
||||||
EIGEN_ONLY_USED_FOR_DEBUG(Size);
|
EIGEN_ONLY_USED_FOR_DEBUG(Size);
|
||||||
eigen_assert(( (Size<=1) || (Size>4) || (extract_data(m_matrix)!=extract_data(dst)))
|
eigen_assert(( (Size<=1) || (Size>4) || (extract_data(m_matrix)!=0 && extract_data(m_matrix)!=extract_data(dst)))
|
||||||
&& "Aliasing problem detected in inverse(), you need to do inverse().eval() here.");
|
&& "Aliasing problem detected in inverse(), you need to do inverse().eval() here.");
|
||||||
|
|
||||||
compute_inverse<MatrixTypeNestedCleaned, Dest>::run(m_matrix, dst);
|
compute_inverse<MatrixTypeNestedCleaned, Dest>::run(m_matrix, dst);
|
||||||
|
|||||||
@@ -151,10 +151,12 @@ struct compute_inverse_size4<Architecture::SSE, float, MatrixType, ResultType>
|
|||||||
iC = _mm_mul_ps(rd,iC);
|
iC = _mm_mul_ps(rd,iC);
|
||||||
iD = _mm_mul_ps(rd,iD);
|
iD = _mm_mul_ps(rd,iD);
|
||||||
|
|
||||||
result.template writePacket<ResultAlignment>( 0, _mm_shuffle_ps(iA,iB,0x77));
|
DenseIndex res_stride = result.outerStride();
|
||||||
result.template writePacket<ResultAlignment>( 4, _mm_shuffle_ps(iA,iB,0x22));
|
float* res = result.data();
|
||||||
result.template writePacket<ResultAlignment>( 8, _mm_shuffle_ps(iC,iD,0x77));
|
pstoret<float, Packet4f, ResultAlignment>(res+0, _mm_shuffle_ps(iA,iB,0x77));
|
||||||
result.template writePacket<ResultAlignment>(12, _mm_shuffle_ps(iC,iD,0x22));
|
pstoret<float, Packet4f, ResultAlignment>(res+res_stride, _mm_shuffle_ps(iA,iB,0x22));
|
||||||
|
pstoret<float, Packet4f, ResultAlignment>(res+2*res_stride, _mm_shuffle_ps(iC,iD,0x77));
|
||||||
|
pstoret<float, Packet4f, ResultAlignment>(res+3*res_stride, _mm_shuffle_ps(iC,iD,0x22));
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
@@ -311,14 +313,16 @@ struct compute_inverse_size4<Architecture::SSE, double, MatrixType, ResultType>
|
|||||||
iC1 = _mm_sub_pd(_mm_mul_pd(B1, dC), iC1);
|
iC1 = _mm_sub_pd(_mm_mul_pd(B1, dC), iC1);
|
||||||
iC2 = _mm_sub_pd(_mm_mul_pd(B2, dC), iC2);
|
iC2 = _mm_sub_pd(_mm_mul_pd(B2, dC), iC2);
|
||||||
|
|
||||||
result.template writePacket<ResultAlignment>( 0, _mm_mul_pd(_mm_shuffle_pd(iA2, iA1, 3), d1)); // iA# / det
|
DenseIndex res_stride = result.outerStride();
|
||||||
result.template writePacket<ResultAlignment>( 4, _mm_mul_pd(_mm_shuffle_pd(iA2, iA1, 0), d2));
|
double* res = result.data();
|
||||||
result.template writePacket<ResultAlignment>( 2, _mm_mul_pd(_mm_shuffle_pd(iB2, iB1, 3), d1)); // iB# / det
|
pstoret<double, Packet2d, ResultAlignment>(res+0, _mm_mul_pd(_mm_shuffle_pd(iA2, iA1, 3), d1));
|
||||||
result.template writePacket<ResultAlignment>( 6, _mm_mul_pd(_mm_shuffle_pd(iB2, iB1, 0), d2));
|
pstoret<double, Packet2d, ResultAlignment>(res+res_stride, _mm_mul_pd(_mm_shuffle_pd(iA2, iA1, 0), d2));
|
||||||
result.template writePacket<ResultAlignment>( 8, _mm_mul_pd(_mm_shuffle_pd(iC2, iC1, 3), d1)); // iC# / det
|
pstoret<double, Packet2d, ResultAlignment>(res+2, _mm_mul_pd(_mm_shuffle_pd(iB2, iB1, 3), d1));
|
||||||
result.template writePacket<ResultAlignment>(12, _mm_mul_pd(_mm_shuffle_pd(iC2, iC1, 0), d2));
|
pstoret<double, Packet2d, ResultAlignment>(res+res_stride+2, _mm_mul_pd(_mm_shuffle_pd(iB2, iB1, 0), d2));
|
||||||
result.template writePacket<ResultAlignment>(10, _mm_mul_pd(_mm_shuffle_pd(iD2, iD1, 3), d1)); // iD# / det
|
pstoret<double, Packet2d, ResultAlignment>(res+2*res_stride, _mm_mul_pd(_mm_shuffle_pd(iC2, iC1, 3), d1));
|
||||||
result.template writePacket<ResultAlignment>(14, _mm_mul_pd(_mm_shuffle_pd(iD2, iD1, 0), d2));
|
pstoret<double, Packet2d, ResultAlignment>(res+3*res_stride, _mm_mul_pd(_mm_shuffle_pd(iC2, iC1, 0), d2));
|
||||||
|
pstoret<double, Packet2d, ResultAlignment>(res+2*res_stride+2,_mm_mul_pd(_mm_shuffle_pd(iD2, iD1, 3), d1));
|
||||||
|
pstoret<double, Packet2d, ResultAlignment>(res+3*res_stride+2,_mm_mul_pd(_mm_shuffle_pd(iD2, iD1, 0), d2));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
NOTE: this routine has been adapted from the CSparse library:
|
NOTE: this routine has been adapted from the CSparse library:
|
||||||
|
|
||||||
Copyright (c) 2006, Timothy A. Davis.
|
Copyright (c) 2006, Timothy A. Davis.
|
||||||
http://www.cise.ufl.edu/research/sparse/CSparse
|
http://www.suitesparse.com
|
||||||
|
|
||||||
CSparse is free software; you can redistribute it and/or
|
CSparse is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU Lesser General Public
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
|||||||
@@ -41,12 +41,8 @@
|
|||||||
//
|
//
|
||||||
// The colamd/symamd library is available at
|
// The colamd/symamd library is available at
|
||||||
//
|
//
|
||||||
// http://www.cise.ufl.edu/research/sparse/colamd/
|
// http://www.suitesparse.com
|
||||||
|
|
||||||
// This is the http://www.cise.ufl.edu/research/sparse/colamd/colamd.h
|
|
||||||
// file. It is required by the colamd.c, colamdmex.c, and symamdmex.c
|
|
||||||
// files, and by any C code that calls the routines whose prototypes are
|
|
||||||
// listed below, or that uses the colamd/symamd definitions listed below.
|
|
||||||
|
|
||||||
#ifndef EIGEN_COLAMD_H
|
#ifndef EIGEN_COLAMD_H
|
||||||
#define EIGEN_COLAMD_H
|
#define EIGEN_COLAMD_H
|
||||||
@@ -102,9 +98,6 @@ namespace internal {
|
|||||||
/* === Definitions ========================================================== */
|
/* === Definitions ========================================================== */
|
||||||
/* ========================================================================== */
|
/* ========================================================================== */
|
||||||
|
|
||||||
#define COLAMD_MAX(a,b) (((a) > (b)) ? (a) : (b))
|
|
||||||
#define COLAMD_MIN(a,b) (((a) < (b)) ? (a) : (b))
|
|
||||||
|
|
||||||
#define ONES_COMPLEMENT(r) (-(r)-1)
|
#define ONES_COMPLEMENT(r) (-(r)-1)
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
@@ -516,7 +509,7 @@ static Index init_rows_cols /* returns true if OK, or false otherwise */
|
|||||||
Col [col].start = p [col] ;
|
Col [col].start = p [col] ;
|
||||||
Col [col].length = p [col+1] - p [col] ;
|
Col [col].length = p [col+1] - p [col] ;
|
||||||
|
|
||||||
if (Col [col].length < 0)
|
if ((Col [col].length) < 0) // extra parentheses to work-around gcc bug 10200
|
||||||
{
|
{
|
||||||
/* column pointers must be non-decreasing */
|
/* column pointers must be non-decreasing */
|
||||||
stats [COLAMD_STATUS] = COLAMD_ERROR_col_length_negative ;
|
stats [COLAMD_STATUS] = COLAMD_ERROR_col_length_negative ;
|
||||||
@@ -739,8 +732,8 @@ static void init_scoring
|
|||||||
|
|
||||||
/* === Extract knobs ==================================================== */
|
/* === Extract knobs ==================================================== */
|
||||||
|
|
||||||
dense_row_count = COLAMD_MAX (0, COLAMD_MIN (knobs [COLAMD_DENSE_ROW] * n_col, n_col)) ;
|
dense_row_count = std::max<Index>(0, (std::min)(Index(knobs [COLAMD_DENSE_ROW] * n_col), n_col)) ;
|
||||||
dense_col_count = COLAMD_MAX (0, COLAMD_MIN (knobs [COLAMD_DENSE_COL] * n_row, n_row)) ;
|
dense_col_count = std::max<Index>(0, (std::min)(Index(knobs [COLAMD_DENSE_COL] * n_row), n_row)) ;
|
||||||
COLAMD_DEBUG1 (("colamd: densecount: %d %d\n", dense_row_count, dense_col_count)) ;
|
COLAMD_DEBUG1 (("colamd: densecount: %d %d\n", dense_row_count, dense_col_count)) ;
|
||||||
max_deg = 0 ;
|
max_deg = 0 ;
|
||||||
n_col2 = n_col ;
|
n_col2 = n_col ;
|
||||||
@@ -804,7 +797,7 @@ static void init_scoring
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* keep track of max degree of remaining rows */
|
/* keep track of max degree of remaining rows */
|
||||||
max_deg = COLAMD_MAX (max_deg, deg) ;
|
max_deg = (std::max)(max_deg, deg) ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
COLAMD_DEBUG1 (("colamd: Dense and null rows killed: %d\n", n_row - n_row2)) ;
|
COLAMD_DEBUG1 (("colamd: Dense and null rows killed: %d\n", n_row - n_row2)) ;
|
||||||
@@ -842,7 +835,7 @@ static void init_scoring
|
|||||||
/* add row's external degree */
|
/* add row's external degree */
|
||||||
score += Row [row].shared1.degree - 1 ;
|
score += Row [row].shared1.degree - 1 ;
|
||||||
/* guard against integer overflow */
|
/* guard against integer overflow */
|
||||||
score = COLAMD_MIN (score, n_col) ;
|
score = (std::min)(score, n_col) ;
|
||||||
}
|
}
|
||||||
/* determine pruned column length */
|
/* determine pruned column length */
|
||||||
col_length = (Index) (new_cp - &A [Col [c].start]) ;
|
col_length = (Index) (new_cp - &A [Col [c].start]) ;
|
||||||
@@ -914,7 +907,7 @@ static void init_scoring
|
|||||||
head [score] = c ;
|
head [score] = c ;
|
||||||
|
|
||||||
/* see if this score is less than current min */
|
/* see if this score is less than current min */
|
||||||
min_score = COLAMD_MIN (min_score, score) ;
|
min_score = (std::min)(min_score, score) ;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1040,7 +1033,7 @@ static Index find_ordering /* return the number of garbage collections */
|
|||||||
|
|
||||||
/* === Garbage_collection, if necessary ============================= */
|
/* === Garbage_collection, if necessary ============================= */
|
||||||
|
|
||||||
needed_memory = COLAMD_MIN (pivot_col_score, n_col - k) ;
|
needed_memory = (std::min)(pivot_col_score, n_col - k) ;
|
||||||
if (pfree + needed_memory >= Alen)
|
if (pfree + needed_memory >= Alen)
|
||||||
{
|
{
|
||||||
pfree = Eigen::internal::garbage_collection (n_row, n_col, Row, Col, A, &A [pfree]) ;
|
pfree = Eigen::internal::garbage_collection (n_row, n_col, Row, Col, A, &A [pfree]) ;
|
||||||
@@ -1099,7 +1092,7 @@ static Index find_ordering /* return the number of garbage collections */
|
|||||||
|
|
||||||
/* clear tag on pivot column */
|
/* clear tag on pivot column */
|
||||||
Col [pivot_col].shared1.thickness = pivot_col_thickness ;
|
Col [pivot_col].shared1.thickness = pivot_col_thickness ;
|
||||||
max_deg = COLAMD_MAX (max_deg, pivot_row_degree) ;
|
max_deg = (std::max)(max_deg, pivot_row_degree) ;
|
||||||
|
|
||||||
|
|
||||||
/* === Kill all rows used to construct pivot row ==================== */
|
/* === Kill all rows used to construct pivot row ==================== */
|
||||||
@@ -1273,7 +1266,7 @@ static Index find_ordering /* return the number of garbage collections */
|
|||||||
/* add set difference */
|
/* add set difference */
|
||||||
cur_score += row_mark - tag_mark ;
|
cur_score += row_mark - tag_mark ;
|
||||||
/* integer overflow... */
|
/* integer overflow... */
|
||||||
cur_score = COLAMD_MIN (cur_score, n_col) ;
|
cur_score = (std::min)(cur_score, n_col) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* recompute the column's length */
|
/* recompute the column's length */
|
||||||
@@ -1386,7 +1379,7 @@ static Index find_ordering /* return the number of garbage collections */
|
|||||||
cur_score -= Col [col].shared1.thickness ;
|
cur_score -= Col [col].shared1.thickness ;
|
||||||
|
|
||||||
/* make sure score is less or equal than the max score */
|
/* make sure score is less or equal than the max score */
|
||||||
cur_score = COLAMD_MIN (cur_score, max_score) ;
|
cur_score = (std::min)(cur_score, max_score) ;
|
||||||
COLAMD_ASSERT (cur_score >= 0) ;
|
COLAMD_ASSERT (cur_score >= 0) ;
|
||||||
|
|
||||||
/* store updated score */
|
/* store updated score */
|
||||||
@@ -1409,7 +1402,7 @@ static Index find_ordering /* return the number of garbage collections */
|
|||||||
head [cur_score] = col ;
|
head [cur_score] = col ;
|
||||||
|
|
||||||
/* see if this score is less than current min */
|
/* see if this score is less than current min */
|
||||||
min_score = COLAMD_MIN (min_score, cur_score) ;
|
min_score = (std::min)(min_score, cur_score) ;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,14 @@
|
|||||||
#ifndef EIGEN_PASTIXSUPPORT_H
|
#ifndef EIGEN_PASTIXSUPPORT_H
|
||||||
#define EIGEN_PASTIXSUPPORT_H
|
#define EIGEN_PASTIXSUPPORT_H
|
||||||
|
|
||||||
|
#if defined(DCOMPLEX)
|
||||||
|
#define PASTIX_COMPLEX COMPLEX
|
||||||
|
#define PASTIX_DCOMPLEX DCOMPLEX
|
||||||
|
#else
|
||||||
|
#define PASTIX_COMPLEX std::complex<float>
|
||||||
|
#define PASTIX_DCOMPLEX std::complex<double>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace Eigen {
|
namespace Eigen {
|
||||||
|
|
||||||
/** \ingroup PaStiXSupport_Module
|
/** \ingroup PaStiXSupport_Module
|
||||||
@@ -74,14 +82,14 @@ namespace internal
|
|||||||
{
|
{
|
||||||
if (n == 0) { ptr = NULL; idx = NULL; vals = NULL; }
|
if (n == 0) { ptr = NULL; idx = NULL; vals = NULL; }
|
||||||
if (nbrhs == 0) {x = NULL; nbrhs=1;}
|
if (nbrhs == 0) {x = NULL; nbrhs=1;}
|
||||||
c_pastix(pastix_data, pastix_comm, n, ptr, idx, reinterpret_cast<COMPLEX*>(vals), perm, invp, reinterpret_cast<COMPLEX*>(x), nbrhs, iparm, dparm);
|
c_pastix(pastix_data, pastix_comm, n, ptr, idx, reinterpret_cast<PASTIX_COMPLEX*>(vals), perm, invp, reinterpret_cast<PASTIX_COMPLEX*>(x), nbrhs, iparm, dparm);
|
||||||
}
|
}
|
||||||
|
|
||||||
void eigen_pastix(pastix_data_t **pastix_data, int pastix_comm, int n, int *ptr, int *idx, std::complex<double> *vals, int *perm, int * invp, std::complex<double> *x, int nbrhs, int *iparm, double *dparm)
|
void eigen_pastix(pastix_data_t **pastix_data, int pastix_comm, int n, int *ptr, int *idx, std::complex<double> *vals, int *perm, int * invp, std::complex<double> *x, int nbrhs, int *iparm, double *dparm)
|
||||||
{
|
{
|
||||||
if (n == 0) { ptr = NULL; idx = NULL; vals = NULL; }
|
if (n == 0) { ptr = NULL; idx = NULL; vals = NULL; }
|
||||||
if (nbrhs == 0) {x = NULL; nbrhs=1;}
|
if (nbrhs == 0) {x = NULL; nbrhs=1;}
|
||||||
z_pastix(pastix_data, pastix_comm, n, ptr, idx, reinterpret_cast<DCOMPLEX*>(vals), perm, invp, reinterpret_cast<DCOMPLEX*>(x), nbrhs, iparm, dparm);
|
z_pastix(pastix_data, pastix_comm, n, ptr, idx, reinterpret_cast<PASTIX_DCOMPLEX*>(vals), perm, invp, reinterpret_cast<PASTIX_DCOMPLEX*>(x), nbrhs, iparm, dparm);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert the matrix to Fortran-style Numbering
|
// Convert the matrix to Fortran-style Numbering
|
||||||
|
|||||||
@@ -221,11 +221,11 @@ class PardisoImpl
|
|||||||
m_type = type;
|
m_type = type;
|
||||||
bool symmetric = std::abs(m_type) < 10;
|
bool symmetric = std::abs(m_type) < 10;
|
||||||
m_iparm[0] = 1; // No solver default
|
m_iparm[0] = 1; // No solver default
|
||||||
m_iparm[1] = 3; // use Metis for the ordering
|
m_iparm[1] = 2; // use Metis for the ordering
|
||||||
m_iparm[2] = 1; // Numbers of processors, value of OMP_NUM_THREADS
|
m_iparm[2] = 0; // Reserved. Set to zero. (??Numbers of processors, value of OMP_NUM_THREADS??)
|
||||||
m_iparm[3] = 0; // No iterative-direct algorithm
|
m_iparm[3] = 0; // No iterative-direct algorithm
|
||||||
m_iparm[4] = 0; // No user fill-in reducing permutation
|
m_iparm[4] = 0; // No user fill-in reducing permutation
|
||||||
m_iparm[5] = 0; // Write solution into x
|
m_iparm[5] = 0; // Write solution into x, b is left unchanged
|
||||||
m_iparm[6] = 0; // Not in use
|
m_iparm[6] = 0; // Not in use
|
||||||
m_iparm[7] = 2; // Max numbers of iterative refinement steps
|
m_iparm[7] = 2; // Max numbers of iterative refinement steps
|
||||||
m_iparm[8] = 0; // Not in use
|
m_iparm[8] = 0; // Not in use
|
||||||
@@ -246,7 +246,10 @@ class PardisoImpl
|
|||||||
m_iparm[26] = 0; // No matrix checker
|
m_iparm[26] = 0; // No matrix checker
|
||||||
m_iparm[27] = (sizeof(RealScalar) == 4) ? 1 : 0;
|
m_iparm[27] = (sizeof(RealScalar) == 4) ? 1 : 0;
|
||||||
m_iparm[34] = 1; // C indexing
|
m_iparm[34] = 1; // C indexing
|
||||||
m_iparm[59] = 1; // Automatic switch between In-Core and Out-of-Core modes
|
m_iparm[36] = 0; // CSR
|
||||||
|
m_iparm[59] = 0; // 0 - In-Core ; 1 - Automatic switch between In-Core and Out-of-Core modes ; 2 - Out-of-Core
|
||||||
|
|
||||||
|
memset(m_pt, 0, sizeof(m_pt));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@@ -384,7 +387,6 @@ bool PardisoImpl<Base>::_solve(const MatrixBase<BDerived> &b, MatrixBase<XDerive
|
|||||||
m_matrix.valuePtr(), m_matrix.outerIndexPtr(), m_matrix.innerIndexPtr(),
|
m_matrix.valuePtr(), m_matrix.outerIndexPtr(), m_matrix.innerIndexPtr(),
|
||||||
m_perm.data(), nrhs, m_iparm.data(), m_msglvl,
|
m_perm.data(), nrhs, m_iparm.data(), m_msglvl,
|
||||||
rhs_ptr, x.derived().data());
|
rhs_ptr, x.derived().data());
|
||||||
|
|
||||||
return error==0;
|
return error==0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -397,6 +399,9 @@ bool PardisoImpl<Base>::_solve(const MatrixBase<BDerived> &b, MatrixBase<XDerive
|
|||||||
* using the Intel MKL PARDISO library. The sparse matrix A must be squared and invertible.
|
* using the Intel MKL PARDISO library. The sparse matrix A must be squared and invertible.
|
||||||
* The vectors or matrices X and B can be either dense or sparse.
|
* The vectors or matrices X and B can be either dense or sparse.
|
||||||
*
|
*
|
||||||
|
* By default, it runs in in-core mode. To enable PARDISO's out-of-core feature, set:
|
||||||
|
* \code solver.pardisoParameterArray()[59] = 1; \endcode
|
||||||
|
*
|
||||||
* \tparam _MatrixType the type of the sparse matrix A, it must be a SparseMatrix<>
|
* \tparam _MatrixType the type of the sparse matrix A, it must be a SparseMatrix<>
|
||||||
*
|
*
|
||||||
* \sa \ref TutorialSparseDirectSolvers
|
* \sa \ref TutorialSparseDirectSolvers
|
||||||
@@ -447,6 +452,9 @@ class PardisoLU : public PardisoImpl< PardisoLU<MatrixType> >
|
|||||||
* using the Intel MKL PARDISO library. The sparse matrix A must be selfajoint and positive definite.
|
* using the Intel MKL PARDISO library. The sparse matrix A must be selfajoint and positive definite.
|
||||||
* The vectors or matrices X and B can be either dense or sparse.
|
* The vectors or matrices X and B can be either dense or sparse.
|
||||||
*
|
*
|
||||||
|
* By default, it runs in in-core mode. To enable PARDISO's out-of-core feature, set:
|
||||||
|
* \code solver.pardisoParameterArray()[59] = 1; \endcode
|
||||||
|
*
|
||||||
* \tparam MatrixType the type of the sparse matrix A, it must be a SparseMatrix<>
|
* \tparam MatrixType the type of the sparse matrix A, it must be a SparseMatrix<>
|
||||||
* \tparam UpLo can be any bitwise combination of Upper, Lower. The default is Upper, meaning only the upper triangular part has to be used.
|
* \tparam UpLo can be any bitwise combination of Upper, Lower. The default is Upper, meaning only the upper triangular part has to be used.
|
||||||
* Upper|Lower can be used to tell both triangular parts can be used as input.
|
* Upper|Lower can be used to tell both triangular parts can be used as input.
|
||||||
@@ -507,6 +515,9 @@ class PardisoLLT : public PardisoImpl< PardisoLLT<MatrixType,_UpLo> >
|
|||||||
* For complex matrices, A can also be symmetric only, see the \a Options template parameter.
|
* For complex matrices, A can also be symmetric only, see the \a Options template parameter.
|
||||||
* The vectors or matrices X and B can be either dense or sparse.
|
* The vectors or matrices X and B can be either dense or sparse.
|
||||||
*
|
*
|
||||||
|
* By default, it runs in in-core mode. To enable PARDISO's out-of-core feature, set:
|
||||||
|
* \code solver.pardisoParameterArray()[59] = 1; \endcode
|
||||||
|
*
|
||||||
* \tparam MatrixType the type of the sparse matrix A, it must be a SparseMatrix<>
|
* \tparam MatrixType the type of the sparse matrix A, it must be a SparseMatrix<>
|
||||||
* \tparam Options can be any bitwise combination of Upper, Lower, and Symmetric. The default is Upper, meaning only the upper triangular part has to be used.
|
* \tparam Options can be any bitwise combination of Upper, Lower, and Symmetric. The default is Upper, meaning only the upper triangular part has to be used.
|
||||||
* Symmetric can be used for symmetric, non-selfadjoint complex matrices, the default being to assume a selfadjoint matrix.
|
* Symmetric can be used for symmetric, non-selfadjoint complex matrices, the default being to assume a selfadjoint matrix.
|
||||||
|
|||||||
@@ -127,9 +127,6 @@ template<typename _MatrixType> class ColPivHouseholderQR
|
|||||||
*
|
*
|
||||||
* \returns a solution.
|
* \returns a solution.
|
||||||
*
|
*
|
||||||
* \note The case where b is a matrix is not yet implemented. Also, this
|
|
||||||
* code is space inefficient.
|
|
||||||
*
|
|
||||||
* \note_about_checking_solutions
|
* \note_about_checking_solutions
|
||||||
*
|
*
|
||||||
* \note_about_arbitrary_choice_of_solution
|
* \note_about_arbitrary_choice_of_solution
|
||||||
|
|||||||
@@ -49,7 +49,6 @@ ColPivHouseholderQR<Matrix<EIGTYPE, Dynamic, Dynamic, EIGCOLROW, Dynamic, Dynami
|
|||||||
{ \
|
{ \
|
||||||
using std::abs; \
|
using std::abs; \
|
||||||
typedef Matrix<EIGTYPE, Dynamic, Dynamic, EIGCOLROW, Dynamic, Dynamic> MatrixType; \
|
typedef Matrix<EIGTYPE, Dynamic, Dynamic, EIGCOLROW, Dynamic, Dynamic> MatrixType; \
|
||||||
typedef MatrixType::Scalar Scalar; \
|
|
||||||
typedef MatrixType::RealScalar RealScalar; \
|
typedef MatrixType::RealScalar RealScalar; \
|
||||||
Index rows = matrix.rows();\
|
Index rows = matrix.rows();\
|
||||||
Index cols = matrix.cols();\
|
Index cols = matrix.cols();\
|
||||||
|
|||||||
@@ -134,9 +134,6 @@ template<typename _MatrixType> class FullPivHouseholderQR
|
|||||||
* \returns the exact or least-square solution if the rank is greater or equal to the number of columns of A,
|
* \returns the exact or least-square solution if the rank is greater or equal to the number of columns of A,
|
||||||
* and an arbitrary solution otherwise.
|
* and an arbitrary solution otherwise.
|
||||||
*
|
*
|
||||||
* \note The case where b is a matrix is not yet implemented. Also, this
|
|
||||||
* code is space inefficient.
|
|
||||||
*
|
|
||||||
* \note_about_checking_solutions
|
* \note_about_checking_solutions
|
||||||
*
|
*
|
||||||
* \note_about_arbitrary_choice_of_solution
|
* \note_about_arbitrary_choice_of_solution
|
||||||
|
|||||||
@@ -107,9 +107,6 @@ template<typename _MatrixType> class HouseholderQR
|
|||||||
*
|
*
|
||||||
* \returns a solution.
|
* \returns a solution.
|
||||||
*
|
*
|
||||||
* \note The case where b is a matrix is not yet implemented. Also, this
|
|
||||||
* code is space inefficient.
|
|
||||||
*
|
|
||||||
* \note_about_checking_solutions
|
* \note_about_checking_solutions
|
||||||
*
|
*
|
||||||
* \note_about_arbitrary_choice_of_solution
|
* \note_about_arbitrary_choice_of_solution
|
||||||
|
|||||||
@@ -359,29 +359,42 @@ struct svd_precondition_2x2_block_to_be_real<MatrixType, QRPreconditioner, false
|
|||||||
{
|
{
|
||||||
typedef JacobiSVD<MatrixType, QRPreconditioner> SVD;
|
typedef JacobiSVD<MatrixType, QRPreconditioner> SVD;
|
||||||
typedef typename SVD::Index Index;
|
typedef typename SVD::Index Index;
|
||||||
static void run(typename SVD::WorkMatrixType&, SVD&, Index, Index) {}
|
typedef typename MatrixType::RealScalar RealScalar;
|
||||||
|
static bool run(typename SVD::WorkMatrixType&, SVD&, Index, Index, RealScalar&) { return true; }
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename MatrixType, int QRPreconditioner>
|
template<typename MatrixType, int QRPreconditioner>
|
||||||
struct svd_precondition_2x2_block_to_be_real<MatrixType, QRPreconditioner, true>
|
struct svd_precondition_2x2_block_to_be_real<MatrixType, QRPreconditioner, true>
|
||||||
{
|
{
|
||||||
typedef JacobiSVD<MatrixType, QRPreconditioner> SVD;
|
typedef JacobiSVD<MatrixType, QRPreconditioner> SVD;
|
||||||
|
typedef typename SVD::Index Index;
|
||||||
typedef typename MatrixType::Scalar Scalar;
|
typedef typename MatrixType::Scalar Scalar;
|
||||||
typedef typename MatrixType::RealScalar RealScalar;
|
typedef typename MatrixType::RealScalar RealScalar;
|
||||||
typedef typename SVD::Index Index;
|
static bool run(typename SVD::WorkMatrixType& work_matrix, SVD& svd, Index p, Index q, RealScalar& maxDiagEntry)
|
||||||
static void run(typename SVD::WorkMatrixType& work_matrix, SVD& svd, Index p, Index q)
|
|
||||||
{
|
{
|
||||||
using std::sqrt;
|
using std::sqrt;
|
||||||
|
using std::abs;
|
||||||
|
using std::max;
|
||||||
Scalar z;
|
Scalar z;
|
||||||
JacobiRotation<Scalar> rot;
|
JacobiRotation<Scalar> rot;
|
||||||
RealScalar n = sqrt(numext::abs2(work_matrix.coeff(p,p)) + numext::abs2(work_matrix.coeff(q,p)));
|
RealScalar n = sqrt(numext::abs2(work_matrix.coeff(p,p)) + numext::abs2(work_matrix.coeff(q,p)));
|
||||||
|
|
||||||
|
const RealScalar considerAsZero = (std::numeric_limits<RealScalar>::min)();
|
||||||
|
const RealScalar precision = NumTraits<Scalar>::epsilon();
|
||||||
|
|
||||||
if(n==0)
|
if(n==0)
|
||||||
{
|
{
|
||||||
z = abs(work_matrix.coeff(p,q)) / work_matrix.coeff(p,q);
|
// make sure first column is zero
|
||||||
work_matrix.row(p) *= z;
|
work_matrix.coeffRef(p,p) = work_matrix.coeffRef(q,p) = Scalar(0);
|
||||||
if(svd.computeU()) svd.m_matrixU.col(p) *= conj(z);
|
|
||||||
if(work_matrix.coeff(q,q)!=Scalar(0))
|
if(abs(numext::imag(work_matrix.coeff(p,q)))>considerAsZero)
|
||||||
|
{
|
||||||
|
// work_matrix.coeff(p,q) can be zero if work_matrix.coeff(q,p) is not zero but small enough to underflow when computing n
|
||||||
|
z = abs(work_matrix.coeff(p,q)) / work_matrix.coeff(p,q);
|
||||||
|
work_matrix.row(p) *= z;
|
||||||
|
if(svd.computeU()) svd.m_matrixU.col(p) *= conj(z);
|
||||||
|
}
|
||||||
|
if(abs(numext::imag(work_matrix.coeff(q,q)))>considerAsZero)
|
||||||
{
|
{
|
||||||
z = abs(work_matrix.coeff(q,q)) / work_matrix.coeff(q,q);
|
z = abs(work_matrix.coeff(q,q)) / work_matrix.coeff(q,q);
|
||||||
work_matrix.row(q) *= z;
|
work_matrix.row(q) *= z;
|
||||||
@@ -395,19 +408,25 @@ struct svd_precondition_2x2_block_to_be_real<MatrixType, QRPreconditioner, true>
|
|||||||
rot.s() = work_matrix.coeff(q,p) / n;
|
rot.s() = work_matrix.coeff(q,p) / n;
|
||||||
work_matrix.applyOnTheLeft(p,q,rot);
|
work_matrix.applyOnTheLeft(p,q,rot);
|
||||||
if(svd.computeU()) svd.m_matrixU.applyOnTheRight(p,q,rot.adjoint());
|
if(svd.computeU()) svd.m_matrixU.applyOnTheRight(p,q,rot.adjoint());
|
||||||
if(work_matrix.coeff(p,q) != Scalar(0))
|
if(abs(numext::imag(work_matrix.coeff(p,q)))>considerAsZero)
|
||||||
{
|
{
|
||||||
Scalar z = abs(work_matrix.coeff(p,q)) / work_matrix.coeff(p,q);
|
z = abs(work_matrix.coeff(p,q)) / work_matrix.coeff(p,q);
|
||||||
work_matrix.col(q) *= z;
|
work_matrix.col(q) *= z;
|
||||||
if(svd.computeV()) svd.m_matrixV.col(q) *= z;
|
if(svd.computeV()) svd.m_matrixV.col(q) *= z;
|
||||||
}
|
}
|
||||||
if(work_matrix.coeff(q,q) != Scalar(0))
|
if(abs(numext::imag(work_matrix.coeff(q,q)))>considerAsZero)
|
||||||
{
|
{
|
||||||
z = abs(work_matrix.coeff(q,q)) / work_matrix.coeff(q,q);
|
z = abs(work_matrix.coeff(q,q)) / work_matrix.coeff(q,q);
|
||||||
work_matrix.row(q) *= z;
|
work_matrix.row(q) *= z;
|
||||||
if(svd.computeU()) svd.m_matrixU.col(q) *= conj(z);
|
if(svd.computeU()) svd.m_matrixU.col(q) *= conj(z);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// update largest diagonal entry
|
||||||
|
maxDiagEntry = max EIGEN_EMPTY (maxDiagEntry,max EIGEN_EMPTY (abs(work_matrix.coeff(p,p)), abs(work_matrix.coeff(q,q))));
|
||||||
|
// and check whether the 2x2 block is already diagonal
|
||||||
|
RealScalar threshold = max EIGEN_EMPTY (considerAsZero, precision * maxDiagEntry);
|
||||||
|
return abs(work_matrix.coeff(p,q))>threshold || abs(work_matrix.coeff(q,p)) > threshold;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -424,22 +443,23 @@ void real_2x2_jacobi_svd(const MatrixType& matrix, Index p, Index q,
|
|||||||
JacobiRotation<RealScalar> rot1;
|
JacobiRotation<RealScalar> rot1;
|
||||||
RealScalar t = m.coeff(0,0) + m.coeff(1,1);
|
RealScalar t = m.coeff(0,0) + m.coeff(1,1);
|
||||||
RealScalar d = m.coeff(1,0) - m.coeff(0,1);
|
RealScalar d = m.coeff(1,0) - m.coeff(0,1);
|
||||||
if(t == RealScalar(0))
|
if(d == RealScalar(0))
|
||||||
{
|
{
|
||||||
rot1.c() = RealScalar(0);
|
rot1.s() = RealScalar(0);
|
||||||
rot1.s() = d > RealScalar(0) ? RealScalar(1) : RealScalar(-1);
|
rot1.c() = RealScalar(1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
RealScalar t2d2 = numext::hypot(t,d);
|
// If d!=0, then t/d cannot overflow because the magnitude of the
|
||||||
rot1.c() = abs(t)/t2d2;
|
// entries forming d are not too small compared to the ones forming t.
|
||||||
rot1.s() = d/t2d2;
|
RealScalar u = t / d;
|
||||||
if(t<RealScalar(0))
|
RealScalar tmp = sqrt(RealScalar(1) + numext::abs2(u));
|
||||||
rot1.s() = -rot1.s();
|
rot1.s() = RealScalar(1) / tmp;
|
||||||
|
rot1.c() = u / tmp;
|
||||||
}
|
}
|
||||||
m.applyOnTheLeft(0,1,rot1);
|
m.applyOnTheLeft(0,1,rot1);
|
||||||
j_right->makeJacobi(m,0,1);
|
j_right->makeJacobi(m,0,1);
|
||||||
*j_left = rot1 * j_right->transpose();
|
*j_left = rot1 * j_right->transpose();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // end namespace internal
|
} // end namespace internal
|
||||||
@@ -816,7 +836,7 @@ void JacobiSVD<MatrixType, QRPreconditioner>::allocate(Index rows, Index cols, u
|
|||||||
|
|
||||||
if(m_cols>m_rows) m_qr_precond_morecols.allocate(*this);
|
if(m_cols>m_rows) m_qr_precond_morecols.allocate(*this);
|
||||||
if(m_rows>m_cols) m_qr_precond_morerows.allocate(*this);
|
if(m_rows>m_cols) m_qr_precond_morerows.allocate(*this);
|
||||||
if(m_cols!=m_cols) m_scaledMatrix.resize(rows,cols);
|
if(m_rows!=m_cols) m_scaledMatrix.resize(rows,cols);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename MatrixType, int QRPreconditioner>
|
template<typename MatrixType, int QRPreconditioner>
|
||||||
@@ -826,6 +846,7 @@ JacobiSVD<MatrixType, QRPreconditioner>::compute(const MatrixType& matrix, unsig
|
|||||||
check_template_parameters();
|
check_template_parameters();
|
||||||
|
|
||||||
using std::abs;
|
using std::abs;
|
||||||
|
using std::max;
|
||||||
allocate(matrix.rows(), matrix.cols(), computationOptions);
|
allocate(matrix.rows(), matrix.cols(), computationOptions);
|
||||||
|
|
||||||
// currently we stop when we reach precision 2*epsilon as the last bit of precision can require an unreasonable number of iterations,
|
// currently we stop when we reach precision 2*epsilon as the last bit of precision can require an unreasonable number of iterations,
|
||||||
@@ -857,6 +878,7 @@ JacobiSVD<MatrixType, QRPreconditioner>::compute(const MatrixType& matrix, unsig
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*** step 2. The main Jacobi SVD iteration. ***/
|
/*** step 2. The main Jacobi SVD iteration. ***/
|
||||||
|
RealScalar maxDiagEntry = m_workMatrix.cwiseAbs().diagonal().maxCoeff();
|
||||||
|
|
||||||
bool finished = false;
|
bool finished = false;
|
||||||
while(!finished)
|
while(!finished)
|
||||||
@@ -872,25 +894,27 @@ JacobiSVD<MatrixType, QRPreconditioner>::compute(const MatrixType& matrix, unsig
|
|||||||
// if this 2x2 sub-matrix is not diagonal already...
|
// if this 2x2 sub-matrix is not diagonal already...
|
||||||
// notice that this comparison will evaluate to false if any NaN is involved, ensuring that NaN's don't
|
// notice that this comparison will evaluate to false if any NaN is involved, ensuring that NaN's don't
|
||||||
// keep us iterating forever. Similarly, small denormal numbers are considered zero.
|
// keep us iterating forever. Similarly, small denormal numbers are considered zero.
|
||||||
using std::max;
|
RealScalar threshold = max EIGEN_EMPTY (considerAsZero, precision * maxDiagEntry);
|
||||||
RealScalar threshold = (max)(considerAsZero, precision * (max)(abs(m_workMatrix.coeff(p,p)),
|
|
||||||
abs(m_workMatrix.coeff(q,q))));
|
|
||||||
// We compare both values to threshold instead of calling max to be robust to NaN (See bug 791)
|
|
||||||
if(abs(m_workMatrix.coeff(p,q))>threshold || abs(m_workMatrix.coeff(q,p)) > threshold)
|
if(abs(m_workMatrix.coeff(p,q))>threshold || abs(m_workMatrix.coeff(q,p)) > threshold)
|
||||||
{
|
{
|
||||||
finished = false;
|
finished = false;
|
||||||
|
|
||||||
// perform SVD decomposition of 2x2 sub-matrix corresponding to indices p,q to make it diagonal
|
// perform SVD decomposition of 2x2 sub-matrix corresponding to indices p,q to make it diagonal
|
||||||
internal::svd_precondition_2x2_block_to_be_real<MatrixType, QRPreconditioner>::run(m_workMatrix, *this, p, q);
|
// the complex to real operation returns true is the updated 2x2 block is not already diagonal
|
||||||
JacobiRotation<RealScalar> j_left, j_right;
|
if(internal::svd_precondition_2x2_block_to_be_real<MatrixType, QRPreconditioner>::run(m_workMatrix, *this, p, q, maxDiagEntry))
|
||||||
internal::real_2x2_jacobi_svd(m_workMatrix, p, q, &j_left, &j_right);
|
{
|
||||||
|
JacobiRotation<RealScalar> j_left, j_right;
|
||||||
|
internal::real_2x2_jacobi_svd(m_workMatrix, p, q, &j_left, &j_right);
|
||||||
|
|
||||||
// accumulate resulting Jacobi rotations
|
// accumulate resulting Jacobi rotations
|
||||||
m_workMatrix.applyOnTheLeft(p,q,j_left);
|
m_workMatrix.applyOnTheLeft(p,q,j_left);
|
||||||
if(computeU()) m_matrixU.applyOnTheRight(p,q,j_left.transpose());
|
if(computeU()) m_matrixU.applyOnTheRight(p,q,j_left.transpose());
|
||||||
|
|
||||||
m_workMatrix.applyOnTheRight(p,q,j_right);
|
m_workMatrix.applyOnTheRight(p,q,j_right);
|
||||||
if(computeV()) m_matrixV.applyOnTheRight(p,q,j_right);
|
if(computeV()) m_matrixV.applyOnTheRight(p,q,j_right);
|
||||||
|
|
||||||
|
// keep track of the largest diagonal coefficient
|
||||||
|
maxDiagEntry = max EIGEN_EMPTY (maxDiagEntry,max EIGEN_EMPTY (abs(m_workMatrix.coeff(p,p)), abs(m_workMatrix.coeff(q,q))));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,8 +45,8 @@ JacobiSVD<Matrix<EIGTYPE, Dynamic, Dynamic, EIGCOLROW, Dynamic, Dynamic>, ColPiv
|
|||||||
JacobiSVD<Matrix<EIGTYPE, Dynamic, Dynamic, EIGCOLROW, Dynamic, Dynamic>, ColPivHouseholderQRPreconditioner>::compute(const Matrix<EIGTYPE, Dynamic, Dynamic, EIGCOLROW, Dynamic, Dynamic>& matrix, unsigned int computationOptions) \
|
JacobiSVD<Matrix<EIGTYPE, Dynamic, Dynamic, EIGCOLROW, Dynamic, Dynamic>, ColPivHouseholderQRPreconditioner>::compute(const Matrix<EIGTYPE, Dynamic, Dynamic, EIGCOLROW, Dynamic, Dynamic>& matrix, unsigned int computationOptions) \
|
||||||
{ \
|
{ \
|
||||||
typedef Matrix<EIGTYPE, Dynamic, Dynamic, EIGCOLROW, Dynamic, Dynamic> MatrixType; \
|
typedef Matrix<EIGTYPE, Dynamic, Dynamic, EIGCOLROW, Dynamic, Dynamic> MatrixType; \
|
||||||
typedef MatrixType::Scalar Scalar; \
|
/*typedef MatrixType::Scalar Scalar;*/ \
|
||||||
typedef MatrixType::RealScalar RealScalar; \
|
/*typedef MatrixType::RealScalar RealScalar;*/ \
|
||||||
allocate(matrix.rows(), matrix.cols(), computationOptions); \
|
allocate(matrix.rows(), matrix.cols(), computationOptions); \
|
||||||
\
|
\
|
||||||
/*const RealScalar precision = RealScalar(2) * NumTraits<Scalar>::epsilon();*/ \
|
/*const RealScalar precision = RealScalar(2) * NumTraits<Scalar>::epsilon();*/ \
|
||||||
|
|||||||
@@ -102,6 +102,11 @@ class CompressedStorage
|
|||||||
inline size_t allocatedSize() const { return m_allocatedSize; }
|
inline size_t allocatedSize() const { return m_allocatedSize; }
|
||||||
inline void clear() { m_size = 0; }
|
inline void clear() { m_size = 0; }
|
||||||
|
|
||||||
|
const Scalar* valuePtr() const { return m_values; }
|
||||||
|
Scalar* valuePtr() { return m_values; }
|
||||||
|
const Index* indexPtr() const { return m_indices; }
|
||||||
|
Index* indexPtr() { return m_indices; }
|
||||||
|
|
||||||
inline Scalar& value(size_t i) { return m_values[i]; }
|
inline Scalar& value(size_t i) { return m_values[i]; }
|
||||||
inline const Scalar& value(size_t i) const { return m_values[i]; }
|
inline const Scalar& value(size_t i) const { return m_values[i]; }
|
||||||
|
|
||||||
@@ -208,8 +213,10 @@ class CompressedStorage
|
|||||||
Index* newIndices = new Index[size];
|
Index* newIndices = new Index[size];
|
||||||
size_t copySize = (std::min)(size, m_size);
|
size_t copySize = (std::min)(size, m_size);
|
||||||
// copy
|
// copy
|
||||||
internal::smart_copy(m_values, m_values+copySize, newValues);
|
if (copySize>0) {
|
||||||
internal::smart_copy(m_indices, m_indices+copySize, newIndices);
|
internal::smart_copy(m_values, m_values+copySize, newValues);
|
||||||
|
internal::smart_copy(m_indices, m_indices+copySize, newIndices);
|
||||||
|
}
|
||||||
// delete old stuff
|
// delete old stuff
|
||||||
delete[] m_values;
|
delete[] m_values;
|
||||||
delete[] m_indices;
|
delete[] m_indices;
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -55,10 +55,9 @@ class CwiseBinaryOpImpl<BinaryOp, Lhs, Rhs, Sparse>
|
|||||||
EIGEN_SPARSE_PUBLIC_INTERFACE(Derived)
|
EIGEN_SPARSE_PUBLIC_INTERFACE(Derived)
|
||||||
CwiseBinaryOpImpl()
|
CwiseBinaryOpImpl()
|
||||||
{
|
{
|
||||||
typedef typename internal::traits<Lhs>::StorageKind LhsStorageKind;
|
|
||||||
typedef typename internal::traits<Rhs>::StorageKind RhsStorageKind;
|
|
||||||
EIGEN_STATIC_ASSERT((
|
EIGEN_STATIC_ASSERT((
|
||||||
(!internal::is_same<LhsStorageKind,RhsStorageKind>::value)
|
(!internal::is_same<typename internal::traits<Lhs>::StorageKind,
|
||||||
|
typename internal::traits<Rhs>::StorageKind>::value)
|
||||||
|| ((Lhs::Flags&RowMajorBit) == (Rhs::Flags&RowMajorBit))),
|
|| ((Lhs::Flags&RowMajorBit) == (Rhs::Flags&RowMajorBit))),
|
||||||
THE_STORAGE_ORDER_OF_BOTH_SIDES_MUST_MATCH);
|
THE_STORAGE_ORDER_OF_BOTH_SIDES_MUST_MATCH);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -128,20 +128,20 @@ class SparseMatrix
|
|||||||
/** \returns a const pointer to the array of values.
|
/** \returns a const pointer to the array of values.
|
||||||
* This function is aimed at interoperability with other libraries.
|
* This function is aimed at interoperability with other libraries.
|
||||||
* \sa innerIndexPtr(), outerIndexPtr() */
|
* \sa innerIndexPtr(), outerIndexPtr() */
|
||||||
inline const Scalar* valuePtr() const { return &m_data.value(0); }
|
inline const Scalar* valuePtr() const { return m_data.valuePtr(); }
|
||||||
/** \returns a non-const pointer to the array of values.
|
/** \returns a non-const pointer to the array of values.
|
||||||
* This function is aimed at interoperability with other libraries.
|
* This function is aimed at interoperability with other libraries.
|
||||||
* \sa innerIndexPtr(), outerIndexPtr() */
|
* \sa innerIndexPtr(), outerIndexPtr() */
|
||||||
inline Scalar* valuePtr() { return &m_data.value(0); }
|
inline Scalar* valuePtr() { return m_data.valuePtr(); }
|
||||||
|
|
||||||
/** \returns a const pointer to the array of inner indices.
|
/** \returns a const pointer to the array of inner indices.
|
||||||
* This function is aimed at interoperability with other libraries.
|
* This function is aimed at interoperability with other libraries.
|
||||||
* \sa valuePtr(), outerIndexPtr() */
|
* \sa valuePtr(), outerIndexPtr() */
|
||||||
inline const Index* innerIndexPtr() const { return &m_data.index(0); }
|
inline const Index* innerIndexPtr() const { return m_data.indexPtr(); }
|
||||||
/** \returns a non-const pointer to the array of inner indices.
|
/** \returns a non-const pointer to the array of inner indices.
|
||||||
* This function is aimed at interoperability with other libraries.
|
* This function is aimed at interoperability with other libraries.
|
||||||
* \sa valuePtr(), outerIndexPtr() */
|
* \sa valuePtr(), outerIndexPtr() */
|
||||||
inline Index* innerIndexPtr() { return &m_data.index(0); }
|
inline Index* innerIndexPtr() { return m_data.indexPtr(); }
|
||||||
|
|
||||||
/** \returns a const pointer to the array of the starting positions of the inner vectors.
|
/** \returns a const pointer to the array of the starting positions of the inner vectors.
|
||||||
* This function is aimed at interoperability with other libraries.
|
* This function is aimed at interoperability with other libraries.
|
||||||
@@ -697,8 +697,8 @@ class SparseMatrix
|
|||||||
{
|
{
|
||||||
eigen_assert(rows() == cols() && "ONLY FOR SQUARED MATRICES");
|
eigen_assert(rows() == cols() && "ONLY FOR SQUARED MATRICES");
|
||||||
this->m_data.resize(rows());
|
this->m_data.resize(rows());
|
||||||
Eigen::Map<Matrix<Index, Dynamic, 1> >(&this->m_data.index(0), rows()).setLinSpaced(0, rows()-1);
|
Eigen::Map<Matrix<Index, Dynamic, 1> >(this->m_data.indexPtr(), rows()).setLinSpaced(0, rows()-1);
|
||||||
Eigen::Map<Matrix<Scalar, Dynamic, 1> >(&this->m_data.value(0), rows()).setOnes();
|
Eigen::Map<Matrix<Scalar, Dynamic, 1> >(this->m_data.valuePtr(), rows()).setOnes();
|
||||||
Eigen::Map<Matrix<Index, Dynamic, 1> >(this->m_outerIndex, rows()+1).setLinSpaced(0, rows());
|
Eigen::Map<Matrix<Index, Dynamic, 1> >(this->m_outerIndex, rows()+1).setLinSpaced(0, rows());
|
||||||
std::free(m_innerNonZeros);
|
std::free(m_innerNonZeros);
|
||||||
m_innerNonZeros = 0;
|
m_innerNonZeros = 0;
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ template<typename Derived> class SparseMatrixBase
|
|||||||
typedef typename internal::packet_traits<Scalar>::type PacketScalar;
|
typedef typename internal::packet_traits<Scalar>::type PacketScalar;
|
||||||
typedef typename internal::traits<Derived>::StorageKind StorageKind;
|
typedef typename internal::traits<Derived>::StorageKind StorageKind;
|
||||||
typedef typename internal::traits<Derived>::Index Index;
|
typedef typename internal::traits<Derived>::Index Index;
|
||||||
|
typedef typename internal::traits<Derived>::Index StorageIndex;
|
||||||
typedef typename internal::add_const_on_value_type_if_arithmetic<
|
typedef typename internal::add_const_on_value_type_if_arithmetic<
|
||||||
typename internal::packet_traits<Scalar>::type
|
typename internal::packet_traits<Scalar>::type
|
||||||
>::type PacketReturnType;
|
>::type PacketReturnType;
|
||||||
|
|||||||
@@ -29,7 +29,10 @@ typename internal::traits<SparseMatrix<_Scalar,_Options,_Index> >::Scalar
|
|||||||
SparseMatrix<_Scalar,_Options,_Index>::sum() const
|
SparseMatrix<_Scalar,_Options,_Index>::sum() const
|
||||||
{
|
{
|
||||||
eigen_assert(rows()>0 && cols()>0 && "you are using a non initialized matrix");
|
eigen_assert(rows()>0 && cols()>0 && "you are using a non initialized matrix");
|
||||||
return Matrix<Scalar,1,Dynamic>::Map(&m_data.value(0), m_data.size()).sum();
|
if(this->isCompressed())
|
||||||
|
return Matrix<Scalar,1,Dynamic>::Map(m_data.valuePtr(), m_data.size()).sum();
|
||||||
|
else
|
||||||
|
return Base::sum();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename _Scalar, int _Options, typename _Index>
|
template<typename _Scalar, int _Options, typename _Index>
|
||||||
@@ -37,7 +40,7 @@ typename internal::traits<SparseVector<_Scalar,_Options, _Index> >::Scalar
|
|||||||
SparseVector<_Scalar,_Options,_Index>::sum() const
|
SparseVector<_Scalar,_Options,_Index>::sum() const
|
||||||
{
|
{
|
||||||
eigen_assert(rows()>0 && cols()>0 && "you are using a non initialized matrix");
|
eigen_assert(rows()>0 && cols()>0 && "you are using a non initialized matrix");
|
||||||
return Matrix<Scalar,1,Dynamic>::Map(&m_data.value(0), m_data.size()).sum();
|
return Matrix<Scalar,1,Dynamic>::Map(m_data.valuePtr(), m_data.size()).sum();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // end namespace Eigen
|
} // end namespace Eigen
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ static void sparse_sparse_product_with_pruning_impl(const Lhs& lhs, const Rhs& r
|
|||||||
res.resize(rows, cols);
|
res.resize(rows, cols);
|
||||||
|
|
||||||
res.reserve(estimated_nnz_prod);
|
res.reserve(estimated_nnz_prod);
|
||||||
double ratioColRes = double(estimated_nnz_prod)/double(lhs.rows()*rhs.cols());
|
double ratioColRes = double(estimated_nnz_prod)/(double(lhs.rows())*double(rhs.cols()));
|
||||||
for (Index j=0; j<cols; ++j)
|
for (Index j=0; j<cols; ++j)
|
||||||
{
|
{
|
||||||
// FIXME:
|
// FIXME:
|
||||||
|
|||||||
@@ -84,12 +84,12 @@ class SparseVector
|
|||||||
EIGEN_STRONG_INLINE Index innerSize() const { return m_size; }
|
EIGEN_STRONG_INLINE Index innerSize() const { return m_size; }
|
||||||
EIGEN_STRONG_INLINE Index outerSize() const { return 1; }
|
EIGEN_STRONG_INLINE Index outerSize() const { return 1; }
|
||||||
|
|
||||||
EIGEN_STRONG_INLINE const Scalar* valuePtr() const { return &m_data.value(0); }
|
EIGEN_STRONG_INLINE const Scalar* valuePtr() const { return m_data.valuePtr(); }
|
||||||
EIGEN_STRONG_INLINE Scalar* valuePtr() { return &m_data.value(0); }
|
EIGEN_STRONG_INLINE Scalar* valuePtr() { return m_data.valuePtr(); }
|
||||||
|
|
||||||
|
EIGEN_STRONG_INLINE const Index* innerIndexPtr() const { return m_data.indexPtr(); }
|
||||||
|
EIGEN_STRONG_INLINE Index* innerIndexPtr() { return m_data.indexPtr(); }
|
||||||
|
|
||||||
EIGEN_STRONG_INLINE const Index* innerIndexPtr() const { return &m_data.index(0); }
|
|
||||||
EIGEN_STRONG_INLINE Index* innerIndexPtr() { return &m_data.index(0); }
|
|
||||||
|
|
||||||
/** \internal */
|
/** \internal */
|
||||||
inline Storage& data() { return m_data; }
|
inline Storage& data() { return m_data; }
|
||||||
/** \internal */
|
/** \internal */
|
||||||
|
|||||||
@@ -35,9 +35,9 @@ class SparseView : public SparseMatrixBase<SparseView<MatrixType> >
|
|||||||
public:
|
public:
|
||||||
EIGEN_SPARSE_PUBLIC_INTERFACE(SparseView)
|
EIGEN_SPARSE_PUBLIC_INTERFACE(SparseView)
|
||||||
|
|
||||||
SparseView(const MatrixType& mat, const Scalar& m_reference = Scalar(0),
|
explicit SparseView(const MatrixType& mat, const Scalar& reference = Scalar(0),
|
||||||
typename NumTraits<Scalar>::Real m_epsilon = NumTraits<Scalar>::dummy_precision()) :
|
const RealScalar &epsilon = NumTraits<Scalar>::dummy_precision())
|
||||||
m_matrix(mat), m_reference(m_reference), m_epsilon(m_epsilon) {}
|
: m_matrix(mat), m_reference(reference), m_epsilon(epsilon) {}
|
||||||
|
|
||||||
class InnerIterator;
|
class InnerIterator;
|
||||||
|
|
||||||
|
|||||||
@@ -13,32 +13,24 @@
|
|||||||
|
|
||||||
#include "details.h"
|
#include "details.h"
|
||||||
|
|
||||||
// Define the explicit instantiation (e.g. necessary for the Intel compiler)
|
|
||||||
#if defined(__INTEL_COMPILER) || defined(__GNUC__)
|
|
||||||
#define EIGEN_EXPLICIT_STL_DEQUE_INSTANTIATION(...) template class std::deque<__VA_ARGS__, EIGEN_ALIGNED_ALLOCATOR<__VA_ARGS__> >;
|
|
||||||
#else
|
|
||||||
#define EIGEN_EXPLICIT_STL_DEQUE_INSTANTIATION(...)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This section contains a convenience MACRO which allows an easy specialization of
|
* This section contains a convenience MACRO which allows an easy specialization of
|
||||||
* std::deque such that for data types with alignment issues the correct allocator
|
* std::deque such that for data types with alignment issues the correct allocator
|
||||||
* is used automatically.
|
* is used automatically.
|
||||||
*/
|
*/
|
||||||
#define EIGEN_DEFINE_STL_DEQUE_SPECIALIZATION(...) \
|
#define EIGEN_DEFINE_STL_DEQUE_SPECIALIZATION(...) \
|
||||||
EIGEN_EXPLICIT_STL_DEQUE_INSTANTIATION(__VA_ARGS__) \
|
|
||||||
namespace std \
|
namespace std \
|
||||||
{ \
|
{ \
|
||||||
template<typename _Ay> \
|
template<> \
|
||||||
class deque<__VA_ARGS__, _Ay> \
|
class deque<__VA_ARGS__, std::allocator<__VA_ARGS__> > \
|
||||||
: public deque<__VA_ARGS__, EIGEN_ALIGNED_ALLOCATOR<__VA_ARGS__> > \
|
: public deque<__VA_ARGS__, EIGEN_ALIGNED_ALLOCATOR<__VA_ARGS__> > \
|
||||||
{ \
|
{ \
|
||||||
typedef deque<__VA_ARGS__, EIGEN_ALIGNED_ALLOCATOR<__VA_ARGS__> > deque_base; \
|
typedef deque<__VA_ARGS__, EIGEN_ALIGNED_ALLOCATOR<__VA_ARGS__> > deque_base; \
|
||||||
public: \
|
public: \
|
||||||
typedef __VA_ARGS__ value_type; \
|
typedef __VA_ARGS__ value_type; \
|
||||||
typedef typename deque_base::allocator_type allocator_type; \
|
typedef deque_base::allocator_type allocator_type; \
|
||||||
typedef typename deque_base::size_type size_type; \
|
typedef deque_base::size_type size_type; \
|
||||||
typedef typename deque_base::iterator iterator; \
|
typedef deque_base::iterator iterator; \
|
||||||
explicit deque(const allocator_type& a = allocator_type()) : deque_base(a) {} \
|
explicit deque(const allocator_type& a = allocator_type()) : deque_base(a) {} \
|
||||||
template<typename InputIterator> \
|
template<typename InputIterator> \
|
||||||
deque(InputIterator first, InputIterator last, const allocator_type& a = allocator_type()) : deque_base(first, last, a) {} \
|
deque(InputIterator first, InputIterator last, const allocator_type& a = allocator_type()) : deque_base(first, last, a) {} \
|
||||||
|
|||||||
@@ -12,32 +12,24 @@
|
|||||||
|
|
||||||
#include "details.h"
|
#include "details.h"
|
||||||
|
|
||||||
// Define the explicit instantiation (e.g. necessary for the Intel compiler)
|
|
||||||
#if defined(__INTEL_COMPILER) || defined(__GNUC__)
|
|
||||||
#define EIGEN_EXPLICIT_STL_LIST_INSTANTIATION(...) template class std::list<__VA_ARGS__, EIGEN_ALIGNED_ALLOCATOR<__VA_ARGS__> >;
|
|
||||||
#else
|
|
||||||
#define EIGEN_EXPLICIT_STL_LIST_INSTANTIATION(...)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This section contains a convenience MACRO which allows an easy specialization of
|
* This section contains a convenience MACRO which allows an easy specialization of
|
||||||
* std::list such that for data types with alignment issues the correct allocator
|
* std::list such that for data types with alignment issues the correct allocator
|
||||||
* is used automatically.
|
* is used automatically.
|
||||||
*/
|
*/
|
||||||
#define EIGEN_DEFINE_STL_LIST_SPECIALIZATION(...) \
|
#define EIGEN_DEFINE_STL_LIST_SPECIALIZATION(...) \
|
||||||
EIGEN_EXPLICIT_STL_LIST_INSTANTIATION(__VA_ARGS__) \
|
|
||||||
namespace std \
|
namespace std \
|
||||||
{ \
|
{ \
|
||||||
template<typename _Ay> \
|
template<> \
|
||||||
class list<__VA_ARGS__, _Ay> \
|
class list<__VA_ARGS__, std::allocator<__VA_ARGS__> > \
|
||||||
: public list<__VA_ARGS__, EIGEN_ALIGNED_ALLOCATOR<__VA_ARGS__> > \
|
: public list<__VA_ARGS__, EIGEN_ALIGNED_ALLOCATOR<__VA_ARGS__> > \
|
||||||
{ \
|
{ \
|
||||||
typedef list<__VA_ARGS__, EIGEN_ALIGNED_ALLOCATOR<__VA_ARGS__> > list_base; \
|
typedef list<__VA_ARGS__, EIGEN_ALIGNED_ALLOCATOR<__VA_ARGS__> > list_base; \
|
||||||
public: \
|
public: \
|
||||||
typedef __VA_ARGS__ value_type; \
|
typedef __VA_ARGS__ value_type; \
|
||||||
typedef typename list_base::allocator_type allocator_type; \
|
typedef list_base::allocator_type allocator_type; \
|
||||||
typedef typename list_base::size_type size_type; \
|
typedef list_base::size_type size_type; \
|
||||||
typedef typename list_base::iterator iterator; \
|
typedef list_base::iterator iterator; \
|
||||||
explicit list(const allocator_type& a = allocator_type()) : list_base(a) {} \
|
explicit list(const allocator_type& a = allocator_type()) : list_base(a) {} \
|
||||||
template<typename InputIterator> \
|
template<typename InputIterator> \
|
||||||
list(InputIterator first, InputIterator last, const allocator_type& a = allocator_type()) : list_base(first, last, a) {} \
|
list(InputIterator first, InputIterator last, const allocator_type& a = allocator_type()) : list_base(first, last, a) {} \
|
||||||
|
|||||||
@@ -148,7 +148,8 @@ class UmfPackLU : internal::noncopyable
|
|||||||
|
|
||||||
UmfPackLU() { init(); }
|
UmfPackLU() { init(); }
|
||||||
|
|
||||||
UmfPackLU(const MatrixType& matrix)
|
template<typename InputMatrixType>
|
||||||
|
UmfPackLU(const InputMatrixType& matrix)
|
||||||
{
|
{
|
||||||
init();
|
init();
|
||||||
compute(matrix);
|
compute(matrix);
|
||||||
|
|||||||
@@ -44,15 +44,10 @@
|
|||||||
#define BTL_ASM_COMMENT(X)
|
#define BTL_ASM_COMMENT(X)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if (defined __GNUC__) && (!defined __INTEL_COMPILER) && !defined(__arm__) && !defined(__powerpc__)
|
#ifdef __SSE__
|
||||||
#define BTL_DISABLE_SSE_EXCEPTIONS() { \
|
#include "xmmintrin.h"
|
||||||
int aux; \
|
// This enables flush to zero (FTZ) and denormals are zero (DAZ) modes:
|
||||||
asm( \
|
#define BTL_DISABLE_SSE_EXCEPTIONS() { _mm_setcsr(_mm_getcsr() | 0x8040); }
|
||||||
"stmxcsr %[aux] \n\t" \
|
|
||||||
"orl $32832, %[aux] \n\t" \
|
|
||||||
"ldmxcsr %[aux] \n\t" \
|
|
||||||
: : [aux] "m" (aux)); \
|
|
||||||
}
|
|
||||||
#else
|
#else
|
||||||
#define BTL_DISABLE_SSE_EXCEPTIONS()
|
#define BTL_DISABLE_SSE_EXCEPTIONS()
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
include(EigenTesting)
|
include(EigenTesting)
|
||||||
include(CheckCXXSourceCompiles)
|
include(CheckCXXSourceCompiles)
|
||||||
|
|
||||||
# configure the "site" and "buildname"
|
# configure the "site" and "buildname"
|
||||||
ei_set_sitename()
|
ei_set_sitename()
|
||||||
|
|
||||||
# retrieve and store the build string
|
# retrieve and store the build string
|
||||||
@@ -14,17 +14,10 @@ add_dependencies(check buildtests)
|
|||||||
# check whether /bin/bash exists
|
# check whether /bin/bash exists
|
||||||
find_file(EIGEN_BIN_BASH_EXISTS "/bin/bash" PATHS "/" NO_DEFAULT_PATH)
|
find_file(EIGEN_BIN_BASH_EXISTS "/bin/bash" PATHS "/" NO_DEFAULT_PATH)
|
||||||
|
|
||||||
# CMake/Ctest does not allow us to change the build command,
|
|
||||||
# so we have to workaround by directly editing the generated DartConfiguration.tcl file
|
|
||||||
# save CMAKE_MAKE_PROGRAM
|
|
||||||
set(CMAKE_MAKE_PROGRAM_SAVE ${CMAKE_MAKE_PROGRAM})
|
|
||||||
# and set a fake one
|
|
||||||
set(CMAKE_MAKE_PROGRAM "@EIGEN_MAKECOMMAND_PLACEHOLDER@")
|
|
||||||
|
|
||||||
# This call activates testing and generates the DartConfiguration.tcl
|
# This call activates testing and generates the DartConfiguration.tcl
|
||||||
include(CTest)
|
include(CTest)
|
||||||
|
|
||||||
set(EIGEN_TEST_BUILD_FLAGS " " CACHE STRING "Options passed to the build command of unit tests")
|
set(EIGEN_TEST_BUILD_FLAGS "" CACHE STRING "Options passed to the build command of unit tests")
|
||||||
|
|
||||||
# Overwrite default DartConfiguration.tcl such that ctest can build our unit tests.
|
# Overwrite default DartConfiguration.tcl such that ctest can build our unit tests.
|
||||||
# Recall that our unit tests are not in the "all" target, so we have to explicitely ask ctest to build our custom 'buildtests' target.
|
# Recall that our unit tests are not in the "all" target, so we have to explicitely ask ctest to build our custom 'buildtests' target.
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ function(DetermineShortWindowsName WIN_VERSION win_num_version)
|
|||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
function(DetermineOSVersion OS_VERSION)
|
function(DetermineOSVersion OS_VERSION)
|
||||||
if (WIN32)
|
if (WIN32 AND CMAKE_HOST_SYSTEM_NAME MATCHES Windows)
|
||||||
file (TO_NATIVE_PATH "$ENV{COMSPEC}" SHELL)
|
file (TO_NATIVE_PATH "$ENV{COMSPEC}" SHELL)
|
||||||
exec_program( ${SHELL} ARGS "/c" "ver" OUTPUT_VARIABLE ver_output)
|
exec_program( ${SHELL} ARGS "/c" "ver" OUTPUT_VARIABLE ver_output)
|
||||||
|
|
||||||
|
|||||||
@@ -89,6 +89,7 @@ add_dependencies(doc-unsupported-prerequisites unsupported_snippets unsupported_
|
|||||||
add_custom_target(doc ALL
|
add_custom_target(doc ALL
|
||||||
COMMAND doxygen
|
COMMAND doxygen
|
||||||
COMMAND doxygen Doxyfile-unsupported
|
COMMAND doxygen Doxyfile-unsupported
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy ${Eigen_BINARY_DIR}/doc/html/group__TopicUnalignedArrayAssert.html ${Eigen_BINARY_DIR}/doc/html/TopicUnalignedArrayAssert.html
|
||||||
COMMAND ${CMAKE_COMMAND} -E rename html eigen-doc
|
COMMAND ${CMAKE_COMMAND} -E rename html eigen-doc
|
||||||
COMMAND ${CMAKE_COMMAND} -E remove eigen-doc/eigen-doc.tgz
|
COMMAND ${CMAKE_COMMAND} -E remove eigen-doc/eigen-doc.tgz
|
||||||
COMMAND ${CMAKE_COMMAND} -E tar cfz eigen-doc.tgz eigen-doc
|
COMMAND ${CMAKE_COMMAND} -E tar cfz eigen-doc.tgz eigen-doc
|
||||||
|
|||||||
@@ -121,6 +121,8 @@ namespace Eigen {
|
|||||||
\ingroup Sparse_chapter */
|
\ingroup Sparse_chapter */
|
||||||
/** \addtogroup TopicSparseSystems
|
/** \addtogroup TopicSparseSystems
|
||||||
\ingroup Sparse_chapter */
|
\ingroup Sparse_chapter */
|
||||||
|
/** \addtogroup MatrixfreeSolverExample
|
||||||
|
\ingroup Sparse_chapter */
|
||||||
|
|
||||||
/** \addtogroup Sparse_Reference
|
/** \addtogroup Sparse_Reference
|
||||||
\ingroup Sparse_chapter */
|
\ingroup Sparse_chapter */
|
||||||
|
|||||||
21
doc/MatrixfreeSolverExample.dox
Normal file
21
doc/MatrixfreeSolverExample.dox
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
|
||||||
|
namespace Eigen {
|
||||||
|
|
||||||
|
/**
|
||||||
|
|
||||||
|
\eigenManualPage MatrixfreeSolverExample Matrix-free solvers
|
||||||
|
|
||||||
|
Iterative solvers such as ConjugateGradient and BiCGSTAB can be used in a matrix free context. To this end, user must provide a wrapper class inheriting EigenBase<> and implementing the following methods:
|
||||||
|
- Index rows() and Index cols(): returns number of rows and columns respectively
|
||||||
|
- operator* with and Eigen dense column vector
|
||||||
|
- resize(rows,cols): needed for source compatibility (can stay empty)
|
||||||
|
|
||||||
|
Eigen::internal::traits<> must also be specialized for the wrapper type.
|
||||||
|
|
||||||
|
For efficiency purpose, one might also want to provide a custom preconditioner. Here is an example using ConjugateGradient and implementing also a custom Jacobi preconditioner:
|
||||||
|
\include matrixfree_cg.cpp
|
||||||
|
Output: \verbinclude matrixfree_cg.out
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
}
|
||||||
@@ -91,6 +91,7 @@ following macros are supported; none of them are defined by default.
|
|||||||
- \b EIGEN_MATRIX_PLUGIN - filename of plugin for extending the Matrix class.
|
- \b EIGEN_MATRIX_PLUGIN - filename of plugin for extending the Matrix class.
|
||||||
- \b EIGEN_MATRIXBASE_PLUGIN - filename of plugin for extending the MatrixBase class.
|
- \b EIGEN_MATRIXBASE_PLUGIN - filename of plugin for extending the MatrixBase class.
|
||||||
- \b EIGEN_PLAINOBJECTBASE_PLUGIN - filename of plugin for extending the PlainObjectBase class.
|
- \b EIGEN_PLAINOBJECTBASE_PLUGIN - filename of plugin for extending the PlainObjectBase class.
|
||||||
|
- \b EIGEN_MAPBASE_PLUGIN - filename of plugin for extending the MapBase class.
|
||||||
- \b EIGEN_QUATERNIONBASE_PLUGIN - filename of plugin for extending the QuaternionBase class.
|
- \b EIGEN_QUATERNIONBASE_PLUGIN - filename of plugin for extending the QuaternionBase class.
|
||||||
- \b EIGEN_SPARSEMATRIX_PLUGIN - filename of plugin for extending the SparseMatrix class.
|
- \b EIGEN_SPARSEMATRIX_PLUGIN - filename of plugin for extending the SparseMatrix class.
|
||||||
- \b EIGEN_SPARSEMATRIXBASE_PLUGIN - filename of plugin for extending the SparseMatrixBase class.
|
- \b EIGEN_SPARSEMATRIXBASE_PLUGIN - filename of plugin for extending the SparseMatrixBase class.
|
||||||
|
|||||||
@@ -35,17 +35,20 @@ They are summarized in the following table:
|
|||||||
<td>Requires the <a href="http://pastix.gforge.inria.fr">PaStiX</a> package, \b CeCILL-C </td>
|
<td>Requires the <a href="http://pastix.gforge.inria.fr">PaStiX</a> package, \b CeCILL-C </td>
|
||||||
<td>optimized for tough problems and symmetric patterns</td></tr>
|
<td>optimized for tough problems and symmetric patterns</td></tr>
|
||||||
<tr><td>CholmodSupernodalLLT</td><td>\link CholmodSupport_Module CholmodSupport \endlink</td><td>Direct LLt factorization</td><td>SPD</td><td>Fill-in reducing, Leverage fast dense algebra</td>
|
<tr><td>CholmodSupernodalLLT</td><td>\link CholmodSupport_Module CholmodSupport \endlink</td><td>Direct LLt factorization</td><td>SPD</td><td>Fill-in reducing, Leverage fast dense algebra</td>
|
||||||
<td>Requires the <a href="http://www.cise.ufl.edu/research/sparse/SuiteSparse/">SuiteSparse</a> package, \b GPL </td>
|
<td>Requires the <a href="http://www.suitesparse.com">SuiteSparse</a> package, \b GPL </td>
|
||||||
<td></td></tr>
|
<td></td></tr>
|
||||||
<tr><td>UmfPackLU</td><td>\link UmfPackSupport_Module UmfPackSupport \endlink</td><td>Direct LU factorization</td><td>Square</td><td>Fill-in reducing, Leverage fast dense algebra</td>
|
<tr><td>UmfPackLU</td><td>\link UmfPackSupport_Module UmfPackSupport \endlink</td><td>Direct LU factorization</td><td>Square</td><td>Fill-in reducing, Leverage fast dense algebra</td>
|
||||||
<td>Requires the <a href="http://www.cise.ufl.edu/research/sparse/SuiteSparse/">SuiteSparse</a> package, \b GPL </td>
|
<td>Requires the <a href="http://www.suitesparse.com">SuiteSparse</a> package, \b GPL </td>
|
||||||
<td></td></tr>
|
<td></td></tr>
|
||||||
<tr><td>SuperLU</td><td>\link SuperLUSupport_Module SuperLUSupport \endlink</td><td>Direct LU factorization</td><td>Square</td><td>Fill-in reducing, Leverage fast dense algebra</td>
|
<tr><td>SuperLU</td><td>\link SuperLUSupport_Module SuperLUSupport \endlink</td><td>Direct LU factorization</td><td>Square</td><td>Fill-in reducing, Leverage fast dense algebra</td>
|
||||||
<td>Requires the <a href="http://crd-legacy.lbl.gov/~xiaoye/SuperLU/">SuperLU</a> library, (BSD-like)</td>
|
<td>Requires the <a href="http://crd-legacy.lbl.gov/~xiaoye/SuperLU/">SuperLU</a> library, (BSD-like)</td>
|
||||||
<td></td></tr>
|
<td></td></tr>
|
||||||
<tr><td>SPQR</td><td>\link SPQRSupport_Module SPQRSupport \endlink </td> <td> QR factorization </td>
|
<tr><td>SPQR</td><td>\link SPQRSupport_Module SPQRSupport \endlink </td> <td> QR factorization </td>
|
||||||
<td> Any, rectangular</td><td>fill-in reducing, multithreaded, fast dense algebra</td>
|
<td> Any, rectangular</td><td>fill-in reducing, multithreaded, fast dense algebra</td>
|
||||||
<td> requires the <a href="http://www.cise.ufl.edu/research/sparse/SuiteSparse/">SuiteSparse</a> package, \b GPL </td><td>recommended for linear least-squares problems, has a rank-revealing feature</tr>
|
<td> requires the <a href="http://www.suitesparse.com">SuiteSparse</a> package, \b GPL </td><td>recommended for linear least-squares problems, has a rank-revealing feature</tr>
|
||||||
|
<tr><td>PardisoLLT \n PardisoLDLT \n PardisoLU</td><td>\link PardisoSupport_Module PardisoSupport \endlink</td><td>Direct LLt, LDLt, LU factorizations</td><td>SPD \n SPD \n Square</td><td>Fill-in reducing, Leverage fast dense algebra, Multithreading</td>
|
||||||
|
<td>Requires the <a href="http://eigen.tuxfamily.org/Counter/redirect_to_mkl.php">Intel MKL</a> package, \b Proprietary </td>
|
||||||
|
<td>optimized for tough problems patterns, see also \link TopicUsingIntelMKL using MKL with Eigen \endlink</td></tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
Here \c SPD means symmetric positive definite.
|
Here \c SPD means symmetric positive definite.
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ i.e either row major or column major. The default is column major. Most arithmet
|
|||||||
<td> Resize/Reserve</td>
|
<td> Resize/Reserve</td>
|
||||||
<td>
|
<td>
|
||||||
\code
|
\code
|
||||||
sm1.resize(m,n); //Change sm1 to a m x n matrix.
|
sm1.resize(m,n); // Change sm1 to a m x n matrix.
|
||||||
sm1.reserve(nnz); // Allocate room for nnz nonzeros elements.
|
sm1.reserve(nnz); // Allocate room for nnz nonzeros elements.
|
||||||
\endcode
|
\endcode
|
||||||
</td>
|
</td>
|
||||||
@@ -151,10 +151,10 @@ It is easy to perform arithmetic operations on sparse matrices provided that the
|
|||||||
<td> Permutation </td>
|
<td> Permutation </td>
|
||||||
<td>
|
<td>
|
||||||
\code
|
\code
|
||||||
perm.indices(); // Reference to the vector of indices
|
perm.indices(); // Reference to the vector of indices
|
||||||
sm1.twistedBy(perm); // Permute rows and columns
|
sm1.twistedBy(perm); // Permute rows and columns
|
||||||
sm2 = sm1 * perm; //Permute the columns
|
sm2 = sm1 * perm; // Permute the columns
|
||||||
sm2 = perm * sm1; // Permute the columns
|
sm2 = perm * sm1; // Permute the columns
|
||||||
\endcode
|
\endcode
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
@@ -181,9 +181,9 @@ sm2 = perm * sm1; // Permute the columns
|
|||||||
|
|
||||||
\section sparseotherops Other supported operations
|
\section sparseotherops Other supported operations
|
||||||
<table class="manual">
|
<table class="manual">
|
||||||
<tr><th>Operations</th> <th> Code </th> <th> Notes</th> </tr>
|
<tr><th style="min-width:initial"> Code </th> <th> Notes</th> </tr>
|
||||||
|
<tr><td colspan="2">Sub-matrices</td></tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Sub-matrices</td>
|
|
||||||
<td>
|
<td>
|
||||||
\code
|
\code
|
||||||
sm1.block(startRow, startCol, rows, cols);
|
sm1.block(startRow, startCol, rows, cols);
|
||||||
@@ -193,25 +193,31 @@ sm2 = perm * sm1; // Permute the columns
|
|||||||
sm1.bottomLeftCorner( rows, cols);
|
sm1.bottomLeftCorner( rows, cols);
|
||||||
sm1.bottomRightCorner( rows, cols);
|
sm1.bottomRightCorner( rows, cols);
|
||||||
\endcode
|
\endcode
|
||||||
</td> <td> </td>
|
</td><td>
|
||||||
|
Contrary to dense matrices, here <strong>all these methods are read-only</strong>.\n
|
||||||
|
See \ref TutorialSparse_SubMatrices and below for read-write sub-matrices.
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr class="alt"><td colspan="2"> Range </td></tr>
|
||||||
<td> Range </td>
|
<tr class="alt">
|
||||||
<td>
|
<td>
|
||||||
\code
|
\code
|
||||||
sm1.innerVector(outer);
|
sm1.innerVector(outer); // RW
|
||||||
sm1.innerVectors(start, size);
|
sm1.innerVectors(start, size); // RW
|
||||||
sm1.leftCols(size);
|
sm1.leftCols(size); // RW
|
||||||
sm2.rightCols(size);
|
sm2.rightCols(size); // RO because sm2 is row-major
|
||||||
sm1.middleRows(start, numRows);
|
sm1.middleRows(start, numRows); // RO becasue sm1 is column-major
|
||||||
sm1.middleCols(start, numCols);
|
sm1.middleCols(start, numCols); // RW
|
||||||
sm1.col(j);
|
sm1.col(j); // RW
|
||||||
\endcode
|
\endcode
|
||||||
</td>
|
</td>
|
||||||
<td>A inner vector is either a row (for row-major) or a column (for column-major). As stated earlier, the evaluation can be done in a matrix with different storage order </td>
|
<td>
|
||||||
|
A inner vector is either a row (for row-major) or a column (for column-major).\n
|
||||||
|
As stated earlier, for a read-write sub-matrix (RW), the evaluation can be done in a matrix with different storage order.
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr><td colspan="2"> Triangular and selfadjoint views</td></tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td> Triangular and selfadjoint views</td>
|
|
||||||
<td>
|
<td>
|
||||||
\code
|
\code
|
||||||
sm2 = sm1.triangularview<Lower>();
|
sm2 = sm1.triangularview<Lower>();
|
||||||
@@ -222,26 +228,30 @@ sm2 = perm * sm1; // Permute the columns
|
|||||||
\code
|
\code
|
||||||
\endcode </td>
|
\endcode </td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr class="alt"><td colspan="2">Triangular solve </td></tr>
|
||||||
<td>Triangular solve </td>
|
<tr class="alt">
|
||||||
<td>
|
<td>
|
||||||
\code
|
\code
|
||||||
dv2 = sm1.triangularView<Upper>().solve(dv1);
|
dv2 = sm1.triangularView<Upper>().solve(dv1);
|
||||||
dv2 = sm1.topLeftCorner(size, size).triangularView<Lower>().solve(dv1);
|
dv2 = sm1.topLeftCorner(size, size)
|
||||||
|
.triangularView<Lower>().solve(dv1);
|
||||||
\endcode
|
\endcode
|
||||||
</td>
|
</td>
|
||||||
<td> For general sparse solve, Use any suitable module described at \ref TopicSparseSystems </td>
|
<td> For general sparse solve, Use any suitable module described at \ref TopicSparseSystems </td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr><td colspan="2"> Low-level API</td></tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td> Low-level API</td>
|
|
||||||
<td>
|
<td>
|
||||||
\code
|
\code
|
||||||
sm1.valuePtr(); // Pointer to the values
|
sm1.valuePtr(); // Pointer to the values
|
||||||
sm1.innerIndextr(); // Pointer to the indices.
|
sm1.innerIndextr(); // Pointer to the indices.
|
||||||
sm1.outerIndexPtr(); //Pointer to the beginning of each inner vector
|
sm1.outerIndexPtr(); // Pointer to the beginning of each inner vector
|
||||||
\endcode
|
\endcode
|
||||||
</td>
|
</td>
|
||||||
<td> If the matrix is not in compressed form, makeCompressed() should be called before. Note that these functions are mostly provided for interoperability purposes with external libraries. A better access to the values of the matrix is done by using the InnerIterator class as described in \link TutorialSparse the Tutorial Sparse \endlink section</td>
|
<td>
|
||||||
|
If the matrix is not in compressed form, makeCompressed() should be called before.\n
|
||||||
|
Note that these functions are mostly provided for interoperability purposes with external libraries.\n
|
||||||
|
A better access to the values of the matrix is done by using the InnerIterator class as described in \link TutorialSparse the Tutorial Sparse \endlink section</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ Both eigen_assert and eigen_plain_assert are defined in Macros.h. Defining eigen
|
|||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#undef eigen_assert
|
#undef eigen_assert
|
||||||
#define eigen_assert(x) \
|
#define eigen_assert(x) \
|
||||||
if (!x) { throw (std::runtime_error("Put your message here")); }
|
if (!(x)) { throw (std::runtime_error("Put your message here")); }
|
||||||
\endcode
|
\endcode
|
||||||
|
|
||||||
\subsection DisableAssert Disabling assertions
|
\subsection DisableAssert Disabling assertions
|
||||||
|
|||||||
@@ -241,11 +241,11 @@ In the following \em sm denotes a sparse matrix, \em sv a sparse vector, \em dm
|
|||||||
sm1.real() sm1.imag() -sm1 0.5*sm1
|
sm1.real() sm1.imag() -sm1 0.5*sm1
|
||||||
sm1+sm2 sm1-sm2 sm1.cwiseProduct(sm2)
|
sm1+sm2 sm1-sm2 sm1.cwiseProduct(sm2)
|
||||||
\endcode
|
\endcode
|
||||||
However, a strong restriction is that the storage orders must match. For instance, in the following example:
|
However, <strong>a strong restriction is that the storage orders must match</strong>. For instance, in the following example:
|
||||||
\code
|
\code
|
||||||
sm4 = sm1 + sm2 + sm3;
|
sm4 = sm1 + sm2 + sm3;
|
||||||
\endcode
|
\endcode
|
||||||
sm1, sm2, and sm3 must all be row-major or all column major.
|
sm1, sm2, and sm3 must all be row-major or all column-major.
|
||||||
On the other hand, there is no restriction on the target matrix sm4.
|
On the other hand, there is no restriction on the target matrix sm4.
|
||||||
For instance, this means that for computing \f$ A^T + A \f$, the matrix \f$ A^T \f$ must be evaluated into a temporary matrix of compatible storage order:
|
For instance, this means that for computing \f$ A^T + A \f$, the matrix \f$ A^T \f$ must be evaluated into a temporary matrix of compatible storage order:
|
||||||
\code
|
\code
|
||||||
@@ -307,6 +307,26 @@ sm2 = sm1.transpose() * P;
|
|||||||
\endcode
|
\endcode
|
||||||
|
|
||||||
|
|
||||||
|
\subsection TutorialSparse_SubMatrices Block operations
|
||||||
|
|
||||||
|
Regarding read-access, sparse matrices expose the same API than for dense matrices to access to sub-matrices such as blocks, columns, and rows. See \ref TutorialBlockOperations for a detailed introduction.
|
||||||
|
However, for performance reasons, writing to a sub-sparse-matrix is much more limited, and currently only contiguous sets of columns (resp. rows) of a column-major (resp. row-major) SparseMatrix are writable. Moreover, this information has to be known at compile-time, leaving out methods such as <tt>block(...)</tt> and <tt>corner*(...)</tt>. The available API for write-access to a SparseMatrix are summarized below:
|
||||||
|
\code
|
||||||
|
SparseMatrix<double,ColMajor> sm1;
|
||||||
|
sm1.col(j) = ...;
|
||||||
|
sm1.leftCols(ncols) = ...;
|
||||||
|
sm1.middleCols(j,ncols) = ...;
|
||||||
|
sm1.rightCols(ncols) = ...;
|
||||||
|
|
||||||
|
SparseMatrix<double,RowMajor> sm2;
|
||||||
|
sm2.row(i) = ...;
|
||||||
|
sm2.topRows(nrows) = ...;
|
||||||
|
sm2.middleRows(i,nrows) = ...;
|
||||||
|
sm2.bottomRows(nrows) = ...;
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
In addition, sparse matrices expose the SparseMatrixBase::innerVector() and SparseMatrixBase::innerVectors() methods, which are aliases to the col/middleCols methods for a column-major storage, and to the row/middleRows methods for a row-major storage.
|
||||||
|
|
||||||
\subsection TutorialSparse_TriangularSelfadjoint Triangular and selfadjoint views
|
\subsection TutorialSparse_TriangularSelfadjoint Triangular and selfadjoint views
|
||||||
|
|
||||||
Just as with dense matrices, the triangularView() function can be used to address a triangular part of the matrix, and perform triangular solves with a dense right hand side:
|
Just as with dense matrices, the triangularView() function can be used to address a triangular part of the matrix, and perform triangular solves with a dense right hand side:
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ Hello! You are seeing this webpage because your program terminated on an asserti
|
|||||||
my_program: path/to/eigen/Eigen/src/Core/DenseStorage.h:44:
|
my_program: path/to/eigen/Eigen/src/Core/DenseStorage.h:44:
|
||||||
Eigen::internal::matrix_array<T, Size, MatrixOptions, Align>::internal::matrix_array()
|
Eigen::internal::matrix_array<T, Size, MatrixOptions, Align>::internal::matrix_array()
|
||||||
[with T = double, int Size = 2, int MatrixOptions = 2, bool Align = true]:
|
[with T = double, int Size = 2, int MatrixOptions = 2, bool Align = true]:
|
||||||
Assertion `(reinterpret_cast<size_t>(array) & 0xf) == 0 && "this assertion
|
Assertion `(reinterpret_cast<size_t>(array) & (sizemask)) == 0 && "this assertion
|
||||||
is explained here: http://eigen.tuxfamily.org/dox/UnalignedArrayAssert.html
|
is explained here: http://eigen.tuxfamily.org/dox/group__TopicUnalignedArrayAssert.html
|
||||||
**** READ THIS WEB PAGE !!! ****"' failed.
|
**** READ THIS WEB PAGE !!! ****"' failed.
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
@@ -46,9 +46,9 @@ then you need to read this separate page: \ref TopicStructHavingEigenMembers "St
|
|||||||
|
|
||||||
Note that here, Eigen::Vector2d is only used as an example, more generally the issue arises for all \ref TopicFixedSizeVectorizable "fixed-size vectorizable Eigen types".
|
Note that here, Eigen::Vector2d is only used as an example, more generally the issue arises for all \ref TopicFixedSizeVectorizable "fixed-size vectorizable Eigen types".
|
||||||
|
|
||||||
\section c2 Cause 2: STL Containers
|
\section c2 Cause 2: STL Containers or manual memory allocation
|
||||||
|
|
||||||
If you use STL Containers such as std::vector, std::map, ..., with Eigen objects, or with classes containing Eigen objects, like this,
|
If you use STL Containers such as std::vector, std::map, ..., with %Eigen objects, or with classes containing %Eigen objects, like this,
|
||||||
|
|
||||||
\code
|
\code
|
||||||
std::vector<Eigen::Matrix2f> my_vector;
|
std::vector<Eigen::Matrix2f> my_vector;
|
||||||
@@ -60,6 +60,8 @@ then you need to read this separate page: \ref TopicStlContainers "Using STL Con
|
|||||||
|
|
||||||
Note that here, Eigen::Matrix2f is only used as an example, more generally the issue arises for all \ref TopicFixedSizeVectorizable "fixed-size vectorizable Eigen types" and \ref TopicStructHavingEigenMembers "structures having such Eigen objects as member".
|
Note that here, Eigen::Matrix2f is only used as an example, more generally the issue arises for all \ref TopicFixedSizeVectorizable "fixed-size vectorizable Eigen types" and \ref TopicStructHavingEigenMembers "structures having such Eigen objects as member".
|
||||||
|
|
||||||
|
The same issue will be exhibited by any classes/functions by-passing operator new to allocate memory, that is, by performing custom memory allocation followed by calls to the placement new operator. This is for instance typically the case of \c std::make_shared or \c std::allocate_shared for which is the solution is to use an \ref aligned_allocator "aligned allocator" as detailed in the \ref TopicStlContainers "solution for STL containers".
|
||||||
|
|
||||||
\section c3 Cause 3: Passing Eigen objects by value
|
\section c3 Cause 3: Passing Eigen objects by value
|
||||||
|
|
||||||
If some function in your code is getting an Eigen object passed by value, like this,
|
If some function in your code is getting an Eigen object passed by value, like this,
|
||||||
@@ -107,7 +109,10 @@ Two possibilities:
|
|||||||
128-bit alignment code and thus preserves ABI compatibility, but completely disables vectorization.</li>
|
128-bit alignment code and thus preserves ABI compatibility, but completely disables vectorization.</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
For more information, see <a href="http://eigen.tuxfamily.org/index.php?title=FAQ#I_disabled_vectorization.2C_but_I.27m_still_getting_annoyed_about_alignment_issues.21">this FAQ</a>.
|
If you want to know why defining EIGEN_DONT_VECTORIZE does not by itself disable 128-bit alignment and the assertion, here's the explanation:
|
||||||
|
|
||||||
|
It doesn't disable the assertion, because otherwise code that runs fine without vectorization would suddenly crash when enabling vectorization.
|
||||||
|
It doesn't disable 128bit alignment, because that would mean that vectorized and non-vectorized code are not mutually ABI-compatible. This ABI compatibility is very important, even for people who develop only an in-house application, as for instance one may want to have in the same application a vectorized path and a non-vectorized path.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
180
doc/examples/matrixfree_cg.cpp
Normal file
180
doc/examples/matrixfree_cg.cpp
Normal file
@@ -0,0 +1,180 @@
|
|||||||
|
#include <iostream>
|
||||||
|
#include <Eigen/Core>
|
||||||
|
#include <Eigen/Dense>
|
||||||
|
#include <Eigen/IterativeLinearSolvers>
|
||||||
|
|
||||||
|
class MatrixReplacement;
|
||||||
|
template<typename Rhs> class MatrixReplacement_ProductReturnType;
|
||||||
|
|
||||||
|
namespace Eigen {
|
||||||
|
namespace internal {
|
||||||
|
template<>
|
||||||
|
struct traits<MatrixReplacement> : Eigen::internal::traits<Eigen::SparseMatrix<double> >
|
||||||
|
{};
|
||||||
|
|
||||||
|
template <typename Rhs>
|
||||||
|
struct traits<MatrixReplacement_ProductReturnType<Rhs> > {
|
||||||
|
// The equivalent plain objet type of the product. This type is used if the product needs to be evaluated into a temporary.
|
||||||
|
typedef Eigen::Matrix<typename Rhs::Scalar, Eigen::Dynamic, Rhs::ColsAtCompileTime> ReturnType;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inheriting EigenBase should not be needed in the future.
|
||||||
|
class MatrixReplacement : public Eigen::EigenBase<MatrixReplacement> {
|
||||||
|
public:
|
||||||
|
// Expose some compile-time information to Eigen:
|
||||||
|
typedef double Scalar;
|
||||||
|
typedef double RealScalar;
|
||||||
|
enum {
|
||||||
|
ColsAtCompileTime = Eigen::Dynamic,
|
||||||
|
RowsAtCompileTime = Eigen::Dynamic,
|
||||||
|
MaxColsAtCompileTime = Eigen::Dynamic,
|
||||||
|
MaxRowsAtCompileTime = Eigen::Dynamic
|
||||||
|
};
|
||||||
|
|
||||||
|
Index rows() const { return 4; }
|
||||||
|
Index cols() const { return 4; }
|
||||||
|
|
||||||
|
void resize(Index a_rows, Index a_cols)
|
||||||
|
{
|
||||||
|
// This method should not be needed in the future.
|
||||||
|
assert(a_rows==0 && a_cols==0 || a_rows==rows() && a_cols==cols());
|
||||||
|
}
|
||||||
|
|
||||||
|
// In the future, the return type should be Eigen::Product<MatrixReplacement,Rhs>
|
||||||
|
template<typename Rhs>
|
||||||
|
MatrixReplacement_ProductReturnType<Rhs> operator*(const Eigen::MatrixBase<Rhs>& x) const {
|
||||||
|
return MatrixReplacement_ProductReturnType<Rhs>(*this, x.derived());
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
// The proxy class representing the product of a MatrixReplacement with a MatrixBase<>
|
||||||
|
template<typename Rhs>
|
||||||
|
class MatrixReplacement_ProductReturnType : public Eigen::ReturnByValue<MatrixReplacement_ProductReturnType<Rhs> > {
|
||||||
|
public:
|
||||||
|
typedef MatrixReplacement::Index Index;
|
||||||
|
|
||||||
|
// The ctor store references to the matrix and right-hand-side object (usually a vector).
|
||||||
|
MatrixReplacement_ProductReturnType(const MatrixReplacement& matrix, const Rhs& rhs)
|
||||||
|
: m_matrix(matrix), m_rhs(rhs)
|
||||||
|
{}
|
||||||
|
|
||||||
|
Index rows() const { return m_matrix.rows(); }
|
||||||
|
Index cols() const { return m_rhs.cols(); }
|
||||||
|
|
||||||
|
// This function is automatically called by Eigen. It must evaluate the product of matrix * rhs into y.
|
||||||
|
template<typename Dest>
|
||||||
|
void evalTo(Dest& y) const
|
||||||
|
{
|
||||||
|
y.setZero(4);
|
||||||
|
|
||||||
|
y(0) += 2 * m_rhs(0); y(1) += 1 * m_rhs(0);
|
||||||
|
y(0) += 1 * m_rhs(1); y(1) += 2 * m_rhs(1); y(2) += 1 * m_rhs(1);
|
||||||
|
y(1) += 1 * m_rhs(2); y(2) += 2 * m_rhs(2); y(3) += 1 * m_rhs(2);
|
||||||
|
y(2) += 1 * m_rhs(3); y(3) += 2 * m_rhs(3);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
const MatrixReplacement& m_matrix;
|
||||||
|
typename Rhs::Nested m_rhs;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*****/
|
||||||
|
|
||||||
|
// This class simply warp a diagonal matrix as a Jacobi preconditioner.
|
||||||
|
// In the future such simple and generic wrapper should be shipped within Eigen itsel.
|
||||||
|
template <typename _Scalar>
|
||||||
|
class MyJacobiPreconditioner
|
||||||
|
{
|
||||||
|
typedef _Scalar Scalar;
|
||||||
|
typedef Eigen::Matrix<Scalar,Eigen::Dynamic,1> Vector;
|
||||||
|
typedef typename Vector::Index Index;
|
||||||
|
|
||||||
|
public:
|
||||||
|
// this typedef is only to export the scalar type and compile-time dimensions to solve_retval
|
||||||
|
typedef Eigen::Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic> MatrixType;
|
||||||
|
|
||||||
|
MyJacobiPreconditioner() : m_isInitialized(false) {}
|
||||||
|
|
||||||
|
void setInvDiag(const Eigen::VectorXd &invdiag) {
|
||||||
|
m_invdiag=invdiag;
|
||||||
|
m_isInitialized=true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Index rows() const { return m_invdiag.size(); }
|
||||||
|
Index cols() const { return m_invdiag.size(); }
|
||||||
|
|
||||||
|
template<typename MatType>
|
||||||
|
MyJacobiPreconditioner& analyzePattern(const MatType& ) { return *this; }
|
||||||
|
|
||||||
|
template<typename MatType>
|
||||||
|
MyJacobiPreconditioner& factorize(const MatType& mat) { return *this; }
|
||||||
|
|
||||||
|
template<typename MatType>
|
||||||
|
MyJacobiPreconditioner& compute(const MatType& mat) { return *this; }
|
||||||
|
|
||||||
|
template<typename Rhs, typename Dest>
|
||||||
|
void _solve(const Rhs& b, Dest& x) const
|
||||||
|
{
|
||||||
|
x = m_invdiag.array() * b.array() ;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Rhs> inline const Eigen::internal::solve_retval<MyJacobiPreconditioner, Rhs>
|
||||||
|
solve(const Eigen::MatrixBase<Rhs>& b) const
|
||||||
|
{
|
||||||
|
eigen_assert(m_isInitialized && "MyJacobiPreconditioner is not initialized.");
|
||||||
|
eigen_assert(m_invdiag.size()==b.rows()
|
||||||
|
&& "MyJacobiPreconditioner::solve(): invalid number of rows of the right hand side matrix b");
|
||||||
|
return Eigen::internal::solve_retval<MyJacobiPreconditioner, Rhs>(*this, b.derived());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Vector m_invdiag;
|
||||||
|
bool m_isInitialized;
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace Eigen {
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
template<typename _MatrixType, typename Rhs>
|
||||||
|
struct solve_retval<MyJacobiPreconditioner<_MatrixType>, Rhs>
|
||||||
|
: solve_retval_base<MyJacobiPreconditioner<_MatrixType>, Rhs>
|
||||||
|
{
|
||||||
|
typedef MyJacobiPreconditioner<_MatrixType> Dec;
|
||||||
|
EIGEN_MAKE_SOLVE_HELPERS(Dec,Rhs)
|
||||||
|
|
||||||
|
template<typename Dest> void evalTo(Dest& dst) const
|
||||||
|
{
|
||||||
|
dec()._solve(rhs(),dst);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*****/
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
MatrixReplacement A;
|
||||||
|
Eigen::VectorXd b(4), x;
|
||||||
|
b << 1, 1, 1, 1;
|
||||||
|
|
||||||
|
// solve Ax = b using CG with matrix-free version:
|
||||||
|
Eigen::ConjugateGradient < MatrixReplacement, Eigen::Lower|Eigen::Upper, MyJacobiPreconditioner<double> > cg;
|
||||||
|
|
||||||
|
Eigen::VectorXd invdiag(4);
|
||||||
|
invdiag << 1./3., 1./4., 1./4., 1./3.;
|
||||||
|
|
||||||
|
cg.preconditioner().setInvDiag(invdiag);
|
||||||
|
cg.compute(A);
|
||||||
|
x = cg.solve(b);
|
||||||
|
|
||||||
|
std::cout << "#iterations: " << cg.iterations() << std::endl;
|
||||||
|
std::cout << "estimated error: " << cg.error() << std::endl;
|
||||||
|
}
|
||||||
@@ -1,6 +1,9 @@
|
|||||||
|
prefix=@CMAKE_INSTALL_PREFIX@
|
||||||
|
exec_prefix=${prefix}
|
||||||
|
|
||||||
Name: Eigen3
|
Name: Eigen3
|
||||||
Description: A C++ template library for linear algebra: vectors, matrices, and related algorithms
|
Description: A C++ template library for linear algebra: vectors, matrices, and related algorithms
|
||||||
Requires:
|
Requires:
|
||||||
Version: ${EIGEN_VERSION_NUMBER}
|
Version: @EIGEN_VERSION_NUMBER@
|
||||||
Libs:
|
Libs:
|
||||||
Cflags: -I${INCLUDE_INSTALL_DIR}
|
Cflags: -I${prefix}/@INCLUDE_INSTALL_DIR@
|
||||||
|
|||||||
@@ -125,6 +125,7 @@ endif(TEST_LIB)
|
|||||||
set_property(GLOBAL PROPERTY EIGEN_CURRENT_SUBPROJECT "Official")
|
set_property(GLOBAL PROPERTY EIGEN_CURRENT_SUBPROJECT "Official")
|
||||||
add_custom_target(BuildOfficial)
|
add_custom_target(BuildOfficial)
|
||||||
|
|
||||||
|
ei_add_test(rand)
|
||||||
ei_add_test(meta)
|
ei_add_test(meta)
|
||||||
ei_add_test(sizeof)
|
ei_add_test(sizeof)
|
||||||
ei_add_test(dynalloc)
|
ei_add_test(dynalloc)
|
||||||
@@ -202,7 +203,9 @@ ei_add_test(geo_alignedbox)
|
|||||||
ei_add_test(stdvector)
|
ei_add_test(stdvector)
|
||||||
ei_add_test(stdvector_overload)
|
ei_add_test(stdvector_overload)
|
||||||
ei_add_test(stdlist)
|
ei_add_test(stdlist)
|
||||||
|
ei_add_test(stdlist_overload)
|
||||||
ei_add_test(stddeque)
|
ei_add_test(stddeque)
|
||||||
|
ei_add_test(stddeque_overload)
|
||||||
ei_add_test(resize)
|
ei_add_test(resize)
|
||||||
ei_add_test(sparse_vector)
|
ei_add_test(sparse_vector)
|
||||||
ei_add_test(sparse_basic)
|
ei_add_test(sparse_basic)
|
||||||
|
|||||||
@@ -9,14 +9,69 @@
|
|||||||
|
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
|
|
||||||
|
|
||||||
|
template<int M1, int M2, int N1, int N2>
|
||||||
|
void test_blocks()
|
||||||
|
{
|
||||||
|
Matrix<int, M1+M2, N1+N2> m_fixed;
|
||||||
|
MatrixXi m_dynamic(M1+M2, N1+N2);
|
||||||
|
|
||||||
|
Matrix<int, M1, N1> mat11; mat11.setRandom();
|
||||||
|
Matrix<int, M1, N2> mat12; mat12.setRandom();
|
||||||
|
Matrix<int, M2, N1> mat21; mat21.setRandom();
|
||||||
|
Matrix<int, M2, N2> mat22; mat22.setRandom();
|
||||||
|
|
||||||
|
MatrixXi matx11 = mat11, matx12 = mat12, matx21 = mat21, matx22 = mat22;
|
||||||
|
|
||||||
|
{
|
||||||
|
VERIFY_IS_EQUAL((m_fixed << mat11, mat12, mat21, matx22).finished(), (m_dynamic << mat11, matx12, mat21, matx22).finished());
|
||||||
|
VERIFY_IS_EQUAL((m_fixed.template topLeftCorner<M1,N1>()), mat11);
|
||||||
|
VERIFY_IS_EQUAL((m_fixed.template topRightCorner<M1,N2>()), mat12);
|
||||||
|
VERIFY_IS_EQUAL((m_fixed.template bottomLeftCorner<M2,N1>()), mat21);
|
||||||
|
VERIFY_IS_EQUAL((m_fixed.template bottomRightCorner<M2,N2>()), mat22);
|
||||||
|
VERIFY_IS_EQUAL((m_fixed << mat12, mat11, matx21, mat22).finished(), (m_dynamic << mat12, matx11, matx21, mat22).finished());
|
||||||
|
}
|
||||||
|
|
||||||
|
if(N1 > 0)
|
||||||
|
{
|
||||||
|
VERIFY_RAISES_ASSERT((m_fixed << mat11, mat12, mat11, mat21, mat22));
|
||||||
|
VERIFY_RAISES_ASSERT((m_fixed << mat11, mat12, mat21, mat21, mat22));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// allow insertion of zero-column blocks:
|
||||||
|
VERIFY_IS_EQUAL((m_fixed << mat11, mat12, mat11, mat11, mat21, mat21, mat22).finished(), (m_dynamic << mat12, mat22).finished());
|
||||||
|
}
|
||||||
|
if(M1 != M2)
|
||||||
|
{
|
||||||
|
VERIFY_RAISES_ASSERT((m_fixed << mat11, mat21, mat12, mat22));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<int N>
|
||||||
|
struct test_block_recursion
|
||||||
|
{
|
||||||
|
static void run()
|
||||||
|
{
|
||||||
|
test_blocks<(N>>6)&3, (N>>4)&3, (N>>2)&3, N & 3>();
|
||||||
|
test_block_recursion<N-1>::run();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct test_block_recursion<-1>
|
||||||
|
{
|
||||||
|
static void run() { }
|
||||||
|
};
|
||||||
|
|
||||||
void test_commainitializer()
|
void test_commainitializer()
|
||||||
{
|
{
|
||||||
Matrix3d m3;
|
Matrix3d m3;
|
||||||
Matrix4d m4;
|
Matrix4d m4;
|
||||||
|
|
||||||
VERIFY_RAISES_ASSERT( (m3 << 1, 2, 3, 4, 5, 6, 7, 8) );
|
|
||||||
|
|
||||||
#ifndef _MSC_VER
|
#ifndef _MSC_VER
|
||||||
|
VERIFY_RAISES_ASSERT( (m3 << 1, 2, 3, 4, 5, 6, 7, 8) );
|
||||||
VERIFY_RAISES_ASSERT( (m3 << 1, 2, 3, 4, 5, 6, 7, 8, 9, 10) );
|
VERIFY_RAISES_ASSERT( (m3 << 1, 2, 3, 4, 5, 6, 7, 8, 9, 10) );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -43,4 +98,7 @@ void test_commainitializer()
|
|||||||
4, 5, 6,
|
4, 5, 6,
|
||||||
vec[2].transpose();
|
vec[2].transpose();
|
||||||
VERIFY_IS_APPROX(m3, ref);
|
VERIFY_IS_APPROX(m3, ref);
|
||||||
|
|
||||||
|
// recursively test all block-sizes from 0 to 3:
|
||||||
|
test_block_recursion<(1<<8) - 1>();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -164,9 +164,12 @@ template<typename MatrixType> void cwiseops(const MatrixType& m)
|
|||||||
VERIFY( (m1.cwise().min(m2).cwise() < (m1+mones)).all() );
|
VERIFY( (m1.cwise().min(m2).cwise() < (m1+mones)).all() );
|
||||||
VERIFY( (m1.cwise().max(m2).cwise() > (m1-mones)).all() );
|
VERIFY( (m1.cwise().max(m2).cwise() > (m1-mones)).all() );
|
||||||
|
|
||||||
|
#if(__cplusplus < 201103L)
|
||||||
|
// std::binder* are deprecated since c++11 and will be removed in c++17
|
||||||
VERIFY( (m1.cwise()<m1.unaryExpr(bind2nd(plus<Scalar>(), Scalar(1)))).all() );
|
VERIFY( (m1.cwise()<m1.unaryExpr(bind2nd(plus<Scalar>(), Scalar(1)))).all() );
|
||||||
VERIFY( !(m1.cwise()<m1bis.unaryExpr(bind2nd(minus<Scalar>(), Scalar(1)))).all() );
|
VERIFY( !(m1.cwise()<m1bis.unaryExpr(bind2nd(minus<Scalar>(), Scalar(1)))).all() );
|
||||||
VERIFY( !(m1.cwise()>m1bis.unaryExpr(bind2nd(plus<Scalar>(), Scalar(1)))).any() );
|
VERIFY( !(m1.cwise()>m1bis.unaryExpr(bind2nd(plus<Scalar>(), Scalar(1)))).any() );
|
||||||
|
#endif
|
||||||
|
|
||||||
cwiseops_real_only(m1, m2, m3, mones);
|
cwiseops_real_only(m1, m2, m3, mones);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -87,6 +87,32 @@ template<typename T> void check_dynaligned()
|
|||||||
delete obj;
|
delete obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T> void check_custom_new_delete()
|
||||||
|
{
|
||||||
|
{
|
||||||
|
T* t = new T;
|
||||||
|
delete t;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
std::size_t N = internal::random<std::size_t>(1,10);
|
||||||
|
T* t = new T[N];
|
||||||
|
delete[] t;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef EIGEN_ALIGN
|
||||||
|
{
|
||||||
|
T* t = static_cast<T *>((T::operator new)(sizeof(T)));
|
||||||
|
(T::operator delete)(t, sizeof(T));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
T* t = static_cast<T *>((T::operator new)(sizeof(T)));
|
||||||
|
(T::operator delete)(t);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void test_dynalloc()
|
void test_dynalloc()
|
||||||
{
|
{
|
||||||
// low level dynamic memory allocation
|
// low level dynamic memory allocation
|
||||||
@@ -94,7 +120,9 @@ void test_dynalloc()
|
|||||||
CALL_SUBTEST(check_aligned_malloc());
|
CALL_SUBTEST(check_aligned_malloc());
|
||||||
CALL_SUBTEST(check_aligned_new());
|
CALL_SUBTEST(check_aligned_new());
|
||||||
CALL_SUBTEST(check_aligned_stack_alloc());
|
CALL_SUBTEST(check_aligned_stack_alloc());
|
||||||
|
|
||||||
|
// check static allocation, who knows ?
|
||||||
|
#if EIGEN_ALIGN_STATICALLY
|
||||||
for (int i=0; i<g_repeat*100; ++i)
|
for (int i=0; i<g_repeat*100; ++i)
|
||||||
{
|
{
|
||||||
CALL_SUBTEST(check_dynaligned<Vector4f>() );
|
CALL_SUBTEST(check_dynaligned<Vector4f>() );
|
||||||
@@ -102,10 +130,13 @@ void test_dynalloc()
|
|||||||
CALL_SUBTEST(check_dynaligned<Matrix4f>() );
|
CALL_SUBTEST(check_dynaligned<Matrix4f>() );
|
||||||
CALL_SUBTEST(check_dynaligned<Vector4d>() );
|
CALL_SUBTEST(check_dynaligned<Vector4d>() );
|
||||||
CALL_SUBTEST(check_dynaligned<Vector4i>() );
|
CALL_SUBTEST(check_dynaligned<Vector4i>() );
|
||||||
|
|
||||||
|
CALL_SUBTEST( check_custom_new_delete<Vector4f>() );
|
||||||
|
CALL_SUBTEST( check_custom_new_delete<Vector2f>() );
|
||||||
|
CALL_SUBTEST( check_custom_new_delete<Matrix4f>() );
|
||||||
|
CALL_SUBTEST( check_custom_new_delete<MatrixXi>() );
|
||||||
}
|
}
|
||||||
|
|
||||||
// check static allocation, who knows ?
|
|
||||||
#if EIGEN_ALIGN_STATICALLY
|
|
||||||
{
|
{
|
||||||
MyStruct foo0; VERIFY(size_t(foo0.avec.data())%ALIGNMENT==0);
|
MyStruct foo0; VERIFY(size_t(foo0.avec.data())%ALIGNMENT==0);
|
||||||
MyClassA fooA; VERIFY(size_t(fooA.avec.data())%ALIGNMENT==0);
|
MyClassA fooA; VERIFY(size_t(fooA.avec.data())%ALIGNMENT==0);
|
||||||
|
|||||||
@@ -137,9 +137,12 @@ template<typename MatrixType> void cwiseops(const MatrixType& m)
|
|||||||
VERIFY( (m1.cwise().min(m2).cwise() < (m1+mones)).all() );
|
VERIFY( (m1.cwise().min(m2).cwise() < (m1+mones)).all() );
|
||||||
VERIFY( (m1.cwise().max(m2).cwise() > (m1-mones)).all() );
|
VERIFY( (m1.cwise().max(m2).cwise() > (m1-mones)).all() );
|
||||||
|
|
||||||
|
#if(__cplusplus < 201103L)
|
||||||
|
// std::binder* are deprecated since c++11 and will be removed in c++17
|
||||||
VERIFY( (m1.cwise()<m1.unaryExpr(bind2nd(plus<Scalar>(), Scalar(1)))).all() );
|
VERIFY( (m1.cwise()<m1.unaryExpr(bind2nd(plus<Scalar>(), Scalar(1)))).all() );
|
||||||
VERIFY( !(m1.cwise()<m1.unaryExpr(bind2nd(minus<Scalar>(), Scalar(1)))).all() );
|
VERIFY( !(m1.cwise()<m1.unaryExpr(bind2nd(minus<Scalar>(), Scalar(1)))).all() );
|
||||||
VERIFY( !(m1.cwise()>m1.unaryExpr(bind2nd(plus<Scalar>(), Scalar(1)))).any() );
|
VERIFY( !(m1.cwise()>m1.unaryExpr(bind2nd(plus<Scalar>(), Scalar(1)))).any() );
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_eigen2_cwiseop()
|
void test_eigen2_cwiseop()
|
||||||
|
|||||||
@@ -54,6 +54,8 @@ template<typename Scalar,int Size> void homogeneous(void)
|
|||||||
T2MatrixType t2 = T2MatrixType::Random();
|
T2MatrixType t2 = T2MatrixType::Random();
|
||||||
VERIFY_IS_APPROX(t2 * (v0.homogeneous().eval()), t2 * v0.homogeneous());
|
VERIFY_IS_APPROX(t2 * (v0.homogeneous().eval()), t2 * v0.homogeneous());
|
||||||
VERIFY_IS_APPROX(t2 * (m0.colwise().homogeneous().eval()), t2 * m0.colwise().homogeneous());
|
VERIFY_IS_APPROX(t2 * (m0.colwise().homogeneous().eval()), t2 * m0.colwise().homogeneous());
|
||||||
|
VERIFY_IS_APPROX(t2 * (v0.homogeneous().asDiagonal()), t2 * hv0.asDiagonal());
|
||||||
|
VERIFY_IS_APPROX((v0.homogeneous().asDiagonal()) * t2, hv0.asDiagonal() * t2);
|
||||||
|
|
||||||
VERIFY_IS_APPROX((v0.transpose().rowwise().homogeneous().eval()) * t2,
|
VERIFY_IS_APPROX((v0.transpose().rowwise().homogeneous().eval()) * t2,
|
||||||
v0.transpose().rowwise().homogeneous() * t2);
|
v0.transpose().rowwise().homogeneous() * t2);
|
||||||
|
|||||||
@@ -320,6 +320,9 @@ template<typename Scalar, int Mode, int Options> void transformations()
|
|||||||
t0.scale(v0);
|
t0.scale(v0);
|
||||||
t1 *= AlignedScaling3(v0);
|
t1 *= AlignedScaling3(v0);
|
||||||
VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
|
VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
|
||||||
|
t1 = AlignedScaling3(v0) * (Translation3(v0) * Transform3(q1));
|
||||||
|
t1 = t1 * v0.asDiagonal();
|
||||||
|
VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
|
||||||
// transformation * translation
|
// transformation * translation
|
||||||
t0.translate(v0);
|
t0.translate(v0);
|
||||||
t1 = t1 * Translation3(v0);
|
t1 = t1 * Translation3(v0);
|
||||||
@@ -437,6 +440,79 @@ template<typename Scalar, int Mode, int Options> void transformations()
|
|||||||
Rotation2D<Scalar> r2(r1); // copy ctor
|
Rotation2D<Scalar> r2(r1); // copy ctor
|
||||||
VERIFY_IS_APPROX(r2.angle(),s0);
|
VERIFY_IS_APPROX(r2.angle(),s0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
Transform3 t32(Matrix4::Random()), t33, t34;
|
||||||
|
t34 = t33 = t32;
|
||||||
|
t32.scale(v0);
|
||||||
|
t33*=AlignedScaling3(v0);
|
||||||
|
VERIFY_IS_APPROX(t32.matrix(), t33.matrix());
|
||||||
|
t33 = t34 * AlignedScaling3(v0);
|
||||||
|
VERIFY_IS_APPROX(t32.matrix(), t33.matrix());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename A1, typename A2, typename P, typename Q, typename V, typename H>
|
||||||
|
void transform_associativity_left(const A1& a1, const A2& a2, const P& p, const Q& q, const V& v, const H& h)
|
||||||
|
{
|
||||||
|
VERIFY_IS_APPROX( q*(a1*v), (q*a1)*v );
|
||||||
|
VERIFY_IS_APPROX( q*(a2*v), (q*a2)*v );
|
||||||
|
VERIFY_IS_APPROX( q*(p*h).hnormalized(), ((q*p)*h).hnormalized() );
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename A1, typename A2, typename P, typename Q, typename V, typename H>
|
||||||
|
void transform_associativity2(const A1& a1, const A2& a2, const P& p, const Q& q, const V& v, const H& h)
|
||||||
|
{
|
||||||
|
VERIFY_IS_APPROX( a1*(q*v), (a1*q)*v );
|
||||||
|
VERIFY_IS_APPROX( a2*(q*v), (a2*q)*v );
|
||||||
|
VERIFY_IS_APPROX( p *(q*v).homogeneous(), (p *q)*v.homogeneous() );
|
||||||
|
|
||||||
|
transform_associativity_left(a1, a2,p, q, v, h);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Scalar, int Dim, int Options,typename RotationType>
|
||||||
|
void transform_associativity(const RotationType& R)
|
||||||
|
{
|
||||||
|
typedef Matrix<Scalar,Dim,1> VectorType;
|
||||||
|
typedef Matrix<Scalar,Dim+1,1> HVectorType;
|
||||||
|
typedef Matrix<Scalar,Dim,Dim> LinearType;
|
||||||
|
typedef Matrix<Scalar,Dim+1,Dim+1> MatrixType;
|
||||||
|
typedef Transform<Scalar,Dim,AffineCompact,Options> AffineCompactType;
|
||||||
|
typedef Transform<Scalar,Dim,Affine,Options> AffineType;
|
||||||
|
typedef Transform<Scalar,Dim,Projective,Options> ProjectiveType;
|
||||||
|
typedef DiagonalMatrix<Scalar,Dim> ScalingType;
|
||||||
|
typedef Translation<Scalar,Dim> TranslationType;
|
||||||
|
|
||||||
|
AffineCompactType A1c; A1c.matrix().setRandom();
|
||||||
|
AffineCompactType A2c; A2c.matrix().setRandom();
|
||||||
|
AffineType A1(A1c);
|
||||||
|
AffineType A2(A2c);
|
||||||
|
ProjectiveType P1; P1.matrix().setRandom();
|
||||||
|
VectorType v1 = VectorType::Random();
|
||||||
|
VectorType v2 = VectorType::Random();
|
||||||
|
HVectorType h1 = HVectorType::Random();
|
||||||
|
Scalar s1 = internal::random<Scalar>();
|
||||||
|
LinearType L = LinearType::Random();
|
||||||
|
MatrixType M = MatrixType::Random();
|
||||||
|
|
||||||
|
CALL_SUBTEST( transform_associativity2(A1c, A1, P1, A2, v2, h1) );
|
||||||
|
CALL_SUBTEST( transform_associativity2(A1c, A1, P1, A2c, v2, h1) );
|
||||||
|
CALL_SUBTEST( transform_associativity2(A1c, A1, P1, v1.asDiagonal(), v2, h1) );
|
||||||
|
CALL_SUBTEST( transform_associativity2(A1c, A1, P1, ScalingType(v1), v2, h1) );
|
||||||
|
CALL_SUBTEST( transform_associativity2(A1c, A1, P1, Scaling(v1), v2, h1) );
|
||||||
|
CALL_SUBTEST( transform_associativity2(A1c, A1, P1, Scaling(s1), v2, h1) );
|
||||||
|
CALL_SUBTEST( transform_associativity2(A1c, A1, P1, TranslationType(v1), v2, h1) );
|
||||||
|
CALL_SUBTEST( transform_associativity_left(A1c, A1, P1, L, v2, h1) );
|
||||||
|
CALL_SUBTEST( transform_associativity2(A1c, A1, P1, R, v2, h1) );
|
||||||
|
|
||||||
|
VERIFY_IS_APPROX( A1*(M*h1), (A1*M)*h1 );
|
||||||
|
VERIFY_IS_APPROX( A1c*(M*h1), (A1c*M)*h1 );
|
||||||
|
VERIFY_IS_APPROX( P1*(M*h1), (P1*M)*h1 );
|
||||||
|
|
||||||
|
VERIFY_IS_APPROX( M*(A1*h1), (M*A1)*h1 );
|
||||||
|
VERIFY_IS_APPROX( M*(A1c*h1), (M*A1c)*h1 );
|
||||||
|
VERIFY_IS_APPROX( M*(P1*h1), ((M*P1)*h1) );
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Scalar> void transform_alignment()
|
template<typename Scalar> void transform_alignment()
|
||||||
@@ -517,5 +593,8 @@ void test_geo_transformations()
|
|||||||
|
|
||||||
CALL_SUBTEST_7(( transform_products<double,3,RowMajor|AutoAlign>() ));
|
CALL_SUBTEST_7(( transform_products<double,3,RowMajor|AutoAlign>() ));
|
||||||
CALL_SUBTEST_7(( transform_products<float,2,AutoAlign>() ));
|
CALL_SUBTEST_7(( transform_products<float,2,AutoAlign>() ));
|
||||||
|
|
||||||
|
CALL_SUBTEST_8(( transform_associativity<double,2,ColMajor>(Rotation2D<double>(internal::random<double>()*double(3.14))) ));
|
||||||
|
CALL_SUBTEST_8(( transform_associativity<double,3,ColMajor>(Quaterniond(Vector4d::Random().normalized())) ));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -327,6 +327,7 @@ template<typename Scalar,bool ConjLhs,bool ConjRhs> void test_conj_helper(Scalar
|
|||||||
ref[i] += cj0(data1[i]) * cj1(data2[i]);
|
ref[i] += cj0(data1[i]) * cj1(data2[i]);
|
||||||
VERIFY(internal::isApprox(ref[i], cj.pmadd(data1[i],data2[i],tmp)) && "conj_helper pmadd");
|
VERIFY(internal::isApprox(ref[i], cj.pmadd(data1[i],data2[i],tmp)) && "conj_helper pmadd");
|
||||||
}
|
}
|
||||||
|
*pval += 0; // Workaround msvc 2013 issue (bad code generation)
|
||||||
internal::pstore(pval,pcj.pmadd(internal::pload<Packet>(data1),internal::pload<Packet>(data2),internal::pload<Packet>(pval)));
|
internal::pstore(pval,pcj.pmadd(internal::pload<Packet>(data1),internal::pload<Packet>(data2),internal::pload<Packet>(pval)));
|
||||||
VERIFY(areApprox(ref, pval, PacketSize) && "conj_helper pmadd");
|
VERIFY(areApprox(ref, pval, PacketSize) && "conj_helper pmadd");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,14 +53,29 @@ template<typename MatrixType> void inverse_general_4x4(int repeat)
|
|||||||
// FIXME that 1.25 used to be 1.2 until we tested gcc 4.1 on 30 June 2010 and got 1.21.
|
// FIXME that 1.25 used to be 1.2 until we tested gcc 4.1 on 30 June 2010 and got 1.21.
|
||||||
VERIFY(error_avg < (NumTraits<Scalar>::IsComplex ? 8.0 : 1.25));
|
VERIFY(error_avg < (NumTraits<Scalar>::IsComplex ? 8.0 : 1.25));
|
||||||
VERIFY(error_max < (NumTraits<Scalar>::IsComplex ? 64.0 : 20.0));
|
VERIFY(error_max < (NumTraits<Scalar>::IsComplex ? 64.0 : 20.0));
|
||||||
|
|
||||||
|
{
|
||||||
|
int s = 5;//internal::random<int>(4,10);
|
||||||
|
int i = 0;//internal::random<int>(0,s-4);
|
||||||
|
int j = 0;//internal::random<int>(0,s-4);
|
||||||
|
Matrix<Scalar,5,5> mat(s,s);
|
||||||
|
mat.setRandom();
|
||||||
|
MatrixType submat = mat.template block<4,4>(i,j);
|
||||||
|
MatrixType mat_inv = mat.template block<4,4>(i,j).inverse();
|
||||||
|
VERIFY_IS_APPROX(mat_inv, submat.inverse());
|
||||||
|
mat.template block<4,4>(i,j) = submat.inverse();
|
||||||
|
VERIFY_IS_APPROX(mat_inv, (mat.template block<4,4>(i,j)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_prec_inverse_4x4()
|
void test_prec_inverse_4x4()
|
||||||
{
|
{
|
||||||
CALL_SUBTEST_1((inverse_permutation_4x4<Matrix4f>()));
|
CALL_SUBTEST_1((inverse_permutation_4x4<Matrix4f>()));
|
||||||
CALL_SUBTEST_1(( inverse_general_4x4<Matrix4f>(200000 * g_repeat) ));
|
CALL_SUBTEST_1(( inverse_general_4x4<Matrix4f>(200000 * g_repeat) ));
|
||||||
|
CALL_SUBTEST_1(( inverse_general_4x4<Matrix<float,4,4,RowMajor> >(200000 * g_repeat) ));
|
||||||
|
|
||||||
CALL_SUBTEST_2((inverse_permutation_4x4<Matrix<double,4,4,RowMajor> >()));
|
CALL_SUBTEST_2((inverse_permutation_4x4<Matrix<double,4,4,RowMajor> >()));
|
||||||
|
CALL_SUBTEST_2(( inverse_general_4x4<Matrix<double,4,4,ColMajor> >(200000 * g_repeat) ));
|
||||||
CALL_SUBTEST_2(( inverse_general_4x4<Matrix<double,4,4,RowMajor> >(200000 * g_repeat) ));
|
CALL_SUBTEST_2(( inverse_general_4x4<Matrix<double,4,4,RowMajor> >(200000 * g_repeat) ));
|
||||||
|
|
||||||
CALL_SUBTEST_3((inverse_permutation_4x4<Matrix4cf>()));
|
CALL_SUBTEST_3((inverse_permutation_4x4<Matrix4cf>()));
|
||||||
|
|||||||
@@ -136,9 +136,27 @@ template<typename MatrixType> void product(const MatrixType& m)
|
|||||||
VERIFY_IS_APPROX(res.col(r).noalias() = square.adjoint() * square.col(r), (square.adjoint() * square.col(r)).eval());
|
VERIFY_IS_APPROX(res.col(r).noalias() = square.adjoint() * square.col(r), (square.adjoint() * square.col(r)).eval());
|
||||||
VERIFY_IS_APPROX(res.col(r).noalias() = square * square.col(r), (square * square.col(r)).eval());
|
VERIFY_IS_APPROX(res.col(r).noalias() = square * square.col(r), (square * square.col(r)).eval());
|
||||||
|
|
||||||
|
// vector at runtime (see bug 1166)
|
||||||
|
{
|
||||||
|
RowSquareMatrixType ref(square);
|
||||||
|
ColSquareMatrixType ref2(square2);
|
||||||
|
ref = res = square;
|
||||||
|
VERIFY_IS_APPROX(res.block(0,0,1,rows).noalias() = m1.col(0).transpose() * square.transpose(), (ref.row(0) = m1.col(0).transpose() * square.transpose()));
|
||||||
|
VERIFY_IS_APPROX(res.block(0,0,1,rows).noalias() = m1.block(0,0,rows,1).transpose() * square.transpose(), (ref.row(0) = m1.col(0).transpose() * square.transpose()));
|
||||||
|
VERIFY_IS_APPROX(res.block(0,0,1,rows).noalias() = m1.col(0).transpose() * square, (ref.row(0) = m1.col(0).transpose() * square));
|
||||||
|
VERIFY_IS_APPROX(res.block(0,0,1,rows).noalias() = m1.block(0,0,rows,1).transpose() * square, (ref.row(0) = m1.col(0).transpose() * square));
|
||||||
|
ref2 = res2 = square2;
|
||||||
|
VERIFY_IS_APPROX(res2.block(0,0,1,cols).noalias() = m1.row(0) * square2.transpose(), (ref2.row(0) = m1.row(0) * square2.transpose()));
|
||||||
|
VERIFY_IS_APPROX(res2.block(0,0,1,cols).noalias() = m1.block(0,0,1,cols) * square2.transpose(), (ref2.row(0) = m1.row(0) * square2.transpose()));
|
||||||
|
VERIFY_IS_APPROX(res2.block(0,0,1,cols).noalias() = m1.row(0) * square2, (ref2.row(0) = m1.row(0) * square2));
|
||||||
|
VERIFY_IS_APPROX(res2.block(0,0,1,cols).noalias() = m1.block(0,0,1,cols) * square2, (ref2.row(0) = m1.row(0) * square2));
|
||||||
|
}
|
||||||
|
|
||||||
// inner product
|
// inner product
|
||||||
Scalar x = square2.row(c) * square2.col(c2);
|
{
|
||||||
VERIFY_IS_APPROX(x, square2.row(c).transpose().cwiseProduct(square2.col(c2)).sum());
|
Scalar x = square2.row(c) * square2.col(c2);
|
||||||
|
VERIFY_IS_APPROX(x, square2.row(c).transpose().cwiseProduct(square2.col(c2)).sum());
|
||||||
|
}
|
||||||
|
|
||||||
// outer product
|
// outer product
|
||||||
VERIFY_IS_APPROX(m1.col(c) * m1.row(r), m1.block(0,c,rows,1) * m1.block(r,0,1,cols));
|
VERIFY_IS_APPROX(m1.col(c) * m1.row(r), m1.block(0,c,rows,1) * m1.block(r,0,1,cols));
|
||||||
@@ -146,5 +164,26 @@ template<typename MatrixType> void product(const MatrixType& m)
|
|||||||
VERIFY_IS_APPROX(m1.block(0,c,rows,1) * m1.row(r), m1.block(0,c,rows,1) * m1.block(r,0,1,cols));
|
VERIFY_IS_APPROX(m1.block(0,c,rows,1) * m1.row(r), m1.block(0,c,rows,1) * m1.block(r,0,1,cols));
|
||||||
VERIFY_IS_APPROX(m1.col(c) * m1.block(r,0,1,cols), m1.block(0,c,rows,1) * m1.block(r,0,1,cols));
|
VERIFY_IS_APPROX(m1.col(c) * m1.block(r,0,1,cols), m1.block(0,c,rows,1) * m1.block(r,0,1,cols));
|
||||||
VERIFY_IS_APPROX(m1.leftCols(1) * m1.row(r), m1.block(0,0,rows,1) * m1.block(r,0,1,cols));
|
VERIFY_IS_APPROX(m1.leftCols(1) * m1.row(r), m1.block(0,0,rows,1) * m1.block(r,0,1,cols));
|
||||||
VERIFY_IS_APPROX(m1.col(c) * m1.topRows(1), m1.block(0,c,rows,1) * m1.block(0,0,1,cols));
|
VERIFY_IS_APPROX(m1.col(c) * m1.topRows(1), m1.block(0,c,rows,1) * m1.block(0,0,1,cols));
|
||||||
|
|
||||||
|
// Aliasing
|
||||||
|
{
|
||||||
|
ColVectorType x(cols); x.setRandom();
|
||||||
|
ColVectorType z(x);
|
||||||
|
ColVectorType y(cols); y.setZero();
|
||||||
|
ColSquareMatrixType A(cols,cols); A.setRandom();
|
||||||
|
// CwiseBinaryOp
|
||||||
|
VERIFY_IS_APPROX(x = y + A*x, A*z);
|
||||||
|
x = z;
|
||||||
|
// CwiseUnaryOp
|
||||||
|
VERIFY_IS_APPROX(x = Scalar(1.)*(A*x), A*z);
|
||||||
|
}
|
||||||
|
|
||||||
|
// regression for blas_trais
|
||||||
|
{
|
||||||
|
VERIFY_IS_APPROX(square * (square*square).transpose(), square * square.transpose() * square.transpose());
|
||||||
|
VERIFY_IS_APPROX(square * (-(square*square)), -square * square * square);
|
||||||
|
VERIFY_IS_APPROX(square * (s1*(square*square)), s1 * square * square * square);
|
||||||
|
VERIFY_IS_APPROX(square * (square*square).conjugate(), square * square.conjugate() * square.conjugate());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,27 @@
|
|||||||
|
|
||||||
#include "product.h"
|
#include "product.h"
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void test_aliasing()
|
||||||
|
{
|
||||||
|
int rows = internal::random<int>(1,12);
|
||||||
|
int cols = internal::random<int>(1,12);
|
||||||
|
typedef Matrix<T,Dynamic,Dynamic> MatrixType;
|
||||||
|
typedef Matrix<T,Dynamic,1> VectorType;
|
||||||
|
VectorType x(cols); x.setRandom();
|
||||||
|
VectorType z(x);
|
||||||
|
VectorType y(rows); y.setZero();
|
||||||
|
MatrixType A(rows,cols); A.setRandom();
|
||||||
|
// CwiseBinaryOp
|
||||||
|
VERIFY_IS_APPROX(x = y + A*x, A*z);
|
||||||
|
x = z;
|
||||||
|
// CwiseUnaryOp
|
||||||
|
VERIFY_IS_APPROX(x = T(1.)*(A*x), A*z);
|
||||||
|
x = z;
|
||||||
|
VERIFY_IS_APPROX(x = y+(-(A*x)), -A*z);
|
||||||
|
x = z;
|
||||||
|
}
|
||||||
|
|
||||||
void test_product_large()
|
void test_product_large()
|
||||||
{
|
{
|
||||||
for(int i = 0; i < g_repeat; i++) {
|
for(int i = 0; i < g_repeat; i++) {
|
||||||
@@ -17,6 +38,8 @@ void test_product_large()
|
|||||||
CALL_SUBTEST_3( product(MatrixXi(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
|
CALL_SUBTEST_3( product(MatrixXi(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
|
||||||
CALL_SUBTEST_4( product(MatrixXcf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2), internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2))) );
|
CALL_SUBTEST_4( product(MatrixXcf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2), internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2))) );
|
||||||
CALL_SUBTEST_5( product(Matrix<float,Dynamic,Dynamic,RowMajor>(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
|
CALL_SUBTEST_5( product(Matrix<float,Dynamic,Dynamic,RowMajor>(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
|
||||||
|
|
||||||
|
CALL_SUBTEST_1( test_aliasing<float>() );
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined EIGEN_TEST_PART_6
|
#if defined EIGEN_TEST_PART_6
|
||||||
|
|||||||
@@ -58,10 +58,19 @@ template<typename MatrixType> void product_notemporary(const MatrixType& m)
|
|||||||
r1 = internal::random<Index>(8,rows-r0);
|
r1 = internal::random<Index>(8,rows-r0);
|
||||||
|
|
||||||
VERIFY_EVALUATION_COUNT( m3 = (m1 * m2.adjoint()), 1);
|
VERIFY_EVALUATION_COUNT( m3 = (m1 * m2.adjoint()), 1);
|
||||||
|
VERIFY_EVALUATION_COUNT( m3 = (m1 * m2.adjoint()).transpose(), 1);
|
||||||
VERIFY_EVALUATION_COUNT( m3.noalias() = m1 * m2.adjoint(), 0);
|
VERIFY_EVALUATION_COUNT( m3.noalias() = m1 * m2.adjoint(), 0);
|
||||||
|
|
||||||
|
VERIFY_EVALUATION_COUNT( m3 = s1 * (m1 * m2.transpose()), 1);
|
||||||
|
VERIFY_EVALUATION_COUNT( m3 = m3 + s1 * (m1 * m2.transpose()), 1);
|
||||||
VERIFY_EVALUATION_COUNT( m3.noalias() = s1 * (m1 * m2.transpose()), 0);
|
VERIFY_EVALUATION_COUNT( m3.noalias() = s1 * (m1 * m2.transpose()), 0);
|
||||||
|
|
||||||
|
VERIFY_EVALUATION_COUNT( m3 = m3 + (m1 * m2.adjoint()), 1);
|
||||||
|
VERIFY_EVALUATION_COUNT( m3 = m3 + (m1 * m2.adjoint()).transpose(), 1);
|
||||||
|
VERIFY_EVALUATION_COUNT( m3.noalias() = m3 + m1 * m2.transpose(), 1); // 0 in 3.3
|
||||||
|
VERIFY_EVALUATION_COUNT( m3.noalias() += m3 + m1 * m2.transpose(), 1); // 0 in 3.3
|
||||||
|
VERIFY_EVALUATION_COUNT( m3.noalias() -= m3 + m1 * m2.transpose(), 1); // 0 in 3.3
|
||||||
|
|
||||||
VERIFY_EVALUATION_COUNT( m3.noalias() = s1 * m1 * s2 * m2.adjoint(), 0);
|
VERIFY_EVALUATION_COUNT( m3.noalias() = s1 * m1 * s2 * m2.adjoint(), 0);
|
||||||
VERIFY_EVALUATION_COUNT( m3.noalias() = s1 * m1 * s2 * (m1*s3+m2*s2).adjoint(), 1);
|
VERIFY_EVALUATION_COUNT( m3.noalias() = s1 * m1 * s2 * (m1*s3+m2*s2).adjoint(), 1);
|
||||||
VERIFY_EVALUATION_COUNT( m3.noalias() = (s1 * m1).adjoint() * s2 * m2, 0);
|
VERIFY_EVALUATION_COUNT( m3.noalias() = (s1 * m1).adjoint() * s2 * m2, 0);
|
||||||
|
|||||||
118
test/rand.cpp
Normal file
118
test/rand.cpp
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
// This file is part of Eigen, a lightweight C++ template library
|
||||||
|
// for linear algebra.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2015 Gael Guennebaud <gael.guennebaud@inria.fr>
|
||||||
|
//
|
||||||
|
// 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/.
|
||||||
|
|
||||||
|
#include "main.h"
|
||||||
|
|
||||||
|
typedef long long int64;
|
||||||
|
|
||||||
|
template<typename Scalar> Scalar check_in_range(Scalar x, Scalar y)
|
||||||
|
{
|
||||||
|
Scalar r = internal::random<Scalar>(x,y);
|
||||||
|
VERIFY(r>=x);
|
||||||
|
if(y>=x)
|
||||||
|
{
|
||||||
|
VERIFY(r<=y);
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Scalar> void check_all_in_range(Scalar x, Scalar y)
|
||||||
|
{
|
||||||
|
Array<int,1,Dynamic> mask(y-x+1);
|
||||||
|
mask.fill(0);
|
||||||
|
long n = (y-x+1)*32;
|
||||||
|
for(long k=0; k<n; ++k)
|
||||||
|
{
|
||||||
|
mask( check_in_range(x,y)-x )++;
|
||||||
|
}
|
||||||
|
for(DenseIndex i=0; i<mask.size(); ++i)
|
||||||
|
if(mask(i)==0)
|
||||||
|
std::cout << "WARNING: value " << x+i << " not reached." << std::endl;
|
||||||
|
VERIFY( (mask>0).all() );
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Scalar> void check_histogram(Scalar x, Scalar y, int bins)
|
||||||
|
{
|
||||||
|
Array<int,1,Dynamic> hist(bins);
|
||||||
|
hist.fill(0);
|
||||||
|
int f = 100000;
|
||||||
|
int n = bins*f;
|
||||||
|
int64 range = int64(y)-int64(x);
|
||||||
|
int divisor = int((range+1)/bins);
|
||||||
|
assert(((range+1)%bins)==0);
|
||||||
|
for(int k=0; k<n; ++k)
|
||||||
|
{
|
||||||
|
Scalar r = check_in_range(x,y);
|
||||||
|
hist( int((int64(r)-int64(x))/divisor) )++;
|
||||||
|
}
|
||||||
|
VERIFY( (((hist.cast<double>()/double(f))-1.0).abs()<0.02).all() );
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_rand()
|
||||||
|
{
|
||||||
|
long long_ref = NumTraits<long>::highest()/10;
|
||||||
|
signed char char_offset = (std::min)(g_repeat,64);
|
||||||
|
signed char short_offset = (std::min)(g_repeat,16000);
|
||||||
|
|
||||||
|
for(int i = 0; i < g_repeat*10000; i++) {
|
||||||
|
CALL_SUBTEST(check_in_range<float>(10,11));
|
||||||
|
CALL_SUBTEST(check_in_range<float>(1.24234523,1.24234523));
|
||||||
|
CALL_SUBTEST(check_in_range<float>(-1,1));
|
||||||
|
CALL_SUBTEST(check_in_range<float>(-1432.2352,-1432.2352));
|
||||||
|
|
||||||
|
CALL_SUBTEST(check_in_range<double>(10,11));
|
||||||
|
CALL_SUBTEST(check_in_range<double>(1.24234523,1.24234523));
|
||||||
|
CALL_SUBTEST(check_in_range<double>(-1,1));
|
||||||
|
CALL_SUBTEST(check_in_range<double>(-1432.2352,-1432.2352));
|
||||||
|
|
||||||
|
CALL_SUBTEST(check_in_range<int>(0,-1));
|
||||||
|
CALL_SUBTEST(check_in_range<short>(0,-1));
|
||||||
|
CALL_SUBTEST(check_in_range<long>(0,-1));
|
||||||
|
CALL_SUBTEST(check_in_range<int>(-673456,673456));
|
||||||
|
CALL_SUBTEST(check_in_range<int>(-RAND_MAX+10,RAND_MAX-10));
|
||||||
|
CALL_SUBTEST(check_in_range<short>(-24345,24345));
|
||||||
|
CALL_SUBTEST(check_in_range<long>(-long_ref,long_ref));
|
||||||
|
}
|
||||||
|
|
||||||
|
CALL_SUBTEST(check_all_in_range<signed char>(11,11));
|
||||||
|
CALL_SUBTEST(check_all_in_range<signed char>(11,11+char_offset));
|
||||||
|
CALL_SUBTEST(check_all_in_range<signed char>(-5,5));
|
||||||
|
CALL_SUBTEST(check_all_in_range<signed char>(-11-char_offset,-11));
|
||||||
|
CALL_SUBTEST(check_all_in_range<signed char>(-126,-126+char_offset));
|
||||||
|
CALL_SUBTEST(check_all_in_range<signed char>(126-char_offset,126));
|
||||||
|
CALL_SUBTEST(check_all_in_range<signed char>(-126,126));
|
||||||
|
|
||||||
|
CALL_SUBTEST(check_all_in_range<short>(11,11));
|
||||||
|
CALL_SUBTEST(check_all_in_range<short>(11,11+short_offset));
|
||||||
|
CALL_SUBTEST(check_all_in_range<short>(-5,5));
|
||||||
|
CALL_SUBTEST(check_all_in_range<short>(-11-short_offset,-11));
|
||||||
|
CALL_SUBTEST(check_all_in_range<short>(-24345,-24345+short_offset));
|
||||||
|
CALL_SUBTEST(check_all_in_range<short>(24345,24345+short_offset));
|
||||||
|
|
||||||
|
CALL_SUBTEST(check_all_in_range<int>(11,11));
|
||||||
|
CALL_SUBTEST(check_all_in_range<int>(11,11+g_repeat));
|
||||||
|
CALL_SUBTEST(check_all_in_range<int>(-5,5));
|
||||||
|
CALL_SUBTEST(check_all_in_range<int>(-11-g_repeat,-11));
|
||||||
|
CALL_SUBTEST(check_all_in_range<int>(-673456,-673456+g_repeat));
|
||||||
|
CALL_SUBTEST(check_all_in_range<int>(673456,673456+g_repeat));
|
||||||
|
|
||||||
|
CALL_SUBTEST(check_all_in_range<long>(11,11));
|
||||||
|
CALL_SUBTEST(check_all_in_range<long>(11,11+g_repeat));
|
||||||
|
CALL_SUBTEST(check_all_in_range<long>(-5,5));
|
||||||
|
CALL_SUBTEST(check_all_in_range<long>(-11-g_repeat,-11));
|
||||||
|
CALL_SUBTEST(check_all_in_range<long>(-long_ref,-long_ref+g_repeat));
|
||||||
|
CALL_SUBTEST(check_all_in_range<long>( long_ref, long_ref+g_repeat));
|
||||||
|
|
||||||
|
CALL_SUBTEST(check_histogram<int>(-5,5,11));
|
||||||
|
int bins = 100;
|
||||||
|
CALL_SUBTEST(check_histogram<int>(-3333,-3333+bins*(3333/bins)-1,bins));
|
||||||
|
bins = 1000;
|
||||||
|
CALL_SUBTEST(check_histogram<int>(-RAND_MAX+10,-RAND_MAX+10+bins*(RAND_MAX/bins)-1,bins));
|
||||||
|
CALL_SUBTEST(check_histogram<int>(-RAND_MAX+10,-int64(RAND_MAX)+10+bins*(2*int64(RAND_MAX)/bins)-1,bins));
|
||||||
|
}
|
||||||
13
test/ref.cpp
13
test/ref.cpp
@@ -34,6 +34,18 @@ inline void on_temporary_creation(int) {
|
|||||||
|
|
||||||
// test Ref.h
|
// test Ref.h
|
||||||
|
|
||||||
|
// Deal with i387 extended precision
|
||||||
|
#if EIGEN_ARCH_i386 && !(EIGEN_ARCH_x86_64)
|
||||||
|
|
||||||
|
#if EIGEN_COMP_GNUC_STRICT && EIGEN_GNUC_AT_LEAST(4,4)
|
||||||
|
#pragma GCC optimize ("-ffloat-store")
|
||||||
|
#else
|
||||||
|
#undef VERIFY_IS_EQUAL
|
||||||
|
#define VERIFY_IS_EQUAL(X,Y) VERIFY_IS_APPROX(X,Y)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
template<typename MatrixType> void ref_matrix(const MatrixType& m)
|
template<typename MatrixType> void ref_matrix(const MatrixType& m)
|
||||||
{
|
{
|
||||||
typedef typename MatrixType::Index Index;
|
typedef typename MatrixType::Index Index;
|
||||||
@@ -71,7 +83,6 @@ template<typename MatrixType> void ref_matrix(const MatrixType& m)
|
|||||||
rm2 = m2.block(i,j,brows,bcols);
|
rm2 = m2.block(i,j,brows,bcols);
|
||||||
VERIFY_IS_EQUAL(m1, m2);
|
VERIFY_IS_EQUAL(m1, m2);
|
||||||
|
|
||||||
|
|
||||||
ConstRefDynMat rm3 = m1.block(i,j,brows,bcols);
|
ConstRefDynMat rm3 = m1.block(i,j,brows,bcols);
|
||||||
m1.block(i,j,brows,bcols) *= 2;
|
m1.block(i,j,brows,bcols) *= 2;
|
||||||
m2.block(i,j,brows,bcols) *= 2;
|
m2.block(i,j,brows,bcols) *= 2;
|
||||||
|
|||||||
@@ -299,6 +299,14 @@ template<typename SparseMatrixType> void sparse_basic(const SparseMatrixType& re
|
|||||||
VERIFY_IS_APPROX(m1.innerVector(0).dot(refM2.row(0)), refM1.row(0).dot(refM2.row(0)));
|
VERIFY_IS_APPROX(m1.innerVector(0).dot(refM2.row(0)), refM1.row(0).dot(refM2.row(0)));
|
||||||
else
|
else
|
||||||
VERIFY_IS_APPROX(m1.innerVector(0).dot(refM2.row(0)), refM1.col(0).dot(refM2.row(0)));
|
VERIFY_IS_APPROX(m1.innerVector(0).dot(refM2.row(0)), refM1.col(0).dot(refM2.row(0)));
|
||||||
|
|
||||||
|
DenseVector rv = DenseVector::Random(m1.cols());
|
||||||
|
DenseVector cv = DenseVector::Random(m1.rows());
|
||||||
|
Index r = internal::random<Index>(0,m1.rows()-2);
|
||||||
|
Index c = internal::random<Index>(0,m1.cols()-1);
|
||||||
|
VERIFY_IS_APPROX(( m1.template block<1,Dynamic>(r,0,1,m1.cols()).dot(rv)) , refM1.row(r).dot(rv));
|
||||||
|
VERIFY_IS_APPROX(m1.row(r).dot(rv), refM1.row(r).dot(rv));
|
||||||
|
VERIFY_IS_APPROX(m1.col(c).dot(cv), refM1.col(c).dot(cv));
|
||||||
|
|
||||||
VERIFY_IS_APPROX(m1.conjugate(), refM1.conjugate());
|
VERIFY_IS_APPROX(m1.conjugate(), refM1.conjugate());
|
||||||
VERIFY_IS_APPROX(m1.real(), refM1.real());
|
VERIFY_IS_APPROX(m1.real(), refM1.real());
|
||||||
|
|||||||
158
test/stddeque_overload.cpp
Normal file
158
test/stddeque_overload.cpp
Normal file
@@ -0,0 +1,158 @@
|
|||||||
|
// This file is part of Eigen, a lightweight C++ template library
|
||||||
|
// for linear algebra.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||||
|
// Copyright (C) 2010 Hauke Heibel <hauke.heibel@gmail.com>
|
||||||
|
//
|
||||||
|
// 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/.
|
||||||
|
|
||||||
|
#include "main.h"
|
||||||
|
|
||||||
|
#include <Eigen/StdDeque>
|
||||||
|
#include <Eigen/Geometry>
|
||||||
|
|
||||||
|
EIGEN_DEFINE_STL_DEQUE_SPECIALIZATION(Vector4f)
|
||||||
|
|
||||||
|
EIGEN_DEFINE_STL_DEQUE_SPECIALIZATION(Matrix2f)
|
||||||
|
EIGEN_DEFINE_STL_DEQUE_SPECIALIZATION(Matrix4f)
|
||||||
|
EIGEN_DEFINE_STL_DEQUE_SPECIALIZATION(Matrix4d)
|
||||||
|
|
||||||
|
EIGEN_DEFINE_STL_DEQUE_SPECIALIZATION(Affine3f)
|
||||||
|
EIGEN_DEFINE_STL_DEQUE_SPECIALIZATION(Affine3d)
|
||||||
|
|
||||||
|
EIGEN_DEFINE_STL_DEQUE_SPECIALIZATION(Quaternionf)
|
||||||
|
EIGEN_DEFINE_STL_DEQUE_SPECIALIZATION(Quaterniond)
|
||||||
|
|
||||||
|
template<typename MatrixType>
|
||||||
|
void check_stddeque_matrix(const MatrixType& m)
|
||||||
|
{
|
||||||
|
typename MatrixType::Index rows = m.rows();
|
||||||
|
typename MatrixType::Index cols = m.cols();
|
||||||
|
MatrixType x = MatrixType::Random(rows,cols), y = MatrixType::Random(rows,cols);
|
||||||
|
std::deque<MatrixType> v(10, MatrixType(rows,cols)), w(20, y);
|
||||||
|
v[5] = x;
|
||||||
|
w[6] = v[5];
|
||||||
|
VERIFY_IS_APPROX(w[6], v[5]);
|
||||||
|
v = w;
|
||||||
|
for(int i = 0; i < 20; i++)
|
||||||
|
{
|
||||||
|
VERIFY_IS_APPROX(w[i], v[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
v.resize(21);
|
||||||
|
v[20] = x;
|
||||||
|
VERIFY_IS_APPROX(v[20], x);
|
||||||
|
v.resize(22,y);
|
||||||
|
VERIFY_IS_APPROX(v[21], y);
|
||||||
|
v.push_back(x);
|
||||||
|
VERIFY_IS_APPROX(v[22], x);
|
||||||
|
|
||||||
|
// do a lot of push_back such that the deque gets internally resized
|
||||||
|
// (with memory reallocation)
|
||||||
|
MatrixType* ref = &w[0];
|
||||||
|
for(int i=0; i<30 || ((ref==&w[0]) && i<300); ++i)
|
||||||
|
v.push_back(w[i%w.size()]);
|
||||||
|
for(unsigned int i=23; i<v.size(); ++i)
|
||||||
|
{
|
||||||
|
VERIFY(v[i]==w[(i-23)%w.size()]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename TransformType>
|
||||||
|
void check_stddeque_transform(const TransformType&)
|
||||||
|
{
|
||||||
|
typedef typename TransformType::MatrixType MatrixType;
|
||||||
|
TransformType x(MatrixType::Random()), y(MatrixType::Random());
|
||||||
|
std::deque<TransformType> v(10), w(20, y);
|
||||||
|
v[5] = x;
|
||||||
|
w[6] = v[5];
|
||||||
|
VERIFY_IS_APPROX(w[6], v[5]);
|
||||||
|
v = w;
|
||||||
|
for(int i = 0; i < 20; i++)
|
||||||
|
{
|
||||||
|
VERIFY_IS_APPROX(w[i], v[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
v.resize(21);
|
||||||
|
v[20] = x;
|
||||||
|
VERIFY_IS_APPROX(v[20], x);
|
||||||
|
v.resize(22,y);
|
||||||
|
VERIFY_IS_APPROX(v[21], y);
|
||||||
|
v.push_back(x);
|
||||||
|
VERIFY_IS_APPROX(v[22], x);
|
||||||
|
|
||||||
|
// do a lot of push_back such that the deque gets internally resized
|
||||||
|
// (with memory reallocation)
|
||||||
|
TransformType* ref = &w[0];
|
||||||
|
for(int i=0; i<30 || ((ref==&w[0]) && i<300); ++i)
|
||||||
|
v.push_back(w[i%w.size()]);
|
||||||
|
for(unsigned int i=23; i<v.size(); ++i)
|
||||||
|
{
|
||||||
|
VERIFY(v[i].matrix()==w[(i-23)%w.size()].matrix());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename QuaternionType>
|
||||||
|
void check_stddeque_quaternion(const QuaternionType&)
|
||||||
|
{
|
||||||
|
typedef typename QuaternionType::Coefficients Coefficients;
|
||||||
|
QuaternionType x(Coefficients::Random()), y(Coefficients::Random());
|
||||||
|
std::deque<QuaternionType> v(10), w(20, y);
|
||||||
|
v[5] = x;
|
||||||
|
w[6] = v[5];
|
||||||
|
VERIFY_IS_APPROX(w[6], v[5]);
|
||||||
|
v = w;
|
||||||
|
for(int i = 0; i < 20; i++)
|
||||||
|
{
|
||||||
|
VERIFY_IS_APPROX(w[i], v[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
v.resize(21);
|
||||||
|
v[20] = x;
|
||||||
|
VERIFY_IS_APPROX(v[20], x);
|
||||||
|
v.resize(22,y);
|
||||||
|
VERIFY_IS_APPROX(v[21], y);
|
||||||
|
v.push_back(x);
|
||||||
|
VERIFY_IS_APPROX(v[22], x);
|
||||||
|
|
||||||
|
// do a lot of push_back such that the deque gets internally resized
|
||||||
|
// (with memory reallocation)
|
||||||
|
QuaternionType* ref = &w[0];
|
||||||
|
for(int i=0; i<30 || ((ref==&w[0]) && i<300); ++i)
|
||||||
|
v.push_back(w[i%w.size()]);
|
||||||
|
for(unsigned int i=23; i<v.size(); ++i)
|
||||||
|
{
|
||||||
|
VERIFY(v[i].coeffs()==w[(i-23)%w.size()].coeffs());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_stddeque_overload()
|
||||||
|
{
|
||||||
|
// some non vectorizable fixed sizes
|
||||||
|
CALL_SUBTEST_1(check_stddeque_matrix(Vector2f()));
|
||||||
|
CALL_SUBTEST_1(check_stddeque_matrix(Matrix3f()));
|
||||||
|
CALL_SUBTEST_2(check_stddeque_matrix(Matrix3d()));
|
||||||
|
|
||||||
|
// some vectorizable fixed sizes
|
||||||
|
CALL_SUBTEST_1(check_stddeque_matrix(Matrix2f()));
|
||||||
|
CALL_SUBTEST_1(check_stddeque_matrix(Vector4f()));
|
||||||
|
CALL_SUBTEST_1(check_stddeque_matrix(Matrix4f()));
|
||||||
|
CALL_SUBTEST_2(check_stddeque_matrix(Matrix4d()));
|
||||||
|
|
||||||
|
// some dynamic sizes
|
||||||
|
CALL_SUBTEST_3(check_stddeque_matrix(MatrixXd(1,1)));
|
||||||
|
CALL_SUBTEST_3(check_stddeque_matrix(VectorXd(20)));
|
||||||
|
CALL_SUBTEST_3(check_stddeque_matrix(RowVectorXf(20)));
|
||||||
|
CALL_SUBTEST_3(check_stddeque_matrix(MatrixXcf(10,10)));
|
||||||
|
|
||||||
|
// some Transform
|
||||||
|
CALL_SUBTEST_4(check_stddeque_transform(Affine2f())); // does not need the specialization (2+1)^2 = 9
|
||||||
|
CALL_SUBTEST_4(check_stddeque_transform(Affine3f()));
|
||||||
|
CALL_SUBTEST_4(check_stddeque_transform(Affine3d()));
|
||||||
|
|
||||||
|
// some Quaternion
|
||||||
|
CALL_SUBTEST_5(check_stddeque_quaternion(Quaternionf()));
|
||||||
|
CALL_SUBTEST_5(check_stddeque_quaternion(Quaterniond()));
|
||||||
|
}
|
||||||
192
test/stdlist_overload.cpp
Normal file
192
test/stdlist_overload.cpp
Normal file
@@ -0,0 +1,192 @@
|
|||||||
|
// This file is part of Eigen, a lightweight C++ template library
|
||||||
|
// for linear algebra.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||||
|
// Copyright (C) 2010 Hauke Heibel <hauke.heibel@gmail.com>
|
||||||
|
//
|
||||||
|
// 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/.
|
||||||
|
|
||||||
|
#include "main.h"
|
||||||
|
|
||||||
|
#include <Eigen/StdList>
|
||||||
|
#include <Eigen/Geometry>
|
||||||
|
|
||||||
|
EIGEN_DEFINE_STL_LIST_SPECIALIZATION(Vector4f)
|
||||||
|
|
||||||
|
EIGEN_DEFINE_STL_LIST_SPECIALIZATION(Matrix2f)
|
||||||
|
EIGEN_DEFINE_STL_LIST_SPECIALIZATION(Matrix4f)
|
||||||
|
EIGEN_DEFINE_STL_LIST_SPECIALIZATION(Matrix4d)
|
||||||
|
|
||||||
|
EIGEN_DEFINE_STL_LIST_SPECIALIZATION(Affine3f)
|
||||||
|
EIGEN_DEFINE_STL_LIST_SPECIALIZATION(Affine3d)
|
||||||
|
|
||||||
|
EIGEN_DEFINE_STL_LIST_SPECIALIZATION(Quaternionf)
|
||||||
|
EIGEN_DEFINE_STL_LIST_SPECIALIZATION(Quaterniond)
|
||||||
|
|
||||||
|
template <class Container, class Position>
|
||||||
|
typename Container::iterator get(Container & c, Position position)
|
||||||
|
{
|
||||||
|
typename Container::iterator it = c.begin();
|
||||||
|
std::advance(it, position);
|
||||||
|
return it;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Container, class Position, class Value>
|
||||||
|
void set(Container & c, Position position, const Value & value)
|
||||||
|
{
|
||||||
|
typename Container::iterator it = c.begin();
|
||||||
|
std::advance(it, position);
|
||||||
|
*it = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename MatrixType>
|
||||||
|
void check_stdlist_matrix(const MatrixType& m)
|
||||||
|
{
|
||||||
|
typename MatrixType::Index rows = m.rows();
|
||||||
|
typename MatrixType::Index cols = m.cols();
|
||||||
|
MatrixType x = MatrixType::Random(rows,cols), y = MatrixType::Random(rows,cols);
|
||||||
|
std::list<MatrixType> v(10, MatrixType(rows,cols)), w(20, y);
|
||||||
|
typename std::list<MatrixType>::iterator itv = get(v, 5);
|
||||||
|
typename std::list<MatrixType>::iterator itw = get(w, 6);
|
||||||
|
*itv = x;
|
||||||
|
*itw = *itv;
|
||||||
|
VERIFY_IS_APPROX(*itw, *itv);
|
||||||
|
v = w;
|
||||||
|
itv = v.begin();
|
||||||
|
itw = w.begin();
|
||||||
|
for(int i = 0; i < 20; i++)
|
||||||
|
{
|
||||||
|
VERIFY_IS_APPROX(*itw, *itv);
|
||||||
|
++itv;
|
||||||
|
++itw;
|
||||||
|
}
|
||||||
|
|
||||||
|
v.resize(21);
|
||||||
|
set(v, 20, x);
|
||||||
|
VERIFY_IS_APPROX(*get(v, 20), x);
|
||||||
|
v.resize(22,y);
|
||||||
|
VERIFY_IS_APPROX(*get(v, 21), y);
|
||||||
|
v.push_back(x);
|
||||||
|
VERIFY_IS_APPROX(*get(v, 22), x);
|
||||||
|
|
||||||
|
// do a lot of push_back such that the list gets internally resized
|
||||||
|
// (with memory reallocation)
|
||||||
|
MatrixType* ref = &(*get(w, 0));
|
||||||
|
for(int i=0; i<30 || ((ref==&(*get(w, 0))) && i<300); ++i)
|
||||||
|
v.push_back(*get(w, i%w.size()));
|
||||||
|
for(unsigned int i=23; i<v.size(); ++i)
|
||||||
|
{
|
||||||
|
VERIFY((*get(v, i))==(*get(w, (i-23)%w.size())));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename TransformType>
|
||||||
|
void check_stdlist_transform(const TransformType&)
|
||||||
|
{
|
||||||
|
typedef typename TransformType::MatrixType MatrixType;
|
||||||
|
TransformType x(MatrixType::Random()), y(MatrixType::Random());
|
||||||
|
std::list<TransformType> v(10), w(20, y);
|
||||||
|
typename std::list<TransformType>::iterator itv = get(v, 5);
|
||||||
|
typename std::list<TransformType>::iterator itw = get(w, 6);
|
||||||
|
*itv = x;
|
||||||
|
*itw = *itv;
|
||||||
|
VERIFY_IS_APPROX(*itw, *itv);
|
||||||
|
v = w;
|
||||||
|
itv = v.begin();
|
||||||
|
itw = w.begin();
|
||||||
|
for(int i = 0; i < 20; i++)
|
||||||
|
{
|
||||||
|
VERIFY_IS_APPROX(*itw, *itv);
|
||||||
|
++itv;
|
||||||
|
++itw;
|
||||||
|
}
|
||||||
|
|
||||||
|
v.resize(21);
|
||||||
|
set(v, 20, x);
|
||||||
|
VERIFY_IS_APPROX(*get(v, 20), x);
|
||||||
|
v.resize(22,y);
|
||||||
|
VERIFY_IS_APPROX(*get(v, 21), y);
|
||||||
|
v.push_back(x);
|
||||||
|
VERIFY_IS_APPROX(*get(v, 22), x);
|
||||||
|
|
||||||
|
// do a lot of push_back such that the list gets internally resized
|
||||||
|
// (with memory reallocation)
|
||||||
|
TransformType* ref = &(*get(w, 0));
|
||||||
|
for(int i=0; i<30 || ((ref==&(*get(w, 0))) && i<300); ++i)
|
||||||
|
v.push_back(*get(w, i%w.size()));
|
||||||
|
for(unsigned int i=23; i<v.size(); ++i)
|
||||||
|
{
|
||||||
|
VERIFY(get(v, i)->matrix()==get(w, (i-23)%w.size())->matrix());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename QuaternionType>
|
||||||
|
void check_stdlist_quaternion(const QuaternionType&)
|
||||||
|
{
|
||||||
|
typedef typename QuaternionType::Coefficients Coefficients;
|
||||||
|
QuaternionType x(Coefficients::Random()), y(Coefficients::Random());
|
||||||
|
std::list<QuaternionType> v(10), w(20, y);
|
||||||
|
typename std::list<QuaternionType>::iterator itv = get(v, 5);
|
||||||
|
typename std::list<QuaternionType>::iterator itw = get(w, 6);
|
||||||
|
*itv = x;
|
||||||
|
*itw = *itv;
|
||||||
|
VERIFY_IS_APPROX(*itw, *itv);
|
||||||
|
v = w;
|
||||||
|
itv = v.begin();
|
||||||
|
itw = w.begin();
|
||||||
|
for(int i = 0; i < 20; i++)
|
||||||
|
{
|
||||||
|
VERIFY_IS_APPROX(*itw, *itv);
|
||||||
|
++itv;
|
||||||
|
++itw;
|
||||||
|
}
|
||||||
|
|
||||||
|
v.resize(21);
|
||||||
|
set(v, 20, x);
|
||||||
|
VERIFY_IS_APPROX(*get(v, 20), x);
|
||||||
|
v.resize(22,y);
|
||||||
|
VERIFY_IS_APPROX(*get(v, 21), y);
|
||||||
|
v.push_back(x);
|
||||||
|
VERIFY_IS_APPROX(*get(v, 22), x);
|
||||||
|
|
||||||
|
// do a lot of push_back such that the list gets internally resized
|
||||||
|
// (with memory reallocation)
|
||||||
|
QuaternionType* ref = &(*get(w, 0));
|
||||||
|
for(int i=0; i<30 || ((ref==&(*get(w, 0))) && i<300); ++i)
|
||||||
|
v.push_back(*get(w, i%w.size()));
|
||||||
|
for(unsigned int i=23; i<v.size(); ++i)
|
||||||
|
{
|
||||||
|
VERIFY(get(v, i)->coeffs()==get(w, (i-23)%w.size())->coeffs());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_stdlist_overload()
|
||||||
|
{
|
||||||
|
// some non vectorizable fixed sizes
|
||||||
|
CALL_SUBTEST_1(check_stdlist_matrix(Vector2f()));
|
||||||
|
CALL_SUBTEST_1(check_stdlist_matrix(Matrix3f()));
|
||||||
|
CALL_SUBTEST_2(check_stdlist_matrix(Matrix3d()));
|
||||||
|
|
||||||
|
// some vectorizable fixed sizes
|
||||||
|
CALL_SUBTEST_1(check_stdlist_matrix(Matrix2f()));
|
||||||
|
CALL_SUBTEST_1(check_stdlist_matrix(Vector4f()));
|
||||||
|
CALL_SUBTEST_1(check_stdlist_matrix(Matrix4f()));
|
||||||
|
CALL_SUBTEST_2(check_stdlist_matrix(Matrix4d()));
|
||||||
|
|
||||||
|
// some dynamic sizes
|
||||||
|
CALL_SUBTEST_3(check_stdlist_matrix(MatrixXd(1,1)));
|
||||||
|
CALL_SUBTEST_3(check_stdlist_matrix(VectorXd(20)));
|
||||||
|
CALL_SUBTEST_3(check_stdlist_matrix(RowVectorXf(20)));
|
||||||
|
CALL_SUBTEST_3(check_stdlist_matrix(MatrixXcf(10,10)));
|
||||||
|
|
||||||
|
// some Transform
|
||||||
|
CALL_SUBTEST_4(check_stdlist_transform(Affine2f())); // does not need the specialization (2+1)^2 = 9
|
||||||
|
CALL_SUBTEST_4(check_stdlist_transform(Affine3f()));
|
||||||
|
CALL_SUBTEST_4(check_stdlist_transform(Affine3d()));
|
||||||
|
|
||||||
|
// some Quaternion
|
||||||
|
CALL_SUBTEST_5(check_stdlist_quaternion(Quaternionf()));
|
||||||
|
CALL_SUBTEST_5(check_stdlist_quaternion(Quaterniond()));
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user