mirror of
https://gitlab.com/libeigen/eigen.git
synced 2026-04-10 11:34:33 +08:00
Compare commits
92 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8f1ce52e76 | ||
|
|
268df314f1 | ||
|
|
522022ebfc | ||
|
|
d048d7e712 | ||
|
|
cd3c8a9404 | ||
|
|
ec8f37ac75 | ||
|
|
fc7f39980c | ||
|
|
70af59c455 | ||
|
|
f4dd399499 | ||
|
|
153557527e | ||
|
|
6aad7f80ff | ||
|
|
e3f6c3115a | ||
|
|
a2c838ff8f | ||
|
|
1e2f56c35a | ||
|
|
808c4e9581 | ||
|
|
65331c3884 | ||
|
|
e158cdd61d | ||
|
|
c64ca6870e | ||
|
|
6a90f6c5f0 | ||
|
|
22dd13fdb9 | ||
|
|
5455d6fbe8 | ||
|
|
de693cf34a | ||
|
|
21c4e0802d | ||
|
|
241b9d34a7 | ||
|
|
9e15a6da2e | ||
|
|
3d365a75cd | ||
|
|
38bc82a6f7 | ||
|
|
6173eb67ff | ||
|
|
9f89431cea | ||
|
|
79e392472a | ||
|
|
e1c96f3fe0 | ||
|
|
46f0fe3b4b | ||
|
|
e17e4f3654 | ||
|
|
2b006ae430 | ||
|
|
df6923fd2b | ||
|
|
21d081c6da | ||
|
|
81fd1e9060 | ||
|
|
be8ae0d45f | ||
|
|
fc8b54c142 | ||
|
|
76d578fb99 | ||
|
|
9af431e78e | ||
|
|
a4a3e511d0 | ||
|
|
ffee27bf72 | ||
|
|
5e24fbbead | ||
|
|
09364c8d05 | ||
|
|
3b8938ee1a | ||
|
|
e43d630d80 | ||
|
|
eb1df142a3 | ||
|
|
746d8b7ce9 | ||
|
|
656c8faeb8 | ||
|
|
8084dbc86a | ||
|
|
79ebba4f52 | ||
|
|
b362b45cff | ||
|
|
c67b8b7ce0 | ||
|
|
bcd621fcd5 | ||
|
|
de88fb67d6 | ||
|
|
4936720648 | ||
|
|
922e11e184 | ||
|
|
8c2ace33c9 | ||
|
|
b66516e746 | ||
|
|
ecf64d2dc3 | ||
|
|
6af2c2c67a | ||
|
|
d0ac4fa479 | ||
|
|
09f77b356d | ||
|
|
8097487b9d | ||
|
|
aaf1826384 | ||
|
|
3590911de2 | ||
|
|
21e97f07d8 | ||
|
|
82df5b4a24 | ||
|
|
35e88996c7 | ||
|
|
5dfb7204bd | ||
|
|
e0cbf79e5a | ||
|
|
3af177058e | ||
|
|
258ea3ea02 | ||
|
|
6580278e2c | ||
|
|
dcefb66283 | ||
|
|
9d64571963 | ||
|
|
65724def70 | ||
|
|
7a44945a16 | ||
|
|
ed33d688e1 | ||
|
|
d7bf8b8581 | ||
|
|
a9c60954ed | ||
|
|
78ea8b2dbd | ||
|
|
d4e25e5acf | ||
|
|
36b324fe7b | ||
|
|
d37de5db30 | ||
|
|
456b6abed5 | ||
|
|
4a50ee8c21 | ||
|
|
c9f7a19053 | ||
|
|
47973c4963 | ||
|
|
65487176e3 | ||
|
|
d28fae5bdf |
24
.hgignore
Normal file
24
.hgignore
Normal file
@@ -0,0 +1,24 @@
|
||||
syntax: glob
|
||||
qrc_*cxx
|
||||
*.orig
|
||||
*.pyc
|
||||
*.diff
|
||||
diff
|
||||
*.save
|
||||
*.old
|
||||
*.gmo
|
||||
*.qm
|
||||
core
|
||||
core.*
|
||||
*.bak
|
||||
*~
|
||||
build
|
||||
*.moc.*
|
||||
*.moc
|
||||
ui_*
|
||||
CMakeCache.txt
|
||||
tags
|
||||
.*.swp
|
||||
activity.png
|
||||
*.out
|
||||
*.php*
|
||||
@@ -1,22 +1,15 @@
|
||||
project(Eigen)
|
||||
set(EIGEN_VERSION_NUMBER "2.0.4")
|
||||
|
||||
#if the svnversion program is absent, this will leave the SVN_REVISION string empty,
|
||||
#but won't stop CMake.
|
||||
execute_process(COMMAND svnversion -n ${CMAKE_SOURCE_DIR}
|
||||
OUTPUT_VARIABLE EIGEN_SVNVERSION_OUTPUT)
|
||||
|
||||
#we only want EIGEN_SVN_REVISION if it is an actual revision number, not a string like "exported"
|
||||
string(REGEX MATCH "^[0-9]+.*" EIGEN_SVN_REVISION "${EIGEN_SVNVERSION_OUTPUT}")
|
||||
|
||||
if(EIGEN_SVN_REVISION)
|
||||
set(EIGEN_VERSION "${EIGEN_VERSION_NUMBER} (SVN revision ${EIGEN_SVN_REVISION})")
|
||||
else(EIGEN_SVN_REVISION)
|
||||
set(EIGEN_VERSION "${EIGEN_VERSION_NUMBER}")
|
||||
endif(EIGEN_SVN_REVISION)
|
||||
|
||||
cmake_minimum_required(VERSION 2.6.2)
|
||||
|
||||
set(INCLUDE_INSTALL_DIR
|
||||
"${CMAKE_INSTALL_PREFIX}/include/eigen2"
|
||||
CACHE PATH
|
||||
"The directory where we install the header files"
|
||||
FORCE)
|
||||
|
||||
set(EIGEN_VERSION_NUMBER "2.0.10")
|
||||
set(EIGEN_VERSION "${EIGEN_VERSION_NUMBER}")
|
||||
|
||||
set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
|
||||
|
||||
option(EIGEN_BUILD_TESTS "Build tests" OFF)
|
||||
@@ -25,6 +18,9 @@ if(NOT WIN32)
|
||||
option(EIGEN_BUILD_LIB "Build the binary shared library" OFF)
|
||||
endif(NOT WIN32)
|
||||
option(EIGEN_BUILD_BTL "Build benchmark suite" OFF)
|
||||
if(NOT WIN32)
|
||||
option(EIGEN_BUILD_PKGCONFIG "Build pkg-config .pc file for Eigen" ON)
|
||||
endif(NOT WIN32)
|
||||
|
||||
if(EIGEN_BUILD_LIB)
|
||||
option(EIGEN_TEST_LIB "Build the unit tests using the library (disable -pedantic)" OFF)
|
||||
@@ -34,7 +30,12 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
|
||||
if(CMAKE_COMPILER_IS_GNUCXX)
|
||||
if(CMAKE_SYSTEM_NAME MATCHES Linux)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wnon-virtual-dtor -Wno-long-long -ansi -Wundef -Wcast-align -Wchar-subscripts -Wall -W -Wpointer-arith -Wwrite-strings -Wformat-security -Wextra -fno-exceptions -fno-check-new -fno-common -fstrict-aliasing")
|
||||
include(CheckCXXCompilerFlag)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wnon-virtual-dtor -Wno-long-long -ansi -Wundef -Wcast-align -Wchar-subscripts -Wall -W -Wpointer-arith -Wwrite-strings -Wformat-security -fno-exceptions -fno-check-new -fno-common -fstrict-aliasing")
|
||||
check_cxx_compiler_flag("-Wextra" has_wextra)
|
||||
if(has_wextra)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wextra")
|
||||
endif()
|
||||
if(NOT EIGEN_TEST_LIB)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pedantic")
|
||||
endif(NOT EIGEN_TEST_LIB)
|
||||
@@ -84,6 +85,13 @@ endif(EIGEN_TEST_NO_EXPLICIT_VECTORIZATION)
|
||||
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
if(EIGEN_BUILD_PKGCONFIG)
|
||||
configure_file(eigen2.pc.in eigen2.pc) # uses INCLUDE_INSTALL_DIR
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/eigen2.pc
|
||||
DESTINATION share/pkgconfig
|
||||
)
|
||||
endif(EIGEN_BUILD_PKGCONFIG)
|
||||
|
||||
add_subdirectory(Eigen)
|
||||
add_subdirectory(unsupported)
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
set(Eigen_HEADERS Core LU Cholesky QR Geometry Sparse Array SVD LeastSquares QtAlignedMalloc StdVector)
|
||||
set(Eigen_HEADERS Core LU Cholesky QR Geometry
|
||||
Sparse Array SVD LeastSquares
|
||||
QtAlignedMalloc StdVector NewStdVector)
|
||||
|
||||
if(EIGEN_BUILD_LIB)
|
||||
set(Eigen_SRCS
|
||||
@@ -20,12 +22,6 @@ if(CMAKE_COMPILER_IS_GNUCXX)
|
||||
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -g1 -O2")
|
||||
endif(CMAKE_COMPILER_IS_GNUCXX)
|
||||
|
||||
set(INCLUDE_INSTALL_DIR
|
||||
"${CMAKE_INSTALL_PREFIX}/include/eigen2"
|
||||
CACHE PATH
|
||||
"The directory where we install the header files"
|
||||
FORCE)
|
||||
|
||||
install(FILES
|
||||
${Eigen_HEADERS}
|
||||
DESTINATION ${INCLUDE_INSTALL_DIR}/Eigen
|
||||
|
||||
@@ -38,8 +38,8 @@ namespace Eigen {
|
||||
} // namespace Eigen
|
||||
|
||||
#define EIGEN_CHOLESKY_MODULE_INSTANTIATE_TYPE(MATRIXTYPE,PREFIX) \
|
||||
PREFIX template class Cholesky<MATRIXTYPE>; \
|
||||
PREFIX template class CholeskyWithoutSquareRoot<MATRIXTYPE>
|
||||
PREFIX template class LLT<MATRIXTYPE>; \
|
||||
PREFIX template class LDLT<MATRIXTYPE>
|
||||
|
||||
#define EIGEN_CHOLESKY_MODULE_INSTANTIATE(PREFIX) \
|
||||
EIGEN_CHOLESKY_MODULE_INSTANTIATE_TYPE(Matrix2f,PREFIX); \
|
||||
|
||||
168
Eigen/NewStdVector
Normal file
168
Eigen/NewStdVector
Normal file
@@ -0,0 +1,168 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2009 Gael Guennebaud <g.gael@free.fr>
|
||||
// Copyright (C) 2009 Hauke Heibel <hauke.heibel@googlemail.com>
|
||||
//
|
||||
// Eigen is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 3 of the License, or (at your option) any later version.
|
||||
//
|
||||
// Alternatively, you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of
|
||||
// the License, or (at your option) any later version.
|
||||
//
|
||||
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License and a copy of the GNU General Public License along with
|
||||
// Eigen. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef EIGEN_STDVECTOR_MODULE_H
|
||||
#define EIGEN_STDVECTOR_MODULE_H
|
||||
|
||||
#include "Core"
|
||||
#include <vector>
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
// This one is needed to prevent reimplementing the whole std::vector.
|
||||
template <class T>
|
||||
class aligned_allocator_indirection : public aligned_allocator<T>
|
||||
{
|
||||
public:
|
||||
typedef size_t size_type;
|
||||
typedef ptrdiff_t difference_type;
|
||||
typedef T* pointer;
|
||||
typedef const T* const_pointer;
|
||||
typedef T& reference;
|
||||
typedef const T& const_reference;
|
||||
typedef T value_type;
|
||||
|
||||
template<class U>
|
||||
struct rebind
|
||||
{
|
||||
typedef aligned_allocator_indirection<U> other;
|
||||
};
|
||||
|
||||
aligned_allocator_indirection() throw() {}
|
||||
aligned_allocator_indirection(const aligned_allocator_indirection& ) throw() : aligned_allocator<T>() {}
|
||||
aligned_allocator_indirection(const aligned_allocator<T>& ) throw() {}
|
||||
template<class U>
|
||||
aligned_allocator_indirection(const aligned_allocator_indirection<U>& ) throw() {}
|
||||
template<class U>
|
||||
aligned_allocator_indirection(const aligned_allocator<U>& ) throw() {}
|
||||
~aligned_allocator_indirection() throw() {}
|
||||
};
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
// sometimes, MSVC detects, at compile time, that the argument x
|
||||
// in std::vector::resize(size_t s,T x) won't be aligned and generate an error
|
||||
// even if this function is never called. Whence this little wrapper.
|
||||
#define EIGEN_WORKAROUND_MSVC_STD_VECTOR(T) Eigen::ei_workaround_msvc_std_vector<T>
|
||||
template<typename T> struct ei_workaround_msvc_std_vector : public T
|
||||
{
|
||||
inline ei_workaround_msvc_std_vector() : T() {}
|
||||
inline ei_workaround_msvc_std_vector(const T& other) : T(other) {}
|
||||
inline operator T& () { return *static_cast<T*>(this); }
|
||||
inline operator const T& () const { return *static_cast<const T*>(this); }
|
||||
template<typename OtherT>
|
||||
inline T& operator=(const OtherT& other)
|
||||
{ T::operator=(other); return *this; }
|
||||
inline ei_workaround_msvc_std_vector& operator=(const ei_workaround_msvc_std_vector& other)
|
||||
{ T::operator=(other); return *this; }
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
#define EIGEN_WORKAROUND_MSVC_STD_VECTOR(T) T
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
namespace std {
|
||||
|
||||
#define EIGEN_STD_VECTOR_SPECIALIZATION_BODY \
|
||||
public: \
|
||||
typedef T value_type; \
|
||||
typedef typename vector_base::allocator_type allocator_type; \
|
||||
typedef typename vector_base::size_type size_type; \
|
||||
typedef typename vector_base::iterator iterator; \
|
||||
typedef typename vector_base::const_iterator const_iterator; \
|
||||
explicit vector(const allocator_type& a = allocator_type()) : vector_base(a) {} \
|
||||
template<typename InputIterator> \
|
||||
vector(InputIterator first, InputIterator last, const allocator_type& a = allocator_type()) \
|
||||
: vector_base(first, last, a) {} \
|
||||
vector(const vector& c) : vector_base(c) {} \
|
||||
explicit vector(size_type num, const value_type& val = value_type()) : vector_base(num, val) {} \
|
||||
vector(iterator start, iterator end) : vector_base(start, end) {} \
|
||||
vector& operator=(const vector& x) { \
|
||||
vector_base::operator=(x); \
|
||||
return *this; \
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
class vector<T,Eigen::aligned_allocator<T> >
|
||||
: public vector<EIGEN_WORKAROUND_MSVC_STD_VECTOR(T),
|
||||
Eigen::aligned_allocator_indirection<EIGEN_WORKAROUND_MSVC_STD_VECTOR(T)> >
|
||||
{
|
||||
typedef vector<EIGEN_WORKAROUND_MSVC_STD_VECTOR(T),
|
||||
Eigen::aligned_allocator_indirection<EIGEN_WORKAROUND_MSVC_STD_VECTOR(T)> > vector_base;
|
||||
EIGEN_STD_VECTOR_SPECIALIZATION_BODY
|
||||
|
||||
void resize(size_type new_size)
|
||||
{ resize(new_size, T()); }
|
||||
|
||||
#if defined(_VECTOR_)
|
||||
// workaround MSVC std::vector implementation
|
||||
void resize(size_type new_size, const value_type& x)
|
||||
{
|
||||
if (vector_base::size() < new_size)
|
||||
vector_base::_Insert_n(vector_base::end(), new_size - vector_base::size(), x);
|
||||
else if (new_size < vector_base::size())
|
||||
vector_base::erase(vector_base::begin() + new_size, vector_base::end());
|
||||
}
|
||||
void push_back(const value_type& x)
|
||||
{ vector_base::push_back(x); }
|
||||
using vector_base::insert;
|
||||
iterator insert(const_iterator position, const value_type& x)
|
||||
{ return vector_base::insert(position,x); }
|
||||
void insert(const_iterator position, size_type new_size, const value_type& x)
|
||||
{ vector_base::insert(position, new_size, x); }
|
||||
#elif defined(_GLIBCXX_VECTOR) && EIGEN_GNUC_AT_LEAST(4,2)
|
||||
// workaround GCC std::vector implementation
|
||||
void resize(size_type new_size, const value_type& x)
|
||||
{
|
||||
if (new_size < vector_base::size())
|
||||
vector_base::_M_erase_at_end(this->_M_impl._M_start + new_size);
|
||||
else
|
||||
vector_base::insert(vector_base::end(), new_size - vector_base::size(), x);
|
||||
}
|
||||
#elif defined(_GLIBCXX_VECTOR) && (!EIGEN_GNUC_AT_LEAST(4,1))
|
||||
// Note that before gcc-4.1 we already have: std::vector::resize(size_type,const T&),
|
||||
// no no need to workaround !
|
||||
using vector_base::resize;
|
||||
#else
|
||||
// either GCC 4.1 or non-GCC
|
||||
// default implementation which should always work.
|
||||
void resize(size_type new_size, const value_type& x)
|
||||
{
|
||||
if (new_size < vector_base::size())
|
||||
vector_base::erase(vector_base::begin() + new_size, vector_base::end());
|
||||
else if (new_size > vector_base::size())
|
||||
vector_base::insert(vector_base::end(), new_size - vector_base::size(), x);
|
||||
}
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // EIGEN_STDVECTOR_MODULE_H
|
||||
@@ -1,10 +1,23 @@
|
||||
|
||||
#ifndef EIGEN_QTMALLOC_MODULE_H
|
||||
#define EIGEN_QTMALLOC_MODULE_H
|
||||
|
||||
#if (!EIGEN_MALLOC_ALREADY_ALIGNED)
|
||||
|
||||
#ifdef QVECTOR_H
|
||||
#error You must include <Eigen/QtAlignedMalloc> before <QtCore/QVector>.
|
||||
#endif
|
||||
|
||||
#ifdef Q_DECL_IMPORT
|
||||
#define Q_DECL_IMPORT_ORIG Q_DECL_IMPORT
|
||||
#undef Q_DECL_IMPORT
|
||||
#define Q_DECL_IMPORT
|
||||
#else
|
||||
#define Q_DECL_IMPORT
|
||||
#endif
|
||||
|
||||
#include "Core"
|
||||
|
||||
#if (!EIGEN_MALLOC_ALREADY_ALIGNED)
|
||||
#include <QtCore/QVector>
|
||||
|
||||
inline void *qMalloc(size_t size)
|
||||
{
|
||||
@@ -26,4 +39,11 @@ inline void *qRealloc(void *ptr, size_t size)
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef Q_DECL_IMPORT_ORIG
|
||||
#define Q_DECL_IMPORT Q_DECL_IMPORT_ORIG
|
||||
#undef Q_DECL_IMPORT_ORIG
|
||||
#else
|
||||
#undef Q_DECL_IMPORT
|
||||
#endif
|
||||
|
||||
#endif // EIGEN_QTMALLOC_MODULE_H
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
#ifdef EIGEN_USE_NEW_STDVECTOR
|
||||
#include "NewStdVector"
|
||||
#else
|
||||
|
||||
#ifndef EIGEN_STDVECTOR_MODULE_H
|
||||
#define EIGEN_STDVECTOR_MODULE_H
|
||||
|
||||
#if defined(_GLIBCXX_VECTOR) || defined(_VECTOR_)
|
||||
#error you must include Eigen/StdVector before std::vector
|
||||
#error you must include <Eigen/StdVector> before <vector>. Also note that <Eigen/Sparse> includes <vector>, so it must be included after <Eigen/StdVector> too.
|
||||
#endif
|
||||
|
||||
#ifndef EIGEN_GNUC_AT_LEAST
|
||||
@@ -112,10 +116,8 @@ class vector<T,DummyAlloc,true>
|
||||
else if (__new_size < vector_base::size())
|
||||
vector_base::erase(vector_base::begin() + __new_size, vector_base::end());
|
||||
}
|
||||
#elif defined(_GLIBCXX_VECTOR) && EIGEN_GNUC_AT_LEAST(4,1)
|
||||
#elif defined(_GLIBCXX_VECTOR) && EIGEN_GNUC_AT_LEAST(4,2)
|
||||
// workaround GCC std::vector implementation
|
||||
// Note that before gcc-4.1 we already have: std::vector::resize(size_type,const T&),
|
||||
// no no need to workaround !
|
||||
void resize(size_type __new_size, const value_type& __x)
|
||||
{
|
||||
if (__new_size < vector_base::size())
|
||||
@@ -123,7 +125,17 @@ class vector<T,DummyAlloc,true>
|
||||
else
|
||||
vector_base::insert(vector_base::end(), __new_size - vector_base::size(), __x);
|
||||
}
|
||||
#elif defined(_GLIBCXX_VECTOR) && EIGEN_GNUC_AT_LEAST(4,1)
|
||||
void resize(size_type __new_size, const value_type& __x)
|
||||
{
|
||||
if (__new_size < vector_base::size())
|
||||
vector_base::erase(vector_base::begin() + __new_size, vector_base::end());
|
||||
else
|
||||
vector_base::insert(vector_base::end(), __new_size - vector_base::size(), __x);
|
||||
}
|
||||
#else
|
||||
// Before gcc-4.1 we already have: std::vector::resize(size_type,const T&),
|
||||
// so no need for a workaround !
|
||||
using vector_base::resize;
|
||||
#endif
|
||||
};
|
||||
@@ -131,3 +143,5 @@ class vector<T,DummyAlloc,true>
|
||||
}
|
||||
|
||||
#endif // EIGEN_STDVECTOR_MODULE_H
|
||||
|
||||
#endif // EIGEN_USE_NEW_STDVECTOR
|
||||
|
||||
@@ -43,6 +43,8 @@ struct ei_scalar_add_op {
|
||||
inline const PacketScalar packetOp(const PacketScalar& a) const
|
||||
{ return ei_padd(a, ei_pset1(m_other)); }
|
||||
const Scalar m_other;
|
||||
private:
|
||||
ei_scalar_add_op& operator=(const ei_scalar_add_op&);
|
||||
};
|
||||
template<typename Scalar>
|
||||
struct ei_functor_traits<ei_scalar_add_op<Scalar> >
|
||||
@@ -138,6 +140,8 @@ struct ei_scalar_pow_op {
|
||||
inline ei_scalar_pow_op(const Scalar& exponent) : m_exponent(exponent) {}
|
||||
inline Scalar operator() (const Scalar& a) const { return ei_pow(a, m_exponent); }
|
||||
const Scalar m_exponent;
|
||||
private:
|
||||
ei_scalar_pow_op& operator=(const ei_scalar_pow_op&);
|
||||
};
|
||||
template<typename Scalar>
|
||||
struct ei_functor_traits<ei_scalar_pow_op<Scalar> >
|
||||
|
||||
@@ -133,6 +133,8 @@ struct ei_member_redux {
|
||||
inline result_type operator()(const MatrixBase<Derived>& mat) const
|
||||
{ return mat.redux(m_functor); }
|
||||
const BinaryOp m_functor;
|
||||
private:
|
||||
ei_member_redux& operator=(const ei_member_redux&);
|
||||
};
|
||||
|
||||
/** \array_module \ingroup Array
|
||||
@@ -290,6 +292,9 @@ template<typename ExpressionType, int Direction> class PartialRedux
|
||||
|
||||
protected:
|
||||
ExpressionTypeNested m_matrix;
|
||||
|
||||
private:
|
||||
PartialRedux& operator=(const PartialRedux&);
|
||||
};
|
||||
|
||||
/** \array_module
|
||||
|
||||
@@ -222,7 +222,7 @@ class Block<MatrixType,BlockRows,BlockCols,PacketAccess,HasDirectAccess>
|
||||
|
||||
class InnerIterator;
|
||||
typedef typename ei_traits<Block>::AlignedDerivedType AlignedDerivedType;
|
||||
friend class Block<MatrixType,BlockRows,BlockCols,PacketAccess==AsRequested?ForceAligned:AsRequested,HasDirectAccess>;
|
||||
friend class Block<MatrixType,BlockRows,BlockCols,PacketAccess==int(AsRequested)?ForceAligned:AsRequested,HasDirectAccess>;
|
||||
|
||||
EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Block)
|
||||
|
||||
|
||||
@@ -116,6 +116,9 @@ struct CommaInitializer
|
||||
int m_row; // current row id
|
||||
int m_col; // current col id
|
||||
int m_currentBlockRows; // current block height
|
||||
|
||||
private:
|
||||
CommaInitializer& operator=(const CommaInitializer&);
|
||||
};
|
||||
|
||||
/** \anchor MatrixBaseCommaInitRef
|
||||
|
||||
@@ -178,6 +178,9 @@ template<typename ExpressionType> class Cwise
|
||||
|
||||
protected:
|
||||
ExpressionTypeNested m_matrix;
|
||||
|
||||
private:
|
||||
Cwise& operator=(const Cwise&);
|
||||
};
|
||||
|
||||
/** \returns a Cwise wrapper of *this providing additional coefficient-wise operations
|
||||
|
||||
@@ -109,6 +109,9 @@ template<typename ExpressionType, unsigned int Added, unsigned int Removed> clas
|
||||
|
||||
protected:
|
||||
ExpressionTypeNested m_matrix;
|
||||
|
||||
private:
|
||||
Flagged& operator=(const Flagged&);
|
||||
};
|
||||
|
||||
/** \returns an expression of *this with added flags
|
||||
|
||||
@@ -279,6 +279,8 @@ struct ei_scalar_multiple_op {
|
||||
EIGEN_STRONG_INLINE const PacketScalar packetOp(const PacketScalar& a) const
|
||||
{ return ei_pmul(a, ei_pset1(m_other)); }
|
||||
const Scalar m_other;
|
||||
private:
|
||||
ei_scalar_multiple_op& operator=(const ei_scalar_multiple_op&);
|
||||
};
|
||||
template<typename Scalar>
|
||||
struct ei_functor_traits<ei_scalar_multiple_op<Scalar> >
|
||||
@@ -294,6 +296,8 @@ struct ei_scalar_quotient1_impl {
|
||||
EIGEN_STRONG_INLINE const PacketScalar packetOp(const PacketScalar& a) const
|
||||
{ return ei_pmul(a, ei_pset1(m_other)); }
|
||||
const Scalar m_other;
|
||||
private:
|
||||
ei_scalar_quotient1_impl& operator=(const ei_scalar_quotient1_impl&);
|
||||
};
|
||||
template<typename Scalar>
|
||||
struct ei_functor_traits<ei_scalar_quotient1_impl<Scalar,true> >
|
||||
@@ -306,6 +310,8 @@ struct ei_scalar_quotient1_impl<Scalar,false> {
|
||||
EIGEN_STRONG_INLINE ei_scalar_quotient1_impl(const Scalar& other) : m_other(other) {}
|
||||
EIGEN_STRONG_INLINE Scalar operator() (const Scalar& a) const { return a / m_other; }
|
||||
const Scalar m_other;
|
||||
private:
|
||||
ei_scalar_quotient1_impl& operator=(const ei_scalar_quotient1_impl&);
|
||||
};
|
||||
template<typename Scalar>
|
||||
struct ei_functor_traits<ei_scalar_quotient1_impl<Scalar,false> >
|
||||
@@ -323,6 +329,8 @@ template<typename Scalar>
|
||||
struct ei_scalar_quotient1_op : ei_scalar_quotient1_impl<Scalar, NumTraits<Scalar>::HasFloatingPoint > {
|
||||
EIGEN_STRONG_INLINE ei_scalar_quotient1_op(const Scalar& other)
|
||||
: ei_scalar_quotient1_impl<Scalar, NumTraits<Scalar>::HasFloatingPoint >(other) {}
|
||||
private:
|
||||
ei_scalar_quotient1_op& operator=(const ei_scalar_quotient1_op&);
|
||||
};
|
||||
|
||||
// nullary functors
|
||||
@@ -335,6 +343,8 @@ struct ei_scalar_constant_op {
|
||||
EIGEN_STRONG_INLINE const Scalar operator() (int, int = 0) const { return m_other; }
|
||||
EIGEN_STRONG_INLINE const PacketScalar packetOp() const { return ei_pset1(m_other); }
|
||||
const Scalar m_other;
|
||||
private:
|
||||
ei_scalar_constant_op& operator=(const ei_scalar_constant_op&);
|
||||
};
|
||||
template<typename Scalar>
|
||||
struct ei_functor_traits<ei_scalar_constant_op<Scalar> >
|
||||
|
||||
@@ -66,11 +66,11 @@ template<typename Derived> class MapBase
|
||||
inline const Scalar* data() const { return m_data; }
|
||||
|
||||
template<bool IsForceAligned,typename Dummy> struct force_aligned_impl {
|
||||
AlignedDerivedType static run(MapBase& a) { return a.derived(); }
|
||||
static AlignedDerivedType run(MapBase& a) { return a.derived(); }
|
||||
};
|
||||
|
||||
template<typename Dummy> struct force_aligned_impl<false,Dummy> {
|
||||
AlignedDerivedType static run(MapBase& a) { return a.derived()._convertToForceAligned(); }
|
||||
static AlignedDerivedType run(MapBase& a) { return a.derived()._convertToForceAligned(); }
|
||||
};
|
||||
|
||||
/** \returns an expression equivalent to \c *this but having the \c PacketAccess constant
|
||||
|
||||
@@ -25,6 +25,11 @@
|
||||
#ifndef EIGEN_MATRIX_H
|
||||
#define EIGEN_MATRIX_H
|
||||
|
||||
#ifdef EIGEN_INITIALIZE_MATRICES_BY_ZERO
|
||||
# define EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED for(int i=0;i<base().size();++i) coeffRef(i)=Scalar(0);
|
||||
#else
|
||||
# define EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED
|
||||
#endif
|
||||
|
||||
/** \class Matrix
|
||||
*
|
||||
@@ -137,6 +142,9 @@ class Matrix
|
||||
enum { NeedsToAlign = (Options&AutoAlign) == AutoAlign
|
||||
&& SizeAtCompileTime!=Dynamic && ((sizeof(Scalar)*SizeAtCompileTime)%16)==0 };
|
||||
EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(NeedsToAlign)
|
||||
|
||||
Base& base() { return *static_cast<Base*>(this); }
|
||||
const Base& base() const { return *static_cast<const Base*>(this); }
|
||||
|
||||
EIGEN_STRONG_INLINE int rows() const { return m_storage.rows(); }
|
||||
EIGEN_STRONG_INLINE int cols() const { return m_storage.cols(); }
|
||||
@@ -230,7 +238,14 @@ class Matrix
|
||||
&& (RowsAtCompileTime == Dynamic || RowsAtCompileTime == rows)
|
||||
&& (MaxColsAtCompileTime == Dynamic || MaxColsAtCompileTime >= cols)
|
||||
&& (ColsAtCompileTime == Dynamic || ColsAtCompileTime == cols));
|
||||
m_storage.resize(rows * cols, rows, cols);
|
||||
#ifdef EIGEN_INITIALIZE_MATRICES_BY_ZERO
|
||||
int size = rows*cols;
|
||||
bool size_changed = size != this->size();
|
||||
m_storage.resize(size, rows, cols);
|
||||
if(size_changed) EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED
|
||||
#else
|
||||
m_storage.resize(rows*cols, rows, cols);
|
||||
#endif
|
||||
}
|
||||
|
||||
/** Resizes \c *this to a vector of length \a size
|
||||
@@ -240,10 +255,17 @@ class Matrix
|
||||
inline void resize(int size)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Matrix)
|
||||
ei_assert(SizeAtCompileTime == Dynamic || SizeAtCompileTime == size);
|
||||
#ifdef EIGEN_INITIALIZE_MATRICES_BY_ZERO
|
||||
bool size_changed = size != this->size();
|
||||
#endif
|
||||
if(RowsAtCompileTime == 1)
|
||||
m_storage.resize(size, 1, size);
|
||||
else
|
||||
m_storage.resize(size, size, 1);
|
||||
#ifdef EIGEN_INITIALIZE_MATRICES_BY_ZERO
|
||||
if(size_changed) EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED
|
||||
#endif
|
||||
}
|
||||
|
||||
/** Copies the value of the expression \a other into \c *this with automatic resizing.
|
||||
@@ -287,13 +309,14 @@ class Matrix
|
||||
EIGEN_STRONG_INLINE explicit Matrix() : m_storage()
|
||||
{
|
||||
_check_template_params();
|
||||
EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED
|
||||
}
|
||||
|
||||
#ifndef EIGEN_PARSED_BY_DOXYGEN
|
||||
/** \internal */
|
||||
Matrix(ei_constructor_without_unaligned_array_assert)
|
||||
: m_storage(ei_constructor_without_unaligned_array_assert())
|
||||
{}
|
||||
{EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED}
|
||||
#endif
|
||||
|
||||
/** Constructs a vector or row-vector with given dimension. \only_for_vectors
|
||||
@@ -309,6 +332,7 @@ class Matrix
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Matrix)
|
||||
ei_assert(dim > 0);
|
||||
ei_assert(SizeAtCompileTime == Dynamic || SizeAtCompileTime == dim);
|
||||
EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED
|
||||
}
|
||||
|
||||
/** This constructor has two very different behaviors, depending on the type of *this.
|
||||
@@ -334,6 +358,7 @@ class Matrix
|
||||
{
|
||||
ei_assert(x > 0 && (RowsAtCompileTime == Dynamic || RowsAtCompileTime == x)
|
||||
&& y > 0 && (ColsAtCompileTime == Dynamic || ColsAtCompileTime == y));
|
||||
EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED
|
||||
}
|
||||
}
|
||||
/** constructs an initialized 2D vector with given coefficients */
|
||||
@@ -395,18 +420,14 @@ class Matrix
|
||||
/** Override MatrixBase::swap() since for dynamic-sized matrices of same type it is enough to swap the
|
||||
* data pointers.
|
||||
*/
|
||||
inline void swap(Matrix& other)
|
||||
{
|
||||
if (Base::SizeAtCompileTime==Dynamic)
|
||||
m_storage.swap(other.m_storage);
|
||||
else
|
||||
this->Base::swap(other);
|
||||
}
|
||||
template<typename OtherDerived>
|
||||
void swap(const MatrixBase<OtherDerived>& other);
|
||||
|
||||
/** \name Map
|
||||
* These are convenience functions returning Map objects. The Map() static functions return unaligned Map objects,
|
||||
* while the AlignedMap() functions return aligned Map objects and thus should be called only with 16-byte-aligned
|
||||
* \a data pointers.
|
||||
* These are convenience functions returning Map objects.
|
||||
*
|
||||
* \warning Do not use MapAligned in the Eigen 2.0. Mapping aligned arrays will be fully
|
||||
* supported in Eigen 3.0 (already implemented in the development branch)
|
||||
*
|
||||
* \see class Map
|
||||
*/
|
||||
@@ -507,7 +528,9 @@ class Matrix
|
||||
template<typename OtherDerived>
|
||||
EIGEN_STRONG_INLINE Matrix& _set(const MatrixBase<OtherDerived>& other)
|
||||
{
|
||||
_set_selector(other.derived(), typename ei_meta_if<(int(OtherDerived::Flags) & EvalBeforeAssigningBit), ei_meta_true, ei_meta_false>::ret());
|
||||
// this enum introduced to fix compilation with gcc 3.3
|
||||
enum { cond = int(OtherDerived::Flags) & EvalBeforeAssigningBit };
|
||||
_set_selector(other.derived(), typename ei_meta_if<bool(cond), ei_meta_true, ei_meta_false>::ret());
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -540,8 +563,39 @@ class Matrix
|
||||
&& (_Options & (AutoAlign|RowMajor)) == _Options),
|
||||
INVALID_MATRIX_TEMPLATE_PARAMETERS)
|
||||
}
|
||||
|
||||
template<typename MatrixType, typename OtherDerived, bool IsSameType, bool IsDynamicSize>
|
||||
friend struct ei_matrix_swap_impl;
|
||||
};
|
||||
|
||||
template<typename MatrixType, typename OtherDerived,
|
||||
bool IsSameType = ei_is_same_type<MatrixType, OtherDerived>::ret,
|
||||
bool IsDynamicSize = MatrixType::SizeAtCompileTime==Dynamic>
|
||||
struct ei_matrix_swap_impl
|
||||
{
|
||||
static inline void run(MatrixType& matrix, MatrixBase<OtherDerived>& other)
|
||||
{
|
||||
matrix.base().swap(other);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename MatrixType, typename OtherDerived>
|
||||
struct ei_matrix_swap_impl<MatrixType, OtherDerived, true, true>
|
||||
{
|
||||
static inline void run(MatrixType& matrix, MatrixBase<OtherDerived>& other)
|
||||
{
|
||||
matrix.m_storage.swap(other.derived().m_storage);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
|
||||
template<typename OtherDerived>
|
||||
inline void Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>::swap(const MatrixBase<OtherDerived>& other)
|
||||
{
|
||||
ei_matrix_swap_impl<Matrix, OtherDerived>::run(*this, *const_cast<MatrixBase<OtherDerived>*>(&other));
|
||||
}
|
||||
|
||||
|
||||
/** \defgroup matrixtypedefs Global matrix typedefs
|
||||
*
|
||||
* \ingroup Core_Module
|
||||
|
||||
@@ -136,12 +136,6 @@ template<typename Derived> class MatrixBase
|
||||
*/
|
||||
};
|
||||
|
||||
/** Default constructor. Just checks at compile-time for self-consistency of the flags. */
|
||||
MatrixBase()
|
||||
{
|
||||
ei_assert(ei_are_flags_consistent<Flags>::ret);
|
||||
}
|
||||
|
||||
#ifndef EIGEN_PARSED_BY_DOXYGEN
|
||||
/** This is the "real scalar" type; if the \a Scalar type is already real numbers
|
||||
* (e.g. int, float or double) then \a RealScalar is just the same as \a Scalar. If
|
||||
@@ -165,7 +159,7 @@ template<typename Derived> class MatrixBase
|
||||
inline int size() const { return rows() * cols(); }
|
||||
/** \returns the number of nonzero coefficients which is in practice the number
|
||||
* of stored coefficients. */
|
||||
inline int nonZeros() const { return derived.nonZeros(); }
|
||||
inline int nonZeros() const { return size(); }
|
||||
/** \returns true if either the number of rows or the number of columns is equal to 1.
|
||||
* In other words, this function returns
|
||||
* \code rows()==1 || cols()==1 \endcode
|
||||
@@ -532,8 +526,11 @@ template<typename Derived> class MatrixBase
|
||||
typename ei_traits<Derived>::Scalar minCoeff() const;
|
||||
typename ei_traits<Derived>::Scalar maxCoeff() const;
|
||||
|
||||
typename ei_traits<Derived>::Scalar minCoeff(int* row, int* col = 0) const;
|
||||
typename ei_traits<Derived>::Scalar maxCoeff(int* row, int* col = 0) const;
|
||||
typename ei_traits<Derived>::Scalar minCoeff(int* row, int* col) const;
|
||||
typename ei_traits<Derived>::Scalar maxCoeff(int* row, int* col) const;
|
||||
|
||||
typename ei_traits<Derived>::Scalar minCoeff(int* index) const;
|
||||
typename ei_traits<Derived>::Scalar maxCoeff(int* index) const;
|
||||
|
||||
template<typename BinaryOp>
|
||||
typename ei_result_of<BinaryOp(typename ei_traits<Derived>::Scalar)>::type
|
||||
@@ -624,6 +621,24 @@ template<typename Derived> class MatrixBase
|
||||
#ifdef EIGEN_MATRIXBASE_PLUGIN
|
||||
#include EIGEN_MATRIXBASE_PLUGIN
|
||||
#endif
|
||||
|
||||
protected:
|
||||
/** Default constructor. Do nothing. */
|
||||
MatrixBase()
|
||||
{
|
||||
/* Just checks for self-consistency of the flags.
|
||||
* Only do it when debugging Eigen, as this borders on paranoiac and could slow compilation down
|
||||
*/
|
||||
#ifdef EIGEN_INTERNAL_DEBUGGING
|
||||
EIGEN_STATIC_ASSERT(ei_are_flags_consistent<Flags>::ret,
|
||||
INVALID_MATRIXBASE_TEMPLATE_PARAMETERS)
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
explicit MatrixBase(int);
|
||||
MatrixBase(int,int);
|
||||
template<typename OtherDerived> explicit MatrixBase(const MatrixBase<OtherDerived>&);
|
||||
};
|
||||
|
||||
#endif // EIGEN_MATRIXBASE_H
|
||||
|
||||
@@ -100,6 +100,9 @@ template<typename ExpressionType> class NestByValue
|
||||
|
||||
protected:
|
||||
const ExpressionType m_expression;
|
||||
|
||||
private:
|
||||
NestByValue& operator=(const NestByValue&);
|
||||
};
|
||||
|
||||
/** \returns an expression of the temporary version of *this.
|
||||
|
||||
@@ -124,8 +124,10 @@ template<typename MatrixType, unsigned int Mode> class Part
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
const typename MatrixType::Nested m_matrix;
|
||||
|
||||
private:
|
||||
Part& operator=(const Part&);
|
||||
};
|
||||
|
||||
/** \nonstableyet
|
||||
|
||||
@@ -762,7 +762,7 @@ inline void Product<Lhs,Rhs,ProductMode>::_cacheFriendlyEvalAndAdd(DestDerived&
|
||||
rows(), cols(), lhs.cols(),
|
||||
_LhsCopy::Flags&RowMajorBit, (const Scalar*)&(lhs.const_cast_derived().coeffRef(0,0)), lhs.stride(),
|
||||
_RhsCopy::Flags&RowMajorBit, (const Scalar*)&(rhs.const_cast_derived().coeffRef(0,0)), rhs.stride(),
|
||||
Flags&RowMajorBit, (Scalar*)&(res.coeffRef(0,0)), res.stride()
|
||||
DestDerived::Flags&RowMajorBit, (Scalar*)&(res.coeffRef(0,0)), res.stride()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -117,6 +117,9 @@ template<typename ExpressionType> class SwapWrapper
|
||||
|
||||
protected:
|
||||
ExpressionType& m_expression;
|
||||
|
||||
private:
|
||||
SwapWrapper& operator=(const SwapWrapper&);
|
||||
};
|
||||
|
||||
/** swaps *this with the expression \a other.
|
||||
|
||||
@@ -69,7 +69,6 @@ template<typename MatrixType> class Transpose
|
||||
|
||||
inline int rows() const { return m_matrix.cols(); }
|
||||
inline int cols() const { return m_matrix.rows(); }
|
||||
inline int nonZeros() const { return m_matrix.nonZeros(); }
|
||||
inline int stride(void) const { return m_matrix.stride(); }
|
||||
|
||||
inline Scalar& coeffRef(int row, int col)
|
||||
|
||||
@@ -164,7 +164,7 @@ struct ei_functor_traits<ei_max_coeff_visitor<Scalar> > {
|
||||
/** \returns the minimum of all coefficients of *this
|
||||
* and puts in *row and *col its location.
|
||||
*
|
||||
* \sa MatrixBase::maxCoeff(int*,int*), MatrixBase::visitor(), MatrixBase::minCoeff()
|
||||
* \sa MatrixBase::minCoeff(int*), MatrixBase::maxCoeff(int*,int*), MatrixBase::visitor(), MatrixBase::minCoeff()
|
||||
*/
|
||||
template<typename Derived>
|
||||
typename ei_traits<Derived>::Scalar
|
||||
@@ -177,6 +177,22 @@ MatrixBase<Derived>::minCoeff(int* row, int* col) const
|
||||
return minVisitor.res;
|
||||
}
|
||||
|
||||
/** \returns the minimum of all coefficients of *this
|
||||
* and puts in *index its location.
|
||||
*
|
||||
* \sa MatrixBase::minCoeff(int*,int*), MatrixBase::maxCoeff(int*,int*), MatrixBase::visitor(), MatrixBase::minCoeff()
|
||||
*/
|
||||
template<typename Derived>
|
||||
typename ei_traits<Derived>::Scalar
|
||||
MatrixBase<Derived>::minCoeff(int* index) const
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
|
||||
ei_min_coeff_visitor<Scalar> minVisitor;
|
||||
this->visit(minVisitor);
|
||||
*index = (RowsAtCompileTime==1) ? minVisitor.col : minVisitor.row;
|
||||
return minVisitor.res;
|
||||
}
|
||||
|
||||
/** \returns the maximum of all coefficients of *this
|
||||
* and puts in *row and *col its location.
|
||||
*
|
||||
@@ -193,5 +209,20 @@ MatrixBase<Derived>::maxCoeff(int* row, int* col) const
|
||||
return maxVisitor.res;
|
||||
}
|
||||
|
||||
/** \returns the maximum of all coefficients of *this
|
||||
* and puts in *index its location.
|
||||
*
|
||||
* \sa MatrixBase::maxCoeff(int*,int*), MatrixBase::minCoeff(int*,int*), MatrixBase::visitor(), MatrixBase::maxCoeff()
|
||||
*/
|
||||
template<typename Derived>
|
||||
typename ei_traits<Derived>::Scalar
|
||||
MatrixBase<Derived>::maxCoeff(int* index) const
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
|
||||
ei_max_coeff_visitor<Scalar> maxVisitor;
|
||||
this->visit(maxVisitor);
|
||||
*index = (RowsAtCompileTime==1) ? maxVisitor.col : maxVisitor.row;
|
||||
return maxVisitor.res;
|
||||
}
|
||||
|
||||
#endif // EIGEN_VISITOR_H
|
||||
|
||||
@@ -114,9 +114,15 @@ template<> EIGEN_STRONG_INLINE void ei_pstoreu<float>(float* to, const __m128&
|
||||
template<> EIGEN_STRONG_INLINE void ei_pstoreu<double>(double* to, const __m128d& from) { _mm_storeu_pd(to, from); }
|
||||
template<> EIGEN_STRONG_INLINE void ei_pstoreu<int>(int* to, const __m128i& from) { _mm_storeu_si128(reinterpret_cast<__m128i*>(to), from); }
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// this fix internal compilation error
|
||||
template<> EIGEN_STRONG_INLINE float ei_pfirst<__m128>(const __m128& a) { float x = _mm_cvtss_f32(a); return x; }
|
||||
#if defined(_MSC_VER) && (_MSC_VER <= 1500) && defined(_WIN64)
|
||||
// The temporary variable fixes an internal compilation error.
|
||||
// Direct of the struct members fixed bug #62.
|
||||
template<> EIGEN_STRONG_INLINE float ei_pfirst<__m128>(const __m128& a) { return a.m128_f32[0]; }
|
||||
template<> EIGEN_STRONG_INLINE double ei_pfirst<__m128d>(const __m128d& a) { return a.m128d_f64[0]; }
|
||||
template<> EIGEN_STRONG_INLINE int ei_pfirst<__m128i>(const __m128i& a) { int x = _mm_cvtsi128_si32(a); return x; }
|
||||
#elif defined(_MSC_VER) && (_MSC_VER <= 1500)
|
||||
// The temporary variable fixes an internal compilation error.
|
||||
template<> EIGEN_STRONG_INLINE float ei_pfirst<__m128>(const __m128& a) { float x = _mm_cvtss_f32(a); return x; }
|
||||
template<> EIGEN_STRONG_INLINE double ei_pfirst<__m128d>(const __m128d& a) { double x = _mm_cvtsd_f64(a); return x; }
|
||||
template<> EIGEN_STRONG_INLINE int ei_pfirst<__m128i>(const __m128i& a) { int x = _mm_cvtsi128_si32(a); return x; }
|
||||
#else
|
||||
@@ -315,4 +321,7 @@ struct ei_palign_impl<Offset,__m128d>
|
||||
};
|
||||
#endif
|
||||
|
||||
#define ei_vec4f_swizzle1(v,p,q,r,s) \
|
||||
(_mm_castsi128_ps(_mm_shuffle_epi32( _mm_castps_si128(v), ((s)<<6|(r)<<4|(q)<<2|(p)))))
|
||||
|
||||
#endif // EIGEN_PACKET_MATH_SSE_H
|
||||
|
||||
@@ -239,4 +239,16 @@ enum {
|
||||
HasDirectAccess = DirectAccessBit
|
||||
};
|
||||
|
||||
const int EiArch_Generic = 0x0;
|
||||
const int EiArch_SSE = 0x1;
|
||||
const int EiArch_AltiVec = 0x2;
|
||||
|
||||
#if defined EIGEN_VECTORIZE_SSE
|
||||
const int EiArch = EiArch_SSE;
|
||||
#elif defined EIGEN_VECTORIZE_ALTIVEC
|
||||
const int EiArch = EiArch_AltiVec;
|
||||
#else
|
||||
const int EiArch = EiArch_Generic;
|
||||
#endif
|
||||
|
||||
#endif // EIGEN_CONSTANTS_H
|
||||
|
||||
@@ -30,30 +30,48 @@
|
||||
|
||||
#define EIGEN_WORLD_VERSION 2
|
||||
#define EIGEN_MAJOR_VERSION 0
|
||||
#define EIGEN_MINOR_VERSION 4
|
||||
#define EIGEN_MINOR_VERSION 10
|
||||
|
||||
#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_MINOR_VERSION>=z))))
|
||||
|
||||
// if the compiler is GNUC, disable 16 byte alignment on exotic archs that probably don't need it, and on which
|
||||
// it may be extra trouble to get aligned memory allocation to work (example: on ARM, overloading new[] is a PITA
|
||||
// because extra memory must be allocated for bookkeeping).
|
||||
// if the compiler is not GNUC, just cross fingers that the architecture isn't too exotic, because we don't want
|
||||
// to keep track of all the different preprocessor symbols for all compilers.
|
||||
#if !defined(__GNUC__) || defined(__i386__) || defined(__x86_64__) || defined(__ppc__) || defined(__ia64__)
|
||||
// 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 enable alignment, but it can be a cause of problems
|
||||
// on some platforms, so we just disable it in certain common platform (compiler+architecture combinations) to avoid these problems.
|
||||
#if defined(__GNUC__) && !(defined(__i386__) || defined(__x86_64__) || defined(__powerpc__) || defined(__ppc__) || defined(__ia64__))
|
||||
#define EIGEN_GCC_AND_ARCH_DOESNT_WANT_ALIGNMENT 1
|
||||
#else
|
||||
#define EIGEN_GCC_AND_ARCH_DOESNT_WANT_ALIGNMENT 0
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) && (__GNUC__ <= 3)
|
||||
#define EIGEN_GCC3_OR_OLDER 1
|
||||
#else
|
||||
#define EIGEN_GCC3_OR_OLDER 0
|
||||
#endif
|
||||
|
||||
// FIXME vectorization + alignment is completely disabled with sun studio
|
||||
#if !EIGEN_GCC_AND_ARCH_DOESNT_WANT_ALIGNMENT && !EIGEN_GCC3_OR_OLDER && !defined(__SUNPRO_CC)
|
||||
#define EIGEN_ARCH_WANTS_ALIGNMENT 1
|
||||
#else
|
||||
#ifdef EIGEN_VECTORIZE
|
||||
#error Vectorization enabled, but the architecture is not listed among those for which we require 16 byte alignment. If you added vectorization for another architecture, you also need to edit this list.
|
||||
#endif
|
||||
#define EIGEN_ARCH_WANTS_ALIGNMENT 0
|
||||
#endif
|
||||
|
||||
// EIGEN_ALIGN is the true test whether we want to align or not. It takes into account both the user choice to explicitly disable
|
||||
// alignment (EIGEN_DONT_ALIGN) and the architecture config (EIGEN_ARCH_WANTS_ALIGNMENT). Henceforth, only EIGEN_ALIGN should be used.
|
||||
#if EIGEN_ARCH_WANTS_ALIGNMENT && !defined(EIGEN_DONT_ALIGN)
|
||||
#define EIGEN_ALIGN 1
|
||||
#else
|
||||
#define EIGEN_ALIGN 0
|
||||
#ifdef EIGEN_VECTORIZE
|
||||
#error "Vectorization enabled, but our platform checks say that we don't do 16 byte alignment on this platform. If you added vectorization for another architecture, you also need to edit this platform check."
|
||||
#endif
|
||||
#ifndef EIGEN_DISABLE_UNALIGNED_ARRAY_ASSERT
|
||||
#define EIGEN_DISABLE_UNALIGNED_ARRAY_ASSERT
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef EIGEN_DEFAULT_TO_ROW_MAJOR
|
||||
#define EIGEN_DEFAULT_MATRIX_STORAGE_ORDER_OPTION RowMajor
|
||||
#else
|
||||
@@ -165,7 +183,7 @@ using Eigen::ei_cos;
|
||||
* If we made alignment depend on whether or not EIGEN_VECTORIZE is defined, it would be impossible to link
|
||||
* vectorized and non-vectorized code.
|
||||
*/
|
||||
#if !EIGEN_ARCH_WANTS_ALIGNMENT
|
||||
#if !EIGEN_ALIGN
|
||||
#define EIGEN_ALIGN_128
|
||||
#elif (defined __GNUC__)
|
||||
#define EIGEN_ALIGN_128 __attribute__((aligned(16)))
|
||||
@@ -175,10 +193,15 @@ using Eigen::ei_cos;
|
||||
#error Please tell me what is the equivalent of __attribute__((aligned(16))) for your compiler
|
||||
#endif
|
||||
|
||||
#define EIGEN_RESTRICT __restrict
|
||||
#ifdef EIGEN_DONT_USE_RESTRICT_KEYWORD
|
||||
#define EIGEN_RESTRICT
|
||||
#endif
|
||||
#ifndef EIGEN_RESTRICT
|
||||
#define EIGEN_RESTRICT __restrict
|
||||
#endif
|
||||
|
||||
#ifndef EIGEN_STACK_ALLOCATION_LIMIT
|
||||
#define EIGEN_STACK_ALLOCATION_LIMIT 16000000
|
||||
#define EIGEN_STACK_ALLOCATION_LIMIT 1000000
|
||||
#endif
|
||||
|
||||
#ifndef EIGEN_DEFAULT_IO_FORMAT
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
// Copyright (C) 2008-2009 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
@@ -27,7 +27,17 @@
|
||||
#ifndef EIGEN_MEMORY_H
|
||||
#define EIGEN_MEMORY_H
|
||||
|
||||
#if defined(__APPLE__) || defined(_WIN64)
|
||||
// FreeBSD 6 seems to have 16-byte aligned malloc
|
||||
// See http://svn.freebsd.org/viewvc/base/stable/6/lib/libc/stdlib/malloc.c?view=markup
|
||||
// FreeBSD 7 seems to have 16-byte aligned malloc except on ARM and MIPS architectures
|
||||
// See http://svn.freebsd.org/viewvc/base/stable/7/lib/libc/stdlib/malloc.c?view=markup
|
||||
#if defined(__FreeBSD__) && !defined(__arm__) && !defined(__mips__)
|
||||
#define EIGEN_FREEBSD_MALLOC_ALREADY_ALIGNED 1
|
||||
#else
|
||||
#define EIGEN_FREEBSD_MALLOC_ALREADY_ALIGNED 0
|
||||
#endif
|
||||
|
||||
#if defined(__APPLE__) || defined(_WIN64) || EIGEN_FREEBSD_MALLOC_ALREADY_ALIGNED
|
||||
#define EIGEN_MALLOC_ALREADY_ALIGNED 1
|
||||
#else
|
||||
#define EIGEN_MALLOC_ALREADY_ALIGNED 0
|
||||
@@ -65,7 +75,7 @@ inline void ei_handmade_aligned_free(void *ptr)
|
||||
}
|
||||
|
||||
/** \internal allocates \a size bytes. The returned pointer is guaranteed to have 16 bytes alignment.
|
||||
* On allocation error, the returned pointer is undefined, but if exceptions are enabled then a std::bad_alloc is thrown.
|
||||
* On allocation error, the returned pointer is null, and if exceptions are enabled then a std::bad_alloc is thrown.
|
||||
*/
|
||||
inline void* ei_aligned_malloc(size_t size)
|
||||
{
|
||||
@@ -73,37 +83,30 @@ inline void* ei_aligned_malloc(size_t size)
|
||||
ei_assert(false && "heap allocation is forbidden (EIGEN_NO_MALLOC is defined)");
|
||||
#endif
|
||||
|
||||
void *result;
|
||||
#if EIGEN_HAS_POSIX_MEMALIGN && EIGEN_ARCH_WANTS_ALIGNMENT && !EIGEN_MALLOC_ALREADY_ALIGNED
|
||||
#ifdef EIGEN_EXCEPTIONS
|
||||
const int failed =
|
||||
#endif
|
||||
posix_memalign(&result, 16, size);
|
||||
void *result;
|
||||
#if !EIGEN_ALIGN
|
||||
result = malloc(size);
|
||||
#elif EIGEN_MALLOC_ALREADY_ALIGNED
|
||||
result = malloc(size);
|
||||
#elif EIGEN_HAS_POSIX_MEMALIGN
|
||||
if(posix_memalign(&result, 16, size)) result = 0;
|
||||
#elif EIGEN_HAS_MM_MALLOC
|
||||
result = _mm_malloc(size, 16);
|
||||
#elif (defined _MSC_VER)
|
||||
result = _aligned_malloc(size, 16);
|
||||
#else
|
||||
#if !EIGEN_ARCH_WANTS_ALIGNMENT
|
||||
result = malloc(size);
|
||||
#elif EIGEN_MALLOC_ALREADY_ALIGNED
|
||||
result = malloc(size);
|
||||
#elif EIGEN_HAS_MM_MALLOC
|
||||
result = _mm_malloc(size, 16);
|
||||
#elif (defined _MSC_VER)
|
||||
result = _aligned_malloc(size, 16);
|
||||
#else
|
||||
result = ei_handmade_aligned_malloc(size);
|
||||
#endif
|
||||
#ifdef EIGEN_EXCEPTIONS
|
||||
const int failed = (result == 0);
|
||||
#endif
|
||||
result = ei_handmade_aligned_malloc(size);
|
||||
#endif
|
||||
|
||||
#ifdef EIGEN_EXCEPTIONS
|
||||
if(failed)
|
||||
if(result == 0)
|
||||
throw std::bad_alloc();
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
/** allocates \a size bytes. If Align is true, then the returned ptr is 16-byte-aligned.
|
||||
* On allocation error, the returned pointer is undefined, but if exceptions are enabled then a std::bad_alloc is thrown.
|
||||
* On allocation error, the returned pointer is null, and if exceptions are enabled then a std::bad_alloc is thrown.
|
||||
*/
|
||||
template<bool Align> inline void* ei_conditional_aligned_malloc(size_t size)
|
||||
{
|
||||
@@ -123,27 +126,36 @@ template<> inline void* ei_conditional_aligned_malloc<false>(size_t size)
|
||||
return result;
|
||||
}
|
||||
|
||||
/** \internal construct the elements of an array.
|
||||
* The \a size parameter tells on how many objects to call the constructor of T.
|
||||
*/
|
||||
template<typename T> inline T* ei_construct_elements_of_array(T *ptr, size_t size)
|
||||
{
|
||||
for (size_t i=0; i < size; ++i) ::new (ptr + i) T;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/** allocates \a size objects of type T. The returned pointer is guaranteed to have 16 bytes alignment.
|
||||
* On allocation error, the returned pointer is undefined, but if exceptions are enabled then a std::bad_alloc is thrown.
|
||||
* The default constructor of T is called.
|
||||
*/
|
||||
template<typename T> inline T* ei_aligned_new(size_t size)
|
||||
{
|
||||
void *void_result = ei_aligned_malloc(sizeof(T)*size);
|
||||
return ::new(void_result) T[size];
|
||||
T *result = reinterpret_cast<T*>(ei_aligned_malloc(sizeof(T)*size));
|
||||
return ei_construct_elements_of_array(result, size);
|
||||
}
|
||||
|
||||
template<typename T, bool Align> inline T* ei_conditional_aligned_new(size_t size)
|
||||
{
|
||||
void *void_result = ei_conditional_aligned_malloc<Align>(sizeof(T)*size);
|
||||
return ::new(void_result) T[size];
|
||||
T *result = reinterpret_cast<T*>(ei_conditional_aligned_malloc<Align>(sizeof(T)*size));
|
||||
return ei_construct_elements_of_array(result, size);
|
||||
}
|
||||
|
||||
/** \internal free memory allocated with ei_aligned_malloc
|
||||
*/
|
||||
inline void ei_aligned_free(void *ptr)
|
||||
{
|
||||
#if !EIGEN_ARCH_WANTS_ALIGNMENT
|
||||
#if !EIGEN_ALIGN
|
||||
free(ptr);
|
||||
#elif EIGEN_MALLOC_ALREADY_ALIGNED
|
||||
free(ptr);
|
||||
@@ -170,10 +182,10 @@ template<> inline void ei_conditional_aligned_free<false>(void *ptr)
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
/** \internal delete the elements of an array.
|
||||
/** \internal destruct the elements of an array.
|
||||
* The \a size parameters tells on how many objects to call the destructor of T.
|
||||
*/
|
||||
template<typename T> inline void ei_delete_elements_of_array(T *ptr, size_t size)
|
||||
template<typename T> inline void ei_destruct_elements_of_array(T *ptr, size_t size)
|
||||
{
|
||||
// always destruct an array starting from the end.
|
||||
while(size) ptr[--size].~T();
|
||||
@@ -184,7 +196,7 @@ template<typename T> inline void ei_delete_elements_of_array(T *ptr, size_t size
|
||||
*/
|
||||
template<typename T> inline void ei_aligned_delete(T *ptr, size_t size)
|
||||
{
|
||||
ei_delete_elements_of_array<T>(ptr, size);
|
||||
ei_destruct_elements_of_array<T>(ptr, size);
|
||||
ei_aligned_free(ptr);
|
||||
}
|
||||
|
||||
@@ -193,7 +205,7 @@ template<typename T> inline void ei_aligned_delete(T *ptr, size_t size)
|
||||
*/
|
||||
template<typename T, bool Align> inline void ei_conditional_aligned_delete(T *ptr, size_t size)
|
||||
{
|
||||
ei_delete_elements_of_array<T>(ptr, size);
|
||||
ei_destruct_elements_of_array<T>(ptr, size);
|
||||
ei_conditional_aligned_free<Align>(ptr);
|
||||
}
|
||||
|
||||
@@ -232,12 +244,12 @@ inline static int ei_alignmentOffset(const Scalar* ptr, int maxOffset)
|
||||
#define ei_aligned_stack_free(PTR,SIZE) ei_aligned_free(PTR)
|
||||
#endif
|
||||
|
||||
#define ei_aligned_stack_new(TYPE,SIZE) ::new(ei_aligned_stack_alloc(sizeof(TYPE)*SIZE)) TYPE[SIZE]
|
||||
#define ei_aligned_stack_delete(TYPE,PTR,SIZE) do {ei_delete_elements_of_array<TYPE>(PTR, SIZE); \
|
||||
#define ei_aligned_stack_new(TYPE,SIZE) ei_construct_elements_of_array(reinterpret_cast<TYPE*>(ei_aligned_stack_alloc(sizeof(TYPE)*SIZE)), SIZE)
|
||||
#define ei_aligned_stack_delete(TYPE,PTR,SIZE) do {ei_destruct_elements_of_array<TYPE>(PTR, SIZE); \
|
||||
ei_aligned_stack_free(PTR,sizeof(TYPE)*SIZE);} while(0)
|
||||
|
||||
|
||||
#if EIGEN_ARCH_WANTS_ALIGNMENT
|
||||
#if EIGEN_ALIGN
|
||||
#ifdef EIGEN_EXCEPTIONS
|
||||
#define EIGEN_MAKE_ALIGNED_OPERATOR_NEW_NOTHROW(NeedsToAlign) \
|
||||
void* operator new(size_t size, const std::nothrow_t&) throw() { \
|
||||
@@ -251,7 +263,7 @@ inline static int ei_alignmentOffset(const Scalar* ptr, int maxOffset)
|
||||
return Eigen::ei_conditional_aligned_malloc<NeedsToAlign>(size); \
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#define EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(NeedsToAlign) \
|
||||
void *operator new(size_t size) { \
|
||||
return Eigen::ei_conditional_aligned_malloc<NeedsToAlign>(size); \
|
||||
|
||||
@@ -74,6 +74,7 @@
|
||||
THIS_METHOD_IS_ONLY_FOR_COLUMN_MAJOR_MATRICES,
|
||||
THIS_METHOD_IS_ONLY_FOR_ROW_MAJOR_MATRICES,
|
||||
INVALID_MATRIX_TEMPLATE_PARAMETERS,
|
||||
INVALID_MATRIXBASE_TEMPLATE_PARAMETERS,
|
||||
BOTH_MATRICES_MUST_HAVE_THE_SAME_STORAGE_ORDER,
|
||||
THIS_METHOD_IS_ONLY_FOR_DIAGONAL_MATRIX
|
||||
};
|
||||
|
||||
@@ -37,6 +37,10 @@
|
||||
//classes inheriting ei_no_assignment_operator don't generate a default operator=.
|
||||
class ei_no_assignment_operator
|
||||
{
|
||||
#if EIGEN_GCC3_OR_OLDER
|
||||
protected:
|
||||
void nevermind_this_is_just_to_work_around_a_stupid_gcc3_warning();
|
||||
#endif
|
||||
private:
|
||||
ei_no_assignment_operator& operator=(const ei_no_assignment_operator&);
|
||||
};
|
||||
|
||||
@@ -224,17 +224,45 @@ typedef Quaternion<float> Quaternionf;
|
||||
* double precision quaternion type */
|
||||
typedef Quaternion<double> Quaterniond;
|
||||
|
||||
// Generic Quaternion * Quaternion product
|
||||
template<int Arch,typename Scalar> inline Quaternion<Scalar>
|
||||
ei_quaternion_product(const Quaternion<Scalar>& a, const Quaternion<Scalar>& b)
|
||||
{
|
||||
return Quaternion<Scalar>
|
||||
(
|
||||
a.w() * b.w() - a.x() * b.x() - a.y() * b.y() - a.z() * b.z(),
|
||||
a.w() * b.x() + a.x() * b.w() + a.y() * b.z() - a.z() * b.y(),
|
||||
a.w() * b.y() + a.y() * b.w() + a.z() * b.x() - a.x() * b.z(),
|
||||
a.w() * b.z() + a.z() * b.w() + a.x() * b.y() - a.y() * b.x()
|
||||
);
|
||||
}
|
||||
|
||||
#ifdef EIGEN_VECTORIZE_SSE
|
||||
template<> inline Quaternion<float>
|
||||
ei_quaternion_product<EiArch_SSE,float>(const Quaternion<float>& _a, const Quaternion<float>& _b)
|
||||
{
|
||||
const __m128 mask = _mm_castsi128_ps(_mm_setr_epi32(0,0,0,0x80000000));
|
||||
Quaternion<float> res;
|
||||
__m128 a = _a.coeffs().packet<Aligned>(0);
|
||||
__m128 b = _b.coeffs().packet<Aligned>(0);
|
||||
__m128 flip1 = _mm_xor_ps(_mm_mul_ps(ei_vec4f_swizzle1(a,1,2,0,2),
|
||||
ei_vec4f_swizzle1(b,2,0,1,2)),mask);
|
||||
__m128 flip2 = _mm_xor_ps(_mm_mul_ps(ei_vec4f_swizzle1(a,3,3,3,1),
|
||||
ei_vec4f_swizzle1(b,0,1,2,1)),mask);
|
||||
ei_pstore(&res.x(),
|
||||
_mm_add_ps(_mm_sub_ps(_mm_mul_ps(a,ei_vec4f_swizzle1(b,3,3,3,3)),
|
||||
_mm_mul_ps(ei_vec4f_swizzle1(a,2,0,1,0),
|
||||
ei_vec4f_swizzle1(b,1,2,0,0))),
|
||||
_mm_add_ps(flip1,flip2)));
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
|
||||
/** \returns the concatenation of two rotations as a quaternion-quaternion product */
|
||||
template <typename Scalar>
|
||||
inline Quaternion<Scalar> Quaternion<Scalar>::operator* (const Quaternion& other) const
|
||||
{
|
||||
return Quaternion
|
||||
(
|
||||
this->w() * other.w() - this->x() * other.x() - this->y() * other.y() - this->z() * other.z(),
|
||||
this->w() * other.x() + this->x() * other.w() + this->y() * other.z() - this->z() * other.y(),
|
||||
this->w() * other.y() + this->y() * other.w() + this->z() * other.x() - this->x() * other.z(),
|
||||
this->w() * other.z() + this->z() * other.w() + this->x() * other.y() - this->y() * other.x()
|
||||
);
|
||||
return ei_quaternion_product<EiArch>(*this,other);
|
||||
}
|
||||
|
||||
/** \sa operator*(Quaternion) */
|
||||
|
||||
@@ -85,7 +85,7 @@ public:
|
||||
|
||||
/** Concatenates two rotations */
|
||||
inline Rotation2D& operator*=(const Rotation2D& other)
|
||||
{ return m_angle += other.m_angle; }
|
||||
{ return m_angle += other.m_angle; return *this; }
|
||||
|
||||
/** Applies the rotation to a 2D vector */
|
||||
Vector2 operator* (const Vector2& vec) const
|
||||
|
||||
@@ -198,6 +198,10 @@ public:
|
||||
|
||||
/** \sa MatrixBase::setIdentity() */
|
||||
void setIdentity() { m_matrix.setIdentity(); }
|
||||
static const typename MatrixType::IdentityReturnType Identity()
|
||||
{
|
||||
return MatrixType::Identity();
|
||||
}
|
||||
|
||||
template<typename OtherDerived>
|
||||
inline Transform& scale(const MatrixBase<OtherDerived> &other);
|
||||
@@ -283,6 +287,10 @@ public:
|
||||
bool isApprox(const Transform& other, typename NumTraits<Scalar>::Real prec = precision<Scalar>()) const
|
||||
{ return m_matrix.isApprox(other.m_matrix, prec); }
|
||||
|
||||
#ifdef EIGEN_TRANSFORM_PLUGIN
|
||||
#include EIGEN_TRANSFORM_PLUGIN
|
||||
#endif
|
||||
|
||||
protected:
|
||||
|
||||
};
|
||||
|
||||
@@ -119,46 +119,54 @@ bool ei_compute_inverse_in_size4_case_helper(const MatrixType& matrix, MatrixTyp
|
||||
}
|
||||
|
||||
template<typename MatrixType>
|
||||
void ei_compute_inverse_in_size4_case(const MatrixType& matrix, MatrixType* result)
|
||||
void ei_compute_inverse_in_size4_case(const MatrixType& _matrix, MatrixType* result)
|
||||
{
|
||||
if(ei_compute_inverse_in_size4_case_helper(matrix, result))
|
||||
{
|
||||
// good ! The topleft 2x2 block was invertible, so the 2x2 blocks approach is successful.
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// rare case: the topleft 2x2 block is not invertible (but the matrix itself is assumed to be).
|
||||
// since this is a rare case, we don't need to optimize it. We just want to handle it with little
|
||||
// additional code.
|
||||
MatrixType m(matrix);
|
||||
m.row(0).swap(m.row(2));
|
||||
m.row(1).swap(m.row(3));
|
||||
if(ei_compute_inverse_in_size4_case_helper(m, result))
|
||||
{
|
||||
// good, the topleft 2x2 block of m is invertible. Since m is different from matrix in that some
|
||||
// rows were permuted, the actual inverse of matrix is derived from the inverse of m by permuting
|
||||
// the corresponding columns.
|
||||
result->col(0).swap(result->col(2));
|
||||
result->col(1).swap(result->col(3));
|
||||
}
|
||||
else
|
||||
{
|
||||
// last possible case. Since matrix is assumed to be invertible, this last case has to work.
|
||||
// first, undo the swaps previously made
|
||||
m.row(0).swap(m.row(2));
|
||||
m.row(1).swap(m.row(3));
|
||||
// swap row 0 with the the row among 0 and 1 that has the biggest 2 first coeffs
|
||||
int swap0with = ei_abs(m.coeff(0,0))+ei_abs(m.coeff(0,1))>ei_abs(m.coeff(1,0))+ei_abs(m.coeff(1,1)) ? 0 : 1;
|
||||
m.row(0).swap(m.row(swap0with));
|
||||
// swap row 1 with the the row among 2 and 3 that has the biggest 2 first coeffs
|
||||
int swap1with = ei_abs(m.coeff(2,0))+ei_abs(m.coeff(2,1))>ei_abs(m.coeff(3,0))+ei_abs(m.coeff(3,1)) ? 2 : 3;
|
||||
m.row(1).swap(m.row(swap1with));
|
||||
ei_compute_inverse_in_size4_case_helper(m, result);
|
||||
result->col(1).swap(result->col(swap1with));
|
||||
result->col(0).swap(result->col(swap0with));
|
||||
}
|
||||
}
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
typedef typename MatrixType::RealScalar RealScalar;
|
||||
|
||||
// we will do row permutations on the matrix. This copy should have negligible cost.
|
||||
// if not, consider working in-place on the matrix (const-cast it, but then undo the permutations
|
||||
// to nevertheless honor constness)
|
||||
typename MatrixType::PlainMatrixType matrix(_matrix);
|
||||
|
||||
// let's extract from the 2 first colums a 2x2 block whose determinant is as big as possible.
|
||||
int good_row0, good_row1, good_i;
|
||||
Matrix<RealScalar,6,1> absdet;
|
||||
|
||||
// any 2x2 block with determinant above this threshold will be considered good enough.
|
||||
// The magic value 1e-1 here comes from experimentation. The bigger it is, the higher the precision,
|
||||
// the slower the computation. This value 1e-1 gives precision almost as good as the brutal cofactors
|
||||
// algorithm, both in average and in worst-case precision.
|
||||
RealScalar d = (matrix.col(0).squaredNorm()+matrix.col(1).squaredNorm()) * RealScalar(1e-1);
|
||||
#define ei_inv_size4_helper_macro(i,row0,row1) \
|
||||
absdet[i] = ei_abs(matrix.coeff(row0,0)*matrix.coeff(row1,1) \
|
||||
- matrix.coeff(row0,1)*matrix.coeff(row1,0)); \
|
||||
if(absdet[i] > d) { good_row0=row0; good_row1=row1; goto good; }
|
||||
ei_inv_size4_helper_macro(0,0,1)
|
||||
ei_inv_size4_helper_macro(1,0,2)
|
||||
ei_inv_size4_helper_macro(2,0,3)
|
||||
ei_inv_size4_helper_macro(3,1,2)
|
||||
ei_inv_size4_helper_macro(4,1,3)
|
||||
ei_inv_size4_helper_macro(5,2,3)
|
||||
|
||||
// no 2x2 block has determinant bigger than the threshold. So just take the one that
|
||||
// has the biggest determinant
|
||||
absdet.maxCoeff(&good_i);
|
||||
good_row0 = good_i <= 2 ? 0 : good_i <= 4 ? 1 : 2;
|
||||
good_row1 = good_i <= 2 ? good_i+1 : good_i <= 4 ? good_i-1 : 3;
|
||||
|
||||
// now good_row0 and good_row1 are correctly set
|
||||
good:
|
||||
|
||||
// do row permutations to move this 2x2 block to the top
|
||||
matrix.row(0).swap(matrix.row(good_row0));
|
||||
matrix.row(1).swap(matrix.row(good_row1));
|
||||
// now applying our helper function is numerically stable
|
||||
ei_compute_inverse_in_size4_case_helper(matrix, result);
|
||||
// Since we did row permutations on the original matrix, we need to do column permutations
|
||||
// in the reverse order on the inverse
|
||||
result->col(1).swap(result->col(good_row1));
|
||||
result->col(0).swap(result->col(good_row0));
|
||||
}
|
||||
|
||||
/***********************************************
|
||||
|
||||
@@ -508,7 +508,7 @@ bool LU<MatrixType>::solve(
|
||||
if(!isSurjective())
|
||||
{
|
||||
// is c is in the image of U ?
|
||||
RealScalar biggest_in_c = c.corner(TopLeft, m_rank, c.cols()).cwise().abs().maxCoeff();
|
||||
RealScalar biggest_in_c = m_rank>0 ? c.corner(TopLeft, m_rank, c.cols()).cwise().abs().maxCoeff() : 0;
|
||||
for(int col = 0; col < c.cols(); ++col)
|
||||
for(int row = m_rank; row < c.rows(); ++row)
|
||||
if(!ei_isMuchSmallerThan(c.coeff(row,col), biggest_in_c, m_precision))
|
||||
|
||||
@@ -61,6 +61,8 @@ template<typename MatrixType> class SVD
|
||||
|
||||
public:
|
||||
|
||||
SVD() {} // a user who relied on compiler-generated default compiler reported problems with MSVC in 2.0.7
|
||||
|
||||
SVD(const MatrixType& matrix)
|
||||
: m_matU(matrix.rows(), std::min(matrix.rows(), matrix.cols())),
|
||||
m_matV(matrix.cols(),matrix.cols()),
|
||||
@@ -107,6 +109,8 @@ void SVD<MatrixType>::compute(const MatrixType& matrix)
|
||||
const int m = matrix.rows();
|
||||
const int n = matrix.cols();
|
||||
const int nu = std::min(m,n);
|
||||
ei_assert(m>=n && "In Eigen 2.0, SVD only works for MxN matrices with M>=N. Sorry!");
|
||||
ei_assert(m>1 && "In Eigen 2.0, SVD doesn't work on 1x1 matrices");
|
||||
|
||||
m_matU.resize(m, nu);
|
||||
m_matU.setZero();
|
||||
|
||||
@@ -99,6 +99,8 @@ template<typename _Scalar> class AmbiVector
|
||||
allocSize = allocSize/sizeof(Scalar) + (allocSize%sizeof(Scalar)>0?1:0);
|
||||
Scalar* newBuffer = new Scalar[allocSize];
|
||||
memcpy(newBuffer, m_buffer, copyElements * sizeof(ListEl));
|
||||
delete[] m_buffer;
|
||||
m_buffer = newBuffer;
|
||||
}
|
||||
|
||||
protected:
|
||||
@@ -238,8 +240,11 @@ Scalar& AmbiVector<Scalar>::coeffRef(int i)
|
||||
else
|
||||
{
|
||||
if (m_llSize>=m_allocatedElements)
|
||||
{
|
||||
reallocateSparse();
|
||||
ei_internal_assert(m_llSize<m_size && "internal error: overflow in sparse mode");
|
||||
llElements = reinterpret_cast<ListEl*>(m_buffer);
|
||||
}
|
||||
ei_internal_assert(m_llSize<m_allocatedElements && "internal error: overflow in sparse mode");
|
||||
// let's insert a new coefficient
|
||||
ListEl& el = llElements[m_llSize];
|
||||
el.value = Scalar(0);
|
||||
@@ -365,6 +370,9 @@ class AmbiVector<_Scalar>::Iterator
|
||||
int m_cachedIndex; // current coordinate
|
||||
Scalar m_cachedValue; // current value
|
||||
bool m_isDense; // mode of the vector
|
||||
|
||||
private:
|
||||
Iterator& operator=(const Iterator&);
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -289,9 +289,11 @@ class DynamicSparseMatrix<Scalar,_Flags>::InnerIterator : public SparseVector<Sc
|
||||
inline int row() const { return IsRowMajor ? m_outer : Base::index(); }
|
||||
inline int col() const { return IsRowMajor ? Base::index() : m_outer; }
|
||||
|
||||
|
||||
protected:
|
||||
const int m_outer;
|
||||
|
||||
private:
|
||||
InnerIterator& operator=(const InnerIterator&);
|
||||
};
|
||||
|
||||
#endif // EIGEN_DYNAMIC_SPARSEMATRIX_H
|
||||
|
||||
@@ -53,6 +53,9 @@ class SparseInnerVectorSet : ei_no_assignment_operator,
|
||||
inline InnerIterator(const SparseInnerVectorSet& xpr, int outer)
|
||||
: MatrixType::InnerIterator(xpr.m_matrix, xpr.m_outerStart + outer)
|
||||
{}
|
||||
|
||||
private:
|
||||
InnerIterator& operator=(const InnerIterator&);
|
||||
};
|
||||
|
||||
inline SparseInnerVectorSet(const MatrixType& matrix, int outerStart, int outerSize)
|
||||
@@ -110,6 +113,8 @@ class SparseInnerVectorSet<DynamicSparseMatrix<_Scalar, _Options>, Size>
|
||||
inline InnerIterator(const SparseInnerVectorSet& xpr, int outer)
|
||||
: MatrixType::InnerIterator(xpr.m_matrix, xpr.m_outerStart + outer)
|
||||
{}
|
||||
private:
|
||||
InnerIterator& operator=(const InnerIterator&);
|
||||
};
|
||||
|
||||
inline SparseInnerVectorSet(const MatrixType& matrix, int outerStart, int outerSize)
|
||||
|
||||
@@ -156,6 +156,9 @@ template<typename ExpressionType> class SparseCwise
|
||||
|
||||
protected:
|
||||
ExpressionTypeNested m_matrix;
|
||||
|
||||
private:
|
||||
SparseCwise& operator=(const SparseCwise&);
|
||||
};
|
||||
|
||||
template<typename Derived>
|
||||
|
||||
@@ -126,6 +126,8 @@ class SparseCwiseBinaryOp<BinaryOp,Lhs,Rhs>::InnerIterator
|
||||
EIGEN_STRONG_INLINE InnerIterator(const SparseCwiseBinaryOp& binOp, int outer)
|
||||
: Base(binOp,outer)
|
||||
{}
|
||||
private:
|
||||
InnerIterator& operator=(const InnerIterator&);
|
||||
};
|
||||
|
||||
/***************************************************************************
|
||||
@@ -197,6 +199,9 @@ class ei_sparse_cwise_binary_op_inner_iterator_selector<BinaryOp, Lhs, Rhs, Deri
|
||||
const BinaryOp& m_functor;
|
||||
Scalar m_value;
|
||||
int m_id;
|
||||
|
||||
private:
|
||||
ei_sparse_cwise_binary_op_inner_iterator_selector& operator=(const ei_sparse_cwise_binary_op_inner_iterator_selector&);
|
||||
};
|
||||
|
||||
// sparse - sparse (product)
|
||||
@@ -250,6 +255,9 @@ class ei_sparse_cwise_binary_op_inner_iterator_selector<ei_scalar_product_op<T>,
|
||||
LhsIterator m_lhsIter;
|
||||
RhsIterator m_rhsIter;
|
||||
const BinaryFunc& m_functor;
|
||||
|
||||
private:
|
||||
ei_sparse_cwise_binary_op_inner_iterator_selector& operator=(const ei_sparse_cwise_binary_op_inner_iterator_selector&);
|
||||
};
|
||||
|
||||
// sparse - dense (product)
|
||||
@@ -290,6 +298,9 @@ class ei_sparse_cwise_binary_op_inner_iterator_selector<ei_scalar_product_op<T>,
|
||||
LhsIterator m_lhsIter;
|
||||
const BinaryFunc m_functor;
|
||||
const int m_outer;
|
||||
|
||||
private:
|
||||
ei_sparse_cwise_binary_op_inner_iterator_selector& operator=(const ei_sparse_cwise_binary_op_inner_iterator_selector&);
|
||||
};
|
||||
|
||||
// sparse - dense (product)
|
||||
|
||||
@@ -90,6 +90,9 @@ class SparseCwiseUnaryOp<UnaryOp,MatrixType>::InnerIterator
|
||||
protected:
|
||||
MatrixTypeIterator m_iter;
|
||||
const UnaryOp m_functor;
|
||||
|
||||
private:
|
||||
InnerIterator& operator=(const InnerIterator&);
|
||||
};
|
||||
|
||||
template<typename Derived>
|
||||
|
||||
@@ -120,6 +120,8 @@ class ei_sparse_diagonal_product_inner_iterator_selector
|
||||
const SparseDiagonalProductType& expr, int outer)
|
||||
: Base(expr.rhs().innerVector(outer) .cwise()* expr.lhs().diagonal(), 0)
|
||||
{}
|
||||
private:
|
||||
ei_sparse_diagonal_product_inner_iterator_selector& operator=(const ei_sparse_diagonal_product_inner_iterator_selector&);
|
||||
};
|
||||
|
||||
template<typename Lhs, typename Rhs, typename SparseDiagonalProductType>
|
||||
|
||||
@@ -64,16 +64,21 @@ template<typename ExpressionType, unsigned int Added, unsigned int Removed> clas
|
||||
|
||||
protected:
|
||||
ExpressionTypeNested m_matrix;
|
||||
|
||||
private:
|
||||
SparseFlagged& operator=(const SparseFlagged&);
|
||||
};
|
||||
|
||||
template<typename ExpressionType, unsigned int Added, unsigned int Removed>
|
||||
class SparseFlagged<ExpressionType,Added,Removed>::InnerIterator : public ExpressionType::InnerIterator
|
||||
{
|
||||
public:
|
||||
|
||||
EIGEN_STRONG_INLINE InnerIterator(const SparseFlagged& xpr, int outer)
|
||||
: ExpressionType::InnerIterator(xpr.m_matrix, outer)
|
||||
{}
|
||||
|
||||
private:
|
||||
InnerIterator& operator=(const InnerIterator&);
|
||||
};
|
||||
|
||||
template<typename ExpressionType, unsigned int Added, unsigned int Removed>
|
||||
|
||||
@@ -259,19 +259,21 @@ class SparseMatrix
|
||||
m_data.resize(k,0);
|
||||
}
|
||||
|
||||
/** Resizes the matrix to a \a rows x \a cols matrix and initializes it to zero
|
||||
* \sa resizeNonZeros(int), reserve(), setZero()
|
||||
*/
|
||||
void resize(int rows, int cols)
|
||||
{
|
||||
// std::cerr << this << " resize " << rows << "x" << cols << "\n";
|
||||
const int outerSize = IsRowMajor ? rows : cols;
|
||||
m_innerSize = IsRowMajor ? cols : rows;
|
||||
m_data.clear();
|
||||
if (m_outerSize != outerSize)
|
||||
if (m_outerSize != outerSize || m_outerSize==0)
|
||||
{
|
||||
delete[] m_outerIndex;
|
||||
m_outerIndex = new int [outerSize+1];
|
||||
m_outerSize = outerSize;
|
||||
memset(m_outerIndex, 0, (m_outerSize+1)*sizeof(int));
|
||||
}
|
||||
memset(m_outerIndex, 0, (m_outerSize+1)*sizeof(int));
|
||||
}
|
||||
void resizeNonZeros(int size)
|
||||
{
|
||||
@@ -442,6 +444,9 @@ class SparseMatrix<Scalar,_Flags>::InnerIterator
|
||||
int m_id;
|
||||
const int m_start;
|
||||
const int m_end;
|
||||
|
||||
private:
|
||||
InnerIterator& operator=(const InnerIterator&);
|
||||
};
|
||||
|
||||
#endif // EIGEN_SPARSEMATRIX_H
|
||||
|
||||
@@ -62,15 +62,20 @@ template<typename MatrixType> class SparseTranspose
|
||||
|
||||
protected:
|
||||
const typename MatrixType::Nested m_matrix;
|
||||
|
||||
private:
|
||||
SparseTranspose& operator=(const SparseTranspose&);
|
||||
};
|
||||
|
||||
template<typename MatrixType> class SparseTranspose<MatrixType>::InnerIterator : public MatrixType::InnerIterator
|
||||
{
|
||||
public:
|
||||
|
||||
EIGEN_STRONG_INLINE InnerIterator(const SparseTranspose& trans, int outer)
|
||||
: MatrixType::InnerIterator(trans.m_matrix, outer)
|
||||
{}
|
||||
|
||||
private:
|
||||
InnerIterator& operator=(const InnerIterator&);
|
||||
};
|
||||
|
||||
template<typename MatrixType> class SparseTranspose<MatrixType>::ReverseInnerIterator : public MatrixType::ReverseInnerIterator
|
||||
|
||||
@@ -360,6 +360,9 @@ class SparseVector<Scalar,_Flags>::InnerIterator
|
||||
const CompressedStorage<Scalar>& m_data;
|
||||
int m_id;
|
||||
const int m_end;
|
||||
|
||||
private:
|
||||
InnerIterator& operator=(const InnerIterator&);
|
||||
};
|
||||
|
||||
#endif // EIGEN_SPARSEVECTOR_H
|
||||
|
||||
@@ -38,7 +38,6 @@ add_custom_target(
|
||||
${CMAKE_CURRENT_BINARY_DIR}/html/
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/Eigen_Silly_Professor_64x64.png
|
||||
${CMAKE_CURRENT_BINARY_DIR}/html/
|
||||
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/buildexamplelist.sh ${Eigen_SOURCE_DIR} > ${CMAKE_CURRENT_BINARY_DIR}/ExampleList.dox
|
||||
COMMAND doxygen
|
||||
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/cleanhierarchy.sh ${CMAKE_CURRENT_BINARY_DIR}/html/hierarchy.html
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||
|
||||
@@ -81,7 +81,7 @@ In order to add support for a custom type \c T you need:
|
||||
3 - define a couple of math functions for your type such as: ei_sqrt, ei_abs, etc...
|
||||
(see the file Eigen/src/Core/MathFunctions.h)
|
||||
|
||||
Here is a concrete example adding support for the Adolc's \c adouble type. <a href="http://www.math.tu-dresden.de/~adol-c/">Adolc</a> is an automatic differentiation library. The type \c adouble is basically a real value tracking the values of any number of partial derivatives.
|
||||
Here is a concrete example adding support for the Adolc's \c adouble type. <a href="https://projects.coin-or.org/ADOL-C">Adolc</a> is an automatic differentiation library. The type \c adouble is basically a real value tracking the values of any number of partial derivatives.
|
||||
|
||||
\code
|
||||
#ifndef ADLOCSUPPORT_H
|
||||
|
||||
@@ -15,7 +15,7 @@ For a first contact with Eigen, the best place is to have a look at the \ref Tut
|
||||
|
||||
Most of the API is available as methods in MatrixBase, so this is a good starting point for browsing. Also have a look at Matrix, as a few methods and the matrix constructors are there. Other notable classes for the Eigen API are Cwise, which contains the methods for doing certain coefficient-wise operations, and Part.
|
||||
|
||||
In fact, except for advanced use, the only class that you'll have to explicitly name in your program, i.e. of which you'll explicitly contruct objects, is Matrix. For instance, vectors are handled as a special case of Matrix with one column. Typedefs are provided, e.g. Vector2f is a typedef for Matrix<float, 2, 1>. Finally, you might also have look at the \ref ExampleList "the list of selected examples".
|
||||
In fact, except for advanced use, the only class that you'll have to explicitly name in your program, i.e. of which you'll explicitly contruct objects, is Matrix. For instance, vectors are handled as a special case of Matrix with one column. Typedefs are provided, e.g. Vector2f is a typedef for Matrix<float, 2, 1>.
|
||||
|
||||
Most of the other classes are just return types for MatrixBase methods.
|
||||
|
||||
|
||||
@@ -229,17 +229,24 @@ Of course, fixed-size matrices can't be resized.
|
||||
|
||||
|
||||
\subsection TutorialMap Map
|
||||
Any memory buffer can be mapped as an Eigen expression:
|
||||
<table class="tutorial_code"><tr><td>
|
||||
Any memory buffer can be mapped as an Eigen expression using the Map() static method:
|
||||
\code
|
||||
std::vector<float> stlarray(10);
|
||||
Map<VectorXf>(&stlarray[0], stlarray.size()).setOnes();
|
||||
int data[4] = 1, 2, 3, 4;
|
||||
Matrix2i mat2x2(data);
|
||||
MatrixXi mat2x2 = Map<Matrix2i>(data);
|
||||
MatrixXi mat2x2 = Map<MatrixXi>(data,2,2);
|
||||
VectorXf::Map(&stlarray[0], stlarray.size()).squaredNorm();
|
||||
\endcode
|
||||
Here VectorXf::Map returns an object of class Map<VectorXf>, which behaves like a VectorXf except that it uses the existing array. You can write to this object, that will write to the existing array. You can also construct a named obtect to reuse it:
|
||||
\code
|
||||
float array[rows*cols];
|
||||
Map<MatrixXf> m(array,rows,cols);
|
||||
m = othermatrix1 * othermatrix2;
|
||||
m.eigenvalues();
|
||||
\endcode
|
||||
In the fixed-size case, no need to pass sizes:
|
||||
\code
|
||||
float array[9];
|
||||
Map<Matrix3d> m(array);
|
||||
Matrix3d::Map(array).setIdentity();
|
||||
\endcode
|
||||
</td></tr></table>
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -6,6 +6,8 @@ namespace Eigen {
|
||||
- \ref summary
|
||||
- \ref allocator
|
||||
- \ref vector
|
||||
- \ref newvector
|
||||
|
||||
|
||||
\section summary Executive summary
|
||||
|
||||
@@ -44,6 +46,18 @@ std::vector<Eigen::Vector4f>
|
||||
\endcode
|
||||
without having to worry about anything.
|
||||
|
||||
\section newvector The new and improved workaround for std::vector
|
||||
|
||||
Well, except that in Eigen 2.0 the <Eigen/StdVector> header causes some compatibility issues as it reimplements the std::vector<T> container in a not-fully-compatible way. If you want to avoid these issues, starting in Eigen 2.0.6 a new implementation is available, which will become default in the next major version of Eigen. You can enable it by defining EIGEN_USE_NEW_STDVECTOR:
|
||||
|
||||
\code
|
||||
#define EIGEN_USE_NEW_STDVECTOR
|
||||
#include<Eigen/StdVector>
|
||||
\endcode
|
||||
|
||||
This new implementation <a href="http://eigen.tuxfamily.org/dox-devel/StlContainers.html#vector">is documented here</a>. In particular, note that if you use it, you must specify Eigen::aligned_allocator<T> as the allocator type, otherwise it doesn't make any difference from the standard std::vector. This new std::vector implementation \b only overrides the standard one if used with this allocator, which guarantees that it doesn't break existing non-Eigen code.
|
||||
|
||||
|
||||
<span class="note">\b Explanation: The resize() method of std::vector takes a value_type argument (defaulting to value_type()). So with std::vector<Eigen::Vector4f>, some Eigen::Vector4f objects will be passed by value, which discards any alignment modifiers, so a Eigen::Vector4f can be created at an unaligned location. In order to avoid that, the only solution we saw was to specialize std::vector to make it work on a slight modification of, here, Eigen::Vector4f, that is able to deal properly with this situation.
|
||||
</span>
|
||||
|
||||
|
||||
@@ -152,7 +152,7 @@ OpenGL compatibility \b 3D </td><td>\code
|
||||
glLoadMatrixf(t.data());\endcode</td></tr>
|
||||
<tr><td>
|
||||
OpenGL compatibility \b 2D </td><td>\code
|
||||
Transform3f aux(Transform3f::Identity);
|
||||
Transform3f aux(Transform3f::Identity());
|
||||
aux.linear().corner<2,2>(TopLeft) = t.linear();
|
||||
aux.translation().start<2>() = t.translation();
|
||||
glLoadMatrixf(aux.data());\endcode</td></tr>
|
||||
|
||||
@@ -12,7 +12,7 @@ is explained here: http://eigen.tuxfamily.org/dox/UnalignedArrayAssert.html
|
||||
**** READ THIS WEB PAGE !!! ****"' failed.
|
||||
</pre>
|
||||
|
||||
There are 3 known causes for this issue. Please read on to understand them and learn how to fix them.
|
||||
There are 4 known causes for this issue. Please read on to understand them and learn how to fix them.
|
||||
|
||||
\b Table \b of \b contents
|
||||
- \ref where
|
||||
@@ -21,6 +21,7 @@ There are 3 known causes for this issue. Please read on to understand them and l
|
||||
- \ref c3
|
||||
- \ref c4
|
||||
- \ref explanation
|
||||
- \ref getrid
|
||||
|
||||
\section where Where in my own code is the cause of the problem?
|
||||
|
||||
@@ -101,6 +102,16 @@ Eigen normally takes care of these alignment issues for you, by setting an align
|
||||
|
||||
However there are a few corner cases where these alignment settings get overridden: they are the possible causes for this assertion.
|
||||
|
||||
\section getrid I don't care about vectorization, how do I get rid of that stuff?
|
||||
|
||||
Two possibilities:
|
||||
<ul>
|
||||
<li>Define EIGEN_DONT_ALIGN. That disables all 128-bit alignment code, and in particular everything vectorization-related. But do note that this in particular breaks ABI compatibility with vectorized code.</li>
|
||||
<li>Or define both EIGEN_DONT_VECTORIZE and EIGEN_DISABLE_UNALIGNED_ARRAY_ASSERT. This keeps the 128-bit alignment code and thus preserves ABI compatibility.</li>
|
||||
</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>.
|
||||
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
7
eigen2.pc.in
Normal file
7
eigen2.pc.in
Normal file
@@ -0,0 +1,7 @@
|
||||
|
||||
Name: Eigen2
|
||||
Description: A C++ template library for linear algebra: vectors, matrices, and related algorithms
|
||||
Requires:
|
||||
Version: ${EIGEN_VERSION_NUMBER}
|
||||
Libs:
|
||||
Cflags: -I${INCLUDE_INSTALL_DIR}
|
||||
26
scripts/eigen_gen_docs
Normal file
26
scripts/eigen_gen_docs
Normal file
@@ -0,0 +1,26 @@
|
||||
#!/bin/sh
|
||||
|
||||
# TODO : actually exit on exit, currently it only exit from the ()
|
||||
# TODO : display error msg on stderr instead of stdout
|
||||
|
||||
# configuration
|
||||
# You should call this script with USER set as you want, else some default
|
||||
# will be used
|
||||
USER=${USER:-'orzel'}
|
||||
|
||||
# step 1 : build
|
||||
# todo if 'build is not there, create one:
|
||||
#mkdir build
|
||||
(cd build && cmake .. && make -j3 doc) || (echo "make failed"; exit 1)
|
||||
#todo: n+1 where n = number of cpus
|
||||
|
||||
#step 2 : upload
|
||||
BRANCH=`hg branch`
|
||||
if [ $BRANCH == "default" ]
|
||||
then
|
||||
BRANCH='devel'
|
||||
fi
|
||||
# (the '/' at the end of path are very important, see rsync documentation)
|
||||
rsync -az build/doc/html/ $USER@ssh.tuxfamily.org:eigen/eigen.tuxfamily.org-web/htdocs/dox-$BRANCH/ || (echo "upload failed"; exit 1)
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ else(CHOLMOD_FOUND)
|
||||
set(EIGEN_MISSING_BACKENDS ${EIGEN_MISSING_BACKENDS} Cholmod)
|
||||
endif(CHOLMOD_FOUND)
|
||||
|
||||
option(EIGEN_TEST_NO_FORTRAN "Disable Fortran" OFF)
|
||||
option(EIGEN_TEST_NO_FORTRAN "Disable Fortran" ON)
|
||||
if(NOT MSVC AND NOT EIGEN_TEST_NO_FORTRAN)
|
||||
enable_language(Fortran OPTIONAL)
|
||||
endif(NOT MSVC AND NOT EIGEN_TEST_NO_FORTRAN)
|
||||
@@ -211,13 +211,18 @@ ei_add_test(parametrizedline)
|
||||
ei_add_test(alignedbox)
|
||||
ei_add_test(regression)
|
||||
ei_add_test(stdvector)
|
||||
ei_add_test(newstdvector)
|
||||
if(QT4_FOUND)
|
||||
ei_add_test(qtvector " " ${QT_QTCORE_LIBRARY})
|
||||
ei_add_test(qtvector " " "${QT_QTCORE_LIBRARY}")
|
||||
endif(QT4_FOUND)
|
||||
ei_add_test(sparse_vector)
|
||||
ei_add_test(sparse_basic)
|
||||
ei_add_test(sparse_solvers " " "${SPARSE_LIBS}")
|
||||
ei_add_test(sparse_product)
|
||||
ei_add_test(swap)
|
||||
ei_add_test(visitor)
|
||||
|
||||
ei_add_test(prec_inverse_4x4 ${EI_OFLAG})
|
||||
|
||||
# print a summary of the different options
|
||||
message("************************************************************")
|
||||
|
||||
@@ -151,7 +151,13 @@ template<typename Scalar> void geometry(void)
|
||||
a = ei_random<Scalar>(-Scalar(0.4)*Scalar(M_PI), Scalar(0.4)*Scalar(M_PI));
|
||||
q1 = AngleAxisx(a, v0.normalized());
|
||||
Transform3 t0, t1, t2;
|
||||
// first test setIdentity() and Identity()
|
||||
t0.setIdentity();
|
||||
VERIFY_IS_APPROX(t0.matrix(), Transform3::MatrixType::Identity());
|
||||
t0.matrix().setZero();
|
||||
t0 = Transform3::Identity();
|
||||
VERIFY_IS_APPROX(t0.matrix(), Transform3::MatrixType::Identity());
|
||||
|
||||
t0.linear() = q1.toRotationMatrix();
|
||||
t1.setIdentity();
|
||||
t1.linear() = q1.toRotationMatrix();
|
||||
|
||||
@@ -121,7 +121,8 @@ template<typename Scalar> void lines()
|
||||
VERIFY_IS_APPROX(result, center);
|
||||
|
||||
// check conversions between two types of lines
|
||||
CoeffsType converted_coeffs(HLine(PLine(line_u)).coeffs());
|
||||
PLine pl(line_u); // gcc 3.3 will commit suicide if we don't name this variable
|
||||
CoeffsType converted_coeffs(HLine(pl).coeffs());
|
||||
converted_coeffs *= line_u.coeffs()(0)/converted_coeffs(0);
|
||||
VERIFY(line_u.coeffs().isApprox(converted_coeffs));
|
||||
}
|
||||
|
||||
164
test/newstdvector.cpp
Normal file
164
test/newstdvector.cpp
Normal file
@@ -0,0 +1,164 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// Eigen is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 3 of the License, or (at your option) any later version.
|
||||
//
|
||||
// Alternatively, you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of
|
||||
// the License, or (at your option) any later version.
|
||||
//
|
||||
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License and a copy of the GNU General Public License along with
|
||||
// Eigen. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#define EIGEN_USE_NEW_STDVECTOR
|
||||
#include "main.h"
|
||||
#include <Eigen/StdVector>
|
||||
#include <Eigen/Geometry>
|
||||
|
||||
template<typename MatrixType>
|
||||
void check_stdvector_matrix(const MatrixType& m)
|
||||
{
|
||||
int rows = m.rows();
|
||||
int cols = m.cols();
|
||||
MatrixType x = MatrixType::Random(rows,cols), y = MatrixType::Random(rows,cols);
|
||||
std::vector<MatrixType,Eigen::aligned_allocator<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);
|
||||
VERIFY((size_t)&(v[22]) == (size_t)&(v[21]) + sizeof(MatrixType));
|
||||
|
||||
// do a lot of push_back such that the vector 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_stdvector_transform(const TransformType&)
|
||||
{
|
||||
typedef typename TransformType::MatrixType MatrixType;
|
||||
TransformType x(MatrixType::Random()), y(MatrixType::Random());
|
||||
std::vector<TransformType,Eigen::aligned_allocator<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);
|
||||
VERIFY((size_t)&(v[22]) == (size_t)&(v[21]) + sizeof(TransformType));
|
||||
|
||||
// do a lot of push_back such that the vector 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_stdvector_quaternion(const QuaternionType&)
|
||||
{
|
||||
typedef typename QuaternionType::Coefficients Coefficients;
|
||||
QuaternionType x(Coefficients::Random()), y(Coefficients::Random());
|
||||
std::vector<QuaternionType,Eigen::aligned_allocator<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);
|
||||
VERIFY((size_t)&(v[22]) == (size_t)&(v[21]) + sizeof(QuaternionType));
|
||||
|
||||
// do a lot of push_back such that the vector 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_newstdvector()
|
||||
{
|
||||
// some non vectorizable fixed sizes
|
||||
CALL_SUBTEST(check_stdvector_matrix(Vector2f()));
|
||||
CALL_SUBTEST(check_stdvector_matrix(Matrix3f()));
|
||||
CALL_SUBTEST(check_stdvector_matrix(Matrix3d()));
|
||||
|
||||
// some vectorizable fixed sizes
|
||||
CALL_SUBTEST(check_stdvector_matrix(Matrix2f()));
|
||||
CALL_SUBTEST(check_stdvector_matrix(Vector4f()));
|
||||
CALL_SUBTEST(check_stdvector_matrix(Matrix4f()));
|
||||
CALL_SUBTEST(check_stdvector_matrix(Matrix4d()));
|
||||
|
||||
// some dynamic sizes
|
||||
CALL_SUBTEST(check_stdvector_matrix(MatrixXd(1,1)));
|
||||
CALL_SUBTEST(check_stdvector_matrix(VectorXd(20)));
|
||||
CALL_SUBTEST(check_stdvector_matrix(RowVectorXf(20)));
|
||||
CALL_SUBTEST(check_stdvector_matrix(MatrixXcf(10,10)));
|
||||
|
||||
// some Transform
|
||||
CALL_SUBTEST(check_stdvector_transform(Transform2f()));
|
||||
CALL_SUBTEST(check_stdvector_transform(Transform3f()));
|
||||
CALL_SUBTEST(check_stdvector_transform(Transform3d()));
|
||||
//CALL_SUBTEST(check_stdvector_transform(Transform4d()));
|
||||
|
||||
// some Quaternion
|
||||
CALL_SUBTEST(check_stdvector_quaternion(Quaternionf()));
|
||||
CALL_SUBTEST(check_stdvector_quaternion(Quaterniond()));
|
||||
}
|
||||
103
test/prec_inverse_4x4.cpp
Normal file
103
test/prec_inverse_4x4.cpp
Normal file
@@ -0,0 +1,103 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2009 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// Eigen is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 3 of the License, or (at your option) any later version.
|
||||
//
|
||||
// Alternatively, you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of
|
||||
// the License, or (at your option) any later version.
|
||||
//
|
||||
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License and a copy of the GNU General Public License along with
|
||||
// Eigen. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "main.h"
|
||||
#include <Eigen/LU>
|
||||
#include <algorithm>
|
||||
|
||||
template<typename T> std::string type_name() { return "other"; }
|
||||
template<> std::string type_name<float>() { return "float"; }
|
||||
template<> std::string type_name<double>() { return "double"; }
|
||||
template<> std::string type_name<int>() { return "int"; }
|
||||
template<> std::string type_name<std::complex<float> >() { return "complex<float>"; }
|
||||
template<> std::string type_name<std::complex<double> >() { return "complex<double>"; }
|
||||
template<> std::string type_name<std::complex<int> >() { return "complex<int>"; }
|
||||
|
||||
#define EIGEN_DEBUG_VAR(x) std::cerr << #x << " = " << x << std::endl;
|
||||
|
||||
template<typename T> inline typename NumTraits<T>::Real epsilon()
|
||||
{
|
||||
return std::numeric_limits<typename NumTraits<T>::Real>::epsilon();
|
||||
}
|
||||
|
||||
template<typename MatrixType> void inverse_permutation_4x4()
|
||||
{
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
typedef typename MatrixType::RealScalar RealScalar;
|
||||
double error_max = 0.;
|
||||
Vector4i indices(0,1,2,3);
|
||||
for(int i = 0; i < 24; ++i)
|
||||
{
|
||||
MatrixType m = MatrixType::Zero();
|
||||
m(indices(0),0) = 1;
|
||||
m(indices(1),1) = 1;
|
||||
m(indices(2),2) = 1;
|
||||
m(indices(3),3) = 1;
|
||||
MatrixType inv = m.inverse();
|
||||
double error = double( (m*inv-MatrixType::Identity()).norm() / epsilon<Scalar>() );
|
||||
error_max = std::max(error_max, error);
|
||||
std::next_permutation(indices.data(),indices.data()+4);
|
||||
}
|
||||
std::cerr << "inverse_permutation_4x4, Scalar = " << type_name<Scalar>() << std::endl;
|
||||
EIGEN_DEBUG_VAR(error_max);
|
||||
VERIFY(error_max < 1. );
|
||||
}
|
||||
|
||||
template<typename MatrixType> void inverse_general_4x4(int repeat)
|
||||
{
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
typedef typename MatrixType::RealScalar RealScalar;
|
||||
double error_sum = 0., error_max = 0.;
|
||||
for(int i = 0; i < repeat; ++i)
|
||||
{
|
||||
MatrixType m;
|
||||
RealScalar absdet;
|
||||
do {
|
||||
m = MatrixType::Random();
|
||||
absdet = ei_abs(m.determinant());
|
||||
} while(absdet < 10 * epsilon<Scalar>());
|
||||
MatrixType inv = m.inverse();
|
||||
double error = double( (m*inv-MatrixType::Identity()).norm() * absdet / epsilon<Scalar>() );
|
||||
error_sum += error;
|
||||
error_max = std::max(error_max, error);
|
||||
}
|
||||
std::cerr << "inverse_general_4x4, Scalar = " << type_name<Scalar>() << std::endl;
|
||||
double error_avg = error_sum / repeat;
|
||||
EIGEN_DEBUG_VAR(error_avg);
|
||||
EIGEN_DEBUG_VAR(error_max);
|
||||
VERIFY(error_avg < (NumTraits<Scalar>::IsComplex ? 8.4 : 1.4) );
|
||||
VERIFY(error_max < (NumTraits<Scalar>::IsComplex ? 160.0 : 75.) );
|
||||
}
|
||||
|
||||
void test_prec_inverse_4x4()
|
||||
{
|
||||
CALL_SUBTEST((inverse_permutation_4x4<Matrix4f>()));
|
||||
CALL_SUBTEST(( inverse_general_4x4<Matrix4f>(200000 * g_repeat) ));
|
||||
|
||||
CALL_SUBTEST((inverse_permutation_4x4<Matrix<double,4,4,RowMajor> >()));
|
||||
CALL_SUBTEST(( inverse_general_4x4<Matrix<double,4,4,RowMajor> >(200000 * g_repeat) ));
|
||||
|
||||
CALL_SUBTEST((inverse_permutation_4x4<Matrix4cf>()));
|
||||
CALL_SUBTEST((inverse_general_4x4<Matrix4cf>(50000 * g_repeat)));
|
||||
}
|
||||
@@ -26,10 +26,12 @@
|
||||
#define EIGEN_WORK_AROUND_QT_BUG_CALLING_WRONG_OPERATOR_NEW_FIXED_IN_QT_4_5
|
||||
|
||||
#include "main.h"
|
||||
#include <QtCore/QVector>
|
||||
|
||||
#include <Eigen/Geometry>
|
||||
#include <Eigen/QtAlignedMalloc>
|
||||
|
||||
#include <QtCore/QVector>
|
||||
|
||||
template<typename MatrixType>
|
||||
void check_qtvector_matrix(const MatrixType& m)
|
||||
{
|
||||
|
||||
@@ -95,5 +95,8 @@ void test_svd()
|
||||
// complex are not implemented yet
|
||||
// CALL_SUBTEST( svd(MatrixXcd(6,6)) );
|
||||
// CALL_SUBTEST( svd(MatrixXcf(3,3)) );
|
||||
SVD<MatrixXf> s;
|
||||
MatrixXf m = MatrixXf::Random(10,1);
|
||||
s.compute(m);
|
||||
}
|
||||
}
|
||||
|
||||
98
test/swap.cpp
Normal file
98
test/swap.cpp
Normal file
@@ -0,0 +1,98 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2009 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// Eigen is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 3 of the License, or (at your option) any later version.
|
||||
//
|
||||
// Alternatively, you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of
|
||||
// the License, or (at your option) any later version.
|
||||
//
|
||||
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License and a copy of the GNU General Public License along with
|
||||
// Eigen. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#define EIGEN_NO_STATIC_ASSERT
|
||||
#include "main.h"
|
||||
|
||||
template<typename T>
|
||||
struct other_matrix_type
|
||||
{
|
||||
typedef int type;
|
||||
};
|
||||
|
||||
template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
|
||||
struct other_matrix_type<Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols> >
|
||||
{
|
||||
typedef Matrix<_Scalar, _Rows, _Cols, _Options^RowMajor, _MaxRows, _MaxCols> type;
|
||||
};
|
||||
|
||||
template<typename MatrixType> void swap(const MatrixType& m)
|
||||
{
|
||||
typedef typename other_matrix_type<MatrixType>::type OtherMatrixType;
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
|
||||
ei_assert((!ei_is_same_type<MatrixType,OtherMatrixType>::ret));
|
||||
int rows = m.rows();
|
||||
int cols = m.cols();
|
||||
|
||||
// construct 3 matrix guaranteed to be distinct
|
||||
MatrixType m1 = MatrixType::Random(rows,cols);
|
||||
MatrixType m2 = MatrixType::Random(rows,cols) + Scalar(100) * MatrixType::Identity(rows,cols);
|
||||
OtherMatrixType m3 = OtherMatrixType::Random(rows,cols) + Scalar(200) * OtherMatrixType::Identity(rows,cols);
|
||||
|
||||
MatrixType m1_copy = m1;
|
||||
MatrixType m2_copy = m2;
|
||||
OtherMatrixType m3_copy = m3;
|
||||
|
||||
// test swapping 2 matrices of same type
|
||||
m1.swap(m2);
|
||||
VERIFY_IS_APPROX(m1,m2_copy);
|
||||
VERIFY_IS_APPROX(m2,m1_copy);
|
||||
m1 = m1_copy;
|
||||
m2 = m2_copy;
|
||||
|
||||
// test swapping 2 matrices of different types
|
||||
m1.swap(m3);
|
||||
VERIFY_IS_APPROX(m1,m3_copy);
|
||||
VERIFY_IS_APPROX(m3,m1_copy);
|
||||
m1 = m1_copy;
|
||||
m3 = m3_copy;
|
||||
|
||||
// test swapping matrix with expression
|
||||
m1.swap(m2.block(0,0,rows,cols));
|
||||
VERIFY_IS_APPROX(m1,m2_copy);
|
||||
VERIFY_IS_APPROX(m2,m1_copy);
|
||||
m1 = m1_copy;
|
||||
m2 = m2_copy;
|
||||
|
||||
// test swapping two expressions of different types
|
||||
m1.transpose().swap(m3.transpose());
|
||||
VERIFY_IS_APPROX(m1,m3_copy);
|
||||
VERIFY_IS_APPROX(m3,m1_copy);
|
||||
m1 = m1_copy;
|
||||
m3 = m3_copy;
|
||||
|
||||
// test assertion on mismatching size -- matrix case
|
||||
VERIFY_RAISES_ASSERT(m1.swap(m1.row(0)));
|
||||
// test assertion on mismatching size -- xpr case
|
||||
VERIFY_RAISES_ASSERT(m1.row(0).swap(m1));
|
||||
}
|
||||
|
||||
void test_swap()
|
||||
{
|
||||
CALL_SUBTEST( swap(Matrix3f()) ); // fixed size, no vectorization
|
||||
CALL_SUBTEST( swap(Matrix4d()) ); // fixed size, possible vectorization
|
||||
CALL_SUBTEST( swap(MatrixXd(3,3)) ); // dyn size, no vectorization
|
||||
CALL_SUBTEST( swap(MatrixXf(30,30)) ); // dyn size, possible vectorization
|
||||
}
|
||||
@@ -39,7 +39,7 @@
|
||||
# VERSION=opensuse-11.1
|
||||
# WORK_DIR=/home/gael/Coding/eigen2/cdash
|
||||
# # get the last version of the script
|
||||
# wget http://bitbucket.org/eigen/eigen2/raw/tip/test/testsuite.cmake -o $WORK_DIR/testsuite.cmake
|
||||
# wget http://bitbucket.org/eigen/eigen/raw/tip/test/testsuite.cmake -o $WORK_DIR/testsuite.cmake
|
||||
# COMMON="ctest -S $WORK_DIR/testsuite.cmake,EIGEN_WORK_DIR=$WORK_DIR,EIGEN_SITE=$SITE,EIGEN_MODE=$1,EIGEN_BUILD_STRING=$OS_VERSION-$ARCH"
|
||||
# $COMMON-gcc-3.4.6,EIGEN_CXX=g++-3.4
|
||||
# $COMMON-gcc-4.0.1,EIGEN_CXX=g++-4.0.1
|
||||
@@ -133,7 +133,7 @@ endif(NOT EIGEN_MODE)
|
||||
## mandatory variables (the default should be ok in most cases):
|
||||
|
||||
SET (CTEST_CVS_COMMAND "hg")
|
||||
SET (CTEST_CVS_CHECKOUT "${CTEST_CVS_COMMAND} clone -r 2.0 http://bitbucket.org/eigen/eigen2 \"${CTEST_SOURCE_DIRECTORY}\"")
|
||||
SET (CTEST_CVS_CHECKOUT "${CTEST_CVS_COMMAND} clone -r 2.0 http://bitbucket.org/eigen/eigen \"${CTEST_SOURCE_DIRECTORY}\"")
|
||||
|
||||
# which ctest command to use for running the dashboard
|
||||
SET (CTEST_COMMAND "${EIGEN_CMAKE_DIR}ctest -D ${EIGEN_MODE}")
|
||||
|
||||
131
test/visitor.cpp
Normal file
131
test/visitor.cpp
Normal file
@@ -0,0 +1,131 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// Eigen is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 3 of the License, or (at your option) any later version.
|
||||
//
|
||||
// Alternatively, you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of
|
||||
// the License, or (at your option) any later version.
|
||||
//
|
||||
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License and a copy of the GNU General Public License along with
|
||||
// Eigen. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "main.h"
|
||||
|
||||
template<typename MatrixType> void matrixVisitor(const MatrixType& p)
|
||||
{
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
|
||||
int rows = p.rows();
|
||||
int cols = p.cols();
|
||||
|
||||
// construct a random matrix where all coefficients are different
|
||||
MatrixType m;
|
||||
m = MatrixType::Random(rows, cols);
|
||||
for(int i = 0; i < m.size(); i++)
|
||||
for(int i2 = 0; i2 < i; i2++)
|
||||
while(m(i) == m(i2)) // yes, ==
|
||||
m(i) = ei_random<Scalar>();
|
||||
|
||||
Scalar minc = Scalar(1000), maxc = Scalar(-1000);
|
||||
int minrow=0,mincol=0,maxrow=0,maxcol=0;
|
||||
for(int j = 0; j < cols; j++)
|
||||
for(int i = 0; i < rows; i++)
|
||||
{
|
||||
if(m(i,j) < minc)
|
||||
{
|
||||
minc = m(i,j);
|
||||
minrow = i;
|
||||
mincol = j;
|
||||
}
|
||||
if(m(i,j) > maxc)
|
||||
{
|
||||
maxc = m(i,j);
|
||||
maxrow = i;
|
||||
maxcol = j;
|
||||
}
|
||||
}
|
||||
int eigen_minrow, eigen_mincol, eigen_maxrow, eigen_maxcol;
|
||||
Scalar eigen_minc, eigen_maxc;
|
||||
eigen_minc = m.minCoeff(&eigen_minrow,&eigen_mincol);
|
||||
eigen_maxc = m.maxCoeff(&eigen_maxrow,&eigen_maxcol);
|
||||
VERIFY(minrow == eigen_minrow);
|
||||
VERIFY(maxrow == eigen_maxrow);
|
||||
VERIFY(mincol == eigen_mincol);
|
||||
VERIFY(maxcol == eigen_maxcol);
|
||||
VERIFY_IS_APPROX(minc, eigen_minc);
|
||||
VERIFY_IS_APPROX(maxc, eigen_maxc);
|
||||
VERIFY_IS_APPROX(minc, m.minCoeff());
|
||||
VERIFY_IS_APPROX(maxc, m.maxCoeff());
|
||||
}
|
||||
|
||||
template<typename VectorType> void vectorVisitor(const VectorType& w)
|
||||
{
|
||||
typedef typename VectorType::Scalar Scalar;
|
||||
|
||||
int size = w.size();
|
||||
|
||||
// construct a random vector where all coefficients are different
|
||||
VectorType v;
|
||||
v = VectorType::Random(size);
|
||||
for(int i = 0; i < size; i++)
|
||||
for(int i2 = 0; i2 < i; i2++)
|
||||
while(v(i) == v(i2)) // yes, ==
|
||||
v(i) = ei_random<Scalar>();
|
||||
|
||||
Scalar minc = Scalar(1000), maxc = Scalar(-1000);
|
||||
int minidx=0,maxidx=0;
|
||||
for(int i = 0; i < size; i++)
|
||||
{
|
||||
if(v(i) < minc)
|
||||
{
|
||||
minc = v(i);
|
||||
minidx = i;
|
||||
}
|
||||
if(v(i) > maxc)
|
||||
{
|
||||
maxc = v(i);
|
||||
maxidx = i;
|
||||
}
|
||||
}
|
||||
int eigen_minidx, eigen_maxidx;
|
||||
Scalar eigen_minc, eigen_maxc;
|
||||
eigen_minc = v.minCoeff(&eigen_minidx);
|
||||
eigen_maxc = v.maxCoeff(&eigen_maxidx);
|
||||
VERIFY(minidx == eigen_minidx);
|
||||
VERIFY(maxidx == eigen_maxidx);
|
||||
VERIFY_IS_APPROX(minc, eigen_minc);
|
||||
VERIFY_IS_APPROX(maxc, eigen_maxc);
|
||||
VERIFY_IS_APPROX(minc, v.minCoeff());
|
||||
VERIFY_IS_APPROX(maxc, v.maxCoeff());
|
||||
}
|
||||
|
||||
void test_visitor()
|
||||
{
|
||||
for(int i = 0; i < g_repeat; i++) {
|
||||
CALL_SUBTEST( matrixVisitor(Matrix<float, 1, 1>()) );
|
||||
CALL_SUBTEST( matrixVisitor(Matrix2f()) );
|
||||
CALL_SUBTEST( matrixVisitor(Matrix4d()) );
|
||||
CALL_SUBTEST( matrixVisitor(MatrixXd(8, 12)) );
|
||||
CALL_SUBTEST( matrixVisitor(Matrix<double,Dynamic,Dynamic,RowMajor>(20, 20)) );
|
||||
CALL_SUBTEST( matrixVisitor(MatrixXi(8, 12)) );
|
||||
}
|
||||
for(int i = 0; i < g_repeat; i++) {
|
||||
CALL_SUBTEST( vectorVisitor(Vector4f()) );
|
||||
CALL_SUBTEST( vectorVisitor(VectorXd(10)) );
|
||||
CALL_SUBTEST( vectorVisitor(RowVectorXd(10)) );
|
||||
CALL_SUBTEST( vectorVisitor(VectorXf(33)) );
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user