mirror of
https://gitlab.com/libeigen/eigen.git
synced 2026-04-10 11:34:33 +08:00
Compare commits
75 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a65053d80b | ||
|
|
adcb220db3 | ||
|
|
b21f9c3573 | ||
|
|
fe228fc50b | ||
|
|
4ab20b4cae | ||
|
|
5d5cf478ab | ||
|
|
55149df4e8 | ||
|
|
b2d10249b4 | ||
|
|
bdf0b0c47e | ||
|
|
ea7923c6f9 | ||
|
|
49b6e9143e | ||
|
|
f096553344 | ||
|
|
433b353013 | ||
|
|
3cb088c39f | ||
|
|
a99ea69b32 | ||
|
|
d03bbcbcbc | ||
|
|
fae2aa3fd9 | ||
|
|
13a17d968f | ||
|
|
135ba535a4 | ||
|
|
bbbf0559fe | ||
|
|
c91fed1eec | ||
|
|
f59b08f3bd | ||
|
|
9155002901 | ||
|
|
46f4bd9ed4 | ||
|
|
ebad34db21 | ||
|
|
c0f867ed10 | ||
|
|
d225bbe534 | ||
|
|
a6f8da7c48 | ||
|
|
33efb8ed62 | ||
|
|
63e5cf525f | ||
|
|
3cd1641dac | ||
|
|
4fe4ab8fc0 | ||
|
|
d7d76bf4ca | ||
|
|
cf76a50a34 | ||
|
|
ee46ae9ba7 | ||
|
|
b3c3627c72 | ||
|
|
e3a521be6b | ||
|
|
4c7d57490c | ||
|
|
fe21e084b4 | ||
|
|
282fd7a2da | ||
|
|
7d28c618a0 | ||
|
|
f07fca2c80 | ||
|
|
99ab2411e5 | ||
|
|
ffefe1bd2e | ||
|
|
55574053d0 | ||
|
|
ffee1d1c87 | ||
|
|
adf5992767 | ||
|
|
19e7c672bb | ||
|
|
99a6178e6a | ||
|
|
c3342b0bb4 | ||
|
|
84c8b6d5c5 | ||
|
|
18a8034348 | ||
|
|
697e1656ce | ||
|
|
c2a23c3e24 | ||
|
|
6d0e3154d7 | ||
|
|
7b122ed158 | ||
|
|
d9232a96aa | ||
|
|
4ecf67f5e4 | ||
|
|
860d66c0f1 | ||
|
|
ba3aafa85f | ||
|
|
b478521ecd | ||
|
|
e8fa6dde01 | ||
|
|
134b83c310 | ||
|
|
b0e810fb3f | ||
|
|
dee686f762 | ||
|
|
90cacfa610 | ||
|
|
de21678aab | ||
|
|
a700d3c506 | ||
|
|
fc4684fe97 | ||
|
|
c088ee78c8 | ||
|
|
e53539435d | ||
|
|
1e8b834ceb | ||
|
|
3c510db6bf | ||
|
|
72ffb63165 | ||
|
|
67e24b85a4 |
23
Eigen/Core
23
Eigen/Core
@@ -51,16 +51,16 @@
|
|||||||
#define EIGEN_SSE2_ON_MSVC_2008_OR_LATER
|
#define EIGEN_SSE2_ON_MSVC_2008_OR_LATER
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#else
|
||||||
|
// Remember that usage of defined() in a #define is undefined by the standard
|
||||||
// Remember that usage of defined() in a #define is undefined by the standard
|
#if (defined __SSE2__) && ( (!defined __GNUC__) || EIGEN_GNUC_AT_LEAST(4,2) )
|
||||||
#if (defined __SSE2__) && ( (!defined __GNUC__) || EIGEN_GNUC_AT_LEAST(4,2) )
|
#define EIGEN_SSE2_ON_NON_MSVC_BUT_NOT_OLD_GCC
|
||||||
#define EIGEN_SSE2_BUT_NOT_OLD_GCC
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef EIGEN_DONT_VECTORIZE
|
#ifndef EIGEN_DONT_VECTORIZE
|
||||||
|
|
||||||
#if defined (EIGEN_SSE2_BUT_NOT_OLD_GCC) || defined(EIGEN_SSE2_ON_MSVC_2008_OR_LATER)
|
#if defined (EIGEN_SSE2_ON_NON_MSVC_BUT_NOT_OLD_GCC) || defined(EIGEN_SSE2_ON_MSVC_2008_OR_LATER)
|
||||||
|
|
||||||
// Defines symbols for compile-time detection of which instructions are
|
// Defines symbols for compile-time detection of which instructions are
|
||||||
// used.
|
// used.
|
||||||
@@ -143,6 +143,7 @@
|
|||||||
#ifdef EIGEN_HAS_ERRNO
|
#ifdef EIGEN_HAS_ERRNO
|
||||||
#include <cerrno>
|
#include <cerrno>
|
||||||
#endif
|
#endif
|
||||||
|
#include <cstddef>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <complex>
|
#include <complex>
|
||||||
@@ -174,16 +175,10 @@
|
|||||||
#include <new>
|
#include <new>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// this needs to be done after all possible windows C header includes and before any Eigen source includes
|
|
||||||
// (system C++ includes are supposed to be able to deal with this already):
|
|
||||||
// windows.h defines min and max macros which would make Eigen fail to compile.
|
|
||||||
#if defined(min) || defined(max)
|
|
||||||
#error The preprocessor symbols 'min' or 'max' are defined. If you are compiling on Windows, do #define NOMINMAX to prevent windows.h from defining these symbols.
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// defined in bits/termios.h
|
// defined in bits/termios.h
|
||||||
#undef B0
|
#undef B0
|
||||||
|
|
||||||
|
/** \brief Namespace containing all symbols from the %Eigen library. */
|
||||||
namespace Eigen {
|
namespace Eigen {
|
||||||
|
|
||||||
inline static const char *SimdInstructionSetsInUse(void) {
|
inline static const char *SimdInstructionSetsInUse(void) {
|
||||||
@@ -239,6 +234,8 @@ inline static const char *SimdInstructionSetsInUse(void) {
|
|||||||
// we use size_t frequently and we'll never remember to prepend it with std:: everytime just to
|
// we use size_t frequently and we'll never remember to prepend it with std:: everytime just to
|
||||||
// ensure QNX/QCC support
|
// ensure QNX/QCC support
|
||||||
using std::size_t;
|
using std::size_t;
|
||||||
|
// gcc 4.6.0 wants std:: for ptrdiff_t
|
||||||
|
using std::ptrdiff_t;
|
||||||
|
|
||||||
/** \defgroup Core_Module Core module
|
/** \defgroup Core_Module Core module
|
||||||
* This is the main module of Eigen providing dense matrix and vector support
|
* This is the main module of Eigen providing dense matrix and vector support
|
||||||
|
|||||||
@@ -233,7 +233,7 @@ template<> struct llt_inplace<Lower>
|
|||||||
|
|
||||||
Index blockSize = size/8;
|
Index blockSize = size/8;
|
||||||
blockSize = (blockSize/16)*16;
|
blockSize = (blockSize/16)*16;
|
||||||
blockSize = std::min(std::max(blockSize,Index(8)), Index(128));
|
blockSize = (std::min)((std::max)(blockSize,Index(8)), Index(128));
|
||||||
|
|
||||||
for (Index k=0; k<size; k+=blockSize)
|
for (Index k=0; k<size; k+=blockSize)
|
||||||
{
|
{
|
||||||
@@ -241,7 +241,7 @@ template<> struct llt_inplace<Lower>
|
|||||||
// A00 | - | -
|
// A00 | - | -
|
||||||
// lu = A10 | A11 | -
|
// lu = A10 | A11 | -
|
||||||
// A20 | A21 | A22
|
// A20 | A21 | A22
|
||||||
Index bs = std::min(blockSize, size-k);
|
Index bs = (std::min)(blockSize, size-k);
|
||||||
Index rs = size - k - bs;
|
Index rs = size - k - bs;
|
||||||
Block<MatrixType,Dynamic,Dynamic> A11(m,k, k, bs,bs);
|
Block<MatrixType,Dynamic,Dynamic> A11(m,k, k, bs,bs);
|
||||||
Block<MatrixType,Dynamic,Dynamic> A21(m,k+bs,k, rs,bs);
|
Block<MatrixType,Dynamic,Dynamic> A21(m,k+bs,k, rs,bs);
|
||||||
|
|||||||
@@ -53,6 +53,12 @@ class ArrayWrapper : public ArrayBase<ArrayWrapper<ExpressionType> >
|
|||||||
EIGEN_DENSE_PUBLIC_INTERFACE(ArrayWrapper)
|
EIGEN_DENSE_PUBLIC_INTERFACE(ArrayWrapper)
|
||||||
EIGEN_INHERIT_ASSIGNMENT_OPERATORS(ArrayWrapper)
|
EIGEN_INHERIT_ASSIGNMENT_OPERATORS(ArrayWrapper)
|
||||||
|
|
||||||
|
typedef typename internal::conditional<
|
||||||
|
internal::is_lvalue<ExpressionType>::value,
|
||||||
|
Scalar,
|
||||||
|
const Scalar
|
||||||
|
>::type ScalarWithConstIfNotLvalue;
|
||||||
|
|
||||||
typedef typename internal::nested<ExpressionType>::type NestedExpressionType;
|
typedef typename internal::nested<ExpressionType>::type NestedExpressionType;
|
||||||
|
|
||||||
inline ArrayWrapper(const ExpressionType& matrix) : m_expression(matrix) {}
|
inline ArrayWrapper(const ExpressionType& matrix) : m_expression(matrix) {}
|
||||||
@@ -62,6 +68,9 @@ class ArrayWrapper : public ArrayBase<ArrayWrapper<ExpressionType> >
|
|||||||
inline Index outerStride() const { return m_expression.outerStride(); }
|
inline Index outerStride() const { return m_expression.outerStride(); }
|
||||||
inline Index innerStride() const { return m_expression.innerStride(); }
|
inline Index innerStride() const { return m_expression.innerStride(); }
|
||||||
|
|
||||||
|
inline ScalarWithConstIfNotLvalue* data() { return m_expression.data(); }
|
||||||
|
inline const Scalar* data() const { return m_expression.data(); }
|
||||||
|
|
||||||
inline const CoeffReturnType coeff(Index row, Index col) const
|
inline const CoeffReturnType coeff(Index row, Index col) const
|
||||||
{
|
{
|
||||||
return m_expression.coeff(row, col);
|
return m_expression.coeff(row, col);
|
||||||
@@ -151,6 +160,12 @@ class MatrixWrapper : public MatrixBase<MatrixWrapper<ExpressionType> >
|
|||||||
EIGEN_DENSE_PUBLIC_INTERFACE(MatrixWrapper)
|
EIGEN_DENSE_PUBLIC_INTERFACE(MatrixWrapper)
|
||||||
EIGEN_INHERIT_ASSIGNMENT_OPERATORS(MatrixWrapper)
|
EIGEN_INHERIT_ASSIGNMENT_OPERATORS(MatrixWrapper)
|
||||||
|
|
||||||
|
typedef typename internal::conditional<
|
||||||
|
internal::is_lvalue<ExpressionType>::value,
|
||||||
|
Scalar,
|
||||||
|
const Scalar
|
||||||
|
>::type ScalarWithConstIfNotLvalue;
|
||||||
|
|
||||||
typedef typename internal::nested<ExpressionType>::type NestedExpressionType;
|
typedef typename internal::nested<ExpressionType>::type NestedExpressionType;
|
||||||
|
|
||||||
inline MatrixWrapper(const ExpressionType& matrix) : m_expression(matrix) {}
|
inline MatrixWrapper(const ExpressionType& matrix) : m_expression(matrix) {}
|
||||||
@@ -160,6 +175,9 @@ class MatrixWrapper : public MatrixBase<MatrixWrapper<ExpressionType> >
|
|||||||
inline Index outerStride() const { return m_expression.outerStride(); }
|
inline Index outerStride() const { return m_expression.outerStride(); }
|
||||||
inline Index innerStride() const { return m_expression.innerStride(); }
|
inline Index innerStride() const { return m_expression.innerStride(); }
|
||||||
|
|
||||||
|
inline ScalarWithConstIfNotLvalue* data() { return m_expression.data(); }
|
||||||
|
inline const Scalar* data() const { return m_expression.data(); }
|
||||||
|
|
||||||
inline const CoeffReturnType coeff(Index row, Index col) const
|
inline const CoeffReturnType coeff(Index row, Index col) const
|
||||||
{
|
{
|
||||||
return m_expression.coeff(row, col);
|
return m_expression.coeff(row, col);
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ class BandMatrixBase : public EigenBase<Derived>
|
|||||||
if (i<=supers())
|
if (i<=supers())
|
||||||
{
|
{
|
||||||
start = supers()-i;
|
start = supers()-i;
|
||||||
len = std::min(rows(),std::max<Index>(0,coeffs().rows() - (supers()-i)));
|
len = (std::min)(rows(),std::max<Index>(0,coeffs().rows() - (supers()-i)));
|
||||||
}
|
}
|
||||||
else if (i>=rows()-subs())
|
else if (i>=rows()-subs())
|
||||||
len = std::max<Index>(0,coeffs().rows() - (i + 1 - rows() + subs()));
|
len = std::max<Index>(0,coeffs().rows() - (i + 1 - rows() + subs()));
|
||||||
@@ -96,11 +96,11 @@ class BandMatrixBase : public EigenBase<Derived>
|
|||||||
|
|
||||||
/** \returns a vector expression of the main diagonal */
|
/** \returns a vector expression of the main diagonal */
|
||||||
inline Block<CoefficientsType,1,SizeAtCompileTime> diagonal()
|
inline Block<CoefficientsType,1,SizeAtCompileTime> diagonal()
|
||||||
{ return Block<CoefficientsType,1,SizeAtCompileTime>(coeffs(),supers(),0,1,std::min(rows(),cols())); }
|
{ return Block<CoefficientsType,1,SizeAtCompileTime>(coeffs(),supers(),0,1,(std::min)(rows(),cols())); }
|
||||||
|
|
||||||
/** \returns a vector expression of the main diagonal (const version) */
|
/** \returns a vector expression of the main diagonal (const version) */
|
||||||
inline const Block<const CoefficientsType,1,SizeAtCompileTime> diagonal() const
|
inline const Block<const CoefficientsType,1,SizeAtCompileTime> diagonal() const
|
||||||
{ return Block<const CoefficientsType,1,SizeAtCompileTime>(coeffs(),supers(),0,1,std::min(rows(),cols())); }
|
{ return Block<const CoefficientsType,1,SizeAtCompileTime>(coeffs(),supers(),0,1,(std::min)(rows(),cols())); }
|
||||||
|
|
||||||
template<int Index> struct DiagonalIntReturnType {
|
template<int Index> struct DiagonalIntReturnType {
|
||||||
enum {
|
enum {
|
||||||
@@ -122,13 +122,13 @@ class BandMatrixBase : public EigenBase<Derived>
|
|||||||
/** \returns a vector expression of the \a N -th sub or super diagonal */
|
/** \returns a vector expression of the \a N -th sub or super diagonal */
|
||||||
template<int N> inline typename DiagonalIntReturnType<N>::Type diagonal()
|
template<int N> inline typename DiagonalIntReturnType<N>::Type diagonal()
|
||||||
{
|
{
|
||||||
return typename DiagonalIntReturnType<N>::BuildType(coeffs(), supers()-N, std::max(0,N), 1, diagonalLength(N));
|
return typename DiagonalIntReturnType<N>::BuildType(coeffs(), supers()-N, (std::max)(0,N), 1, diagonalLength(N));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** \returns a vector expression of the \a N -th sub or super diagonal */
|
/** \returns a vector expression of the \a N -th sub or super diagonal */
|
||||||
template<int N> inline const typename DiagonalIntReturnType<N>::Type diagonal() const
|
template<int N> inline const typename DiagonalIntReturnType<N>::Type diagonal() const
|
||||||
{
|
{
|
||||||
return typename DiagonalIntReturnType<N>::BuildType(coeffs(), supers()-N, std::max(0,N), 1, diagonalLength(N));
|
return typename DiagonalIntReturnType<N>::BuildType(coeffs(), supers()-N, (std::max)(0,N), 1, diagonalLength(N));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** \returns a vector expression of the \a i -th sub or super diagonal */
|
/** \returns a vector expression of the \a i -th sub or super diagonal */
|
||||||
@@ -166,7 +166,7 @@ class BandMatrixBase : public EigenBase<Derived>
|
|||||||
protected:
|
protected:
|
||||||
|
|
||||||
inline Index diagonalLength(Index i) const
|
inline Index diagonalLength(Index i) const
|
||||||
{ return i<0 ? std::min(cols(),rows()+i) : std::min(rows(),cols()-i); }
|
{ return i<0 ? (std::min)(cols(),rows()+i) : (std::min)(rows(),cols()-i); }
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -180,7 +180,7 @@ class BandMatrixBase : public EigenBase<Derived>
|
|||||||
* \param Cols Number of columns, or \b Dynamic
|
* \param Cols Number of columns, or \b Dynamic
|
||||||
* \param Supers Number of super diagonal
|
* \param Supers Number of super diagonal
|
||||||
* \param Subs Number of sub diagonal
|
* \param Subs Number of sub diagonal
|
||||||
* \param _Options A combination of either \b RowMajor or \b ColMajor, and of \b SelfAdjoint
|
* \param _Options A combination of either \b #RowMajor or \b #ColMajor, and of \b #SelfAdjoint
|
||||||
* The former controls \ref TopicStorageOrders "storage order", and defaults to
|
* The former controls \ref TopicStorageOrders "storage order", and defaults to
|
||||||
* column-major. The latter controls whether the matrix represents a selfadjoint
|
* column-major. The latter controls whether the matrix represents a selfadjoint
|
||||||
* matrix in which case either Supers of Subs have to be null.
|
* matrix in which case either Supers of Subs have to be null.
|
||||||
@@ -284,6 +284,7 @@ class BandMatrixWrapper : public BandMatrixBase<BandMatrixWrapper<_CoefficientsT
|
|||||||
: m_coeffs(coeffs),
|
: m_coeffs(coeffs),
|
||||||
m_rows(rows), m_supers(supers), m_subs(subs)
|
m_rows(rows), m_supers(supers), m_subs(subs)
|
||||||
{
|
{
|
||||||
|
EIGEN_UNUSED_VARIABLE(cols);
|
||||||
//internal::assert(coeffs.cols()==cols() && (supers()+subs()+1)==coeffs.rows());
|
//internal::assert(coeffs.cols()==cols() && (supers()+subs()+1)==coeffs.rows());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -742,7 +742,7 @@ struct setIdentity_impl<Derived, true>
|
|||||||
static EIGEN_STRONG_INLINE Derived& run(Derived& m)
|
static EIGEN_STRONG_INLINE Derived& run(Derived& m)
|
||||||
{
|
{
|
||||||
m.setZero();
|
m.setZero();
|
||||||
const Index size = std::min(m.rows(), m.cols());
|
const Index size = (std::min)(m.rows(), m.cols());
|
||||||
for(Index i = 0; i < size; ++i) m.coeffRef(i,i) = typename Derived::Scalar(1);
|
for(Index i = 0; i < size; ++i) m.coeffRef(i,i) = typename Derived::Scalar(1);
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ template<typename T> struct add_const_on_value_type_if_arithmetic
|
|||||||
/** \brief Base class providing read-only coefficient access to matrices and arrays.
|
/** \brief Base class providing read-only coefficient access to matrices and arrays.
|
||||||
* \ingroup Core_Module
|
* \ingroup Core_Module
|
||||||
* \tparam Derived Type of the derived class
|
* \tparam Derived Type of the derived class
|
||||||
* \tparam ReadOnlyAccessors Constant indicating read-only access
|
* \tparam #ReadOnlyAccessors Constant indicating read-only access
|
||||||
*
|
*
|
||||||
* This class defines the \c operator() \c const function and friends, which can be used to read specific
|
* This class defines the \c operator() \c const function and friends, which can be used to read specific
|
||||||
* entries of a matrix or array.
|
* entries of a matrix or array.
|
||||||
@@ -212,7 +212,7 @@ class DenseCoeffsBase<Derived,ReadOnlyAccessors> : public EigenBase<Derived>
|
|||||||
* to ensure that a packet really starts there. This method is only available on expressions having the
|
* to ensure that a packet really starts there. This method is only available on expressions having the
|
||||||
* PacketAccessBit.
|
* PacketAccessBit.
|
||||||
*
|
*
|
||||||
* The \a LoadMode parameter may have the value \a Aligned or \a Unaligned. Its effect is to select
|
* The \a LoadMode parameter may have the value \a #Aligned or \a #Unaligned. Its effect is to select
|
||||||
* the appropriate vectorization instruction. Aligned access is faster, but is only possible for packets
|
* the appropriate vectorization instruction. Aligned access is faster, but is only possible for packets
|
||||||
* starting at an address which is a multiple of the packet size.
|
* starting at an address which is a multiple of the packet size.
|
||||||
*/
|
*/
|
||||||
@@ -239,7 +239,7 @@ class DenseCoeffsBase<Derived,ReadOnlyAccessors> : public EigenBase<Derived>
|
|||||||
* to ensure that a packet really starts there. This method is only available on expressions having the
|
* to ensure that a packet really starts there. This method is only available on expressions having the
|
||||||
* PacketAccessBit and the LinearAccessBit.
|
* PacketAccessBit and the LinearAccessBit.
|
||||||
*
|
*
|
||||||
* The \a LoadMode parameter may have the value \a Aligned or \a Unaligned. Its effect is to select
|
* The \a LoadMode parameter may have the value \a #Aligned or \a #Unaligned. Its effect is to select
|
||||||
* the appropriate vectorization instruction. Aligned access is faster, but is only possible for packets
|
* the appropriate vectorization instruction. Aligned access is faster, but is only possible for packets
|
||||||
* starting at an address which is a multiple of the packet size.
|
* starting at an address which is a multiple of the packet size.
|
||||||
*/
|
*/
|
||||||
@@ -275,7 +275,7 @@ class DenseCoeffsBase<Derived,ReadOnlyAccessors> : public EigenBase<Derived>
|
|||||||
/** \brief Base class providing read/write coefficient access to matrices and arrays.
|
/** \brief Base class providing read/write coefficient access to matrices and arrays.
|
||||||
* \ingroup Core_Module
|
* \ingroup Core_Module
|
||||||
* \tparam Derived Type of the derived class
|
* \tparam Derived Type of the derived class
|
||||||
* \tparam WriteAccessors Constant indicating read/write access
|
* \tparam #WriteAccessors Constant indicating read/write access
|
||||||
*
|
*
|
||||||
* This class defines the non-const \c operator() function and friends, which can be used to write specific
|
* This class defines the non-const \c operator() function and friends, which can be used to write specific
|
||||||
* entries of a matrix or array. This class inherits DenseCoeffsBase<Derived, ReadOnlyAccessors> which
|
* entries of a matrix or array. This class inherits DenseCoeffsBase<Derived, ReadOnlyAccessors> which
|
||||||
@@ -433,7 +433,7 @@ class DenseCoeffsBase<Derived, WriteAccessors> : public DenseCoeffsBase<Derived,
|
|||||||
* to ensure that a packet really starts there. This method is only available on expressions having the
|
* to ensure that a packet really starts there. This method is only available on expressions having the
|
||||||
* PacketAccessBit.
|
* PacketAccessBit.
|
||||||
*
|
*
|
||||||
* The \a LoadMode parameter may have the value \a Aligned or \a Unaligned. Its effect is to select
|
* The \a LoadMode parameter may have the value \a #Aligned or \a #Unaligned. Its effect is to select
|
||||||
* the appropriate vectorization instruction. Aligned access is faster, but is only possible for packets
|
* the appropriate vectorization instruction. Aligned access is faster, but is only possible for packets
|
||||||
* starting at an address which is a multiple of the packet size.
|
* starting at an address which is a multiple of the packet size.
|
||||||
*/
|
*/
|
||||||
@@ -567,7 +567,7 @@ class DenseCoeffsBase<Derived, WriteAccessors> : public DenseCoeffsBase<Derived,
|
|||||||
/** \brief Base class providing direct read-only coefficient access to matrices and arrays.
|
/** \brief Base class providing direct read-only coefficient access to matrices and arrays.
|
||||||
* \ingroup Core_Module
|
* \ingroup Core_Module
|
||||||
* \tparam Derived Type of the derived class
|
* \tparam Derived Type of the derived class
|
||||||
* \tparam DirectAccessors Constant indicating direct access
|
* \tparam #DirectAccessors Constant indicating direct access
|
||||||
*
|
*
|
||||||
* This class defines functions to work with strides which can be used to access entries directly. This class
|
* This class defines functions to work with strides which can be used to access entries directly. This class
|
||||||
* inherits DenseCoeffsBase<Derived, ReadOnlyAccessors> which defines functions to access entries read-only using
|
* inherits DenseCoeffsBase<Derived, ReadOnlyAccessors> which defines functions to access entries read-only using
|
||||||
@@ -637,7 +637,7 @@ class DenseCoeffsBase<Derived, DirectAccessors> : public DenseCoeffsBase<Derived
|
|||||||
/** \brief Base class providing direct read/write coefficient access to matrices and arrays.
|
/** \brief Base class providing direct read/write coefficient access to matrices and arrays.
|
||||||
* \ingroup Core_Module
|
* \ingroup Core_Module
|
||||||
* \tparam Derived Type of the derived class
|
* \tparam Derived Type of the derived class
|
||||||
* \tparam DirectAccessors Constant indicating direct access
|
* \tparam #DirectWriteAccessors Constant indicating direct access
|
||||||
*
|
*
|
||||||
* This class defines functions to work with strides which can be used to access entries directly. This class
|
* This class defines functions to work with strides which can be used to access entries directly. This class
|
||||||
* inherits DenseCoeffsBase<Derived, WriteAccessors> which defines functions to access entries read/write using
|
* inherits DenseCoeffsBase<Derived, WriteAccessors> which defines functions to access entries read/write using
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ struct plain_array
|
|||||||
#define EIGEN_MAKE_UNALIGNED_ARRAY_ASSERT(sizemask) \
|
#define EIGEN_MAKE_UNALIGNED_ARRAY_ASSERT(sizemask) \
|
||||||
eigen_assert((reinterpret_cast<size_t>(array) & sizemask) == 0 \
|
eigen_assert((reinterpret_cast<size_t>(array) & sizemask) == 0 \
|
||||||
&& "this assertion is explained here: " \
|
&& "this assertion is explained here: " \
|
||||||
"http://eigen.tuxfamily.org/dox/UnalignedArrayAssert.html" \
|
"http://eigen.tuxfamily.org/dox-devel/TopicUnalignedArrayAssert.html" \
|
||||||
" **** READ THIS WEB PAGE !!! ****");
|
" **** READ THIS WEB PAGE !!! ****");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ template<typename MatrixType, int DiagIndex> class Diagonal
|
|||||||
EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Diagonal)
|
EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Diagonal)
|
||||||
|
|
||||||
inline Index rows() const
|
inline Index rows() const
|
||||||
{ return m_index.value()<0 ? std::min(m_matrix.cols(),m_matrix.rows()+m_index.value()) : std::min(m_matrix.rows(),m_matrix.cols()-m_index.value()); }
|
{ return m_index.value()<0 ? (std::min)(m_matrix.cols(),m_matrix.rows()+m_index.value()) : (std::min)(m_matrix.rows(),m_matrix.cols()-m_index.value()); }
|
||||||
|
|
||||||
inline Index cols() const { return 1; }
|
inline Index cols() const { return 1; }
|
||||||
|
|
||||||
|
|||||||
@@ -116,7 +116,9 @@ MatrixBase<Derived>::eigen2_dot(const MatrixBase<OtherDerived>& other) const
|
|||||||
|
|
||||||
//---------- implementation of L2 norm and related functions ----------
|
//---------- implementation of L2 norm and related functions ----------
|
||||||
|
|
||||||
/** \returns the squared \em l2 norm of *this, i.e., for vectors, the dot product of *this with itself.
|
/** \returns, for vectors, the squared \em l2 norm of \c *this, and for matrices the Frobenius norm.
|
||||||
|
* In both cases, it consists in the sum of the square of all the matrix entries.
|
||||||
|
* For vectors, this is also equals to the dot product of \c *this with itself.
|
||||||
*
|
*
|
||||||
* \sa dot(), norm()
|
* \sa dot(), norm()
|
||||||
*/
|
*/
|
||||||
@@ -126,7 +128,9 @@ EIGEN_STRONG_INLINE typename NumTraits<typename internal::traits<Derived>::Scala
|
|||||||
return internal::real((*this).cwiseAbs2().sum());
|
return internal::real((*this).cwiseAbs2().sum());
|
||||||
}
|
}
|
||||||
|
|
||||||
/** \returns the \em l2 norm of *this, i.e., for vectors, the square root of the dot product of *this with itself.
|
/** \returns, for vectors, the \em l2 norm of \c *this, and for matrices the Frobenius norm.
|
||||||
|
* In both cases, it consists in the square root of the sum of the square of all the matrix entries.
|
||||||
|
* For vectors, this is also equals to the square root of the dot product of \c *this with itself.
|
||||||
*
|
*
|
||||||
* \sa dot(), squaredNorm()
|
* \sa dot(), squaredNorm()
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ struct functor_traits<scalar_conj_product_op<LhsScalar,RhsScalar> > {
|
|||||||
*/
|
*/
|
||||||
template<typename Scalar> struct scalar_min_op {
|
template<typename Scalar> struct scalar_min_op {
|
||||||
EIGEN_EMPTY_STRUCT_CTOR(scalar_min_op)
|
EIGEN_EMPTY_STRUCT_CTOR(scalar_min_op)
|
||||||
EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a, const Scalar& b) const { return std::min(a, b); }
|
EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a, const Scalar& b) const { using std::min; return (min)(a, b); }
|
||||||
template<typename Packet>
|
template<typename Packet>
|
||||||
EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
|
EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
|
||||||
{ return internal::pmin(a,b); }
|
{ return internal::pmin(a,b); }
|
||||||
@@ -139,7 +139,7 @@ struct functor_traits<scalar_min_op<Scalar> > {
|
|||||||
*/
|
*/
|
||||||
template<typename Scalar> struct scalar_max_op {
|
template<typename Scalar> struct scalar_max_op {
|
||||||
EIGEN_EMPTY_STRUCT_CTOR(scalar_max_op)
|
EIGEN_EMPTY_STRUCT_CTOR(scalar_max_op)
|
||||||
EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a, const Scalar& b) const { return std::max(a, b); }
|
EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a, const Scalar& b) const { using std::max; return (max)(a, b); }
|
||||||
template<typename Packet>
|
template<typename Packet>
|
||||||
EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
|
EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
|
||||||
{ return internal::pmax(a,b); }
|
{ return internal::pmax(a,b); }
|
||||||
@@ -165,8 +165,10 @@ template<typename Scalar> struct scalar_hypot_op {
|
|||||||
// typedef typename NumTraits<Scalar>::Real result_type;
|
// typedef typename NumTraits<Scalar>::Real result_type;
|
||||||
EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& _x, const Scalar& _y) const
|
EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& _x, const Scalar& _y) const
|
||||||
{
|
{
|
||||||
Scalar p = std::max(_x, _y);
|
using std::max;
|
||||||
Scalar q = std::min(_x, _y);
|
using std::min;
|
||||||
|
Scalar p = (max)(_x, _y);
|
||||||
|
Scalar q = (min)(_x, _y);
|
||||||
Scalar qp = q/p;
|
Scalar qp = q/p;
|
||||||
return p * sqrt(Scalar(1) + qp*qp);
|
return p * sqrt(Scalar(1) + qp*qp);
|
||||||
}
|
}
|
||||||
@@ -605,7 +607,7 @@ template <typename Scalar, bool RandomAccess> struct linspaced_op
|
|||||||
EIGEN_STRONG_INLINE const Packet packetOp(Index row, Index col) const
|
EIGEN_STRONG_INLINE const Packet packetOp(Index row, Index col) const
|
||||||
{
|
{
|
||||||
eigen_assert(col==0 || row==0);
|
eigen_assert(col==0 || row==0);
|
||||||
return impl(col + row);
|
return impl.packetOp(col + row);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This proxy object handles the actual required temporaries, the different
|
// This proxy object handles the actual required temporaries, the different
|
||||||
@@ -750,9 +752,9 @@ struct functor_traits<scalar_acos_op<Scalar> >
|
|||||||
*/
|
*/
|
||||||
template<typename Scalar> struct scalar_asin_op {
|
template<typename Scalar> struct scalar_asin_op {
|
||||||
EIGEN_EMPTY_STRUCT_CTOR(scalar_asin_op)
|
EIGEN_EMPTY_STRUCT_CTOR(scalar_asin_op)
|
||||||
inline const Scalar operator() (const Scalar& a) const { return acos(a); }
|
inline const Scalar operator() (const Scalar& a) const { return asin(a); }
|
||||||
typedef typename packet_traits<Scalar>::type Packet;
|
typedef typename packet_traits<Scalar>::type Packet;
|
||||||
inline Packet packetOp(const Packet& a) const { return internal::pacos(a); }
|
inline Packet packetOp(const Packet& a) const { return internal::pasin(a); }
|
||||||
};
|
};
|
||||||
template<typename Scalar>
|
template<typename Scalar>
|
||||||
struct functor_traits<scalar_asin_op<Scalar> >
|
struct functor_traits<scalar_asin_op<Scalar> >
|
||||||
|
|||||||
@@ -34,9 +34,10 @@ struct isApprox_selector
|
|||||||
{
|
{
|
||||||
static bool run(const Derived& x, const OtherDerived& y, typename Derived::RealScalar prec)
|
static bool run(const Derived& x, const OtherDerived& y, typename Derived::RealScalar prec)
|
||||||
{
|
{
|
||||||
|
using std::min;
|
||||||
const typename internal::nested<Derived,2>::type nested(x);
|
const typename internal::nested<Derived,2>::type nested(x);
|
||||||
const typename internal::nested<OtherDerived,2>::type otherNested(y);
|
const typename internal::nested<OtherDerived,2>::type otherNested(y);
|
||||||
return (nested - otherNested).cwiseAbs2().sum() <= prec * prec * std::min(nested.cwiseAbs2().sum(), otherNested.cwiseAbs2().sum());
|
return (nested - otherNested).cwiseAbs2().sum() <= prec * prec * (min)(nested.cwiseAbs2().sum(), otherNested.cwiseAbs2().sum());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -93,7 +94,7 @@ struct isMuchSmallerThan_scalar_selector<Derived, true>
|
|||||||
*
|
*
|
||||||
* \note The fuzzy compares are done multiplicatively. Two vectors \f$ v \f$ and \f$ w \f$
|
* \note The fuzzy compares are done multiplicatively. Two vectors \f$ v \f$ and \f$ w \f$
|
||||||
* are considered to be approximately equal within precision \f$ p \f$ if
|
* are considered to be approximately equal within precision \f$ p \f$ if
|
||||||
* \f[ \Vert v - w \Vert \leqslant p\,\min(\Vert v\Vert, \Vert w\Vert). \f]
|
* \f[ \Vert v - w \Vert \leqslant p\,\(min)(\Vert v\Vert, \Vert w\Vert). \f]
|
||||||
* For matrices, the comparison is done using the Hilbert-Schmidt norm (aka Frobenius norm
|
* For matrices, the comparison is done using the Hilbert-Schmidt norm (aka Frobenius norm
|
||||||
* L2 norm).
|
* L2 norm).
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -134,12 +134,12 @@ pdiv(const Packet& a,
|
|||||||
/** \internal \returns the min of \a a and \a b (coeff-wise) */
|
/** \internal \returns the min of \a a and \a b (coeff-wise) */
|
||||||
template<typename Packet> inline Packet
|
template<typename Packet> inline Packet
|
||||||
pmin(const Packet& a,
|
pmin(const Packet& a,
|
||||||
const Packet& b) { return std::min(a, b); }
|
const Packet& b) { using std::min; return (min)(a, b); }
|
||||||
|
|
||||||
/** \internal \returns the max of \a a and \a b (coeff-wise) */
|
/** \internal \returns the max of \a a and \a b (coeff-wise) */
|
||||||
template<typename Packet> inline Packet
|
template<typename Packet> inline Packet
|
||||||
pmax(const Packet& a,
|
pmax(const Packet& a,
|
||||||
const Packet& b) { return std::max(a, b); }
|
const Packet& b) { using std::max; return (max)(a, b); }
|
||||||
|
|
||||||
/** \internal \returns the absolute value of \a a */
|
/** \internal \returns the absolute value of \a a */
|
||||||
template<typename Packet> inline Packet
|
template<typename Packet> inline Packet
|
||||||
@@ -286,7 +286,7 @@ pmadd(const Packet& a,
|
|||||||
{ return padd(pmul(a, b),c); }
|
{ return padd(pmul(a, b),c); }
|
||||||
|
|
||||||
/** \internal \returns a packet version of \a *from.
|
/** \internal \returns a packet version of \a *from.
|
||||||
* \If LoadMode equals Aligned, \a from must be 16 bytes aligned */
|
* If LoadMode equals #Aligned, \a from must be 16 bytes aligned */
|
||||||
template<typename Packet, int LoadMode>
|
template<typename Packet, int LoadMode>
|
||||||
inline Packet ploadt(const typename unpacket_traits<Packet>::type* from)
|
inline Packet ploadt(const typename unpacket_traits<Packet>::type* from)
|
||||||
{
|
{
|
||||||
@@ -297,7 +297,7 @@ inline Packet ploadt(const typename unpacket_traits<Packet>::type* from)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** \internal copy the packet \a from to \a *to.
|
/** \internal copy the packet \a from to \a *to.
|
||||||
* If StoreMode equals Aligned, \a to must be 16 bytes aligned */
|
* If StoreMode equals #Aligned, \a to must be 16 bytes aligned */
|
||||||
template<typename Scalar, typename Packet, int LoadMode>
|
template<typename Scalar, typename Packet, int LoadMode>
|
||||||
inline void pstoret(Scalar* to, const Packet& from)
|
inline void pstoret(Scalar* to, const Packet& from)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -141,7 +141,8 @@ struct significant_decimals_default_impl
|
|||||||
typedef typename NumTraits<Scalar>::Real RealScalar;
|
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||||
static inline int run()
|
static inline int run()
|
||||||
{
|
{
|
||||||
return cast<RealScalar,int>(std::ceil(-log(NumTraits<RealScalar>::epsilon())/log(RealScalar(10))));
|
using std::ceil;
|
||||||
|
return cast<RealScalar,int>(ceil(-log(NumTraits<RealScalar>::epsilon())/log(RealScalar(10))));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -31,10 +31,10 @@
|
|||||||
*
|
*
|
||||||
* \brief A matrix or vector expression mapping an existing array of data.
|
* \brief A matrix or vector expression mapping an existing array of data.
|
||||||
*
|
*
|
||||||
* \param PlainObjectType the equivalent matrix type of the mapped data
|
* \tparam PlainObjectType the equivalent matrix type of the mapped data
|
||||||
* \param MapOptions specifies whether the pointer is \c Aligned, or \c Unaligned.
|
* \tparam MapOptions specifies whether the pointer is \c #Aligned, or \c #Unaligned.
|
||||||
* The default is \c Unaligned.
|
* The default is \c #Unaligned.
|
||||||
* \param StrideType optionnally specifies strides. By default, Map assumes the memory layout
|
* \tparam StrideType optionnally specifies strides. By default, Map assumes the memory layout
|
||||||
* of an ordinary, contiguous array. This can be overridden by specifying strides.
|
* of an ordinary, contiguous array. This can be overridden by specifying strides.
|
||||||
* The type passed here must be a specialization of the Stride template, see examples below.
|
* The type passed here must be a specialization of the Stride template, see examples below.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -238,7 +238,7 @@ template<typename Derived> class MapBase<Derived, WriteAccessors>
|
|||||||
(this->m_data + index * innerStride(), x);
|
(this->m_data + index * innerStride(), x);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline MapBase(PointerType data) : Base(data) {}
|
explicit inline MapBase(PointerType data) : Base(data) {}
|
||||||
inline MapBase(PointerType data, Index size) : Base(data, size) {}
|
inline MapBase(PointerType data, Index size) : Base(data, size) {}
|
||||||
inline MapBase(PointerType data, Index rows, Index cols) : Base(data, rows, cols) {}
|
inline MapBase(PointerType data, Index rows, Index cols) : Base(data, rows, cols) {}
|
||||||
|
|
||||||
|
|||||||
@@ -87,7 +87,8 @@ struct real_impl<std::complex<RealScalar> >
|
|||||||
{
|
{
|
||||||
static inline RealScalar run(const std::complex<RealScalar>& x)
|
static inline RealScalar run(const std::complex<RealScalar>& x)
|
||||||
{
|
{
|
||||||
return std::real(x);
|
using std::real;
|
||||||
|
return real(x);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -122,7 +123,8 @@ struct imag_impl<std::complex<RealScalar> >
|
|||||||
{
|
{
|
||||||
static inline RealScalar run(const std::complex<RealScalar>& x)
|
static inline RealScalar run(const std::complex<RealScalar>& x)
|
||||||
{
|
{
|
||||||
return std::imag(x);
|
using std::imag;
|
||||||
|
return imag(x);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -244,7 +246,8 @@ struct conj_impl<std::complex<RealScalar> >
|
|||||||
{
|
{
|
||||||
static inline std::complex<RealScalar> run(const std::complex<RealScalar>& x)
|
static inline std::complex<RealScalar> run(const std::complex<RealScalar>& x)
|
||||||
{
|
{
|
||||||
return std::conj(x);
|
using std::conj;
|
||||||
|
return conj(x);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -270,7 +273,8 @@ struct abs_impl
|
|||||||
typedef typename NumTraits<Scalar>::Real RealScalar;
|
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||||
static inline RealScalar run(const Scalar& x)
|
static inline RealScalar run(const Scalar& x)
|
||||||
{
|
{
|
||||||
return std::abs(x);
|
using std::abs;
|
||||||
|
return abs(x);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -305,7 +309,8 @@ struct abs2_impl<std::complex<RealScalar> >
|
|||||||
{
|
{
|
||||||
static inline RealScalar run(const std::complex<RealScalar>& x)
|
static inline RealScalar run(const std::complex<RealScalar>& x)
|
||||||
{
|
{
|
||||||
return std::norm(x);
|
using std::norm;
|
||||||
|
return norm(x);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -369,10 +374,12 @@ struct hypot_impl
|
|||||||
typedef typename NumTraits<Scalar>::Real RealScalar;
|
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||||
static inline RealScalar run(const Scalar& x, const Scalar& y)
|
static inline RealScalar run(const Scalar& x, const Scalar& y)
|
||||||
{
|
{
|
||||||
|
using std::max;
|
||||||
|
using std::min;
|
||||||
RealScalar _x = abs(x);
|
RealScalar _x = abs(x);
|
||||||
RealScalar _y = abs(y);
|
RealScalar _y = abs(y);
|
||||||
RealScalar p = std::max(_x, _y);
|
RealScalar p = (max)(_x, _y);
|
||||||
RealScalar q = std::min(_x, _y);
|
RealScalar q = (min)(_x, _y);
|
||||||
RealScalar qp = q/p;
|
RealScalar qp = q/p;
|
||||||
return p * sqrt(RealScalar(1) + qp*qp);
|
return p * sqrt(RealScalar(1) + qp*qp);
|
||||||
}
|
}
|
||||||
@@ -420,7 +427,8 @@ struct sqrt_default_impl
|
|||||||
{
|
{
|
||||||
static inline Scalar run(const Scalar& x)
|
static inline Scalar run(const Scalar& x)
|
||||||
{
|
{
|
||||||
return std::sqrt(x);
|
using std::sqrt;
|
||||||
|
return sqrt(x);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -460,7 +468,7 @@ inline EIGEN_MATHFUNC_RETVAL(sqrt, Scalar) sqrt(const Scalar& x)
|
|||||||
// This macro instanciate all the necessary template mechanism which is common to all unary real functions.
|
// This macro instanciate all the necessary template mechanism which is common to all unary real functions.
|
||||||
#define EIGEN_MATHFUNC_STANDARD_REAL_UNARY(NAME) \
|
#define EIGEN_MATHFUNC_STANDARD_REAL_UNARY(NAME) \
|
||||||
template<typename Scalar, bool IsInteger> struct NAME##_default_impl { \
|
template<typename Scalar, bool IsInteger> struct NAME##_default_impl { \
|
||||||
static inline Scalar run(const Scalar& x) { return std::NAME(x); } \
|
static inline Scalar run(const Scalar& x) { using std::NAME; return NAME(x); } \
|
||||||
}; \
|
}; \
|
||||||
template<typename Scalar> struct NAME##_default_impl<Scalar, true> { \
|
template<typename Scalar> struct NAME##_default_impl<Scalar, true> { \
|
||||||
static inline Scalar run(const Scalar&) { \
|
static inline Scalar run(const Scalar&) { \
|
||||||
@@ -495,7 +503,8 @@ struct atan2_default_impl
|
|||||||
typedef Scalar retval;
|
typedef Scalar retval;
|
||||||
static inline Scalar run(const Scalar& x, const Scalar& y)
|
static inline Scalar run(const Scalar& x, const Scalar& y)
|
||||||
{
|
{
|
||||||
return std::atan2(x, y);
|
using std::atan2;
|
||||||
|
return atan2(x, y);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -534,7 +543,8 @@ struct pow_default_impl
|
|||||||
typedef Scalar retval;
|
typedef Scalar retval;
|
||||||
static inline Scalar run(const Scalar& x, const Scalar& y)
|
static inline Scalar run(const Scalar& x, const Scalar& y)
|
||||||
{
|
{
|
||||||
return std::pow(x, y);
|
using std::pow;
|
||||||
|
return pow(x, y);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -726,7 +736,8 @@ struct scalar_fuzzy_default_impl<Scalar, false, false>
|
|||||||
}
|
}
|
||||||
static inline bool isApprox(const Scalar& x, const Scalar& y, const RealScalar& prec)
|
static inline bool isApprox(const Scalar& x, const Scalar& y, const RealScalar& prec)
|
||||||
{
|
{
|
||||||
return abs(x - y) <= std::min(abs(x), abs(y)) * prec;
|
using std::min;
|
||||||
|
return abs(x - y) <= (min)(abs(x), abs(y)) * prec;
|
||||||
}
|
}
|
||||||
static inline bool isApproxOrLessThan(const Scalar& x, const Scalar& y, const RealScalar& prec)
|
static inline bool isApproxOrLessThan(const Scalar& x, const Scalar& y, const RealScalar& prec)
|
||||||
{
|
{
|
||||||
@@ -764,7 +775,8 @@ struct scalar_fuzzy_default_impl<Scalar, true, false>
|
|||||||
}
|
}
|
||||||
static inline bool isApprox(const Scalar& x, const Scalar& y, const RealScalar& prec)
|
static inline bool isApprox(const Scalar& x, const Scalar& y, const RealScalar& prec)
|
||||||
{
|
{
|
||||||
return abs2(x - y) <= std::min(abs2(x), abs2(y)) * prec * prec;
|
using std::min;
|
||||||
|
return abs2(x - y) <= (min)(abs2(x), abs2(y)) * prec * prec;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -43,8 +43,8 @@
|
|||||||
* \tparam _Cols Number of columns, or \b Dynamic
|
* \tparam _Cols Number of columns, or \b Dynamic
|
||||||
*
|
*
|
||||||
* The remaining template parameters are optional -- in most cases you don't have to worry about them.
|
* The remaining template parameters are optional -- in most cases you don't have to worry about them.
|
||||||
* \tparam _Options \anchor matrix_tparam_options A combination of either \b RowMajor or \b ColMajor, and of either
|
* \tparam _Options \anchor matrix_tparam_options A combination of either \b #RowMajor or \b #ColMajor, and of either
|
||||||
* \b AutoAlign or \b DontAlign.
|
* \b #AutoAlign or \b #DontAlign.
|
||||||
* The former controls \ref TopicStorageOrders "storage order", and defaults to column-major. The latter controls alignment, which is required
|
* The former controls \ref TopicStorageOrders "storage order", and defaults to column-major. The latter controls alignment, which is required
|
||||||
* for vectorization. It defaults to aligning matrices except for fixed sizes that aren't a multiple of the packet size.
|
* for vectorization. It defaults to aligning matrices except for fixed sizes that aren't a multiple of the packet size.
|
||||||
* \tparam _MaxRows Maximum number of rows. Defaults to \a _Rows (\ref maxrows "note").
|
* \tparam _MaxRows Maximum number of rows. Defaults to \a _Rows (\ref maxrows "note").
|
||||||
|
|||||||
@@ -111,7 +111,7 @@ template<typename Derived> class MatrixBase
|
|||||||
|
|
||||||
/** \returns the size of the main diagonal, which is min(rows(),cols()).
|
/** \returns the size of the main diagonal, which is min(rows(),cols()).
|
||||||
* \sa rows(), cols(), SizeAtCompileTime. */
|
* \sa rows(), cols(), SizeAtCompileTime. */
|
||||||
inline Index diagonalSize() const { return std::min(rows(),cols()); }
|
inline Index diagonalSize() const { return (std::min)(rows(),cols()); }
|
||||||
|
|
||||||
/** \brief The plain matrix type corresponding to this expression.
|
/** \brief The plain matrix type corresponding to this expression.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -87,8 +87,8 @@ template<typename T> struct GenericNumTraits
|
|||||||
// make sure to override this for floating-point types
|
// make sure to override this for floating-point types
|
||||||
return Real(0);
|
return Real(0);
|
||||||
}
|
}
|
||||||
inline static T highest() { return std::numeric_limits<T>::max(); }
|
inline static T highest() { return (std::numeric_limits<T>::max)(); }
|
||||||
inline static T lowest() { return IsInteger ? std::numeric_limits<T>::min() : (-std::numeric_limits<T>::max()); }
|
inline static T lowest() { return IsInteger ? (std::numeric_limits<T>::min)() : (-(std::numeric_limits<T>::max)()); }
|
||||||
|
|
||||||
#ifdef EIGEN2_SUPPORT
|
#ifdef EIGEN2_SUPPORT
|
||||||
enum {
|
enum {
|
||||||
|
|||||||
@@ -647,8 +647,8 @@ struct internal::conservative_resize_like_impl
|
|||||||
{
|
{
|
||||||
// The storage order does not allow us to use reallocation.
|
// The storage order does not allow us to use reallocation.
|
||||||
typename Derived::PlainObject tmp(rows,cols);
|
typename Derived::PlainObject tmp(rows,cols);
|
||||||
const Index common_rows = std::min(rows, _this.rows());
|
const Index common_rows = (std::min)(rows, _this.rows());
|
||||||
const Index common_cols = std::min(cols, _this.cols());
|
const Index common_cols = (std::min)(cols, _this.cols());
|
||||||
tmp.block(0,0,common_rows,common_cols) = _this.block(0,0,common_rows,common_cols);
|
tmp.block(0,0,common_rows,common_cols) = _this.block(0,0,common_rows,common_cols);
|
||||||
_this.derived().swap(tmp);
|
_this.derived().swap(tmp);
|
||||||
}
|
}
|
||||||
@@ -681,8 +681,8 @@ struct internal::conservative_resize_like_impl
|
|||||||
{
|
{
|
||||||
// The storage order does not allow us to use reallocation.
|
// The storage order does not allow us to use reallocation.
|
||||||
typename Derived::PlainObject tmp(other);
|
typename Derived::PlainObject tmp(other);
|
||||||
const Index common_rows = std::min(tmp.rows(), _this.rows());
|
const Index common_rows = (std::min)(tmp.rows(), _this.rows());
|
||||||
const Index common_cols = std::min(tmp.cols(), _this.cols());
|
const Index common_cols = (std::min)(tmp.cols(), _this.cols());
|
||||||
tmp.block(0,0,common_rows,common_cols) = _this.block(0,0,common_rows,common_cols);
|
tmp.block(0,0,common_rows,common_cols) = _this.block(0,0,common_rows,common_cols);
|
||||||
_this.derived().swap(tmp);
|
_this.derived().swap(tmp);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -375,8 +375,23 @@ struct gemv_static_vector_if<Scalar,Size,Dynamic,true>
|
|||||||
template<typename Scalar,int Size,int MaxSize>
|
template<typename Scalar,int Size,int MaxSize>
|
||||||
struct gemv_static_vector_if<Scalar,Size,MaxSize,true>
|
struct gemv_static_vector_if<Scalar,Size,MaxSize,true>
|
||||||
{
|
{
|
||||||
|
#if EIGEN_ALIGN_STATICALLY
|
||||||
internal::plain_array<Scalar,EIGEN_SIZE_MIN_PREFER_FIXED(Size,MaxSize),0> m_data;
|
internal::plain_array<Scalar,EIGEN_SIZE_MIN_PREFER_FIXED(Size,MaxSize),0> m_data;
|
||||||
EIGEN_STRONG_INLINE Scalar* data() { return m_data.array; }
|
EIGEN_STRONG_INLINE Scalar* data() { return m_data.array; }
|
||||||
|
#else
|
||||||
|
// Some architectures cannot align on the stack,
|
||||||
|
// => let's manually enforce alignment by allocating more data and return the address of the first aligned element.
|
||||||
|
enum {
|
||||||
|
ForceAlignment = internal::packet_traits<Scalar>::Vectorizable,
|
||||||
|
PacketSize = internal::packet_traits<Scalar>::size
|
||||||
|
};
|
||||||
|
internal::plain_array<Scalar,EIGEN_SIZE_MIN_PREFER_FIXED(Size,MaxSize)+(ForceAlignment?PacketSize:0),0> m_data;
|
||||||
|
EIGEN_STRONG_INLINE Scalar* data() {
|
||||||
|
return ForceAlignment
|
||||||
|
? reinterpret_cast<Scalar*>((reinterpret_cast<size_t>(m_data.array) & ~(size_t(15))) + 16)
|
||||||
|
: m_data.array;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
template<> struct gemv_selector<OnTheRight,ColMajor,true>
|
template<> struct gemv_selector<OnTheRight,ColMajor,true>
|
||||||
@@ -411,28 +426,21 @@ template<> struct gemv_selector<OnTheRight,ColMajor,true>
|
|||||||
|
|
||||||
gemv_static_vector_if<ResScalar,Dest::SizeAtCompileTime,Dest::MaxSizeAtCompileTime,MightCannotUseDest> static_dest;
|
gemv_static_vector_if<ResScalar,Dest::SizeAtCompileTime,Dest::MaxSizeAtCompileTime,MightCannotUseDest> static_dest;
|
||||||
|
|
||||||
bool alphaIsCompatible = (!ComplexByReal) || (imag(actualAlpha)==RealScalar(0));
|
// this is written like this (i.e., with a ?:) to workaround an ICE with ICC 12
|
||||||
|
bool alphaIsCompatible = (!ComplexByReal) ? true : (imag(actualAlpha)==RealScalar(0));
|
||||||
bool evalToDest = EvalToDestAtCompileTime && alphaIsCompatible;
|
bool evalToDest = EvalToDestAtCompileTime && alphaIsCompatible;
|
||||||
|
|
||||||
RhsScalar compatibleAlpha = get_factor<ResScalar,RhsScalar>::run(actualAlpha);
|
RhsScalar compatibleAlpha = get_factor<ResScalar,RhsScalar>::run(actualAlpha);
|
||||||
|
|
||||||
ResScalar* actualDestPtr;
|
ei_declare_aligned_stack_constructed_variable(ResScalar,actualDestPtr,dest.size(),
|
||||||
bool freeDestPtr = false;
|
evalToDest ? dest.data() : static_dest.data());
|
||||||
if (evalToDest)
|
|
||||||
{
|
if(!evalToDest)
|
||||||
actualDestPtr = &dest.coeffRef(0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
#ifdef EIGEN_DENSE_STORAGE_CTOR_PLUGIN
|
#ifdef EIGEN_DENSE_STORAGE_CTOR_PLUGIN
|
||||||
int size = dest.size();
|
int size = dest.size();
|
||||||
EIGEN_DENSE_STORAGE_CTOR_PLUGIN
|
EIGEN_DENSE_STORAGE_CTOR_PLUGIN
|
||||||
#endif
|
#endif
|
||||||
if((actualDestPtr = static_dest.data())==0)
|
|
||||||
{
|
|
||||||
freeDestPtr = true;
|
|
||||||
actualDestPtr = ei_aligned_stack_new(ResScalar,dest.size());
|
|
||||||
}
|
|
||||||
if(!alphaIsCompatible)
|
if(!alphaIsCompatible)
|
||||||
{
|
{
|
||||||
MappedDest(actualDestPtr, dest.size()).setZero();
|
MappedDest(actualDestPtr, dest.size()).setZero();
|
||||||
@@ -456,7 +464,6 @@ template<> struct gemv_selector<OnTheRight,ColMajor,true>
|
|||||||
dest += actualAlpha * MappedDest(actualDestPtr, dest.size());
|
dest += actualAlpha * MappedDest(actualDestPtr, dest.size());
|
||||||
else
|
else
|
||||||
dest = MappedDest(actualDestPtr, dest.size());
|
dest = MappedDest(actualDestPtr, dest.size());
|
||||||
if(freeDestPtr) ei_aligned_stack_delete(ResScalar, actualDestPtr, dest.size());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -490,23 +497,15 @@ template<> struct gemv_selector<OnTheRight,RowMajor,true>
|
|||||||
|
|
||||||
gemv_static_vector_if<RhsScalar,_ActualRhsType::SizeAtCompileTime,_ActualRhsType::MaxSizeAtCompileTime,!DirectlyUseRhs> static_rhs;
|
gemv_static_vector_if<RhsScalar,_ActualRhsType::SizeAtCompileTime,_ActualRhsType::MaxSizeAtCompileTime,!DirectlyUseRhs> static_rhs;
|
||||||
|
|
||||||
RhsScalar* actualRhsPtr;
|
ei_declare_aligned_stack_constructed_variable(RhsScalar,actualRhsPtr,actualRhs.size(),
|
||||||
bool freeRhsPtr = false;
|
DirectlyUseRhs ? const_cast<RhsScalar*>(actualRhs.data()) : static_rhs.data());
|
||||||
if (DirectlyUseRhs)
|
|
||||||
{
|
if(!DirectlyUseRhs)
|
||||||
actualRhsPtr = const_cast<RhsScalar*>(&actualRhs.coeffRef(0));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
#ifdef EIGEN_DENSE_STORAGE_CTOR_PLUGIN
|
#ifdef EIGEN_DENSE_STORAGE_CTOR_PLUGIN
|
||||||
int size = actualRhs.size();
|
int size = actualRhs.size();
|
||||||
EIGEN_DENSE_STORAGE_CTOR_PLUGIN
|
EIGEN_DENSE_STORAGE_CTOR_PLUGIN
|
||||||
#endif
|
#endif
|
||||||
if((actualRhsPtr = static_rhs.data())==0)
|
|
||||||
{
|
|
||||||
freeRhsPtr = true;
|
|
||||||
actualRhsPtr = ei_aligned_stack_new(RhsScalar, actualRhs.size());
|
|
||||||
}
|
|
||||||
Map<typename _ActualRhsType::PlainObject>(actualRhsPtr, actualRhs.size()) = actualRhs;
|
Map<typename _ActualRhsType::PlainObject>(actualRhsPtr, actualRhs.size()) = actualRhs;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -517,8 +516,6 @@ template<> struct gemv_selector<OnTheRight,RowMajor,true>
|
|||||||
actualRhsPtr, 1,
|
actualRhsPtr, 1,
|
||||||
&dest.coeffRef(0,0), dest.innerStride(),
|
&dest.coeffRef(0,0), dest.innerStride(),
|
||||||
actualAlpha);
|
actualAlpha);
|
||||||
|
|
||||||
if((!DirectlyUseRhs) && freeRhsPtr) ei_aligned_stack_delete(RhsScalar, actualRhsPtr, prod.rhs().size());
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -32,13 +32,13 @@
|
|||||||
* \brief Expression of a selfadjoint matrix from a triangular part of a dense matrix
|
* \brief Expression of a selfadjoint matrix from a triangular part of a dense matrix
|
||||||
*
|
*
|
||||||
* \param MatrixType the type of the dense matrix storing the coefficients
|
* \param MatrixType the type of the dense matrix storing the coefficients
|
||||||
* \param TriangularPart can be either \c Lower or \c Upper
|
* \param TriangularPart can be either \c #Lower or \c #Upper
|
||||||
*
|
*
|
||||||
* This class is an expression of a sefladjoint matrix from a triangular part of a matrix
|
* This class is an expression of a sefladjoint matrix from a triangular part of a matrix
|
||||||
* with given dense storage of the coefficients. It is the return type of MatrixBase::selfadjointView()
|
* with given dense storage of the coefficients. It is the return type of MatrixBase::selfadjointView()
|
||||||
* and most of the time this is the only way that it is used.
|
* and most of the time this is the only way that it is used.
|
||||||
*
|
*
|
||||||
* \sa class TriangularBase, MatrixBase::selfAdjointView()
|
* \sa class TriangularBase, MatrixBase::selfadjointView()
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|||||||
@@ -74,26 +74,19 @@ struct triangular_solver_selector<Lhs,Rhs,Side,Mode,NoUnrolling,1>
|
|||||||
// FIXME find a way to allow an inner stride if packet_traits<Scalar>::size==1
|
// FIXME find a way to allow an inner stride if packet_traits<Scalar>::size==1
|
||||||
|
|
||||||
bool useRhsDirectly = Rhs::InnerStrideAtCompileTime==1 || rhs.innerStride()==1;
|
bool useRhsDirectly = Rhs::InnerStrideAtCompileTime==1 || rhs.innerStride()==1;
|
||||||
RhsScalar* actualRhs;
|
|
||||||
if(useRhsDirectly)
|
ei_declare_aligned_stack_constructed_variable(RhsScalar,actualRhs,rhs.size(),
|
||||||
{
|
(useRhsDirectly ? rhs.data() : 0));
|
||||||
actualRhs = &rhs.coeffRef(0);
|
|
||||||
}
|
if(!useRhsDirectly)
|
||||||
else
|
|
||||||
{
|
|
||||||
actualRhs = ei_aligned_stack_new(RhsScalar,rhs.size());
|
|
||||||
MappedRhs(actualRhs,rhs.size()) = rhs;
|
MappedRhs(actualRhs,rhs.size()) = rhs;
|
||||||
}
|
|
||||||
|
|
||||||
triangular_solve_vector<LhsScalar, RhsScalar, typename Lhs::Index, Side, Mode, LhsProductTraits::NeedToConjugate,
|
triangular_solve_vector<LhsScalar, RhsScalar, typename Lhs::Index, Side, Mode, LhsProductTraits::NeedToConjugate,
|
||||||
(int(Lhs::Flags) & RowMajorBit) ? RowMajor : ColMajor>
|
(int(Lhs::Flags) & RowMajorBit) ? RowMajor : ColMajor>
|
||||||
::run(actualLhs.cols(), actualLhs.data(), actualLhs.outerStride(), actualRhs);
|
::run(actualLhs.cols(), actualLhs.data(), actualLhs.outerStride(), actualRhs);
|
||||||
|
|
||||||
if(!useRhsDirectly)
|
if(!useRhsDirectly)
|
||||||
{
|
|
||||||
rhs = MappedRhs(actualRhs, rhs.size());
|
rhs = MappedRhs(actualRhs, rhs.size());
|
||||||
ei_aligned_stack_delete(RhsScalar, actualRhs, rhs.size());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ template<typename Derived>
|
|||||||
inline typename NumTraits<typename internal::traits<Derived>::Scalar>::Real
|
inline typename NumTraits<typename internal::traits<Derived>::Scalar>::Real
|
||||||
MatrixBase<Derived>::stableNorm() const
|
MatrixBase<Derived>::stableNorm() const
|
||||||
{
|
{
|
||||||
|
using std::min;
|
||||||
const Index blockSize = 4096;
|
const Index blockSize = 4096;
|
||||||
RealScalar scale = 0;
|
RealScalar scale = 0;
|
||||||
RealScalar invScale = 1;
|
RealScalar invScale = 1;
|
||||||
@@ -68,7 +69,7 @@ MatrixBase<Derived>::stableNorm() const
|
|||||||
if (bi>0)
|
if (bi>0)
|
||||||
internal::stable_norm_kernel(this->head(bi), ssq, scale, invScale);
|
internal::stable_norm_kernel(this->head(bi), ssq, scale, invScale);
|
||||||
for (; bi<n; bi+=blockSize)
|
for (; bi<n; bi+=blockSize)
|
||||||
internal::stable_norm_kernel(this->segment(bi,std::min(blockSize, n - bi)).template forceAlignedAccessIf<Alignment>(), ssq, scale, invScale);
|
internal::stable_norm_kernel(this->segment(bi,(min)(blockSize, n - bi)).template forceAlignedAccessIf<Alignment>(), ssq, scale, invScale);
|
||||||
return scale * internal::sqrt(ssq);
|
return scale * internal::sqrt(ssq);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,6 +86,9 @@ template<typename Derived>
|
|||||||
inline typename NumTraits<typename internal::traits<Derived>::Scalar>::Real
|
inline typename NumTraits<typename internal::traits<Derived>::Scalar>::Real
|
||||||
MatrixBase<Derived>::blueNorm() const
|
MatrixBase<Derived>::blueNorm() const
|
||||||
{
|
{
|
||||||
|
using std::pow;
|
||||||
|
using std::min;
|
||||||
|
using std::max;
|
||||||
static Index nmax = -1;
|
static Index nmax = -1;
|
||||||
static RealScalar b1, b2, s1m, s2m, overfl, rbig, relerr;
|
static RealScalar b1, b2, s1m, s2m, overfl, rbig, relerr;
|
||||||
if(nmax <= 0)
|
if(nmax <= 0)
|
||||||
@@ -99,25 +103,25 @@ MatrixBase<Derived>::blueNorm() const
|
|||||||
// For portability, the PORT subprograms "ilmaeh" and "rlmach"
|
// For portability, the PORT subprograms "ilmaeh" and "rlmach"
|
||||||
// are used. For any specific computer, each of the assignment
|
// are used. For any specific computer, each of the assignment
|
||||||
// statements can be replaced
|
// statements can be replaced
|
||||||
nbig = std::numeric_limits<Index>::max(); // largest integer
|
nbig = (std::numeric_limits<Index>::max)(); // largest integer
|
||||||
ibeta = std::numeric_limits<RealScalar>::radix; // base for floating-point numbers
|
ibeta = std::numeric_limits<RealScalar>::radix; // base for floating-point numbers
|
||||||
it = std::numeric_limits<RealScalar>::digits; // number of base-beta digits in mantissa
|
it = std::numeric_limits<RealScalar>::digits; // number of base-beta digits in mantissa
|
||||||
iemin = std::numeric_limits<RealScalar>::min_exponent; // minimum exponent
|
iemin = std::numeric_limits<RealScalar>::min_exponent; // minimum exponent
|
||||||
iemax = std::numeric_limits<RealScalar>::max_exponent; // maximum exponent
|
iemax = std::numeric_limits<RealScalar>::max_exponent; // maximum exponent
|
||||||
rbig = std::numeric_limits<RealScalar>::max(); // largest floating-point number
|
rbig = (std::numeric_limits<RealScalar>::max)(); // largest floating-point number
|
||||||
|
|
||||||
iexp = -((1-iemin)/2);
|
iexp = -((1-iemin)/2);
|
||||||
b1 = RealScalar(std::pow(RealScalar(ibeta),RealScalar(iexp))); // lower boundary of midrange
|
b1 = RealScalar(pow(RealScalar(ibeta),RealScalar(iexp))); // lower boundary of midrange
|
||||||
iexp = (iemax + 1 - it)/2;
|
iexp = (iemax + 1 - it)/2;
|
||||||
b2 = RealScalar(std::pow(RealScalar(ibeta),RealScalar(iexp))); // upper boundary of midrange
|
b2 = RealScalar(pow(RealScalar(ibeta),RealScalar(iexp))); // upper boundary of midrange
|
||||||
|
|
||||||
iexp = (2-iemin)/2;
|
iexp = (2-iemin)/2;
|
||||||
s1m = RealScalar(std::pow(RealScalar(ibeta),RealScalar(iexp))); // scaling factor for lower range
|
s1m = RealScalar(pow(RealScalar(ibeta),RealScalar(iexp))); // scaling factor for lower range
|
||||||
iexp = - ((iemax+it)/2);
|
iexp = - ((iemax+it)/2);
|
||||||
s2m = RealScalar(std::pow(RealScalar(ibeta),RealScalar(iexp))); // scaling factor for upper range
|
s2m = RealScalar(pow(RealScalar(ibeta),RealScalar(iexp))); // scaling factor for upper range
|
||||||
|
|
||||||
overfl = rbig*s2m; // overflow boundary for abig
|
overfl = rbig*s2m; // overflow boundary for abig
|
||||||
eps = RealScalar(std::pow(double(ibeta), 1-it));
|
eps = RealScalar(pow(double(ibeta), 1-it));
|
||||||
relerr = internal::sqrt(eps); // tolerance for neglecting asml
|
relerr = internal::sqrt(eps); // tolerance for neglecting asml
|
||||||
abig = RealScalar(1.0/eps - 1.0);
|
abig = RealScalar(1.0/eps - 1.0);
|
||||||
if (RealScalar(nbig)>abig) nmax = int(abig); // largest safe n
|
if (RealScalar(nbig)>abig) nmax = int(abig); // largest safe n
|
||||||
@@ -163,8 +167,8 @@ MatrixBase<Derived>::blueNorm() const
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
return internal::sqrt(amed);
|
return internal::sqrt(amed);
|
||||||
asml = std::min(abig, amed);
|
asml = (min)(abig, amed);
|
||||||
abig = std::max(abig, amed);
|
abig = (max)(abig, amed);
|
||||||
if(asml <= abig*relerr)
|
if(asml <= abig*relerr)
|
||||||
return abig;
|
return abig;
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -350,15 +350,14 @@ struct blas_traits<SelfCwiseBinaryOp<BinOp,NestedXpr,Rhs> >
|
|||||||
template<bool DestIsTransposed, typename OtherDerived>
|
template<bool DestIsTransposed, typename OtherDerived>
|
||||||
struct check_transpose_aliasing_compile_time_selector
|
struct check_transpose_aliasing_compile_time_selector
|
||||||
{
|
{
|
||||||
enum { ret = blas_traits<OtherDerived>::IsTransposed != DestIsTransposed
|
enum { ret = bool(blas_traits<OtherDerived>::IsTransposed) != DestIsTransposed };
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<bool DestIsTransposed, typename BinOp, typename DerivedA, typename DerivedB>
|
template<bool DestIsTransposed, typename BinOp, typename DerivedA, typename DerivedB>
|
||||||
struct check_transpose_aliasing_compile_time_selector<DestIsTransposed,CwiseBinaryOp<BinOp,DerivedA,DerivedB> >
|
struct check_transpose_aliasing_compile_time_selector<DestIsTransposed,CwiseBinaryOp<BinOp,DerivedA,DerivedB> >
|
||||||
{
|
{
|
||||||
enum { ret = blas_traits<DerivedA>::IsTransposed != DestIsTransposed
|
enum { ret = bool(blas_traits<DerivedA>::IsTransposed) != DestIsTransposed
|
||||||
|| blas_traits<DerivedB>::IsTransposed != DestIsTransposed
|
|| bool(blas_traits<DerivedB>::IsTransposed) != DestIsTransposed
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -367,7 +366,7 @@ struct check_transpose_aliasing_run_time_selector
|
|||||||
{
|
{
|
||||||
static bool run(const Scalar* dest, const OtherDerived& src)
|
static bool run(const Scalar* dest, const OtherDerived& src)
|
||||||
{
|
{
|
||||||
return (blas_traits<OtherDerived>::IsTransposed != DestIsTransposed) && (dest!=0 && dest==(Scalar*)extract_data(src));
|
return (bool(blas_traits<OtherDerived>::IsTransposed) != DestIsTransposed) && (dest!=0 && dest==(Scalar*)extract_data(src));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -111,6 +111,7 @@ template<typename Derived> class TriangularBase : public EigenBase<Derived>
|
|||||||
EIGEN_ONLY_USED_FOR_DEBUG(col);
|
EIGEN_ONLY_USED_FOR_DEBUG(col);
|
||||||
eigen_assert(col>=0 && col<cols() && row>=0 && row<rows());
|
eigen_assert(col>=0 && col<cols() && row>=0 && row<rows());
|
||||||
const int mode = int(Mode) & ~SelfAdjoint;
|
const int mode = int(Mode) & ~SelfAdjoint;
|
||||||
|
EIGEN_ONLY_USED_FOR_DEBUG(mode);
|
||||||
eigen_assert((mode==Upper && col>=row)
|
eigen_assert((mode==Upper && col>=row)
|
||||||
|| (mode==Lower && col<=row)
|
|| (mode==Lower && col<=row)
|
||||||
|| ((mode==StrictlyUpper || mode==UnitUpper) && col>row)
|
|| ((mode==StrictlyUpper || mode==UnitUpper) && col>row)
|
||||||
@@ -134,13 +135,13 @@ template<typename Derived> class TriangularBase : public EigenBase<Derived>
|
|||||||
* \brief Base class for triangular part in a matrix
|
* \brief Base class for triangular part in a matrix
|
||||||
*
|
*
|
||||||
* \param MatrixType the type of the object in which we are taking the triangular part
|
* \param MatrixType the type of the object in which we are taking the triangular part
|
||||||
* \param Mode the kind of triangular matrix expression to construct. Can be Upper,
|
* \param Mode the kind of triangular matrix expression to construct. Can be #Upper,
|
||||||
* Lower, UpperSelfadjoint, or LowerSelfadjoint. This is in fact a bit field;
|
* #Lower, #UnitUpper, #UnitLower, #StrictlyUpper, or #StrictlyLower.
|
||||||
* it must have either Upper or Lower, and additionnaly it may have either
|
* This is in fact a bit field; it must have either #Upper or #Lower,
|
||||||
* UnitDiag or Selfadjoint.
|
* and additionnaly it may have #UnitDiag or #ZeroDiag or neither.
|
||||||
*
|
*
|
||||||
* This class represents a triangular part of a matrix, not necessarily square. Strictly speaking, for rectangular
|
* This class represents a triangular part of a matrix, not necessarily square. Strictly speaking, for rectangular
|
||||||
* matrices one should speak ok "trapezoid" parts. This class is the return type
|
* matrices one should speak of "trapezoid" parts. This class is the return type
|
||||||
* of MatrixBase::triangularView() and most of the time this is the only way it is used.
|
* of MatrixBase::triangularView() and most of the time this is the only way it is used.
|
||||||
*
|
*
|
||||||
* \sa MatrixBase::triangularView()
|
* \sa MatrixBase::triangularView()
|
||||||
@@ -448,6 +449,8 @@ struct triangular_assignment_selector
|
|||||||
col = (UnrollCount-1) / Derived1::RowsAtCompileTime,
|
col = (UnrollCount-1) / Derived1::RowsAtCompileTime,
|
||||||
row = (UnrollCount-1) % Derived1::RowsAtCompileTime
|
row = (UnrollCount-1) % Derived1::RowsAtCompileTime
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef typename Derived1::Scalar Scalar;
|
||||||
|
|
||||||
inline static void run(Derived1 &dst, const Derived2 &src)
|
inline static void run(Derived1 &dst, const Derived2 &src)
|
||||||
{
|
{
|
||||||
@@ -466,9 +469,9 @@ struct triangular_assignment_selector
|
|||||||
else if(ClearOpposite)
|
else if(ClearOpposite)
|
||||||
{
|
{
|
||||||
if (Mode&UnitDiag && row==col)
|
if (Mode&UnitDiag && row==col)
|
||||||
dst.coeffRef(row, col) = 1;
|
dst.coeffRef(row, col) = Scalar(1);
|
||||||
else
|
else
|
||||||
dst.coeffRef(row, col) = 0;
|
dst.coeffRef(row, col) = Scalar(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -484,16 +487,17 @@ template<typename Derived1, typename Derived2, bool ClearOpposite>
|
|||||||
struct triangular_assignment_selector<Derived1, Derived2, Upper, Dynamic, ClearOpposite>
|
struct triangular_assignment_selector<Derived1, Derived2, Upper, Dynamic, ClearOpposite>
|
||||||
{
|
{
|
||||||
typedef typename Derived1::Index Index;
|
typedef typename Derived1::Index Index;
|
||||||
|
typedef typename Derived1::Scalar Scalar;
|
||||||
inline static void run(Derived1 &dst, const Derived2 &src)
|
inline static void run(Derived1 &dst, const Derived2 &src)
|
||||||
{
|
{
|
||||||
for(Index j = 0; j < dst.cols(); ++j)
|
for(Index j = 0; j < dst.cols(); ++j)
|
||||||
{
|
{
|
||||||
Index maxi = std::min(j, dst.rows()-1);
|
Index maxi = (std::min)(j, dst.rows()-1);
|
||||||
for(Index i = 0; i <= maxi; ++i)
|
for(Index i = 0; i <= maxi; ++i)
|
||||||
dst.copyCoeff(i, j, src);
|
dst.copyCoeff(i, j, src);
|
||||||
if (ClearOpposite)
|
if (ClearOpposite)
|
||||||
for(Index i = maxi+1; i < dst.rows(); ++i)
|
for(Index i = maxi+1; i < dst.rows(); ++i)
|
||||||
dst.coeffRef(i, j) = 0;
|
dst.coeffRef(i, j) = Scalar(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -508,10 +512,10 @@ struct triangular_assignment_selector<Derived1, Derived2, Lower, Dynamic, ClearO
|
|||||||
{
|
{
|
||||||
for(Index i = j; i < dst.rows(); ++i)
|
for(Index i = j; i < dst.rows(); ++i)
|
||||||
dst.copyCoeff(i, j, src);
|
dst.copyCoeff(i, j, src);
|
||||||
Index maxi = std::min(j, dst.rows());
|
Index maxi = (std::min)(j, dst.rows());
|
||||||
if (ClearOpposite)
|
if (ClearOpposite)
|
||||||
for(Index i = 0; i < maxi; ++i)
|
for(Index i = 0; i < maxi; ++i)
|
||||||
dst.coeffRef(i, j) = 0;
|
dst.coeffRef(i, j) = static_cast<typename Derived1::Scalar>(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -524,7 +528,7 @@ struct triangular_assignment_selector<Derived1, Derived2, StrictlyUpper, Dynamic
|
|||||||
{
|
{
|
||||||
for(Index j = 0; j < dst.cols(); ++j)
|
for(Index j = 0; j < dst.cols(); ++j)
|
||||||
{
|
{
|
||||||
Index maxi = std::min(j, dst.rows());
|
Index maxi = (std::min)(j, dst.rows());
|
||||||
for(Index i = 0; i < maxi; ++i)
|
for(Index i = 0; i < maxi; ++i)
|
||||||
dst.copyCoeff(i, j, src);
|
dst.copyCoeff(i, j, src);
|
||||||
if (ClearOpposite)
|
if (ClearOpposite)
|
||||||
@@ -544,10 +548,10 @@ struct triangular_assignment_selector<Derived1, Derived2, StrictlyLower, Dynamic
|
|||||||
{
|
{
|
||||||
for(Index i = j+1; i < dst.rows(); ++i)
|
for(Index i = j+1; i < dst.rows(); ++i)
|
||||||
dst.copyCoeff(i, j, src);
|
dst.copyCoeff(i, j, src);
|
||||||
Index maxi = std::min(j, dst.rows()-1);
|
Index maxi = (std::min)(j, dst.rows()-1);
|
||||||
if (ClearOpposite)
|
if (ClearOpposite)
|
||||||
for(Index i = 0; i <= maxi; ++i)
|
for(Index i = 0; i <= maxi; ++i)
|
||||||
dst.coeffRef(i, j) = 0;
|
dst.coeffRef(i, j) = static_cast<typename Derived1::Scalar>(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -560,7 +564,7 @@ struct triangular_assignment_selector<Derived1, Derived2, UnitUpper, Dynamic, Cl
|
|||||||
{
|
{
|
||||||
for(Index j = 0; j < dst.cols(); ++j)
|
for(Index j = 0; j < dst.cols(); ++j)
|
||||||
{
|
{
|
||||||
Index maxi = std::min(j, dst.rows());
|
Index maxi = (std::min)(j, dst.rows());
|
||||||
for(Index i = 0; i < maxi; ++i)
|
for(Index i = 0; i < maxi; ++i)
|
||||||
dst.copyCoeff(i, j, src);
|
dst.copyCoeff(i, j, src);
|
||||||
if (ClearOpposite)
|
if (ClearOpposite)
|
||||||
@@ -580,7 +584,7 @@ struct triangular_assignment_selector<Derived1, Derived2, UnitLower, Dynamic, Cl
|
|||||||
{
|
{
|
||||||
for(Index j = 0; j < dst.cols(); ++j)
|
for(Index j = 0; j < dst.cols(); ++j)
|
||||||
{
|
{
|
||||||
Index maxi = std::min(j, dst.rows());
|
Index maxi = (std::min)(j, dst.rows());
|
||||||
for(Index i = maxi+1; i < dst.rows(); ++i)
|
for(Index i = maxi+1; i < dst.rows(); ++i)
|
||||||
dst.copyCoeff(i, j, src);
|
dst.copyCoeff(i, j, src);
|
||||||
if (ClearOpposite)
|
if (ClearOpposite)
|
||||||
@@ -756,8 +760,8 @@ typename internal::eigen2_part_return_type<Derived, Mode>::type MatrixBase<Deriv
|
|||||||
/**
|
/**
|
||||||
* \returns an expression of a triangular view extracted from the current matrix
|
* \returns an expression of a triangular view extracted from the current matrix
|
||||||
*
|
*
|
||||||
* The parameter \a Mode can have the following values: \c Upper, \c StrictlyUpper, \c UnitUpper,
|
* The parameter \a Mode can have the following values: \c #Upper, \c #StrictlyUpper, \c #UnitUpper,
|
||||||
* \c Lower, \c StrictlyLower, \c UnitLower.
|
* \c #Lower, \c #StrictlyLower, \c #UnitLower.
|
||||||
*
|
*
|
||||||
* Example: \include MatrixBase_extract.cpp
|
* Example: \include MatrixBase_extract.cpp
|
||||||
* Output: \verbinclude MatrixBase_extract.out
|
* Output: \verbinclude MatrixBase_extract.out
|
||||||
@@ -792,7 +796,7 @@ bool MatrixBase<Derived>::isUpperTriangular(RealScalar prec) const
|
|||||||
RealScalar maxAbsOnUpperPart = static_cast<RealScalar>(-1);
|
RealScalar maxAbsOnUpperPart = static_cast<RealScalar>(-1);
|
||||||
for(Index j = 0; j < cols(); ++j)
|
for(Index j = 0; j < cols(); ++j)
|
||||||
{
|
{
|
||||||
Index maxi = std::min(j, rows()-1);
|
Index maxi = (std::min)(j, rows()-1);
|
||||||
for(Index i = 0; i <= maxi; ++i)
|
for(Index i = 0; i <= maxi; ++i)
|
||||||
{
|
{
|
||||||
RealScalar absValue = internal::abs(coeff(i,j));
|
RealScalar absValue = internal::abs(coeff(i,j));
|
||||||
@@ -824,7 +828,7 @@ bool MatrixBase<Derived>::isLowerTriangular(RealScalar prec) const
|
|||||||
RealScalar threshold = maxAbsOnLowerPart * prec;
|
RealScalar threshold = maxAbsOnLowerPart * prec;
|
||||||
for(Index j = 1; j < cols(); ++j)
|
for(Index j = 1; j < cols(); ++j)
|
||||||
{
|
{
|
||||||
Index maxi = std::min(j, rows()-1);
|
Index maxi = (std::min)(j, rows()-1);
|
||||||
for(Index i = 0; i < maxi; ++i)
|
for(Index i = 0; i < maxi; ++i)
|
||||||
if(internal::abs(coeff(i, j)) > threshold) return false;
|
if(internal::abs(coeff(i, j)) > threshold) return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,9 +31,9 @@
|
|||||||
*
|
*
|
||||||
* \brief Generic expression of a partially reduxed matrix
|
* \brief Generic expression of a partially reduxed matrix
|
||||||
*
|
*
|
||||||
* \param MatrixType the type of the matrix we are applying the redux operation
|
* \tparam MatrixType the type of the matrix we are applying the redux operation
|
||||||
* \param MemberOp type of the member functor
|
* \tparam MemberOp type of the member functor
|
||||||
* \param Direction indicates the direction of the redux (Vertical or Horizontal)
|
* \tparam Direction indicates the direction of the redux (#Vertical or #Horizontal)
|
||||||
*
|
*
|
||||||
* This class represents an expression of a partial redux operator of a matrix.
|
* This class represents an expression of a partial redux operator of a matrix.
|
||||||
* It is the return type of some VectorwiseOp functions,
|
* It is the return type of some VectorwiseOp functions,
|
||||||
@@ -164,7 +164,7 @@ struct member_redux {
|
|||||||
* \brief Pseudo expression providing partial reduction operations
|
* \brief Pseudo expression providing partial reduction operations
|
||||||
*
|
*
|
||||||
* \param ExpressionType the type of the object on which to do partial reductions
|
* \param ExpressionType the type of the object on which to do partial reductions
|
||||||
* \param Direction indicates the direction of the redux (Vertical or Horizontal)
|
* \param Direction indicates the direction of the redux (#Vertical or #Horizontal)
|
||||||
*
|
*
|
||||||
* This class represents a pseudo expression with partial reduction features.
|
* This class represents a pseudo expression with partial reduction features.
|
||||||
* It is the return type of DenseBase::colwise() and DenseBase::rowwise()
|
* It is the return type of DenseBase::colwise() and DenseBase::rowwise()
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ template<> struct packet_traits<std::complex<float> > : default_packet_traits
|
|||||||
typedef Packet2cf type;
|
typedef Packet2cf type;
|
||||||
enum {
|
enum {
|
||||||
Vectorizable = 1,
|
Vectorizable = 1,
|
||||||
|
AlignedOnScalar = 1,
|
||||||
size = 2,
|
size = 2,
|
||||||
|
|
||||||
HasAdd = 1,
|
HasAdd = 1,
|
||||||
|
|||||||
@@ -100,12 +100,12 @@ template<> EIGEN_STRONG_INLINE Packet4i pset1<Packet4i>(const int& from) {
|
|||||||
|
|
||||||
template<> EIGEN_STRONG_INLINE Packet4f plset<float>(const float& a)
|
template<> EIGEN_STRONG_INLINE Packet4f plset<float>(const float& a)
|
||||||
{
|
{
|
||||||
Packet4f countdown = { 3, 2, 1, 0 };
|
Packet4f countdown = { 0, 1, 2, 3 };
|
||||||
return vaddq_f32(pset1<Packet4f>(a), countdown);
|
return vaddq_f32(pset1<Packet4f>(a), countdown);
|
||||||
}
|
}
|
||||||
template<> EIGEN_STRONG_INLINE Packet4i plset<int>(const int& a)
|
template<> EIGEN_STRONG_INLINE Packet4i plset<int>(const int& a)
|
||||||
{
|
{
|
||||||
Packet4i countdown = { 3, 2, 1, 0 };
|
Packet4i countdown = { 0, 1, 2, 3 };
|
||||||
return vaddq_s32(pset1<Packet4i>(a), countdown);
|
return vaddq_s32(pset1<Packet4i>(a), countdown);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,14 +191,14 @@ template<> EIGEN_STRONG_INLINE Packet4f ploaddup<Packet4f>(const float* from)
|
|||||||
{
|
{
|
||||||
float32x2_t lo, hi;
|
float32x2_t lo, hi;
|
||||||
lo = vdup_n_f32(*from);
|
lo = vdup_n_f32(*from);
|
||||||
hi = vdup_n_f32(*from);
|
hi = vdup_n_f32(*(from+1));
|
||||||
return vcombine_f32(lo, hi);
|
return vcombine_f32(lo, hi);
|
||||||
}
|
}
|
||||||
template<> EIGEN_STRONG_INLINE Packet4i ploaddup<Packet4i>(const int* from)
|
template<> EIGEN_STRONG_INLINE Packet4i ploaddup<Packet4i>(const int* from)
|
||||||
{
|
{
|
||||||
int32x2_t lo, hi;
|
int32x2_t lo, hi;
|
||||||
lo = vdup_n_s32(*from);
|
lo = vdup_n_s32(*from);
|
||||||
hi = vdup_n_s32(*from);
|
hi = vdup_n_s32(*(from+1));
|
||||||
return vcombine_s32(lo, hi);
|
return vcombine_s32(lo, hi);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -81,6 +81,7 @@ inline void manage_caching_sizes(Action action, std::ptrdiff_t* l1=0, std::ptrdi
|
|||||||
template<typename LhsScalar, typename RhsScalar, int KcFactor>
|
template<typename LhsScalar, typename RhsScalar, int KcFactor>
|
||||||
void computeProductBlockingSizes(std::ptrdiff_t& k, std::ptrdiff_t& m, std::ptrdiff_t& n)
|
void computeProductBlockingSizes(std::ptrdiff_t& k, std::ptrdiff_t& m, std::ptrdiff_t& n)
|
||||||
{
|
{
|
||||||
|
EIGEN_UNUSED_VARIABLE(n);
|
||||||
// Explanations:
|
// Explanations:
|
||||||
// Let's recall the product algorithms form kc x nc horizontal panels B' on the rhs and
|
// Let's recall the product algorithms form kc x nc horizontal panels B' on the rhs and
|
||||||
// mc x kc blocks A' on the lhs. A' has to fit into L2 cache. Moreover, B' is processed
|
// mc x kc blocks A' on the lhs. A' has to fit into L2 cache. Moreover, B' is processed
|
||||||
@@ -102,7 +103,6 @@ void computeProductBlockingSizes(std::ptrdiff_t& k, std::ptrdiff_t& m, std::ptrd
|
|||||||
k = std::min<std::ptrdiff_t>(k, l1/kdiv);
|
k = std::min<std::ptrdiff_t>(k, l1/kdiv);
|
||||||
std::ptrdiff_t _m = k>0 ? l2/(4 * sizeof(LhsScalar) * k) : 0;
|
std::ptrdiff_t _m = k>0 ? l2/(4 * sizeof(LhsScalar) * k) : 0;
|
||||||
if(_m<m) m = _m & mr_mask;
|
if(_m<m) m = _m & mr_mask;
|
||||||
n = n;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename LhsScalar, typename RhsScalar>
|
template<typename LhsScalar, typename RhsScalar>
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ static void run(Index rows, Index cols, Index depth,
|
|||||||
typedef gebp_traits<LhsScalar,RhsScalar> Traits;
|
typedef gebp_traits<LhsScalar,RhsScalar> Traits;
|
||||||
|
|
||||||
Index kc = blocking.kc(); // cache block size along the K direction
|
Index kc = blocking.kc(); // cache block size along the K direction
|
||||||
Index mc = std::min(rows,blocking.mc()); // cache block size along the M direction
|
Index mc = (std::min)(rows,blocking.mc()); // cache block size along the M direction
|
||||||
//Index nc = blocking.nc(); // cache block size along the N direction
|
//Index nc = blocking.nc(); // cache block size along the N direction
|
||||||
|
|
||||||
gemm_pack_lhs<LhsScalar, Index, Traits::mr, Traits::LhsProgress, LhsStorageOrder> pack_lhs;
|
gemm_pack_lhs<LhsScalar, Index, Traits::mr, Traits::LhsProgress, LhsStorageOrder> pack_lhs;
|
||||||
@@ -94,15 +94,16 @@ static void run(Index rows, Index cols, Index depth,
|
|||||||
|
|
||||||
std::size_t sizeA = kc*mc;
|
std::size_t sizeA = kc*mc;
|
||||||
std::size_t sizeW = kc*Traits::WorkSpaceFactor;
|
std::size_t sizeW = kc*Traits::WorkSpaceFactor;
|
||||||
LhsScalar* blockA = ei_aligned_stack_new(LhsScalar, sizeA);
|
ei_declare_aligned_stack_constructed_variable(LhsScalar, blockA, sizeA, 0);
|
||||||
RhsScalar* w = ei_aligned_stack_new(RhsScalar, sizeW);
|
ei_declare_aligned_stack_constructed_variable(RhsScalar, w, sizeW, 0);
|
||||||
|
|
||||||
RhsScalar* blockB = blocking.blockB();
|
RhsScalar* blockB = blocking.blockB();
|
||||||
eigen_internal_assert(blockB!=0);
|
eigen_internal_assert(blockB!=0);
|
||||||
|
|
||||||
// For each horizontal panel of the rhs, and corresponding vertical panel of the lhs...
|
// For each horizontal panel of the rhs, and corresponding vertical panel of the lhs...
|
||||||
for(Index k=0; k<depth; k+=kc)
|
for(Index k=0; k<depth; k+=kc)
|
||||||
{
|
{
|
||||||
const Index actual_kc = std::min(k+kc,depth)-k; // => rows of B', and cols of the A'
|
const Index actual_kc = (std::min)(k+kc,depth)-k; // => rows of B', and cols of the A'
|
||||||
|
|
||||||
// In order to reduce the chance that a thread has to wait for the other,
|
// In order to reduce the chance that a thread has to wait for the other,
|
||||||
// let's start by packing A'.
|
// let's start by packing A'.
|
||||||
@@ -139,7 +140,7 @@ static void run(Index rows, Index cols, Index depth,
|
|||||||
// Then keep going as usual with the remaining A'
|
// Then keep going as usual with the remaining A'
|
||||||
for(Index i=mc; i<rows; i+=mc)
|
for(Index i=mc; i<rows; i+=mc)
|
||||||
{
|
{
|
||||||
const Index actual_mc = std::min(i+mc,rows)-i;
|
const Index actual_mc = (std::min)(i+mc,rows)-i;
|
||||||
|
|
||||||
// pack A_i,k to A'
|
// pack A_i,k to A'
|
||||||
pack_lhs(blockA, &lhs(i,k), lhsStride, actual_kc, actual_mc);
|
pack_lhs(blockA, &lhs(i,k), lhsStride, actual_kc, actual_mc);
|
||||||
@@ -154,9 +155,6 @@ static void run(Index rows, Index cols, Index depth,
|
|||||||
#pragma omp atomic
|
#pragma omp atomic
|
||||||
--(info[j].users);
|
--(info[j].users);
|
||||||
}
|
}
|
||||||
|
|
||||||
ei_aligned_stack_delete(LhsScalar, blockA, kc*mc);
|
|
||||||
ei_aligned_stack_delete(RhsScalar, w, sizeW);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif // EIGEN_HAS_OPENMP
|
#endif // EIGEN_HAS_OPENMP
|
||||||
@@ -167,15 +165,16 @@ static void run(Index rows, Index cols, Index depth,
|
|||||||
std::size_t sizeA = kc*mc;
|
std::size_t sizeA = kc*mc;
|
||||||
std::size_t sizeB = kc*cols;
|
std::size_t sizeB = kc*cols;
|
||||||
std::size_t sizeW = kc*Traits::WorkSpaceFactor;
|
std::size_t sizeW = kc*Traits::WorkSpaceFactor;
|
||||||
LhsScalar *blockA = blocking.blockA()==0 ? ei_aligned_stack_new(LhsScalar, sizeA) : blocking.blockA();
|
|
||||||
RhsScalar *blockB = blocking.blockB()==0 ? ei_aligned_stack_new(RhsScalar, sizeB) : blocking.blockB();
|
ei_declare_aligned_stack_constructed_variable(LhsScalar, blockA, sizeA, blocking.blockA());
|
||||||
RhsScalar *blockW = blocking.blockW()==0 ? ei_aligned_stack_new(RhsScalar, sizeW) : blocking.blockW();
|
ei_declare_aligned_stack_constructed_variable(RhsScalar, blockB, sizeB, blocking.blockB());
|
||||||
|
ei_declare_aligned_stack_constructed_variable(RhsScalar, blockW, sizeW, blocking.blockW());
|
||||||
|
|
||||||
// For each horizontal panel of the rhs, and corresponding panel of the lhs...
|
// For each horizontal panel of the rhs, and corresponding panel of the lhs...
|
||||||
// (==GEMM_VAR1)
|
// (==GEMM_VAR1)
|
||||||
for(Index k2=0; k2<depth; k2+=kc)
|
for(Index k2=0; k2<depth; k2+=kc)
|
||||||
{
|
{
|
||||||
const Index actual_kc = std::min(k2+kc,depth)-k2;
|
const Index actual_kc = (std::min)(k2+kc,depth)-k2;
|
||||||
|
|
||||||
// OK, here we have selected one horizontal panel of rhs and one vertical panel of lhs.
|
// OK, here we have selected one horizontal panel of rhs and one vertical panel of lhs.
|
||||||
// => Pack rhs's panel into a sequential chunk of memory (L2 caching)
|
// => Pack rhs's panel into a sequential chunk of memory (L2 caching)
|
||||||
@@ -188,7 +187,7 @@ static void run(Index rows, Index cols, Index depth,
|
|||||||
// (==GEPP_VAR1)
|
// (==GEPP_VAR1)
|
||||||
for(Index i2=0; i2<rows; i2+=mc)
|
for(Index i2=0; i2<rows; i2+=mc)
|
||||||
{
|
{
|
||||||
const Index actual_mc = std::min(i2+mc,rows)-i2;
|
const Index actual_mc = (std::min)(i2+mc,rows)-i2;
|
||||||
|
|
||||||
// We pack the lhs's block into a sequential chunk of memory (L1 caching)
|
// We pack the lhs's block into a sequential chunk of memory (L1 caching)
|
||||||
// Note that this block will be read a very high number of times, which is equal to the number of
|
// Note that this block will be read a very high number of times, which is equal to the number of
|
||||||
@@ -200,10 +199,6 @@ static void run(Index rows, Index cols, Index depth,
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(blocking.blockA()==0) ei_aligned_stack_delete(LhsScalar, blockA, sizeA);
|
|
||||||
if(blocking.blockB()==0) ei_aligned_stack_delete(RhsScalar, blockB, sizeB);
|
|
||||||
if(blocking.blockW()==0) ei_aligned_stack_delete(RhsScalar, blockW, sizeW);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -83,10 +83,10 @@ struct general_matrix_matrix_triangular_product<Index,LhsScalar,LhsStorageOrder,
|
|||||||
if(mc > Traits::nr)
|
if(mc > Traits::nr)
|
||||||
mc = (mc/Traits::nr)*Traits::nr;
|
mc = (mc/Traits::nr)*Traits::nr;
|
||||||
|
|
||||||
LhsScalar* blockA = ei_aligned_stack_new(LhsScalar, kc*mc);
|
|
||||||
std::size_t sizeW = kc*Traits::WorkSpaceFactor;
|
std::size_t sizeW = kc*Traits::WorkSpaceFactor;
|
||||||
std::size_t sizeB = sizeW + kc*size;
|
std::size_t sizeB = sizeW + kc*size;
|
||||||
RhsScalar* allocatedBlockB = ei_aligned_stack_new(RhsScalar, sizeB);
|
ei_declare_aligned_stack_constructed_variable(LhsScalar, blockA, kc*mc, 0);
|
||||||
|
ei_declare_aligned_stack_constructed_variable(RhsScalar, allocatedBlockB, sizeB, 0);
|
||||||
RhsScalar* blockB = allocatedBlockB + sizeW;
|
RhsScalar* blockB = allocatedBlockB + sizeW;
|
||||||
|
|
||||||
gemm_pack_lhs<LhsScalar, Index, Traits::mr, Traits::LhsProgress, LhsStorageOrder> pack_lhs;
|
gemm_pack_lhs<LhsScalar, Index, Traits::mr, Traits::LhsProgress, LhsStorageOrder> pack_lhs;
|
||||||
@@ -96,14 +96,14 @@ struct general_matrix_matrix_triangular_product<Index,LhsScalar,LhsStorageOrder,
|
|||||||
|
|
||||||
for(Index k2=0; k2<depth; k2+=kc)
|
for(Index k2=0; k2<depth; k2+=kc)
|
||||||
{
|
{
|
||||||
const Index actual_kc = std::min(k2+kc,depth)-k2;
|
const Index actual_kc = (std::min)(k2+kc,depth)-k2;
|
||||||
|
|
||||||
// note that the actual rhs is the transpose/adjoint of mat
|
// note that the actual rhs is the transpose/adjoint of mat
|
||||||
pack_rhs(blockB, &rhs(k2,0), rhsStride, actual_kc, size);
|
pack_rhs(blockB, &rhs(k2,0), rhsStride, actual_kc, size);
|
||||||
|
|
||||||
for(Index i2=0; i2<size; i2+=mc)
|
for(Index i2=0; i2<size; i2+=mc)
|
||||||
{
|
{
|
||||||
const Index actual_mc = std::min(i2+mc,size)-i2;
|
const Index actual_mc = (std::min)(i2+mc,size)-i2;
|
||||||
|
|
||||||
pack_lhs(blockA, &lhs(i2, k2), lhsStride, actual_kc, actual_mc);
|
pack_lhs(blockA, &lhs(i2, k2), lhsStride, actual_kc, actual_mc);
|
||||||
|
|
||||||
@@ -112,7 +112,7 @@ struct general_matrix_matrix_triangular_product<Index,LhsScalar,LhsStorageOrder,
|
|||||||
// 2 - the actual_mc x actual_mc symmetric block => processed with a special kernel
|
// 2 - the actual_mc x actual_mc symmetric block => processed with a special kernel
|
||||||
// 3 - after the diagonal => processed with gebp or skipped
|
// 3 - after the diagonal => processed with gebp or skipped
|
||||||
if (UpLo==Lower)
|
if (UpLo==Lower)
|
||||||
gebp(res+i2, resStride, blockA, blockB, actual_mc, actual_kc, std::min(size,i2), alpha,
|
gebp(res+i2, resStride, blockA, blockB, actual_mc, actual_kc, (std::min)(size,i2), alpha,
|
||||||
-1, -1, 0, 0, allocatedBlockB);
|
-1, -1, 0, 0, allocatedBlockB);
|
||||||
|
|
||||||
sybb(res+resStride*i2 + i2, resStride, blockA, blockB + actual_kc*i2, actual_mc, actual_kc, alpha, allocatedBlockB);
|
sybb(res+resStride*i2 + i2, resStride, blockA, blockB + actual_kc*i2, actual_mc, actual_kc, alpha, allocatedBlockB);
|
||||||
@@ -120,13 +120,11 @@ struct general_matrix_matrix_triangular_product<Index,LhsScalar,LhsStorageOrder,
|
|||||||
if (UpLo==Upper)
|
if (UpLo==Upper)
|
||||||
{
|
{
|
||||||
Index j2 = i2+actual_mc;
|
Index j2 = i2+actual_mc;
|
||||||
gebp(res+resStride*j2+i2, resStride, blockA, blockB+actual_kc*j2, actual_mc, actual_kc, std::max(Index(0), size-j2), alpha,
|
gebp(res+resStride*j2+i2, resStride, blockA, blockB+actual_kc*j2, actual_mc, actual_kc, (std::max)(Index(0), size-j2), alpha,
|
||||||
-1, -1, 0, 0, allocatedBlockB);
|
-1, -1, 0, 0, allocatedBlockB);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ei_aligned_stack_delete(LhsScalar, blockA, kc*mc);
|
|
||||||
ei_aligned_stack_delete(RhsScalar, allocatedBlockB, sizeB);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -134,7 +134,7 @@ EIGEN_DONT_INLINE static void run(
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
skipColumns = std::min(skipColumns,cols);
|
skipColumns = (std::min)(skipColumns,cols);
|
||||||
// note that the skiped columns are processed later.
|
// note that the skiped columns are processed later.
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -386,7 +386,7 @@ EIGEN_DONT_INLINE static void run(
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
skipRows = std::min(skipRows,Index(rows));
|
skipRows = (std::min)(skipRows,Index(rows));
|
||||||
// note that the skiped columns are processed later.
|
// note that the skiped columns are processed later.
|
||||||
}
|
}
|
||||||
eigen_internal_assert( alignmentPattern==NoneAligned
|
eigen_internal_assert( alignmentPattern==NoneAligned
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ struct symm_pack_rhs
|
|||||||
}
|
}
|
||||||
|
|
||||||
// second part: diagonal block
|
// second part: diagonal block
|
||||||
for(Index j2=k2; j2<std::min(k2+rows,packet_cols); j2+=nr)
|
for(Index j2=k2; j2<(std::min)(k2+rows,packet_cols); j2+=nr)
|
||||||
{
|
{
|
||||||
// again we can split vertically in three different parts (transpose, symmetric, normal)
|
// again we can split vertically in three different parts (transpose, symmetric, normal)
|
||||||
// transpose
|
// transpose
|
||||||
@@ -179,7 +179,7 @@ struct symm_pack_rhs
|
|||||||
for(Index j2=packet_cols; j2<cols; ++j2)
|
for(Index j2=packet_cols; j2<cols; ++j2)
|
||||||
{
|
{
|
||||||
// transpose
|
// transpose
|
||||||
Index half = std::min(end_k,j2);
|
Index half = (std::min)(end_k,j2);
|
||||||
for(Index k=k2; k<half; k++)
|
for(Index k=k2; k<half; k++)
|
||||||
{
|
{
|
||||||
blockB[count] = conj(rhs(j2,k));
|
blockB[count] = conj(rhs(j2,k));
|
||||||
@@ -261,12 +261,12 @@ struct product_selfadjoint_matrix<Scalar,Index,LhsStorageOrder,true,ConjugateLhs
|
|||||||
Index nc = cols; // cache block size along the N direction
|
Index nc = cols; // cache block size along the N direction
|
||||||
computeProductBlockingSizes<Scalar,Scalar>(kc, mc, nc);
|
computeProductBlockingSizes<Scalar,Scalar>(kc, mc, nc);
|
||||||
// kc must smaller than mc
|
// kc must smaller than mc
|
||||||
kc = std::min(kc,mc);
|
kc = (std::min)(kc,mc);
|
||||||
|
|
||||||
Scalar* blockA = ei_aligned_stack_new(Scalar, kc*mc);
|
|
||||||
std::size_t sizeW = kc*Traits::WorkSpaceFactor;
|
std::size_t sizeW = kc*Traits::WorkSpaceFactor;
|
||||||
std::size_t sizeB = sizeW + kc*cols;
|
std::size_t sizeB = sizeW + kc*cols;
|
||||||
Scalar* allocatedBlockB = ei_aligned_stack_new(Scalar, sizeB);
|
ei_declare_aligned_stack_constructed_variable(Scalar, blockA, kc*mc, 0);
|
||||||
|
ei_declare_aligned_stack_constructed_variable(Scalar, allocatedBlockB, sizeB, 0);
|
||||||
Scalar* blockB = allocatedBlockB + sizeW;
|
Scalar* blockB = allocatedBlockB + sizeW;
|
||||||
|
|
||||||
gebp_kernel<Scalar, Scalar, Index, Traits::mr, Traits::nr, ConjugateLhs, ConjugateRhs> gebp_kernel;
|
gebp_kernel<Scalar, Scalar, Index, Traits::mr, Traits::nr, ConjugateLhs, ConjugateRhs> gebp_kernel;
|
||||||
@@ -276,7 +276,7 @@ struct product_selfadjoint_matrix<Scalar,Index,LhsStorageOrder,true,ConjugateLhs
|
|||||||
|
|
||||||
for(Index k2=0; k2<size; k2+=kc)
|
for(Index k2=0; k2<size; k2+=kc)
|
||||||
{
|
{
|
||||||
const Index actual_kc = std::min(k2+kc,size)-k2;
|
const Index actual_kc = (std::min)(k2+kc,size)-k2;
|
||||||
|
|
||||||
// we have selected one row panel of rhs and one column panel of lhs
|
// we have selected one row panel of rhs and one column panel of lhs
|
||||||
// pack rhs's panel into a sequential chunk of memory
|
// pack rhs's panel into a sequential chunk of memory
|
||||||
@@ -289,7 +289,7 @@ struct product_selfadjoint_matrix<Scalar,Index,LhsStorageOrder,true,ConjugateLhs
|
|||||||
// 3 - the panel below the diagonal block => generic packed copy
|
// 3 - the panel below the diagonal block => generic packed copy
|
||||||
for(Index i2=0; i2<k2; i2+=mc)
|
for(Index i2=0; i2<k2; i2+=mc)
|
||||||
{
|
{
|
||||||
const Index actual_mc = std::min(i2+mc,k2)-i2;
|
const Index actual_mc = (std::min)(i2+mc,k2)-i2;
|
||||||
// transposed packed copy
|
// transposed packed copy
|
||||||
pack_lhs_transposed(blockA, &lhs(k2, i2), lhsStride, actual_kc, actual_mc);
|
pack_lhs_transposed(blockA, &lhs(k2, i2), lhsStride, actual_kc, actual_mc);
|
||||||
|
|
||||||
@@ -297,7 +297,7 @@ struct product_selfadjoint_matrix<Scalar,Index,LhsStorageOrder,true,ConjugateLhs
|
|||||||
}
|
}
|
||||||
// the block diagonal
|
// the block diagonal
|
||||||
{
|
{
|
||||||
const Index actual_mc = std::min(k2+kc,size)-k2;
|
const Index actual_mc = (std::min)(k2+kc,size)-k2;
|
||||||
// symmetric packed copy
|
// symmetric packed copy
|
||||||
pack_lhs(blockA, &lhs(k2,k2), lhsStride, actual_kc, actual_mc);
|
pack_lhs(blockA, &lhs(k2,k2), lhsStride, actual_kc, actual_mc);
|
||||||
|
|
||||||
@@ -306,16 +306,13 @@ struct product_selfadjoint_matrix<Scalar,Index,LhsStorageOrder,true,ConjugateLhs
|
|||||||
|
|
||||||
for(Index i2=k2+kc; i2<size; i2+=mc)
|
for(Index i2=k2+kc; i2<size; i2+=mc)
|
||||||
{
|
{
|
||||||
const Index actual_mc = std::min(i2+mc,size)-i2;
|
const Index actual_mc = (std::min)(i2+mc,size)-i2;
|
||||||
gemm_pack_lhs<Scalar, Index, Traits::mr, Traits::LhsProgress, LhsStorageOrder,false>()
|
gemm_pack_lhs<Scalar, Index, Traits::mr, Traits::LhsProgress, LhsStorageOrder,false>()
|
||||||
(blockA, &lhs(i2, k2), lhsStride, actual_kc, actual_mc);
|
(blockA, &lhs(i2, k2), lhsStride, actual_kc, actual_mc);
|
||||||
|
|
||||||
gebp_kernel(res+i2, resStride, blockA, blockB, actual_mc, actual_kc, cols, alpha);
|
gebp_kernel(res+i2, resStride, blockA, blockB, actual_mc, actual_kc, cols, alpha);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ei_aligned_stack_delete(Scalar, blockA, kc*mc);
|
|
||||||
ei_aligned_stack_delete(Scalar, allocatedBlockB, sizeB);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -343,11 +340,10 @@ struct product_selfadjoint_matrix<Scalar,Index,LhsStorageOrder,false,ConjugateLh
|
|||||||
Index mc = rows; // cache block size along the M direction
|
Index mc = rows; // cache block size along the M direction
|
||||||
Index nc = cols; // cache block size along the N direction
|
Index nc = cols; // cache block size along the N direction
|
||||||
computeProductBlockingSizes<Scalar,Scalar>(kc, mc, nc);
|
computeProductBlockingSizes<Scalar,Scalar>(kc, mc, nc);
|
||||||
|
|
||||||
Scalar* blockA = ei_aligned_stack_new(Scalar, kc*mc);
|
|
||||||
std::size_t sizeW = kc*Traits::WorkSpaceFactor;
|
std::size_t sizeW = kc*Traits::WorkSpaceFactor;
|
||||||
std::size_t sizeB = sizeW + kc*cols;
|
std::size_t sizeB = sizeW + kc*cols;
|
||||||
Scalar* allocatedBlockB = ei_aligned_stack_new(Scalar, sizeB);
|
ei_declare_aligned_stack_constructed_variable(Scalar, blockA, kc*mc, 0);
|
||||||
|
ei_declare_aligned_stack_constructed_variable(Scalar, allocatedBlockB, sizeB, 0);
|
||||||
Scalar* blockB = allocatedBlockB + sizeW;
|
Scalar* blockB = allocatedBlockB + sizeW;
|
||||||
|
|
||||||
gebp_kernel<Scalar, Scalar, Index, Traits::mr, Traits::nr, ConjugateLhs, ConjugateRhs> gebp_kernel;
|
gebp_kernel<Scalar, Scalar, Index, Traits::mr, Traits::nr, ConjugateLhs, ConjugateRhs> gebp_kernel;
|
||||||
@@ -356,22 +352,19 @@ struct product_selfadjoint_matrix<Scalar,Index,LhsStorageOrder,false,ConjugateLh
|
|||||||
|
|
||||||
for(Index k2=0; k2<size; k2+=kc)
|
for(Index k2=0; k2<size; k2+=kc)
|
||||||
{
|
{
|
||||||
const Index actual_kc = std::min(k2+kc,size)-k2;
|
const Index actual_kc = (std::min)(k2+kc,size)-k2;
|
||||||
|
|
||||||
pack_rhs(blockB, _rhs, rhsStride, actual_kc, cols, k2);
|
pack_rhs(blockB, _rhs, rhsStride, actual_kc, cols, k2);
|
||||||
|
|
||||||
// => GEPP
|
// => GEPP
|
||||||
for(Index i2=0; i2<rows; i2+=mc)
|
for(Index i2=0; i2<rows; i2+=mc)
|
||||||
{
|
{
|
||||||
const Index actual_mc = std::min(i2+mc,rows)-i2;
|
const Index actual_mc = (std::min)(i2+mc,rows)-i2;
|
||||||
pack_lhs(blockA, &lhs(i2, k2), lhsStride, actual_kc, actual_mc);
|
pack_lhs(blockA, &lhs(i2, k2), lhsStride, actual_kc, actual_mc);
|
||||||
|
|
||||||
gebp_kernel(res+i2, resStride, blockA, blockB, actual_mc, actual_kc, cols, alpha);
|
gebp_kernel(res+i2, resStride, blockA, blockB, actual_mc, actual_kc, cols, alpha);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ei_aligned_stack_delete(Scalar, blockA, kc*mc);
|
|
||||||
ei_aligned_stack_delete(Scalar, allocatedBlockB, sizeB);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -62,17 +62,15 @@ static EIGEN_DONT_INLINE void product_selfadjoint_vector(
|
|||||||
// FIXME this copy is now handled outside product_selfadjoint_vector, so it could probably be removed.
|
// FIXME this copy is now handled outside product_selfadjoint_vector, so it could probably be removed.
|
||||||
// if the rhs is not sequentially stored in memory we copy it to a temporary buffer,
|
// if the rhs is not sequentially stored in memory we copy it to a temporary buffer,
|
||||||
// this is because we need to extract packets
|
// this is because we need to extract packets
|
||||||
const Scalar* EIGEN_RESTRICT rhs = _rhs;
|
ei_declare_aligned_stack_constructed_variable(Scalar,rhs,size,rhsIncr==1 ? const_cast<Scalar*>(_rhs) : 0);
|
||||||
if (rhsIncr!=1)
|
if (rhsIncr!=1)
|
||||||
{
|
{
|
||||||
Scalar* r = ei_aligned_stack_new(Scalar, size);
|
|
||||||
const Scalar* it = _rhs;
|
const Scalar* it = _rhs;
|
||||||
for (Index i=0; i<size; ++i, it+=rhsIncr)
|
for (Index i=0; i<size; ++i, it+=rhsIncr)
|
||||||
r[i] = *it;
|
rhs[i] = *it;
|
||||||
rhs = r;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Index bound = std::max(Index(0),size-8) & 0xfffffffe;
|
Index bound = (std::max)(Index(0),size-8) & 0xfffffffe;
|
||||||
if (FirstTriangular)
|
if (FirstTriangular)
|
||||||
bound = size - bound;
|
bound = size - bound;
|
||||||
|
|
||||||
@@ -160,9 +158,6 @@ static EIGEN_DONT_INLINE void product_selfadjoint_vector(
|
|||||||
}
|
}
|
||||||
res[j] += alpha * t2;
|
res[j] += alpha * t2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(rhsIncr!=1)
|
|
||||||
ei_aligned_stack_delete(Scalar, const_cast<Scalar*>(rhs), size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // end namespace internal
|
} // end namespace internal
|
||||||
@@ -211,40 +206,28 @@ struct SelfadjointProductMatrix<Lhs,LhsMode,false,Rhs,0,true>
|
|||||||
|
|
||||||
internal::gemv_static_vector_if<ResScalar,Dest::SizeAtCompileTime,Dest::MaxSizeAtCompileTime,!EvalToDest> static_dest;
|
internal::gemv_static_vector_if<ResScalar,Dest::SizeAtCompileTime,Dest::MaxSizeAtCompileTime,!EvalToDest> static_dest;
|
||||||
internal::gemv_static_vector_if<RhsScalar,_ActualRhsType::SizeAtCompileTime,_ActualRhsType::MaxSizeAtCompileTime,!UseRhs> static_rhs;
|
internal::gemv_static_vector_if<RhsScalar,_ActualRhsType::SizeAtCompileTime,_ActualRhsType::MaxSizeAtCompileTime,!UseRhs> static_rhs;
|
||||||
|
|
||||||
|
ei_declare_aligned_stack_constructed_variable(ResScalar,actualDestPtr,dest.size(),
|
||||||
|
EvalToDest ? dest.data() : static_dest.data());
|
||||||
|
|
||||||
|
ei_declare_aligned_stack_constructed_variable(RhsScalar,actualRhsPtr,rhs.size(),
|
||||||
|
UseRhs ? const_cast<RhsScalar*>(rhs.data()) : static_rhs.data());
|
||||||
|
|
||||||
bool freeDestPtr = false;
|
if(!EvalToDest)
|
||||||
ResScalar* actualDestPtr;
|
|
||||||
if(EvalToDest)
|
|
||||||
actualDestPtr = dest.data();
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
#ifdef EIGEN_DENSE_STORAGE_CTOR_PLUGIN
|
#ifdef EIGEN_DENSE_STORAGE_CTOR_PLUGIN
|
||||||
int size = dest.size();
|
int size = dest.size();
|
||||||
EIGEN_DENSE_STORAGE_CTOR_PLUGIN
|
EIGEN_DENSE_STORAGE_CTOR_PLUGIN
|
||||||
#endif
|
#endif
|
||||||
if((actualDestPtr=static_dest.data())==0)
|
|
||||||
{
|
|
||||||
freeDestPtr = true;
|
|
||||||
actualDestPtr = ei_aligned_stack_new(ResScalar,dest.size());
|
|
||||||
}
|
|
||||||
MappedDest(actualDestPtr, dest.size()) = dest;
|
MappedDest(actualDestPtr, dest.size()) = dest;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool freeRhsPtr = false;
|
if(!UseRhs)
|
||||||
RhsScalar* actualRhsPtr;
|
|
||||||
if(UseRhs)
|
|
||||||
actualRhsPtr = const_cast<RhsScalar*>(rhs.data());
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
#ifdef EIGEN_DENSE_STORAGE_CTOR_PLUGIN
|
#ifdef EIGEN_DENSE_STORAGE_CTOR_PLUGIN
|
||||||
int size = rhs.size();
|
int size = rhs.size();
|
||||||
EIGEN_DENSE_STORAGE_CTOR_PLUGIN
|
EIGEN_DENSE_STORAGE_CTOR_PLUGIN
|
||||||
#endif
|
#endif
|
||||||
if((actualRhsPtr=static_rhs.data())==0)
|
|
||||||
{
|
|
||||||
freeRhsPtr = true;
|
|
||||||
actualRhsPtr = ei_aligned_stack_new(RhsScalar,rhs.size());
|
|
||||||
}
|
|
||||||
Map<typename _ActualRhsType::PlainObject>(actualRhsPtr, rhs.size()) = rhs;
|
Map<typename _ActualRhsType::PlainObject>(actualRhsPtr, rhs.size()) = rhs;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -259,11 +242,7 @@ struct SelfadjointProductMatrix<Lhs,LhsMode,false,Rhs,0,true>
|
|||||||
);
|
);
|
||||||
|
|
||||||
if(!EvalToDest)
|
if(!EvalToDest)
|
||||||
{
|
|
||||||
dest = MappedDest(actualDestPtr, dest.size());
|
dest = MappedDest(actualDestPtr, dest.size());
|
||||||
if(freeDestPtr) ei_aligned_stack_delete(ResScalar, actualDestPtr, dest.size());
|
|
||||||
}
|
|
||||||
if(freeRhsPtr) ei_aligned_stack_delete(RhsScalar, actualRhsPtr, rhs.size());
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -81,27 +81,17 @@ struct selfadjoint_product_selector<MatrixType,OtherType,UpLo,true>
|
|||||||
UseOtherDirectly = _ActualOtherType::InnerStrideAtCompileTime==1
|
UseOtherDirectly = _ActualOtherType::InnerStrideAtCompileTime==1
|
||||||
};
|
};
|
||||||
internal::gemv_static_vector_if<Scalar,OtherType::SizeAtCompileTime,OtherType::MaxSizeAtCompileTime,!UseOtherDirectly> static_other;
|
internal::gemv_static_vector_if<Scalar,OtherType::SizeAtCompileTime,OtherType::MaxSizeAtCompileTime,!UseOtherDirectly> static_other;
|
||||||
|
|
||||||
bool freeOtherPtr = false;
|
ei_declare_aligned_stack_constructed_variable(Scalar, actualOtherPtr, other.size(),
|
||||||
Scalar* actualOtherPtr;
|
(UseOtherDirectly ? const_cast<Scalar*>(actualOther.data()) : static_other.data()));
|
||||||
if(UseOtherDirectly)
|
|
||||||
actualOtherPtr = const_cast<Scalar*>(actualOther.data());
|
if(!UseOtherDirectly)
|
||||||
else
|
|
||||||
{
|
|
||||||
if((actualOtherPtr=static_other.data())==0)
|
|
||||||
{
|
|
||||||
freeOtherPtr = true;
|
|
||||||
actualOtherPtr = ei_aligned_stack_new(Scalar,other.size());
|
|
||||||
}
|
|
||||||
Map<typename _ActualOtherType::PlainObject>(actualOtherPtr, actualOther.size()) = actualOther;
|
Map<typename _ActualOtherType::PlainObject>(actualOtherPtr, actualOther.size()) = actualOther;
|
||||||
}
|
|
||||||
|
|
||||||
selfadjoint_rank1_update<Scalar,Index,StorageOrder,UpLo,
|
selfadjoint_rank1_update<Scalar,Index,StorageOrder,UpLo,
|
||||||
OtherBlasTraits::NeedToConjugate && NumTraits<Scalar>::IsComplex,
|
OtherBlasTraits::NeedToConjugate && NumTraits<Scalar>::IsComplex,
|
||||||
(!OtherBlasTraits::NeedToConjugate) && NumTraits<Scalar>::IsComplex>
|
(!OtherBlasTraits::NeedToConjugate) && NumTraits<Scalar>::IsComplex>
|
||||||
::run(other.size(), mat.data(), mat.outerStride(), actualOtherPtr, actualAlpha);
|
::run(other.size(), mat.data(), mat.outerStride(), actualOtherPtr, actualAlpha);
|
||||||
|
|
||||||
if((!UseOtherDirectly) && freeOtherPtr) ei_aligned_stack_delete(Scalar, actualOtherPtr, other.size());
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -96,33 +96,38 @@ struct product_triangular_matrix_matrix<Scalar,Index,Mode,true,
|
|||||||
LhsStorageOrder,ConjugateLhs,
|
LhsStorageOrder,ConjugateLhs,
|
||||||
RhsStorageOrder,ConjugateRhs,ColMajor>
|
RhsStorageOrder,ConjugateRhs,ColMajor>
|
||||||
{
|
{
|
||||||
|
|
||||||
|
typedef gebp_traits<Scalar,Scalar> Traits;
|
||||||
|
enum {
|
||||||
|
SmallPanelWidth = EIGEN_PLAIN_ENUM_MAX(Traits::mr,Traits::nr),
|
||||||
|
IsLower = (Mode&Lower) == Lower,
|
||||||
|
SetDiag = (Mode&(ZeroDiag|UnitDiag)) ? 0 : 1
|
||||||
|
};
|
||||||
|
|
||||||
static EIGEN_DONT_INLINE void run(
|
static EIGEN_DONT_INLINE void run(
|
||||||
Index rows, Index cols, Index depth,
|
Index _rows, Index _cols, Index _depth,
|
||||||
const Scalar* _lhs, Index lhsStride,
|
const Scalar* _lhs, Index lhsStride,
|
||||||
const Scalar* _rhs, Index rhsStride,
|
const Scalar* _rhs, Index rhsStride,
|
||||||
Scalar* res, Index resStride,
|
Scalar* res, Index resStride,
|
||||||
Scalar alpha)
|
Scalar alpha)
|
||||||
{
|
{
|
||||||
|
// strip zeros
|
||||||
|
Index diagSize = (std::min)(_rows,_depth);
|
||||||
|
Index rows = IsLower ? _rows : diagSize;
|
||||||
|
Index depth = IsLower ? diagSize : _depth;
|
||||||
|
Index cols = _cols;
|
||||||
|
|
||||||
const_blas_data_mapper<Scalar, Index, LhsStorageOrder> lhs(_lhs,lhsStride);
|
const_blas_data_mapper<Scalar, Index, LhsStorageOrder> lhs(_lhs,lhsStride);
|
||||||
const_blas_data_mapper<Scalar, Index, RhsStorageOrder> rhs(_rhs,rhsStride);
|
const_blas_data_mapper<Scalar, Index, RhsStorageOrder> rhs(_rhs,rhsStride);
|
||||||
|
|
||||||
typedef gebp_traits<Scalar,Scalar> Traits;
|
|
||||||
enum {
|
|
||||||
SmallPanelWidth = EIGEN_PLAIN_ENUM_MAX(Traits::mr,Traits::nr),
|
|
||||||
IsLower = (Mode&Lower) == Lower,
|
|
||||||
SetDiag = (Mode&(ZeroDiag|UnitDiag)) ? 0 : 1
|
|
||||||
};
|
|
||||||
|
|
||||||
Index kc = depth; // cache block size along the K direction
|
Index kc = depth; // cache block size along the K direction
|
||||||
Index mc = rows; // cache block size along the M direction
|
Index mc = rows; // cache block size along the M direction
|
||||||
Index nc = cols; // cache block size along the N direction
|
Index nc = cols; // cache block size along the N direction
|
||||||
computeProductBlockingSizes<Scalar,Scalar,4>(kc, mc, nc);
|
computeProductBlockingSizes<Scalar,Scalar,4>(kc, mc, nc);
|
||||||
|
|
||||||
Scalar* blockA = ei_aligned_stack_new(Scalar, kc*mc);
|
|
||||||
std::size_t sizeW = kc*Traits::WorkSpaceFactor;
|
std::size_t sizeW = kc*Traits::WorkSpaceFactor;
|
||||||
std::size_t sizeB = sizeW + kc*cols;
|
std::size_t sizeB = sizeW + kc*cols;
|
||||||
Scalar* allocatedBlockB = ei_aligned_stack_new(Scalar, sizeB);
|
ei_declare_aligned_stack_constructed_variable(Scalar, blockA, kc*mc, 0);
|
||||||
|
ei_declare_aligned_stack_constructed_variable(Scalar, allocatedBlockB, sizeB, 0);
|
||||||
Scalar* blockB = allocatedBlockB + sizeW;
|
Scalar* blockB = allocatedBlockB + sizeW;
|
||||||
|
|
||||||
Matrix<Scalar,SmallPanelWidth,SmallPanelWidth,LhsStorageOrder> triangularBuffer;
|
Matrix<Scalar,SmallPanelWidth,SmallPanelWidth,LhsStorageOrder> triangularBuffer;
|
||||||
@@ -140,7 +145,7 @@ struct product_triangular_matrix_matrix<Scalar,Index,Mode,true,
|
|||||||
IsLower ? k2>0 : k2<depth;
|
IsLower ? k2>0 : k2<depth;
|
||||||
IsLower ? k2-=kc : k2+=kc)
|
IsLower ? k2-=kc : k2+=kc)
|
||||||
{
|
{
|
||||||
Index actual_kc = std::min(IsLower ? k2 : depth-k2, kc);
|
Index actual_kc = (std::min)(IsLower ? k2 : depth-k2, kc);
|
||||||
Index actual_k2 = IsLower ? k2-actual_kc : k2;
|
Index actual_k2 = IsLower ? k2-actual_kc : k2;
|
||||||
|
|
||||||
// align blocks with the end of the triangular part for trapezoidal lhs
|
// align blocks with the end of the triangular part for trapezoidal lhs
|
||||||
@@ -153,10 +158,11 @@ struct product_triangular_matrix_matrix<Scalar,Index,Mode,true,
|
|||||||
pack_rhs(blockB, &rhs(actual_k2,0), rhsStride, actual_kc, cols);
|
pack_rhs(blockB, &rhs(actual_k2,0), rhsStride, actual_kc, cols);
|
||||||
|
|
||||||
// the selected lhs's panel has to be split in three different parts:
|
// the selected lhs's panel has to be split in three different parts:
|
||||||
// 1 - the part which is above the diagonal block => skip it
|
// 1 - the part which is zero => skip it
|
||||||
// 2 - the diagonal block => special kernel
|
// 2 - the diagonal block => special kernel
|
||||||
// 3 - the panel below the diagonal block => GEPP
|
// 3 - the dense panel below (lower case) or above (upper case) the diagonal block => GEPP
|
||||||
// the block diagonal, if any
|
|
||||||
|
// the block diagonal, if any:
|
||||||
if(IsLower || actual_k2<rows)
|
if(IsLower || actual_k2<rows)
|
||||||
{
|
{
|
||||||
// for each small vertical panels of lhs
|
// for each small vertical panels of lhs
|
||||||
@@ -194,13 +200,13 @@ struct product_triangular_matrix_matrix<Scalar,Index,Mode,true,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// the part below the diagonal => GEPP
|
// the part below (lower case) or above (upper case) the diagonal => GEPP
|
||||||
{
|
{
|
||||||
Index start = IsLower ? k2 : 0;
|
Index start = IsLower ? k2 : 0;
|
||||||
Index end = IsLower ? rows : std::min(actual_k2,rows);
|
Index end = IsLower ? rows : (std::min)(actual_k2,rows);
|
||||||
for(Index i2=start; i2<end; i2+=mc)
|
for(Index i2=start; i2<end; i2+=mc)
|
||||||
{
|
{
|
||||||
const Index actual_mc = std::min(i2+mc,end)-i2;
|
const Index actual_mc = (std::min)(i2+mc,end)-i2;
|
||||||
gemm_pack_lhs<Scalar, Index, Traits::mr,Traits::LhsProgress, LhsStorageOrder,false>()
|
gemm_pack_lhs<Scalar, Index, Traits::mr,Traits::LhsProgress, LhsStorageOrder,false>()
|
||||||
(blockA, &lhs(i2, actual_k2), lhsStride, actual_kc, actual_mc);
|
(blockA, &lhs(i2, actual_k2), lhsStride, actual_kc, actual_mc);
|
||||||
|
|
||||||
@@ -208,10 +214,6 @@ struct product_triangular_matrix_matrix<Scalar,Index,Mode,true,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ei_aligned_stack_delete(Scalar, blockA, kc*mc);
|
|
||||||
ei_aligned_stack_delete(Scalar, allocatedBlockB, sizeB);
|
|
||||||
// delete[] allocatedBlockB;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -223,33 +225,38 @@ struct product_triangular_matrix_matrix<Scalar,Index,Mode,false,
|
|||||||
LhsStorageOrder,ConjugateLhs,
|
LhsStorageOrder,ConjugateLhs,
|
||||||
RhsStorageOrder,ConjugateRhs,ColMajor>
|
RhsStorageOrder,ConjugateRhs,ColMajor>
|
||||||
{
|
{
|
||||||
|
typedef gebp_traits<Scalar,Scalar> Traits;
|
||||||
|
enum {
|
||||||
|
SmallPanelWidth = EIGEN_PLAIN_ENUM_MAX(Traits::mr,Traits::nr),
|
||||||
|
IsLower = (Mode&Lower) == Lower,
|
||||||
|
SetDiag = (Mode&(ZeroDiag|UnitDiag)) ? 0 : 1
|
||||||
|
};
|
||||||
|
|
||||||
static EIGEN_DONT_INLINE void run(
|
static EIGEN_DONT_INLINE void run(
|
||||||
Index rows, Index cols, Index depth,
|
Index _rows, Index _cols, Index _depth,
|
||||||
const Scalar* _lhs, Index lhsStride,
|
const Scalar* _lhs, Index lhsStride,
|
||||||
const Scalar* _rhs, Index rhsStride,
|
const Scalar* _rhs, Index rhsStride,
|
||||||
Scalar* res, Index resStride,
|
Scalar* res, Index resStride,
|
||||||
Scalar alpha)
|
Scalar alpha)
|
||||||
{
|
{
|
||||||
|
// strip zeros
|
||||||
|
Index diagSize = (std::min)(_cols,_depth);
|
||||||
|
Index rows = _rows;
|
||||||
|
Index depth = IsLower ? _depth : diagSize;
|
||||||
|
Index cols = IsLower ? diagSize : _cols;
|
||||||
|
|
||||||
const_blas_data_mapper<Scalar, Index, LhsStorageOrder> lhs(_lhs,lhsStride);
|
const_blas_data_mapper<Scalar, Index, LhsStorageOrder> lhs(_lhs,lhsStride);
|
||||||
const_blas_data_mapper<Scalar, Index, RhsStorageOrder> rhs(_rhs,rhsStride);
|
const_blas_data_mapper<Scalar, Index, RhsStorageOrder> rhs(_rhs,rhsStride);
|
||||||
|
|
||||||
typedef gebp_traits<Scalar,Scalar> Traits;
|
|
||||||
enum {
|
|
||||||
SmallPanelWidth = EIGEN_PLAIN_ENUM_MAX(Traits::mr,Traits::nr),
|
|
||||||
IsLower = (Mode&Lower) == Lower,
|
|
||||||
SetDiag = (Mode&(ZeroDiag|UnitDiag)) ? 0 : 1
|
|
||||||
};
|
|
||||||
|
|
||||||
Index kc = depth; // cache block size along the K direction
|
Index kc = depth; // cache block size along the K direction
|
||||||
Index mc = rows; // cache block size along the M direction
|
Index mc = rows; // cache block size along the M direction
|
||||||
Index nc = cols; // cache block size along the N direction
|
Index nc = cols; // cache block size along the N direction
|
||||||
computeProductBlockingSizes<Scalar,Scalar,4>(kc, mc, nc);
|
computeProductBlockingSizes<Scalar,Scalar,4>(kc, mc, nc);
|
||||||
|
|
||||||
Scalar* blockA = ei_aligned_stack_new(Scalar, kc*mc);
|
|
||||||
std::size_t sizeW = kc*Traits::WorkSpaceFactor;
|
std::size_t sizeW = kc*Traits::WorkSpaceFactor;
|
||||||
std::size_t sizeB = sizeW + kc*cols;
|
std::size_t sizeB = sizeW + kc*cols;
|
||||||
Scalar* allocatedBlockB = ei_aligned_stack_new(Scalar,sizeB);
|
ei_declare_aligned_stack_constructed_variable(Scalar, blockA, kc*mc, 0);
|
||||||
|
ei_declare_aligned_stack_constructed_variable(Scalar, allocatedBlockB, sizeB, 0);
|
||||||
Scalar* blockB = allocatedBlockB + sizeW;
|
Scalar* blockB = allocatedBlockB + sizeW;
|
||||||
|
|
||||||
Matrix<Scalar,SmallPanelWidth,SmallPanelWidth,RhsStorageOrder> triangularBuffer;
|
Matrix<Scalar,SmallPanelWidth,SmallPanelWidth,RhsStorageOrder> triangularBuffer;
|
||||||
@@ -268,7 +275,7 @@ struct product_triangular_matrix_matrix<Scalar,Index,Mode,false,
|
|||||||
IsLower ? k2<depth : k2>0;
|
IsLower ? k2<depth : k2>0;
|
||||||
IsLower ? k2+=kc : k2-=kc)
|
IsLower ? k2+=kc : k2-=kc)
|
||||||
{
|
{
|
||||||
Index actual_kc = std::min(IsLower ? depth-k2 : k2, kc);
|
Index actual_kc = (std::min)(IsLower ? depth-k2 : k2, kc);
|
||||||
Index actual_k2 = IsLower ? k2 : k2-actual_kc;
|
Index actual_k2 = IsLower ? k2 : k2-actual_kc;
|
||||||
|
|
||||||
// align blocks with the end of the triangular part for trapezoidal rhs
|
// align blocks with the end of the triangular part for trapezoidal rhs
|
||||||
@@ -279,7 +286,7 @@ struct product_triangular_matrix_matrix<Scalar,Index,Mode,false,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// remaining size
|
// remaining size
|
||||||
Index rs = IsLower ? std::min(cols,actual_k2) : cols - k2;
|
Index rs = IsLower ? (std::min)(cols,actual_k2) : cols - k2;
|
||||||
// size of the triangular part
|
// size of the triangular part
|
||||||
Index ts = (IsLower && actual_k2>=cols) ? 0 : actual_kc;
|
Index ts = (IsLower && actual_k2>=cols) ? 0 : actual_kc;
|
||||||
|
|
||||||
@@ -320,7 +327,7 @@ struct product_triangular_matrix_matrix<Scalar,Index,Mode,false,
|
|||||||
|
|
||||||
for (Index i2=0; i2<rows; i2+=mc)
|
for (Index i2=0; i2<rows; i2+=mc)
|
||||||
{
|
{
|
||||||
const Index actual_mc = std::min(mc,rows-i2);
|
const Index actual_mc = (std::min)(mc,rows-i2);
|
||||||
pack_lhs(blockA, &lhs(i2, actual_k2), lhsStride, actual_kc, actual_mc);
|
pack_lhs(blockA, &lhs(i2, actual_k2), lhsStride, actual_kc, actual_mc);
|
||||||
|
|
||||||
// triangular kernel
|
// triangular kernel
|
||||||
@@ -347,9 +354,6 @@ struct product_triangular_matrix_matrix<Scalar,Index,Mode,false,
|
|||||||
-1, -1, 0, 0, allocatedBlockB);
|
-1, -1, 0, 0, allocatedBlockB);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ei_aligned_stack_delete(Scalar, blockA, kc*mc);
|
|
||||||
ei_aligned_stack_delete(Scalar, allocatedBlockB, sizeB);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -41,9 +41,6 @@ struct product_triangular_matrix_vector<Index,Mode,LhsScalar,ConjLhs,RhsScalar,C
|
|||||||
static EIGEN_DONT_INLINE void run(Index rows, Index cols, const LhsScalar* _lhs, Index lhsStride,
|
static EIGEN_DONT_INLINE void run(Index rows, Index cols, const LhsScalar* _lhs, Index lhsStride,
|
||||||
const RhsScalar* _rhs, Index rhsIncr, ResScalar* _res, Index resIncr, ResScalar alpha)
|
const RhsScalar* _rhs, Index rhsIncr, ResScalar* _res, Index resIncr, ResScalar alpha)
|
||||||
{
|
{
|
||||||
EIGEN_UNUSED_VARIABLE(resIncr);
|
|
||||||
eigen_assert(resIncr==1);
|
|
||||||
|
|
||||||
static const Index PanelWidth = EIGEN_TUNE_TRIANGULAR_PANEL_WIDTH;
|
static const Index PanelWidth = EIGEN_TUNE_TRIANGULAR_PANEL_WIDTH;
|
||||||
|
|
||||||
typedef Map<const Matrix<LhsScalar,Dynamic,Dynamic,ColMajor>, 0, OuterStride<> > LhsMap;
|
typedef Map<const Matrix<LhsScalar,Dynamic,Dynamic,ColMajor>, 0, OuterStride<> > LhsMap;
|
||||||
@@ -59,7 +56,7 @@ struct product_triangular_matrix_vector<Index,Mode,LhsScalar,ConjLhs,RhsScalar,C
|
|||||||
|
|
||||||
for (Index pi=0; pi<cols; pi+=PanelWidth)
|
for (Index pi=0; pi<cols; pi+=PanelWidth)
|
||||||
{
|
{
|
||||||
Index actualPanelWidth = std::min(PanelWidth, cols-pi);
|
Index actualPanelWidth = (std::min)(PanelWidth, cols-pi);
|
||||||
for (Index k=0; k<actualPanelWidth; ++k)
|
for (Index k=0; k<actualPanelWidth; ++k)
|
||||||
{
|
{
|
||||||
Index i = pi + k;
|
Index i = pi + k;
|
||||||
@@ -95,9 +92,6 @@ struct product_triangular_matrix_vector<Index,Mode,LhsScalar,ConjLhs,RhsScalar,C
|
|||||||
static void run(Index rows, Index cols, const LhsScalar* _lhs, Index lhsStride,
|
static void run(Index rows, Index cols, const LhsScalar* _lhs, Index lhsStride,
|
||||||
const RhsScalar* _rhs, Index rhsIncr, ResScalar* _res, Index resIncr, ResScalar alpha)
|
const RhsScalar* _rhs, Index rhsIncr, ResScalar* _res, Index resIncr, ResScalar alpha)
|
||||||
{
|
{
|
||||||
eigen_assert(rhsIncr==1);
|
|
||||||
EIGEN_UNUSED_VARIABLE(rhsIncr);
|
|
||||||
|
|
||||||
static const Index PanelWidth = EIGEN_TUNE_TRIANGULAR_PANEL_WIDTH;
|
static const Index PanelWidth = EIGEN_TUNE_TRIANGULAR_PANEL_WIDTH;
|
||||||
|
|
||||||
typedef Map<const Matrix<LhsScalar,Dynamic,Dynamic,RowMajor>, 0, OuterStride<> > LhsMap;
|
typedef Map<const Matrix<LhsScalar,Dynamic,Dynamic,RowMajor>, 0, OuterStride<> > LhsMap;
|
||||||
@@ -113,7 +107,7 @@ struct product_triangular_matrix_vector<Index,Mode,LhsScalar,ConjLhs,RhsScalar,C
|
|||||||
|
|
||||||
for (Index pi=0; pi<cols; pi+=PanelWidth)
|
for (Index pi=0; pi<cols; pi+=PanelWidth)
|
||||||
{
|
{
|
||||||
Index actualPanelWidth = std::min(PanelWidth, cols-pi);
|
Index actualPanelWidth = (std::min)(PanelWidth, cols-pi);
|
||||||
for (Index k=0; k<actualPanelWidth; ++k)
|
for (Index k=0; k<actualPanelWidth; ++k)
|
||||||
{
|
{
|
||||||
Index i = pi + k;
|
Index i = pi + k;
|
||||||
@@ -185,7 +179,7 @@ struct TriangularProduct<Mode,false,Lhs,true,Rhs,false>
|
|||||||
template<typename Dest> void scaleAndAddTo(Dest& dst, Scalar alpha) const
|
template<typename Dest> void scaleAndAddTo(Dest& dst, Scalar alpha) const
|
||||||
{
|
{
|
||||||
eigen_assert(dst.rows()==m_lhs.rows() && dst.cols()==m_rhs.cols());
|
eigen_assert(dst.rows()==m_lhs.rows() && dst.cols()==m_rhs.cols());
|
||||||
|
|
||||||
typedef TriangularProduct<(Mode & UnitDiag) | ((Mode & Lower) ? Upper : Lower),true,Transpose<const Rhs>,false,Transpose<const Lhs>,true> TriangularProductTranspose;
|
typedef TriangularProduct<(Mode & UnitDiag) | ((Mode & Lower) ? Upper : Lower),true,Transpose<const Rhs>,false,Transpose<const Lhs>,true> TriangularProductTranspose;
|
||||||
Transpose<Dest> dstT(dst);
|
Transpose<Dest> dstT(dst);
|
||||||
internal::trmv_selector<(int(internal::traits<Rhs>::Flags)&RowMajorBit) ? ColMajor : RowMajor>::run(
|
internal::trmv_selector<(int(internal::traits<Rhs>::Flags)&RowMajorBit) ? ColMajor : RowMajor>::run(
|
||||||
@@ -235,23 +229,15 @@ template<> struct trmv_selector<ColMajor>
|
|||||||
|
|
||||||
RhsScalar compatibleAlpha = get_factor<ResScalar,RhsScalar>::run(actualAlpha);
|
RhsScalar compatibleAlpha = get_factor<ResScalar,RhsScalar>::run(actualAlpha);
|
||||||
|
|
||||||
ResScalar* actualDestPtr;
|
ei_declare_aligned_stack_constructed_variable(ResScalar,actualDestPtr,dest.size(),
|
||||||
bool freeDestPtr = false;
|
evalToDest ? dest.data() : static_dest.data());
|
||||||
if (evalToDest)
|
|
||||||
{
|
if(!evalToDest)
|
||||||
actualDestPtr = dest.data();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
#ifdef EIGEN_DENSE_STORAGE_CTOR_PLUGIN
|
#ifdef EIGEN_DENSE_STORAGE_CTOR_PLUGIN
|
||||||
int size = dest.size();
|
int size = dest.size();
|
||||||
EIGEN_DENSE_STORAGE_CTOR_PLUGIN
|
EIGEN_DENSE_STORAGE_CTOR_PLUGIN
|
||||||
#endif
|
#endif
|
||||||
if((actualDestPtr = static_dest.data())==0)
|
|
||||||
{
|
|
||||||
freeDestPtr = true;
|
|
||||||
actualDestPtr = ei_aligned_stack_new(ResScalar,dest.size());
|
|
||||||
}
|
|
||||||
if(!alphaIsCompatible)
|
if(!alphaIsCompatible)
|
||||||
{
|
{
|
||||||
MappedDest(actualDestPtr, dest.size()).setZero();
|
MappedDest(actualDestPtr, dest.size()).setZero();
|
||||||
@@ -277,7 +263,6 @@ template<> struct trmv_selector<ColMajor>
|
|||||||
dest += actualAlpha * MappedDest(actualDestPtr, dest.size());
|
dest += actualAlpha * MappedDest(actualDestPtr, dest.size());
|
||||||
else
|
else
|
||||||
dest = MappedDest(actualDestPtr, dest.size());
|
dest = MappedDest(actualDestPtr, dest.size());
|
||||||
if(freeDestPtr) ei_aligned_stack_delete(ResScalar, actualDestPtr, dest.size());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -310,23 +295,15 @@ template<> struct trmv_selector<RowMajor>
|
|||||||
|
|
||||||
gemv_static_vector_if<RhsScalar,_ActualRhsType::SizeAtCompileTime,_ActualRhsType::MaxSizeAtCompileTime,!DirectlyUseRhs> static_rhs;
|
gemv_static_vector_if<RhsScalar,_ActualRhsType::SizeAtCompileTime,_ActualRhsType::MaxSizeAtCompileTime,!DirectlyUseRhs> static_rhs;
|
||||||
|
|
||||||
RhsScalar* actualRhsPtr;
|
ei_declare_aligned_stack_constructed_variable(RhsScalar,actualRhsPtr,actualRhs.size(),
|
||||||
bool freeRhsPtr = false;
|
DirectlyUseRhs ? const_cast<RhsScalar*>(actualRhs.data()) : static_rhs.data());
|
||||||
if (DirectlyUseRhs)
|
|
||||||
{
|
if(!DirectlyUseRhs)
|
||||||
actualRhsPtr = const_cast<RhsScalar*>(actualRhs.data());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
#ifdef EIGEN_DENSE_STORAGE_CTOR_PLUGIN
|
#ifdef EIGEN_DENSE_STORAGE_CTOR_PLUGIN
|
||||||
int size = actualRhs.size();
|
int size = actualRhs.size();
|
||||||
EIGEN_DENSE_STORAGE_CTOR_PLUGIN
|
EIGEN_DENSE_STORAGE_CTOR_PLUGIN
|
||||||
#endif
|
#endif
|
||||||
if((actualRhsPtr = static_rhs.data())==0)
|
|
||||||
{
|
|
||||||
freeRhsPtr = true;
|
|
||||||
actualRhsPtr = ei_aligned_stack_new(RhsScalar, actualRhs.size());
|
|
||||||
}
|
|
||||||
Map<typename _ActualRhsType::PlainObject>(actualRhsPtr, actualRhs.size()) = actualRhs;
|
Map<typename _ActualRhsType::PlainObject>(actualRhsPtr, actualRhs.size()) = actualRhs;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -340,8 +317,6 @@ template<> struct trmv_selector<RowMajor>
|
|||||||
actualRhsPtr,1,
|
actualRhsPtr,1,
|
||||||
dest.data(),dest.innerStride(),
|
dest.data(),dest.innerStride(),
|
||||||
actualAlpha);
|
actualAlpha);
|
||||||
|
|
||||||
if((!DirectlyUseRhs) && freeRhsPtr) ei_aligned_stack_delete(RhsScalar, actualRhsPtr, prod.rhs().size());
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -70,10 +70,10 @@ struct triangular_solve_matrix<Scalar,Index,OnTheLeft,Mode,Conjugate,TriStorageO
|
|||||||
Index nc = cols; // cache block size along the N direction
|
Index nc = cols; // cache block size along the N direction
|
||||||
computeProductBlockingSizes<Scalar,Scalar,4>(kc, mc, nc);
|
computeProductBlockingSizes<Scalar,Scalar,4>(kc, mc, nc);
|
||||||
|
|
||||||
Scalar* blockA = ei_aligned_stack_new(Scalar, kc*mc);
|
|
||||||
std::size_t sizeW = kc*Traits::WorkSpaceFactor;
|
std::size_t sizeW = kc*Traits::WorkSpaceFactor;
|
||||||
std::size_t sizeB = sizeW + kc*cols;
|
std::size_t sizeB = sizeW + kc*cols;
|
||||||
Scalar* allocatedBlockB = ei_aligned_stack_new(Scalar, sizeB);
|
ei_declare_aligned_stack_constructed_variable(Scalar, blockA, kc*mc, 0);
|
||||||
|
ei_declare_aligned_stack_constructed_variable(Scalar, allocatedBlockB, sizeB, 0);
|
||||||
Scalar* blockB = allocatedBlockB + sizeW;
|
Scalar* blockB = allocatedBlockB + sizeW;
|
||||||
|
|
||||||
conj_if<Conjugate> conj;
|
conj_if<Conjugate> conj;
|
||||||
@@ -85,7 +85,7 @@ struct triangular_solve_matrix<Scalar,Index,OnTheLeft,Mode,Conjugate,TriStorageO
|
|||||||
IsLower ? k2<size : k2>0;
|
IsLower ? k2<size : k2>0;
|
||||||
IsLower ? k2+=kc : k2-=kc)
|
IsLower ? k2+=kc : k2-=kc)
|
||||||
{
|
{
|
||||||
const Index actual_kc = std::min(IsLower ? size-k2 : k2, kc);
|
const Index actual_kc = (std::min)(IsLower ? size-k2 : k2, kc);
|
||||||
|
|
||||||
// We have selected and packed a big horizontal panel R1 of rhs. Let B be the packed copy of this panel,
|
// We have selected and packed a big horizontal panel R1 of rhs. Let B be the packed copy of this panel,
|
||||||
// and R2 the remaining part of rhs. The corresponding vertical panel of lhs is split into
|
// and R2 the remaining part of rhs. The corresponding vertical panel of lhs is split into
|
||||||
@@ -164,7 +164,7 @@ struct triangular_solve_matrix<Scalar,Index,OnTheLeft,Mode,Conjugate,TriStorageO
|
|||||||
Index end = IsLower ? size : k2-kc;
|
Index end = IsLower ? size : k2-kc;
|
||||||
for(Index i2=start; i2<end; i2+=mc)
|
for(Index i2=start; i2<end; i2+=mc)
|
||||||
{
|
{
|
||||||
const Index actual_mc = std::min(mc,end-i2);
|
const Index actual_mc = (std::min)(mc,end-i2);
|
||||||
if (actual_mc>0)
|
if (actual_mc>0)
|
||||||
{
|
{
|
||||||
pack_lhs(blockA, &tri(i2, IsLower ? k2 : k2-kc), triStride, actual_kc, actual_mc);
|
pack_lhs(blockA, &tri(i2, IsLower ? k2 : k2-kc), triStride, actual_kc, actual_mc);
|
||||||
@@ -174,9 +174,6 @@ struct triangular_solve_matrix<Scalar,Index,OnTheLeft,Mode,Conjugate,TriStorageO
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ei_aligned_stack_delete(Scalar, blockA, kc*mc);
|
|
||||||
ei_aligned_stack_delete(Scalar, allocatedBlockB, sizeB);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -209,10 +206,10 @@ struct triangular_solve_matrix<Scalar,Index,OnTheRight,Mode,Conjugate,TriStorage
|
|||||||
Index nc = rows; // cache block size along the N direction
|
Index nc = rows; // cache block size along the N direction
|
||||||
computeProductBlockingSizes<Scalar,Scalar,4>(kc, mc, nc);
|
computeProductBlockingSizes<Scalar,Scalar,4>(kc, mc, nc);
|
||||||
|
|
||||||
Scalar* blockA = ei_aligned_stack_new(Scalar, kc*mc);
|
|
||||||
std::size_t sizeW = kc*Traits::WorkSpaceFactor;
|
std::size_t sizeW = kc*Traits::WorkSpaceFactor;
|
||||||
std::size_t sizeB = sizeW + kc*size;
|
std::size_t sizeB = sizeW + kc*size;
|
||||||
Scalar* allocatedBlockB = ei_aligned_stack_new(Scalar, sizeB);
|
ei_declare_aligned_stack_constructed_variable(Scalar, blockA, kc*mc, 0);
|
||||||
|
ei_declare_aligned_stack_constructed_variable(Scalar, allocatedBlockB, sizeB, 0);
|
||||||
Scalar* blockB = allocatedBlockB + sizeW;
|
Scalar* blockB = allocatedBlockB + sizeW;
|
||||||
|
|
||||||
conj_if<Conjugate> conj;
|
conj_if<Conjugate> conj;
|
||||||
@@ -225,7 +222,7 @@ struct triangular_solve_matrix<Scalar,Index,OnTheRight,Mode,Conjugate,TriStorage
|
|||||||
IsLower ? k2>0 : k2<size;
|
IsLower ? k2>0 : k2<size;
|
||||||
IsLower ? k2-=kc : k2+=kc)
|
IsLower ? k2-=kc : k2+=kc)
|
||||||
{
|
{
|
||||||
const Index actual_kc = std::min(IsLower ? k2 : size-k2, kc);
|
const Index actual_kc = (std::min)(IsLower ? k2 : size-k2, kc);
|
||||||
Index actual_k2 = IsLower ? k2-actual_kc : k2 ;
|
Index actual_k2 = IsLower ? k2-actual_kc : k2 ;
|
||||||
|
|
||||||
Index startPanel = IsLower ? 0 : k2+actual_kc;
|
Index startPanel = IsLower ? 0 : k2+actual_kc;
|
||||||
@@ -254,7 +251,7 @@ struct triangular_solve_matrix<Scalar,Index,OnTheRight,Mode,Conjugate,TriStorage
|
|||||||
|
|
||||||
for(Index i2=0; i2<rows; i2+=mc)
|
for(Index i2=0; i2<rows; i2+=mc)
|
||||||
{
|
{
|
||||||
const Index actual_mc = std::min(mc,rows-i2);
|
const Index actual_mc = (std::min)(mc,rows-i2);
|
||||||
|
|
||||||
// triangular solver kernel
|
// triangular solver kernel
|
||||||
{
|
{
|
||||||
@@ -314,9 +311,6 @@ struct triangular_solve_matrix<Scalar,Index,OnTheRight,Mode,Conjugate,TriStorage
|
|||||||
-1, -1, 0, 0, allocatedBlockB);
|
-1, -1, 0, 0, allocatedBlockB);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ei_aligned_stack_delete(Scalar, blockA, kc*mc);
|
|
||||||
ei_aligned_stack_delete(Scalar, allocatedBlockB, sizeB);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ struct triangular_solve_vector<LhsScalar, RhsScalar, Index, OnTheLeft, Mode, Con
|
|||||||
IsLower ? pi<size : pi>0;
|
IsLower ? pi<size : pi>0;
|
||||||
IsLower ? pi+=PanelWidth : pi-=PanelWidth)
|
IsLower ? pi+=PanelWidth : pi-=PanelWidth)
|
||||||
{
|
{
|
||||||
Index actualPanelWidth = std::min(IsLower ? size - pi : pi, PanelWidth);
|
Index actualPanelWidth = (std::min)(IsLower ? size - pi : pi, PanelWidth);
|
||||||
|
|
||||||
Index r = IsLower ? pi : size - pi; // remaining size
|
Index r = IsLower ? pi : size - pi; // remaining size
|
||||||
if (r > 0)
|
if (r > 0)
|
||||||
@@ -114,7 +114,7 @@ struct triangular_solve_vector<LhsScalar, RhsScalar, Index, OnTheLeft, Mode, Con
|
|||||||
IsLower ? pi<size : pi>0;
|
IsLower ? pi<size : pi>0;
|
||||||
IsLower ? pi+=PanelWidth : pi-=PanelWidth)
|
IsLower ? pi+=PanelWidth : pi-=PanelWidth)
|
||||||
{
|
{
|
||||||
Index actualPanelWidth = std::min(IsLower ? size - pi : pi, PanelWidth);
|
Index actualPanelWidth = (std::min)(IsLower ? size - pi : pi, PanelWidth);
|
||||||
Index startBlock = IsLower ? pi : pi-actualPanelWidth;
|
Index startBlock = IsLower ? pi : pi-actualPanelWidth;
|
||||||
Index endBlock = IsLower ? pi + actualPanelWidth : 0;
|
Index endBlock = IsLower ? pi + actualPanelWidth : 0;
|
||||||
|
|
||||||
|
|||||||
@@ -161,23 +161,72 @@ const unsigned int HereditaryBits = RowMajorBit
|
|||||||
| EvalBeforeNestingBit
|
| EvalBeforeNestingBit
|
||||||
| EvalBeforeAssigningBit;
|
| EvalBeforeAssigningBit;
|
||||||
|
|
||||||
// Possible values for the Mode parameter of triangularView()
|
/** \defgroup enums Enumerations
|
||||||
enum {
|
* \ingroup Core_Module
|
||||||
Lower=0x1, Upper=0x2, UnitDiag=0x4, ZeroDiag=0x8,
|
*
|
||||||
UnitLower=UnitDiag|Lower, UnitUpper=UnitDiag|Upper,
|
* Various enumerations used in %Eigen. Many of these are used as template parameters.
|
||||||
StrictlyLower=ZeroDiag|Lower, StrictlyUpper=ZeroDiag|Upper,
|
*/
|
||||||
SelfAdjoint=0x10};
|
|
||||||
|
/** \ingroup enums
|
||||||
|
* Enum containing possible values for the \p Mode parameter of
|
||||||
|
* MatrixBase::selfadjointView() and MatrixBase::triangularView(). */
|
||||||
|
enum {
|
||||||
|
/** View matrix as a lower triangular matrix. */
|
||||||
|
Lower=0x1,
|
||||||
|
/** View matrix as an upper triangular matrix. */
|
||||||
|
Upper=0x2,
|
||||||
|
/** %Matrix has ones on the diagonal; to be used in combination with #Lower or #Upper. */
|
||||||
|
UnitDiag=0x4,
|
||||||
|
/** %Matrix has zeros on the diagonal; to be used in combination with #Lower or #Upper. */
|
||||||
|
ZeroDiag=0x8,
|
||||||
|
/** View matrix as a lower triangular matrix with ones on the diagonal. */
|
||||||
|
UnitLower=UnitDiag|Lower,
|
||||||
|
/** View matrix as an upper triangular matrix with ones on the diagonal. */
|
||||||
|
UnitUpper=UnitDiag|Upper,
|
||||||
|
/** View matrix as a lower triangular matrix with zeros on the diagonal. */
|
||||||
|
StrictlyLower=ZeroDiag|Lower,
|
||||||
|
/** View matrix as an upper triangular matrix with zeros on the diagonal. */
|
||||||
|
StrictlyUpper=ZeroDiag|Upper,
|
||||||
|
/** Used in BandMatrix and SelfAdjointView to indicate that the matrix is self-adjoint. */
|
||||||
|
SelfAdjoint=0x10
|
||||||
|
};
|
||||||
|
|
||||||
|
/** \ingroup enums
|
||||||
|
* Enum for indicating whether an object is aligned or not. */
|
||||||
|
enum {
|
||||||
|
/** Object is not correctly aligned for vectorization. */
|
||||||
|
Unaligned=0,
|
||||||
|
/** Object is aligned for vectorization. */
|
||||||
|
Aligned=1
|
||||||
|
};
|
||||||
|
|
||||||
enum { Unaligned=0, Aligned=1 };
|
|
||||||
enum { ConditionalJumpCost = 5 };
|
enum { ConditionalJumpCost = 5 };
|
||||||
|
|
||||||
|
/** \ingroup enums
|
||||||
|
* Enum used by DenseBase::corner() in Eigen2 compatibility mode. */
|
||||||
// FIXME after the corner() API change, this was not needed anymore, except by AlignedBox
|
// FIXME after the corner() API change, this was not needed anymore, except by AlignedBox
|
||||||
// TODO: find out what to do with that. Adapt the AlignedBox API ?
|
// TODO: find out what to do with that. Adapt the AlignedBox API ?
|
||||||
enum CornerType { TopLeft, TopRight, BottomLeft, BottomRight };
|
enum CornerType { TopLeft, TopRight, BottomLeft, BottomRight };
|
||||||
|
|
||||||
enum DirectionType { Vertical, Horizontal, BothDirections };
|
/** \ingroup enums
|
||||||
|
* Enum containing possible values for the \p Direction parameter of
|
||||||
|
* Reverse, PartialReduxExpr and VectorwiseOp. */
|
||||||
|
enum DirectionType {
|
||||||
|
/** For Reverse, all columns are reversed;
|
||||||
|
* for PartialReduxExpr and VectorwiseOp, act on columns. */
|
||||||
|
Vertical,
|
||||||
|
/** For Reverse, all rows are reversed;
|
||||||
|
* for PartialReduxExpr and VectorwiseOp, act on rows. */
|
||||||
|
Horizontal,
|
||||||
|
/** For Reverse, both rows and columns are reversed;
|
||||||
|
* not used for PartialReduxExpr and VectorwiseOp. */
|
||||||
|
BothDirections
|
||||||
|
};
|
||||||
|
|
||||||
enum ProductEvaluationMode { NormalProduct, CacheFriendlyProduct };
|
enum ProductEvaluationMode { NormalProduct, CacheFriendlyProduct };
|
||||||
|
|
||||||
|
/** \internal \ingroup enums
|
||||||
|
* Enum to specify how to traverse the entries of a matrix. */
|
||||||
enum {
|
enum {
|
||||||
/** \internal Default traversal, no vectorization, no index-based access */
|
/** \internal Default traversal, no vectorization, no index-based access */
|
||||||
DefaultTraversal,
|
DefaultTraversal,
|
||||||
@@ -196,14 +245,25 @@ enum {
|
|||||||
InvalidTraversal
|
InvalidTraversal
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** \internal \ingroup enums
|
||||||
|
* Enum to specify whether to unroll loops when traversing over the entries of a matrix. */
|
||||||
enum {
|
enum {
|
||||||
|
/** \internal Do not unroll loops. */
|
||||||
NoUnrolling,
|
NoUnrolling,
|
||||||
|
/** \internal Unroll only the inner loop, but not the outer loop. */
|
||||||
InnerUnrolling,
|
InnerUnrolling,
|
||||||
|
/** \internal Unroll both the inner and the outer loop. If there is only one loop,
|
||||||
|
* because linear traversal is used, then unroll that loop. */
|
||||||
CompleteUnrolling
|
CompleteUnrolling
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** \ingroup enums
|
||||||
|
* Enum containing possible values for the \p _Options template parameter of
|
||||||
|
* Matrix, Array and BandMatrix. */
|
||||||
enum {
|
enum {
|
||||||
|
/** Storage order is column major (see \ref TopicStorageOrders). */
|
||||||
ColMajor = 0,
|
ColMajor = 0,
|
||||||
|
/** Storage order is row major (see \ref TopicStorageOrders). */
|
||||||
RowMajor = 0x1, // it is only a coincidence that this is equal to RowMajorBit -- don't rely on that
|
RowMajor = 0x1, // it is only a coincidence that this is equal to RowMajorBit -- don't rely on that
|
||||||
/** \internal Align the matrix itself if it is vectorizable fixed-size */
|
/** \internal Align the matrix itself if it is vectorizable fixed-size */
|
||||||
AutoAlign = 0,
|
AutoAlign = 0,
|
||||||
@@ -211,11 +271,13 @@ enum {
|
|||||||
DontAlign = 0x2
|
DontAlign = 0x2
|
||||||
};
|
};
|
||||||
|
|
||||||
/** \brief Enum for specifying whether to apply or solve on the left or right.
|
/** \ingroup enums
|
||||||
*/
|
* Enum for specifying whether to apply or solve on the left or right. */
|
||||||
enum {
|
enum {
|
||||||
OnTheLeft = 1, /**< \brief Apply transformation on the left. */
|
/** Apply transformation on the left. */
|
||||||
OnTheRight = 2 /**< \brief Apply transformation on the right. */
|
OnTheLeft = 1,
|
||||||
|
/** Apply transformation on the right. */
|
||||||
|
OnTheRight = 2
|
||||||
};
|
};
|
||||||
|
|
||||||
/* the following could as well be written:
|
/* the following could as well be written:
|
||||||
@@ -239,53 +301,108 @@ namespace {
|
|||||||
EIGEN_UNUSED Default_t Default;
|
EIGEN_UNUSED Default_t Default;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** \internal \ingroup enums
|
||||||
|
* Used in AmbiVector. */
|
||||||
enum {
|
enum {
|
||||||
IsDense = 0,
|
IsDense = 0,
|
||||||
IsSparse
|
IsSparse
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** \ingroup enums
|
||||||
|
* Used as template parameter in DenseCoeffBase and MapBase to indicate
|
||||||
|
* which accessors should be provided. */
|
||||||
enum AccessorLevels {
|
enum AccessorLevels {
|
||||||
ReadOnlyAccessors, WriteAccessors, DirectAccessors, DirectWriteAccessors
|
/** Read-only access via a member function. */
|
||||||
|
ReadOnlyAccessors,
|
||||||
|
/** Read/write access via member functions. */
|
||||||
|
WriteAccessors,
|
||||||
|
/** Direct read-only access to the coefficients. */
|
||||||
|
DirectAccessors,
|
||||||
|
/** Direct read/write access to the coefficients. */
|
||||||
|
DirectWriteAccessors
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** \ingroup enums
|
||||||
|
* Enum with options to give to various decompositions. */
|
||||||
enum DecompositionOptions {
|
enum DecompositionOptions {
|
||||||
Pivoting = 0x01, // LDLT,
|
/** \internal Not used (meant for LDLT?). */
|
||||||
NoPivoting = 0x02, // LDLT,
|
Pivoting = 0x01,
|
||||||
ComputeFullU = 0x04, // SVD,
|
/** \internal Not used (meant for LDLT?). */
|
||||||
ComputeThinU = 0x08, // SVD,
|
NoPivoting = 0x02,
|
||||||
ComputeFullV = 0x10, // SVD,
|
/** Used in JacobiSVD to indicate that the square matrix U is to be computed. */
|
||||||
ComputeThinV = 0x20, // SVD,
|
ComputeFullU = 0x04,
|
||||||
EigenvaluesOnly = 0x40, // all eigen solvers
|
/** Used in JacobiSVD to indicate that the thin matrix U is to be computed. */
|
||||||
ComputeEigenvectors = 0x80, // all eigen solvers
|
ComputeThinU = 0x08,
|
||||||
|
/** Used in JacobiSVD to indicate that the square matrix V is to be computed. */
|
||||||
|
ComputeFullV = 0x10,
|
||||||
|
/** Used in JacobiSVD to indicate that the thin matrix V is to be computed. */
|
||||||
|
ComputeThinV = 0x20,
|
||||||
|
/** Used in SelfAdjointEigenSolver and GeneralizedSelfAdjointEigenSolver to specify
|
||||||
|
* that only the eigenvalues are to be computed and not the eigenvectors. */
|
||||||
|
EigenvaluesOnly = 0x40,
|
||||||
|
/** Used in SelfAdjointEigenSolver and GeneralizedSelfAdjointEigenSolver to specify
|
||||||
|
* that both the eigenvalues and the eigenvectors are to be computed. */
|
||||||
|
ComputeEigenvectors = 0x80,
|
||||||
|
/** \internal */
|
||||||
EigVecMask = EigenvaluesOnly | ComputeEigenvectors,
|
EigVecMask = EigenvaluesOnly | ComputeEigenvectors,
|
||||||
|
/** Used in GeneralizedSelfAdjointEigenSolver to indicate that it should
|
||||||
|
* solve the generalized eigenproblem \f$ Ax = \lambda B x \f$. */
|
||||||
Ax_lBx = 0x100,
|
Ax_lBx = 0x100,
|
||||||
|
/** Used in GeneralizedSelfAdjointEigenSolver to indicate that it should
|
||||||
|
* solve the generalized eigenproblem \f$ ABx = \lambda x \f$. */
|
||||||
ABx_lx = 0x200,
|
ABx_lx = 0x200,
|
||||||
|
/** Used in GeneralizedSelfAdjointEigenSolver to indicate that it should
|
||||||
|
* solve the generalized eigenproblem \f$ BAx = \lambda x \f$. */
|
||||||
BAx_lx = 0x400,
|
BAx_lx = 0x400,
|
||||||
|
/** \internal */
|
||||||
GenEigMask = Ax_lBx | ABx_lx | BAx_lx
|
GenEigMask = Ax_lBx | ABx_lx | BAx_lx
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** \ingroup enums
|
||||||
|
* Possible values for the \p QRPreconditioner template parameter of JacobiSVD. */
|
||||||
enum QRPreconditioners {
|
enum QRPreconditioners {
|
||||||
|
/** Do not specify what is to be done if the SVD of a non-square matrix is asked for. */
|
||||||
NoQRPreconditioner,
|
NoQRPreconditioner,
|
||||||
|
/** Use a QR decomposition without pivoting as the first step. */
|
||||||
HouseholderQRPreconditioner,
|
HouseholderQRPreconditioner,
|
||||||
|
/** Use a QR decomposition with column pivoting as the first step. */
|
||||||
ColPivHouseholderQRPreconditioner,
|
ColPivHouseholderQRPreconditioner,
|
||||||
|
/** Use a QR decomposition with full pivoting as the first step. */
|
||||||
FullPivHouseholderQRPreconditioner
|
FullPivHouseholderQRPreconditioner
|
||||||
};
|
};
|
||||||
|
|
||||||
/** \brief Enum for reporting the status of a computation.
|
#ifdef Success
|
||||||
*/
|
#error The preprocessor symbol 'Success' is defined, possibly by the X11 header file X.h
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** \ingroups enums
|
||||||
|
* Enum for reporting the status of a computation. */
|
||||||
enum ComputationInfo {
|
enum ComputationInfo {
|
||||||
Success = 0, /**< \brief Computation was successful. */
|
/** Computation was successful. */
|
||||||
NumericalIssue = 1, /**< \brief The provided data did not satisfy the prerequisites. */
|
Success = 0,
|
||||||
NoConvergence = 2 /**< \brief Iterative procedure did not converge. */
|
/** The provided data did not satisfy the prerequisites. */
|
||||||
|
NumericalIssue = 1,
|
||||||
|
/** Iterative procedure did not converge. */
|
||||||
|
NoConvergence = 2
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** \ingroup enums
|
||||||
|
* Enum used to specify how a particular transformation is stored in a matrix.
|
||||||
|
* \sa Transform, Hyperplane::transform(). */
|
||||||
enum TransformTraits {
|
enum TransformTraits {
|
||||||
|
/** Transformation is an isometry. */
|
||||||
Isometry = 0x1,
|
Isometry = 0x1,
|
||||||
|
/** Transformation is an affine transformation stored as a (Dim+1)^2 matrix whose last row is
|
||||||
|
* assumed to be [0 ... 0 1]. */
|
||||||
Affine = 0x2,
|
Affine = 0x2,
|
||||||
|
/** Transformation is an affine transformation stored as a (Dim) x (Dim+1) matrix. */
|
||||||
AffineCompact = 0x10 | Affine,
|
AffineCompact = 0x10 | Affine,
|
||||||
|
/** Transformation is a general projective transformation stored as a (Dim+1)^2 matrix. */
|
||||||
Projective = 0x20
|
Projective = 0x20
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** \internal \ingroup enums
|
||||||
|
* Enum used to choose between implementation depending on the computer architecture. */
|
||||||
namespace Architecture
|
namespace Architecture
|
||||||
{
|
{
|
||||||
enum Type {
|
enum Type {
|
||||||
@@ -302,8 +419,12 @@ namespace Architecture
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** \internal \ingroup enums
|
||||||
|
* Enum used as template parameter in GeneralProduct. */
|
||||||
enum { CoeffBasedProductMode, LazyCoeffBasedProductMode, OuterProduct, InnerProduct, GemvProduct, GemmProduct };
|
enum { CoeffBasedProductMode, LazyCoeffBasedProductMode, OuterProduct, InnerProduct, GemvProduct, GemmProduct };
|
||||||
|
|
||||||
|
/** \internal \ingroup enums
|
||||||
|
* Enum used in experimental parallel implementation. */
|
||||||
enum Action {GetAction, SetAction};
|
enum Action {GetAction, SetAction};
|
||||||
|
|
||||||
/** The type used to identify a dense storage. */
|
/** The type used to identify a dense storage. */
|
||||||
|
|||||||
@@ -26,9 +26,9 @@
|
|||||||
#ifndef EIGEN_MACROS_H
|
#ifndef EIGEN_MACROS_H
|
||||||
#define EIGEN_MACROS_H
|
#define EIGEN_MACROS_H
|
||||||
|
|
||||||
#define EIGEN_WORLD_VERSION 2
|
#define EIGEN_WORLD_VERSION 3
|
||||||
#define EIGEN_MAJOR_VERSION 95
|
#define EIGEN_MAJOR_VERSION 0
|
||||||
#define EIGEN_MINOR_VERSION 0
|
#define EIGEN_MINOR_VERSION 2
|
||||||
|
|
||||||
#define EIGEN_VERSION_AT_LEAST(x,y,z) (EIGEN_WORLD_VERSION>x || (EIGEN_WORLD_VERSION>=x && \
|
#define EIGEN_VERSION_AT_LEAST(x,y,z) (EIGEN_WORLD_VERSION>x || (EIGEN_WORLD_VERSION>=x && \
|
||||||
(EIGEN_MAJOR_VERSION>y || (EIGEN_MAJOR_VERSION>=y && \
|
(EIGEN_MAJOR_VERSION>y || (EIGEN_MAJOR_VERSION>=y && \
|
||||||
@@ -399,7 +399,7 @@
|
|||||||
#define EIGEN_MAKE_CWISE_BINARY_OP(METHOD,FUNCTOR) \
|
#define EIGEN_MAKE_CWISE_BINARY_OP(METHOD,FUNCTOR) \
|
||||||
template<typename OtherDerived> \
|
template<typename OtherDerived> \
|
||||||
EIGEN_STRONG_INLINE const CwiseBinaryOp<FUNCTOR<Scalar>, const Derived, const OtherDerived> \
|
EIGEN_STRONG_INLINE const CwiseBinaryOp<FUNCTOR<Scalar>, const Derived, const OtherDerived> \
|
||||||
METHOD(const EIGEN_CURRENT_STORAGE_BASE_CLASS<OtherDerived> &other) const \
|
(METHOD)(const EIGEN_CURRENT_STORAGE_BASE_CLASS<OtherDerived> &other) const \
|
||||||
{ \
|
{ \
|
||||||
return CwiseBinaryOp<FUNCTOR<Scalar>, const Derived, const OtherDerived>(derived(), other.derived()); \
|
return CwiseBinaryOp<FUNCTOR<Scalar>, const Derived, const OtherDerived>(derived(), other.derived()); \
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -156,7 +156,7 @@ inline void* generic_aligned_realloc(void* ptr, size_t size, size_t old_size)
|
|||||||
|
|
||||||
if (ptr != 0)
|
if (ptr != 0)
|
||||||
{
|
{
|
||||||
std::memcpy(newptr, ptr, std::min(size,old_size));
|
std::memcpy(newptr, ptr, (std::min)(size,old_size));
|
||||||
aligned_free(ptr);
|
aligned_free(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -468,36 +468,87 @@ inline static Index first_aligned(const Scalar* array, Index size)
|
|||||||
*** Implementation of runtime stack allocation (falling back to malloc) ***
|
*** Implementation of runtime stack allocation (falling back to malloc) ***
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
/** \internal
|
// you can overwrite Eigen's default behavior regarding alloca by defining EIGEN_ALLOCA
|
||||||
* Allocates an aligned buffer of SIZE bytes on the stack if SIZE is smaller than
|
// to the appropriate stack allocation function
|
||||||
* EIGEN_STACK_ALLOCATION_LIMIT, and if stack allocation is supported by the platform
|
#ifndef EIGEN_ALLOCA
|
||||||
* (currently, this is Linux only). Otherwise the memory is allocated on the heap.
|
#if (defined __linux__)
|
||||||
* Data allocated with ei_aligned_stack_alloc \b must be freed by calling
|
#define EIGEN_ALLOCA alloca
|
||||||
* ei_aligned_stack_free(PTR,SIZE).
|
#elif defined(_MSC_VER)
|
||||||
* \code
|
#define EIGEN_ALLOCA _alloca
|
||||||
* float * data = ei_aligned_stack_alloc(float,array.size());
|
#endif
|
||||||
* // ...
|
|
||||||
* ei_aligned_stack_free(data,float,array.size());
|
|
||||||
* \endcode
|
|
||||||
*/
|
|
||||||
#if (defined __linux__)
|
|
||||||
#define ei_aligned_stack_alloc(SIZE) (SIZE<=EIGEN_STACK_ALLOCATION_LIMIT) \
|
|
||||||
? alloca(SIZE) \
|
|
||||||
: Eigen::internal::aligned_malloc(SIZE)
|
|
||||||
#define ei_aligned_stack_free(PTR,SIZE) if(SIZE>EIGEN_STACK_ALLOCATION_LIMIT) Eigen::internal::aligned_free(PTR)
|
|
||||||
#elif defined(_MSC_VER)
|
|
||||||
#define ei_aligned_stack_alloc(SIZE) (SIZE<=EIGEN_STACK_ALLOCATION_LIMIT) \
|
|
||||||
? _alloca(SIZE) \
|
|
||||||
: Eigen::internal::aligned_malloc(SIZE)
|
|
||||||
#define ei_aligned_stack_free(PTR,SIZE) if(SIZE>EIGEN_STACK_ALLOCATION_LIMIT) Eigen::internal::aligned_free(PTR)
|
|
||||||
#else
|
|
||||||
#define ei_aligned_stack_alloc(SIZE) Eigen::internal::aligned_malloc(SIZE)
|
|
||||||
#define ei_aligned_stack_free(PTR,SIZE) Eigen::internal::aligned_free(PTR)
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define ei_aligned_stack_new(TYPE,SIZE) Eigen::internal::construct_elements_of_array(reinterpret_cast<TYPE*>(ei_aligned_stack_alloc(sizeof(TYPE)*SIZE)), SIZE)
|
namespace internal {
|
||||||
#define ei_aligned_stack_delete(TYPE,PTR,SIZE) do {Eigen::internal::destruct_elements_of_array<TYPE>(PTR, SIZE); \
|
|
||||||
ei_aligned_stack_free(PTR,sizeof(TYPE)*SIZE);} while(0)
|
// This helper class construct the allocated memory, and takes care of destructing and freeing the handled data
|
||||||
|
// at destruction time. In practice this helper class is mainly useful to avoid memory leak in case of exceptions.
|
||||||
|
template<typename T> class aligned_stack_memory_handler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/* Creates a stack_memory_handler responsible for the buffer \a ptr of size \a size.
|
||||||
|
* Note that \a ptr can be 0 regardless of the other parameters.
|
||||||
|
* This constructor takes care of constructing/initializing the elements of the buffer if required by the scalar type T (see NumTraits<T>::RequireInitialization).
|
||||||
|
* In this case, the buffer elements will also be destructed when this handler will be destructed.
|
||||||
|
* Finally, if \a dealloc is true, then the pointer \a ptr is freed.
|
||||||
|
**/
|
||||||
|
aligned_stack_memory_handler(T* ptr, size_t size, bool dealloc)
|
||||||
|
: m_ptr(ptr), m_size(size), m_deallocate(dealloc)
|
||||||
|
{
|
||||||
|
if(NumTraits<T>::RequireInitialization && m_ptr)
|
||||||
|
Eigen::internal::construct_elements_of_array(m_ptr, size);
|
||||||
|
}
|
||||||
|
~aligned_stack_memory_handler()
|
||||||
|
{
|
||||||
|
if(NumTraits<T>::RequireInitialization && m_ptr)
|
||||||
|
Eigen::internal::destruct_elements_of_array<T>(m_ptr, m_size);
|
||||||
|
if(m_deallocate)
|
||||||
|
Eigen::internal::aligned_free(m_ptr);
|
||||||
|
}
|
||||||
|
protected:
|
||||||
|
T* m_ptr;
|
||||||
|
size_t m_size;
|
||||||
|
bool m_deallocate;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/** \internal
|
||||||
|
* Declares, allocates and construct an aligned buffer named NAME of SIZE elements of type TYPE on the stack
|
||||||
|
* if SIZE is smaller than EIGEN_STACK_ALLOCATION_LIMIT, and if stack allocation is supported by the platform
|
||||||
|
* (currently, this is Linux and Visual Studio only). Otherwise the memory is allocated on the heap.
|
||||||
|
* The allocated buffer is automatically deleted when exiting the scope of this declaration.
|
||||||
|
* If BUFFER is non nul, then the declared variable is simply an alias for BUFFER, and no allocation/deletion occurs.
|
||||||
|
* Here is an example:
|
||||||
|
* \code
|
||||||
|
* {
|
||||||
|
* ei_declare_aligned_stack_constructed_variable(float,data,size,0);
|
||||||
|
* // use data[0] to data[size-1]
|
||||||
|
* }
|
||||||
|
* \endcode
|
||||||
|
* The underlying stack allocation function can controlled with the EIGEN_ALLOCA preprocessor token.
|
||||||
|
*/
|
||||||
|
#ifdef EIGEN_ALLOCA
|
||||||
|
|
||||||
|
#ifdef __arm__
|
||||||
|
#define EIGEN_ALIGNED_ALLOCA(SIZE) reinterpret_cast<void*>((reinterpret_cast<size_t>(EIGEN_ALLOCA(SIZE+16)) & ~(size_t(15))) + 16)
|
||||||
|
#else
|
||||||
|
#define EIGEN_ALIGNED_ALLOCA EIGEN_ALLOCA
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define ei_declare_aligned_stack_constructed_variable(TYPE,NAME,SIZE,BUFFER) \
|
||||||
|
TYPE* NAME = (BUFFER)!=0 ? (BUFFER) \
|
||||||
|
: reinterpret_cast<TYPE*>( \
|
||||||
|
(sizeof(TYPE)*SIZE<=EIGEN_STACK_ALLOCATION_LIMIT) ? EIGEN_ALIGNED_ALLOCA(sizeof(TYPE)*SIZE) \
|
||||||
|
: Eigen::internal::aligned_malloc(sizeof(TYPE)*SIZE) ); \
|
||||||
|
Eigen::internal::aligned_stack_memory_handler<TYPE> EIGEN_CAT(NAME,_stack_memory_destructor)((BUFFER)==0 ? NAME : 0,SIZE,sizeof(TYPE)*SIZE>EIGEN_STACK_ALLOCATION_LIMIT)
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define ei_declare_aligned_stack_constructed_variable(TYPE,NAME,SIZE,BUFFER) \
|
||||||
|
TYPE* NAME = (BUFFER)!=0 ? BUFFER : reinterpret_cast<TYPE*>(Eigen::internal::aligned_malloc(sizeof(TYPE)*SIZE)); \
|
||||||
|
Eigen::internal::aligned_stack_memory_handler<TYPE> EIGEN_CAT(NAME,_stack_memory_destructor)((BUFFER)==0 ? NAME : 0,SIZE,true)
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
@@ -612,12 +663,12 @@ public:
|
|||||||
|
|
||||||
size_type max_size() const throw()
|
size_type max_size() const throw()
|
||||||
{
|
{
|
||||||
return std::numeric_limits<size_type>::max();
|
return (std::numeric_limits<size_type>::max)();
|
||||||
}
|
}
|
||||||
|
|
||||||
pointer allocate( size_type num, const_pointer* hint = 0 )
|
pointer allocate( size_type num, const void* hint = 0 )
|
||||||
{
|
{
|
||||||
static_cast<void>( hint ); // suppress unused variable warning
|
EIGEN_UNUSED_VARIABLE(hint);
|
||||||
return static_cast<pointer>( internal::aligned_malloc( num * sizeof(T) ) );
|
return static_cast<pointer>( internal::aligned_malloc( num * sizeof(T) ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -852,7 +903,7 @@ inline int queryTopLevelCacheSize()
|
|||||||
{
|
{
|
||||||
int l1, l2(-1), l3(-1);
|
int l1, l2(-1), l3(-1);
|
||||||
queryCacheSizes(l1,l2,l3);
|
queryCacheSizes(l1,l2,l3);
|
||||||
return std::max(l2,l3);
|
return (std::max)(l2,l3);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // end namespace internal
|
} // end namespace internal
|
||||||
|
|||||||
@@ -82,13 +82,17 @@ template<typename ExpressionType> class Cwise
|
|||||||
const EIGEN_CWISE_BINOP_RETURN_TYPE(internal::scalar_quotient_op)
|
const EIGEN_CWISE_BINOP_RETURN_TYPE(internal::scalar_quotient_op)
|
||||||
operator/(const MatrixBase<OtherDerived> &other) const;
|
operator/(const MatrixBase<OtherDerived> &other) const;
|
||||||
|
|
||||||
|
/** \deprecated ArrayBase::min() */
|
||||||
template<typename OtherDerived>
|
template<typename OtherDerived>
|
||||||
const EIGEN_CWISE_BINOP_RETURN_TYPE(internal::scalar_min_op)
|
const EIGEN_CWISE_BINOP_RETURN_TYPE(internal::scalar_min_op)
|
||||||
min(const MatrixBase<OtherDerived> &other) const;
|
(min)(const MatrixBase<OtherDerived> &other) const
|
||||||
|
{ return EIGEN_CWISE_BINOP_RETURN_TYPE(internal::scalar_min_op)(_expression(), other.derived()); }
|
||||||
|
|
||||||
|
/** \deprecated ArrayBase::max() */
|
||||||
template<typename OtherDerived>
|
template<typename OtherDerived>
|
||||||
const EIGEN_CWISE_BINOP_RETURN_TYPE(internal::scalar_max_op)
|
const EIGEN_CWISE_BINOP_RETURN_TYPE(internal::scalar_max_op)
|
||||||
max(const MatrixBase<OtherDerived> &other) const;
|
(max)(const MatrixBase<OtherDerived> &other) const
|
||||||
|
{ return EIGEN_CWISE_BINOP_RETURN_TYPE(internal::scalar_max_op)(_expression(), other.derived()); }
|
||||||
|
|
||||||
const EIGEN_CWISE_UNOP_RETURN_TYPE(internal::scalar_abs_op) abs() const;
|
const EIGEN_CWISE_UNOP_RETURN_TYPE(internal::scalar_abs_op) abs() const;
|
||||||
const EIGEN_CWISE_UNOP_RETURN_TYPE(internal::scalar_abs2_op) abs2() const;
|
const EIGEN_CWISE_UNOP_RETURN_TYPE(internal::scalar_abs2_op) abs2() const;
|
||||||
|
|||||||
@@ -96,24 +96,6 @@ inline ExpressionType& Cwise<ExpressionType>::operator/=(const MatrixBase<OtherD
|
|||||||
return m_matrix.const_cast_derived() = *this / other;
|
return m_matrix.const_cast_derived() = *this / other;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** \deprecated ArrayBase::min() */
|
|
||||||
template<typename ExpressionType>
|
|
||||||
template<typename OtherDerived>
|
|
||||||
EIGEN_STRONG_INLINE const EIGEN_CWISE_BINOP_RETURN_TYPE(internal::scalar_min_op)
|
|
||||||
Cwise<ExpressionType>::min(const MatrixBase<OtherDerived> &other) const
|
|
||||||
{
|
|
||||||
return EIGEN_CWISE_BINOP_RETURN_TYPE(internal::scalar_min_op)(_expression(), other.derived());
|
|
||||||
}
|
|
||||||
|
|
||||||
/** \deprecated ArrayBase::max() */
|
|
||||||
template<typename ExpressionType>
|
|
||||||
template<typename OtherDerived>
|
|
||||||
EIGEN_STRONG_INLINE const EIGEN_CWISE_BINOP_RETURN_TYPE(internal::scalar_max_op)
|
|
||||||
Cwise<ExpressionType>::max(const MatrixBase<OtherDerived> &other) const
|
|
||||||
{
|
|
||||||
return EIGEN_CWISE_BINOP_RETURN_TYPE(internal::scalar_max_op)(_expression(), other.derived());
|
|
||||||
}
|
|
||||||
|
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
* The following functions were defined in Array
|
* The following functions were defined in Array
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|||||||
@@ -51,14 +51,14 @@ EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_AmbientDim==
|
|||||||
{ if (AmbientDimAtCompileTime!=Dynamic) setNull(); }
|
{ if (AmbientDimAtCompileTime!=Dynamic) setNull(); }
|
||||||
|
|
||||||
/** Constructs a null box with \a _dim the dimension of the ambient space. */
|
/** Constructs a null box with \a _dim the dimension of the ambient space. */
|
||||||
inline explicit AlignedBox(int _dim) : m_min(_dim), m_max(_dim)
|
inline explicit AlignedBox(int _dim) : m_(min)(_dim), m_(max)(_dim)
|
||||||
{ setNull(); }
|
{ setNull(); }
|
||||||
|
|
||||||
/** Constructs a box with extremities \a _min and \a _max. */
|
/** Constructs a box with extremities \a _min and \a _max. */
|
||||||
inline AlignedBox(const VectorType& _min, const VectorType& _max) : m_min(_min), m_max(_max) {}
|
inline AlignedBox(const VectorType& _min, const VectorType& _max) : m_(min)(_min), m_(max)(_max) {}
|
||||||
|
|
||||||
/** Constructs a box containing a single point \a p. */
|
/** Constructs a box containing a single point \a p. */
|
||||||
inline explicit AlignedBox(const VectorType& p) : m_min(p), m_max(p) {}
|
inline explicit AlignedBox(const VectorType& p) : m_(min)(p), m_(max)(p) {}
|
||||||
|
|
||||||
~AlignedBox() {}
|
~AlignedBox() {}
|
||||||
|
|
||||||
@@ -71,18 +71,18 @@ EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_AmbientDim==
|
|||||||
/** Makes \c *this a null/empty box. */
|
/** Makes \c *this a null/empty box. */
|
||||||
inline void setNull()
|
inline void setNull()
|
||||||
{
|
{
|
||||||
m_min.setConstant( std::numeric_limits<Scalar>::max());
|
m_min.setConstant( std::numeric_limits<Scalar>::(max)());
|
||||||
m_max.setConstant(-std::numeric_limits<Scalar>::max());
|
m_max.setConstant(-std::numeric_limits<Scalar>::(max)());
|
||||||
}
|
}
|
||||||
|
|
||||||
/** \returns the minimal corner */
|
/** \returns the minimal corner */
|
||||||
inline const VectorType& min() const { return m_min; }
|
inline const VectorType& (min)() const { return m_min; }
|
||||||
/** \returns a non const reference to the minimal corner */
|
/** \returns a non const reference to the minimal corner */
|
||||||
inline VectorType& min() { return m_min; }
|
inline VectorType& (min)() { return m_min; }
|
||||||
/** \returns the maximal corner */
|
/** \returns the maximal corner */
|
||||||
inline const VectorType& max() const { return m_max; }
|
inline const VectorType& (max)() const { return m_max; }
|
||||||
/** \returns a non const reference to the maximal corner */
|
/** \returns a non const reference to the maximal corner */
|
||||||
inline VectorType& max() { return m_max; }
|
inline VectorType& (max)() { return m_max; }
|
||||||
|
|
||||||
/** \returns true if the point \a p is inside the box \c *this. */
|
/** \returns true if the point \a p is inside the box \c *this. */
|
||||||
inline bool contains(const VectorType& p) const
|
inline bool contains(const VectorType& p) const
|
||||||
@@ -90,19 +90,19 @@ EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_AmbientDim==
|
|||||||
|
|
||||||
/** \returns true if the box \a b is entirely inside the box \c *this. */
|
/** \returns true if the box \a b is entirely inside the box \c *this. */
|
||||||
inline bool contains(const AlignedBox& b) const
|
inline bool contains(const AlignedBox& b) const
|
||||||
{ return (m_min.cwise()<=b.min()).all() && (b.max().cwise()<=m_max).all(); }
|
{ return (m_min.cwise()<=b.(min)()).all() && (b.(max)().cwise()<=m_max).all(); }
|
||||||
|
|
||||||
/** Extends \c *this such that it contains the point \a p and returns a reference to \c *this. */
|
/** Extends \c *this such that it contains the point \a p and returns a reference to \c *this. */
|
||||||
inline AlignedBox& extend(const VectorType& p)
|
inline AlignedBox& extend(const VectorType& p)
|
||||||
{ m_min = m_min.cwise().min(p); m_max = m_max.cwise().max(p); return *this; }
|
{ m_min = m_min.cwise().(min)(p); m_max = m_max.cwise().(max)(p); return *this; }
|
||||||
|
|
||||||
/** Extends \c *this such that it contains the box \a b and returns a reference to \c *this. */
|
/** Extends \c *this such that it contains the box \a b and returns a reference to \c *this. */
|
||||||
inline AlignedBox& extend(const AlignedBox& b)
|
inline AlignedBox& extend(const AlignedBox& b)
|
||||||
{ m_min = m_min.cwise().min(b.m_min); m_max = m_max.cwise().max(b.m_max); return *this; }
|
{ m_min = m_min.cwise().(min)(b.m_min); m_max = m_max.cwise().(max)(b.m_max); return *this; }
|
||||||
|
|
||||||
/** Clamps \c *this by the box \a b and returns a reference to \c *this. */
|
/** Clamps \c *this by the box \a b and returns a reference to \c *this. */
|
||||||
inline AlignedBox& clamp(const AlignedBox& b)
|
inline AlignedBox& clamp(const AlignedBox& b)
|
||||||
{ m_min = m_min.cwise().max(b.m_min); m_max = m_max.cwise().min(b.m_max); return *this; }
|
{ m_min = m_min.cwise().(max)(b.m_min); m_max = m_max.cwise().(min)(b.m_max); return *this; }
|
||||||
|
|
||||||
/** Translate \c *this by the vector \a t and returns a reference to \c *this. */
|
/** Translate \c *this by the vector \a t and returns a reference to \c *this. */
|
||||||
inline AlignedBox& translate(const VectorType& t)
|
inline AlignedBox& translate(const VectorType& t)
|
||||||
@@ -138,8 +138,8 @@ EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_AmbientDim==
|
|||||||
template<typename OtherScalarType>
|
template<typename OtherScalarType>
|
||||||
inline explicit AlignedBox(const AlignedBox<OtherScalarType,AmbientDimAtCompileTime>& other)
|
inline explicit AlignedBox(const AlignedBox<OtherScalarType,AmbientDimAtCompileTime>& other)
|
||||||
{
|
{
|
||||||
m_min = other.min().template cast<Scalar>();
|
m_min = other.(min)().template cast<Scalar>();
|
||||||
m_max = other.max().template cast<Scalar>();
|
m_max = other.(max)().template cast<Scalar>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** \returns \c true if \c *this is approximately equal to \a other, within the precision
|
/** \returns \c true if \c *this is approximately equal to \a other, within the precision
|
||||||
|
|||||||
@@ -64,9 +64,9 @@ template<typename MatrixType> class SVD
|
|||||||
SVD() {} // a user who relied on compiler-generated default compiler reported problems with MSVC in 2.0.7
|
SVD() {} // a user who relied on compiler-generated default compiler reported problems with MSVC in 2.0.7
|
||||||
|
|
||||||
SVD(const MatrixType& matrix)
|
SVD(const MatrixType& matrix)
|
||||||
: m_matU(matrix.rows(), std::min(matrix.rows(), matrix.cols())),
|
: m_matU(matrix.rows(), (std::min)(matrix.rows(), matrix.cols())),
|
||||||
m_matV(matrix.cols(),matrix.cols()),
|
m_matV(matrix.cols(),matrix.cols()),
|
||||||
m_sigma(std::min(matrix.rows(),matrix.cols()))
|
m_sigma((std::min)(matrix.rows(),matrix.cols()))
|
||||||
{
|
{
|
||||||
compute(matrix);
|
compute(matrix);
|
||||||
}
|
}
|
||||||
@@ -108,13 +108,13 @@ void SVD<MatrixType>::compute(const MatrixType& matrix)
|
|||||||
{
|
{
|
||||||
const int m = matrix.rows();
|
const int m = matrix.rows();
|
||||||
const int n = matrix.cols();
|
const int n = matrix.cols();
|
||||||
const int nu = std::min(m,n);
|
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>=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");
|
ei_assert(m>1 && "In Eigen 2.0, SVD doesn't work on 1x1 matrices");
|
||||||
|
|
||||||
m_matU.resize(m, nu);
|
m_matU.resize(m, nu);
|
||||||
m_matU.setZero();
|
m_matU.setZero();
|
||||||
m_sigma.resize(std::min(m,n));
|
m_sigma.resize((std::min)(m,n));
|
||||||
m_matV.resize(n,n);
|
m_matV.resize(n,n);
|
||||||
|
|
||||||
RowVector e(n);
|
RowVector e(n);
|
||||||
@@ -126,9 +126,9 @@ void SVD<MatrixType>::compute(const MatrixType& matrix)
|
|||||||
|
|
||||||
// Reduce A to bidiagonal form, storing the diagonal elements
|
// Reduce A to bidiagonal form, storing the diagonal elements
|
||||||
// in s and the super-diagonal elements in e.
|
// in s and the super-diagonal elements in e.
|
||||||
int nct = std::min(m-1,n);
|
int nct = (std::min)(m-1,n);
|
||||||
int nrt = std::max(0,std::min(n-2,m));
|
int nrt = (std::max)(0,(std::min)(n-2,m));
|
||||||
for (k = 0; k < std::max(nct,nrt); ++k)
|
for (k = 0; k < (std::max)(nct,nrt); ++k)
|
||||||
{
|
{
|
||||||
if (k < nct)
|
if (k < nct)
|
||||||
{
|
{
|
||||||
@@ -193,7 +193,7 @@ void SVD<MatrixType>::compute(const MatrixType& matrix)
|
|||||||
|
|
||||||
|
|
||||||
// Set up the final bidiagonal matrix or order p.
|
// Set up the final bidiagonal matrix or order p.
|
||||||
int p = std::min(n,m+1);
|
int p = (std::min)(n,m+1);
|
||||||
if (nct < n)
|
if (nct < n)
|
||||||
m_sigma[nct] = matA(nct,nct);
|
m_sigma[nct] = matA(nct,nct);
|
||||||
if (m < p)
|
if (m < p)
|
||||||
@@ -380,7 +380,7 @@ void SVD<MatrixType>::compute(const MatrixType& matrix)
|
|||||||
case 3:
|
case 3:
|
||||||
{
|
{
|
||||||
// Calculate the shift.
|
// Calculate the shift.
|
||||||
Scalar scale = std::max(std::max(std::max(std::max(
|
Scalar scale = (std::max)((std::max)((std::max)((std::max)(
|
||||||
ei_abs(m_sigma[p-1]),ei_abs(m_sigma[p-2])),ei_abs(e[p-2])),
|
ei_abs(m_sigma[p-1]),ei_abs(m_sigma[p-2])),ei_abs(e[p-2])),
|
||||||
ei_abs(m_sigma[k])),ei_abs(e[k]));
|
ei_abs(m_sigma[k])),ei_abs(e[k]));
|
||||||
Scalar sp = m_sigma[p-1]/scale;
|
Scalar sp = m_sigma[p-1]/scale;
|
||||||
|
|||||||
@@ -423,7 +423,7 @@ void ComplexSchur<MatrixType>::reduceToTriangularForm(bool computeU)
|
|||||||
JacobiRotation<ComplexScalar> rot;
|
JacobiRotation<ComplexScalar> rot;
|
||||||
rot.makeGivens(m_matT.coeff(il,il) - shift, m_matT.coeff(il+1,il));
|
rot.makeGivens(m_matT.coeff(il,il) - shift, m_matT.coeff(il+1,il));
|
||||||
m_matT.rightCols(m_matT.cols()-il).applyOnTheLeft(il, il+1, rot.adjoint());
|
m_matT.rightCols(m_matT.cols()-il).applyOnTheLeft(il, il+1, rot.adjoint());
|
||||||
m_matT.topRows(std::min(il+2,iu)+1).applyOnTheRight(il, il+1, rot);
|
m_matT.topRows((std::min)(il+2,iu)+1).applyOnTheRight(il, il+1, rot);
|
||||||
if(computeU) m_matU.applyOnTheRight(il, il+1, rot);
|
if(computeU) m_matU.applyOnTheRight(il, il+1, rot);
|
||||||
|
|
||||||
for(Index i=il+1 ; i<iu ; i++)
|
for(Index i=il+1 ; i<iu ; i++)
|
||||||
@@ -431,7 +431,7 @@ void ComplexSchur<MatrixType>::reduceToTriangularForm(bool computeU)
|
|||||||
rot.makeGivens(m_matT.coeffRef(i,i-1), m_matT.coeffRef(i+1,i-1), &m_matT.coeffRef(i,i-1));
|
rot.makeGivens(m_matT.coeffRef(i,i-1), m_matT.coeffRef(i+1,i-1), &m_matT.coeffRef(i,i-1));
|
||||||
m_matT.coeffRef(i+1,i-1) = ComplexScalar(0);
|
m_matT.coeffRef(i+1,i-1) = ComplexScalar(0);
|
||||||
m_matT.rightCols(m_matT.cols()-i).applyOnTheLeft(i, i+1, rot.adjoint());
|
m_matT.rightCols(m_matT.cols()-i).applyOnTheLeft(i, i+1, rot.adjoint());
|
||||||
m_matT.topRows(std::min(i+2,iu)+1).applyOnTheRight(i, i+1, rot);
|
m_matT.topRows((std::min)(i+2,iu)+1).applyOnTheRight(i, i+1, rot);
|
||||||
if(computeU) m_matU.applyOnTheRight(i, i+1, rot);
|
if(computeU) m_matU.applyOnTheRight(i, i+1, rot);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -343,6 +343,7 @@ typename EigenSolver<MatrixType>::EigenvectorsType EigenSolver<MatrixType>::eige
|
|||||||
{
|
{
|
||||||
// we have a real eigen value
|
// we have a real eigen value
|
||||||
matV.col(j) = m_eivec.col(j).template cast<ComplexScalar>();
|
matV.col(j) = m_eivec.col(j).template cast<ComplexScalar>();
|
||||||
|
matV.col(j).normalize();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -434,7 +435,7 @@ void EigenSolver<MatrixType>::doComputeEigenvectors()
|
|||||||
Scalar norm = 0.0;
|
Scalar norm = 0.0;
|
||||||
for (Index j = 0; j < size; ++j)
|
for (Index j = 0; j < size; ++j)
|
||||||
{
|
{
|
||||||
norm += m_matT.row(j).segment(std::max(j-1,Index(0)), size-std::max(j-1,Index(0))).cwiseAbs().sum();
|
norm += m_matT.row(j).segment((std::max)(j-1,Index(0)), size-(std::max)(j-1,Index(0))).cwiseAbs().sum();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Backsubstitute to find vectors of upper triangular form
|
// Backsubstitute to find vectors of upper triangular form
|
||||||
@@ -449,7 +450,7 @@ void EigenSolver<MatrixType>::doComputeEigenvectors()
|
|||||||
Scalar q = m_eivalues.coeff(n).imag();
|
Scalar q = m_eivalues.coeff(n).imag();
|
||||||
|
|
||||||
// Scalar vector
|
// Scalar vector
|
||||||
if (q == 0)
|
if (q == Scalar(0))
|
||||||
{
|
{
|
||||||
Scalar lastr=0, lastw=0;
|
Scalar lastr=0, lastw=0;
|
||||||
Index l = n;
|
Index l = n;
|
||||||
@@ -490,12 +491,12 @@ void EigenSolver<MatrixType>::doComputeEigenvectors()
|
|||||||
|
|
||||||
// Overflow control
|
// Overflow control
|
||||||
Scalar t = internal::abs(m_matT.coeff(i,n));
|
Scalar t = internal::abs(m_matT.coeff(i,n));
|
||||||
if ((eps * t) * t > 1)
|
if ((eps * t) * t > Scalar(1))
|
||||||
m_matT.col(n).tail(size-i) /= t;
|
m_matT.col(n).tail(size-i) /= t;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (q < 0) // Complex vector
|
else if (q < Scalar(0) && n > 0) // Complex vector
|
||||||
{
|
{
|
||||||
Scalar lastra=0, lastsa=0, lastw=0;
|
Scalar lastra=0, lastsa=0, lastw=0;
|
||||||
Index l = n-1;
|
Index l = n-1;
|
||||||
@@ -529,7 +530,7 @@ void EigenSolver<MatrixType>::doComputeEigenvectors()
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
l = i;
|
l = i;
|
||||||
if (m_eivalues.coeff(i).imag() == 0)
|
if (m_eivalues.coeff(i).imag() == RealScalar(0))
|
||||||
{
|
{
|
||||||
std::complex<Scalar> cc = cdiv(-ra,-sa,w,q);
|
std::complex<Scalar> cc = cdiv(-ra,-sa,w,q);
|
||||||
m_matT.coeffRef(i,n-1) = internal::real(cc);
|
m_matT.coeffRef(i,n-1) = internal::real(cc);
|
||||||
@@ -562,13 +563,18 @@ void EigenSolver<MatrixType>::doComputeEigenvectors()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Overflow control
|
// Overflow control
|
||||||
Scalar t = std::max(internal::abs(m_matT.coeff(i,n-1)),internal::abs(m_matT.coeff(i,n)));
|
using std::max;
|
||||||
if ((eps * t) * t > 1)
|
Scalar t = (max)(internal::abs(m_matT.coeff(i,n-1)),internal::abs(m_matT.coeff(i,n)));
|
||||||
|
if ((eps * t) * t > Scalar(1))
|
||||||
m_matT.block(i, n-1, size-i, 2) /= t;
|
m_matT.block(i, n-1, size-i, 2) /= t;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
eigen_assert("Internal bug in EigenSolver"); // this should not happen
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Back transformation to get eigenvectors of original matrix
|
// Back transformation to get eigenvectors of original matrix
|
||||||
|
|||||||
@@ -98,8 +98,8 @@ class GeneralizedSelfAdjointEigenSolver : public SelfAdjointEigenSolver<_MatrixT
|
|||||||
* Only the lower triangular part of the matrix is referenced.
|
* Only the lower triangular part of the matrix is referenced.
|
||||||
* \param[in] matB Positive-definite matrix in matrix pencil.
|
* \param[in] matB Positive-definite matrix in matrix pencil.
|
||||||
* Only the lower triangular part of the matrix is referenced.
|
* Only the lower triangular part of the matrix is referenced.
|
||||||
* \param[in] options A or-ed set of flags {ComputeEigenvectors,EigenvaluesOnly} | {Ax_lBx,ABx_lx,BAx_lx}.
|
* \param[in] options A or-ed set of flags {#ComputeEigenvectors,#EigenvaluesOnly} | {#Ax_lBx,#ABx_lx,#BAx_lx}.
|
||||||
* Default is ComputeEigenvectors|Ax_lBx.
|
* Default is #ComputeEigenvectors|#Ax_lBx.
|
||||||
*
|
*
|
||||||
* This constructor calls compute(const MatrixType&, const MatrixType&, int)
|
* This constructor calls compute(const MatrixType&, const MatrixType&, int)
|
||||||
* to compute the eigenvalues and (if requested) the eigenvectors of the
|
* to compute the eigenvalues and (if requested) the eigenvectors of the
|
||||||
@@ -131,8 +131,8 @@ class GeneralizedSelfAdjointEigenSolver : public SelfAdjointEigenSolver<_MatrixT
|
|||||||
* Only the lower triangular part of the matrix is referenced.
|
* Only the lower triangular part of the matrix is referenced.
|
||||||
* \param[in] matB Positive-definite matrix in matrix pencil.
|
* \param[in] matB Positive-definite matrix in matrix pencil.
|
||||||
* Only the lower triangular part of the matrix is referenced.
|
* Only the lower triangular part of the matrix is referenced.
|
||||||
* \param[in] options A or-ed set of flags {ComputeEigenvectors,EigenvaluesOnly} | {Ax_lBx,ABx_lx,BAx_lx}.
|
* \param[in] options A or-ed set of flags {#ComputeEigenvectors,#EigenvaluesOnly} | {#Ax_lBx,#ABx_lx,#BAx_lx}.
|
||||||
* Default is ComputeEigenvectors|Ax_lBx.
|
* Default is #ComputeEigenvectors|#Ax_lBx.
|
||||||
*
|
*
|
||||||
* \returns Reference to \c *this
|
* \returns Reference to \c *this
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -290,7 +290,7 @@ inline typename MatrixType::Scalar RealSchur<MatrixType>::computeNormOfT()
|
|||||||
// + m_matT.bottomLeftCorner(size-1,size-1).diagonal().cwiseAbs().sum();
|
// + m_matT.bottomLeftCorner(size-1,size-1).diagonal().cwiseAbs().sum();
|
||||||
Scalar norm = 0.0;
|
Scalar norm = 0.0;
|
||||||
for (Index j = 0; j < size; ++j)
|
for (Index j = 0; j < size; ++j)
|
||||||
norm += m_matT.row(j).segment(std::max(j-1,Index(0)), size-std::max(j-1,Index(0))).cwiseAbs().sum();
|
norm += m_matT.row(j).segment((std::max)(j-1,Index(0)), size-(std::max)(j-1,Index(0))).cwiseAbs().sum();
|
||||||
return norm;
|
return norm;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -324,11 +324,11 @@ inline void RealSchur<MatrixType>::splitOffTwoRows(Index iu, bool computeU, Scal
|
|||||||
m_matT.coeffRef(iu,iu) += exshift;
|
m_matT.coeffRef(iu,iu) += exshift;
|
||||||
m_matT.coeffRef(iu-1,iu-1) += exshift;
|
m_matT.coeffRef(iu-1,iu-1) += exshift;
|
||||||
|
|
||||||
if (q >= 0) // Two real eigenvalues
|
if (q >= Scalar(0)) // Two real eigenvalues
|
||||||
{
|
{
|
||||||
Scalar z = internal::sqrt(internal::abs(q));
|
Scalar z = internal::sqrt(internal::abs(q));
|
||||||
JacobiRotation<Scalar> rot;
|
JacobiRotation<Scalar> rot;
|
||||||
if (p >= 0)
|
if (p >= Scalar(0))
|
||||||
rot.makeGivens(p + z, m_matT.coeff(iu, iu-1));
|
rot.makeGivens(p + z, m_matT.coeff(iu, iu-1));
|
||||||
else
|
else
|
||||||
rot.makeGivens(p - z, m_matT.coeff(iu, iu-1));
|
rot.makeGivens(p - z, m_matT.coeff(iu, iu-1));
|
||||||
@@ -369,7 +369,7 @@ inline void RealSchur<MatrixType>::computeShift(Index iu, Index iter, Scalar& ex
|
|||||||
{
|
{
|
||||||
Scalar s = (shiftInfo.coeff(1) - shiftInfo.coeff(0)) / Scalar(2.0);
|
Scalar s = (shiftInfo.coeff(1) - shiftInfo.coeff(0)) / Scalar(2.0);
|
||||||
s = s * s + shiftInfo.coeff(2);
|
s = s * s + shiftInfo.coeff(2);
|
||||||
if (s > 0)
|
if (s > Scalar(0))
|
||||||
{
|
{
|
||||||
s = internal::sqrt(s);
|
s = internal::sqrt(s);
|
||||||
if (shiftInfo.coeff(1) < shiftInfo.coeff(0))
|
if (shiftInfo.coeff(1) < shiftInfo.coeff(0))
|
||||||
@@ -442,7 +442,7 @@ inline void RealSchur<MatrixType>::performFrancisQRStep(Index il, Index im, Inde
|
|||||||
|
|
||||||
// These Householder transformations form the O(n^3) part of the algorithm
|
// These Householder transformations form the O(n^3) part of the algorithm
|
||||||
m_matT.block(k, k, 3, size-k).applyHouseholderOnTheLeft(ess, tau, workspace);
|
m_matT.block(k, k, 3, size-k).applyHouseholderOnTheLeft(ess, tau, workspace);
|
||||||
m_matT.block(0, k, std::min(iu,k+3) + 1, 3).applyHouseholderOnTheRight(ess, tau, workspace);
|
m_matT.block(0, k, (std::min)(iu,k+3) + 1, 3).applyHouseholderOnTheRight(ess, tau, workspace);
|
||||||
if (computeU)
|
if (computeU)
|
||||||
m_matU.block(0, k, size, 3).applyHouseholderOnTheRight(ess, tau, workspace);
|
m_matU.block(0, k, size, 3).applyHouseholderOnTheRight(ess, tau, workspace);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -147,11 +147,11 @@ template<typename _MatrixType> class SelfAdjointEigenSolver
|
|||||||
*
|
*
|
||||||
* \param[in] matrix Selfadjoint matrix whose eigendecomposition is to
|
* \param[in] matrix Selfadjoint matrix whose eigendecomposition is to
|
||||||
* be computed. Only the lower triangular part of the matrix is referenced.
|
* be computed. Only the lower triangular part of the matrix is referenced.
|
||||||
* \param[in] options Can be ComputeEigenvectors (default) or EigenvaluesOnly.
|
* \param[in] options Can be #ComputeEigenvectors (default) or #EigenvaluesOnly.
|
||||||
*
|
*
|
||||||
* This constructor calls compute(const MatrixType&, int) to compute the
|
* This constructor calls compute(const MatrixType&, int) to compute the
|
||||||
* eigenvalues of the matrix \p matrix. The eigenvectors are computed if
|
* eigenvalues of the matrix \p matrix. The eigenvectors are computed if
|
||||||
* \p options equals ComputeEigenvectors.
|
* \p options equals #ComputeEigenvectors.
|
||||||
*
|
*
|
||||||
* Example: \include SelfAdjointEigenSolver_SelfAdjointEigenSolver_MatrixType.cpp
|
* Example: \include SelfAdjointEigenSolver_SelfAdjointEigenSolver_MatrixType.cpp
|
||||||
* Output: \verbinclude SelfAdjointEigenSolver_SelfAdjointEigenSolver_MatrixType.out
|
* Output: \verbinclude SelfAdjointEigenSolver_SelfAdjointEigenSolver_MatrixType.out
|
||||||
@@ -171,11 +171,11 @@ template<typename _MatrixType> class SelfAdjointEigenSolver
|
|||||||
*
|
*
|
||||||
* \param[in] matrix Selfadjoint matrix whose eigendecomposition is to
|
* \param[in] matrix Selfadjoint matrix whose eigendecomposition is to
|
||||||
* be computed. Only the lower triangular part of the matrix is referenced.
|
* be computed. Only the lower triangular part of the matrix is referenced.
|
||||||
* \param[in] options Can be ComputeEigenvectors (default) or EigenvaluesOnly.
|
* \param[in] options Can be #ComputeEigenvectors (default) or #EigenvaluesOnly.
|
||||||
* \returns Reference to \c *this
|
* \returns Reference to \c *this
|
||||||
*
|
*
|
||||||
* This function computes the eigenvalues of \p matrix. The eigenvalues()
|
* This function computes the eigenvalues of \p matrix. The eigenvalues()
|
||||||
* function can be used to retrieve them. If \p options equals ComputeEigenvectors,
|
* function can be used to retrieve them. If \p options equals #ComputeEigenvectors,
|
||||||
* then the eigenvectors are also computed and can be retrieved by
|
* then the eigenvectors are also computed and can be retrieved by
|
||||||
* calling eigenvectors().
|
* calling eigenvectors().
|
||||||
*
|
*
|
||||||
@@ -387,7 +387,7 @@ SelfAdjointEigenSolver<MatrixType>& SelfAdjointEigenSolver<MatrixType>
|
|||||||
{
|
{
|
||||||
m_eivalues.coeffRef(0,0) = internal::real(matrix.coeff(0,0));
|
m_eivalues.coeffRef(0,0) = internal::real(matrix.coeff(0,0));
|
||||||
if(computeEigenvectors)
|
if(computeEigenvectors)
|
||||||
m_eivec.setOnes();
|
m_eivec.setOnes(n,n);
|
||||||
m_info = Success;
|
m_info = Success;
|
||||||
m_isInitialized = true;
|
m_isInitialized = true;
|
||||||
m_eigenvectorsOk = computeEigenvectors;
|
m_eigenvectorsOk = computeEigenvectors;
|
||||||
|
|||||||
@@ -111,13 +111,13 @@ EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_AmbientDim)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** \returns the minimal corner */
|
/** \returns the minimal corner */
|
||||||
inline const VectorType& min() const { return m_min; }
|
inline const VectorType& (min)() const { return m_min; }
|
||||||
/** \returns a non const reference to the minimal corner */
|
/** \returns a non const reference to the minimal corner */
|
||||||
inline VectorType& min() { return m_min; }
|
inline VectorType& (min)() { return m_min; }
|
||||||
/** \returns the maximal corner */
|
/** \returns the maximal corner */
|
||||||
inline const VectorType& max() const { return m_max; }
|
inline const VectorType& (max)() const { return m_max; }
|
||||||
/** \returns a non const reference to the maximal corner */
|
/** \returns a non const reference to the maximal corner */
|
||||||
inline VectorType& max() { return m_max; }
|
inline VectorType& (max)() { return m_max; }
|
||||||
|
|
||||||
/** \returns the center of the box */
|
/** \returns the center of the box */
|
||||||
inline const CwiseUnaryOp<internal::scalar_quotient1_op<Scalar>,
|
inline const CwiseUnaryOp<internal::scalar_quotient1_op<Scalar>,
|
||||||
@@ -196,7 +196,7 @@ EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_AmbientDim)
|
|||||||
|
|
||||||
/** \returns true if the box \a b is entirely inside the box \c *this. */
|
/** \returns true if the box \a b is entirely inside the box \c *this. */
|
||||||
inline bool contains(const AlignedBox& b) const
|
inline bool contains(const AlignedBox& b) const
|
||||||
{ return (m_min.array()<=b.min().array()).all() && (b.max().array()<=m_max.array()).all(); }
|
{ return (m_min.array()<=(b.min)().array()).all() && ((b.max)().array()<=m_max.array()).all(); }
|
||||||
|
|
||||||
/** Extends \c *this such that it contains the point \a p and returns a reference to \c *this. */
|
/** Extends \c *this such that it contains the point \a p and returns a reference to \c *this. */
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
@@ -287,8 +287,8 @@ EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_AmbientDim)
|
|||||||
template<typename OtherScalarType>
|
template<typename OtherScalarType>
|
||||||
inline explicit AlignedBox(const AlignedBox<OtherScalarType,AmbientDimAtCompileTime>& other)
|
inline explicit AlignedBox(const AlignedBox<OtherScalarType,AmbientDimAtCompileTime>& other)
|
||||||
{
|
{
|
||||||
m_min = other.min().template cast<Scalar>();
|
m_min = (other.min)().template cast<Scalar>();
|
||||||
m_max = other.max().template cast<Scalar>();
|
m_max = (other.max)().template cast<Scalar>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** \returns \c true if \c *this is approximately equal to \a other, within the precision
|
/** \returns \c true if \c *this is approximately equal to \a other, within the precision
|
||||||
|
|||||||
@@ -171,6 +171,9 @@ template<typename Scalar>
|
|||||||
template<typename QuatDerived>
|
template<typename QuatDerived>
|
||||||
AngleAxis<Scalar>& AngleAxis<Scalar>::operator=(const QuaternionBase<QuatDerived>& q)
|
AngleAxis<Scalar>& AngleAxis<Scalar>::operator=(const QuaternionBase<QuatDerived>& q)
|
||||||
{
|
{
|
||||||
|
using std::acos;
|
||||||
|
using std::min;
|
||||||
|
using std::max;
|
||||||
Scalar n2 = q.vec().squaredNorm();
|
Scalar n2 = q.vec().squaredNorm();
|
||||||
if (n2 < NumTraits<Scalar>::dummy_precision()*NumTraits<Scalar>::dummy_precision())
|
if (n2 < NumTraits<Scalar>::dummy_precision()*NumTraits<Scalar>::dummy_precision())
|
||||||
{
|
{
|
||||||
@@ -179,7 +182,7 @@ AngleAxis<Scalar>& AngleAxis<Scalar>::operator=(const QuaternionBase<QuatDerived
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_angle = Scalar(2)*std::acos(std::min(std::max(Scalar(-1),q.w()),Scalar(1)));
|
m_angle = Scalar(2)*acos((min)((max)(Scalar(-1),q.w()),Scalar(1)));
|
||||||
m_axis = q.vec() / internal::sqrt(n2);
|
m_axis = q.vec() / internal::sqrt(n2);
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
|
|||||||
@@ -189,7 +189,7 @@ public:
|
|||||||
*
|
*
|
||||||
* \note If \a other is approximately parallel to *this, this method will return any point on *this.
|
* \note If \a other is approximately parallel to *this, this method will return any point on *this.
|
||||||
*/
|
*/
|
||||||
VectorType intersection(const Hyperplane& other)
|
VectorType intersection(const Hyperplane& other) const
|
||||||
{
|
{
|
||||||
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(VectorType, 2)
|
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(VectorType, 2)
|
||||||
Scalar det = coeffs().coeff(0) * other.coeffs().coeff(1) - coeffs().coeff(1) * other.coeffs().coeff(0);
|
Scalar det = coeffs().coeff(0) * other.coeffs().coeff(1) - coeffs().coeff(1) * other.coeffs().coeff(0);
|
||||||
@@ -213,8 +213,8 @@ public:
|
|||||||
/** Applies the transformation matrix \a mat to \c *this and returns a reference to \c *this.
|
/** Applies the transformation matrix \a mat to \c *this and returns a reference to \c *this.
|
||||||
*
|
*
|
||||||
* \param mat the Dim x Dim transformation matrix
|
* \param mat the Dim x Dim transformation matrix
|
||||||
* \param traits specifies whether the matrix \a mat represents an Isometry
|
* \param traits specifies whether the matrix \a mat represents an #Isometry
|
||||||
* or a more generic Affine transformation. The default is Affine.
|
* or a more generic #Affine transformation. The default is #Affine.
|
||||||
*/
|
*/
|
||||||
template<typename XprType>
|
template<typename XprType>
|
||||||
inline Hyperplane& transform(const MatrixBase<XprType>& mat, TransformTraits traits = Affine)
|
inline Hyperplane& transform(const MatrixBase<XprType>& mat, TransformTraits traits = Affine)
|
||||||
@@ -233,8 +233,8 @@ public:
|
|||||||
/** Applies the transformation \a t to \c *this and returns a reference to \c *this.
|
/** Applies the transformation \a t to \c *this and returns a reference to \c *this.
|
||||||
*
|
*
|
||||||
* \param t the transformation of dimension Dim
|
* \param t the transformation of dimension Dim
|
||||||
* \param traits specifies whether the transformation \a t represents an Isometry
|
* \param traits specifies whether the transformation \a t represents an #Isometry
|
||||||
* or a more generic Affine transformation. The default is Affine.
|
* or a more generic #Affine transformation. The default is #Affine.
|
||||||
* Other kind of transformations are not supported.
|
* Other kind of transformations are not supported.
|
||||||
*/
|
*/
|
||||||
template<int TrOptions>
|
template<int TrOptions>
|
||||||
|
|||||||
@@ -34,7 +34,7 @@
|
|||||||
*
|
*
|
||||||
* A parametrized line is defined by an origin point \f$ \mathbf{o} \f$ and a unit
|
* A parametrized line is defined by an origin point \f$ \mathbf{o} \f$ and a unit
|
||||||
* direction vector \f$ \mathbf{d} \f$ such that the line corresponds to
|
* direction vector \f$ \mathbf{d} \f$ such that the line corresponds to
|
||||||
* the set \f$ l(t) = \mathbf{o} + t \mathbf{d} \f$, \f$ l \in \mathbf{R} \f$.
|
* the set \f$ l(t) = \mathbf{o} + t \mathbf{d} \f$, \f$ t \in \mathbf{R} \f$.
|
||||||
*
|
*
|
||||||
* \param _Scalar the scalar type, i.e., the type of the coefficients
|
* \param _Scalar the scalar type, i.e., the type of the coefficients
|
||||||
* \param _AmbientDim the dimension of the ambient space, can be a compile time value or Dynamic.
|
* \param _AmbientDim the dimension of the ambient space, can be a compile time value or Dynamic.
|
||||||
@@ -107,7 +107,7 @@ public:
|
|||||||
{ return origin() + direction().dot(p-origin()) * direction(); }
|
{ return origin() + direction().dot(p-origin()) * direction(); }
|
||||||
|
|
||||||
template <int OtherOptions>
|
template <int OtherOptions>
|
||||||
Scalar intersection(const Hyperplane<_Scalar, _AmbientDim, OtherOptions>& hyperplane);
|
Scalar intersection(const Hyperplane<_Scalar, _AmbientDim, OtherOptions>& hyperplane) const;
|
||||||
|
|
||||||
/** \returns \c *this with scalar type casted to \a NewScalarType
|
/** \returns \c *this with scalar type casted to \a NewScalarType
|
||||||
*
|
*
|
||||||
@@ -159,7 +159,7 @@ inline ParametrizedLine<_Scalar, _AmbientDim,_Options>::ParametrizedLine(const H
|
|||||||
*/
|
*/
|
||||||
template <typename _Scalar, int _AmbientDim, int _Options>
|
template <typename _Scalar, int _AmbientDim, int _Options>
|
||||||
template <int OtherOptions>
|
template <int OtherOptions>
|
||||||
inline _Scalar ParametrizedLine<_Scalar, _AmbientDim,_Options>::intersection(const Hyperplane<_Scalar, _AmbientDim, OtherOptions>& hyperplane)
|
inline _Scalar ParametrizedLine<_Scalar, _AmbientDim,_Options>::intersection(const Hyperplane<_Scalar, _AmbientDim, OtherOptions>& hyperplane) const
|
||||||
{
|
{
|
||||||
return -(hyperplane.offset()+hyperplane.normal().dot(origin()))
|
return -(hyperplane.offset()+hyperplane.normal().dot(origin()))
|
||||||
/ hyperplane.normal().dot(direction());
|
/ hyperplane.normal().dot(direction());
|
||||||
|
|||||||
@@ -49,6 +49,9 @@ public:
|
|||||||
typedef typename internal::traits<Derived>::Scalar Scalar;
|
typedef typename internal::traits<Derived>::Scalar Scalar;
|
||||||
typedef typename NumTraits<Scalar>::Real RealScalar;
|
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||||
typedef typename internal::traits<Derived>::Coefficients Coefficients;
|
typedef typename internal::traits<Derived>::Coefficients Coefficients;
|
||||||
|
enum {
|
||||||
|
Flags = Eigen::internal::traits<Derived>::Flags
|
||||||
|
};
|
||||||
|
|
||||||
// typedef typename Matrix<Scalar,4,1> Coefficients;
|
// typedef typename Matrix<Scalar,4,1> Coefficients;
|
||||||
/** the type of a 3D vector */
|
/** the type of a 3D vector */
|
||||||
@@ -222,7 +225,8 @@ struct traits<Quaternion<_Scalar,_Options> >
|
|||||||
typedef _Scalar Scalar;
|
typedef _Scalar Scalar;
|
||||||
typedef Matrix<_Scalar,4,1,_Options> Coefficients;
|
typedef Matrix<_Scalar,4,1,_Options> Coefficients;
|
||||||
enum{
|
enum{
|
||||||
PacketAccess = _Options & DontAlign ? Unaligned : Aligned
|
IsAligned = bool(EIGEN_ALIGN) && ((int(_Options)&Aligned)==Aligned),
|
||||||
|
Flags = IsAligned ? (AlignedBit | LvalueBit) : LvalueBit
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -294,33 +298,53 @@ typedef Quaternion<double> Quaterniond;
|
|||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
namespace internal {
|
namespace internal {
|
||||||
template<typename _Scalar, int _PacketAccess>
|
template<typename _Scalar, int _Options>
|
||||||
struct traits<Map<Quaternion<_Scalar>, _PacketAccess> >:
|
struct traits<Map<Quaternion<_Scalar>, _Options> >:
|
||||||
traits<Quaternion<_Scalar> >
|
traits<Quaternion<_Scalar, _Options> >
|
||||||
{
|
{
|
||||||
typedef _Scalar Scalar;
|
typedef _Scalar Scalar;
|
||||||
typedef Map<Matrix<_Scalar,4,1>, _PacketAccess> Coefficients;
|
typedef Map<Matrix<_Scalar,4,1>, _Options> Coefficients;
|
||||||
enum {
|
|
||||||
PacketAccess = _PacketAccess
|
typedef traits<Quaternion<_Scalar, _Options> > TraitsBase;
|
||||||
|
enum {
|
||||||
|
IsAligned = TraitsBase::IsAligned,
|
||||||
|
|
||||||
|
Flags = TraitsBase::Flags
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace internal {
|
||||||
|
template<typename _Scalar, int _Options>
|
||||||
|
struct traits<Map<const Quaternion<_Scalar>, _Options> >:
|
||||||
|
traits<Quaternion<_Scalar> >
|
||||||
|
{
|
||||||
|
typedef _Scalar Scalar;
|
||||||
|
typedef Map<const Matrix<_Scalar,4,1>, _Options> Coefficients;
|
||||||
|
|
||||||
|
typedef traits<Quaternion<_Scalar, _Options> > TraitsBase;
|
||||||
|
enum {
|
||||||
|
IsAligned = TraitsBase::IsAligned,
|
||||||
|
Flags = TraitsBase::Flags & ~LvalueBit
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** \brief Quaternion expression mapping a constant memory buffer
|
/** \brief Quaternion expression mapping a constant memory buffer
|
||||||
*
|
*
|
||||||
* \param _Scalar the type of the Quaternion coefficients
|
* \param _Scalar the type of the Quaternion coefficients
|
||||||
* \param PacketAccess see class Map
|
* \param _Options see class Map
|
||||||
*
|
*
|
||||||
* This is a specialization of class Map for Quaternion. This class allows to view
|
* This is a specialization of class Map for Quaternion. This class allows to view
|
||||||
* a 4 scalar memory buffer as an Eigen's Quaternion object.
|
* a 4 scalar memory buffer as an Eigen's Quaternion object.
|
||||||
*
|
*
|
||||||
* \sa class Map, class Quaternion, class QuaternionBase
|
* \sa class Map, class Quaternion, class QuaternionBase
|
||||||
*/
|
*/
|
||||||
template<typename _Scalar, int PacketAccess>
|
template<typename _Scalar, int _Options>
|
||||||
class Map<const Quaternion<_Scalar>, PacketAccess >
|
class Map<const Quaternion<_Scalar>, _Options >
|
||||||
: public QuaternionBase<Map<const Quaternion<_Scalar>, PacketAccess> >
|
: public QuaternionBase<Map<const Quaternion<_Scalar>, _Options> >
|
||||||
{
|
{
|
||||||
typedef QuaternionBase<Map<Quaternion<_Scalar>, PacketAccess> > Base;
|
typedef QuaternionBase<Map<const Quaternion<_Scalar>, _Options> > Base;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef _Scalar Scalar;
|
typedef _Scalar Scalar;
|
||||||
@@ -333,7 +357,7 @@ class Map<const Quaternion<_Scalar>, PacketAccess >
|
|||||||
* The pointer \a coeffs must reference the four coeffecients of Quaternion in the following order:
|
* The pointer \a coeffs must reference the four coeffecients of Quaternion in the following order:
|
||||||
* \code *coeffs == {x, y, z, w} \endcode
|
* \code *coeffs == {x, y, z, w} \endcode
|
||||||
*
|
*
|
||||||
* If the template parameter PacketAccess is set to Aligned, then the pointer coeffs must be aligned. */
|
* If the template parameter _Options is set to #Aligned, then the pointer coeffs must be aligned. */
|
||||||
EIGEN_STRONG_INLINE Map(const Scalar* coeffs) : m_coeffs(coeffs) {}
|
EIGEN_STRONG_INLINE Map(const Scalar* coeffs) : m_coeffs(coeffs) {}
|
||||||
|
|
||||||
inline const Coefficients& coeffs() const { return m_coeffs;}
|
inline const Coefficients& coeffs() const { return m_coeffs;}
|
||||||
@@ -345,18 +369,18 @@ class Map<const Quaternion<_Scalar>, PacketAccess >
|
|||||||
/** \brief Expression of a quaternion from a memory buffer
|
/** \brief Expression of a quaternion from a memory buffer
|
||||||
*
|
*
|
||||||
* \param _Scalar the type of the Quaternion coefficients
|
* \param _Scalar the type of the Quaternion coefficients
|
||||||
* \param PacketAccess see class Map
|
* \param _Options see class Map
|
||||||
*
|
*
|
||||||
* This is a specialization of class Map for Quaternion. This class allows to view
|
* This is a specialization of class Map for Quaternion. This class allows to view
|
||||||
* a 4 scalar memory buffer as an Eigen's Quaternion object.
|
* a 4 scalar memory buffer as an Eigen's Quaternion object.
|
||||||
*
|
*
|
||||||
* \sa class Map, class Quaternion, class QuaternionBase
|
* \sa class Map, class Quaternion, class QuaternionBase
|
||||||
*/
|
*/
|
||||||
template<typename _Scalar, int PacketAccess>
|
template<typename _Scalar, int _Options>
|
||||||
class Map<Quaternion<_Scalar>, PacketAccess >
|
class Map<Quaternion<_Scalar>, _Options >
|
||||||
: public QuaternionBase<Map<Quaternion<_Scalar>, PacketAccess> >
|
: public QuaternionBase<Map<Quaternion<_Scalar>, _Options> >
|
||||||
{
|
{
|
||||||
typedef QuaternionBase<Map<Quaternion<_Scalar>, PacketAccess> > Base;
|
typedef QuaternionBase<Map<Quaternion<_Scalar>, _Options> > Base;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef _Scalar Scalar;
|
typedef _Scalar Scalar;
|
||||||
@@ -369,7 +393,7 @@ class Map<Quaternion<_Scalar>, PacketAccess >
|
|||||||
* The pointer \a coeffs must reference the four coeffecients of Quaternion in the following order:
|
* The pointer \a coeffs must reference the four coeffecients of Quaternion in the following order:
|
||||||
* \code *coeffs == {x, y, z, w} \endcode
|
* \code *coeffs == {x, y, z, w} \endcode
|
||||||
*
|
*
|
||||||
* If the template parameter PacketAccess is set to Aligned, then the pointer coeffs must be aligned. */
|
* If the template parameter _Options is set to #Aligned, then the pointer coeffs must be aligned. */
|
||||||
EIGEN_STRONG_INLINE Map(Scalar* coeffs) : m_coeffs(coeffs) {}
|
EIGEN_STRONG_INLINE Map(Scalar* coeffs) : m_coeffs(coeffs) {}
|
||||||
|
|
||||||
inline Coefficients& coeffs() { return m_coeffs; }
|
inline Coefficients& coeffs() { return m_coeffs; }
|
||||||
@@ -399,7 +423,7 @@ typedef Map<Quaternion<double>, Aligned> QuaternionMapAlignedd;
|
|||||||
// Generic Quaternion * Quaternion product
|
// Generic Quaternion * Quaternion product
|
||||||
// This product can be specialized for a given architecture via the Arch template argument.
|
// This product can be specialized for a given architecture via the Arch template argument.
|
||||||
namespace internal {
|
namespace internal {
|
||||||
template<int Arch, class Derived1, class Derived2, typename Scalar, int PacketAccess> struct quat_product
|
template<int Arch, class Derived1, class Derived2, typename Scalar, int _Options> struct quat_product
|
||||||
{
|
{
|
||||||
EIGEN_STRONG_INLINE static Quaternion<Scalar> run(const QuaternionBase<Derived1>& a, const QuaternionBase<Derived2>& b){
|
EIGEN_STRONG_INLINE static Quaternion<Scalar> run(const QuaternionBase<Derived1>& a, const QuaternionBase<Derived2>& b){
|
||||||
return Quaternion<Scalar>
|
return Quaternion<Scalar>
|
||||||
@@ -423,7 +447,7 @@ QuaternionBase<Derived>::operator* (const QuaternionBase<OtherDerived>& other) c
|
|||||||
YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
|
YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
|
||||||
return internal::quat_product<Architecture::Target, Derived, OtherDerived,
|
return internal::quat_product<Architecture::Target, Derived, OtherDerived,
|
||||||
typename internal::traits<Derived>::Scalar,
|
typename internal::traits<Derived>::Scalar,
|
||||||
internal::traits<Derived>::PacketAccess && internal::traits<OtherDerived>::PacketAccess>::run(*this, other);
|
internal::traits<Derived>::IsAligned && internal::traits<OtherDerived>::IsAligned>::run(*this, other);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** \sa operator*(Quaternion) */
|
/** \sa operator*(Quaternion) */
|
||||||
@@ -551,6 +575,7 @@ template<class Derived>
|
|||||||
template<typename Derived1, typename Derived2>
|
template<typename Derived1, typename Derived2>
|
||||||
inline Derived& QuaternionBase<Derived>::setFromTwoVectors(const MatrixBase<Derived1>& a, const MatrixBase<Derived2>& b)
|
inline Derived& QuaternionBase<Derived>::setFromTwoVectors(const MatrixBase<Derived1>& a, const MatrixBase<Derived2>& b)
|
||||||
{
|
{
|
||||||
|
using std::max;
|
||||||
Vector3 v0 = a.normalized();
|
Vector3 v0 = a.normalized();
|
||||||
Vector3 v1 = b.normalized();
|
Vector3 v1 = b.normalized();
|
||||||
Scalar c = v1.dot(v0);
|
Scalar c = v1.dot(v0);
|
||||||
@@ -565,7 +590,7 @@ inline Derived& QuaternionBase<Derived>::setFromTwoVectors(const MatrixBase<Deri
|
|||||||
// which yields a singular value problem
|
// which yields a singular value problem
|
||||||
if (c < Scalar(-1)+NumTraits<Scalar>::dummy_precision())
|
if (c < Scalar(-1)+NumTraits<Scalar>::dummy_precision())
|
||||||
{
|
{
|
||||||
c = std::max<Scalar>(c,-1);
|
c = max<Scalar>(c,-1);
|
||||||
Matrix<Scalar,2,3> m; m << v0.transpose(), v1.transpose();
|
Matrix<Scalar,2,3> m; m << v0.transpose(), v1.transpose();
|
||||||
JacobiSVD<Matrix<Scalar,2,3> > svd(m, ComputeFullV);
|
JacobiSVD<Matrix<Scalar,2,3> > svd(m, ComputeFullV);
|
||||||
Vector3 axis = svd.matrixV().col(2);
|
Vector3 axis = svd.matrixV().col(2);
|
||||||
@@ -625,10 +650,11 @@ template <class OtherDerived>
|
|||||||
inline typename internal::traits<Derived>::Scalar
|
inline typename internal::traits<Derived>::Scalar
|
||||||
QuaternionBase<Derived>::angularDistance(const QuaternionBase<OtherDerived>& other) const
|
QuaternionBase<Derived>::angularDistance(const QuaternionBase<OtherDerived>& other) const
|
||||||
{
|
{
|
||||||
|
using std::acos;
|
||||||
double d = internal::abs(this->dot(other));
|
double d = internal::abs(this->dot(other));
|
||||||
if (d>=1.0)
|
if (d>=1.0)
|
||||||
return Scalar(0);
|
return Scalar(0);
|
||||||
return static_cast<Scalar>(2 * std::acos(d));
|
return static_cast<Scalar>(2 * acos(d));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** \returns the spherical linear interpolation between the two quaternions
|
/** \returns the spherical linear interpolation between the two quaternions
|
||||||
@@ -639,6 +665,7 @@ template <class OtherDerived>
|
|||||||
Quaternion<typename internal::traits<Derived>::Scalar>
|
Quaternion<typename internal::traits<Derived>::Scalar>
|
||||||
QuaternionBase<Derived>::slerp(Scalar t, const QuaternionBase<OtherDerived>& other) const
|
QuaternionBase<Derived>::slerp(Scalar t, const QuaternionBase<OtherDerived>& other) const
|
||||||
{
|
{
|
||||||
|
using std::acos;
|
||||||
static const Scalar one = Scalar(1) - NumTraits<Scalar>::epsilon();
|
static const Scalar one = Scalar(1) - NumTraits<Scalar>::epsilon();
|
||||||
Scalar d = this->dot(other);
|
Scalar d = this->dot(other);
|
||||||
Scalar absD = internal::abs(d);
|
Scalar absD = internal::abs(d);
|
||||||
@@ -654,7 +681,7 @@ QuaternionBase<Derived>::slerp(Scalar t, const QuaternionBase<OtherDerived>& oth
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// theta is the angle between the 2 quaternions
|
// theta is the angle between the 2 quaternions
|
||||||
Scalar theta = std::acos(absD);
|
Scalar theta = acos(absD);
|
||||||
Scalar sinTheta = internal::sin(theta);
|
Scalar sinTheta = internal::sin(theta);
|
||||||
|
|
||||||
scale0 = internal::sin( ( Scalar(1) - t ) * theta) / sinTheta;
|
scale0 = internal::sin( ( Scalar(1) - t ) * theta) / sinTheta;
|
||||||
|
|||||||
@@ -86,11 +86,11 @@ template<typename TransformType> struct transform_take_affine_part;
|
|||||||
* \tparam _Scalar the scalar type, i.e., the type of the coefficients
|
* \tparam _Scalar the scalar type, i.e., the type of the coefficients
|
||||||
* \tparam _Dim the dimension of the space
|
* \tparam _Dim the dimension of the space
|
||||||
* \tparam _Mode the type of the transformation. Can be:
|
* \tparam _Mode the type of the transformation. Can be:
|
||||||
* - Affine: the transformation is stored as a (Dim+1)^2 matrix,
|
* - #Affine: the transformation is stored as a (Dim+1)^2 matrix,
|
||||||
* where the last row is assumed to be [0 ... 0 1].
|
* where the last row is assumed to be [0 ... 0 1].
|
||||||
* - AffineCompact: the transformation is stored as a (Dim)x(Dim+1) matrix.
|
* - #AffineCompact: the transformation is stored as a (Dim)x(Dim+1) matrix.
|
||||||
* - Projective: the transformation is stored as a (Dim+1)^2 matrix
|
* - #Projective: the transformation is stored as a (Dim+1)^2 matrix
|
||||||
* without any assumption.
|
* without any assumption.
|
||||||
* \tparam _Options has the same meaning as in class Matrix. It allows to specify DontAlign and/or RowMajor.
|
* \tparam _Options has the same meaning as in class Matrix. It allows to specify DontAlign and/or RowMajor.
|
||||||
* These Options are passed directly to the underlying matrix type.
|
* These Options are passed directly to the underlying matrix type.
|
||||||
*
|
*
|
||||||
@@ -672,7 +672,7 @@ Transform<Scalar,Dim,Mode,Options>::Transform(const QMatrix& other)
|
|||||||
*
|
*
|
||||||
* This function is available only if the token EIGEN_QT_SUPPORT is defined.
|
* This function is available only if the token EIGEN_QT_SUPPORT is defined.
|
||||||
*/
|
*/
|
||||||
template<typename Scalar, int Dim, int Mode,int Otpions>
|
template<typename Scalar, int Dim, int Mode,int Options>
|
||||||
Transform<Scalar,Dim,Mode,Options>& Transform<Scalar,Dim,Mode,Options>::operator=(const QMatrix& other)
|
Transform<Scalar,Dim,Mode,Options>& Transform<Scalar,Dim,Mode,Options>::operator=(const QMatrix& other)
|
||||||
{
|
{
|
||||||
EIGEN_STATIC_ASSERT(Dim==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
|
EIGEN_STATIC_ASSERT(Dim==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
|
||||||
@@ -718,9 +718,13 @@ Transform<Scalar,Dim,Mode,Options>& Transform<Scalar,Dim,Mode,Options>::operator
|
|||||||
{
|
{
|
||||||
check_template_params();
|
check_template_params();
|
||||||
EIGEN_STATIC_ASSERT(Dim==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
|
EIGEN_STATIC_ASSERT(Dim==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
|
||||||
m_matrix << other.m11(), other.m21(), other.dx(),
|
if (Mode == int(AffineCompact))
|
||||||
other.m12(), other.m22(), other.dy(),
|
m_matrix << other.m11(), other.m21(), other.dx(),
|
||||||
other.m13(), other.m23(), other.m33();
|
other.m12(), other.m22(), other.dy();
|
||||||
|
else
|
||||||
|
m_matrix << other.m11(), other.m21(), other.dx(),
|
||||||
|
other.m12(), other.m22(), other.dy(),
|
||||||
|
other.m13(), other.m23(), other.m33();
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -732,9 +736,14 @@ template<typename Scalar, int Dim, int Mode, int Options>
|
|||||||
QTransform Transform<Scalar,Dim,Mode,Options>::toQTransform(void) const
|
QTransform Transform<Scalar,Dim,Mode,Options>::toQTransform(void) const
|
||||||
{
|
{
|
||||||
EIGEN_STATIC_ASSERT(Dim==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
|
EIGEN_STATIC_ASSERT(Dim==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
|
||||||
return QTransform(matrix.coeff(0,0), matrix.coeff(1,0), matrix.coeff(2,0)
|
if (Mode == int(AffineCompact))
|
||||||
matrix.coeff(0,1), matrix.coeff(1,1), matrix.coeff(2,1)
|
return QTransform(m_matrix.coeff(0,0), m_matrix.coeff(1,0),
|
||||||
matrix.coeff(0,2), matrix.coeff(1,2), matrix.coeff(2,2));
|
m_matrix.coeff(0,1), m_matrix.coeff(1,1),
|
||||||
|
m_matrix.coeff(0,2), m_matrix.coeff(1,2));
|
||||||
|
else
|
||||||
|
return QTransform(m_matrix.coeff(0,0), m_matrix.coeff(1,0), m_matrix.coeff(2,0),
|
||||||
|
m_matrix.coeff(0,1), m_matrix.coeff(1,1), m_matrix.coeff(2,1),
|
||||||
|
m_matrix.coeff(0,2), m_matrix.coeff(1,2), m_matrix.coeff(2,2));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -1082,10 +1091,10 @@ struct projective_transform_inverse<TransformType, Projective>
|
|||||||
*
|
*
|
||||||
* \param hint allows to optimize the inversion process when the transformation
|
* \param hint allows to optimize the inversion process when the transformation
|
||||||
* is known to be not a general transformation (optional). The possible values are:
|
* is known to be not a general transformation (optional). The possible values are:
|
||||||
* - Projective if the transformation is not necessarily affine, i.e., if the
|
* - #Projective if the transformation is not necessarily affine, i.e., if the
|
||||||
* last row is not guaranteed to be [0 ... 0 1]
|
* last row is not guaranteed to be [0 ... 0 1]
|
||||||
* - Affine if the last row can be assumed to be [0 ... 0 1]
|
* - #Affine if the last row can be assumed to be [0 ... 0 1]
|
||||||
* - Isometry if the transformation is only a concatenations of translations
|
* - #Isometry if the transformation is only a concatenations of translations
|
||||||
* and rotations.
|
* and rotations.
|
||||||
* The default is the template class parameter \c Mode.
|
* The default is the template class parameter \c Mode.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -72,8 +72,9 @@ void MatrixBase<Derived>::makeHouseholder(
|
|||||||
|
|
||||||
if(tailSqNorm == RealScalar(0) && internal::imag(c0)==RealScalar(0))
|
if(tailSqNorm == RealScalar(0) && internal::imag(c0)==RealScalar(0))
|
||||||
{
|
{
|
||||||
tau = 0;
|
tau = RealScalar(0);
|
||||||
beta = internal::real(c0);
|
beta = internal::real(c0);
|
||||||
|
essential.setZero();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -104,9 +104,9 @@ bool JacobiRotation<Scalar>::makeJacobi(RealScalar x, Scalar y, RealScalar z)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
RealScalar tau = (x-z)/(RealScalar(2)*internal::abs(y));
|
RealScalar tau = (x-z)/(RealScalar(2)*internal::abs(y));
|
||||||
RealScalar w = internal::sqrt(internal::abs2(tau) + 1);
|
RealScalar w = internal::sqrt(internal::abs2(tau) + RealScalar(1));
|
||||||
RealScalar t;
|
RealScalar t;
|
||||||
if(tau>0)
|
if(tau>RealScalar(0))
|
||||||
{
|
{
|
||||||
t = RealScalar(1) / (tau + w);
|
t = RealScalar(1) / (tau + w);
|
||||||
}
|
}
|
||||||
@@ -114,8 +114,8 @@ bool JacobiRotation<Scalar>::makeJacobi(RealScalar x, Scalar y, RealScalar z)
|
|||||||
{
|
{
|
||||||
t = RealScalar(1) / (tau - w);
|
t = RealScalar(1) / (tau - w);
|
||||||
}
|
}
|
||||||
RealScalar sign_t = t > 0 ? 1 : -1;
|
RealScalar sign_t = t > RealScalar(0) ? RealScalar(1) : RealScalar(-1);
|
||||||
RealScalar n = RealScalar(1) / internal::sqrt(internal::abs2(t)+1);
|
RealScalar n = RealScalar(1) / internal::sqrt(internal::abs2(t)+RealScalar(1));
|
||||||
m_s = - sign_t * (internal::conj(y) / internal::abs(y)) * internal::abs(t) * n;
|
m_s = - sign_t * (internal::conj(y) / internal::abs(y)) * internal::abs(t) * n;
|
||||||
m_c = n;
|
m_c = n;
|
||||||
return true;
|
return true;
|
||||||
@@ -221,15 +221,15 @@ template<typename Scalar>
|
|||||||
void JacobiRotation<Scalar>::makeGivens(const Scalar& p, const Scalar& q, Scalar* r, internal::false_type)
|
void JacobiRotation<Scalar>::makeGivens(const Scalar& p, const Scalar& q, Scalar* r, internal::false_type)
|
||||||
{
|
{
|
||||||
|
|
||||||
if(q==0)
|
if(q==Scalar(0))
|
||||||
{
|
{
|
||||||
m_c = p<Scalar(0) ? Scalar(-1) : Scalar(1);
|
m_c = p<Scalar(0) ? Scalar(-1) : Scalar(1);
|
||||||
m_s = 0;
|
m_s = Scalar(0);
|
||||||
if(r) *r = internal::abs(p);
|
if(r) *r = internal::abs(p);
|
||||||
}
|
}
|
||||||
else if(p==0)
|
else if(p==Scalar(0))
|
||||||
{
|
{
|
||||||
m_c = 0;
|
m_c = Scalar(0);
|
||||||
m_s = q<Scalar(0) ? Scalar(1) : Scalar(-1);
|
m_s = q<Scalar(0) ? Scalar(1) : Scalar(-1);
|
||||||
if(r) *r = internal::abs(q);
|
if(r) *r = internal::abs(q);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -533,7 +533,7 @@ template<typename MatrixType>
|
|||||||
MatrixType FullPivLU<MatrixType>::reconstructedMatrix() const
|
MatrixType FullPivLU<MatrixType>::reconstructedMatrix() const
|
||||||
{
|
{
|
||||||
eigen_assert(m_isInitialized && "LU is not initialized.");
|
eigen_assert(m_isInitialized && "LU is not initialized.");
|
||||||
const Index smalldim = std::min(m_lu.rows(), m_lu.cols());
|
const Index smalldim = (std::min)(m_lu.rows(), m_lu.cols());
|
||||||
// LU
|
// LU
|
||||||
MatrixType res(m_lu.rows(),m_lu.cols());
|
MatrixType res(m_lu.rows(),m_lu.cols());
|
||||||
// FIXME the .toDenseMatrix() should not be needed...
|
// FIXME the .toDenseMatrix() should not be needed...
|
||||||
@@ -695,7 +695,7 @@ struct solve_retval<FullPivLU<_MatrixType>, Rhs>
|
|||||||
const Index rows = dec().rows(), cols = dec().cols(),
|
const Index rows = dec().rows(), cols = dec().cols(),
|
||||||
nonzero_pivots = dec().nonzeroPivots();
|
nonzero_pivots = dec().nonzeroPivots();
|
||||||
eigen_assert(rhs().rows() == rows);
|
eigen_assert(rhs().rows() == rows);
|
||||||
const Index smalldim = std::min(rows, cols);
|
const Index smalldim = (std::min)(rows, cols);
|
||||||
|
|
||||||
if(nonzero_pivots == 0)
|
if(nonzero_pivots == 0)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -253,7 +253,7 @@ struct partial_lu_impl
|
|||||||
{
|
{
|
||||||
const Index rows = lu.rows();
|
const Index rows = lu.rows();
|
||||||
const Index cols = lu.cols();
|
const Index cols = lu.cols();
|
||||||
const Index size = std::min(rows,cols);
|
const Index size = (std::min)(rows,cols);
|
||||||
nb_transpositions = 0;
|
nb_transpositions = 0;
|
||||||
int first_zero_pivot = -1;
|
int first_zero_pivot = -1;
|
||||||
for(Index k = 0; k < size; ++k)
|
for(Index k = 0; k < size; ++k)
|
||||||
@@ -268,7 +268,7 @@ struct partial_lu_impl
|
|||||||
|
|
||||||
row_transpositions[k] = row_of_biggest_in_col;
|
row_transpositions[k] = row_of_biggest_in_col;
|
||||||
|
|
||||||
if(biggest_in_corner != 0)
|
if(biggest_in_corner != RealScalar(0))
|
||||||
{
|
{
|
||||||
if(k != row_of_biggest_in_col)
|
if(k != row_of_biggest_in_col)
|
||||||
{
|
{
|
||||||
@@ -313,7 +313,7 @@ struct partial_lu_impl
|
|||||||
MapLU lu1(lu_data,StorageOrder==RowMajor?rows:luStride,StorageOrder==RowMajor?luStride:cols);
|
MapLU lu1(lu_data,StorageOrder==RowMajor?rows:luStride,StorageOrder==RowMajor?luStride:cols);
|
||||||
MatrixType lu(lu1,0,0,rows,cols);
|
MatrixType lu(lu1,0,0,rows,cols);
|
||||||
|
|
||||||
const Index size = std::min(rows,cols);
|
const Index size = (std::min)(rows,cols);
|
||||||
|
|
||||||
// if the matrix is too small, no blocking:
|
// if the matrix is too small, no blocking:
|
||||||
if(size<=16)
|
if(size<=16)
|
||||||
@@ -327,14 +327,14 @@ struct partial_lu_impl
|
|||||||
{
|
{
|
||||||
blockSize = size/8;
|
blockSize = size/8;
|
||||||
blockSize = (blockSize/16)*16;
|
blockSize = (blockSize/16)*16;
|
||||||
blockSize = std::min(std::max(blockSize,Index(8)), maxBlockSize);
|
blockSize = (std::min)((std::max)(blockSize,Index(8)), maxBlockSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
nb_transpositions = 0;
|
nb_transpositions = 0;
|
||||||
int first_zero_pivot = -1;
|
int first_zero_pivot = -1;
|
||||||
for(Index k = 0; k < size; k+=blockSize)
|
for(Index k = 0; k < size; k+=blockSize)
|
||||||
{
|
{
|
||||||
Index bs = std::min(size-k,blockSize); // actual size of the block
|
Index bs = (std::min)(size-k,blockSize); // actual size of the block
|
||||||
Index trows = rows - k - bs; // trailing rows
|
Index trows = rows - k - bs; // trailing rows
|
||||||
Index tsize = size - k - bs; // trailing size
|
Index tsize = size - k - bs; // trailing size
|
||||||
|
|
||||||
|
|||||||
@@ -182,8 +182,8 @@ struct compute_inverse_size4<Architecture::SSE, double, MatrixType, ResultType>
|
|||||||
};
|
};
|
||||||
static void run(const MatrixType& matrix, ResultType& result)
|
static void run(const MatrixType& matrix, ResultType& result)
|
||||||
{
|
{
|
||||||
const EIGEN_ALIGN16 long long int _Sign_NP[2] = { 0x8000000000000000ll, 0x0000000000000000ll };
|
const __m128d _Sign_NP = _mm_castsi128_pd(_mm_set_epi32(0x0,0x0,0x80000000,0x0));
|
||||||
const EIGEN_ALIGN16 long long int _Sign_PN[2] = { 0x0000000000000000ll, 0x8000000000000000ll };
|
const __m128d _Sign_PN = _mm_castsi128_pd(_mm_set_epi32(0x80000000,0x0,0x0,0x0));
|
||||||
|
|
||||||
// The inverse is calculated using "Divide and Conquer" technique. The
|
// The inverse is calculated using "Divide and Conquer" technique. The
|
||||||
// original matrix is divide into four 2x2 sub-matrices. Since each
|
// original matrix is divide into four 2x2 sub-matrices. Since each
|
||||||
@@ -316,8 +316,8 @@ struct compute_inverse_size4<Architecture::SSE, double, MatrixType, ResultType>
|
|||||||
iB1 = _mm_sub_pd(_mm_mul_pd(C1, dB), iB1);
|
iB1 = _mm_sub_pd(_mm_mul_pd(C1, dB), iB1);
|
||||||
iB2 = _mm_sub_pd(_mm_mul_pd(C2, dB), iB2);
|
iB2 = _mm_sub_pd(_mm_mul_pd(C2, dB), iB2);
|
||||||
|
|
||||||
d1 = _mm_xor_pd(rd, _mm_load_pd((double*)_Sign_PN));
|
d1 = _mm_xor_pd(rd, _Sign_PN);
|
||||||
d2 = _mm_xor_pd(rd, _mm_load_pd((double*)_Sign_NP));
|
d2 = _mm_xor_pd(rd, _Sign_NP);
|
||||||
|
|
||||||
// iC = B*|C| - A*C#*D;
|
// iC = B*|C| - A*C#*D;
|
||||||
dC = _mm_shuffle_pd(dC,dC,0);
|
dC = _mm_shuffle_pd(dC,dC,0);
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ template<typename _MatrixType> class ColPivHouseholderQR
|
|||||||
*/
|
*/
|
||||||
ColPivHouseholderQR(Index rows, Index cols)
|
ColPivHouseholderQR(Index rows, Index cols)
|
||||||
: m_qr(rows, cols),
|
: m_qr(rows, cols),
|
||||||
m_hCoeffs(std::min(rows,cols)),
|
m_hCoeffs((std::min)(rows,cols)),
|
||||||
m_colsPermutation(cols),
|
m_colsPermutation(cols),
|
||||||
m_colsTranspositions(cols),
|
m_colsTranspositions(cols),
|
||||||
m_temp(cols),
|
m_temp(cols),
|
||||||
@@ -103,7 +103,7 @@ template<typename _MatrixType> class ColPivHouseholderQR
|
|||||||
|
|
||||||
ColPivHouseholderQR(const MatrixType& matrix)
|
ColPivHouseholderQR(const MatrixType& matrix)
|
||||||
: m_qr(matrix.rows(), matrix.cols()),
|
: m_qr(matrix.rows(), matrix.cols()),
|
||||||
m_hCoeffs(std::min(matrix.rows(),matrix.cols())),
|
m_hCoeffs((std::min)(matrix.rows(),matrix.cols())),
|
||||||
m_colsPermutation(matrix.cols()),
|
m_colsPermutation(matrix.cols()),
|
||||||
m_colsTranspositions(matrix.cols()),
|
m_colsTranspositions(matrix.cols()),
|
||||||
m_temp(matrix.cols()),
|
m_temp(matrix.cols()),
|
||||||
@@ -330,12 +330,12 @@ template<typename _MatrixType> class ColPivHouseholderQR
|
|||||||
*/
|
*/
|
||||||
inline Index nonzeroPivots() const
|
inline Index nonzeroPivots() const
|
||||||
{
|
{
|
||||||
eigen_assert(m_isInitialized && "LU is not initialized.");
|
eigen_assert(m_isInitialized && "ColPivHouseholderQR is not initialized.");
|
||||||
return m_nonzero_pivots;
|
return m_nonzero_pivots;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** \returns the absolute value of the biggest pivot, i.e. the biggest
|
/** \returns the absolute value of the biggest pivot, i.e. the biggest
|
||||||
* diagonal coefficient of U.
|
* diagonal coefficient of R.
|
||||||
*/
|
*/
|
||||||
RealScalar maxPivot() const { return m_maxpivot; }
|
RealScalar maxPivot() const { return m_maxpivot; }
|
||||||
|
|
||||||
@@ -387,7 +387,7 @@ ColPivHouseholderQR<MatrixType>& ColPivHouseholderQR<MatrixType>::compute(const
|
|||||||
for(Index k = 0; k < cols; ++k)
|
for(Index k = 0; k < cols; ++k)
|
||||||
m_colSqNorms.coeffRef(k) = m_qr.col(k).squaredNorm();
|
m_colSqNorms.coeffRef(k) = m_qr.col(k).squaredNorm();
|
||||||
|
|
||||||
RealScalar threshold_helper = m_colSqNorms.maxCoeff() * internal::abs2(NumTraits<Scalar>::epsilon()) / rows;
|
RealScalar threshold_helper = m_colSqNorms.maxCoeff() * internal::abs2(NumTraits<Scalar>::epsilon()) / RealScalar(rows);
|
||||||
|
|
||||||
m_nonzero_pivots = size; // the generic case is that in which all pivots are nonzero (invertible case)
|
m_nonzero_pivots = size; // the generic case is that in which all pivots are nonzero (invertible case)
|
||||||
m_maxpivot = RealScalar(0);
|
m_maxpivot = RealScalar(0);
|
||||||
@@ -413,7 +413,7 @@ ColPivHouseholderQR<MatrixType>& ColPivHouseholderQR<MatrixType>::compute(const
|
|||||||
// Note that here, if we test instead for "biggest == 0", we get a failure every 1000 (or so)
|
// Note that here, if we test instead for "biggest == 0", we get a failure every 1000 (or so)
|
||||||
// repetitions of the unit test, with the result of solve() filled with large values of the order
|
// repetitions of the unit test, with the result of solve() filled with large values of the order
|
||||||
// of 1/(size*epsilon).
|
// of 1/(size*epsilon).
|
||||||
if(biggest_col_sq_norm < threshold_helper * (rows-k))
|
if(biggest_col_sq_norm < threshold_helper * RealScalar(rows-k))
|
||||||
{
|
{
|
||||||
m_nonzero_pivots = k;
|
m_nonzero_pivots = k;
|
||||||
m_hCoeffs.tail(size-k).setZero();
|
m_hCoeffs.tail(size-k).setZero();
|
||||||
|
|||||||
@@ -93,21 +93,21 @@ template<typename _MatrixType> class FullPivHouseholderQR
|
|||||||
*/
|
*/
|
||||||
FullPivHouseholderQR(Index rows, Index cols)
|
FullPivHouseholderQR(Index rows, Index cols)
|
||||||
: m_qr(rows, cols),
|
: m_qr(rows, cols),
|
||||||
m_hCoeffs(std::min(rows,cols)),
|
m_hCoeffs((std::min)(rows,cols)),
|
||||||
m_rows_transpositions(rows),
|
m_rows_transpositions(rows),
|
||||||
m_cols_transpositions(cols),
|
m_cols_transpositions(cols),
|
||||||
m_cols_permutation(cols),
|
m_cols_permutation(cols),
|
||||||
m_temp(std::min(rows,cols)),
|
m_temp((std::min)(rows,cols)),
|
||||||
m_isInitialized(false),
|
m_isInitialized(false),
|
||||||
m_usePrescribedThreshold(false) {}
|
m_usePrescribedThreshold(false) {}
|
||||||
|
|
||||||
FullPivHouseholderQR(const MatrixType& matrix)
|
FullPivHouseholderQR(const MatrixType& matrix)
|
||||||
: m_qr(matrix.rows(), matrix.cols()),
|
: m_qr(matrix.rows(), matrix.cols()),
|
||||||
m_hCoeffs(std::min(matrix.rows(), matrix.cols())),
|
m_hCoeffs((std::min)(matrix.rows(), matrix.cols())),
|
||||||
m_rows_transpositions(matrix.rows()),
|
m_rows_transpositions(matrix.rows()),
|
||||||
m_cols_transpositions(matrix.cols()),
|
m_cols_transpositions(matrix.cols()),
|
||||||
m_cols_permutation(matrix.cols()),
|
m_cols_permutation(matrix.cols()),
|
||||||
m_temp(std::min(matrix.rows(), matrix.cols())),
|
m_temp((std::min)(matrix.rows(), matrix.cols())),
|
||||||
m_isInitialized(false),
|
m_isInitialized(false),
|
||||||
m_usePrescribedThreshold(false)
|
m_usePrescribedThreshold(false)
|
||||||
{
|
{
|
||||||
@@ -379,7 +379,7 @@ FullPivHouseholderQR<MatrixType>& FullPivHouseholderQR<MatrixType>::compute(cons
|
|||||||
{
|
{
|
||||||
Index rows = matrix.rows();
|
Index rows = matrix.rows();
|
||||||
Index cols = matrix.cols();
|
Index cols = matrix.cols();
|
||||||
Index size = std::min(rows,cols);
|
Index size = (std::min)(rows,cols);
|
||||||
|
|
||||||
m_qr = matrix;
|
m_qr = matrix;
|
||||||
m_hCoeffs.resize(size);
|
m_hCoeffs.resize(size);
|
||||||
@@ -493,7 +493,7 @@ struct solve_retval<FullPivHouseholderQR<_MatrixType>, Rhs>
|
|||||||
RealScalar biggest_in_upper_part_of_c = c.topRows( dec().rank() ).cwiseAbs().maxCoeff();
|
RealScalar biggest_in_upper_part_of_c = c.topRows( dec().rank() ).cwiseAbs().maxCoeff();
|
||||||
RealScalar biggest_in_lower_part_of_c = c.bottomRows(rows-dec().rank()).cwiseAbs().maxCoeff();
|
RealScalar biggest_in_lower_part_of_c = c.bottomRows(rows-dec().rank()).cwiseAbs().maxCoeff();
|
||||||
// FIXME brain dead
|
// FIXME brain dead
|
||||||
const RealScalar m_precision = NumTraits<Scalar>::epsilon() * std::min(rows,cols);
|
const RealScalar m_precision = NumTraits<Scalar>::epsilon() * (std::min)(rows,cols);
|
||||||
// this internal:: prefix is needed by at least gcc 3.4 and ICC
|
// this internal:: prefix is needed by at least gcc 3.4 and ICC
|
||||||
if(!internal::isMuchSmallerThan(biggest_in_lower_part_of_c, biggest_in_upper_part_of_c, m_precision))
|
if(!internal::isMuchSmallerThan(biggest_in_lower_part_of_c, biggest_in_upper_part_of_c, m_precision))
|
||||||
return;
|
return;
|
||||||
@@ -520,7 +520,7 @@ typename FullPivHouseholderQR<MatrixType>::MatrixQType FullPivHouseholderQR<Matr
|
|||||||
// and v_k is the k-th Householder vector [1,m_qr(k+1,k), m_qr(k+2,k), ...]
|
// and v_k is the k-th Householder vector [1,m_qr(k+1,k), m_qr(k+2,k), ...]
|
||||||
Index rows = m_qr.rows();
|
Index rows = m_qr.rows();
|
||||||
Index cols = m_qr.cols();
|
Index cols = m_qr.cols();
|
||||||
Index size = std::min(rows,cols);
|
Index size = (std::min)(rows,cols);
|
||||||
MatrixQType res = MatrixQType::Identity(rows, rows);
|
MatrixQType res = MatrixQType::Identity(rows, rows);
|
||||||
Matrix<Scalar,1,MatrixType::RowsAtCompileTime> temp(rows);
|
Matrix<Scalar,1,MatrixType::RowsAtCompileTime> temp(rows);
|
||||||
for (Index k = size-1; k >= 0; k--)
|
for (Index k = size-1; k >= 0; k--)
|
||||||
|
|||||||
@@ -88,13 +88,13 @@ template<typename _MatrixType> class HouseholderQR
|
|||||||
*/
|
*/
|
||||||
HouseholderQR(Index rows, Index cols)
|
HouseholderQR(Index rows, Index cols)
|
||||||
: m_qr(rows, cols),
|
: m_qr(rows, cols),
|
||||||
m_hCoeffs(std::min(rows,cols)),
|
m_hCoeffs((std::min)(rows,cols)),
|
||||||
m_temp(cols),
|
m_temp(cols),
|
||||||
m_isInitialized(false) {}
|
m_isInitialized(false) {}
|
||||||
|
|
||||||
HouseholderQR(const MatrixType& matrix)
|
HouseholderQR(const MatrixType& matrix)
|
||||||
: m_qr(matrix.rows(), matrix.cols()),
|
: m_qr(matrix.rows(), matrix.cols()),
|
||||||
m_hCoeffs(std::min(matrix.rows(),matrix.cols())),
|
m_hCoeffs((std::min)(matrix.rows(),matrix.cols())),
|
||||||
m_temp(matrix.cols()),
|
m_temp(matrix.cols()),
|
||||||
m_isInitialized(false)
|
m_isInitialized(false)
|
||||||
{
|
{
|
||||||
@@ -210,7 +210,7 @@ void householder_qr_inplace_unblocked(MatrixQR& mat, HCoeffs& hCoeffs, typename
|
|||||||
typedef typename MatrixQR::RealScalar RealScalar;
|
typedef typename MatrixQR::RealScalar RealScalar;
|
||||||
Index rows = mat.rows();
|
Index rows = mat.rows();
|
||||||
Index cols = mat.cols();
|
Index cols = mat.cols();
|
||||||
Index size = std::min(rows,cols);
|
Index size = (std::min)(rows,cols);
|
||||||
|
|
||||||
eigen_assert(hCoeffs.size() == size);
|
eigen_assert(hCoeffs.size() == size);
|
||||||
|
|
||||||
@@ -250,7 +250,7 @@ void householder_qr_inplace_blocked(MatrixQR& mat, HCoeffs& hCoeffs,
|
|||||||
|
|
||||||
Index rows = mat.rows();
|
Index rows = mat.rows();
|
||||||
Index cols = mat.cols();
|
Index cols = mat.cols();
|
||||||
Index size = std::min(rows, cols);
|
Index size = (std::min)(rows, cols);
|
||||||
|
|
||||||
typedef Matrix<Scalar,Dynamic,1,ColMajor,MatrixQR::MaxColsAtCompileTime,1> TempType;
|
typedef Matrix<Scalar,Dynamic,1,ColMajor,MatrixQR::MaxColsAtCompileTime,1> TempType;
|
||||||
TempType tempVector;
|
TempType tempVector;
|
||||||
@@ -260,12 +260,12 @@ void householder_qr_inplace_blocked(MatrixQR& mat, HCoeffs& hCoeffs,
|
|||||||
tempData = tempVector.data();
|
tempData = tempVector.data();
|
||||||
}
|
}
|
||||||
|
|
||||||
Index blockSize = std::min(maxBlockSize,size);
|
Index blockSize = (std::min)(maxBlockSize,size);
|
||||||
|
|
||||||
int k = 0;
|
Index k = 0;
|
||||||
for (k = 0; k < size; k += blockSize)
|
for (k = 0; k < size; k += blockSize)
|
||||||
{
|
{
|
||||||
Index bs = std::min(size-k,blockSize); // actual size of the block
|
Index bs = (std::min)(size-k,blockSize); // actual size of the block
|
||||||
Index tcols = cols - k - bs; // trailing columns
|
Index tcols = cols - k - bs; // trailing columns
|
||||||
Index brows = rows-k; // rows of the block
|
Index brows = rows-k; // rows of the block
|
||||||
|
|
||||||
@@ -299,7 +299,7 @@ struct solve_retval<HouseholderQR<_MatrixType>, Rhs>
|
|||||||
template<typename Dest> void evalTo(Dest& dst) const
|
template<typename Dest> void evalTo(Dest& dst) const
|
||||||
{
|
{
|
||||||
const Index rows = dec().rows(), cols = dec().cols();
|
const Index rows = dec().rows(), cols = dec().cols();
|
||||||
const Index rank = std::min(rows, cols);
|
const Index rank = (std::min)(rows, cols);
|
||||||
eigen_assert(rhs().rows() == rows);
|
eigen_assert(rhs().rows() == rows);
|
||||||
|
|
||||||
typename Rhs::PlainObject c(rhs());
|
typename Rhs::PlainObject c(rhs());
|
||||||
@@ -327,7 +327,7 @@ HouseholderQR<MatrixType>& HouseholderQR<MatrixType>::compute(const MatrixType&
|
|||||||
{
|
{
|
||||||
Index rows = matrix.rows();
|
Index rows = matrix.rows();
|
||||||
Index cols = matrix.cols();
|
Index cols = matrix.cols();
|
||||||
Index size = std::min(rows,cols);
|
Index size = (std::min)(rows,cols);
|
||||||
|
|
||||||
m_qr = matrix;
|
m_qr = matrix;
|
||||||
m_hCoeffs.resize(size);
|
m_hCoeffs.resize(size);
|
||||||
|
|||||||
@@ -271,13 +271,13 @@ void real_2x2_jacobi_svd(const MatrixType& matrix, Index p, Index q,
|
|||||||
RealScalar d = m.coeff(1,0) - m.coeff(0,1);
|
RealScalar d = m.coeff(1,0) - m.coeff(0,1);
|
||||||
if(t == RealScalar(0))
|
if(t == RealScalar(0))
|
||||||
{
|
{
|
||||||
rot1.c() = 0;
|
rot1.c() = RealScalar(0);
|
||||||
rot1.s() = d > 0 ? 1 : -1;
|
rot1.s() = d > RealScalar(0) ? RealScalar(1) : RealScalar(-1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
RealScalar u = d / t;
|
RealScalar u = d / t;
|
||||||
rot1.c() = RealScalar(1) / sqrt(1 + abs2(u));
|
rot1.c() = RealScalar(1) / sqrt(RealScalar(1) + abs2(u));
|
||||||
rot1.s() = rot1.c() * u;
|
rot1.s() = rot1.c() * u;
|
||||||
}
|
}
|
||||||
m.applyOnTheLeft(0,1,rot1);
|
m.applyOnTheLeft(0,1,rot1);
|
||||||
@@ -292,7 +292,7 @@ void real_2x2_jacobi_svd(const MatrixType& matrix, Index p, Index q,
|
|||||||
*
|
*
|
||||||
* \class JacobiSVD
|
* \class JacobiSVD
|
||||||
*
|
*
|
||||||
* \brief Two-sided Jacobi SVD decomposition of a square matrix
|
* \brief Two-sided Jacobi SVD decomposition of a rectangular matrix
|
||||||
*
|
*
|
||||||
* \param MatrixType the type of the matrix of which we are computing the SVD decomposition
|
* \param MatrixType the type of the matrix of which we are computing the SVD decomposition
|
||||||
* \param QRPreconditioner this optional parameter allows to specify the type of QR decomposition that will be used internally
|
* \param QRPreconditioner this optional parameter allows to specify the type of QR decomposition that will be used internally
|
||||||
@@ -403,8 +403,8 @@ template<typename _MatrixType, int QRPreconditioner> class JacobiSVD
|
|||||||
*
|
*
|
||||||
* \param matrix the matrix to decompose
|
* \param matrix the matrix to decompose
|
||||||
* \param computationOptions optional parameter allowing to specify if you want full or thin U or V unitaries to be computed.
|
* \param computationOptions optional parameter allowing to specify if you want full or thin U or V unitaries to be computed.
|
||||||
* By default, none is computed. This is a bit-field, the possible bits are ComputeFullU, ComputeThinU,
|
* By default, none is computed. This is a bit-field, the possible bits are #ComputeFullU, #ComputeThinU,
|
||||||
* ComputeFullV, ComputeThinV.
|
* #ComputeFullV, #ComputeThinV.
|
||||||
*
|
*
|
||||||
* Thin unitaries are only available if your matrix type has a Dynamic number of columns (for example MatrixXf). They also are not
|
* Thin unitaries are only available if your matrix type has a Dynamic number of columns (for example MatrixXf). They also are not
|
||||||
* available with the (non-default) FullPivHouseholderQR preconditioner.
|
* available with the (non-default) FullPivHouseholderQR preconditioner.
|
||||||
@@ -422,8 +422,8 @@ template<typename _MatrixType, int QRPreconditioner> class JacobiSVD
|
|||||||
*
|
*
|
||||||
* \param matrix the matrix to decompose
|
* \param matrix the matrix to decompose
|
||||||
* \param computationOptions optional parameter allowing to specify if you want full or thin U or V unitaries to be computed.
|
* \param computationOptions optional parameter allowing to specify if you want full or thin U or V unitaries to be computed.
|
||||||
* By default, none is computed. This is a bit-field, the possible bits are ComputeFullU, ComputeThinU,
|
* By default, none is computed. This is a bit-field, the possible bits are #ComputeFullU, #ComputeThinU,
|
||||||
* ComputeFullV, ComputeThinV.
|
* #ComputeFullV, #ComputeThinV.
|
||||||
*
|
*
|
||||||
* Thin unitaries are only available if your matrix type has a Dynamic number of columns (for example MatrixXf). They also are not
|
* Thin unitaries are only available if your matrix type has a Dynamic number of columns (for example MatrixXf). They also are not
|
||||||
* available with the (non-default) FullPivHouseholderQR preconditioner.
|
* available with the (non-default) FullPivHouseholderQR preconditioner.
|
||||||
@@ -444,7 +444,7 @@ template<typename _MatrixType, int QRPreconditioner> class JacobiSVD
|
|||||||
/** \returns the \a U matrix.
|
/** \returns the \a U matrix.
|
||||||
*
|
*
|
||||||
* For the SVD decomposition of a n-by-p matrix, letting \a m be the minimum of \a n and \a p,
|
* For the SVD decomposition of a n-by-p matrix, letting \a m be the minimum of \a n and \a p,
|
||||||
* the U matrix is n-by-n if you asked for ComputeFullU, and is n-by-m if you asked for ComputeThinU.
|
* the U matrix is n-by-n if you asked for #ComputeFullU, and is n-by-m if you asked for #ComputeThinU.
|
||||||
*
|
*
|
||||||
* The \a m first columns of \a U are the left singular vectors of the matrix being decomposed.
|
* The \a m first columns of \a U are the left singular vectors of the matrix being decomposed.
|
||||||
*
|
*
|
||||||
@@ -460,7 +460,7 @@ template<typename _MatrixType, int QRPreconditioner> class JacobiSVD
|
|||||||
/** \returns the \a V matrix.
|
/** \returns the \a V matrix.
|
||||||
*
|
*
|
||||||
* For the SVD decomposition of a n-by-p matrix, letting \a m be the minimum of \a n and \a p,
|
* For the SVD decomposition of a n-by-p matrix, letting \a m be the minimum of \a n and \a p,
|
||||||
* the V matrix is p-by-p if you asked for ComputeFullV, and is p-by-m if you asked for ComputeThinV.
|
* the V matrix is p-by-p if you asked for #ComputeFullV, and is p-by-m if you asked for ComputeThinV.
|
||||||
*
|
*
|
||||||
* The \a m first columns of \a V are the right singular vectors of the matrix being decomposed.
|
* The \a m first columns of \a V are the right singular vectors of the matrix being decomposed.
|
||||||
*
|
*
|
||||||
@@ -569,7 +569,7 @@ void JacobiSVD<MatrixType, QRPreconditioner>::allocate(Index rows, Index cols, u
|
|||||||
"JacobiSVD: can't compute thin U or thin V with the FullPivHouseholderQR preconditioner. "
|
"JacobiSVD: can't compute thin U or thin V with the FullPivHouseholderQR preconditioner. "
|
||||||
"Use the ColPivHouseholderQR preconditioner instead.");
|
"Use the ColPivHouseholderQR preconditioner instead.");
|
||||||
}
|
}
|
||||||
m_diagSize = std::min(m_rows, m_cols);
|
m_diagSize = (std::min)(m_rows, m_cols);
|
||||||
m_singularValues.resize(m_diagSize);
|
m_singularValues.resize(m_diagSize);
|
||||||
m_matrixU.resize(m_rows, m_computeFullU ? m_rows
|
m_matrixU.resize(m_rows, m_computeFullU ? m_rows
|
||||||
: m_computeThinU ? m_diagSize
|
: m_computeThinU ? m_diagSize
|
||||||
@@ -618,8 +618,9 @@ JacobiSVD<MatrixType, QRPreconditioner>::compute(const MatrixType& matrix, unsig
|
|||||||
// if this 2x2 sub-matrix is not diagonal already...
|
// if this 2x2 sub-matrix is not diagonal already...
|
||||||
// notice that this comparison will evaluate to false if any NaN is involved, ensuring that NaN's don't
|
// notice that this comparison will evaluate to false if any NaN is involved, ensuring that NaN's don't
|
||||||
// keep us iterating forever.
|
// keep us iterating forever.
|
||||||
if(std::max(internal::abs(m_workMatrix.coeff(p,q)),internal::abs(m_workMatrix.coeff(q,p)))
|
using std::max;
|
||||||
> std::max(internal::abs(m_workMatrix.coeff(p,p)),internal::abs(m_workMatrix.coeff(q,q)))*precision)
|
if((max)(internal::abs(m_workMatrix.coeff(p,q)),internal::abs(m_workMatrix.coeff(q,p)))
|
||||||
|
> (max)(internal::abs(m_workMatrix.coeff(p,p)),internal::abs(m_workMatrix.coeff(q,q)))*precision)
|
||||||
{
|
{
|
||||||
finished = false;
|
finished = false;
|
||||||
|
|
||||||
@@ -688,7 +689,7 @@ struct solve_retval<JacobiSVD<_MatrixType, QRPreconditioner>, Rhs>
|
|||||||
// A = U S V^*
|
// A = U S V^*
|
||||||
// So A^{-1} = V S^{-1} U^*
|
// So A^{-1} = V S^{-1} U^*
|
||||||
|
|
||||||
Index diagSize = std::min(dec().rows(), dec().cols());
|
Index diagSize = (std::min)(dec().rows(), dec().cols());
|
||||||
typename JacobiSVDType::SingularValuesType invertedSingVals(diagSize);
|
typename JacobiSVDType::SingularValuesType invertedSingVals(diagSize);
|
||||||
|
|
||||||
Index nonzeroSingVals = dec().nonzeroSingularValues();
|
Index nonzeroSingVals = dec().nonzeroSingularValues();
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ class AmbiVector
|
|||||||
void reallocateSparse()
|
void reallocateSparse()
|
||||||
{
|
{
|
||||||
Index copyElements = m_allocatedElements;
|
Index copyElements = m_allocatedElements;
|
||||||
m_allocatedElements = std::min(Index(m_allocatedElements*1.5),m_size);
|
m_allocatedElements = (std::min)(Index(m_allocatedElements*1.5),m_size);
|
||||||
Index allocSize = m_allocatedElements * sizeof(ListEl);
|
Index allocSize = m_allocatedElements * sizeof(ListEl);
|
||||||
allocSize = allocSize/sizeof(Scalar) + (allocSize%sizeof(Scalar)>0?1:0);
|
allocSize = allocSize/sizeof(Scalar) + (allocSize%sizeof(Scalar)>0?1:0);
|
||||||
Scalar* newBuffer = new Scalar[allocSize];
|
Scalar* newBuffer = new Scalar[allocSize];
|
||||||
|
|||||||
@@ -216,7 +216,7 @@ class CompressedStorage
|
|||||||
{
|
{
|
||||||
Scalar* newValues = new Scalar[size];
|
Scalar* newValues = new Scalar[size];
|
||||||
Index* newIndices = new Index[size];
|
Index* newIndices = new Index[size];
|
||||||
size_t copySize = std::min(size, m_size);
|
size_t copySize = (std::min)(size, m_size);
|
||||||
// copy
|
// copy
|
||||||
memcpy(newValues, m_values, copySize * sizeof(Scalar));
|
memcpy(newValues, m_values, copySize * sizeof(Scalar));
|
||||||
memcpy(newIndices, m_indices, copySize * sizeof(Index));
|
memcpy(newIndices, m_indices, copySize * sizeof(Index));
|
||||||
|
|||||||
@@ -141,7 +141,7 @@ class DynamicSparseMatrix
|
|||||||
{
|
{
|
||||||
if (outerSize()>0)
|
if (outerSize()>0)
|
||||||
{
|
{
|
||||||
Index reserveSizePerVector = std::max(reserveSize/outerSize(),Index(4));
|
Index reserveSizePerVector = (std::max)(reserveSize/outerSize(),Index(4));
|
||||||
for (Index j=0; j<outerSize(); ++j)
|
for (Index j=0; j<outerSize(); ++j)
|
||||||
{
|
{
|
||||||
m_data[j].reserve(reserveSizePerVector);
|
m_data[j].reserve(reserveSizePerVector);
|
||||||
|
|||||||
@@ -35,7 +35,7 @@
|
|||||||
// const typename internal::nested<Derived,2>::type nested(derived());
|
// const typename internal::nested<Derived,2>::type nested(derived());
|
||||||
// const typename internal::nested<OtherDerived,2>::type otherNested(other.derived());
|
// const typename internal::nested<OtherDerived,2>::type otherNested(other.derived());
|
||||||
// return (nested - otherNested).cwise().abs2().sum()
|
// return (nested - otherNested).cwise().abs2().sum()
|
||||||
// <= prec * prec * std::min(nested.cwise().abs2().sum(), otherNested.cwise().abs2().sum());
|
// <= prec * prec * (std::min)(nested.cwise().abs2().sum(), otherNested.cwise().abs2().sum());
|
||||||
// }
|
// }
|
||||||
|
|
||||||
#endif // EIGEN_SPARSE_FUZZY_H
|
#endif // EIGEN_SPARSE_FUZZY_H
|
||||||
|
|||||||
@@ -257,7 +257,7 @@ class SparseMatrix
|
|||||||
// furthermore we bound the realloc ratio to:
|
// furthermore we bound the realloc ratio to:
|
||||||
// 1) reduce multiple minor realloc when the matrix is almost filled
|
// 1) reduce multiple minor realloc when the matrix is almost filled
|
||||||
// 2) avoid to allocate too much memory when the matrix is almost empty
|
// 2) avoid to allocate too much memory when the matrix is almost empty
|
||||||
reallocRatio = std::min(std::max(reallocRatio,1.5f),8.f);
|
reallocRatio = (std::min)((std::max)(reallocRatio,1.5f),8.f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_data.resize(m_data.size()+1,reallocRatio);
|
m_data.resize(m_data.size()+1,reallocRatio);
|
||||||
|
|||||||
@@ -223,7 +223,7 @@ template<typename Derived> class SparseMatrixBase : public EigenBase<Derived>
|
|||||||
// thanks to shallow copies, we always eval to a tempary
|
// thanks to shallow copies, we always eval to a tempary
|
||||||
Derived temp(other.rows(), other.cols());
|
Derived temp(other.rows(), other.cols());
|
||||||
|
|
||||||
temp.reserve(std::max(this->rows(),this->cols())*2);
|
temp.reserve((std::max)(this->rows(),this->cols())*2);
|
||||||
for (Index j=0; j<outerSize; ++j)
|
for (Index j=0; j<outerSize; ++j)
|
||||||
{
|
{
|
||||||
temp.startVec(j);
|
temp.startVec(j);
|
||||||
@@ -253,7 +253,7 @@ template<typename Derived> class SparseMatrixBase : public EigenBase<Derived>
|
|||||||
// eval without temporary
|
// eval without temporary
|
||||||
derived().resize(other.rows(), other.cols());
|
derived().resize(other.rows(), other.cols());
|
||||||
derived().setZero();
|
derived().setZero();
|
||||||
derived().reserve(std::max(this->rows(),this->cols())*2);
|
derived().reserve((std::max)(this->rows(),this->cols())*2);
|
||||||
for (Index j=0; j<outerSize; ++j)
|
for (Index j=0; j<outerSize; ++j)
|
||||||
{
|
{
|
||||||
derived().startVec(j);
|
derived().startVec(j);
|
||||||
|
|||||||
@@ -31,13 +31,13 @@
|
|||||||
* \brief Pseudo expression to manipulate a triangular sparse matrix as a selfadjoint matrix.
|
* \brief Pseudo expression to manipulate a triangular sparse matrix as a selfadjoint matrix.
|
||||||
*
|
*
|
||||||
* \param MatrixType the type of the dense matrix storing the coefficients
|
* \param MatrixType the type of the dense matrix storing the coefficients
|
||||||
* \param UpLo can be either \c Lower or \c Upper
|
* \param UpLo can be either \c #Lower or \c #Upper
|
||||||
*
|
*
|
||||||
* This class is an expression of a sefladjoint matrix from a triangular part of a matrix
|
* This class is an expression of a sefladjoint matrix from a triangular part of a matrix
|
||||||
* with given dense storage of the coefficients. It is the return type of MatrixBase::selfadjointView()
|
* with given dense storage of the coefficients. It is the return type of MatrixBase::selfadjointView()
|
||||||
* and most of the time this is the only way that it is used.
|
* and most of the time this is the only way that it is used.
|
||||||
*
|
*
|
||||||
* \sa SparseMatrixBase::selfAdjointView()
|
* \sa SparseMatrixBase::selfadjointView()
|
||||||
*/
|
*/
|
||||||
template<typename Lhs, typename Rhs, int UpLo>
|
template<typename Lhs, typename Rhs, int UpLo>
|
||||||
class SparseSelfAdjointTimeDenseProduct;
|
class SparseSelfAdjointTimeDenseProduct;
|
||||||
@@ -383,7 +383,7 @@ void permute_symm_to_symm(const MatrixType& mat, SparseMatrix<typename MatrixTyp
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
Index ip = perm ? perm[i] : i;
|
Index ip = perm ? perm[i] : i;
|
||||||
count[DstUpLo==Lower ? std::min(ip,jp) : std::max(ip,jp)]++;
|
count[DstUpLo==Lower ? (std::min)(ip,jp) : (std::max)(ip,jp)]++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dest._outerIndexPtr()[0] = 0;
|
dest._outerIndexPtr()[0] = 0;
|
||||||
@@ -403,8 +403,8 @@ void permute_symm_to_symm(const MatrixType& mat, SparseMatrix<typename MatrixTyp
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
Index ip = perm? perm[i] : i;
|
Index ip = perm? perm[i] : i;
|
||||||
Index k = count[DstUpLo==Lower ? std::min(ip,jp) : std::max(ip,jp)]++;
|
Index k = count[DstUpLo==Lower ? (std::min)(ip,jp) : (std::max)(ip,jp)]++;
|
||||||
dest._innerIndexPtr()[k] = DstUpLo==Lower ? std::max(ip,jp) : std::min(ip,jp);
|
dest._innerIndexPtr()[k] = DstUpLo==Lower ? (std::max)(ip,jp) : (std::min)(ip,jp);
|
||||||
|
|
||||||
if((DstUpLo==Lower && ip<jp) || (DstUpLo==Upper && ip>jp))
|
if((DstUpLo==Lower && ip<jp) || (DstUpLo==Upper && ip>jp))
|
||||||
dest._valuePtr()[k] = conj(it.value());
|
dest._valuePtr()[k] = conj(it.value());
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ static void sparse_product_impl2(const Lhs& lhs, const Rhs& rhs, ResultType& res
|
|||||||
// estimate the number of non zero entries
|
// estimate the number of non zero entries
|
||||||
float ratioLhs = float(lhs.nonZeros())/(float(lhs.rows())*float(lhs.cols()));
|
float ratioLhs = float(lhs.nonZeros())/(float(lhs.rows())*float(lhs.cols()));
|
||||||
float avgNnzPerRhsColumn = float(rhs.nonZeros())/float(cols);
|
float avgNnzPerRhsColumn = float(rhs.nonZeros())/float(cols);
|
||||||
float ratioRes = std::min(ratioLhs * avgNnzPerRhsColumn, 1.f);
|
float ratioRes = (std::min)(ratioLhs * avgNnzPerRhsColumn, 1.f);
|
||||||
|
|
||||||
// int t200 = rows/(log2(200)*1.39);
|
// int t200 = rows/(log2(200)*1.39);
|
||||||
// int t = (rows*100)/139;
|
// int t = (rows*100)/139;
|
||||||
@@ -131,7 +131,7 @@ static void sparse_product_impl(const Lhs& lhs, const Rhs& rhs, ResultType& res)
|
|||||||
// estimate the number of non zero entries
|
// estimate the number of non zero entries
|
||||||
float ratioLhs = float(lhs.nonZeros())/(float(lhs.rows())*float(lhs.cols()));
|
float ratioLhs = float(lhs.nonZeros())/(float(lhs.rows())*float(lhs.cols()));
|
||||||
float avgNnzPerRhsColumn = float(rhs.nonZeros())/float(cols);
|
float avgNnzPerRhsColumn = float(rhs.nonZeros())/float(cols);
|
||||||
float ratioRes = std::min(ratioLhs * avgNnzPerRhsColumn, 1.f);
|
float ratioRes = (std::min)(ratioLhs * avgNnzPerRhsColumn, 1.f);
|
||||||
|
|
||||||
// mimics a resizeByInnerOuter:
|
// mimics a resizeByInnerOuter:
|
||||||
if(ResultType::IsRowMajor)
|
if(ResultType::IsRowMajor)
|
||||||
@@ -143,7 +143,7 @@ static void sparse_product_impl(const Lhs& lhs, const Rhs& rhs, ResultType& res)
|
|||||||
for (Index j=0; j<cols; ++j)
|
for (Index j=0; j<cols; ++j)
|
||||||
{
|
{
|
||||||
// let's do a more accurate determination of the nnz ratio for the current column j of res
|
// let's do a more accurate determination of the nnz ratio for the current column j of res
|
||||||
//float ratioColRes = std::min(ratioLhs * rhs.innerNonZeros(j), 1.f);
|
//float ratioColRes = (std::min)(ratioLhs * rhs.innerNonZeros(j), 1.f);
|
||||||
// FIXME find a nice way to get the number of nonzeros of a sub matrix (here an inner vector)
|
// FIXME find a nice way to get the number of nonzeros of a sub matrix (here an inner vector)
|
||||||
float ratioColRes = ratioRes;
|
float ratioColRes = ratioRes;
|
||||||
tempVector.init(ratioColRes);
|
tempVector.init(ratioColRes);
|
||||||
|
|||||||
@@ -28,32 +28,24 @@
|
|||||||
|
|
||||||
#include "Eigen/src/StlSupport/details.h"
|
#include "Eigen/src/StlSupport/details.h"
|
||||||
|
|
||||||
// Define the explicit instantiation (e.g. necessary for the Intel compiler)
|
|
||||||
#if defined(__INTEL_COMPILER) || defined(__GNUC__)
|
|
||||||
#define EIGEN_EXPLICIT_STL_VECTOR_INSTANTIATION(...) template class std::vector<__VA_ARGS__, EIGEN_ALIGNED_ALLOCATOR<__VA_ARGS__> >;
|
|
||||||
#else
|
|
||||||
#define EIGEN_EXPLICIT_STL_VECTOR_INSTANTIATION(...)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This section contains a convenience MACRO which allows an easy specialization of
|
* This section contains a convenience MACRO which allows an easy specialization of
|
||||||
* std::vector such that for data types with alignment issues the correct allocator
|
* std::vector such that for data types with alignment issues the correct allocator
|
||||||
* is used automatically.
|
* is used automatically.
|
||||||
*/
|
*/
|
||||||
#define EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION(...) \
|
#define EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION(...) \
|
||||||
EIGEN_EXPLICIT_STL_VECTOR_INSTANTIATION(__VA_ARGS__) \
|
|
||||||
namespace std \
|
namespace std \
|
||||||
{ \
|
{ \
|
||||||
template<typename _Ay> \
|
template<> \
|
||||||
class vector<__VA_ARGS__, _Ay> \
|
class vector<__VA_ARGS__, std::allocator<__VA_ARGS__> > \
|
||||||
: public vector<__VA_ARGS__, EIGEN_ALIGNED_ALLOCATOR<__VA_ARGS__> > \
|
: public vector<__VA_ARGS__, EIGEN_ALIGNED_ALLOCATOR<__VA_ARGS__> > \
|
||||||
{ \
|
{ \
|
||||||
typedef vector<__VA_ARGS__, EIGEN_ALIGNED_ALLOCATOR<__VA_ARGS__> > vector_base; \
|
typedef vector<__VA_ARGS__, EIGEN_ALIGNED_ALLOCATOR<__VA_ARGS__> > vector_base; \
|
||||||
public: \
|
public: \
|
||||||
typedef __VA_ARGS__ value_type; \
|
typedef __VA_ARGS__ value_type; \
|
||||||
typedef typename vector_base::allocator_type allocator_type; \
|
typedef vector_base::allocator_type allocator_type; \
|
||||||
typedef typename vector_base::size_type size_type; \
|
typedef vector_base::size_type size_type; \
|
||||||
typedef typename vector_base::iterator iterator; \
|
typedef vector_base::iterator iterator; \
|
||||||
explicit vector(const allocator_type& a = allocator_type()) : vector_base(a) {} \
|
explicit vector(const allocator_type& a = allocator_type()) : vector_base(a) {} \
|
||||||
template<typename InputIterator> \
|
template<typename InputIterator> \
|
||||||
vector(InputIterator first, InputIterator last, const allocator_type& a = allocator_type()) : vector_base(first, last, a) {} \
|
vector(InputIterator first, InputIterator last, const allocator_type& a = allocator_type()) : vector_base(first, last, a) {} \
|
||||||
|
|||||||
@@ -119,7 +119,7 @@ public:
|
|||||||
|
|
||||||
inline double getCpuTime()
|
inline double getCpuTime()
|
||||||
{
|
{
|
||||||
#ifdef WIN32
|
#ifdef _WIN32
|
||||||
LARGE_INTEGER query_ticks;
|
LARGE_INTEGER query_ticks;
|
||||||
QueryPerformanceCounter(&query_ticks);
|
QueryPerformanceCounter(&query_ticks);
|
||||||
return query_ticks.QuadPart/m_frequency;
|
return query_ticks.QuadPart/m_frequency;
|
||||||
@@ -132,7 +132,7 @@ public:
|
|||||||
|
|
||||||
inline double getRealTime()
|
inline double getRealTime()
|
||||||
{
|
{
|
||||||
#ifdef WIN32
|
#ifdef _WIN32
|
||||||
SYSTEMTIME st;
|
SYSTEMTIME st;
|
||||||
GetSystemTime(&st);
|
GetSystemTime(&st);
|
||||||
return (double)st.wSecond + 1.e-3 * (double)st.wMilliseconds;
|
return (double)st.wSecond + 1.e-3 * (double)st.wMilliseconds;
|
||||||
|
|||||||
@@ -56,12 +56,12 @@ class EigenMatrixPrinter:
|
|||||||
template_params = m.split(',')
|
template_params = m.split(',')
|
||||||
template_params = map(lambda x:x.replace(" ", ""), template_params)
|
template_params = map(lambda x:x.replace(" ", ""), template_params)
|
||||||
|
|
||||||
if template_params[1] == '-0x00000000000000001':
|
if template_params[1] == '-0x00000000000000001' or template_params[1] == '-0x000000001':
|
||||||
self.rows = val['m_storage']['m_rows']
|
self.rows = val['m_storage']['m_rows']
|
||||||
else:
|
else:
|
||||||
self.rows = int(template_params[1])
|
self.rows = int(template_params[1])
|
||||||
|
|
||||||
if template_params[2] == '-0x00000000000000001':
|
if template_params[2] == '-0x00000000000000001' or template_params[2] == '-0x000000001':
|
||||||
self.cols = val['m_storage']['m_cols']
|
self.cols = val['m_storage']['m_cols']
|
||||||
else:
|
else:
|
||||||
self.cols = int(template_params[2])
|
self.cols = int(template_params[2])
|
||||||
|
|||||||
@@ -287,7 +287,7 @@ The EIGEN_DONT_ALIGN option still exists in Eigen 3, but it has a new cousin: EI
|
|||||||
|
|
||||||
A common issue with Eigen 2 was that when mapping an array with Map, there was no way to tell Eigen that your array was aligned. There was a ForceAligned option but it didn't mean that; it was just confusing and has been removed.
|
A common issue with Eigen 2 was that when mapping an array with Map, there was no way to tell Eigen that your array was aligned. There was a ForceAligned option but it didn't mean that; it was just confusing and has been removed.
|
||||||
|
|
||||||
New in Eigen3 is the Aligned option. See the documentation of class Map. Use it like this:
|
New in Eigen3 is the #Aligned option. See the documentation of class Map. Use it like this:
|
||||||
\code
|
\code
|
||||||
Map<Vector4f, Aligned> myMappedVector(some_aligned_array);
|
Map<Vector4f, Aligned> myMappedVector(some_aligned_array);
|
||||||
\endcode
|
\endcode
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ The output is as follows:
|
|||||||
|
|
||||||
The second example starts by declaring a 3-by-3 matrix \c m which is initialized using the \link DenseBase::Random(Index,Index) Random() \endlink method with random values between -1 and 1. The next line applies a linear mapping such that the values are between 10 and 110. The function call \link DenseBase::Constant(Index,Index,const Scalar&) MatrixXd::Constant\endlink(3,3,1.2) returns a 3-by-3 matrix expression having all coefficients equal to 1.2. The rest is standard arithmetics.
|
The second example starts by declaring a 3-by-3 matrix \c m which is initialized using the \link DenseBase::Random(Index,Index) Random() \endlink method with random values between -1 and 1. The next line applies a linear mapping such that the values are between 10 and 110. The function call \link DenseBase::Constant(Index,Index,const Scalar&) MatrixXd::Constant\endlink(3,3,1.2) returns a 3-by-3 matrix expression having all coefficients equal to 1.2. The rest is standard arithmetics.
|
||||||
|
|
||||||
The next line of the \c main function introduces a new type: \c VectorXd. This represents a (column) vector of arbitrary size. Here, the vector \c v is created to contains \c 3 coefficients which are left unitialized. The one but last line uses the so-called comma-initializer, explained in \ref TutorialAdvancedInitialization, to set all coefficients of the vector \c v to be as follows:
|
The next line of the \c main function introduces a new type: \c VectorXd. This represents a (column) vector of arbitrary size. Here, the vector \c v is created to contain \c 3 coefficients which are left unitialized. The one but last line uses the so-called comma-initializer, explained in \ref TutorialAdvancedInitialization, to set all coefficients of the vector \c v to be as follows:
|
||||||
|
|
||||||
\f[
|
\f[
|
||||||
v =
|
v =
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ we won't explain it again here and just refer to \ref TutorialMatrixClass.
|
|||||||
|
|
||||||
Eigen also provides typedefs for some common cases, in a way that is similar to the Matrix typedefs
|
Eigen also provides typedefs for some common cases, in a way that is similar to the Matrix typedefs
|
||||||
but with some slight differences, as the word "array" is used for both 1-dimensional and 2-dimensional arrays.
|
but with some slight differences, as the word "array" is used for both 1-dimensional and 2-dimensional arrays.
|
||||||
We adopt that convention that typedefs of the form ArrayNt stand for 1-dimensional arrays, where N and t are
|
We adopt the convention that typedefs of the form ArrayNt stand for 1-dimensional arrays, where N and t are
|
||||||
the size and the scalar type, as in the Matrix typedefs explained on \ref TutorialMatrixClass "this page". For 2-dimensional arrays, we
|
the size and the scalar type, as in the Matrix typedefs explained on \ref TutorialMatrixClass "this page". For 2-dimensional arrays, we
|
||||||
use typedefs of the form ArrayNNt. Some examples are shown in the following table:
|
use typedefs of the form ArrayNNt. Some examples are shown in the following table:
|
||||||
|
|
||||||
@@ -104,8 +104,8 @@ This provides a functionality that is not directly available for Matrix objects.
|
|||||||
|
|
||||||
First of all, of course you can multiply an array by a scalar, this works in the same way as matrices. Where arrays
|
First of all, of course you can multiply an array by a scalar, this works in the same way as matrices. Where arrays
|
||||||
are fundamentally different from matrices, is when you multiply two together. Matrices interpret
|
are fundamentally different from matrices, is when you multiply two together. Matrices interpret
|
||||||
multiplication as the matrix product and arrays interpret multiplication as the coefficient-wise product. Thus, two
|
multiplication as matrix product and arrays interpret multiplication as coefficient-wise product. Thus, two
|
||||||
arrays can be multiplied if they have the same size.
|
arrays can be multiplied if and only if they have the same dimensions.
|
||||||
|
|
||||||
<table class="example">
|
<table class="example">
|
||||||
<tr><th>Example:</th><th>Output:</th></tr>
|
<tr><th>Example:</th><th>Output:</th></tr>
|
||||||
@@ -119,8 +119,8 @@ arrays can be multiplied if they have the same size.
|
|||||||
|
|
||||||
\section TutorialArrayClassCwiseOther Other coefficient-wise operations
|
\section TutorialArrayClassCwiseOther Other coefficient-wise operations
|
||||||
|
|
||||||
The Array class defined other coefficient-wise operations besides the addition, subtraction and multiplication
|
The Array class defines other coefficient-wise operations besides the addition, subtraction and multiplication
|
||||||
operators described about. For example, the \link ArrayBase::abs() .abs() \endlink method takes the absolute
|
operators described above. For example, the \link ArrayBase::abs() .abs() \endlink method takes the absolute
|
||||||
value of each coefficient, while \link ArrayBase::sqrt() .sqrt() \endlink computes the square root of the
|
value of each coefficient, while \link ArrayBase::sqrt() .sqrt() \endlink computes the square root of the
|
||||||
coefficients. If you have two arrays of the same size, you can call \link ArrayBase::min() .min() \endlink to
|
coefficients. If you have two arrays of the same size, you can call \link ArrayBase::min() .min() \endlink to
|
||||||
construct the array whose coefficients are the minimum of the corresponding coefficients of the two given
|
construct the array whose coefficients are the minimum of the corresponding coefficients of the two given
|
||||||
@@ -155,7 +155,7 @@ this doesn't have any runtime cost (provided that you let your compiler optimize
|
|||||||
Both \link MatrixBase::array() .array() \endlink and \link ArrayBase::matrix() .matrix() \endlink
|
Both \link MatrixBase::array() .array() \endlink and \link ArrayBase::matrix() .matrix() \endlink
|
||||||
can be used as rvalues and as lvalues.
|
can be used as rvalues and as lvalues.
|
||||||
|
|
||||||
Mixing matrices and arrays in an expression is forbidden with Eigen. For instance, you cannot add a amtrix and
|
Mixing matrices and arrays in an expression is forbidden with Eigen. For instance, you cannot add a matrix and
|
||||||
array directly; the operands of a \c + operator should either both be matrices or both be arrays. However,
|
array directly; the operands of a \c + operator should either both be matrices or both be arrays. However,
|
||||||
it is easy to convert from one to the other with \link MatrixBase::array() .array() \endlink and
|
it is easy to convert from one to the other with \link MatrixBase::array() .array() \endlink and
|
||||||
\link ArrayBase::matrix() .matrix()\endlink. The exception to this rule is the assignment operator: it is
|
\link ArrayBase::matrix() .matrix()\endlink. The exception to this rule is the assignment operator: it is
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ Array.
|
|||||||
|
|
||||||
The arguments passed to a visitor are pointers to the variables where the
|
The arguments passed to a visitor are pointers to the variables where the
|
||||||
row and column position are to be stored. These variables should be of type
|
row and column position are to be stored. These variables should be of type
|
||||||
\link DenseBase::Index Index \endlink (FIXME: link ok?), as shown below:
|
\link DenseBase::Index Index \endlink, as shown below:
|
||||||
|
|
||||||
<table class="example">
|
<table class="example">
|
||||||
<tr><th>Example:</th><th>Output:</th></tr>
|
<tr><th>Example:</th><th>Output:</th></tr>
|
||||||
@@ -141,7 +141,7 @@ return a 'column-vector'</b>
|
|||||||
|
|
||||||
\subsection TutorialReductionsVisitorsBroadcastingPartialReductionsCombined Combining partial reductions with other operations
|
\subsection TutorialReductionsVisitorsBroadcastingPartialReductionsCombined Combining partial reductions with other operations
|
||||||
It is also possible to use the result of a partial reduction to do further processing.
|
It is also possible to use the result of a partial reduction to do further processing.
|
||||||
Here is another example that aims to find the column whose sum of elements is the maximum
|
Here is another example that finds the column whose sum of elements is the maximum
|
||||||
within a matrix. With column-wise partial reductions this can be coded as:
|
within a matrix. With column-wise partial reductions this can be coded as:
|
||||||
|
|
||||||
<table class="example">
|
<table class="example">
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ namespace Eigen {
|
|||||||
\li \b Previous: \ref TutorialReductionsVisitorsBroadcasting
|
\li \b Previous: \ref TutorialReductionsVisitorsBroadcasting
|
||||||
\li \b Next: \ref TutorialSparse
|
\li \b Next: \ref TutorialSparse
|
||||||
|
|
||||||
In this tutorial, we will shortly introduce the many possibilities offered by the \ref Geometry_Module "geometry module", namely 2D and 3D rotations and projective or affine transformations.
|
In this tutorial, we will briefly introduce the many possibilities offered by the \ref Geometry_Module "geometry module", namely 2D and 3D rotations and projective or affine transformations.
|
||||||
|
|
||||||
\b Table \b of \b contents
|
\b Table \b of \b contents
|
||||||
- \ref TutorialGeoElementaryTransformations
|
- \ref TutorialGeoElementaryTransformations
|
||||||
@@ -48,7 +48,7 @@ Rotation2D<float> rot2(angle_in_radian);\endcode</td></tr>
|
|||||||
AngleAxis<float> aa(angle_in_radian, Vector3f(ax,ay,az));\endcode</td></tr>
|
AngleAxis<float> aa(angle_in_radian, Vector3f(ax,ay,az));\endcode</td></tr>
|
||||||
<tr><td>
|
<tr><td>
|
||||||
3D rotation as a \ref Quaternion "quaternion"</td><td>\code
|
3D rotation as a \ref Quaternion "quaternion"</td><td>\code
|
||||||
Quaternion<float> q = AngleAxis<float>(angle_in_radian, axis);\endcode</td></tr>
|
Quaternion<float> q; q = AngleAxis<float>(angle_in_radian, axis);\endcode</td></tr>
|
||||||
<tr class="alt"><td>
|
<tr class="alt"><td>
|
||||||
N-D Scaling</td><td>\code
|
N-D Scaling</td><td>\code
|
||||||
Scaling<float,2>(sx, sy)
|
Scaling<float,2>(sx, sy)
|
||||||
@@ -78,7 +78,7 @@ representations are rotation matrices, while for other usages Quaternion is the
|
|||||||
representation of choice as they are compact, fast and stable. Finally Rotation2D and
|
representation of choice as they are compact, fast and stable. Finally Rotation2D and
|
||||||
AngleAxis are mainly convenient types to create other rotation objects.
|
AngleAxis are mainly convenient types to create other rotation objects.
|
||||||
|
|
||||||
<strong>Notes on Translation and Scaling</strong>\n Likewise AngleAxis, these classes were
|
<strong>Notes on Translation and Scaling</strong>\n Like AngleAxis, these classes were
|
||||||
designed to simplify the creation/initialization of linear (Matrix) and affine (Transform)
|
designed to simplify the creation/initialization of linear (Matrix) and affine (Transform)
|
||||||
transformations. Nevertheless, unlike AngleAxis which is inefficient to use, these classes
|
transformations. Nevertheless, unlike AngleAxis which is inefficient to use, these classes
|
||||||
might still be interesting to write generic and efficient algorithms taking as input any
|
might still be interesting to write generic and efficient algorithms taking as input any
|
||||||
@@ -88,13 +88,13 @@ Any of the above transformation types can be converted to any other types of the
|
|||||||
or to a more generic type. Here are some additional examples:
|
or to a more generic type. Here are some additional examples:
|
||||||
<table class="manual">
|
<table class="manual">
|
||||||
<tr><td>\code
|
<tr><td>\code
|
||||||
Rotation2Df r = Matrix2f(..); // assumes a pure rotation matrix
|
Rotation2Df r; r = Matrix2f(..); // assumes a pure rotation matrix
|
||||||
AngleAxisf aa = Quaternionf(..);
|
AngleAxisf aa; aa = Quaternionf(..);
|
||||||
AngleAxisf aa = Matrix3f(..); // assumes a pure rotation matrix
|
AngleAxisf aa; aa = Matrix3f(..); // assumes a pure rotation matrix
|
||||||
Matrix2f m = Rotation2Df(..);
|
Matrix2f m; m = Rotation2Df(..);
|
||||||
Matrix3f m = Quaternionf(..); Matrix3f m = Scaling3f(..);
|
Matrix3f m; m = Quaternionf(..); Matrix3f m; m = Scaling3f(..);
|
||||||
Affine3f m = AngleAxis3f(..); Affine3f m = Scaling3f(..);
|
Affine3f m; m = AngleAxis3f(..); Affine3f m; m = Scaling3f(..);
|
||||||
Affine3f m = Translation3f(..); Affine3f m = Matrix3f(..);
|
Affine3f m; m = Translation3f(..); Affine3f m; m = Matrix3f(..);
|
||||||
\endcode</td></tr>
|
\endcode</td></tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
@@ -186,7 +186,7 @@ matNxN = t.extractRotation();
|
|||||||
While transformation objects can be created and updated concatenating elementary transformations,
|
While transformation objects can be created and updated concatenating elementary transformations,
|
||||||
the Transform class also features a procedural API:
|
the Transform class also features a procedural API:
|
||||||
<table class="manual">
|
<table class="manual">
|
||||||
<tr><th></th><th>procedurale API</th><th>equivalent natural API </th></tr>
|
<tr><th></th><th>procedural API</th><th>equivalent natural API </th></tr>
|
||||||
<tr><td>Translation</td><td>\code
|
<tr><td>Translation</td><td>\code
|
||||||
t.translate(Vector_(tx,ty,..));
|
t.translate(Vector_(tx,ty,..));
|
||||||
t.pretranslate(Vector_(tx,ty,..));
|
t.pretranslate(Vector_(tx,ty,..));
|
||||||
@@ -234,7 +234,7 @@ t = Translation_(..) * t * RotationType(..) * Translation_(..) * Scaling_(..);
|
|||||||
<table class="manual">
|
<table class="manual">
|
||||||
<tr><td style="max-width:30em;">
|
<tr><td style="max-width:30em;">
|
||||||
Euler angles might be convenient to create rotation objects.
|
Euler angles might be convenient to create rotation objects.
|
||||||
On the other hand, since there exist 24 differents convension,they are pretty confusing to use. This example shows how
|
On the other hand, since there exist 24 different conventions, they are pretty confusing to use. This example shows how
|
||||||
to create a rotation matrix according to the 2-1-2 convention.</td><td>\code
|
to create a rotation matrix according to the 2-1-2 convention.</td><td>\code
|
||||||
Matrix3f m;
|
Matrix3f m;
|
||||||
m = AngleAxisf(angle1, Vector3f::UnitZ())
|
m = AngleAxisf(angle1, Vector3f::UnitZ())
|
||||||
|
|||||||
@@ -55,17 +55,17 @@ and its internal representation using the Compressed Column Storage format:
|
|||||||
</table>
|
</table>
|
||||||
Outer indices:<table class="manual"><tr><td>0</td><td>2</td><td>4</td><td>5</td><td>6</td><td>\em 7 </td></tr></table>
|
Outer indices:<table class="manual"><tr><td>0</td><td>2</td><td>4</td><td>5</td><td>6</td><td>\em 7 </td></tr></table>
|
||||||
|
|
||||||
As you can guess, here the storage order is even more important than with dense matrix. We will therefore often make a clear difference between the \em inner and \em outer dimensions. For instance, it is easy to loop over the coefficients of an \em inner \em vector (e.g., a column of a column-major matrix), but completely inefficient to do the same for an \em outer \em vector (e.g., a row of a col-major matrix).
|
As you might guess, here the storage order is even more important than with dense matrices. We will therefore often make a clear difference between the \em inner and \em outer dimensions. For instance, it is efficient to loop over the coefficients of an \em inner \em vector (e.g., a column of a column-major matrix), but completely inefficient to do the same for an \em outer \em vector (e.g., a row of a column-major matrix).
|
||||||
|
|
||||||
The SparseVector class implements the same compressed storage scheme but, of course, without any outer index buffer.
|
The SparseVector class implements the same compressed storage scheme but, of course, without any outer index buffer.
|
||||||
|
|
||||||
Since all nonzero coefficients of such a matrix are sequentially stored in memory, random insertion of new nonzeros can be extremely costly. To overcome this limitation, Eigen's sparse module provides a DynamicSparseMatrix class which is basically implemented as an array of SparseVector. In other words, a DynamicSparseMatrix is a SparseMatrix where the values and inner-indices arrays have been splitted into multiple small and resizable arrays. Assuming the number of nonzeros per inner vector is relatively low, this slight modification allow for very fast random insertion at the cost of a slight memory overhead and a lost of compatibility with other sparse libraries used by some of our highlevel solvers. Note that the major memory overhead comes from the extra memory preallocated by each inner vector to avoid an expensive memory reallocation at every insertion.
|
Since all nonzero coefficients of such a matrix are sequentially stored in memory, inserting a new nonzero near the "beginning" of the matrix can be extremely costly. As described below (\ref TutorialSparseFilling), one strategy is to fill nonzero coefficients in order. In cases where this is not possible, Eigen's sparse module also provides a DynamicSparseMatrix class which allows efficient random insertion. DynamicSparseMatrix is essentially implemented as an array of SparseVector, where the values and inner-indices arrays have been split into multiple small and resizable arrays. Assuming the number of nonzeros per inner vector is relatively small, this modification allows for very fast random insertion at the cost of a slight memory overhead (due to extra memory preallocated by each inner vector to avoid an expensive memory reallocation at every insertion) and a loss of compatibility with other sparse libraries used by some of our high-level solvers. Once complete, a DynamicSparseMatrix can be converted to a SparseMatrix to permit usage of these sparse libraries.
|
||||||
|
|
||||||
To summarize, it is recommanded to use a SparseMatrix whenever this is possible, and reserve the use of DynamicSparseMatrix for matrix assembly purpose when a SparseMatrix is not flexible enough. The respective pro/cons of both representations are summarized in the following table:
|
To summarize, it is recommended to use SparseMatrix whenever possible, and reserve the use of DynamicSparseMatrix to assemble a sparse matrix in cases when a SparseMatrix is not flexible enough. The respective pros/cons of both representations are summarized in the following table:
|
||||||
|
|
||||||
<table class="manual">
|
<table class="manual">
|
||||||
<tr><td></td> <td>SparseMatrix</td><td>DynamicSparseMatrix</td></tr>
|
<tr><td></td> <td>SparseMatrix</td><td>DynamicSparseMatrix</td></tr>
|
||||||
<tr><td>memory usage</td><td>***</td><td>**</td></tr>
|
<tr><td>memory efficiency</td><td>***</td><td>**</td></tr>
|
||||||
<tr><td>sorted insertion</td><td>***</td><td>***</td></tr>
|
<tr><td>sorted insertion</td><td>***</td><td>***</td></tr>
|
||||||
<tr><td>random insertion \n in sorted inner vector</td><td>**</td><td>**</td></tr>
|
<tr><td>random insertion \n in sorted inner vector</td><td>**</td><td>**</td></tr>
|
||||||
<tr><td>sorted insertion \n in random inner vector</td><td>-</td><td>***</td></tr>
|
<tr><td>sorted insertion \n in random inner vector</td><td>-</td><td>***</td></tr>
|
||||||
@@ -82,7 +82,7 @@ To summarize, it is recommanded to use a SparseMatrix whenever this is possible,
|
|||||||
|
|
||||||
\b Matrix \b and \b vector \b properties \n
|
\b Matrix \b and \b vector \b properties \n
|
||||||
|
|
||||||
Here mat and vec represents any sparse-matrix and sparse-vector types respectively.
|
Here mat and vec represent any sparse-matrix and sparse-vector type, respectively.
|
||||||
|
|
||||||
<table class="manual">
|
<table class="manual">
|
||||||
<tr><td>Standard \n dimensions</td><td>\code
|
<tr><td>Standard \n dimensions</td><td>\code
|
||||||
@@ -96,7 +96,7 @@ mat.innerSize()
|
|||||||
mat.outerSize()\endcode</td>
|
mat.outerSize()\endcode</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr><td>Number of non \n zero coefficiens</td><td>\code
|
<tr><td>Number of non \n zero coefficients</td><td>\code
|
||||||
mat.nonZeros() \endcode</td>
|
mat.nonZeros() \endcode</td>
|
||||||
<td>\code
|
<td>\code
|
||||||
vec.nonZeros() \endcode</td></tr>
|
vec.nonZeros() \endcode</td></tr>
|
||||||
@@ -105,12 +105,12 @@ vec.nonZeros() \endcode</td></tr>
|
|||||||
|
|
||||||
\b Iterating \b over \b the \b nonzero \b coefficients \n
|
\b Iterating \b over \b the \b nonzero \b coefficients \n
|
||||||
|
|
||||||
Iterating over the coefficients of a sparse matrix can be done only in the same order than the storage order. Here is an example:
|
Iterating over the coefficients of a sparse matrix can be done only in the same order as the storage order. Here is an example:
|
||||||
<table class="manual">
|
<table class="manual">
|
||||||
<tr><td>
|
<tr><td>
|
||||||
\code
|
\code
|
||||||
SparseMatrixType mat(rows,cols);
|
SparseMatrixType mat(rows,cols);
|
||||||
for (int k=0; k\<m1.outerSize(); ++k)
|
for (int k=0; k<m1.outerSize(); ++k)
|
||||||
for (SparseMatrixType::InnerIterator it(mat,k); it; ++it)
|
for (SparseMatrixType::InnerIterator it(mat,k); it; ++it)
|
||||||
{
|
{
|
||||||
it.value();
|
it.value();
|
||||||
|
|||||||
@@ -488,7 +488,7 @@ SHOW_FILES = YES
|
|||||||
# Namespaces page. This will remove the Namespaces entry from the Quick Index
|
# Namespaces page. This will remove the Namespaces entry from the Quick Index
|
||||||
# and from the Folder Tree View (if specified). The default is YES.
|
# and from the Folder Tree View (if specified). The default is YES.
|
||||||
|
|
||||||
SHOW_NAMESPACES = NO
|
SHOW_NAMESPACES = YES
|
||||||
|
|
||||||
# The FILE_VERSION_FILTER tag can be used to specify a program or script that
|
# The FILE_VERSION_FILTER tag can be used to specify a program or script that
|
||||||
# doxygen should invoke to get the current version for each file (typically from
|
# doxygen should invoke to get the current version for each file (typically from
|
||||||
|
|||||||
@@ -400,7 +400,7 @@ inline void writePacket(int index, const PacketScalar& x)
|
|||||||
internal::pstoret<Scalar, PacketScalar, StoreMode>(m_storage.data() + index, x);
|
internal::pstoret<Scalar, PacketScalar, StoreMode>(m_storage.data() + index, x);
|
||||||
}
|
}
|
||||||
\endcode
|
\endcode
|
||||||
Here, \a StoreMode is \a Aligned, indicating that we are doing a 128-bit-aligned write access, \a PacketScalar is a type representing a "SSE packet of 4 floats" and internal::pstoret is a function writing such a packet in memory. Their definitions are architecture-specific, we find them in src/Core/arch/SSE/PacketMath.h:
|
Here, \a StoreMode is \a #Aligned, indicating that we are doing a 128-bit-aligned write access, \a PacketScalar is a type representing a "SSE packet of 4 floats" and internal::pstoret is a function writing such a packet in memory. Their definitions are architecture-specific, we find them in src/Core/arch/SSE/PacketMath.h:
|
||||||
|
|
||||||
The line in src/Core/arch/SSE/PacketMath.h that determines the PacketScalar type (via a typedef in Matrix.h) is:
|
The line in src/Core/arch/SSE/PacketMath.h that determines the PacketScalar type (via a typedef in Matrix.h) is:
|
||||||
\code
|
\code
|
||||||
@@ -442,7 +442,7 @@ class CwiseBinaryOp
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
\endcode
|
\endcode
|
||||||
Here, \a m_lhs is the vector \a v, and \a m_rhs is the vector \a w. So the packet() function here is Matrix::packet(). The template parameter \a LoadMode is \a Aligned. So we're looking at
|
Here, \a m_lhs is the vector \a v, and \a m_rhs is the vector \a w. So the packet() function here is Matrix::packet(). The template parameter \a LoadMode is \a #Aligned. So we're looking at
|
||||||
\code
|
\code
|
||||||
class Matrix
|
class Matrix
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -535,7 +535,7 @@ vec.reverse() mat.colwise().reverse() mat.rowwise().reverse()
|
|||||||
vec.reverseInPlace()
|
vec.reverseInPlace()
|
||||||
\endcode
|
\endcode
|
||||||
|
|
||||||
\subsection QuickRef_Reverse Replicate
|
\subsection QuickRef_Replicate Replicate
|
||||||
Vectors, matrices, rows, and/or columns can be replicated in any direction (see DenseBase::replicate(), VectorwiseOp::replicate())
|
Vectors, matrices, rows, and/or columns can be replicated in any direction (see DenseBase::replicate(), VectorwiseOp::replicate())
|
||||||
\code
|
\code
|
||||||
vec.replicate(times) vec.replicate<Times>
|
vec.replicate(times) vec.replicate<Times>
|
||||||
@@ -594,7 +594,7 @@ unit or null diagonal (read/write):
|
|||||||
</td><td>\code
|
</td><td>\code
|
||||||
m.triangularView<Xxx>()
|
m.triangularView<Xxx>()
|
||||||
\endcode \n
|
\endcode \n
|
||||||
\c Xxx = Upper, Lower, StrictlyUpper, StrictlyLower, UnitUpper, UnitLower
|
\c Xxx = ::Upper, ::Lower, ::StrictlyUpper, ::StrictlyLower, ::UnitUpper, ::UnitLower
|
||||||
</td></tr>
|
</td></tr>
|
||||||
<tr><td>
|
<tr><td>
|
||||||
Writing to a specific triangular part:\n (only the referenced triangular part is evaluated)
|
Writing to a specific triangular part:\n (only the referenced triangular part is evaluated)
|
||||||
@@ -645,14 +645,14 @@ m3 -= s1 * m3.adjoint() * m1.selfadjointView<Eigen::Lower>();\endcode
|
|||||||
</td></tr>
|
</td></tr>
|
||||||
<tr><td>
|
<tr><td>
|
||||||
Rank 1 and rank K update: \n
|
Rank 1 and rank K update: \n
|
||||||
\f$ upper(M_1) += s1 M_2^* M_2 \f$ \n
|
\f$ upper(M_1) \mathrel{{+}{=}} s_1 M_2^* M_2 \f$ \n
|
||||||
\f$ lower(M_1) -= M_2 M_2^* \f$
|
\f$ lower(M_1) \mathbin{{-}{=}} M_2 M_2^* \f$
|
||||||
</td><td>\n \code
|
</td><td>\n \code
|
||||||
M1.selfadjointView<Eigen::Upper>().rankUpdate(M2,s1);
|
M1.selfadjointView<Eigen::Upper>().rankUpdate(M2,s1);
|
||||||
m1.selfadjointView<Eigen::Lower>().rankUpdate(m2.adjoint(),-1); \endcode
|
m1.selfadjointView<Eigen::Lower>().rankUpdate(m2.adjoint(),-1); \endcode
|
||||||
</td></tr>
|
</td></tr>
|
||||||
<tr><td>
|
<tr><td>
|
||||||
Rank 2 update: (\f$ M += s u v^* + s v u^* \f$)
|
Rank 2 update: (\f$ M \mathrel{{+}{=}} s u v^* + s v u^* \f$)
|
||||||
</td><td>\code
|
</td><td>\code
|
||||||
M.selfadjointView<Eigen::Upper>().rankUpdate(u,v,s);
|
M.selfadjointView<Eigen::Upper>().rankUpdate(u,v,s);
|
||||||
\endcode
|
\endcode
|
||||||
|
|||||||
@@ -5,15 +5,17 @@
|
|||||||
# will be used
|
# will be used
|
||||||
USER=${USER:-'orzel'}
|
USER=${USER:-'orzel'}
|
||||||
|
|
||||||
|
#ulimit -v 1024000
|
||||||
|
|
||||||
# step 1 : build
|
# step 1 : build
|
||||||
# todo if 'build is not there, create one:
|
# todo if 'build is not there, create one:
|
||||||
#mkdir build
|
mkdir build -p
|
||||||
(cd build && cmake .. && make -j3 doc) || { echo "make failed"; exit 1; }
|
(cd build && cmake .. && make doc) || { echo "make failed"; exit 1; }
|
||||||
#todo: n+1 where n = number of cpus
|
#todo: n+1 where n = number of cpus
|
||||||
|
|
||||||
#step 2 : upload
|
#step 2 : upload
|
||||||
# (the '/' at the end of path are very important, see rsync documentation)
|
# (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-devel/ || { echo "upload failed"; exit 1; }
|
rsync -az build/doc/html/ $USER@ssh.tuxfamily.org:eigen/eigen.tuxfamily.org-web/htdocs/dox-3.0/ || { echo "upload failed"; exit 1; }
|
||||||
|
|
||||||
echo "Uploaded successfully"
|
echo "Uploaded successfully"
|
||||||
|
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ ei_add_test(linearstructure)
|
|||||||
ei_add_test(integer_types)
|
ei_add_test(integer_types)
|
||||||
ei_add_test(cwiseop)
|
ei_add_test(cwiseop)
|
||||||
ei_add_test(unalignedcount)
|
ei_add_test(unalignedcount)
|
||||||
|
ei_add_test(exceptions)
|
||||||
ei_add_test(redux)
|
ei_add_test(redux)
|
||||||
ei_add_test(visitor)
|
ei_add_test(visitor)
|
||||||
ei_add_test(block)
|
ei_add_test(block)
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ template<typename MatrixType> void adjoint(const MatrixType& m)
|
|||||||
// check basic properties of dot, norm, norm2
|
// check basic properties of dot, norm, norm2
|
||||||
typedef typename NumTraits<Scalar>::Real RealScalar;
|
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||||
|
|
||||||
RealScalar ref = NumTraits<Scalar>::IsInteger ? 0 : std::max((s1 * v1 + s2 * v2).norm(),v3.norm());
|
RealScalar ref = NumTraits<Scalar>::IsInteger ? 0 : (std::max)((s1 * v1 + s2 * v2).norm(),v3.norm());
|
||||||
VERIFY(test_isApproxWithRef((s1 * v1 + s2 * v2).dot(v3), internal::conj(s1) * v1.dot(v3) + internal::conj(s2) * v2.dot(v3), ref));
|
VERIFY(test_isApproxWithRef((s1 * v1 + s2 * v2).dot(v3), internal::conj(s1) * v1.dot(v3) + internal::conj(s2) * v2.dot(v3), ref));
|
||||||
VERIFY(test_isApproxWithRef(v3.dot(s1 * v1 + s2 * v2), s1*v3.dot(v1)+s2*v3.dot(v2), ref));
|
VERIFY(test_isApproxWithRef(v3.dot(s1 * v1 + s2 * v2), s1*v3.dot(v1)+s2*v3.dot(v2), ref));
|
||||||
VERIFY_IS_APPROX(internal::conj(v1.dot(v2)), v2.dot(v1));
|
VERIFY_IS_APPROX(internal::conj(v1.dot(v2)), v2.dot(v1));
|
||||||
@@ -76,7 +76,7 @@ template<typename MatrixType> void adjoint(const MatrixType& m)
|
|||||||
|
|
||||||
// check compatibility of dot and adjoint
|
// check compatibility of dot and adjoint
|
||||||
|
|
||||||
ref = NumTraits<Scalar>::IsInteger ? 0 : std::max(std::max(v1.norm(),v2.norm()),std::max((square * v2).norm(),(square.adjoint() * v1).norm()));
|
ref = NumTraits<Scalar>::IsInteger ? 0 : (std::max)((std::max)(v1.norm(),v2.norm()),(std::max)((square * v2).norm(),(square.adjoint() * v1).norm()));
|
||||||
VERIFY(test_isApproxWithRef(v1.dot(square * v2), (square.adjoint() * v1).dot(v2), ref));
|
VERIFY(test_isApproxWithRef(v1.dot(square * v2), (square.adjoint() * v1).dot(v2), ref));
|
||||||
|
|
||||||
// like in testBasicStuff, test operator() to check const-qualification
|
// like in testBasicStuff, test operator() to check const-qualification
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ template<typename MatrixType> void bandmatrix(const MatrixType& _m)
|
|||||||
m.col(i).setConstant(static_cast<RealScalar>(i+1));
|
m.col(i).setConstant(static_cast<RealScalar>(i+1));
|
||||||
dm1.col(i).setConstant(static_cast<RealScalar>(i+1));
|
dm1.col(i).setConstant(static_cast<RealScalar>(i+1));
|
||||||
}
|
}
|
||||||
Index d = std::min(rows,cols);
|
Index d = (std::min)(rows,cols);
|
||||||
Index a = std::max<Index>(0,cols-d-supers);
|
Index a = std::max<Index>(0,cols-d-supers);
|
||||||
Index b = std::max<Index>(0,rows-d-subs);
|
Index b = std::max<Index>(0,rows-d-subs);
|
||||||
if(a>0) dm1.block(0,d+supers,rows,a).setZero();
|
if(a>0) dm1.block(0,d+supers,rows,a).setZero();
|
||||||
|
|||||||
@@ -28,6 +28,14 @@
|
|||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
|
#ifdef min
|
||||||
|
#undef min
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef max
|
||||||
|
#undef max
|
||||||
|
#endif
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
template<typename Scalar> struct AddIfNull {
|
template<typename Scalar> struct AddIfNull {
|
||||||
|
|||||||
@@ -70,11 +70,10 @@ void check_aligned_stack_alloc()
|
|||||||
{
|
{
|
||||||
for(int i = 1; i < 1000; i++)
|
for(int i = 1; i < 1000; i++)
|
||||||
{
|
{
|
||||||
float *p = ei_aligned_stack_new(float,i);
|
ei_declare_aligned_stack_constructed_variable(float,p,i,0);
|
||||||
VERIFY(size_t(p)%ALIGNMENT==0);
|
VERIFY(size_t(p)%ALIGNMENT==0);
|
||||||
// if the buffer is wrongly allocated this will give a bad write --> check with valgrind
|
// if the buffer is wrongly allocated this will give a bad write --> check with valgrind
|
||||||
for(int j = 0; j < i; j++) p[j]=0;
|
for(int j = 0; j < i; j++) p[j]=0;
|
||||||
ei_aligned_stack_delete(float,p,i);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -70,11 +70,10 @@ void check_aligned_stack_alloc()
|
|||||||
{
|
{
|
||||||
for(int i = 1; i < 1000; i++)
|
for(int i = 1; i < 1000; i++)
|
||||||
{
|
{
|
||||||
float *p = ei_aligned_stack_new(float,i);
|
ei_declare_aligned_stack_constructed_variable(float, p, i, 0);
|
||||||
VERIFY(std::size_t(p)%ALIGNMENT==0);
|
VERIFY(std::size_t(p)%ALIGNMENT==0);
|
||||||
// if the buffer is wrongly allocated this will give a bad write --> check with valgrind
|
// if the buffer is wrongly allocated this will give a bad write --> check with valgrind
|
||||||
for(int j = 0; j < i; j++) p[j]=0;
|
for(int j = 0; j < i; j++) p[j]=0;
|
||||||
ei_aligned_stack_delete(float,p,i);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ template<typename MatrixType> void eigensolver(const MatrixType& m)
|
|||||||
VERIFY_IS_APPROX(a * ei1.pseudoEigenvectors(), ei1.pseudoEigenvectors() * ei1.pseudoEigenvalueMatrix());
|
VERIFY_IS_APPROX(a * ei1.pseudoEigenvectors(), ei1.pseudoEigenvectors() * ei1.pseudoEigenvalueMatrix());
|
||||||
VERIFY_IS_APPROX(a.template cast<Complex>() * ei1.eigenvectors(),
|
VERIFY_IS_APPROX(a.template cast<Complex>() * ei1.eigenvectors(),
|
||||||
ei1.eigenvectors() * ei1.eigenvalues().asDiagonal());
|
ei1.eigenvectors() * ei1.eigenvalues().asDiagonal());
|
||||||
|
VERIFY_IS_APPROX(ei1.eigenvectors().colwise().norm(), RealVectorType::Ones(rows).transpose());
|
||||||
VERIFY_IS_APPROX(a.eigenvalues(), ei1.eigenvalues());
|
VERIFY_IS_APPROX(a.eigenvalues(), ei1.eigenvalues());
|
||||||
|
|
||||||
EigenSolver<MatrixType> eiNoEivecs(a, false);
|
EigenSolver<MatrixType> eiNoEivecs(a, false);
|
||||||
|
|||||||
124
test/exceptions.cpp
Normal file
124
test/exceptions.cpp
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
// This file is part of Eigen, a lightweight C++ template library
|
||||||
|
// for linear algebra.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2011 Gael Guennebaud <gael.guennebaud@inria.fr>
|
||||||
|
//
|
||||||
|
// 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/>.
|
||||||
|
|
||||||
|
|
||||||
|
// Various sanity tests with exceptions:
|
||||||
|
// - no memory leak when a custom scalar type trow an exceptions
|
||||||
|
// - todo: complete the list of tests!
|
||||||
|
|
||||||
|
#define EIGEN_STACK_ALLOCATION_LIMIT 100000000
|
||||||
|
|
||||||
|
#include "main.h"
|
||||||
|
|
||||||
|
struct my_exception
|
||||||
|
{
|
||||||
|
my_exception() {}
|
||||||
|
~my_exception() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class ScalarWithExceptions
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ScalarWithExceptions() { init(); }
|
||||||
|
ScalarWithExceptions(const float& _v) { init(); *v = _v; }
|
||||||
|
ScalarWithExceptions(const ScalarWithExceptions& other) { init(); *v = *(other.v); }
|
||||||
|
~ScalarWithExceptions() {
|
||||||
|
delete v;
|
||||||
|
instances--;
|
||||||
|
}
|
||||||
|
|
||||||
|
void init() {
|
||||||
|
v = new float;
|
||||||
|
instances++;
|
||||||
|
}
|
||||||
|
|
||||||
|
ScalarWithExceptions operator+(const ScalarWithExceptions& other) const
|
||||||
|
{
|
||||||
|
countdown--;
|
||||||
|
if(countdown<=0)
|
||||||
|
throw my_exception();
|
||||||
|
return ScalarWithExceptions(*v+*other.v);
|
||||||
|
}
|
||||||
|
|
||||||
|
ScalarWithExceptions operator-(const ScalarWithExceptions& other) const
|
||||||
|
{ return ScalarWithExceptions(*v-*other.v); }
|
||||||
|
|
||||||
|
ScalarWithExceptions operator*(const ScalarWithExceptions& other) const
|
||||||
|
{ return ScalarWithExceptions((*v)*(*other.v)); }
|
||||||
|
|
||||||
|
ScalarWithExceptions& operator+=(const ScalarWithExceptions& other)
|
||||||
|
{ *v+=*other.v; return *this; }
|
||||||
|
ScalarWithExceptions& operator-=(const ScalarWithExceptions& other)
|
||||||
|
{ *v-=*other.v; return *this; }
|
||||||
|
ScalarWithExceptions& operator=(const ScalarWithExceptions& other)
|
||||||
|
{ *v = *(other.v); return *this; }
|
||||||
|
|
||||||
|
bool operator==(const ScalarWithExceptions& other) const
|
||||||
|
{ return *v==*other.v; }
|
||||||
|
bool operator!=(const ScalarWithExceptions& other) const
|
||||||
|
{ return *v!=*other.v; }
|
||||||
|
|
||||||
|
float* v;
|
||||||
|
static int instances;
|
||||||
|
static int countdown;
|
||||||
|
};
|
||||||
|
|
||||||
|
int ScalarWithExceptions::instances = 0;
|
||||||
|
int ScalarWithExceptions::countdown = 0;
|
||||||
|
|
||||||
|
|
||||||
|
#define CHECK_MEMLEAK(OP) { \
|
||||||
|
ScalarWithExceptions::countdown = 100; \
|
||||||
|
int before = ScalarWithExceptions::instances; \
|
||||||
|
bool exception_thrown = false; \
|
||||||
|
try { OP; } \
|
||||||
|
catch (my_exception) { \
|
||||||
|
exception_thrown = true; \
|
||||||
|
VERIFY(ScalarWithExceptions::instances==before && "memory leak detected in " && EIGEN_MAKESTRING(OP)); \
|
||||||
|
} \
|
||||||
|
VERIFY(exception_thrown && " no exception thrown in " && EIGEN_MAKESTRING(OP)); \
|
||||||
|
}
|
||||||
|
|
||||||
|
void memoryleak()
|
||||||
|
{
|
||||||
|
typedef Eigen::Matrix<ScalarWithExceptions,Dynamic,1> VectorType;
|
||||||
|
typedef Eigen::Matrix<ScalarWithExceptions,Dynamic,Dynamic> MatrixType;
|
||||||
|
|
||||||
|
{
|
||||||
|
int n = 50;
|
||||||
|
VectorType v0(n), v1(n);
|
||||||
|
MatrixType m0(n,n), m1(n,n), m2(n,n);
|
||||||
|
v0.setOnes(); v1.setOnes();
|
||||||
|
m0.setOnes(); m1.setOnes(); m2.setOnes();
|
||||||
|
CHECK_MEMLEAK(v0 = m0 * m1 * v1);
|
||||||
|
CHECK_MEMLEAK(m2 = m0 * m1 * m2);
|
||||||
|
CHECK_MEMLEAK((v0+v1).dot(v0+v1));
|
||||||
|
}
|
||||||
|
VERIFY(ScalarWithExceptions::instances==0 && "global memory leak detected in " && EIGEN_MAKESTRING(OP)); \
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_exceptions()
|
||||||
|
{
|
||||||
|
CALL_SUBTEST( memoryleak() );
|
||||||
|
}
|
||||||
@@ -150,8 +150,9 @@ template<typename Scalar> void hyperplane_alignment()
|
|||||||
VERIFY_IS_APPROX(p1->coeffs(), p2->coeffs());
|
VERIFY_IS_APPROX(p1->coeffs(), p2->coeffs());
|
||||||
VERIFY_IS_APPROX(p1->coeffs(), p3->coeffs());
|
VERIFY_IS_APPROX(p1->coeffs(), p3->coeffs());
|
||||||
|
|
||||||
#ifdef EIGEN_VECTORIZE
|
#if defined(EIGEN_VECTORIZE) && EIGEN_ALIGN_STATICALLY
|
||||||
VERIFY_RAISES_ASSERT((::new(reinterpret_cast<void*>(array3u)) Plane3a));
|
if(internal::packet_traits<Scalar>::Vectorizable)
|
||||||
|
VERIFY_RAISES_ASSERT((::new(reinterpret_cast<void*>(array3u)) Plane3a));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -90,8 +90,9 @@ template<typename Scalar> void parametrizedline_alignment()
|
|||||||
VERIFY_IS_APPROX(p1->direction(), p2->direction());
|
VERIFY_IS_APPROX(p1->direction(), p2->direction());
|
||||||
VERIFY_IS_APPROX(p1->direction(), p3->direction());
|
VERIFY_IS_APPROX(p1->direction(), p3->direction());
|
||||||
|
|
||||||
#ifdef EIGEN_VECTORIZE
|
#if defined(EIGEN_VECTORIZE) && EIGEN_ALIGN_STATICALLY
|
||||||
VERIFY_RAISES_ASSERT((::new(reinterpret_cast<void*>(array3u)) Line4a));
|
if(internal::packet_traits<Scalar>::Vectorizable)
|
||||||
|
VERIFY_RAISES_ASSERT((::new(reinterpret_cast<void*>(array3u)) Line4a));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,6 +101,7 @@ void test_geo_parametrizedline()
|
|||||||
for(int i = 0; i < g_repeat; i++) {
|
for(int i = 0; i < g_repeat; i++) {
|
||||||
CALL_SUBTEST_1( parametrizedline(ParametrizedLine<float,2>()) );
|
CALL_SUBTEST_1( parametrizedline(ParametrizedLine<float,2>()) );
|
||||||
CALL_SUBTEST_2( parametrizedline(ParametrizedLine<float,3>()) );
|
CALL_SUBTEST_2( parametrizedline(ParametrizedLine<float,3>()) );
|
||||||
|
CALL_SUBTEST_2( parametrizedline_alignment<float>() );
|
||||||
CALL_SUBTEST_3( parametrizedline(ParametrizedLine<double,4>()) );
|
CALL_SUBTEST_3( parametrizedline(ParametrizedLine<double,4>()) );
|
||||||
CALL_SUBTEST_3( parametrizedline_alignment<double>() );
|
CALL_SUBTEST_3( parametrizedline_alignment<double>() );
|
||||||
CALL_SUBTEST_4( parametrizedline(ParametrizedLine<std::complex<double>,5>()) );
|
CALL_SUBTEST_4( parametrizedline(ParametrizedLine<std::complex<double>,5>()) );
|
||||||
|
|||||||
@@ -125,6 +125,7 @@ template<typename Scalar, int Options> void quaternion(void)
|
|||||||
template<typename Scalar> void mapQuaternion(void){
|
template<typename Scalar> void mapQuaternion(void){
|
||||||
typedef Map<Quaternion<Scalar>, Aligned> MQuaternionA;
|
typedef Map<Quaternion<Scalar>, Aligned> MQuaternionA;
|
||||||
typedef Map<Quaternion<Scalar> > MQuaternionUA;
|
typedef Map<Quaternion<Scalar> > MQuaternionUA;
|
||||||
|
typedef Map<const Quaternion<Scalar> > MCQuaternionUA;
|
||||||
typedef Quaternion<Scalar> Quaternionx;
|
typedef Quaternion<Scalar> Quaternionx;
|
||||||
|
|
||||||
EIGEN_ALIGN16 Scalar array1[4];
|
EIGEN_ALIGN16 Scalar array1[4];
|
||||||
@@ -132,6 +133,7 @@ template<typename Scalar> void mapQuaternion(void){
|
|||||||
EIGEN_ALIGN16 Scalar array3[4+1];
|
EIGEN_ALIGN16 Scalar array3[4+1];
|
||||||
Scalar* array3unaligned = array3+1;
|
Scalar* array3unaligned = array3+1;
|
||||||
|
|
||||||
|
// std::cerr << array1 << " " << array2 << " " << array3 << "\n";
|
||||||
MQuaternionA(array1).coeffs().setRandom();
|
MQuaternionA(array1).coeffs().setRandom();
|
||||||
(MQuaternionA(array2)) = MQuaternionA(array1);
|
(MQuaternionA(array2)) = MQuaternionA(array1);
|
||||||
(MQuaternionUA(array3unaligned)) = MQuaternionA(array1);
|
(MQuaternionUA(array3unaligned)) = MQuaternionA(array1);
|
||||||
@@ -139,11 +141,14 @@ template<typename Scalar> void mapQuaternion(void){
|
|||||||
Quaternionx q1 = MQuaternionA(array1);
|
Quaternionx q1 = MQuaternionA(array1);
|
||||||
Quaternionx q2 = MQuaternionA(array2);
|
Quaternionx q2 = MQuaternionA(array2);
|
||||||
Quaternionx q3 = MQuaternionUA(array3unaligned);
|
Quaternionx q3 = MQuaternionUA(array3unaligned);
|
||||||
|
Quaternionx q4 = MCQuaternionUA(array3unaligned);
|
||||||
|
|
||||||
VERIFY_IS_APPROX(q1.coeffs(), q2.coeffs());
|
VERIFY_IS_APPROX(q1.coeffs(), q2.coeffs());
|
||||||
VERIFY_IS_APPROX(q1.coeffs(), q3.coeffs());
|
VERIFY_IS_APPROX(q1.coeffs(), q3.coeffs());
|
||||||
|
VERIFY_IS_APPROX(q4.coeffs(), q3.coeffs());
|
||||||
#ifdef EIGEN_VECTORIZE
|
#ifdef EIGEN_VECTORIZE
|
||||||
VERIFY_RAISES_ASSERT((MQuaternionA(array3unaligned)));
|
if(internal::packet_traits<Scalar>::Vectorizable)
|
||||||
|
VERIFY_RAISES_ASSERT((MQuaternionA(array3unaligned)));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -166,21 +171,39 @@ template<typename Scalar> void quaternionAlignment(void){
|
|||||||
|
|
||||||
VERIFY_IS_APPROX(q1->coeffs(), q2->coeffs());
|
VERIFY_IS_APPROX(q1->coeffs(), q2->coeffs());
|
||||||
VERIFY_IS_APPROX(q1->coeffs(), q3->coeffs());
|
VERIFY_IS_APPROX(q1->coeffs(), q3->coeffs());
|
||||||
#ifdef EIGEN_VECTORIZE
|
#if defined(EIGEN_VECTORIZE) && EIGEN_ALIGN_STATICALLY
|
||||||
VERIFY_RAISES_ASSERT((::new(reinterpret_cast<void*>(arrayunaligned)) QuaternionA));
|
if(internal::packet_traits<Scalar>::Vectorizable)
|
||||||
|
VERIFY_RAISES_ASSERT((::new(reinterpret_cast<void*>(arrayunaligned)) QuaternionA));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename PlainObjectType> void check_const_correctness(const PlainObjectType&)
|
||||||
|
{
|
||||||
|
// there's a lot that we can't test here while still having this test compile!
|
||||||
|
// the only possible approach would be to run a script trying to compile stuff and checking that it fails.
|
||||||
|
// CMake can help with that.
|
||||||
|
|
||||||
|
// verify that map-to-const don't have LvalueBit
|
||||||
|
typedef typename internal::add_const<PlainObjectType>::type ConstPlainObjectType;
|
||||||
|
VERIFY( !(internal::traits<Map<ConstPlainObjectType> >::Flags & LvalueBit) );
|
||||||
|
VERIFY( !(internal::traits<Map<ConstPlainObjectType, Aligned> >::Flags & LvalueBit) );
|
||||||
|
VERIFY( !(Map<ConstPlainObjectType>::Flags & LvalueBit) );
|
||||||
|
VERIFY( !(Map<ConstPlainObjectType, Aligned>::Flags & LvalueBit) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void test_geo_quaternion()
|
void test_geo_quaternion()
|
||||||
{
|
{
|
||||||
for(int i = 0; i < g_repeat; i++) {
|
for(int i = 0; i < g_repeat; i++) {
|
||||||
CALL_SUBTEST_1(( quaternion<float,AutoAlign>() ));
|
CALL_SUBTEST_1(( quaternion<float,AutoAlign>() ));
|
||||||
|
CALL_SUBTEST_1( check_const_correctness(Quaternionf()) );
|
||||||
CALL_SUBTEST_2(( quaternion<double,AutoAlign>() ));
|
CALL_SUBTEST_2(( quaternion<double,AutoAlign>() ));
|
||||||
|
CALL_SUBTEST_2( check_const_correctness(Quaterniond()) );
|
||||||
CALL_SUBTEST_3(( quaternion<float,DontAlign>() ));
|
CALL_SUBTEST_3(( quaternion<float,DontAlign>() ));
|
||||||
CALL_SUBTEST_4(( quaternion<double,DontAlign>() ));
|
CALL_SUBTEST_4(( quaternion<double,DontAlign>() ));
|
||||||
CALL_SUBTEST_5(( quaternionAlignment<float>() ));
|
CALL_SUBTEST_5(( quaternionAlignment<float>() ));
|
||||||
CALL_SUBTEST_6(( quaternionAlignment<double>() ));
|
CALL_SUBTEST_6(( quaternionAlignment<double>() ));
|
||||||
CALL_SUBTEST( mapQuaternion<float>() );
|
CALL_SUBTEST_1( mapQuaternion<float>() );
|
||||||
CALL_SUBTEST( mapQuaternion<double>() );
|
CALL_SUBTEST_2( mapQuaternion<double>() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -442,8 +442,9 @@ template<typename Scalar> void transform_alignment()
|
|||||||
|
|
||||||
VERIFY_IS_APPROX( (*p1) * (*p1), (*p2)*(*p3));
|
VERIFY_IS_APPROX( (*p1) * (*p1), (*p2)*(*p3));
|
||||||
|
|
||||||
#ifdef EIGEN_VECTORIZE
|
#if defined(EIGEN_VECTORIZE) && EIGEN_ALIGN_STATICALLY
|
||||||
VERIFY_RAISES_ASSERT((::new(reinterpret_cast<void*>(array3u)) Projective3a));
|
if(internal::packet_traits<Scalar>::Vectorizable)
|
||||||
|
VERIFY_RAISES_ASSERT((::new(reinterpret_cast<void*>(array3u)) Projective3a));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -455,7 +456,8 @@ void test_geo_transformations()
|
|||||||
|
|
||||||
CALL_SUBTEST_2(( transformations<float,AffineCompact,AutoAlign>() ));
|
CALL_SUBTEST_2(( transformations<float,AffineCompact,AutoAlign>() ));
|
||||||
CALL_SUBTEST_2(( non_projective_only<float,AffineCompact,AutoAlign>() ));
|
CALL_SUBTEST_2(( non_projective_only<float,AffineCompact,AutoAlign>() ));
|
||||||
|
CALL_SUBTEST_2(( transform_alignment<float>() ));
|
||||||
|
|
||||||
CALL_SUBTEST_3(( transformations<double,Projective,AutoAlign>() ));
|
CALL_SUBTEST_3(( transformations<double,Projective,AutoAlign>() ));
|
||||||
CALL_SUBTEST_3(( transformations<double,Projective,DontAlign>() ));
|
CALL_SUBTEST_3(( transformations<double,Projective,DontAlign>() ));
|
||||||
CALL_SUBTEST_3(( transform_alignment<double>() ));
|
CALL_SUBTEST_3(( transform_alignment<double>() ));
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user