mirror of
https://gitlab.com/libeigen/eigen.git
synced 2026-04-10 11:34:33 +08:00
Compare commits
37 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cee93a92af | ||
|
|
ed5cd0a4d1 | ||
|
|
17c2fde66b | ||
|
|
adb6679262 | ||
|
|
036ed69bc7 | ||
|
|
1ded6bf3fa | ||
|
|
18038fc829 | ||
|
|
03fd417f66 | ||
|
|
91207cbae3 | ||
|
|
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 |
41
.gitignore
vendored
Normal file
41
.gitignore
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
qrc_*cxx
|
||||
*.orig
|
||||
*.pyc
|
||||
*.diff
|
||||
diff
|
||||
*.save
|
||||
save
|
||||
*.old
|
||||
*.gmo
|
||||
*.qm
|
||||
core
|
||||
core.*
|
||||
*.bak
|
||||
*~
|
||||
*.build*
|
||||
*.moc.*
|
||||
*.moc
|
||||
ui_*
|
||||
CMakeCache.txt
|
||||
tags
|
||||
.*.swp
|
||||
activity.png
|
||||
*.out
|
||||
*.php*
|
||||
*.log
|
||||
*.orig
|
||||
*.rej
|
||||
log
|
||||
patch
|
||||
*.patch
|
||||
a
|
||||
a.*
|
||||
lapack/testing
|
||||
lapack/reference
|
||||
.*project
|
||||
.settings
|
||||
Makefile
|
||||
!ci/build.gitlab-ci.yml
|
||||
!scripts/buildtests.in
|
||||
!Eigen/Core
|
||||
!Eigen/src/Core
|
||||
28
.gitlab-ci.yml
Normal file
28
.gitlab-ci.yml
Normal file
@@ -0,0 +1,28 @@
|
||||
# This file is part of Eigen, a lightweight C++ template library
|
||||
# for linear algebra.
|
||||
#
|
||||
# Copyright (C) 2023, The Eigen Authors
|
||||
#
|
||||
# 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/.
|
||||
|
||||
stages:
|
||||
- build
|
||||
- deploy
|
||||
|
||||
variables:
|
||||
# CMake build directory.
|
||||
EIGEN_CI_BUILDDIR: .build
|
||||
# Specify the CMake build target.
|
||||
EIGEN_CI_BUILD_TARGET: ""
|
||||
# If a test regex is specified, that will be selected.
|
||||
# Otherwise, we will try a label if specified.
|
||||
EIGEN_CI_CTEST_REGEX: ""
|
||||
EIGEN_CI_CTEST_LABEL: ""
|
||||
EIGEN_CI_CTEST_ARGS: ""
|
||||
|
||||
include:
|
||||
- "/ci/common.gitlab-ci.yml"
|
||||
- "/ci/build.linux.gitlab-ci.yml"
|
||||
- "/ci/deploy.gitlab-ci.yml"
|
||||
@@ -14,34 +14,40 @@ namespace Eigen {
|
||||
|
||||
namespace internal {
|
||||
|
||||
template<typename Scalar, typename CholmodType>
|
||||
void cholmod_configure_matrix(CholmodType& mat)
|
||||
{
|
||||
if (internal::is_same<Scalar,float>::value)
|
||||
{
|
||||
mat.xtype = CHOLMOD_REAL;
|
||||
mat.dtype = CHOLMOD_SINGLE;
|
||||
}
|
||||
else if (internal::is_same<Scalar,double>::value)
|
||||
{
|
||||
template<typename Scalar> struct cholmod_configure_matrix;
|
||||
|
||||
template<> struct cholmod_configure_matrix<double> {
|
||||
template<typename CholmodType>
|
||||
static void run(CholmodType& mat) {
|
||||
mat.xtype = CHOLMOD_REAL;
|
||||
mat.dtype = CHOLMOD_DOUBLE;
|
||||
}
|
||||
else if (internal::is_same<Scalar,std::complex<float> >::value)
|
||||
{
|
||||
mat.xtype = CHOLMOD_COMPLEX;
|
||||
mat.dtype = CHOLMOD_SINGLE;
|
||||
}
|
||||
else if (internal::is_same<Scalar,std::complex<double> >::value)
|
||||
{
|
||||
};
|
||||
|
||||
template<> struct cholmod_configure_matrix<std::complex<double> > {
|
||||
template<typename CholmodType>
|
||||
static void run(CholmodType& mat) {
|
||||
mat.xtype = CHOLMOD_COMPLEX;
|
||||
mat.dtype = CHOLMOD_DOUBLE;
|
||||
}
|
||||
else
|
||||
{
|
||||
eigen_assert(false && "Scalar type not supported by CHOLMOD");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Other scalar types are not yet suppotred by Cholmod
|
||||
// template<> struct cholmod_configure_matrix<float> {
|
||||
// template<typename CholmodType>
|
||||
// static void run(CholmodType& mat) {
|
||||
// mat.xtype = CHOLMOD_REAL;
|
||||
// mat.dtype = CHOLMOD_SINGLE;
|
||||
// }
|
||||
// };
|
||||
//
|
||||
// template<> struct cholmod_configure_matrix<std::complex<float> > {
|
||||
// template<typename CholmodType>
|
||||
// static void run(CholmodType& mat) {
|
||||
// mat.xtype = CHOLMOD_COMPLEX;
|
||||
// mat.dtype = CHOLMOD_SINGLE;
|
||||
// }
|
||||
// };
|
||||
|
||||
} // namespace internal
|
||||
|
||||
@@ -88,7 +94,7 @@ cholmod_sparse viewAsCholmod(SparseMatrix<_Scalar,_Options,_Index>& mat)
|
||||
}
|
||||
|
||||
// setup res.xtype
|
||||
internal::cholmod_configure_matrix<_Scalar>(res);
|
||||
internal::cholmod_configure_matrix<_Scalar>::run(res);
|
||||
|
||||
res.stype = 0;
|
||||
|
||||
@@ -131,7 +137,7 @@ cholmod_dense viewAsCholmod(MatrixBase<Derived>& mat)
|
||||
res.x = (void*)(mat.derived().data());
|
||||
res.z = 0;
|
||||
|
||||
internal::cholmod_configure_matrix<Scalar>(res);
|
||||
internal::cholmod_configure_matrix<Scalar>::run(res);
|
||||
|
||||
return res;
|
||||
}
|
||||
@@ -172,14 +178,16 @@ class CholmodBase : internal::noncopyable
|
||||
CholmodBase()
|
||||
: m_cholmodFactor(0), m_info(Success), m_isInitialized(false)
|
||||
{
|
||||
m_shiftOffset[0] = m_shiftOffset[1] = RealScalar(0.0);
|
||||
EIGEN_STATIC_ASSERT((internal::is_same<double,RealScalar>::value), CHOLMOD_SUPPORTS_DOUBLE_PRECISION_ONLY);
|
||||
m_shiftOffset[0] = m_shiftOffset[1] = 0.0;
|
||||
cholmod_start(&m_cholmod);
|
||||
}
|
||||
|
||||
CholmodBase(const MatrixType& matrix)
|
||||
: m_cholmodFactor(0), m_info(Success), m_isInitialized(false)
|
||||
{
|
||||
m_shiftOffset[0] = m_shiftOffset[1] = RealScalar(0.0);
|
||||
EIGEN_STATIC_ASSERT((internal::is_same<double,RealScalar>::value), CHOLMOD_SUPPORTS_DOUBLE_PRECISION_ONLY);
|
||||
m_shiftOffset[0] = m_shiftOffset[1] = 0.0;
|
||||
cholmod_start(&m_cholmod);
|
||||
compute(matrix);
|
||||
}
|
||||
@@ -277,7 +285,7 @@ class CholmodBase : internal::noncopyable
|
||||
eigen_assert(m_analysisIsOk && "You must first call analyzePattern()");
|
||||
cholmod_sparse A = viewAsCholmod(matrix.template selfadjointView<UpLo>());
|
||||
cholmod_factorize_p(&A, m_shiftOffset, 0, 0, m_cholmodFactor, &m_cholmod);
|
||||
|
||||
|
||||
// If the factorization failed, minor is the column at which it did. On success minor == n.
|
||||
this->m_info = (m_cholmodFactor->minor == m_cholmodFactor->n ? Success : NumericalIssue);
|
||||
m_factorizationIsOk = true;
|
||||
@@ -344,7 +352,7 @@ class CholmodBase : internal::noncopyable
|
||||
*/
|
||||
Derived& setShift(const RealScalar& offset)
|
||||
{
|
||||
m_shiftOffset[0] = offset;
|
||||
m_shiftOffset[0] = double(offset);
|
||||
return derived();
|
||||
}
|
||||
|
||||
@@ -355,7 +363,7 @@ class CholmodBase : internal::noncopyable
|
||||
protected:
|
||||
mutable cholmod_common m_cholmod;
|
||||
cholmod_factor* m_cholmodFactor;
|
||||
RealScalar m_shiftOffset[2];
|
||||
double m_shiftOffset[2];
|
||||
mutable ComputationInfo m_info;
|
||||
bool m_isInitialized;
|
||||
int m_factorizationIsOk;
|
||||
@@ -378,6 +386,8 @@ class CholmodBase : internal::noncopyable
|
||||
*
|
||||
* This class supports all kind of SparseMatrix<>: row or column major; upper, lower, or both; compressed or non compressed.
|
||||
*
|
||||
* \warning Only double precision real and complex scalar types are supported by Cholmod.
|
||||
*
|
||||
* \sa \ref TutorialSparseDirectSolvers, class CholmodSupernodalLLT, class SimplicialLLT
|
||||
*/
|
||||
template<typename _MatrixType, int _UpLo = Lower>
|
||||
@@ -425,6 +435,8 @@ class CholmodSimplicialLLT : public CholmodBase<_MatrixType, _UpLo, CholmodSimpl
|
||||
*
|
||||
* This class supports all kind of SparseMatrix<>: row or column major; upper, lower, or both; compressed or non compressed.
|
||||
*
|
||||
* \warning Only double precision real and complex scalar types are supported by Cholmod.
|
||||
*
|
||||
* \sa \ref TutorialSparseDirectSolvers, class CholmodSupernodalLLT, class SimplicialLDLT
|
||||
*/
|
||||
template<typename _MatrixType, int _UpLo = Lower>
|
||||
@@ -470,6 +482,8 @@ class CholmodSimplicialLDLT : public CholmodBase<_MatrixType, _UpLo, CholmodSimp
|
||||
*
|
||||
* This class supports all kind of SparseMatrix<>: row or column major; upper, lower, or both; compressed or non compressed.
|
||||
*
|
||||
* \warning Only double precision real and complex scalar types are supported by Cholmod.
|
||||
*
|
||||
* \sa \ref TutorialSparseDirectSolvers
|
||||
*/
|
||||
template<typename _MatrixType, int _UpLo = Lower>
|
||||
@@ -517,6 +531,8 @@ class CholmodSupernodalLLT : public CholmodBase<_MatrixType, _UpLo, CholmodSuper
|
||||
*
|
||||
* This class supports all kind of SparseMatrix<>: row or column major; upper, lower, or both; compressed or non compressed.
|
||||
*
|
||||
* \warning Only double precision real and complex scalar types are supported by Cholmod.
|
||||
*
|
||||
* \sa \ref TutorialSparseDirectSolvers
|
||||
*/
|
||||
template<typename _MatrixType, int _UpLo = Lower>
|
||||
|
||||
@@ -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 && \
|
||||
@@ -412,10 +412,11 @@
|
||||
// attribute to maximize inlining. This should only be used when really necessary: in particular,
|
||||
// it uses __attribute__((always_inline)) on GCC, which most of the time is useless and can severely harm compile times.
|
||||
// FIXME with the always_inline attribute,
|
||||
// gcc 3.4.x reports the following compilation error:
|
||||
// gcc 3.4.x and 4.1 reports the following compilation error:
|
||||
// Eval.h:91: sorry, unimplemented: inlining failed in call to 'const Eigen::Eval<Derived> Eigen::MatrixBase<Scalar, Derived>::eval() const'
|
||||
// : function body not available
|
||||
#if EIGEN_GNUC_AT_LEAST(4,0)
|
||||
// See also bug 1367
|
||||
#if EIGEN_GNUC_AT_LEAST(4,2)
|
||||
#define EIGEN_ALWAYS_INLINE __attribute__((always_inline)) inline
|
||||
#else
|
||||
#define EIGEN_ALWAYS_INLINE EIGEN_STRONG_INLINE
|
||||
|
||||
@@ -92,7 +92,8 @@
|
||||
THE_STORAGE_ORDER_OF_BOTH_SIDES_MUST_MATCH,
|
||||
OBJECT_ALLOCATED_ON_STACK_IS_TOO_BIG,
|
||||
IMPLICIT_CONVERSION_TO_SCALAR_IS_FOR_INNER_PRODUCT_ONLY,
|
||||
STORAGE_LAYOUT_DOES_NOT_MATCH
|
||||
STORAGE_LAYOUT_DOES_NOT_MATCH,
|
||||
CHOLMOD_SUPPORTS_DOUBLE_PRECISION_ONLY
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -218,7 +218,10 @@ public:
|
||||
inline Hyperplane& transform(const MatrixBase<XprType>& mat, TransformTraits traits = Affine)
|
||||
{
|
||||
if (traits==Affine)
|
||||
{
|
||||
normal() = mat.inverse().transpose() * normal();
|
||||
m_coeffs /= normal().norm();
|
||||
}
|
||||
else if (traits==Isometry)
|
||||
normal() = mat * normal();
|
||||
else
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -110,16 +110,16 @@ class SPQR
|
||||
max2Norm = RealScalar(1);
|
||||
pivotThreshold = 20 * (mat.rows() + mat.cols()) * max2Norm * NumTraits<RealScalar>::epsilon();
|
||||
}
|
||||
|
||||
cholmod_sparse A;
|
||||
A = viewAsCholmod(mat);
|
||||
m_rows = matrix.rows();
|
||||
Index col = matrix.cols();
|
||||
m_rank = SuiteSparseQR<Scalar>(m_ordering, pivotThreshold, col, &A,
|
||||
&m_cR, &m_E, &m_H, &m_HPinv, &m_HTau, &m_cc);
|
||||
|
||||
if (!m_cR)
|
||||
{
|
||||
m_info = NumericalIssue;
|
||||
m_info = NumericalIssue;
|
||||
m_isInitialized = false;
|
||||
return;
|
||||
}
|
||||
@@ -130,7 +130,7 @@ class SPQR
|
||||
/**
|
||||
* Get the number of rows of the input matrix and the Q matrix
|
||||
*/
|
||||
inline Index rows() const {return m_cR->nrow; }
|
||||
inline Index rows() const {return m_rows; }
|
||||
|
||||
/**
|
||||
* Get the number of columns of the input matrix.
|
||||
@@ -254,6 +254,7 @@ class SPQR
|
||||
mutable Index m_rank; // The rank of the matrix
|
||||
mutable cholmod_common m_cc; // Workspace and parameters
|
||||
bool m_useDefaultThreshold; // Use default threshold
|
||||
Index m_rows;
|
||||
template<typename ,typename > friend struct SPQR_QProduct;
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -27,6 +27,20 @@ struct traits<SparseView<MatrixType> > : traits<MatrixType>
|
||||
|
||||
} // end namespace internal
|
||||
|
||||
/** \ingroup SparseCore_Module
|
||||
* \class SparseView
|
||||
*
|
||||
* \brief Expression of a dense or sparse matrix with zero or too small values removed
|
||||
*
|
||||
* \tparam MatrixType the type of the object of which we are removing the small entries
|
||||
*
|
||||
* This class represents an expression of a given dense or sparse matrix with
|
||||
* entries smaller than \c reference * \c epsilon are removed.
|
||||
* It is the return type of MatrixBase::sparseView() and SparseMatrixBase::pruned()
|
||||
* and most of the time this is the only way it is used.
|
||||
*
|
||||
* \sa MatrixBase::sparseView(), SparseMatrixBase::pruned()
|
||||
*/
|
||||
template<typename MatrixType>
|
||||
class SparseView : public SparseMatrixBase<SparseView<MatrixType> >
|
||||
{
|
||||
@@ -87,6 +101,25 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
/** \ingroup SparseCore_Module
|
||||
*
|
||||
* \returns a sparse expression of the dense expression \c *this with values smaller than
|
||||
* \a reference * \a epsilon removed.
|
||||
*
|
||||
* This method is typically used when prototyping to convert a quickly assembled dense Matrix \c D to a SparseMatrix \c S:
|
||||
* \code
|
||||
* MatrixXd D(n,m);
|
||||
* SparseMatrix<double> S;
|
||||
* S = D.sparseView(); // suppress numerical zeros (exact)
|
||||
* S = D.sparseView(reference);
|
||||
* S = D.sparseView(reference,epsilon);
|
||||
* \endcode
|
||||
* where \a reference is a meaningful non zero reference value,
|
||||
* and \a epsilon is a tolerance factor defaulting to NumTraits<Scalar>::dummy_precision().
|
||||
*
|
||||
* \sa SparseMatrixBase::pruned(), class SparseView */
|
||||
template<typename Derived>
|
||||
const SparseView<Derived> MatrixBase<Derived>::sparseView(const Scalar& m_reference,
|
||||
const typename NumTraits<Scalar>::Real& m_epsilon) const
|
||||
|
||||
@@ -148,7 +148,8 @@ class UmfPackLU : internal::noncopyable
|
||||
|
||||
UmfPackLU() { init(); }
|
||||
|
||||
UmfPackLU(const MatrixType& matrix)
|
||||
template<typename InputMatrixType>
|
||||
UmfPackLU(const InputMatrixType& matrix)
|
||||
{
|
||||
init();
|
||||
compute(matrix);
|
||||
|
||||
30
ci/build.linux.gitlab-ci.yml
Normal file
30
ci/build.linux.gitlab-ci.yml
Normal file
@@ -0,0 +1,30 @@
|
||||
# Base configuration for linux cross-compilation.
|
||||
.build:linux:cross:
|
||||
extends: .common:linux:cross
|
||||
stage: build
|
||||
variables:
|
||||
EIGEN_CI_BUILD_TARGET: buildtests
|
||||
script:
|
||||
- . ci/scripts/build.linux.script.sh
|
||||
tags:
|
||||
- saas-linux-2xlarge-amd64
|
||||
rules:
|
||||
- if: $CI_PIPELINE_SOURCE == "schedule" && $CI_PROJECT_NAMESPACE == "libeigen"
|
||||
- if: $CI_PIPELINE_SOURCE == "web" && $CI_PROJECT_NAMESPACE == "libeigen"
|
||||
- if: $CI_PIPELINE_SOURCE == "merge_request_event" && $CI_PROJECT_NAMESPACE == "libeigen" && $CI_MERGE_REQUEST_LABELS =~ "/all-tests/"
|
||||
cache:
|
||||
key: "$CI_JOB_NAME_SLUG-$CI_COMMIT_REF_SLUG-BUILD"
|
||||
paths:
|
||||
- ${EIGEN_CI_BUILDDIR}/
|
||||
|
||||
build:linux:docs:
|
||||
extends: .build:linux:cross
|
||||
variables:
|
||||
EIGEN_CI_TARGET_ARCH: any
|
||||
EIGEN_CI_BUILD_TARGET: doc
|
||||
EIGEN_CI_INSTALL: ca-certificates clang flex python3 bison graphviz
|
||||
EIGEN_CI_C_COMPILER: clang
|
||||
EIGEN_CI_CXX_COMPILER: clang++
|
||||
EIGEN_CI_BEFORE_SCRIPT: ". ci/scripts/build_and_install_doxygen.sh Release_1_13_2"
|
||||
rules:
|
||||
- if: $CI_PIPELINE_SOURCE == "push" && $CI_PROJECT_NAMESPACE == "libeigen"
|
||||
24
ci/common.gitlab-ci.yml
Normal file
24
ci/common.gitlab-ci.yml
Normal file
@@ -0,0 +1,24 @@
|
||||
# Base configuration for linux builds and tests.
|
||||
.common:linux:cross:
|
||||
image: ubuntu:20.04
|
||||
variables:
|
||||
EIGEN_CI_TARGET_ARCH: ""
|
||||
EIGEN_CI_ADDITIONAL_ARGS: ""
|
||||
# If host matches target, use the following:
|
||||
EIGEN_CI_C_COMPILER: ""
|
||||
EIGEN_CI_CXX_COMPILER: ""
|
||||
EIGEN_CI_INSTALL: "${EIGEN_CI_C_COMPILER} ${EIGEN_CI_CXX_COMPILER}"
|
||||
# If host does not match the target, use the following:
|
||||
EIGEN_CI_CROSS_TARGET_TRIPLE: ""
|
||||
EIGEN_CI_CROSS_C_COMPILER: ${EIGEN_CI_C_COMPILER}
|
||||
EIGEN_CI_CROSS_CXX_COMPILER: ${EIGEN_CI_CXX_COMPILER}
|
||||
EIGEN_CI_CROSS_INSTALL: "${EIGEN_CI_CROSS_C_COMPILER} ${EIGEN_CI_CROSS_CXX_COMPILER}"
|
||||
before_script:
|
||||
# Call script in current shell - it sets up some environment variables.
|
||||
- . ci/scripts/common.linux.before_script.sh
|
||||
artifacts:
|
||||
when: always
|
||||
name: "$CI_JOB_NAME_SLUG-$CI_COMMIT_REF_SLUG"
|
||||
paths:
|
||||
- ${EIGEN_CI_BUILDDIR}/
|
||||
expire_in: 5 days
|
||||
25
ci/deploy.gitlab-ci.yml
Normal file
25
ci/deploy.gitlab-ci.yml
Normal file
@@ -0,0 +1,25 @@
|
||||
# Upload docs if pipeline succeeded.
|
||||
deploy:docs:
|
||||
stage: deploy
|
||||
image: busybox
|
||||
dependencies: [ build:linux:docs ]
|
||||
variables:
|
||||
PAGES_PREFIX: docs-nightly
|
||||
script:
|
||||
- echo "Deploying site to $CI_PAGES_URL"
|
||||
- mv ${EIGEN_CI_BUILDDIR}/doc/html public
|
||||
pages:
|
||||
path_prefix: $PAGES_PREFIX
|
||||
expire_in: never
|
||||
artifacts:
|
||||
name: "$CI_JOB_NAME_SLUG-$CI_COMMIT_REF_SLUG"
|
||||
paths:
|
||||
- public
|
||||
tags:
|
||||
- saas-linux-small-amd64
|
||||
rules:
|
||||
- if: $CI_PIPELINE_SOURCE == "schedule" && $CI_PROJECT_NAMESPACE == "libeigen"
|
||||
- if: $CI_PIPELINE_SOURCE == "web" && $CI_PROJECT_NAMESPACE == "libeigen"
|
||||
- if: $CI_PIPELINE_SOURCE == "push" && $CI_PROJECT_NAMESPACE == "libeigen"
|
||||
variables:
|
||||
PAGES_PREFIX: docs-$CI_COMMIT_REF_NAME
|
||||
31
ci/scripts/build.linux.script.sh
Executable file
31
ci/scripts/build.linux.script.sh
Executable file
@@ -0,0 +1,31 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -x
|
||||
|
||||
# Create and enter build directory.
|
||||
rootdir=`pwd`
|
||||
mkdir -p ${EIGEN_CI_BUILDDIR}
|
||||
cd ${EIGEN_CI_BUILDDIR}
|
||||
|
||||
# Configure build.
|
||||
cmake -G Ninja \
|
||||
-DCMAKE_CXX_COMPILER=${EIGEN_CI_CXX_COMPILER} \
|
||||
-DCMAKE_C_COMPILER=${EIGEN_CI_C_COMPILER} \
|
||||
-DCMAKE_CXX_COMPILER_TARGET=${EIGEN_CI_CXX_COMPILER_TARGET} \
|
||||
${EIGEN_CI_ADDITIONAL_ARGS} ${rootdir}
|
||||
|
||||
target=""
|
||||
if [[ ${EIGEN_CI_BUILD_TARGET} ]]; then
|
||||
target="--target ${EIGEN_CI_BUILD_TARGET}"
|
||||
fi
|
||||
|
||||
# Builds (particularly gcc) sometimes get killed, potentially when running
|
||||
# out of resources. In that case, keep trying to build the remaining
|
||||
# targets (k0), then try to build again with a single thread (j1) to minimize
|
||||
# resource use.
|
||||
cmake --build . ${target} -- -k0 || cmake --build . ${target} -- -k0 -j1
|
||||
|
||||
# Return to root directory.
|
||||
cd ${rootdir}
|
||||
|
||||
set +x
|
||||
6
ci/scripts/build_and_install_doxygen.sh
Normal file
6
ci/scripts/build_and_install_doxygen.sh
Normal file
@@ -0,0 +1,6 @@
|
||||
git clone --depth 1 --branch $1 https://github.com/doxygen/doxygen.git
|
||||
cmake -B doxygen/.build -G Ninja \
|
||||
-DCMAKE_CXX_COMPILER=${EIGEN_CI_CXX_COMPILER} \
|
||||
-DCMAKE_C_COMPILER=${EIGEN_CI_C_COMPILER} \
|
||||
doxygen
|
||||
cmake --build doxygen/.build -t install
|
||||
46
ci/scripts/common.linux.before_script.sh
Executable file
46
ci/scripts/common.linux.before_script.sh
Executable file
@@ -0,0 +1,46 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -x
|
||||
|
||||
echo "Running ${CI_JOB_NAME}"
|
||||
|
||||
# Get architecture and display CI configuration.
|
||||
export ARCH=`uname -m`
|
||||
export NPROC=`nproc`
|
||||
echo "arch=$ARCH, target=${EIGEN_CI_TARGET_ARCH}"
|
||||
echo "Processors: ${NPROC}"
|
||||
echo "CI Variables:"
|
||||
export | grep EIGEN
|
||||
|
||||
# Set noninteractive, otherwise tzdata may be installed and prompt for a
|
||||
# geographical region.
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
apt-get update -y > /dev/null
|
||||
apt-get install -y --no-install-recommends ninja-build cmake git > /dev/null
|
||||
|
||||
# Install required dependencies and set up compilers.
|
||||
# These are required even for testing to ensure that dynamic runtime libraries
|
||||
# are available.
|
||||
if [[ "$ARCH" == "${EIGEN_CI_TARGET_ARCH}" || "${EIGEN_CI_TARGET_ARCH}" == "any" ]]; then
|
||||
apt-get install -y --no-install-recommends ${EIGEN_CI_INSTALL} > /dev/null;
|
||||
export EIGEN_CI_CXX_IMPLICIT_INCLUDE_DIRECTORIES="";
|
||||
export EIGEN_CI_CXX_COMPILER_TARGET="";
|
||||
else
|
||||
apt-get install -y --no-install-recommends ${EIGEN_CI_CROSS_INSTALL} > /dev/null;
|
||||
export EIGEN_CI_C_COMPILER=${EIGEN_CI_CROSS_C_COMPILER};
|
||||
export EIGEN_CI_CXX_COMPILER=${EIGEN_CI_CROSS_CXX_COMPILER};
|
||||
export EIGEN_CI_CXX_COMPILER_TARGET=${EIGEN_CI_CROSS_TARGET_TRIPLE};
|
||||
# Tell the compiler where to find headers and libraries if using clang.
|
||||
# NOTE: this breaks GCC since it messes with include path order
|
||||
# (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70129)
|
||||
if [[ "${EIGEN_CI_CROSS_CXX_COMPILER}" == *"clang"* ]]; then
|
||||
export CPLUS_INCLUDE_PATH="/usr/${EIGEN_CI_CROSS_TARGET_TRIPLE}/include";
|
||||
export LIBRARY_PATH="/usr/${EIGEN_CI_CROSS_TARGET_TRIPLE}/lib64";
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "Compilers: ${EIGEN_CI_C_COMPILER} ${EIGEN_CI_CXX_COMPILER}"
|
||||
|
||||
if [ -n "$EIGEN_CI_BEFORE_SCRIPT" ]; then eval "$EIGEN_CI_BEFORE_SCRIPT"; fi
|
||||
|
||||
set +x
|
||||
@@ -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
|
||||
|
||||
@@ -17,18 +17,22 @@ $generatedby  <a href="http://www.doxygen.org/index.html">
|
||||
</small></address>
|
||||
<!--END !GENERATE_TREEVIEW-->
|
||||
|
||||
<!-- Piwik -->
|
||||
<!-- Matomo -->
|
||||
<script type="text/javascript">
|
||||
var pkBaseURL = (("https:" == document.location.protocol) ? "https://stats.sylphide-consulting.com/piwik/" : "http://stats.sylphide-consulting.com/piwik/");
|
||||
document.write(unescape("%3Cscript src='" + pkBaseURL + "piwik.js' type='text/javascript'%3E%3C/script%3E"));
|
||||
</script><script type="text/javascript">
|
||||
try {
|
||||
var piwikTracker = Piwik.getTracker(pkBaseURL + "piwik.php", 20);
|
||||
piwikTracker.trackPageView();
|
||||
piwikTracker.enableLinkTracking();
|
||||
} catch( err ) {}
|
||||
</script><noscript><p><img src="http://stats.sylphide-consulting.com/piwik/piwik.php?idsite=20" style="border:0" alt="" /></p></noscript>
|
||||
<!-- End Piwik Tracking Code -->
|
||||
var _paq = _paq || [];
|
||||
/* tracker methods like "setCustomDimension" should be called before "trackPageView" */
|
||||
_paq.push(['trackPageView']);
|
||||
_paq.push(['enableLinkTracking']);
|
||||
(function() {
|
||||
var u="//stats.sylphide-consulting.com/matomo/";
|
||||
_paq.push(['setTrackerUrl', u+'piwik.php']);
|
||||
_paq.push(['setSiteId', '20']);
|
||||
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
|
||||
g.type='text/javascript'; g.async=true; g.defer=true; g.src=u+'piwik.js'; s.parentNode.insertBefore(g,s);
|
||||
})();
|
||||
</script>
|
||||
<noscript><p><img src="//stats.sylphide-consulting.com/matomo/piwik.php?idsite=20&rec=1" style="border:0;" alt="" /></p></noscript>
|
||||
<!-- End Matomo Code -->
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -59,12 +59,15 @@ template<typename HyperplaneType> void hyperplane(const HyperplaneType& _plane)
|
||||
VERIFY_IS_MUCH_SMALLER_THAN( pl2.transform(rot,Isometry).absDistance(rot * p1), Scalar(1) );
|
||||
pl2 = pl1;
|
||||
VERIFY_IS_MUCH_SMALLER_THAN( pl2.transform(rot*scaling).absDistance((rot*scaling) * p1), Scalar(1) );
|
||||
VERIFY_IS_APPROX( pl2.normal().norm(), RealScalar(1) );
|
||||
pl2 = pl1;
|
||||
VERIFY_IS_MUCH_SMALLER_THAN( pl2.transform(rot*scaling*translation)
|
||||
.absDistance((rot*scaling*translation) * p1), Scalar(1) );
|
||||
VERIFY_IS_APPROX( pl2.normal().norm(), RealScalar(1) );
|
||||
pl2 = pl1;
|
||||
VERIFY_IS_MUCH_SMALLER_THAN( pl2.transform(rot*translation,Isometry)
|
||||
.absDistance((rot*translation) * p1), Scalar(1) );
|
||||
VERIFY_IS_APPROX( pl2.normal().norm(), RealScalar(1) );
|
||||
}
|
||||
|
||||
// casting
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -18,8 +18,8 @@ int generate_sparse_rectangular_problem(MatrixType& A, DenseMat& dA, int maxRows
|
||||
int cols = internal::random<int>(1,rows);
|
||||
double density = (std::max)(8./(rows*cols), 0.01);
|
||||
|
||||
A.resize(rows,rows);
|
||||
dA.resize(rows,rows);
|
||||
A.resize(rows,cols);
|
||||
dA.resize(rows,cols);
|
||||
initSparse<Scalar>(density, dA, A,ForceNonZeroDiag);
|
||||
A.makeCompressed();
|
||||
return rows;
|
||||
|
||||
Reference in New Issue
Block a user