mirror of
https://gitlab.com/libeigen/eigen.git
synced 2026-04-10 11:34:33 +08:00
Compare commits
28 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1c9aa054c7 | ||
|
|
e01d70e94e | ||
|
|
be55ce03e0 | ||
|
|
91b2fa2985 | ||
|
|
f7ddd033e1 | ||
|
|
046850e1d0 | ||
|
|
d7769cc3bd | ||
|
|
459dc4684e | ||
|
|
a60d71b840 | ||
|
|
fb81e4ab79 | ||
|
|
0e42db7cab | ||
|
|
67ce7ee5c4 | ||
|
|
9661180a4d | ||
|
|
ef7230c229 | ||
|
|
1cc2788047 | ||
|
|
7cfcaaf328 | ||
|
|
3745f0808c | ||
|
|
ab2a3e3c1c | ||
|
|
c40006d0b9 | ||
|
|
c1f217bbef | ||
|
|
3e2684986b | ||
|
|
5ed7b37b8f | ||
|
|
009a69fbf4 | ||
|
|
15cebe2ecc | ||
|
|
756024825d | ||
|
|
ec6ca4eae9 | ||
|
|
eb7863ebd0 | ||
|
|
aa0d407f2e |
@@ -66,9 +66,8 @@ struct traits<Block<XprType, BlockRows, BlockCols, InnerPanel> > : traits<XprTyp
|
||||
: ColsAtCompileTime != Dynamic ? int(ColsAtCompileTime)
|
||||
: int(traits<XprType>::MaxColsAtCompileTime),
|
||||
XprTypeIsRowMajor = (int(traits<XprType>::Flags)&RowMajorBit) != 0,
|
||||
IsDense = is_same<StorageKind,Dense>::value,
|
||||
IsRowMajor = (IsDense&&MaxRowsAtCompileTime==1&&MaxColsAtCompileTime!=1) ? 1
|
||||
: (IsDense&&MaxColsAtCompileTime==1&&MaxRowsAtCompileTime!=1) ? 0
|
||||
IsRowMajor = (MaxRowsAtCompileTime==1&&MaxColsAtCompileTime!=1) ? 1
|
||||
: (MaxColsAtCompileTime==1&&MaxRowsAtCompileTime!=1) ? 0
|
||||
: XprTypeIsRowMajor,
|
||||
HasSameStorageOrderAsXprType = (IsRowMajor == XprTypeIsRowMajor),
|
||||
InnerSize = IsRowMajor ? int(ColsAtCompileTime) : int(RowsAtCompileTime),
|
||||
|
||||
@@ -76,12 +76,7 @@ struct CommaInitializer
|
||||
template<typename OtherDerived>
|
||||
CommaInitializer& operator,(const DenseBase<OtherDerived>& other)
|
||||
{
|
||||
if(other.rows()==0)
|
||||
{
|
||||
m_col += other.cols();
|
||||
return *this;
|
||||
}
|
||||
if (m_col==m_xpr.cols())
|
||||
if (m_col==m_xpr.cols() && (other.cols()!=0 || other.rows()!=m_currentBlockRows))
|
||||
{
|
||||
m_row+=m_currentBlockRows;
|
||||
m_col = 0;
|
||||
@@ -89,24 +84,18 @@ struct CommaInitializer
|
||||
eigen_assert(m_row+m_currentBlockRows<=m_xpr.rows()
|
||||
&& "Too many rows passed to comma initializer (operator<<)");
|
||||
}
|
||||
eigen_assert((m_col<m_xpr.cols() || (m_xpr.cols()==0 && m_col==0))
|
||||
eigen_assert((m_col + other.cols() <= m_xpr.cols())
|
||||
&& "Too many coefficients passed to comma initializer (operator<<)");
|
||||
eigen_assert(m_currentBlockRows==other.rows());
|
||||
if (OtherDerived::SizeAtCompileTime != Dynamic)
|
||||
m_xpr.template block<OtherDerived::RowsAtCompileTime != Dynamic ? OtherDerived::RowsAtCompileTime : 1,
|
||||
OtherDerived::ColsAtCompileTime != Dynamic ? OtherDerived::ColsAtCompileTime : 1>
|
||||
(m_row, m_col) = other;
|
||||
else
|
||||
m_xpr.block(m_row, m_col, other.rows(), other.cols()) = other;
|
||||
m_xpr.template block<OtherDerived::RowsAtCompileTime, OtherDerived::ColsAtCompileTime>
|
||||
(m_row, m_col, other.rows(), other.cols()) = other;
|
||||
m_col += other.cols();
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline ~CommaInitializer()
|
||||
{
|
||||
eigen_assert((m_row+m_currentBlockRows) == m_xpr.rows()
|
||||
&& m_col == m_xpr.cols()
|
||||
&& "Too few coefficients passed to comma initializer (operator<<)");
|
||||
finished();
|
||||
}
|
||||
|
||||
/** \returns the built matrix once all its coefficients have been set.
|
||||
@@ -116,7 +105,12 @@ struct CommaInitializer
|
||||
* quaternion.fromRotationMatrix((Matrix3f() << axis0, axis1, axis2).finished());
|
||||
* \endcode
|
||||
*/
|
||||
inline XprType& finished() { return m_xpr; }
|
||||
inline XprType& finished() {
|
||||
eigen_assert(((m_row+m_currentBlockRows) == m_xpr.rows() || m_xpr.cols() == 0)
|
||||
&& m_col == m_xpr.cols()
|
||||
&& "Too few coefficients passed to comma initializer (operator<<)");
|
||||
return m_xpr;
|
||||
}
|
||||
|
||||
XprType& m_xpr; // target expression
|
||||
Index m_row; // current row id
|
||||
|
||||
@@ -969,6 +969,8 @@ template<typename T>
|
||||
struct functor_traits<std::not_equal_to<T> >
|
||||
{ enum { Cost = 1, PacketAccess = false }; };
|
||||
|
||||
#if(__cplusplus < 201103L)
|
||||
// std::binder* are deprecated since c++11 and will be removed in c++17
|
||||
template<typename T>
|
||||
struct functor_traits<std::binder2nd<T> >
|
||||
{ enum { Cost = functor_traits<T>::Cost, PacketAccess = false }; };
|
||||
@@ -976,6 +978,7 @@ struct functor_traits<std::binder2nd<T> >
|
||||
template<typename T>
|
||||
struct functor_traits<std::binder1st<T> >
|
||||
{ enum { Cost = functor_traits<T>::Cost, PacketAccess = false }; };
|
||||
#endif
|
||||
|
||||
template<typename T>
|
||||
struct functor_traits<std::unary_negate<T> >
|
||||
|
||||
@@ -183,8 +183,8 @@ template<typename Scalar, typename Packet> inline void pstoreu(Scalar* to, const
|
||||
/** \internal tries to do cache prefetching of \a addr */
|
||||
template<typename Scalar> inline void prefetch(const Scalar* addr)
|
||||
{
|
||||
#if !defined(_MSC_VER)
|
||||
__builtin_prefetch(addr);
|
||||
#if (!EIGEN_COMP_MSVC) && (EIGEN_COMP_GNUC || EIGEN_COMP_CLANG || EIGEN_COMP_ICC)
|
||||
__builtin_prefetch(addr);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -507,11 +507,24 @@ struct floor_log2<n, lower, upper, floor_log2_bogus>
|
||||
template<typename Scalar>
|
||||
struct random_default_impl<Scalar, false, true>
|
||||
{
|
||||
typedef typename NumTraits<Scalar>::NonInteger NonInteger;
|
||||
|
||||
static inline Scalar run(const Scalar& x, const Scalar& y)
|
||||
{
|
||||
return x + Scalar((NonInteger(y)-x+1) * std::rand() / (RAND_MAX + NonInteger(1)));
|
||||
typedef typename conditional<NumTraits<Scalar>::IsSigned,std::ptrdiff_t,std::size_t>::type ScalarX;
|
||||
if(y<x)
|
||||
return x;
|
||||
// the following difference might overflow on a 32 bits system,
|
||||
// but since y>=x the result converted to an unsigned long is still correct.
|
||||
std::size_t range = ScalarX(y)-ScalarX(x);
|
||||
std::size_t offset = 0;
|
||||
// rejection sampling
|
||||
std::size_t divisor = 1;
|
||||
std::size_t multiplier = 1;
|
||||
if(range<RAND_MAX) divisor = (std::size_t(RAND_MAX)+1)/(range+1);
|
||||
else multiplier = 1 + range/(std::size_t(RAND_MAX)+1);
|
||||
do {
|
||||
offset = (std::size_t(std::rand()) * multiplier) / divisor;
|
||||
} while (offset > range);
|
||||
return Scalar(ScalarX(x) + offset);
|
||||
}
|
||||
|
||||
static inline Scalar run()
|
||||
|
||||
@@ -76,9 +76,23 @@ template<typename MatrixType, int Direction> class Reverse
|
||||
EIGEN_DENSE_PUBLIC_INTERFACE(Reverse)
|
||||
using Base::IsRowMajor;
|
||||
|
||||
// next line is necessary because otherwise const version of operator()
|
||||
// is hidden by non-const version defined in this file
|
||||
using Base::operator();
|
||||
// The following two operators are provided to worarkound
|
||||
// a MSVC 2013 issue. In theory, we could simply do:
|
||||
// using Base::operator();
|
||||
// to make const version of operator() visible.
|
||||
// Otheriwse, they would be hidden by the non-const versions defined in this file
|
||||
|
||||
inline CoeffReturnType operator()(Index row, Index col) const
|
||||
{
|
||||
eigen_assert(row >= 0 && row < rows() && col >= 0 && col < cols());
|
||||
return coeff(row, col);
|
||||
}
|
||||
|
||||
inline CoeffReturnType operator()(Index index) const
|
||||
{
|
||||
eigen_assert(index >= 0 && index < m_matrix.size());
|
||||
return coeff(index);
|
||||
}
|
||||
|
||||
protected:
|
||||
enum {
|
||||
|
||||
@@ -42,16 +42,29 @@ template<bool Conjugate> struct conj_if;
|
||||
|
||||
template<> struct conj_if<true> {
|
||||
template<typename T>
|
||||
inline T operator()(const T& x) { return numext::conj(x); }
|
||||
inline T operator()(const T& x) const { return numext::conj(x); }
|
||||
template<typename T>
|
||||
inline T pconj(const T& x) { return internal::pconj(x); }
|
||||
inline T pconj(const T& x) const { return internal::pconj(x); }
|
||||
};
|
||||
|
||||
template<> struct conj_if<false> {
|
||||
template<typename T>
|
||||
inline const T& operator()(const T& x) { return x; }
|
||||
inline const T& operator()(const T& x) const { return x; }
|
||||
template<typename T>
|
||||
inline const T& pconj(const T& x) { return x; }
|
||||
inline const T& pconj(const T& x) const { return x; }
|
||||
};
|
||||
|
||||
// Generic implementation for custom complex types.
|
||||
template<typename LhsScalar, typename RhsScalar, bool ConjLhs, bool ConjRhs>
|
||||
struct conj_helper
|
||||
{
|
||||
typedef typename scalar_product_traits<LhsScalar,RhsScalar>::ReturnType Scalar;
|
||||
|
||||
EIGEN_STRONG_INLINE Scalar pmadd(const LhsScalar& x, const RhsScalar& y, const Scalar& c) const
|
||||
{ return padd(c, pmul(x,y)); }
|
||||
|
||||
EIGEN_STRONG_INLINE Scalar pmul(const LhsScalar& x, const RhsScalar& y) const
|
||||
{ return conj_if<ConjLhs>()(x) * conj_if<ConjRhs>()(y); }
|
||||
};
|
||||
|
||||
template<typename Scalar> struct conj_helper<Scalar,Scalar,false,false>
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
#define EIGEN_WORLD_VERSION 3
|
||||
#define EIGEN_MAJOR_VERSION 2
|
||||
#define EIGEN_MINOR_VERSION 9
|
||||
#define EIGEN_MINOR_VERSION 10
|
||||
|
||||
#define EIGEN_VERSION_AT_LEAST(x,y,z) (EIGEN_WORLD_VERSION>x || (EIGEN_WORLD_VERSION>=x && \
|
||||
(EIGEN_MAJOR_VERSION>y || (EIGEN_MAJOR_VERSION>=y && \
|
||||
|
||||
@@ -443,7 +443,7 @@ public:
|
||||
operator * (const DiagonalBase<DiagonalDerived> &b) const
|
||||
{
|
||||
TransformTimeDiagonalReturnType res(*this);
|
||||
res.linear() *= b;
|
||||
res.linearExt() *= b;
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -557,7 +557,7 @@ public:
|
||||
return res;
|
||||
}
|
||||
|
||||
inline Transform& operator*=(const DiagonalMatrix<Scalar,Dim>& s) { linear() *= s; return *this; }
|
||||
inline Transform& operator*=(const DiagonalMatrix<Scalar,Dim>& s) { linearExt() *= s; return *this; }
|
||||
|
||||
template<typename Derived>
|
||||
inline Transform& operator=(const RotationBase<Derived,Dim>& r);
|
||||
@@ -828,7 +828,7 @@ Transform<Scalar,Dim,Mode,Options>::prescale(const MatrixBase<OtherDerived> &oth
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim))
|
||||
EIGEN_STATIC_ASSERT(Mode!=int(Isometry), THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS)
|
||||
m_matrix.template block<Dim,HDim>(0,0).noalias() = (other.asDiagonal() * m_matrix.template block<Dim,HDim>(0,0));
|
||||
affine().noalias() = (other.asDiagonal() * affine());
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -1048,7 +1048,7 @@ void Transform<Scalar,Dim,Mode,Options>::computeRotationScaling(RotationMatrixTy
|
||||
}
|
||||
}
|
||||
|
||||
/** decomposes the linear part of the transformation as a product rotation x scaling, the scaling being
|
||||
/** decomposes the linear part of the transformation as a product scaling x rotation, the scaling being
|
||||
* not necessarily positive.
|
||||
*
|
||||
* If either pointer is zero, the corresponding computation is skipped.
|
||||
|
||||
@@ -130,8 +130,10 @@ public:
|
||||
}
|
||||
|
||||
/** Applies translation to vector */
|
||||
inline VectorType operator* (const VectorType& other) const
|
||||
{ return m_coeffs + other; }
|
||||
template<typename Derived>
|
||||
inline typename internal::enable_if<Derived::IsVectorAtCompileTime,VectorType>::type
|
||||
operator* (const MatrixBase<Derived>& vec) const
|
||||
{ return m_coeffs + vec.derived(); }
|
||||
|
||||
/** \returns the inverse translation (opposite) */
|
||||
Translation inverse() const { return Translation(-m_coeffs); }
|
||||
|
||||
@@ -151,10 +151,12 @@ struct compute_inverse_size4<Architecture::SSE, float, MatrixType, ResultType>
|
||||
iC = _mm_mul_ps(rd,iC);
|
||||
iD = _mm_mul_ps(rd,iD);
|
||||
|
||||
result.template writePacket<ResultAlignment>( 0, _mm_shuffle_ps(iA,iB,0x77));
|
||||
result.template writePacket<ResultAlignment>( 4, _mm_shuffle_ps(iA,iB,0x22));
|
||||
result.template writePacket<ResultAlignment>( 8, _mm_shuffle_ps(iC,iD,0x77));
|
||||
result.template writePacket<ResultAlignment>(12, _mm_shuffle_ps(iC,iD,0x22));
|
||||
DenseIndex res_stride = result.outerStride();
|
||||
float* res = result.data();
|
||||
pstoret<float, Packet4f, ResultAlignment>(res+0, _mm_shuffle_ps(iA,iB,0x77));
|
||||
pstoret<float, Packet4f, ResultAlignment>(res+res_stride, _mm_shuffle_ps(iA,iB,0x22));
|
||||
pstoret<float, Packet4f, ResultAlignment>(res+2*res_stride, _mm_shuffle_ps(iC,iD,0x77));
|
||||
pstoret<float, Packet4f, ResultAlignment>(res+3*res_stride, _mm_shuffle_ps(iC,iD,0x22));
|
||||
}
|
||||
|
||||
};
|
||||
@@ -311,14 +313,16 @@ struct compute_inverse_size4<Architecture::SSE, double, MatrixType, ResultType>
|
||||
iC1 = _mm_sub_pd(_mm_mul_pd(B1, dC), iC1);
|
||||
iC2 = _mm_sub_pd(_mm_mul_pd(B2, dC), iC2);
|
||||
|
||||
result.template writePacket<ResultAlignment>( 0, _mm_mul_pd(_mm_shuffle_pd(iA2, iA1, 3), d1)); // iA# / det
|
||||
result.template writePacket<ResultAlignment>( 4, _mm_mul_pd(_mm_shuffle_pd(iA2, iA1, 0), d2));
|
||||
result.template writePacket<ResultAlignment>( 2, _mm_mul_pd(_mm_shuffle_pd(iB2, iB1, 3), d1)); // iB# / det
|
||||
result.template writePacket<ResultAlignment>( 6, _mm_mul_pd(_mm_shuffle_pd(iB2, iB1, 0), d2));
|
||||
result.template writePacket<ResultAlignment>( 8, _mm_mul_pd(_mm_shuffle_pd(iC2, iC1, 3), d1)); // iC# / det
|
||||
result.template writePacket<ResultAlignment>(12, _mm_mul_pd(_mm_shuffle_pd(iC2, iC1, 0), d2));
|
||||
result.template writePacket<ResultAlignment>(10, _mm_mul_pd(_mm_shuffle_pd(iD2, iD1, 3), d1)); // iD# / det
|
||||
result.template writePacket<ResultAlignment>(14, _mm_mul_pd(_mm_shuffle_pd(iD2, iD1, 0), d2));
|
||||
DenseIndex res_stride = result.outerStride();
|
||||
double* res = result.data();
|
||||
pstoret<double, Packet2d, ResultAlignment>(res+0, _mm_mul_pd(_mm_shuffle_pd(iA2, iA1, 3), d1));
|
||||
pstoret<double, Packet2d, ResultAlignment>(res+res_stride, _mm_mul_pd(_mm_shuffle_pd(iA2, iA1, 0), d2));
|
||||
pstoret<double, Packet2d, ResultAlignment>(res+2, _mm_mul_pd(_mm_shuffle_pd(iB2, iB1, 3), d1));
|
||||
pstoret<double, Packet2d, ResultAlignment>(res+res_stride+2, _mm_mul_pd(_mm_shuffle_pd(iB2, iB1, 0), d2));
|
||||
pstoret<double, Packet2d, ResultAlignment>(res+2*res_stride, _mm_mul_pd(_mm_shuffle_pd(iC2, iC1, 3), d1));
|
||||
pstoret<double, Packet2d, ResultAlignment>(res+3*res_stride, _mm_mul_pd(_mm_shuffle_pd(iC2, iC1, 0), d2));
|
||||
pstoret<double, Packet2d, ResultAlignment>(res+2*res_stride+2,_mm_mul_pd(_mm_shuffle_pd(iD2, iD1, 3), d1));
|
||||
pstoret<double, Packet2d, ResultAlignment>(res+3*res_stride+2,_mm_mul_pd(_mm_shuffle_pd(iD2, iD1, 0), d2));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -127,9 +127,6 @@ template<typename _MatrixType> class ColPivHouseholderQR
|
||||
*
|
||||
* \returns a solution.
|
||||
*
|
||||
* \note The case where b is a matrix is not yet implemented. Also, this
|
||||
* code is space inefficient.
|
||||
*
|
||||
* \note_about_checking_solutions
|
||||
*
|
||||
* \note_about_arbitrary_choice_of_solution
|
||||
|
||||
@@ -134,9 +134,6 @@ template<typename _MatrixType> class FullPivHouseholderQR
|
||||
* \returns the exact or least-square solution if the rank is greater or equal to the number of columns of A,
|
||||
* and an arbitrary solution otherwise.
|
||||
*
|
||||
* \note The case where b is a matrix is not yet implemented. Also, this
|
||||
* code is space inefficient.
|
||||
*
|
||||
* \note_about_checking_solutions
|
||||
*
|
||||
* \note_about_arbitrary_choice_of_solution
|
||||
|
||||
@@ -107,9 +107,6 @@ template<typename _MatrixType> class HouseholderQR
|
||||
*
|
||||
* \returns a solution.
|
||||
*
|
||||
* \note The case where b is a matrix is not yet implemented. Also, this
|
||||
* code is space inefficient.
|
||||
*
|
||||
* \note_about_checking_solutions
|
||||
*
|
||||
* \note_about_arbitrary_choice_of_solution
|
||||
|
||||
@@ -16,11 +16,11 @@ template<typename XprType, int BlockRows, int BlockCols>
|
||||
class BlockImpl<XprType,BlockRows,BlockCols,true,Sparse>
|
||||
: public SparseMatrixBase<Block<XprType,BlockRows,BlockCols,true> >
|
||||
{
|
||||
typedef typename internal::remove_all<typename XprType::Nested>::type _MatrixTypeNested;
|
||||
typedef Block<XprType, BlockRows, BlockCols, true> BlockType;
|
||||
public:
|
||||
typedef Block<XprType, BlockRows, BlockCols, true> BlockType;
|
||||
enum { IsRowMajor = internal::traits<BlockType>::IsRowMajor };
|
||||
protected:
|
||||
typedef typename internal::remove_all<typename XprType::Nested>::type _MatrixTypeNested;
|
||||
enum { OuterSize = IsRowMajor ? BlockRows : BlockCols };
|
||||
public:
|
||||
EIGEN_SPARSE_PUBLIC_INTERFACE(BlockType)
|
||||
@@ -29,13 +29,13 @@ public:
|
||||
{
|
||||
typedef typename BlockImpl::Index Index;
|
||||
public:
|
||||
inline InnerIterator(const BlockType& xpr, Index outer)
|
||||
inline InnerIterator(const Block<XprType, BlockRows, BlockCols, true>& xpr, Index outer)
|
||||
: XprType::InnerIterator(xpr.m_matrix, xpr.m_outerStart + outer), m_outer(outer)
|
||||
{}
|
||||
inline Index row() const { return IsRowMajor ? m_outer : this->index(); }
|
||||
inline Index col() const { return IsRowMajor ? this->index() : m_outer; }
|
||||
protected:
|
||||
Index m_outer;
|
||||
Index m_outer;
|
||||
};
|
||||
class ReverseInnerIterator: public XprType::ReverseInnerIterator
|
||||
{
|
||||
@@ -93,9 +93,9 @@ class BlockImpl<SparseMatrix<_Scalar, _Options, _Index>,BlockRows,BlockCols,true
|
||||
{
|
||||
typedef SparseMatrix<_Scalar, _Options, _Index> SparseMatrixType;
|
||||
typedef typename internal::remove_all<typename SparseMatrixType::Nested>::type _MatrixTypeNested;
|
||||
typedef Block<SparseMatrixType, BlockRows, BlockCols, true> BlockType;
|
||||
typedef Block<const SparseMatrixType, BlockRows, BlockCols, true> ConstBlockType;
|
||||
public:
|
||||
typedef Block<SparseMatrixType, BlockRows, BlockCols, true> BlockType;
|
||||
enum { IsRowMajor = internal::traits<BlockType>::IsRowMajor };
|
||||
EIGEN_SPARSE_PUBLIC_INTERFACE(BlockType)
|
||||
protected:
|
||||
@@ -280,8 +280,8 @@ class BlockImpl<const SparseMatrix<_Scalar, _Options, _Index>,BlockRows,BlockCol
|
||||
{
|
||||
typedef SparseMatrix<_Scalar, _Options, _Index> SparseMatrixType;
|
||||
typedef typename internal::remove_all<typename SparseMatrixType::Nested>::type _MatrixTypeNested;
|
||||
typedef Block<const SparseMatrixType, BlockRows, BlockCols, true> BlockType;
|
||||
public:
|
||||
typedef Block<const SparseMatrixType, BlockRows, BlockCols, true> BlockType;
|
||||
enum { IsRowMajor = internal::traits<BlockType>::IsRowMajor };
|
||||
EIGEN_SPARSE_PUBLIC_INTERFACE(BlockType)
|
||||
protected:
|
||||
@@ -413,6 +413,14 @@ SparseMatrixBase<Derived>::innerVectors(Index outerStart, Index outerSize) const
|
||||
|
||||
}
|
||||
|
||||
namespace internal {
|
||||
|
||||
template< typename XprType, int BlockRows, int BlockCols, bool InnerPanel,
|
||||
bool OuterVector = (BlockCols==1 && XprType::IsRowMajor) || (BlockRows==1 && !XprType::IsRowMajor)>
|
||||
class GenericSparseBlockInnerIteratorImpl;
|
||||
|
||||
}
|
||||
|
||||
/** Generic implementation of sparse Block expression.
|
||||
* Real-only.
|
||||
*/
|
||||
@@ -420,9 +428,9 @@ template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel>
|
||||
class BlockImpl<XprType,BlockRows,BlockCols,InnerPanel,Sparse>
|
||||
: public SparseMatrixBase<Block<XprType,BlockRows,BlockCols,InnerPanel> >, internal::no_assignment_operator
|
||||
{
|
||||
typedef typename internal::remove_all<typename XprType::Nested>::type _MatrixTypeNested;
|
||||
typedef Block<XprType, BlockRows, BlockCols, InnerPanel> BlockType;
|
||||
public:
|
||||
typedef typename internal::remove_all<typename XprType::Nested>::type _MatrixTypeNested;
|
||||
public:
|
||||
typedef Block<XprType, BlockRows, BlockCols, InnerPanel> BlockType;
|
||||
enum { IsRowMajor = internal::traits<BlockType>::IsRowMajor };
|
||||
EIGEN_SPARSE_PUBLIC_INTERFACE(BlockType)
|
||||
|
||||
@@ -472,29 +480,8 @@ public:
|
||||
|
||||
inline const _MatrixTypeNested& nestedExpression() const { return m_matrix; }
|
||||
|
||||
class InnerIterator : public _MatrixTypeNested::InnerIterator
|
||||
{
|
||||
typedef typename _MatrixTypeNested::InnerIterator Base;
|
||||
const BlockType& m_block;
|
||||
Index m_end;
|
||||
public:
|
||||
|
||||
EIGEN_STRONG_INLINE InnerIterator(const BlockType& block, Index outer)
|
||||
: Base(block.derived().nestedExpression(), outer + (IsRowMajor ? block.m_startRow.value() : block.m_startCol.value())),
|
||||
m_block(block),
|
||||
m_end(IsRowMajor ? block.m_startCol.value()+block.m_blockCols.value() : block.m_startRow.value()+block.m_blockRows.value())
|
||||
{
|
||||
while( (Base::operator bool()) && (Base::index() < (IsRowMajor ? m_block.m_startCol.value() : m_block.m_startRow.value())) )
|
||||
Base::operator++();
|
||||
}
|
||||
|
||||
inline Index index() const { return Base::index() - (IsRowMajor ? m_block.m_startCol.value() : m_block.m_startRow.value()); }
|
||||
inline Index outer() const { return Base::outer() - (IsRowMajor ? m_block.m_startRow.value() : m_block.m_startCol.value()); }
|
||||
inline Index row() const { return Base::row() - m_block.m_startRow.value(); }
|
||||
inline Index col() const { return Base::col() - m_block.m_startCol.value(); }
|
||||
|
||||
inline operator bool() const { return Base::operator bool() && Base::index() < m_end; }
|
||||
};
|
||||
typedef internal::GenericSparseBlockInnerIteratorImpl<XprType,BlockRows,BlockCols,InnerPanel> InnerIterator;
|
||||
|
||||
class ReverseInnerIterator : public _MatrixTypeNested::ReverseInnerIterator
|
||||
{
|
||||
typedef typename _MatrixTypeNested::ReverseInnerIterator Base;
|
||||
@@ -519,7 +506,7 @@ public:
|
||||
inline operator bool() const { return Base::operator bool() && Base::index() >= m_begin; }
|
||||
};
|
||||
protected:
|
||||
friend class InnerIterator;
|
||||
friend class internal::GenericSparseBlockInnerIteratorImpl<XprType,BlockRows,BlockCols,InnerPanel>;
|
||||
friend class ReverseInnerIterator;
|
||||
|
||||
EIGEN_INHERIT_ASSIGNMENT_OPERATORS(BlockImpl)
|
||||
@@ -533,6 +520,104 @@ public:
|
||||
Index nonZeros() const;
|
||||
};
|
||||
|
||||
namespace internal {
|
||||
template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel>
|
||||
class GenericSparseBlockInnerIteratorImpl<XprType,BlockRows,BlockCols,InnerPanel,false> : public internal::remove_all<typename XprType::Nested>::type::InnerIterator
|
||||
{
|
||||
public:
|
||||
typedef Block<XprType, BlockRows, BlockCols, InnerPanel> BlockType;
|
||||
enum {
|
||||
IsRowMajor = BlockType::IsRowMajor
|
||||
};
|
||||
typedef typename BlockType::Index Index;
|
||||
protected:
|
||||
typedef typename internal::remove_all<typename XprType::Nested>::type _MatrixTypeNested;
|
||||
typedef typename _MatrixTypeNested::InnerIterator Base;
|
||||
const BlockType& m_block;
|
||||
Index m_end;
|
||||
public:
|
||||
|
||||
EIGEN_STRONG_INLINE GenericSparseBlockInnerIteratorImpl(const BlockType& block, Index outer)
|
||||
: Base(block.derived().nestedExpression(), outer + (IsRowMajor ? block.m_startRow.value() : block.m_startCol.value())),
|
||||
m_block(block),
|
||||
m_end(IsRowMajor ? block.m_startCol.value()+block.m_blockCols.value() : block.m_startRow.value()+block.m_blockRows.value())
|
||||
{
|
||||
while( (Base::operator bool()) && (Base::index() < (IsRowMajor ? m_block.m_startCol.value() : m_block.m_startRow.value())) )
|
||||
Base::operator++();
|
||||
}
|
||||
|
||||
inline Index index() const { return Base::index() - (IsRowMajor ? m_block.m_startCol.value() : m_block.m_startRow.value()); }
|
||||
inline Index outer() const { return Base::outer() - (IsRowMajor ? m_block.m_startRow.value() : m_block.m_startCol.value()); }
|
||||
inline Index row() const { return Base::row() - m_block.m_startRow.value(); }
|
||||
inline Index col() const { return Base::col() - m_block.m_startCol.value(); }
|
||||
|
||||
inline operator bool() const { return Base::operator bool() && Base::index() < m_end; }
|
||||
};
|
||||
|
||||
// Row vector of a column-major sparse matrix or column of a row-major one.
|
||||
template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel>
|
||||
class GenericSparseBlockInnerIteratorImpl<XprType,BlockRows,BlockCols,InnerPanel,true>
|
||||
{
|
||||
public:
|
||||
typedef Block<XprType, BlockRows, BlockCols, InnerPanel> BlockType;
|
||||
enum {
|
||||
IsRowMajor = BlockType::IsRowMajor
|
||||
};
|
||||
typedef typename BlockType::Index Index;
|
||||
typedef typename BlockType::Scalar Scalar;
|
||||
protected:
|
||||
typedef typename internal::remove_all<typename XprType::Nested>::type _MatrixTypeNested;
|
||||
const BlockType& m_block;
|
||||
Index m_outerPos;
|
||||
Index m_innerIndex;
|
||||
Scalar m_value;
|
||||
Index m_end;
|
||||
public:
|
||||
|
||||
EIGEN_STRONG_INLINE GenericSparseBlockInnerIteratorImpl(const BlockType& block, Index outer = 0)
|
||||
:
|
||||
m_block(block),
|
||||
m_outerPos( (IsRowMajor ? block.m_startCol.value() : block.m_startRow.value()) - 1), // -1 so that operator++ finds the first non-zero entry
|
||||
m_innerIndex(IsRowMajor ? block.m_startRow.value() : block.m_startCol.value()),
|
||||
m_end(IsRowMajor ? block.m_startCol.value()+block.m_blockCols.value() : block.m_startRow.value()+block.m_blockRows.value())
|
||||
{
|
||||
EIGEN_UNUSED_VARIABLE(outer);
|
||||
eigen_assert(outer==0);
|
||||
|
||||
++(*this);
|
||||
}
|
||||
|
||||
inline Index index() const { return m_outerPos - (IsRowMajor ? m_block.m_startCol.value() : m_block.m_startRow.value()); }
|
||||
inline Index outer() const { return 0; }
|
||||
inline Index row() const { return IsRowMajor ? 0 : index(); }
|
||||
inline Index col() const { return IsRowMajor ? index() : 0; }
|
||||
|
||||
inline Scalar value() const { return m_value; }
|
||||
|
||||
inline GenericSparseBlockInnerIteratorImpl& operator++()
|
||||
{
|
||||
// search next non-zero entry
|
||||
while(m_outerPos<m_end)
|
||||
{
|
||||
m_outerPos++;
|
||||
typename XprType::InnerIterator it(m_block.m_matrix, m_outerPos);
|
||||
// search for the key m_innerIndex in the current outer-vector
|
||||
while(it && it.index() < m_innerIndex) ++it;
|
||||
if(it && it.index()==m_innerIndex)
|
||||
{
|
||||
m_value = it.value();
|
||||
break;
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline operator bool() const { return m_outerPos < m_end; }
|
||||
};
|
||||
|
||||
} // end namespace internal
|
||||
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // EIGEN_SPARSE_BLOCK_H
|
||||
|
||||
@@ -148,7 +148,8 @@ class UmfPackLU : internal::noncopyable
|
||||
|
||||
UmfPackLU() { init(); }
|
||||
|
||||
UmfPackLU(const MatrixType& matrix)
|
||||
template<typename InputMatrixType>
|
||||
UmfPackLU(const InputMatrixType& matrix)
|
||||
{
|
||||
init();
|
||||
compute(matrix);
|
||||
|
||||
@@ -46,6 +46,9 @@ They are summarized in the following table:
|
||||
<tr><td>SPQR</td><td>\link SPQRSupport_Module SPQRSupport \endlink </td> <td> QR factorization </td>
|
||||
<td> Any, rectangular</td><td>fill-in reducing, multithreaded, fast dense algebra</td>
|
||||
<td> requires the <a href="http://www.suitesparse.com">SuiteSparse</a> package, \b GPL </td><td>recommended for linear least-squares problems, has a rank-revealing feature</tr>
|
||||
<tr><td>PardisoLLT \n PardisoLDLT \n PardisoLU</td><td>\link PardisoSupport_Module PardisoSupport \endlink</td><td>Direct LLt, LDLt, LU factorizations</td><td>SPD \n SPD \n Square</td><td>Fill-in reducing, Leverage fast dense algebra, Multithreading</td>
|
||||
<td>Requires the <a href="http://eigen.tuxfamily.org/Counter/redirect_to_mkl.php">Intel MKL</a> package, \b Proprietary </td>
|
||||
<td>optimized for tough problems patterns, see also \link TopicUsingIntelMKL using MKL with Eigen \endlink</td></tr>
|
||||
</table>
|
||||
|
||||
Here \c SPD means symmetric positive definite.
|
||||
|
||||
@@ -16,7 +16,7 @@ Both eigen_assert and eigen_plain_assert are defined in Macros.h. Defining eigen
|
||||
#include <stdexcept>
|
||||
#undef eigen_assert
|
||||
#define eigen_assert(x) \
|
||||
if (!x) { throw (std::runtime_error("Put your message here")); }
|
||||
if (!(x)) { throw (std::runtime_error("Put your message here")); }
|
||||
\endcode
|
||||
|
||||
\subsection DisableAssert Disabling assertions
|
||||
|
||||
@@ -125,6 +125,7 @@ endif(TEST_LIB)
|
||||
set_property(GLOBAL PROPERTY EIGEN_CURRENT_SUBPROJECT "Official")
|
||||
add_custom_target(BuildOfficial)
|
||||
|
||||
ei_add_test(rand)
|
||||
ei_add_test(meta)
|
||||
ei_add_test(sizeof)
|
||||
ei_add_test(dynalloc)
|
||||
|
||||
@@ -9,14 +9,69 @@
|
||||
|
||||
#include "main.h"
|
||||
|
||||
|
||||
template<int M1, int M2, int N1, int N2>
|
||||
void test_blocks()
|
||||
{
|
||||
Matrix<int, M1+M2, N1+N2> m_fixed;
|
||||
MatrixXi m_dynamic(M1+M2, N1+N2);
|
||||
|
||||
Matrix<int, M1, N1> mat11; mat11.setRandom();
|
||||
Matrix<int, M1, N2> mat12; mat12.setRandom();
|
||||
Matrix<int, M2, N1> mat21; mat21.setRandom();
|
||||
Matrix<int, M2, N2> mat22; mat22.setRandom();
|
||||
|
||||
MatrixXi matx11 = mat11, matx12 = mat12, matx21 = mat21, matx22 = mat22;
|
||||
|
||||
{
|
||||
VERIFY_IS_EQUAL((m_fixed << mat11, mat12, mat21, matx22).finished(), (m_dynamic << mat11, matx12, mat21, matx22).finished());
|
||||
VERIFY_IS_EQUAL((m_fixed.template topLeftCorner<M1,N1>()), mat11);
|
||||
VERIFY_IS_EQUAL((m_fixed.template topRightCorner<M1,N2>()), mat12);
|
||||
VERIFY_IS_EQUAL((m_fixed.template bottomLeftCorner<M2,N1>()), mat21);
|
||||
VERIFY_IS_EQUAL((m_fixed.template bottomRightCorner<M2,N2>()), mat22);
|
||||
VERIFY_IS_EQUAL((m_fixed << mat12, mat11, matx21, mat22).finished(), (m_dynamic << mat12, matx11, matx21, mat22).finished());
|
||||
}
|
||||
|
||||
if(N1 > 0)
|
||||
{
|
||||
VERIFY_RAISES_ASSERT((m_fixed << mat11, mat12, mat11, mat21, mat22));
|
||||
VERIFY_RAISES_ASSERT((m_fixed << mat11, mat12, mat21, mat21, mat22));
|
||||
}
|
||||
else
|
||||
{
|
||||
// allow insertion of zero-column blocks:
|
||||
VERIFY_IS_EQUAL((m_fixed << mat11, mat12, mat11, mat11, mat21, mat21, mat22).finished(), (m_dynamic << mat12, mat22).finished());
|
||||
}
|
||||
if(M1 != M2)
|
||||
{
|
||||
VERIFY_RAISES_ASSERT((m_fixed << mat11, mat21, mat12, mat22));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<int N>
|
||||
struct test_block_recursion
|
||||
{
|
||||
static void run()
|
||||
{
|
||||
test_blocks<(N>>6)&3, (N>>4)&3, (N>>2)&3, N & 3>();
|
||||
test_block_recursion<N-1>::run();
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct test_block_recursion<-1>
|
||||
{
|
||||
static void run() { }
|
||||
};
|
||||
|
||||
void test_commainitializer()
|
||||
{
|
||||
Matrix3d m3;
|
||||
Matrix4d m4;
|
||||
|
||||
VERIFY_RAISES_ASSERT( (m3 << 1, 2, 3, 4, 5, 6, 7, 8) );
|
||||
|
||||
#ifndef _MSC_VER
|
||||
VERIFY_RAISES_ASSERT( (m3 << 1, 2, 3, 4, 5, 6, 7, 8) );
|
||||
VERIFY_RAISES_ASSERT( (m3 << 1, 2, 3, 4, 5, 6, 7, 8, 9, 10) );
|
||||
#endif
|
||||
|
||||
@@ -44,4 +99,6 @@ void test_commainitializer()
|
||||
vec[2].transpose();
|
||||
VERIFY_IS_APPROX(m3, ref);
|
||||
|
||||
// recursively test all block-sizes from 0 to 3:
|
||||
test_block_recursion<(1<<8) - 1>();
|
||||
}
|
||||
|
||||
@@ -164,9 +164,12 @@ template<typename MatrixType> void cwiseops(const MatrixType& m)
|
||||
VERIFY( (m1.cwise().min(m2).cwise() < (m1+mones)).all() );
|
||||
VERIFY( (m1.cwise().max(m2).cwise() > (m1-mones)).all() );
|
||||
|
||||
#if(__cplusplus < 201103L)
|
||||
// std::binder* are deprecated since c++11 and will be removed in c++17
|
||||
VERIFY( (m1.cwise()<m1.unaryExpr(bind2nd(plus<Scalar>(), Scalar(1)))).all() );
|
||||
VERIFY( !(m1.cwise()<m1bis.unaryExpr(bind2nd(minus<Scalar>(), Scalar(1)))).all() );
|
||||
VERIFY( !(m1.cwise()>m1bis.unaryExpr(bind2nd(plus<Scalar>(), Scalar(1)))).any() );
|
||||
#endif
|
||||
|
||||
cwiseops_real_only(m1, m2, m3, mones);
|
||||
}
|
||||
|
||||
@@ -137,9 +137,12 @@ template<typename MatrixType> void cwiseops(const MatrixType& m)
|
||||
VERIFY( (m1.cwise().min(m2).cwise() < (m1+mones)).all() );
|
||||
VERIFY( (m1.cwise().max(m2).cwise() > (m1-mones)).all() );
|
||||
|
||||
#if(__cplusplus < 201103L)
|
||||
// std::binder* are deprecated since c++11 and will be removed in c++17
|
||||
VERIFY( (m1.cwise()<m1.unaryExpr(bind2nd(plus<Scalar>(), Scalar(1)))).all() );
|
||||
VERIFY( !(m1.cwise()<m1.unaryExpr(bind2nd(minus<Scalar>(), Scalar(1)))).all() );
|
||||
VERIFY( !(m1.cwise()>m1.unaryExpr(bind2nd(plus<Scalar>(), Scalar(1)))).any() );
|
||||
#endif
|
||||
}
|
||||
|
||||
void test_eigen2_cwiseop()
|
||||
|
||||
@@ -320,6 +320,9 @@ template<typename Scalar, int Mode, int Options> void transformations()
|
||||
t0.scale(v0);
|
||||
t1 *= AlignedScaling3(v0);
|
||||
VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
|
||||
t1 = AlignedScaling3(v0) * (Translation3(v0) * Transform3(q1));
|
||||
t1 = t1 * v0.asDiagonal();
|
||||
VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
|
||||
// transformation * translation
|
||||
t0.translate(v0);
|
||||
t1 = t1 * Translation3(v0);
|
||||
@@ -437,6 +440,79 @@ template<typename Scalar, int Mode, int Options> void transformations()
|
||||
Rotation2D<Scalar> r2(r1); // copy ctor
|
||||
VERIFY_IS_APPROX(r2.angle(),s0);
|
||||
}
|
||||
|
||||
{
|
||||
Transform3 t32(Matrix4::Random()), t33, t34;
|
||||
t34 = t33 = t32;
|
||||
t32.scale(v0);
|
||||
t33*=AlignedScaling3(v0);
|
||||
VERIFY_IS_APPROX(t32.matrix(), t33.matrix());
|
||||
t33 = t34 * AlignedScaling3(v0);
|
||||
VERIFY_IS_APPROX(t32.matrix(), t33.matrix());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template<typename A1, typename A2, typename P, typename Q, typename V, typename H>
|
||||
void transform_associativity_left(const A1& a1, const A2& a2, const P& p, const Q& q, const V& v, const H& h)
|
||||
{
|
||||
VERIFY_IS_APPROX( q*(a1*v), (q*a1)*v );
|
||||
VERIFY_IS_APPROX( q*(a2*v), (q*a2)*v );
|
||||
VERIFY_IS_APPROX( q*(p*h).hnormalized(), ((q*p)*h).hnormalized() );
|
||||
}
|
||||
|
||||
template<typename A1, typename A2, typename P, typename Q, typename V, typename H>
|
||||
void transform_associativity2(const A1& a1, const A2& a2, const P& p, const Q& q, const V& v, const H& h)
|
||||
{
|
||||
VERIFY_IS_APPROX( a1*(q*v), (a1*q)*v );
|
||||
VERIFY_IS_APPROX( a2*(q*v), (a2*q)*v );
|
||||
VERIFY_IS_APPROX( p *(q*v).homogeneous(), (p *q)*v.homogeneous() );
|
||||
|
||||
transform_associativity_left(a1, a2,p, q, v, h);
|
||||
}
|
||||
|
||||
template<typename Scalar, int Dim, int Options,typename RotationType>
|
||||
void transform_associativity(const RotationType& R)
|
||||
{
|
||||
typedef Matrix<Scalar,Dim,1> VectorType;
|
||||
typedef Matrix<Scalar,Dim+1,1> HVectorType;
|
||||
typedef Matrix<Scalar,Dim,Dim> LinearType;
|
||||
typedef Matrix<Scalar,Dim+1,Dim+1> MatrixType;
|
||||
typedef Transform<Scalar,Dim,AffineCompact,Options> AffineCompactType;
|
||||
typedef Transform<Scalar,Dim,Affine,Options> AffineType;
|
||||
typedef Transform<Scalar,Dim,Projective,Options> ProjectiveType;
|
||||
typedef DiagonalMatrix<Scalar,Dim> ScalingType;
|
||||
typedef Translation<Scalar,Dim> TranslationType;
|
||||
|
||||
AffineCompactType A1c; A1c.matrix().setRandom();
|
||||
AffineCompactType A2c; A2c.matrix().setRandom();
|
||||
AffineType A1(A1c);
|
||||
AffineType A2(A2c);
|
||||
ProjectiveType P1; P1.matrix().setRandom();
|
||||
VectorType v1 = VectorType::Random();
|
||||
VectorType v2 = VectorType::Random();
|
||||
HVectorType h1 = HVectorType::Random();
|
||||
Scalar s1 = internal::random<Scalar>();
|
||||
LinearType L = LinearType::Random();
|
||||
MatrixType M = MatrixType::Random();
|
||||
|
||||
CALL_SUBTEST( transform_associativity2(A1c, A1, P1, A2, v2, h1) );
|
||||
CALL_SUBTEST( transform_associativity2(A1c, A1, P1, A2c, v2, h1) );
|
||||
CALL_SUBTEST( transform_associativity2(A1c, A1, P1, v1.asDiagonal(), v2, h1) );
|
||||
CALL_SUBTEST( transform_associativity2(A1c, A1, P1, ScalingType(v1), v2, h1) );
|
||||
CALL_SUBTEST( transform_associativity2(A1c, A1, P1, Scaling(v1), v2, h1) );
|
||||
CALL_SUBTEST( transform_associativity2(A1c, A1, P1, Scaling(s1), v2, h1) );
|
||||
CALL_SUBTEST( transform_associativity2(A1c, A1, P1, TranslationType(v1), v2, h1) );
|
||||
CALL_SUBTEST( transform_associativity_left(A1c, A1, P1, L, v2, h1) );
|
||||
CALL_SUBTEST( transform_associativity2(A1c, A1, P1, R, v2, h1) );
|
||||
|
||||
VERIFY_IS_APPROX( A1*(M*h1), (A1*M)*h1 );
|
||||
VERIFY_IS_APPROX( A1c*(M*h1), (A1c*M)*h1 );
|
||||
VERIFY_IS_APPROX( P1*(M*h1), (P1*M)*h1 );
|
||||
|
||||
VERIFY_IS_APPROX( M*(A1*h1), (M*A1)*h1 );
|
||||
VERIFY_IS_APPROX( M*(A1c*h1), (M*A1c)*h1 );
|
||||
VERIFY_IS_APPROX( M*(P1*h1), ((M*P1)*h1) );
|
||||
}
|
||||
|
||||
template<typename Scalar> void transform_alignment()
|
||||
@@ -517,5 +593,8 @@ void test_geo_transformations()
|
||||
|
||||
CALL_SUBTEST_7(( transform_products<double,3,RowMajor|AutoAlign>() ));
|
||||
CALL_SUBTEST_7(( transform_products<float,2,AutoAlign>() ));
|
||||
|
||||
CALL_SUBTEST_8(( transform_associativity<double,2,ColMajor>(Rotation2D<double>(internal::random<double>()*double(3.14))) ));
|
||||
CALL_SUBTEST_8(( transform_associativity<double,3,ColMajor>(Quaterniond(Vector4d::Random().normalized())) ));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -327,6 +327,7 @@ template<typename Scalar,bool ConjLhs,bool ConjRhs> void test_conj_helper(Scalar
|
||||
ref[i] += cj0(data1[i]) * cj1(data2[i]);
|
||||
VERIFY(internal::isApprox(ref[i], cj.pmadd(data1[i],data2[i],tmp)) && "conj_helper pmadd");
|
||||
}
|
||||
*pval += 0; // Workaround msvc 2013 issue (bad code generation)
|
||||
internal::pstore(pval,pcj.pmadd(internal::pload<Packet>(data1),internal::pload<Packet>(data2),internal::pload<Packet>(pval)));
|
||||
VERIFY(areApprox(ref, pval, PacketSize) && "conj_helper pmadd");
|
||||
}
|
||||
|
||||
@@ -53,14 +53,29 @@ template<typename MatrixType> void inverse_general_4x4(int repeat)
|
||||
// FIXME that 1.25 used to be 1.2 until we tested gcc 4.1 on 30 June 2010 and got 1.21.
|
||||
VERIFY(error_avg < (NumTraits<Scalar>::IsComplex ? 8.0 : 1.25));
|
||||
VERIFY(error_max < (NumTraits<Scalar>::IsComplex ? 64.0 : 20.0));
|
||||
|
||||
{
|
||||
int s = 5;//internal::random<int>(4,10);
|
||||
int i = 0;//internal::random<int>(0,s-4);
|
||||
int j = 0;//internal::random<int>(0,s-4);
|
||||
Matrix<Scalar,5,5> mat(s,s);
|
||||
mat.setRandom();
|
||||
MatrixType submat = mat.template block<4,4>(i,j);
|
||||
MatrixType mat_inv = mat.template block<4,4>(i,j).inverse();
|
||||
VERIFY_IS_APPROX(mat_inv, submat.inverse());
|
||||
mat.template block<4,4>(i,j) = submat.inverse();
|
||||
VERIFY_IS_APPROX(mat_inv, (mat.template block<4,4>(i,j)));
|
||||
}
|
||||
}
|
||||
|
||||
void test_prec_inverse_4x4()
|
||||
{
|
||||
CALL_SUBTEST_1((inverse_permutation_4x4<Matrix4f>()));
|
||||
CALL_SUBTEST_1(( inverse_general_4x4<Matrix4f>(200000 * g_repeat) ));
|
||||
CALL_SUBTEST_1(( inverse_general_4x4<Matrix<float,4,4,RowMajor> >(200000 * g_repeat) ));
|
||||
|
||||
CALL_SUBTEST_2((inverse_permutation_4x4<Matrix<double,4,4,RowMajor> >()));
|
||||
CALL_SUBTEST_2(( inverse_general_4x4<Matrix<double,4,4,ColMajor> >(200000 * g_repeat) ));
|
||||
CALL_SUBTEST_2(( inverse_general_4x4<Matrix<double,4,4,RowMajor> >(200000 * g_repeat) ));
|
||||
|
||||
CALL_SUBTEST_3((inverse_permutation_4x4<Matrix4cf>()));
|
||||
|
||||
118
test/rand.cpp
Normal file
118
test/rand.cpp
Normal file
@@ -0,0 +1,118 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2015 Gael Guennebaud <gael.guennebaud@inria.fr>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#include "main.h"
|
||||
|
||||
typedef long long int64;
|
||||
|
||||
template<typename Scalar> Scalar check_in_range(Scalar x, Scalar y)
|
||||
{
|
||||
Scalar r = internal::random<Scalar>(x,y);
|
||||
VERIFY(r>=x);
|
||||
if(y>=x)
|
||||
{
|
||||
VERIFY(r<=y);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
template<typename Scalar> void check_all_in_range(Scalar x, Scalar y)
|
||||
{
|
||||
Array<int,1,Dynamic> mask(y-x+1);
|
||||
mask.fill(0);
|
||||
long n = (y-x+1)*32;
|
||||
for(long k=0; k<n; ++k)
|
||||
{
|
||||
mask( check_in_range(x,y)-x )++;
|
||||
}
|
||||
for(DenseIndex i=0; i<mask.size(); ++i)
|
||||
if(mask(i)==0)
|
||||
std::cout << "WARNING: value " << x+i << " not reached." << std::endl;
|
||||
VERIFY( (mask>0).all() );
|
||||
}
|
||||
|
||||
template<typename Scalar> void check_histogram(Scalar x, Scalar y, int bins)
|
||||
{
|
||||
Array<int,1,Dynamic> hist(bins);
|
||||
hist.fill(0);
|
||||
int f = 100000;
|
||||
int n = bins*f;
|
||||
int64 range = int64(y)-int64(x);
|
||||
int divisor = int((range+1)/bins);
|
||||
assert(((range+1)%bins)==0);
|
||||
for(int k=0; k<n; ++k)
|
||||
{
|
||||
Scalar r = check_in_range(x,y);
|
||||
hist( int((int64(r)-int64(x))/divisor) )++;
|
||||
}
|
||||
VERIFY( (((hist.cast<double>()/double(f))-1.0).abs()<0.02).all() );
|
||||
}
|
||||
|
||||
void test_rand()
|
||||
{
|
||||
long long_ref = NumTraits<long>::highest()/10;
|
||||
signed char char_offset = (std::min)(g_repeat,64);
|
||||
signed char short_offset = (std::min)(g_repeat,16000);
|
||||
|
||||
for(int i = 0; i < g_repeat*10000; i++) {
|
||||
CALL_SUBTEST(check_in_range<float>(10,11));
|
||||
CALL_SUBTEST(check_in_range<float>(1.24234523,1.24234523));
|
||||
CALL_SUBTEST(check_in_range<float>(-1,1));
|
||||
CALL_SUBTEST(check_in_range<float>(-1432.2352,-1432.2352));
|
||||
|
||||
CALL_SUBTEST(check_in_range<double>(10,11));
|
||||
CALL_SUBTEST(check_in_range<double>(1.24234523,1.24234523));
|
||||
CALL_SUBTEST(check_in_range<double>(-1,1));
|
||||
CALL_SUBTEST(check_in_range<double>(-1432.2352,-1432.2352));
|
||||
|
||||
CALL_SUBTEST(check_in_range<int>(0,-1));
|
||||
CALL_SUBTEST(check_in_range<short>(0,-1));
|
||||
CALL_SUBTEST(check_in_range<long>(0,-1));
|
||||
CALL_SUBTEST(check_in_range<int>(-673456,673456));
|
||||
CALL_SUBTEST(check_in_range<int>(-RAND_MAX+10,RAND_MAX-10));
|
||||
CALL_SUBTEST(check_in_range<short>(-24345,24345));
|
||||
CALL_SUBTEST(check_in_range<long>(-long_ref,long_ref));
|
||||
}
|
||||
|
||||
CALL_SUBTEST(check_all_in_range<signed char>(11,11));
|
||||
CALL_SUBTEST(check_all_in_range<signed char>(11,11+char_offset));
|
||||
CALL_SUBTEST(check_all_in_range<signed char>(-5,5));
|
||||
CALL_SUBTEST(check_all_in_range<signed char>(-11-char_offset,-11));
|
||||
CALL_SUBTEST(check_all_in_range<signed char>(-126,-126+char_offset));
|
||||
CALL_SUBTEST(check_all_in_range<signed char>(126-char_offset,126));
|
||||
CALL_SUBTEST(check_all_in_range<signed char>(-126,126));
|
||||
|
||||
CALL_SUBTEST(check_all_in_range<short>(11,11));
|
||||
CALL_SUBTEST(check_all_in_range<short>(11,11+short_offset));
|
||||
CALL_SUBTEST(check_all_in_range<short>(-5,5));
|
||||
CALL_SUBTEST(check_all_in_range<short>(-11-short_offset,-11));
|
||||
CALL_SUBTEST(check_all_in_range<short>(-24345,-24345+short_offset));
|
||||
CALL_SUBTEST(check_all_in_range<short>(24345,24345+short_offset));
|
||||
|
||||
CALL_SUBTEST(check_all_in_range<int>(11,11));
|
||||
CALL_SUBTEST(check_all_in_range<int>(11,11+g_repeat));
|
||||
CALL_SUBTEST(check_all_in_range<int>(-5,5));
|
||||
CALL_SUBTEST(check_all_in_range<int>(-11-g_repeat,-11));
|
||||
CALL_SUBTEST(check_all_in_range<int>(-673456,-673456+g_repeat));
|
||||
CALL_SUBTEST(check_all_in_range<int>(673456,673456+g_repeat));
|
||||
|
||||
CALL_SUBTEST(check_all_in_range<long>(11,11));
|
||||
CALL_SUBTEST(check_all_in_range<long>(11,11+g_repeat));
|
||||
CALL_SUBTEST(check_all_in_range<long>(-5,5));
|
||||
CALL_SUBTEST(check_all_in_range<long>(-11-g_repeat,-11));
|
||||
CALL_SUBTEST(check_all_in_range<long>(-long_ref,-long_ref+g_repeat));
|
||||
CALL_SUBTEST(check_all_in_range<long>( long_ref, long_ref+g_repeat));
|
||||
|
||||
CALL_SUBTEST(check_histogram<int>(-5,5,11));
|
||||
int bins = 100;
|
||||
CALL_SUBTEST(check_histogram<int>(-3333,-3333+bins*(3333/bins)-1,bins));
|
||||
bins = 1000;
|
||||
CALL_SUBTEST(check_histogram<int>(-RAND_MAX+10,-RAND_MAX+10+bins*(RAND_MAX/bins)-1,bins));
|
||||
CALL_SUBTEST(check_histogram<int>(-RAND_MAX+10,-int64(RAND_MAX)+10+bins*(2*int64(RAND_MAX)/bins)-1,bins));
|
||||
}
|
||||
@@ -299,6 +299,14 @@ template<typename SparseMatrixType> void sparse_basic(const SparseMatrixType& re
|
||||
VERIFY_IS_APPROX(m1.innerVector(0).dot(refM2.row(0)), refM1.row(0).dot(refM2.row(0)));
|
||||
else
|
||||
VERIFY_IS_APPROX(m1.innerVector(0).dot(refM2.row(0)), refM1.col(0).dot(refM2.row(0)));
|
||||
|
||||
DenseVector rv = DenseVector::Random(m1.cols());
|
||||
DenseVector cv = DenseVector::Random(m1.rows());
|
||||
Index r = internal::random<Index>(0,m1.rows()-2);
|
||||
Index c = internal::random<Index>(0,m1.cols()-1);
|
||||
VERIFY_IS_APPROX(( m1.template block<1,Dynamic>(r,0,1,m1.cols()).dot(rv)) , refM1.row(r).dot(rv));
|
||||
VERIFY_IS_APPROX(m1.row(r).dot(rv), refM1.row(r).dot(rv));
|
||||
VERIFY_IS_APPROX(m1.col(c).dot(cv), refM1.col(c).dot(cv));
|
||||
|
||||
VERIFY_IS_APPROX(m1.conjugate(), refM1.conjugate());
|
||||
VERIFY_IS_APPROX(m1.real(), refM1.real());
|
||||
|
||||
Reference in New Issue
Block a user