mirror of
https://gitlab.com/libeigen/eigen.git
synced 2026-04-10 11:34:33 +08:00
Compare commits
80 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f7df9f92ff | ||
|
|
d2dcca52a3 | ||
|
|
7408e923a7 | ||
|
|
18ca438a62 | ||
|
|
d286300362 | ||
|
|
02ba4e2f54 | ||
|
|
2eef21a8d5 | ||
|
|
bea1737a5a | ||
|
|
4b09865b8f | ||
|
|
f6aa60bcf3 | ||
|
|
8d236e74a1 | ||
|
|
046a84c0ef | ||
|
|
d7f60257dd | ||
|
|
874ff5a0b4 | ||
|
|
062d6bd47a | ||
|
|
b05c5dd1be | ||
|
|
9ea1050281 | ||
|
|
2776a3197b | ||
|
|
670de11dca | ||
|
|
a79deafc6d | ||
|
|
65e4ae4ff4 | ||
|
|
00d7f8e567 | ||
|
|
414ee1db4b | ||
|
|
56c7e164f0 | ||
|
|
81b0ab53cf | ||
|
|
9849931500 | ||
|
|
e7c48fac9b | ||
|
|
899e2ada15 | ||
|
|
6a722602e6 | ||
|
|
d3dcb04f2d | ||
|
|
291ee89684 | ||
|
|
876b1fb842 | ||
|
|
32754d806d | ||
|
|
9e3c73110a | ||
|
|
4225b7bf57 | ||
|
|
7ccea9222c | ||
|
|
52cf07d266 | ||
|
|
25f1658fce | ||
|
|
5f43a42ee7 | ||
|
|
a5fbf27843 | ||
|
|
294682a25a | ||
|
|
f645d1f911 | ||
|
|
8973d12cda | ||
|
|
81cb887baf | ||
|
|
3134d5290b | ||
|
|
3e5b3a33fa | ||
|
|
8690ba923c | ||
|
|
36c478cd6e | ||
|
|
178858f1bd | ||
|
|
385fd3d918 | ||
|
|
dcaa58744e | ||
|
|
9ae03f4589 | ||
|
|
708fa36750 | ||
|
|
d58bb54e7f | ||
|
|
0c7974dd4d | ||
|
|
22792c696f | ||
|
|
61b85b1436 | ||
|
|
cc6c4d807b | ||
|
|
c5020c6e8e | ||
|
|
1eec38dc36 | ||
|
|
e556e647f4 | ||
|
|
86a192681e | ||
|
|
48df9ed715 | ||
|
|
ccdcebcf03 | ||
|
|
9a4b7998cf | ||
|
|
87241089e1 | ||
|
|
96e1e582ff | ||
|
|
4f33fbfc07 | ||
|
|
2d53466fa9 | ||
|
|
f5741d4277 | ||
|
|
0b606dcccd | ||
|
|
c4c70669d1 | ||
|
|
ee87f5ee49 | ||
|
|
a5632fe1db | ||
|
|
e8e1084267 | ||
|
|
ec0b2f900c | ||
|
|
b179f8e1a4 | ||
|
|
62d01d3cf4 | ||
|
|
534dc60672 | ||
|
|
38d916d50f |
@@ -1,5 +1,5 @@
|
||||
project(Eigen)
|
||||
set(EIGEN_VERSION_NUMBER "2.0-beta6")
|
||||
set(EIGEN_VERSION_NUMBER "2.0-rc1")
|
||||
|
||||
#if the svnversion program is absent, this will leave the SVN_REVISION string empty,
|
||||
#but won't stop CMake.
|
||||
@@ -76,6 +76,12 @@ if(MSVC)
|
||||
endif(EIGEN_TEST_SSE2)
|
||||
endif(MSVC)
|
||||
|
||||
option(EIGEN_TEST_NO_EXPLICIT_VECTORIZATION "Disable explicit vectorization in tests/examples" OFF)
|
||||
if(EIGEN_TEST_NO_EXPLICIT_VECTORIZATION)
|
||||
add_definitions(-DEIGEN_DONT_VECTORIZE=1)
|
||||
message("Disabling vectorization in tests/examples")
|
||||
endif(EIGEN_TEST_NO_EXPLICIT_VECTORIZATION)
|
||||
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
add_subdirectory(Eigen)
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
/** \defgroup Array Array module
|
||||
/** \defgroup Array_Module Array module
|
||||
* This module provides several handy features to manipulate matrices as simple array of values.
|
||||
* In addition to listed classes, it defines various methods of the Cwise interface
|
||||
* (accessible from MatrixBase::cwise()), including:
|
||||
@@ -26,7 +26,7 @@ namespace Eigen {
|
||||
|
||||
#include "src/Array/CwiseOperators.h"
|
||||
#include "src/Array/Functors.h"
|
||||
#include "src/Array/AllAndAny.h"
|
||||
#include "src/Array/BooleanRedux.h"
|
||||
#include "src/Array/Select.h"
|
||||
#include "src/Array/PartialRedux.h"
|
||||
#include "src/Array/Random.h"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
set(Eigen_HEADERS Core LU Cholesky QR Geometry Sparse Array SVD Regression LeastSquares StdVector)
|
||||
set(Eigen_HEADERS Core LU Cholesky QR Geometry Sparse Array SVD LeastSquares QtAlignedMalloc StdVector)
|
||||
|
||||
if(EIGEN_BUILD_LIB)
|
||||
set(Eigen_SRCS
|
||||
|
||||
@@ -17,6 +17,9 @@
|
||||
namespace Eigen {
|
||||
|
||||
/** \defgroup Cholesky_Module Cholesky module
|
||||
*
|
||||
* \nonstableyet
|
||||
*
|
||||
* This module provides two variants of the Cholesky decomposition for selfadjoint (hermitian) matrices.
|
||||
* Those decompositions are accessible via the following MatrixBase methods:
|
||||
* - MatrixBase::llt(),
|
||||
@@ -31,8 +34,6 @@ namespace Eigen {
|
||||
#include "src/Array/Functors.h"
|
||||
#include "src/Cholesky/LLT.h"
|
||||
#include "src/Cholesky/LDLT.h"
|
||||
#include "src/Cholesky/Cholesky.h"
|
||||
#include "src/Cholesky/CholeskyWithoutSquareRoot.h"
|
||||
|
||||
} // namespace Eigen
|
||||
|
||||
|
||||
@@ -69,6 +69,13 @@
|
||||
#include <new>
|
||||
#endif
|
||||
|
||||
// this needs to be done after all possible windows C header includes and before any Eigen source includes
|
||||
// (system C++ includes are supposed to be able to deal with this already):
|
||||
// windows.h defines min and max macros which would make Eigen fail to compile.
|
||||
#if defined(min) || defined(max)
|
||||
#error The preprocessor symbols 'min' or 'max' are defined. If you are compiling on Windows, do #define NOMINMAX to prevent windows.h from defining these symbols.
|
||||
#endif
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
/** \defgroup Core_Module Core module
|
||||
|
||||
@@ -14,7 +14,10 @@
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
/** \defgroup GeometryModule Geometry module
|
||||
/** \defgroup Geometry_Module Geometry module
|
||||
*
|
||||
* \nonstableyet
|
||||
*
|
||||
* This module provides support for:
|
||||
* - fixed-size homogeneous transformations
|
||||
* - translation, scaling, 2D and 3D rotations
|
||||
|
||||
@@ -11,15 +11,15 @@
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
/** \defgroup Regression_Module Regression module
|
||||
/** \defgroup LeastSquares_Module LeastSquares module
|
||||
* This module provides linear regression and related features.
|
||||
*
|
||||
* \code
|
||||
* #include <Eigen/Regression>
|
||||
* #include <Eigen/LeastSquares>
|
||||
* \endcode
|
||||
*/
|
||||
|
||||
#include "src/Regression/Regression.h"
|
||||
#include "src/LeastSquares/LeastSquares.h"
|
||||
|
||||
} // namespace Eigen
|
||||
|
||||
|
||||
3
Eigen/QR
3
Eigen/QR
@@ -19,6 +19,9 @@
|
||||
namespace Eigen {
|
||||
|
||||
/** \defgroup QR_Module QR module
|
||||
*
|
||||
* \nonstableyet
|
||||
*
|
||||
* This module mainly provides QR decomposition and an eigen value solver.
|
||||
* This module also provides some MatrixBase methods, including:
|
||||
* - MatrixBase::qr(),
|
||||
|
||||
29
Eigen/QtAlignedMalloc
Normal file
29
Eigen/QtAlignedMalloc
Normal file
@@ -0,0 +1,29 @@
|
||||
|
||||
#ifndef EIGEN_QTMALLOC_MODULE_H
|
||||
#define EIGEN_QTMALLOC_MODULE_H
|
||||
|
||||
#include "Core"
|
||||
|
||||
#if (!EIGEN_MALLOC_ALREADY_ALIGNED)
|
||||
|
||||
inline void *qMalloc(size_t size)
|
||||
{
|
||||
return Eigen::ei_aligned_malloc(size);
|
||||
}
|
||||
|
||||
inline void qFree(void *ptr)
|
||||
{
|
||||
Eigen::ei_aligned_free(ptr);
|
||||
}
|
||||
|
||||
inline void *qRealloc(void *ptr, size_t size)
|
||||
{
|
||||
void* newPtr = Eigen::ei_aligned_malloc(size);
|
||||
memcpy(newPtr, ptr, size);
|
||||
Eigen::ei_aligned_free(ptr);
|
||||
return newPtr;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif // EIGEN_QTMALLOC_MODULE_H
|
||||
@@ -1,5 +0,0 @@
|
||||
#ifdef __GNUC__
|
||||
#warning "The Eigen/Regression header file has been renamed to Eigen/LeastSquares. The old name is deprecated, please update your code."
|
||||
#endif
|
||||
|
||||
#include "LeastSquares"
|
||||
@@ -8,6 +8,9 @@
|
||||
namespace Eigen {
|
||||
|
||||
/** \defgroup SVD_Module SVD module
|
||||
*
|
||||
* \nonstableyet
|
||||
*
|
||||
* This module provides SVD decomposition for (currently) real matrices.
|
||||
* This decomposition is accessible via the following MatrixBase method:
|
||||
* - MatrixBase::svd()
|
||||
|
||||
23
Eigen/Sparse
23
Eigen/Sparse
@@ -70,16 +70,37 @@
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
/** \defgroup Sparse_Module Sparse module
|
||||
*
|
||||
* \nonstableyet
|
||||
*
|
||||
* See the \ref TutorialSparse "Sparse tutorial"
|
||||
*
|
||||
* \code
|
||||
* #include <Eigen/QR>
|
||||
* \endcode
|
||||
*/
|
||||
|
||||
#include "src/Sparse/SparseUtil.h"
|
||||
#include "src/Sparse/SparseMatrixBase.h"
|
||||
#include "src/Sparse/SparseArray.h"
|
||||
#include "src/Sparse/CompressedStorage.h"
|
||||
#include "src/Sparse/AmbiVector.h"
|
||||
#include "src/Sparse/RandomSetter.h"
|
||||
#include "src/Sparse/SparseBlock.h"
|
||||
#include "src/Sparse/SparseMatrix.h"
|
||||
#include "src/Sparse/DynamicSparseMatrix.h"
|
||||
#include "src/Sparse/MappedSparseMatrix.h"
|
||||
#include "src/Sparse/SparseVector.h"
|
||||
#include "src/Sparse/CoreIterators.h"
|
||||
#include "src/Sparse/SparseTranspose.h"
|
||||
#include "src/Sparse/SparseCwise.h"
|
||||
#include "src/Sparse/SparseCwiseUnaryOp.h"
|
||||
#include "src/Sparse/SparseCwiseBinaryOp.h"
|
||||
#include "src/Sparse/SparseDot.h"
|
||||
#include "src/Sparse/SparseAssign.h"
|
||||
#include "src/Sparse/SparseRedux.h"
|
||||
#include "src/Sparse/SparseFuzzy.h"
|
||||
#include "src/Sparse/SparseFlagged.h"
|
||||
#include "src/Sparse/SparseProduct.h"
|
||||
#include "src/Sparse/TriangularSolver.h"
|
||||
#include "src/Sparse/SparseLLT.h"
|
||||
|
||||
@@ -89,7 +89,7 @@ struct ei_any_unroller<Derived, Dynamic>
|
||||
* \sa MatrixBase::any(), Cwise::operator<()
|
||||
*/
|
||||
template<typename Derived>
|
||||
inline bool MatrixBase<Derived>::all(void) const
|
||||
inline bool MatrixBase<Derived>::all() const
|
||||
{
|
||||
const bool unroll = SizeAtCompileTime * (CoeffReadCost + NumTraits<Scalar>::AddCost)
|
||||
<= EIGEN_UNROLLING_LIMIT;
|
||||
@@ -113,7 +113,7 @@ inline bool MatrixBase<Derived>::all(void) const
|
||||
* \sa MatrixBase::all()
|
||||
*/
|
||||
template<typename Derived>
|
||||
inline bool MatrixBase<Derived>::any(void) const
|
||||
inline bool MatrixBase<Derived>::any() const
|
||||
{
|
||||
const bool unroll = SizeAtCompileTime * (CoeffReadCost + NumTraits<Scalar>::AddCost)
|
||||
<= EIGEN_UNROLLING_LIMIT;
|
||||
@@ -130,4 +130,16 @@ inline bool MatrixBase<Derived>::any(void) const
|
||||
}
|
||||
}
|
||||
|
||||
/** \array_module
|
||||
*
|
||||
* \returns the number of coefficients which evaluate to true
|
||||
*
|
||||
* \sa MatrixBase::all(), MatrixBase::any()
|
||||
*/
|
||||
template<typename Derived>
|
||||
inline int MatrixBase<Derived>::count() const
|
||||
{
|
||||
return this->cast<bool>().cast<int>().sum();
|
||||
}
|
||||
|
||||
#endif // EIGEN_ALLANDANY_H
|
||||
@@ -200,7 +200,6 @@ template<typename Scalar>
|
||||
struct ei_functor_traits<ei_scalar_cube_op<Scalar> >
|
||||
{ enum { Cost = 2*NumTraits<Scalar>::MulCost, PacketAccess = int(ei_packet_traits<Scalar>::size)>1 }; };
|
||||
|
||||
|
||||
// default ei_functor_traits for STL functors:
|
||||
|
||||
template<typename T>
|
||||
|
||||
@@ -114,6 +114,7 @@ EIGEN_MEMBER_FUNCTOR(minCoeff, (Size-1)*NumTraits<Scalar>::AddCost);
|
||||
EIGEN_MEMBER_FUNCTOR(maxCoeff, (Size-1)*NumTraits<Scalar>::AddCost);
|
||||
EIGEN_MEMBER_FUNCTOR(all, (Size-1)*NumTraits<Scalar>::AddCost);
|
||||
EIGEN_MEMBER_FUNCTOR(any, (Size-1)*NumTraits<Scalar>::AddCost);
|
||||
EIGEN_MEMBER_FUNCTOR(count, (Size-1)*NumTraits<Scalar>::AddCost);
|
||||
|
||||
/** \internal */
|
||||
template <typename BinaryOp, typename Scalar>
|
||||
@@ -173,7 +174,7 @@ template<typename ExpressionType, int Direction> class PartialRedux
|
||||
};
|
||||
|
||||
typedef typename ExpressionType::PlainMatrixType CrossReturnType;
|
||||
|
||||
|
||||
inline PartialRedux(const ExpressionType& matrix) : m_matrix(matrix) {}
|
||||
|
||||
/** \internal */
|
||||
@@ -246,6 +247,16 @@ template<typename ExpressionType, int Direction> class PartialRedux
|
||||
* \sa MatrixBase::any() */
|
||||
const typename ReturnType<ei_member_any>::Type any() const
|
||||
{ return _expression(); }
|
||||
|
||||
/** \returns a row (or column) vector expression representing
|
||||
* the number of \c true coefficients of each respective column (or row).
|
||||
*
|
||||
* Example: \include PartialRedux_count.cpp
|
||||
* Output: \verbinclude PartialRedux_count.out
|
||||
*
|
||||
* \sa MatrixBase::count() */
|
||||
const PartialReduxExpr<ExpressionType, ei_member_count<int>, Direction> count() const
|
||||
{ return _expression(); }
|
||||
|
||||
/** \returns a 3x3 matrix expression of the cross product
|
||||
* of each column or row of the referenced expression with the \a other vector.
|
||||
|
||||
@@ -108,6 +108,9 @@ class Select : ei_no_assignment_operator,
|
||||
* \returns a matrix where each coefficient (i,j) is equal to \a thenMatrix(i,j)
|
||||
* if \c *this(i,j), and \a elseMatrix(i,j) otherwise.
|
||||
*
|
||||
* Example: \include MatrixBase_select.cpp
|
||||
* Output: \verbinclude MatrixBase_select.out
|
||||
*
|
||||
* \sa class Select
|
||||
*/
|
||||
template<typename Derived>
|
||||
|
||||
@@ -5,5 +5,6 @@ ADD_SUBDIRECTORY(SVD)
|
||||
ADD_SUBDIRECTORY(Cholesky)
|
||||
ADD_SUBDIRECTORY(Array)
|
||||
ADD_SUBDIRECTORY(Geometry)
|
||||
ADD_SUBDIRECTORY(Regression)
|
||||
ADD_SUBDIRECTORY(LeastSquares)
|
||||
ADD_SUBDIRECTORY(Sparse)
|
||||
ADD_SUBDIRECTORY(StdVector)
|
||||
|
||||
@@ -1,165 +0,0 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
//
|
||||
// Eigen is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 3 of the License, or (at your option) any later version.
|
||||
//
|
||||
// Alternatively, you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of
|
||||
// the License, or (at your option) any later version.
|
||||
//
|
||||
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License and a copy of the GNU General Public License along with
|
||||
// Eigen. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef EIGEN_CHOLESKY_H
|
||||
#define EIGEN_CHOLESKY_H
|
||||
|
||||
/** \ingroup Cholesky_Module
|
||||
*
|
||||
* \class Cholesky
|
||||
*
|
||||
* \deprecated this class has been renamed LLT
|
||||
*/
|
||||
template<typename MatrixType> class Cholesky
|
||||
{
|
||||
private:
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
typedef typename NumTraits<typename MatrixType::Scalar>::Real RealScalar;
|
||||
typedef Matrix<Scalar, MatrixType::ColsAtCompileTime, 1> VectorType;
|
||||
|
||||
enum {
|
||||
PacketSize = ei_packet_traits<Scalar>::size,
|
||||
AlignmentMask = int(PacketSize)-1
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
Cholesky(const MatrixType& matrix)
|
||||
: m_matrix(matrix.rows(), matrix.cols())
|
||||
{
|
||||
compute(matrix);
|
||||
}
|
||||
|
||||
/** \deprecated */
|
||||
inline Part<MatrixType, LowerTriangular> matrixL(void) const { return m_matrix; }
|
||||
|
||||
/** \deprecated */
|
||||
inline bool isPositiveDefinite(void) const { return m_isPositiveDefinite; }
|
||||
|
||||
template<typename Derived>
|
||||
EIGEN_DEPRECATED typename MatrixBase<Derived>::PlainMatrixType_ColMajor solve(const MatrixBase<Derived> &b) const;
|
||||
|
||||
template<typename RhsDerived, typename ResDerived>
|
||||
bool solve(const MatrixBase<RhsDerived> &b, MatrixBase<ResDerived> *result) const;
|
||||
|
||||
template<typename Derived>
|
||||
bool solveInPlace(MatrixBase<Derived> &bAndX) const;
|
||||
|
||||
void compute(const MatrixType& matrix);
|
||||
|
||||
protected:
|
||||
/** \internal
|
||||
* Used to compute and store L
|
||||
* The strict upper part is not used and even not initialized.
|
||||
*/
|
||||
MatrixType m_matrix;
|
||||
bool m_isPositiveDefinite;
|
||||
};
|
||||
|
||||
/** \deprecated */
|
||||
template<typename MatrixType>
|
||||
void Cholesky<MatrixType>::compute(const MatrixType& a)
|
||||
{
|
||||
assert(a.rows()==a.cols());
|
||||
const int size = a.rows();
|
||||
m_matrix.resize(size, size);
|
||||
const RealScalar eps = ei_sqrt(precision<Scalar>());
|
||||
|
||||
RealScalar x;
|
||||
x = ei_real(a.coeff(0,0));
|
||||
m_isPositiveDefinite = x > eps && ei_isMuchSmallerThan(ei_imag(a.coeff(0,0)), RealScalar(1));
|
||||
m_matrix.coeffRef(0,0) = ei_sqrt(x);
|
||||
m_matrix.col(0).end(size-1) = a.row(0).end(size-1).adjoint() / ei_real(m_matrix.coeff(0,0));
|
||||
for (int j = 1; j < size; ++j)
|
||||
{
|
||||
Scalar tmp = ei_real(a.coeff(j,j)) - m_matrix.row(j).start(j).squaredNorm();
|
||||
x = ei_real(tmp);
|
||||
if (x < eps || (!ei_isMuchSmallerThan(ei_imag(tmp), RealScalar(1))))
|
||||
{
|
||||
m_isPositiveDefinite = false;
|
||||
return;
|
||||
}
|
||||
m_matrix.coeffRef(j,j) = x = ei_sqrt(x);
|
||||
|
||||
int endSize = size-j-1;
|
||||
if (endSize>0) {
|
||||
// Note that when all matrix columns have good alignment, then the following
|
||||
// product is guaranteed to be optimal with respect to alignment.
|
||||
m_matrix.col(j).end(endSize) =
|
||||
(m_matrix.block(j+1, 0, endSize, j) * m_matrix.row(j).start(j).adjoint()).lazy();
|
||||
|
||||
// FIXME could use a.col instead of a.row
|
||||
m_matrix.col(j).end(endSize) = (a.row(j).end(endSize).adjoint()
|
||||
- m_matrix.col(j).end(endSize) ) / x;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** \deprecated */
|
||||
template<typename MatrixType>
|
||||
template<typename Derived>
|
||||
typename MatrixBase<Derived>::PlainMatrixType_ColMajor Cholesky<MatrixType>::solve(const MatrixBase<Derived> &b) const
|
||||
{
|
||||
const int size = m_matrix.rows();
|
||||
ei_assert(size==b.rows());
|
||||
typename MatrixBase<Derived>::PlainMatrixType_ColMajor x(b);
|
||||
solveInPlace(x);
|
||||
return x;
|
||||
}
|
||||
|
||||
/** \deprecated */
|
||||
template<typename MatrixType>
|
||||
template<typename RhsDerived, typename ResDerived>
|
||||
bool Cholesky<MatrixType>::solve(const MatrixBase<RhsDerived> &b, MatrixBase<ResDerived> *result) const
|
||||
{
|
||||
const int size = m_matrix.rows();
|
||||
ei_assert(size==b.rows() && "Cholesky::solve(): invalid number of rows of the right hand side matrix b");
|
||||
return solveInPlace((*result) = b);
|
||||
}
|
||||
|
||||
/** \deprecated */
|
||||
template<typename MatrixType>
|
||||
template<typename Derived>
|
||||
bool Cholesky<MatrixType>::solveInPlace(MatrixBase<Derived> &bAndX) const
|
||||
{
|
||||
const int size = m_matrix.rows();
|
||||
ei_assert(size==bAndX.rows());
|
||||
if (!m_isPositiveDefinite)
|
||||
return false;
|
||||
matrixL().solveTriangularInPlace(bAndX);
|
||||
m_matrix.adjoint().template part<UpperTriangular>().solveTriangularInPlace(bAndX);
|
||||
return true;
|
||||
}
|
||||
|
||||
/** \cholesky_module
|
||||
* \deprecated has been renamed llt()
|
||||
*/
|
||||
template<typename Derived>
|
||||
inline const Cholesky<typename MatrixBase<Derived>::PlainMatrixType>
|
||||
MatrixBase<Derived>::cholesky() const
|
||||
{
|
||||
return Cholesky<PlainMatrixType>(derived());
|
||||
}
|
||||
|
||||
#endif // EIGEN_CHOLESKY_H
|
||||
@@ -1,184 +0,0 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
//
|
||||
// Eigen is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 3 of the License, or (at your option) any later version.
|
||||
//
|
||||
// Alternatively, you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of
|
||||
// the License, or (at your option) any later version.
|
||||
//
|
||||
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License and a copy of the GNU General Public License along with
|
||||
// Eigen. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef EIGEN_CHOLESKY_WITHOUT_SQUARE_ROOT_H
|
||||
#define EIGEN_CHOLESKY_WITHOUT_SQUARE_ROOT_H
|
||||
|
||||
/** \deprecated \ingroup Cholesky_Module
|
||||
*
|
||||
* \class CholeskyWithoutSquareRoot
|
||||
*
|
||||
* \deprecated this class has been renamed LDLT
|
||||
*/
|
||||
template<typename MatrixType> class CholeskyWithoutSquareRoot
|
||||
{
|
||||
public:
|
||||
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
typedef typename NumTraits<typename MatrixType::Scalar>::Real RealScalar;
|
||||
typedef Matrix<Scalar, MatrixType::ColsAtCompileTime, 1> VectorType;
|
||||
|
||||
CholeskyWithoutSquareRoot(const MatrixType& matrix)
|
||||
: m_matrix(matrix.rows(), matrix.cols())
|
||||
{
|
||||
compute(matrix);
|
||||
}
|
||||
|
||||
/** \returns the lower triangular matrix L */
|
||||
inline Part<MatrixType, UnitLowerTriangular> matrixL(void) const { return m_matrix; }
|
||||
|
||||
/** \returns the coefficients of the diagonal matrix D */
|
||||
inline DiagonalCoeffs<MatrixType> vectorD(void) const { return m_matrix.diagonal(); }
|
||||
|
||||
/** \returns true if the matrix is positive definite */
|
||||
inline bool isPositiveDefinite(void) const { return m_isPositiveDefinite; }
|
||||
|
||||
template<typename Derived>
|
||||
EIGEN_DEPRECATED typename Derived::Eval solve(const MatrixBase<Derived> &b) const;
|
||||
|
||||
template<typename RhsDerived, typename ResDerived>
|
||||
bool solve(const MatrixBase<RhsDerived> &b, MatrixBase<ResDerived> *result) const;
|
||||
|
||||
template<typename Derived>
|
||||
bool solveInPlace(MatrixBase<Derived> &bAndX) const;
|
||||
|
||||
void compute(const MatrixType& matrix);
|
||||
|
||||
protected:
|
||||
/** \internal
|
||||
* Used to compute and store the cholesky decomposition A = L D L^* = U^* D U.
|
||||
* The strict upper part is used during the decomposition, the strict lower
|
||||
* part correspond to the coefficients of L (its diagonal is equal to 1 and
|
||||
* is not stored), and the diagonal entries correspond to D.
|
||||
*/
|
||||
MatrixType m_matrix;
|
||||
|
||||
bool m_isPositiveDefinite;
|
||||
};
|
||||
|
||||
/** \deprecated */
|
||||
template<typename MatrixType>
|
||||
void CholeskyWithoutSquareRoot<MatrixType>::compute(const MatrixType& a)
|
||||
{
|
||||
assert(a.rows()==a.cols());
|
||||
const int size = a.rows();
|
||||
m_matrix.resize(size, size);
|
||||
m_isPositiveDefinite = true;
|
||||
const RealScalar eps = ei_sqrt(precision<Scalar>());
|
||||
|
||||
if (size<=1)
|
||||
{
|
||||
m_matrix = a;
|
||||
return;
|
||||
}
|
||||
|
||||
// Let's preallocate a temporay vector to evaluate the matrix-vector product into it.
|
||||
// Unlike the standard Cholesky decomposition, here we cannot evaluate it to the destination
|
||||
// matrix because it a sub-row which is not compatible suitable for efficient packet evaluation.
|
||||
// (at least if we assume the matrix is col-major)
|
||||
Matrix<Scalar,MatrixType::RowsAtCompileTime,1> _temporary(size);
|
||||
|
||||
// Note that, in this algorithm the rows of the strict upper part of m_matrix is used to store
|
||||
// column vector, thus the strange .conjugate() and .transpose()...
|
||||
|
||||
m_matrix.row(0) = a.row(0).conjugate();
|
||||
m_matrix.col(0).end(size-1) = m_matrix.row(0).end(size-1) / m_matrix.coeff(0,0);
|
||||
for (int j = 1; j < size; ++j)
|
||||
{
|
||||
RealScalar tmp = ei_real(a.coeff(j,j) - (m_matrix.row(j).start(j) * m_matrix.col(j).start(j).conjugate()).coeff(0,0));
|
||||
m_matrix.coeffRef(j,j) = tmp;
|
||||
|
||||
if (tmp < eps)
|
||||
{
|
||||
m_isPositiveDefinite = false;
|
||||
return;
|
||||
}
|
||||
|
||||
int endSize = size-j-1;
|
||||
if (endSize>0)
|
||||
{
|
||||
_temporary.end(endSize) = ( m_matrix.block(j+1,0, endSize, j)
|
||||
* m_matrix.col(j).start(j).conjugate() ).lazy();
|
||||
|
||||
m_matrix.row(j).end(endSize) = a.row(j).end(endSize).conjugate()
|
||||
- _temporary.end(endSize).transpose();
|
||||
|
||||
m_matrix.col(j).end(endSize) = m_matrix.row(j).end(endSize) / tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** \deprecated */
|
||||
template<typename MatrixType>
|
||||
template<typename Derived>
|
||||
typename Derived::Eval CholeskyWithoutSquareRoot<MatrixType>::solve(const MatrixBase<Derived> &b) const
|
||||
{
|
||||
const int size = m_matrix.rows();
|
||||
ei_assert(size==b.rows());
|
||||
|
||||
return m_matrix.adjoint().template part<UnitUpperTriangular>()
|
||||
.solveTriangular(
|
||||
( m_matrix.cwise().inverse().template part<Diagonal>()
|
||||
* matrixL().solveTriangular(b))
|
||||
);
|
||||
}
|
||||
|
||||
/** \deprecated */
|
||||
template<typename MatrixType>
|
||||
template<typename RhsDerived, typename ResDerived>
|
||||
bool CholeskyWithoutSquareRoot<MatrixType>
|
||||
::solve(const MatrixBase<RhsDerived> &b, MatrixBase<ResDerived> *result) const
|
||||
{
|
||||
const int size = m_matrix.rows();
|
||||
ei_assert(size==b.rows() && "Cholesky::solve(): invalid number of rows of the right hand side matrix b");
|
||||
*result = b;
|
||||
return solveInPlace(*result);
|
||||
}
|
||||
|
||||
/** \deprecated */
|
||||
template<typename MatrixType>
|
||||
template<typename Derived>
|
||||
bool CholeskyWithoutSquareRoot<MatrixType>::solveInPlace(MatrixBase<Derived> &bAndX) const
|
||||
{
|
||||
const int size = m_matrix.rows();
|
||||
ei_assert(size==bAndX.rows());
|
||||
if (!m_isPositiveDefinite)
|
||||
return false;
|
||||
matrixL().solveTriangularInPlace(bAndX);
|
||||
bAndX = (m_matrix.cwise().inverse().template part<Diagonal>() * bAndX).lazy();
|
||||
m_matrix.adjoint().template part<UnitUpperTriangular>().solveTriangularInPlace(bAndX);
|
||||
return true;
|
||||
}
|
||||
|
||||
/** \cholesky_module
|
||||
* \deprecated has been renamed ldlt()
|
||||
*/
|
||||
template<typename Derived>
|
||||
inline const CholeskyWithoutSquareRoot<typename MatrixBase<Derived>::PlainMatrixType>
|
||||
MatrixBase<Derived>::choleskyNoSqrt() const
|
||||
{
|
||||
return derived();
|
||||
}
|
||||
|
||||
#endif // EIGEN_CHOLESKY_WITHOUT_SQUARE_ROOT_H
|
||||
@@ -401,6 +401,8 @@ EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>
|
||||
::lazyAssign(const MatrixBase<OtherDerived>& other)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(Derived,OtherDerived)
|
||||
EIGEN_STATIC_ASSERT((ei_is_same_type<typename Derived::Scalar, typename OtherDerived::Scalar>::ret),
|
||||
YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
|
||||
ei_assert(rows() == other.rows() && cols() == other.cols());
|
||||
ei_assign_impl<Derived, OtherDerived>::run(derived(),other.derived());
|
||||
return derived();
|
||||
@@ -437,8 +439,6 @@ template<typename OtherDerived>
|
||||
EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>
|
||||
::operator=(const MatrixBase<OtherDerived>& other)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT((ei_is_same_type<Scalar, typename OtherDerived::Scalar>::ret),
|
||||
YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
|
||||
return ei_assign_selector<Derived,OtherDerived>::run(derived(), other.derived());
|
||||
}
|
||||
|
||||
|
||||
@@ -146,8 +146,6 @@ template<typename MatrixType, int BlockRows, int BlockCols, int PacketAccess, in
|
||||
inline int rows() const { return m_blockRows.value(); }
|
||||
inline int cols() const { return m_blockCols.value(); }
|
||||
|
||||
inline int stride(void) const { return m_matrix.stride(); }
|
||||
|
||||
inline Scalar& coeffRef(int row, int col)
|
||||
{
|
||||
return m_matrix.const_cast_derived()
|
||||
|
||||
@@ -81,7 +81,7 @@ static void ei_cache_friendly_product(
|
||||
MaxBlockRows_ClampingMask = 0xFFFFF8,
|
||||
#endif
|
||||
// maximal size of the blocks fitted in L2 cache
|
||||
MaxL2BlockSize = ei_L2_block_traits<EIGEN_TUNE_FOR_L2_CACHE_SIZE,Scalar>::width
|
||||
MaxL2BlockSize = ei_L2_block_traits<EIGEN_TUNE_FOR_CPU_CACHE_SIZE,Scalar>::width
|
||||
};
|
||||
|
||||
const bool resIsAligned = (PacketSize==1) || (((resStride%PacketSize) == 0) && (size_t(res)%16==0));
|
||||
@@ -433,8 +433,13 @@ static EIGEN_DONT_INLINE void ei_cache_friendly_product_colmajor_times_vector(
|
||||
{
|
||||
/* explicit vectorization */
|
||||
// process initial unaligned coeffs
|
||||
for (int j=0; j<alignedStart; ++j)
|
||||
res[j] += ei_pfirst(ptmp0)*lhs0[j] + ei_pfirst(ptmp1)*lhs1[j] + ei_pfirst(ptmp2)*lhs2[j] + ei_pfirst(ptmp3)*lhs3[j];
|
||||
for (int j=0; j<alignedStart; ++j) {
|
||||
Scalar s = ei_pfirst(ptmp0)*lhs0[j];
|
||||
s += ei_pfirst(ptmp1)*lhs1[j];
|
||||
s += ei_pfirst(ptmp2)*lhs2[j];
|
||||
s += ei_pfirst(ptmp3)*lhs3[j];
|
||||
res[j] += s;
|
||||
}
|
||||
|
||||
if (alignedSize>alignedStart)
|
||||
{
|
||||
|
||||
@@ -313,6 +313,8 @@ EIGEN_STRONG_INLINE void MatrixBase<Derived>::writePacket
|
||||
derived().template writePacket<StoreMode>(index,x);
|
||||
}
|
||||
|
||||
#ifndef EIGEN_PARSED_BY_DOXYGEN
|
||||
|
||||
/** \internal Copies the coefficient at position (row,col) of other into *this.
|
||||
*
|
||||
* This method is overridden in SwapWrapper, allowing swap() assignments to share 99% of their code
|
||||
@@ -377,4 +379,6 @@ EIGEN_STRONG_INLINE void MatrixBase<Derived>::copyPacket(int index, const Matrix
|
||||
other.derived().template packet<LoadMode>(index));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif // EIGEN_COEFFS_H
|
||||
|
||||
@@ -171,6 +171,11 @@ template<typename ExpressionType> class Cwise
|
||||
const EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(std::not_equal_to)
|
||||
operator!=(Scalar s) const;
|
||||
|
||||
// allow to extend Cwise outside Eigen
|
||||
#ifdef EIGEN_CWISE_PLUGIN
|
||||
#include EIGEN_CWISE_PLUGIN
|
||||
#endif
|
||||
|
||||
protected:
|
||||
ExpressionTypeNested m_matrix;
|
||||
};
|
||||
|
||||
@@ -86,14 +86,12 @@ class CwiseBinaryOp : ei_no_assignment_operator,
|
||||
typedef typename ei_traits<CwiseBinaryOp>::LhsNested LhsNested;
|
||||
typedef typename ei_traits<CwiseBinaryOp>::RhsNested RhsNested;
|
||||
|
||||
class InnerIterator;
|
||||
|
||||
EIGEN_STRONG_INLINE CwiseBinaryOp(const Lhs& lhs, const Rhs& rhs, const BinaryOp& func = BinaryOp())
|
||||
: m_lhs(lhs), m_rhs(rhs), m_functor(func)
|
||||
{
|
||||
// we require Lhs and Rhs to have the same scalar type. Currently there is no example of a binary functor
|
||||
// that would take two operands of different types. If there were such an example, then this check should be
|
||||
// moved to the BinaryOp functors, on a per-case basis. This would however require a change in the BinaryOp functors, as
|
||||
// moved to the BinaryOp functors, on a per-case basis. This would however require a change in the BinaryOp functors, as
|
||||
// currently they take only one typename Scalar template parameter.
|
||||
// It is tempting to always allow mixing different types but remember that this is often impossible in the vectorized paths.
|
||||
// So allowing mixing different types gives very unexpected errors when enabling vectorization, when the user tries to
|
||||
|
||||
@@ -238,9 +238,19 @@ bool MatrixBase<Derived>::isApproxToConstant
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Alias for setConstant(): sets all coefficients in this expression to \a value.
|
||||
*
|
||||
* \sa setConstant(), Constant(), class CwiseNullaryOp
|
||||
*/
|
||||
template<typename Derived>
|
||||
EIGEN_STRONG_INLINE void MatrixBase<Derived>::fill(const Scalar& value)
|
||||
{
|
||||
setConstant(value);
|
||||
}
|
||||
|
||||
/** Sets all coefficients in this expression to \a value.
|
||||
*
|
||||
* \sa class CwiseNullaryOp, Zero(), Ones()
|
||||
* \sa fill(), Constant(), class CwiseNullaryOp, setZero(), setOnes()
|
||||
*/
|
||||
template<typename Derived>
|
||||
EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>::setConstant(const Scalar& value)
|
||||
|
||||
@@ -64,8 +64,6 @@ class CwiseUnaryOp : ei_no_assignment_operator,
|
||||
|
||||
EIGEN_GENERIC_PUBLIC_INTERFACE(CwiseUnaryOp)
|
||||
|
||||
class InnerIterator;
|
||||
|
||||
inline CwiseUnaryOp(const MatrixType& mat, const UnaryOp& func = UnaryOp())
|
||||
: m_matrix(mat), m_functor(func) {}
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#define EIGEN_DIAGONALMATRIX_H
|
||||
|
||||
/** \class DiagonalMatrix
|
||||
* \nonstableyet
|
||||
*
|
||||
* \brief Expression of a diagonal matrix
|
||||
*
|
||||
@@ -91,7 +92,8 @@ class DiagonalMatrix : ei_no_assignment_operator,
|
||||
const typename CoeffsVectorType::Nested m_coeffs;
|
||||
};
|
||||
|
||||
/** \returns an expression of a diagonal matrix with *this as vector of diagonal coefficients
|
||||
/** \nonstableyet
|
||||
* \returns an expression of a diagonal matrix with *this as vector of diagonal coefficients
|
||||
*
|
||||
* \only_for_vectors
|
||||
*
|
||||
@@ -109,7 +111,8 @@ MatrixBase<Derived>::asDiagonal() const
|
||||
return derived();
|
||||
}
|
||||
|
||||
/** \returns true if *this is approximately equal to a diagonal matrix,
|
||||
/** \nonstableyet
|
||||
* \returns true if *this is approximately equal to a diagonal matrix,
|
||||
* within the precision given by \a prec.
|
||||
*
|
||||
* Example: \include MatrixBase_isDiagonal.cpp
|
||||
|
||||
@@ -73,7 +73,7 @@ struct ei_traits<Product<LhsNested, RhsNested, DiagonalProduct> >
|
||||
RemovedBits = ~((RhsFlags & RowMajorBit) && (!CanVectorizeLhs) ? 0 : RowMajorBit),
|
||||
|
||||
Flags = ((unsigned int)(LhsFlags | RhsFlags) & HereditaryBits & RemovedBits)
|
||||
| (CanVectorizeLhs || CanVectorizeRhs ? PacketAccessBit : 0),
|
||||
| (((CanVectorizeLhs&&RhsIsDiagonal) || (CanVectorizeRhs&&LhsIsDiagonal)) ? PacketAccessBit : 0),
|
||||
|
||||
CoeffReadCost = NumTraits<Scalar>::MulCost + _LhsNested::CoeffReadCost + _RhsNested::CoeffReadCost
|
||||
};
|
||||
@@ -114,12 +114,10 @@ template<typename LhsNested, typename RhsNested> class Product<LhsNested, RhsNes
|
||||
{
|
||||
if (RhsIsDiagonal)
|
||||
{
|
||||
ei_assert((_LhsNested::Flags&RowMajorBit)==0);
|
||||
return ei_pmul(m_lhs.template packet<LoadMode>(row, col), ei_pset1(m_rhs.coeff(col, col)));
|
||||
}
|
||||
else
|
||||
{
|
||||
ei_assert(_RhsNested::Flags&RowMajorBit);
|
||||
return ei_pmul(ei_pset1(m_lhs.coeff(row, row)), m_rhs.template packet<LoadMode>(row, col));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,13 +143,12 @@ struct ei_dot_vec_unroller<Derived1, Derived2, Index, Stop, true>
|
||||
|
||||
template<typename Derived1, typename Derived2,
|
||||
int Vectorization = ei_dot_traits<Derived1, Derived2>::Vectorization,
|
||||
int Unrolling = ei_dot_traits<Derived1, Derived2>::Unrolling,
|
||||
int Storage = (ei_traits<Derived1>::Flags | ei_traits<Derived2>::Flags) & SparseBit
|
||||
int Unrolling = ei_dot_traits<Derived1, Derived2>::Unrolling
|
||||
>
|
||||
struct ei_dot_impl;
|
||||
|
||||
template<typename Derived1, typename Derived2>
|
||||
struct ei_dot_impl<Derived1, Derived2, NoVectorization, NoUnrolling, IsDense>
|
||||
struct ei_dot_impl<Derived1, Derived2, NoVectorization, NoUnrolling>
|
||||
{
|
||||
typedef typename Derived1::Scalar Scalar;
|
||||
static Scalar run(const Derived1& v1, const Derived2& v2)
|
||||
@@ -164,12 +163,12 @@ struct ei_dot_impl<Derived1, Derived2, NoVectorization, NoUnrolling, IsDense>
|
||||
};
|
||||
|
||||
template<typename Derived1, typename Derived2>
|
||||
struct ei_dot_impl<Derived1, Derived2, NoVectorization, CompleteUnrolling, IsDense>
|
||||
struct ei_dot_impl<Derived1, Derived2, NoVectorization, CompleteUnrolling>
|
||||
: public ei_dot_novec_unroller<Derived1, Derived2, 0, Derived1::SizeAtCompileTime>
|
||||
{};
|
||||
|
||||
template<typename Derived1, typename Derived2>
|
||||
struct ei_dot_impl<Derived1, Derived2, LinearVectorization, NoUnrolling, IsDense>
|
||||
struct ei_dot_impl<Derived1, Derived2, LinearVectorization, NoUnrolling>
|
||||
{
|
||||
typedef typename Derived1::Scalar Scalar;
|
||||
typedef typename ei_packet_traits<Scalar>::type PacketScalar;
|
||||
@@ -222,7 +221,7 @@ struct ei_dot_impl<Derived1, Derived2, LinearVectorization, NoUnrolling, IsDense
|
||||
};
|
||||
|
||||
template<typename Derived1, typename Derived2>
|
||||
struct ei_dot_impl<Derived1, Derived2, LinearVectorization, CompleteUnrolling, IsDense>
|
||||
struct ei_dot_impl<Derived1, Derived2, LinearVectorization, CompleteUnrolling>
|
||||
{
|
||||
typedef typename Derived1::Scalar Scalar;
|
||||
typedef typename ei_packet_traits<Scalar>::type PacketScalar;
|
||||
@@ -270,25 +269,7 @@ MatrixBase<Derived>::dot(const MatrixBase<OtherDerived>& other) const
|
||||
return ei_dot_impl<Derived, OtherDerived>::run(derived(), other.derived());
|
||||
}
|
||||
|
||||
/** \returns the squared norm of *this, i.e. the dot product of *this with itself.
|
||||
*
|
||||
* \note This is \em not the \em l2 norm, but its square.
|
||||
*
|
||||
* \deprecated Use squaredNorm() instead. This norm2() function is kept only for compatibility and will be removed in Eigen 2.0.
|
||||
*
|
||||
* \only_for_vectors
|
||||
*
|
||||
* \sa dot(), norm()
|
||||
*/
|
||||
template<typename Derived>
|
||||
EIGEN_DEPRECATED inline typename NumTraits<typename ei_traits<Derived>::Scalar>::Real MatrixBase<Derived>::norm2() const
|
||||
{
|
||||
return ei_real((*this).cwise().abs2().sum());
|
||||
}
|
||||
|
||||
/** \returns the squared norm of *this, i.e. the dot product of *this with itself.
|
||||
*
|
||||
* \only_for_vectors
|
||||
/** \returns the squared \em l2 norm of *this, i.e., for vectors, the dot product of *this with itself.
|
||||
*
|
||||
* \sa dot(), norm()
|
||||
*/
|
||||
@@ -298,9 +279,7 @@ inline typename NumTraits<typename ei_traits<Derived>::Scalar>::Real MatrixBase<
|
||||
return ei_real((*this).cwise().abs2().sum());
|
||||
}
|
||||
|
||||
/** \returns the \em l2 norm of *this, i.e. the square root of the dot product of *this with itself.
|
||||
*
|
||||
* \only_for_vectors
|
||||
/** \returns the \em l2 norm of *this, i.e., for vectors, the square root of the dot product of *this with itself.
|
||||
*
|
||||
* \sa dot(), squaredNorm()
|
||||
*/
|
||||
|
||||
@@ -348,6 +348,12 @@ template<typename Scalar>
|
||||
struct ei_functor_traits<ei_scalar_identity_op<Scalar> >
|
||||
{ enum { Cost = NumTraits<Scalar>::AddCost, PacketAccess = false, IsRepeatable = true }; };
|
||||
|
||||
// allow to add new functors and specializations of ei_functor_traits from outside Eigen.
|
||||
// this macro is really needed because ei_functor_traits must be specialized after it is declared but before it is used...
|
||||
#ifdef EIGEN_FUNCTORS_PLUGIN
|
||||
#include EIGEN_FUNCTORS_PLUGIN
|
||||
#endif
|
||||
|
||||
// all functors allow linear access, except ei_scalar_identity_op. So we fix here a quick meta
|
||||
// to indicate whether a functor allows linear access, just always answering 'yes' except for
|
||||
// ei_scalar_identity_op.
|
||||
|
||||
@@ -85,7 +85,7 @@ template<typename MatrixType, int PacketAccess> class Map
|
||||
EIGEN_ONLY_USED_FOR_DEBUG(rows);
|
||||
EIGEN_ONLY_USED_FOR_DEBUG(cols);
|
||||
ei_assert(rows == this->rows());
|
||||
ei_assert(rows == this->cols());
|
||||
ei_assert(cols == this->cols());
|
||||
}
|
||||
|
||||
inline void resize(int size)
|
||||
@@ -102,17 +102,13 @@ template<typename MatrixType, int PacketAccess> class Map
|
||||
* Only for fixed-size matrices and vectors.
|
||||
* \param data The array of data to copy
|
||||
*
|
||||
* For dynamic-size matrices and vectors, see the variants taking additional int parameters
|
||||
* for the dimensions.
|
||||
*
|
||||
* \sa Matrix(const Scalar *, int), Matrix(const Scalar *, int, int),
|
||||
* Matrix::Map(const Scalar *)
|
||||
* \sa Matrix::Map(const Scalar *)
|
||||
*/
|
||||
template<typename _Scalar, int _Rows, int _Cols, int _StorageOrder, int _MaxRows, int _MaxCols>
|
||||
inline Matrix<_Scalar, _Rows, _Cols, _StorageOrder, _MaxRows, _MaxCols>
|
||||
::Matrix(const Scalar *data)
|
||||
{
|
||||
*this = Eigen::Map<Matrix>(data);
|
||||
_set_noalias(Eigen::Map<Matrix>(data));
|
||||
}
|
||||
|
||||
#endif // EIGEN_MAP_H
|
||||
|
||||
@@ -63,6 +63,7 @@ template<typename Derived> class MapBase
|
||||
inline int cols() const { return m_cols.value(); }
|
||||
|
||||
inline int stride() const { return derived().stride(); }
|
||||
inline const Scalar* data() const { return m_data; }
|
||||
|
||||
/** \returns an expression equivalent to \c *this but having the \c PacketAccess constant
|
||||
* set to \c ForceAligned. Must be reimplemented by the derived class. */
|
||||
@@ -149,7 +150,7 @@ template<typename Derived> class MapBase
|
||||
|| ( rows > 0 && (RowsAtCompileTime == Dynamic || RowsAtCompileTime == rows)
|
||||
&& cols > 0 && (ColsAtCompileTime == Dynamic || ColsAtCompileTime == cols)));
|
||||
}
|
||||
|
||||
|
||||
template<typename OtherDerived>
|
||||
Derived& operator+=(const MatrixBase<OtherDerived>& other)
|
||||
{ return derived() = forceAligned() + other; }
|
||||
|
||||
@@ -100,6 +100,7 @@
|
||||
* when the exact numbers of rows and columns are not known are compile-time, but it is known at compile-time that they cannot
|
||||
* exceed a certain value. This happens when taking dynamic-size blocks inside fixed-size matrices: in this case _MaxRows and _MaxCols
|
||||
* are the dimensions of the original matrix, while _Rows and _Cols are Dynamic.</dd>
|
||||
* </dl>
|
||||
*
|
||||
* \see MatrixBase for the majority of the API methods for matrices
|
||||
*/
|
||||
@@ -113,8 +114,7 @@ struct ei_traits<Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols> >
|
||||
MaxRowsAtCompileTime = _MaxRows,
|
||||
MaxColsAtCompileTime = _MaxCols,
|
||||
Flags = ei_compute_matrix_flags<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>::ret,
|
||||
CoeffReadCost = NumTraits<Scalar>::ReadCost,
|
||||
SupportedAccessPatterns = RandomAccessPattern
|
||||
CoeffReadCost = NumTraits<Scalar>::ReadCost
|
||||
};
|
||||
};
|
||||
|
||||
@@ -226,12 +226,11 @@ class Matrix
|
||||
*/
|
||||
inline void resize(int rows, int cols)
|
||||
{
|
||||
ei_assert(rows > 0
|
||||
&& (MaxRowsAtCompileTime == Dynamic || MaxRowsAtCompileTime >= rows)
|
||||
&& (RowsAtCompileTime == Dynamic || RowsAtCompileTime == rows)
|
||||
&& cols > 0
|
||||
&& (MaxColsAtCompileTime == Dynamic || MaxColsAtCompileTime >= cols)
|
||||
&& (ColsAtCompileTime == Dynamic || ColsAtCompileTime == cols));
|
||||
ei_assert(rows > 0 && cols > 0 && "a matrix cannot be resized to 0 size");
|
||||
ei_assert((MaxRowsAtCompileTime == Dynamic || MaxRowsAtCompileTime >= rows)
|
||||
&& (RowsAtCompileTime == Dynamic || RowsAtCompileTime == rows)
|
||||
&& (MaxColsAtCompileTime == Dynamic || MaxColsAtCompileTime >= cols)
|
||||
&& (ColsAtCompileTime == Dynamic || ColsAtCompileTime == cols));
|
||||
m_storage.resize(rows * cols, rows, cols);
|
||||
}
|
||||
|
||||
@@ -249,49 +248,19 @@ class Matrix
|
||||
m_storage.resize(size, size, 1);
|
||||
}
|
||||
|
||||
/** Copies the value of the expression \a other into \c *this.
|
||||
*
|
||||
* \warning Note that the sizes of \c *this and \a other must match.
|
||||
* If you want automatic resizing, then you must use the function set().
|
||||
*
|
||||
* As a special exception, copying a row-vector into a vector (and conversely)
|
||||
* is allowed.
|
||||
*
|
||||
* \sa set()
|
||||
*/
|
||||
template<typename OtherDerived>
|
||||
EIGEN_STRONG_INLINE Matrix& operator=(const MatrixBase<OtherDerived>& other)
|
||||
{
|
||||
ei_assert(m_storage.data()!=0 && "you cannot use operator= with a non initialized matrix (instead use set()");
|
||||
return Base::operator=(other.derived());
|
||||
}
|
||||
|
||||
/** Copies the value of the expression \a other into \c *this with automatic resizing.
|
||||
*
|
||||
* This function is the same than the assignment operator = excepted that \c *this might
|
||||
* be resized to match the dimensions of \a other.
|
||||
* *this might be resized to match the dimensions of \a other. If *this was a null matrix (not already initialized),
|
||||
* it will be initialized.
|
||||
*
|
||||
* Note that copying a row-vector into a vector (and conversely) is allowed.
|
||||
* The resizing, if any, is then done in the appropriate way so that row-vectors
|
||||
* remain row-vectors and vectors remain vectors.
|
||||
*
|
||||
* \sa operator=()
|
||||
*/
|
||||
template<typename OtherDerived>
|
||||
inline Matrix& set(const MatrixBase<OtherDerived>& other)
|
||||
EIGEN_STRONG_INLINE Matrix& operator=(const MatrixBase<OtherDerived>& other)
|
||||
{
|
||||
if(RowsAtCompileTime == 1)
|
||||
{
|
||||
ei_assert(other.isVector());
|
||||
resize(1, other.size());
|
||||
}
|
||||
else if(ColsAtCompileTime == 1)
|
||||
{
|
||||
ei_assert(other.isVector());
|
||||
resize(other.size(), 1);
|
||||
}
|
||||
else resize(other.rows(), other.cols());
|
||||
return Base::operator=(other.derived());
|
||||
return _set(other);
|
||||
}
|
||||
|
||||
/** This is a special case of the templated operator=. Its purpose is to
|
||||
@@ -299,7 +268,7 @@ class Matrix
|
||||
*/
|
||||
EIGEN_STRONG_INLINE Matrix& operator=(const Matrix& other)
|
||||
{
|
||||
return operator=<Matrix>(other);
|
||||
return _set(other);
|
||||
}
|
||||
|
||||
EIGEN_INHERIT_ASSIGNMENT_OPERATOR(Matrix, +=)
|
||||
@@ -311,34 +280,23 @@ class Matrix
|
||||
*
|
||||
* For fixed-size matrices, does nothing.
|
||||
*
|
||||
* For dynamic-size matrices, creates an empty matrix of size null.
|
||||
* \warning while creating such an \em null matrix is allowed, it \b cannot
|
||||
* \b be \b used before having being resized or initialized with the function set().
|
||||
* In particular, initializing a null matrix with operator = is not supported.
|
||||
* Finally, this constructor is the unique way to create null matrices: resizing
|
||||
* For dynamic-size matrices, creates an empty matrix of size 0. Does not allocate any array. Such a matrix
|
||||
* is called a null matrix. This constructor is the unique way to create null matrices: resizing
|
||||
* a matrix to 0 is not supported.
|
||||
* Here are some examples:
|
||||
* \code
|
||||
* MatrixXf r = MatrixXf::Random(3,4); // create a random matrix of floats
|
||||
* MatrixXf m1, m2; // creates two null matrices of float
|
||||
*
|
||||
* m1 = r; // illegal (raise an assertion)
|
||||
* r = m1; // illegal (raise an assertion)
|
||||
* m1 = m2; // illegal (raise an assertion)
|
||||
* m1.set(r); // OK
|
||||
* m2.resize(3,4);
|
||||
* m2 = r; // OK
|
||||
* \endcode
|
||||
*
|
||||
* \sa resize(int,int), set()
|
||||
* \sa resize(int,int)
|
||||
*/
|
||||
EIGEN_STRONG_INLINE explicit Matrix() : m_storage()
|
||||
{
|
||||
ei_assert(RowsAtCompileTime > 0 && ColsAtCompileTime > 0);
|
||||
_check_template_params();
|
||||
}
|
||||
|
||||
#ifndef EIGEN_PARSED_BY_DOXYGEN
|
||||
/** \internal */
|
||||
Matrix(ei_constructor_without_unaligned_array_assert)
|
||||
: m_storage(ei_constructor_without_unaligned_array_assert()) {}
|
||||
: m_storage(ei_constructor_without_unaligned_array_assert())
|
||||
{}
|
||||
#endif
|
||||
|
||||
/** Constructs a vector or row-vector with given dimension. \only_for_vectors
|
||||
*
|
||||
@@ -349,6 +307,7 @@ class Matrix
|
||||
EIGEN_STRONG_INLINE explicit Matrix(int dim)
|
||||
: m_storage(dim, RowsAtCompileTime == 1 ? 1 : dim, ColsAtCompileTime == 1 ? 1 : dim)
|
||||
{
|
||||
_check_template_params();
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Matrix)
|
||||
ei_assert(dim > 0);
|
||||
ei_assert(SizeAtCompileTime == Dynamic || SizeAtCompileTime == dim);
|
||||
@@ -366,6 +325,7 @@ class Matrix
|
||||
*/
|
||||
EIGEN_STRONG_INLINE Matrix(int x, int y) : m_storage(x*y, x, y)
|
||||
{
|
||||
_check_template_params();
|
||||
if((RowsAtCompileTime == 1 && ColsAtCompileTime == 2)
|
||||
|| (RowsAtCompileTime == 2 && ColsAtCompileTime == 1))
|
||||
{
|
||||
@@ -381,6 +341,7 @@ class Matrix
|
||||
/** constructs an initialized 2D vector with given coefficients */
|
||||
EIGEN_STRONG_INLINE Matrix(const float& x, const float& y)
|
||||
{
|
||||
_check_template_params();
|
||||
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Matrix, 2)
|
||||
m_storage.data()[0] = x;
|
||||
m_storage.data()[1] = y;
|
||||
@@ -388,6 +349,7 @@ class Matrix
|
||||
/** constructs an initialized 2D vector with given coefficients */
|
||||
EIGEN_STRONG_INLINE Matrix(const double& x, const double& y)
|
||||
{
|
||||
_check_template_params();
|
||||
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Matrix, 2)
|
||||
m_storage.data()[0] = x;
|
||||
m_storage.data()[1] = y;
|
||||
@@ -395,6 +357,7 @@ class Matrix
|
||||
/** constructs an initialized 3D vector with given coefficients */
|
||||
EIGEN_STRONG_INLINE Matrix(const Scalar& x, const Scalar& y, const Scalar& z)
|
||||
{
|
||||
_check_template_params();
|
||||
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Matrix, 3)
|
||||
m_storage.data()[0] = x;
|
||||
m_storage.data()[1] = y;
|
||||
@@ -403,6 +366,7 @@ class Matrix
|
||||
/** constructs an initialized 4D vector with given coefficients */
|
||||
EIGEN_STRONG_INLINE Matrix(const Scalar& x, const Scalar& y, const Scalar& z, const Scalar& w)
|
||||
{
|
||||
_check_template_params();
|
||||
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Matrix, 4)
|
||||
m_storage.data()[0] = x;
|
||||
m_storage.data()[1] = y;
|
||||
@@ -417,14 +381,15 @@ class Matrix
|
||||
EIGEN_STRONG_INLINE Matrix(const MatrixBase<OtherDerived>& other)
|
||||
: m_storage(other.rows() * other.cols(), other.rows(), other.cols())
|
||||
{
|
||||
ei_assign_selector<Matrix,OtherDerived,false>::run(*this, other.derived());
|
||||
//Base::operator=(other.derived());
|
||||
_check_template_params();
|
||||
_set_noalias(other);
|
||||
}
|
||||
/** Copy constructor */
|
||||
EIGEN_STRONG_INLINE Matrix(const Matrix& other)
|
||||
: Base(), m_storage(other.rows() * other.cols(), other.rows(), other.cols())
|
||||
{
|
||||
Base::lazyAssign(other);
|
||||
_check_template_params();
|
||||
_set_noalias(other);
|
||||
}
|
||||
/** Destructor */
|
||||
inline ~Matrix() {}
|
||||
@@ -486,6 +451,72 @@ class Matrix
|
||||
#ifdef EIGEN_MATRIX_PLUGIN
|
||||
#include EIGEN_MATRIX_PLUGIN
|
||||
#endif
|
||||
|
||||
private:
|
||||
/** \internal Resizes *this in preparation for assigning \a other to it.
|
||||
* Takes care of doing all the checking that's needed.
|
||||
*
|
||||
* Note that copying a row-vector into a vector (and conversely) is allowed.
|
||||
* The resizing, if any, is then done in the appropriate way so that row-vectors
|
||||
* remain row-vectors and vectors remain vectors.
|
||||
*/
|
||||
template<typename OtherDerived>
|
||||
EIGEN_STRONG_INLINE void _resize_to_match(const MatrixBase<OtherDerived>& other)
|
||||
{
|
||||
if(RowsAtCompileTime == 1)
|
||||
{
|
||||
ei_assert(other.isVector());
|
||||
resize(1, other.size());
|
||||
}
|
||||
else if(ColsAtCompileTime == 1)
|
||||
{
|
||||
ei_assert(other.isVector());
|
||||
resize(other.size(), 1);
|
||||
}
|
||||
else resize(other.rows(), other.cols());
|
||||
}
|
||||
|
||||
/** \internal Copies the value of the expression \a other into \c *this with automatic resizing.
|
||||
*
|
||||
* *this might be resized to match the dimensions of \a other. If *this was a null matrix (not already initialized),
|
||||
* it will be initialized.
|
||||
*
|
||||
* Note that copying a row-vector into a vector (and conversely) is allowed.
|
||||
* The resizing, if any, is then done in the appropriate way so that row-vectors
|
||||
* remain row-vectors and vectors remain vectors.
|
||||
*
|
||||
* \sa operator=(const MatrixBase<OtherDerived>&), _set_noalias()
|
||||
*/
|
||||
template<typename OtherDerived>
|
||||
EIGEN_STRONG_INLINE Matrix& _set(const MatrixBase<OtherDerived>& other)
|
||||
{
|
||||
_resize_to_match(other);
|
||||
return Base::operator=(other);
|
||||
}
|
||||
|
||||
/** \internal Like _set() but additionally makes the assumption that no aliasing effect can happen (which
|
||||
* is the case when creating a new matrix) so one can enforce lazy evaluation.
|
||||
*
|
||||
* \sa operator=(const MatrixBase<OtherDerived>&), _set()
|
||||
*/
|
||||
template<typename OtherDerived>
|
||||
EIGEN_STRONG_INLINE Matrix& _set_noalias(const MatrixBase<OtherDerived>& other)
|
||||
{
|
||||
_resize_to_match(other);
|
||||
// the 'false' below means to enforce lazy evaluation. We don't use lazyAssign() because
|
||||
// it wouldn't allow to copy a row-vector into a column-vector.
|
||||
return ei_assign_selector<Matrix,OtherDerived,false>::run(*this, other.derived());
|
||||
}
|
||||
|
||||
static EIGEN_STRONG_INLINE void _check_template_params()
|
||||
{
|
||||
EIGEN_STATIC_ASSERT((_Rows > 0
|
||||
&& _Cols > 0
|
||||
&& _MaxRows <= _Rows
|
||||
&& _MaxCols <= _Cols
|
||||
&& (_Options & (AutoAlign|RowMajor)) == _Options),
|
||||
INVALID_MATRIX_TEMPLATE_PARAMETERS)
|
||||
}
|
||||
};
|
||||
|
||||
/** \defgroup matrixtypedefs Global matrix typedefs
|
||||
|
||||
@@ -229,10 +229,6 @@ template<typename Derived> class MatrixBase
|
||||
template<typename OtherDerived>
|
||||
Derived& operator=(const MatrixBase<OtherDerived>& other);
|
||||
|
||||
/** Copies \a other into *this without evaluating other. \returns a reference to *this. */
|
||||
template<typename OtherDerived>
|
||||
Derived& lazyAssign(const MatrixBase<OtherDerived>& other);
|
||||
|
||||
/** Special case of the template operator=, in order to prevent the compiler
|
||||
* from generating a default operator= (issue hit with g++ 4.1)
|
||||
*/
|
||||
@@ -241,6 +237,11 @@ template<typename Derived> class MatrixBase
|
||||
return this->operator=<Derived>(other);
|
||||
}
|
||||
|
||||
#ifndef EIGEN_PARSED_BY_DOXYGEN
|
||||
/** Copies \a other into *this without evaluating other. \returns a reference to *this. */
|
||||
template<typename OtherDerived>
|
||||
Derived& lazyAssign(const MatrixBase<OtherDerived>& other);
|
||||
|
||||
/** Overloaded for cache friendly product evaluation */
|
||||
template<typename Lhs, typename Rhs>
|
||||
Derived& lazyAssign(const Product<Lhs,Rhs,CacheFriendlyProduct>& product);
|
||||
@@ -249,10 +250,7 @@ template<typename Derived> class MatrixBase
|
||||
template<typename OtherDerived>
|
||||
Derived& lazyAssign(const Flagged<OtherDerived, 0, EvalBeforeNestingBit | EvalBeforeAssigningBit>& other)
|
||||
{ return lazyAssign(other._expression()); }
|
||||
|
||||
/** Overloaded for sparse product evaluation */
|
||||
template<typename Derived1, typename Derived2>
|
||||
Derived& lazyAssign(const Product<Derived1,Derived2,SparseProduct>& product);
|
||||
#endif // not EIGEN_PARSED_BY_DOXYGEN
|
||||
|
||||
CommaInitializer<Derived> operator<< (const Scalar& s);
|
||||
|
||||
@@ -346,13 +344,12 @@ template<typename Derived> class MatrixBase
|
||||
solveTriangular(const MatrixBase<OtherDerived>& other) const;
|
||||
|
||||
template<typename OtherDerived>
|
||||
void solveTriangularInPlace(MatrixBase<OtherDerived>& other) const;
|
||||
void solveTriangularInPlace(const MatrixBase<OtherDerived>& other) const;
|
||||
|
||||
|
||||
template<typename OtherDerived>
|
||||
Scalar dot(const MatrixBase<OtherDerived>& other) const;
|
||||
RealScalar squaredNorm() const;
|
||||
RealScalar norm2() const;
|
||||
RealScalar norm() const;
|
||||
const PlainMatrixType normalized() const;
|
||||
void normalize();
|
||||
@@ -448,6 +445,7 @@ template<typename Derived> class MatrixBase
|
||||
|
||||
const DiagonalMatrix<Derived> asDiagonal() const;
|
||||
|
||||
void fill(const Scalar& value);
|
||||
Derived& setConstant(const Scalar& value);
|
||||
Derived& setZero();
|
||||
Derived& setOnes();
|
||||
@@ -559,6 +557,7 @@ template<typename Derived> class MatrixBase
|
||||
|
||||
bool all(void) const;
|
||||
bool any(void) const;
|
||||
int count() const;
|
||||
|
||||
const PartialRedux<Derived,Horizontal> rowwise() const;
|
||||
const PartialRedux<Derived,Vertical> colwise() const;
|
||||
@@ -593,9 +592,6 @@ template<typename Derived> class MatrixBase
|
||||
|
||||
const LLT<PlainMatrixType> llt() const;
|
||||
const LDLT<PlainMatrixType> ldlt() const;
|
||||
// deprecated:
|
||||
const Cholesky<PlainMatrixType> cholesky() const;
|
||||
const CholeskyWithoutSquareRoot<PlainMatrixType> choleskyNoSqrt() const;
|
||||
|
||||
/////////// QR module ///////////
|
||||
|
||||
@@ -615,6 +611,15 @@ template<typename Derived> class MatrixBase
|
||||
PlainMatrixType unitOrthogonal(void) const;
|
||||
Matrix<Scalar,3,1> eulerAngles(int a0, int a1, int a2) const;
|
||||
|
||||
/////////// Sparse module ///////////
|
||||
|
||||
// dense = spasre * dense
|
||||
template<typename Derived1, typename Derived2>
|
||||
Derived& lazyAssign(const SparseProduct<Derived1,Derived2,SparseTimeDenseProduct>& product);
|
||||
// dense = dense * spasre
|
||||
template<typename Derived1, typename Derived2>
|
||||
Derived& lazyAssign(const SparseProduct<Derived1,Derived2,DenseTimeSparseProduct>& product);
|
||||
|
||||
#ifdef EIGEN_MATRIXBASE_PLUGIN
|
||||
#include EIGEN_MATRIXBASE_PLUGIN
|
||||
#endif
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
// Copyright (C) 2006-2009 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// Eigen is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
@@ -41,7 +41,7 @@ template <typename T, int Size, int MatrixOptions,
|
||||
{
|
||||
#ifndef EIGEN_DISABLE_UNALIGNED_ARRAY_ASSERT
|
||||
ei_assert((reinterpret_cast<size_t>(array) & 0xf) == 0
|
||||
&& "this assertion is explained here: http://eigen.tuxfamily.org/api/UnalignedArrayAssert.html **** READ THIS WEB PAGE !!! ****");
|
||||
&& "this assertion is explained here: http://eigen.tuxfamily.org/dox/UnalignedArrayAssert.html **** READ THIS WEB PAGE !!! ****");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,8 @@
|
||||
#ifndef EIGEN_MINOR_H
|
||||
#define EIGEN_MINOR_H
|
||||
|
||||
/** \class Minor
|
||||
/** \nonstableyet
|
||||
* \class Minor
|
||||
*
|
||||
* \brief Expression of a minor
|
||||
*
|
||||
@@ -92,7 +93,8 @@ template<typename MatrixType> class Minor
|
||||
const int m_row, m_col;
|
||||
};
|
||||
|
||||
/** \return an expression of the (\a row, \a col)-minor of *this,
|
||||
/** \nonstableyet
|
||||
* \return an expression of the (\a row, \a col)-minor of *this,
|
||||
* i.e. an expression constructed from *this by removing the specified
|
||||
* row and column.
|
||||
*
|
||||
@@ -108,7 +110,8 @@ MatrixBase<Derived>::minor(int row, int col)
|
||||
return Minor<Derived>(derived(), row, col);
|
||||
}
|
||||
|
||||
/** This is the const version of minor(). */
|
||||
/** \nonstableyet
|
||||
* This is the const version of minor(). */
|
||||
template<typename Derived>
|
||||
inline const Minor<Derived>
|
||||
MatrixBase<Derived>::minor(int row, int col) const
|
||||
|
||||
@@ -26,7 +26,8 @@
|
||||
#ifndef EIGEN_PART_H
|
||||
#define EIGEN_PART_H
|
||||
|
||||
/** \class Part
|
||||
/** \nonstableyet
|
||||
* \class Part
|
||||
*
|
||||
* \brief Expression of a triangular matrix extracted from a given matrix
|
||||
*
|
||||
@@ -127,7 +128,8 @@ template<typename MatrixType, unsigned int Mode> class Part
|
||||
const typename MatrixType::Nested m_matrix;
|
||||
};
|
||||
|
||||
/** \returns an expression of a triangular matrix extracted from the current matrix
|
||||
/** \nonstableyet
|
||||
* \returns an expression of a triangular matrix extracted from the current matrix
|
||||
*
|
||||
* The parameter \a Mode can have the following values: \c UpperTriangular, \c StrictlyUpperTriangular, \c UnitUpperTriangular,
|
||||
* \c LowerTriangular, \c StrictlyLowerTriangular, \c UnitLowerTriangular.
|
||||
@@ -278,7 +280,8 @@ void Part<MatrixType, Mode>::lazyAssign(const Other& other)
|
||||
>::run(m_matrix.const_cast_derived(), other.derived());
|
||||
}
|
||||
|
||||
/** \returns a lvalue pseudo-expression allowing to perform special operations on \c *this.
|
||||
/** \nonstableyet
|
||||
* \returns a lvalue pseudo-expression allowing to perform special operations on \c *this.
|
||||
*
|
||||
* The \a Mode parameter can have the following values: \c UpperTriangular, \c StrictlyUpperTriangular, \c LowerTriangular,
|
||||
* \c StrictlyLowerTriangular, \c SelfAdjoint.
|
||||
|
||||
@@ -79,7 +79,6 @@ struct ProductReturnType<Lhs,Rhs,CacheFriendlyProduct>
|
||||
* - NormalProduct
|
||||
* - CacheFriendlyProduct
|
||||
* - DiagonalProduct
|
||||
* - SparseProduct
|
||||
*/
|
||||
template<typename Lhs, typename Rhs> struct ei_product_mode
|
||||
{
|
||||
@@ -87,8 +86,6 @@ template<typename Lhs, typename Rhs> struct ei_product_mode
|
||||
|
||||
value = ((Rhs::Flags&Diagonal)==Diagonal) || ((Lhs::Flags&Diagonal)==Diagonal)
|
||||
? DiagonalProduct
|
||||
: (Rhs::Flags & Lhs::Flags & SparseBit)
|
||||
? SparseProduct
|
||||
: Lhs::MaxColsAtCompileTime == Dynamic
|
||||
&& ( Lhs::MaxRowsAtCompileTime == Dynamic
|
||||
|| Rhs::MaxColsAtCompileTime == Dynamic )
|
||||
|
||||
@@ -221,13 +221,19 @@ struct ei_solve_triangular_selector<Lhs,Rhs,UpLo,ColMajor|IsDense>
|
||||
};
|
||||
|
||||
/** "in-place" version of MatrixBase::solveTriangular() where the result is written in \a other
|
||||
*
|
||||
* \nonstableyet
|
||||
*
|
||||
* The parameter is only marked 'const' to make the C++ compiler accept a temporary expression here.
|
||||
* This function will const_cast it, so constness isn't honored here.
|
||||
*
|
||||
* See MatrixBase:solveTriangular() for the details.
|
||||
*/
|
||||
template<typename Derived>
|
||||
template<typename OtherDerived>
|
||||
void MatrixBase<Derived>::solveTriangularInPlace(MatrixBase<OtherDerived>& other) const
|
||||
void MatrixBase<Derived>::solveTriangularInPlace(const MatrixBase<OtherDerived>& _other) const
|
||||
{
|
||||
MatrixBase<OtherDerived>& other = _other.const_cast_derived();
|
||||
ei_assert(derived().cols() == derived().rows());
|
||||
ei_assert(derived().cols() == other.rows());
|
||||
ei_assert(!(Flags & ZeroDiagBit));
|
||||
@@ -246,6 +252,8 @@ void MatrixBase<Derived>::solveTriangularInPlace(MatrixBase<OtherDerived>& other
|
||||
}
|
||||
|
||||
/** \returns the product of the inverse of \c *this with \a other, \a *this being triangular.
|
||||
*
|
||||
* \nonstableyet
|
||||
*
|
||||
* This function computes the inverse-matrix matrix product inverse(\c *this) * \a other.
|
||||
* The matrix \c *this must be triangular and invertible (i.e., all the coefficients of the
|
||||
|
||||
@@ -100,18 +100,13 @@ struct ei_sum_novec_unroller<Derived, Start, 1>
|
||||
};
|
||||
|
||||
/*** vectorization ***/
|
||||
|
||||
template<typename Derived, int Index, int Stop,
|
||||
bool LastPacket = (Stop-Index == ei_packet_traits<typename Derived::Scalar>::size)>
|
||||
|
||||
template<typename Derived, int Start, int Length>
|
||||
struct ei_sum_vec_unroller
|
||||
{
|
||||
enum {
|
||||
row = int(Derived::Flags)&RowMajorBit
|
||||
? Index / int(Derived::ColsAtCompileTime)
|
||||
: Index % Derived::RowsAtCompileTime,
|
||||
col = int(Derived::Flags)&RowMajorBit
|
||||
? Index % int(Derived::ColsAtCompileTime)
|
||||
: Index / Derived::RowsAtCompileTime
|
||||
PacketSize = ei_packet_traits<typename Derived::Scalar>::size,
|
||||
HalfLength = Length/2
|
||||
};
|
||||
|
||||
typedef typename Derived::Scalar Scalar;
|
||||
@@ -120,22 +115,22 @@ struct ei_sum_vec_unroller
|
||||
inline static PacketScalar run(const Derived &mat)
|
||||
{
|
||||
return ei_padd(
|
||||
mat.template packet<Aligned>(row, col),
|
||||
ei_sum_vec_unroller<Derived, Index+ei_packet_traits<typename Derived::Scalar>::size, Stop>::run(mat)
|
||||
);
|
||||
ei_sum_vec_unroller<Derived, Start, HalfLength>::run(mat),
|
||||
ei_sum_vec_unroller<Derived, Start+HalfLength, Length-HalfLength>::run(mat) );
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Derived, int Index, int Stop>
|
||||
struct ei_sum_vec_unroller<Derived, Index, Stop, true>
|
||||
template<typename Derived, int Start>
|
||||
struct ei_sum_vec_unroller<Derived, Start, 1>
|
||||
{
|
||||
enum {
|
||||
index = Start * ei_packet_traits<typename Derived::Scalar>::size,
|
||||
row = int(Derived::Flags)&RowMajorBit
|
||||
? Index / int(Derived::ColsAtCompileTime)
|
||||
: Index % Derived::RowsAtCompileTime,
|
||||
? index / int(Derived::ColsAtCompileTime)
|
||||
: index % Derived::RowsAtCompileTime,
|
||||
col = int(Derived::Flags)&RowMajorBit
|
||||
? Index % int(Derived::ColsAtCompileTime)
|
||||
: Index / Derived::RowsAtCompileTime,
|
||||
? index % int(Derived::ColsAtCompileTime)
|
||||
: index / Derived::RowsAtCompileTime,
|
||||
alignment = (Derived::Flags & AlignedBit) ? Aligned : Unaligned
|
||||
};
|
||||
|
||||
@@ -154,13 +149,12 @@ struct ei_sum_vec_unroller<Derived, Index, Stop, true>
|
||||
|
||||
template<typename Derived,
|
||||
int Vectorization = ei_sum_traits<Derived>::Vectorization,
|
||||
int Unrolling = ei_sum_traits<Derived>::Unrolling,
|
||||
int Storage = ei_traits<Derived>::Flags & SparseBit
|
||||
int Unrolling = ei_sum_traits<Derived>::Unrolling
|
||||
>
|
||||
struct ei_sum_impl;
|
||||
|
||||
template<typename Derived>
|
||||
struct ei_sum_impl<Derived, NoVectorization, NoUnrolling, IsDense>
|
||||
struct ei_sum_impl<Derived, NoVectorization, NoUnrolling>
|
||||
{
|
||||
typedef typename Derived::Scalar Scalar;
|
||||
static Scalar run(const Derived& mat)
|
||||
@@ -178,12 +172,12 @@ struct ei_sum_impl<Derived, NoVectorization, NoUnrolling, IsDense>
|
||||
};
|
||||
|
||||
template<typename Derived>
|
||||
struct ei_sum_impl<Derived, NoVectorization, CompleteUnrolling, IsDense>
|
||||
struct ei_sum_impl<Derived, NoVectorization, CompleteUnrolling>
|
||||
: public ei_sum_novec_unroller<Derived, 0, Derived::SizeAtCompileTime>
|
||||
{};
|
||||
|
||||
template<typename Derived>
|
||||
struct ei_sum_impl<Derived, LinearVectorization, NoUnrolling,IsDense>
|
||||
struct ei_sum_impl<Derived, LinearVectorization, NoUnrolling>
|
||||
{
|
||||
typedef typename Derived::Scalar Scalar;
|
||||
typedef typename ei_packet_traits<Scalar>::type PacketScalar;
|
||||
@@ -228,7 +222,7 @@ struct ei_sum_impl<Derived, LinearVectorization, NoUnrolling,IsDense>
|
||||
};
|
||||
|
||||
template<typename Derived>
|
||||
struct ei_sum_impl<Derived, LinearVectorization, CompleteUnrolling, IsDense>
|
||||
struct ei_sum_impl<Derived, LinearVectorization, CompleteUnrolling>
|
||||
{
|
||||
typedef typename Derived::Scalar Scalar;
|
||||
typedef typename ei_packet_traits<Scalar>::type PacketScalar;
|
||||
@@ -239,7 +233,7 @@ struct ei_sum_impl<Derived, LinearVectorization, CompleteUnrolling, IsDense>
|
||||
};
|
||||
static Scalar run(const Derived& mat)
|
||||
{
|
||||
Scalar res = ei_predux(ei_sum_vec_unroller<Derived, 0, VectorizationSize>::run(mat));
|
||||
Scalar res = ei_predux(ei_sum_vec_unroller<Derived, 0, Size / PacketSize>::run(mat));
|
||||
if (VectorizationSize != Size)
|
||||
res += ei_sum_novec_unroller<Derived, VectorizationSize, Size-VectorizationSize>::run(mat);
|
||||
return res;
|
||||
|
||||
@@ -63,8 +63,6 @@ template<typename MatrixType> class Transpose
|
||||
|
||||
EIGEN_GENERIC_PUBLIC_INTERFACE(Transpose)
|
||||
|
||||
class InnerIterator;
|
||||
|
||||
inline Transpose(const MatrixType& matrix) : m_matrix(matrix) {}
|
||||
|
||||
EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Transpose)
|
||||
@@ -177,7 +175,7 @@ struct ei_inplace_transpose_selector<MatrixType,false> { // non square matrix
|
||||
if (m.rows()==m.cols())
|
||||
m.template part<StrictlyUpperTriangular>().swap(m.transpose());
|
||||
else
|
||||
m.set(m.transpose().eval());
|
||||
m = m.transpose().eval();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -185,10 +183,10 @@ struct ei_inplace_transpose_selector<MatrixType,false> { // non square matrix
|
||||
*
|
||||
* In most cases it is probably better to simply use the transposed expression
|
||||
* of a matrix. However, when transposing the matrix data itself is really needed,
|
||||
* then this "in-place" version is probably the right choice because it provides
|
||||
* then this "in-place" version is probably the right choice because it provides
|
||||
* the following additional features:
|
||||
* - less error prone: doing the same operation with .transpose() requires special care:
|
||||
* \code m.set(m.transpose().eval()); \endcode
|
||||
* \code m = m.transpose().eval(); \endcode
|
||||
* - no temporary object is created (currently only for squared matrices)
|
||||
* - it allows future optimizations (cache friendliness, etc.)
|
||||
*
|
||||
|
||||
@@ -37,6 +37,10 @@ template<> struct ei_unpacket_traits<__m128> { typedef float type; enum {size=
|
||||
template<> struct ei_unpacket_traits<__m128d> { typedef double type; enum {size=2}; };
|
||||
template<> struct ei_unpacket_traits<__m128i> { typedef int type; enum {size=4}; };
|
||||
|
||||
template<> EIGEN_STRONG_INLINE __m128 ei_pset1<float>(const float& from) { return _mm_set1_ps(from); }
|
||||
template<> EIGEN_STRONG_INLINE __m128d ei_pset1<double>(const double& from) { return _mm_set1_pd(from); }
|
||||
template<> EIGEN_STRONG_INLINE __m128i ei_pset1<int>(const int& from) { return _mm_set1_epi32(from); }
|
||||
|
||||
template<> EIGEN_STRONG_INLINE __m128 ei_padd<__m128>(const __m128& a, const __m128& b) { return _mm_add_ps(a,b); }
|
||||
template<> EIGEN_STRONG_INLINE __m128d ei_padd<__m128d>(const __m128d& a, const __m128d& b) { return _mm_add_pd(a,b); }
|
||||
template<> EIGEN_STRONG_INLINE __m128i ei_padd<__m128i>(const __m128i& a, const __m128i& b) { return _mm_add_epi32(a,b); }
|
||||
@@ -63,7 +67,7 @@ template<> EIGEN_STRONG_INLINE __m128 ei_pdiv<__m128>(const __m128& a, const _
|
||||
template<> EIGEN_STRONG_INLINE __m128d ei_pdiv<__m128d>(const __m128d& a, const __m128d& b) { return _mm_div_pd(a,b); }
|
||||
template<> EIGEN_STRONG_INLINE __m128i ei_pdiv<__m128i>(const __m128i& /*a*/, const __m128i& /*b*/)
|
||||
{ ei_assert(false && "packet integer division are not supported by SSE");
|
||||
__m128i dummy;
|
||||
__m128i dummy = ei_pset1<int>(0);
|
||||
return dummy;
|
||||
}
|
||||
|
||||
@@ -102,10 +106,6 @@ template<> EIGEN_STRONG_INLINE __m128 ei_ploadu<float>(const float* from) { r
|
||||
template<> EIGEN_STRONG_INLINE __m128d ei_ploadu<double>(const double* from) { return _mm_loadu_pd(from); }
|
||||
template<> EIGEN_STRONG_INLINE __m128i ei_ploadu<int>(const int* from) { return _mm_loadu_si128(reinterpret_cast<const __m128i*>(from)); }
|
||||
|
||||
template<> EIGEN_STRONG_INLINE __m128 ei_pset1<float>(const float& from) { return _mm_set1_ps(from); }
|
||||
template<> EIGEN_STRONG_INLINE __m128d ei_pset1<double>(const double& from) { return _mm_set1_pd(from); }
|
||||
template<> EIGEN_STRONG_INLINE __m128i ei_pset1<int>(const int& from) { return _mm_set1_epi32(from); }
|
||||
|
||||
template<> EIGEN_STRONG_INLINE void ei_pstore<float>(float* to, const __m128& from) { _mm_store_ps(to, from); }
|
||||
template<> EIGEN_STRONG_INLINE void ei_pstore<double>(double* to, const __m128d& from) { _mm_store_pd(to, from); }
|
||||
template<> EIGEN_STRONG_INLINE void ei_pstore<int>(int* to, const __m128i& from) { _mm_store_si128(reinterpret_cast<__m128i*>(to), from); }
|
||||
|
||||
@@ -201,7 +201,7 @@ enum { ForceAligned, AsRequested };
|
||||
enum { ConditionalJumpCost = 5 };
|
||||
enum CornerType { TopLeft, TopRight, BottomLeft, BottomRight };
|
||||
enum DirectionType { Vertical, Horizontal };
|
||||
enum ProductEvaluationMode { NormalProduct, CacheFriendlyProduct, DiagonalProduct, SparseProduct };
|
||||
enum ProductEvaluationMode { NormalProduct, CacheFriendlyProduct, DiagonalProduct, SparseTimeSparseProduct, SparseTimeDenseProduct, DenseTimeSparseProduct };
|
||||
|
||||
enum {
|
||||
/** \internal Equivalent to a slice vectorization for fixed-size matrices having good alignment
|
||||
@@ -239,9 +239,4 @@ enum {
|
||||
HasDirectAccess = DirectAccessBit
|
||||
};
|
||||
|
||||
const int FullyCoherentAccessPattern = 0x1;
|
||||
const int InnerCoherentAccessPattern = 0x2 | FullyCoherentAccessPattern;
|
||||
const int OuterCoherentAccessPattern = 0x4 | InnerCoherentAccessPattern;
|
||||
const int RandomAccessPattern = 0x8 | OuterCoherentAccessPattern;
|
||||
|
||||
#endif // EIGEN_CONSTANTS_H
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning( push )
|
||||
#pragma warning( disable : 4181 4244 4127 4211 )
|
||||
#pragma warning( disable : 4181 4244 4127 4211 4717 )
|
||||
#endif
|
||||
|
||||
@@ -106,9 +106,6 @@ template<typename MatrixType> class QR;
|
||||
template<typename MatrixType> class SVD;
|
||||
template<typename MatrixType> class LLT;
|
||||
template<typename MatrixType> class LDLT;
|
||||
// deprecated:
|
||||
template<typename MatrixType> class Cholesky;
|
||||
template<typename MatrixType> class CholeskyWithoutSquareRoot;
|
||||
|
||||
// Geometry module:
|
||||
template<typename Derived, int _Dim> class RotationBase;
|
||||
@@ -122,4 +119,7 @@ template <typename _Scalar, int _AmbientDim> class Hyperplane;
|
||||
template<typename Scalar,int Dim> class Translation;
|
||||
template<typename Scalar,int Dim> class Scaling;
|
||||
|
||||
// Sparse module:
|
||||
template<typename Lhs, typename Rhs, int ProductMode> class SparseProduct;
|
||||
|
||||
#endif // EIGEN_FORWARDDECLARATIONS_H
|
||||
|
||||
@@ -50,10 +50,18 @@
|
||||
#define EIGEN_UNROLLING_LIMIT 100
|
||||
#endif
|
||||
|
||||
/** \internal Define the maximal size in Bytes of L2 blocks.
|
||||
* The current value is set to generate blocks of 256x256 for float */
|
||||
#ifndef EIGEN_TUNE_FOR_L2_CACHE_SIZE
|
||||
#define EIGEN_TUNE_FOR_L2_CACHE_SIZE (sizeof(float)*256*256)
|
||||
/** \internal Define the maximal size in Bytes of blocks fitting in CPU cache.
|
||||
* The current value is set to generate blocks of 256x256 for float
|
||||
*
|
||||
* Typically for a single-threaded application you would set that to 25% of the size of your CPU caches in bytes
|
||||
*/
|
||||
#ifndef EIGEN_TUNE_FOR_CPU_CACHE_SIZE
|
||||
#define EIGEN_TUNE_FOR_CPU_CACHE_SIZE (sizeof(float)*256*256)
|
||||
#endif
|
||||
|
||||
// FIXME this should go away quickly
|
||||
#ifdef EIGEN_TUNE_FOR_L2_CACHE_SIZE
|
||||
#error EIGEN_TUNE_FOR_L2_CACHE_SIZE is now called EIGEN_TUNE_FOR_CPU_CACHE_SIZE.
|
||||
#endif
|
||||
|
||||
#define USING_PART_OF_NAMESPACE_EIGEN \
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
// Copyright (C) 2008-2009 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
// Copyright (C) 2009 Kenneth Riddile <kfriddile@yahoo.com>
|
||||
//
|
||||
// Eigen is free software; you can redistribute it and/or
|
||||
@@ -27,7 +27,7 @@
|
||||
#ifndef EIGEN_MEMORY_H
|
||||
#define EIGEN_MEMORY_H
|
||||
|
||||
#if defined(__APPLE__) || defined(__FreeBSD__) || defined(_WIN64)
|
||||
#if defined(__APPLE__) || defined(_WIN64)
|
||||
#define EIGEN_MALLOC_ALREADY_ALIGNED 1
|
||||
#else
|
||||
#define EIGEN_MALLOC_ALREADY_ALIGNED 0
|
||||
@@ -114,11 +114,11 @@ template<> inline void* ei_conditional_aligned_malloc<false>(size_t size)
|
||||
ei_assert(false && "heap allocation is forbidden (EIGEN_NO_MALLOC is defined)");
|
||||
#endif
|
||||
|
||||
void *void_result = malloc(size);
|
||||
void *result = malloc(size);
|
||||
#ifdef EIGEN_EXCEPTIONS
|
||||
if(!void_result) throw std::bad_alloc();
|
||||
if(!result) throw std::bad_alloc();
|
||||
#endif
|
||||
return void_result;
|
||||
return result;
|
||||
}
|
||||
|
||||
/** allocates \a size objects of type T. The returned pointer is guaranteed to have 16 bytes alignment.
|
||||
@@ -232,27 +232,7 @@ inline static int ei_alignmentOffset(const Scalar* ptr, int maxOffset)
|
||||
#define ei_aligned_stack_delete(TYPE,PTR,SIZE) do {ei_delete_elements_of_array<TYPE>(PTR, SIZE); \
|
||||
ei_aligned_stack_free(PTR,sizeof(TYPE)*SIZE);} while(0)
|
||||
|
||||
/** Qt <= 4.4 has a bug where it calls new(ptr) T instead of ::new(ptr) T.
|
||||
* This fails as we overload other operator new but not this one. What Qt really means is placement new.
|
||||
* Since this is getting used only with fixed-size Eigen matrices where the ctor does nothing, it is OK to
|
||||
* emulate placement new by just returning the ptr -- no need to call ctors. Good, because we don't know the
|
||||
* class in this macro. So this can safely be used for QVector<Eigen::Vector4f> but definitely not for
|
||||
* QVector<Eigen::VectorXf>.
|
||||
*
|
||||
* This macro will go away as soon as Qt >= 4.5 is prevalent -- most likely it should go away in Eigen 2.1.
|
||||
*/
|
||||
#ifdef EIGEN_WORK_AROUND_QT_BUG_CALLING_WRONG_OPERATOR_NEW_FIXED_IN_QT_4_5
|
||||
#define EIGEN_WORKAROUND_FOR_QT_BUG_CALLING_WRONG_OPERATOR_NEW \
|
||||
void *operator new(size_t, void *ptr) throw() { \
|
||||
return ptr; \
|
||||
} \
|
||||
void *operator new[](size_t, void *ptr) throw() { \
|
||||
return ptr; \
|
||||
}
|
||||
#else
|
||||
#define EIGEN_WORKAROUND_FOR_QT_BUG_CALLING_WRONG_OPERATOR_NEW
|
||||
#endif
|
||||
|
||||
|
||||
/** \brief Overloads the operator new and delete of the class Type with operators that are aligned if NeedsToAlign is true
|
||||
*
|
||||
* When Eigen's explicit vectorization is enabled, Eigen assumes that some fixed sizes types are aligned
|
||||
@@ -300,18 +280,12 @@ inline static int ei_alignmentOffset(const Scalar* ptr, int maxOffset)
|
||||
} \
|
||||
void operator delete(void * ptr) { Eigen::ei_conditional_aligned_free<NeedsToAlign>(ptr); } \
|
||||
void operator delete[](void * ptr) { Eigen::ei_conditional_aligned_free<NeedsToAlign>(ptr); } \
|
||||
EIGEN_WORKAROUND_FOR_QT_BUG_CALLING_WRONG_OPERATOR_NEW
|
||||
void *operator new(size_t, void *ptr) throw() { return ptr; }
|
||||
|
||||
#define EIGEN_MAKE_ALIGNED_OPERATOR_NEW EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(true)
|
||||
#define EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(Scalar,Size) \
|
||||
EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(((Size)!=Eigen::Dynamic) && ((sizeof(Scalar)*(Size))%16==0))
|
||||
|
||||
/** Deprecated, use the EIGEN_MAKE_ALIGNED_OPERATOR_NEW macro instead in your own class */
|
||||
struct WithAlignedOperatorNew
|
||||
{
|
||||
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
|
||||
};
|
||||
|
||||
/** \class aligned_allocator
|
||||
*
|
||||
* \brief stl compatible allocator to use with with 16 byte aligned types
|
||||
|
||||
@@ -71,7 +71,9 @@
|
||||
INVALID_VECTOR_VECTOR_PRODUCT__IF_YOU_WANTED_A_DOT_OR_COEFF_WISE_PRODUCT_YOU_MUST_USE_THE_EXPLICIT_FUNCTIONS,
|
||||
INVALID_MATRIX_PRODUCT__IF_YOU_WANTED_A_COEFF_WISE_PRODUCT_YOU_MUST_USE_THE_EXPLICIT_FUNCTION,
|
||||
YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY,
|
||||
THIS_METHOD_IS_ONLY_FOR_COLUMN_MAJOR_MATRICES
|
||||
THIS_METHOD_IS_ONLY_FOR_COLUMN_MAJOR_MATRICES,
|
||||
THIS_METHOD_IS_ONLY_FOR_ROW_MAJOR_MATRICES,
|
||||
INVALID_MATRIX_TEMPLATE_PARAMETERS
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
#ifndef EIGEN_ALIGNEDBOX_H
|
||||
#define EIGEN_ALIGNEDBOX_H
|
||||
|
||||
/** \geometry_module \ingroup GeometryModule
|
||||
/** \geometry_module \ingroup Geometry_Module
|
||||
* \nonstableyet
|
||||
*
|
||||
* \class AlignedBox
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
#ifndef EIGEN_ANGLEAXIS_H
|
||||
#define EIGEN_ANGLEAXIS_H
|
||||
|
||||
/** \geometry_module \ingroup GeometryModule
|
||||
/** \geometry_module \ingroup Geometry_Module
|
||||
*
|
||||
* \class AngleAxis
|
||||
*
|
||||
@@ -158,10 +158,10 @@ public:
|
||||
{ return m_axis.isApprox(other.m_axis, prec) && ei_isApprox(m_angle,other.m_angle, prec); }
|
||||
};
|
||||
|
||||
/** \ingroup GeometryModule
|
||||
/** \ingroup Geometry_Module
|
||||
* single precision angle-axis type */
|
||||
typedef AngleAxis<float> AngleAxisf;
|
||||
/** \ingroup GeometryModule
|
||||
/** \ingroup Geometry_Module
|
||||
* double precision angle-axis type */
|
||||
typedef AngleAxis<double> AngleAxisd;
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
#ifndef EIGEN_EULERANGLES_H
|
||||
#define EIGEN_EULERANGLES_H
|
||||
|
||||
/** \geometry_module \ingroup GeometryModule
|
||||
/** \geometry_module \ingroup Geometry_Module
|
||||
* \nonstableyet
|
||||
*
|
||||
* \returns the Euler-angles of the rotation matrix \c *this using the convention defined by the triplet (\a a0,\a a1,\a a2)
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
#ifndef EIGEN_HYPERPLANE_H
|
||||
#define EIGEN_HYPERPLANE_H
|
||||
|
||||
/** \geometry_module \ingroup GeometryModule
|
||||
/** \geometry_module \ingroup Geometry_Module
|
||||
*
|
||||
* \class Hyperplane
|
||||
*
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
#ifndef EIGEN_PARAMETRIZEDLINE_H
|
||||
#define EIGEN_PARAMETRIZEDLINE_H
|
||||
|
||||
/** \geometry_module \ingroup GeometryModule
|
||||
/** \geometry_module \ingroup Geometry_Module
|
||||
*
|
||||
* \class ParametrizedLine
|
||||
*
|
||||
|
||||
@@ -30,7 +30,7 @@ template<typename Other,
|
||||
int OtherCols=Other::ColsAtCompileTime>
|
||||
struct ei_quaternion_assign_impl;
|
||||
|
||||
/** \geometry_module \ingroup GeometryModule
|
||||
/** \geometry_module \ingroup Geometry_Module
|
||||
*
|
||||
* \class Quaternion
|
||||
*
|
||||
@@ -109,7 +109,7 @@ public:
|
||||
/** \returns a vector expression of the coefficients (x,y,z,w) */
|
||||
inline Coefficients& coeffs() { return m_coeffs; }
|
||||
|
||||
/** Default constructor and initializing an identity quaternion. */
|
||||
/** Default constructor leaving the quaternion uninitialized. */
|
||||
inline Quaternion() {}
|
||||
|
||||
inline Quaternion(ei_constructor_without_unaligned_array_assert)
|
||||
@@ -221,10 +221,10 @@ protected:
|
||||
Coefficients m_coeffs;
|
||||
};
|
||||
|
||||
/** \ingroup GeometryModule
|
||||
/** \ingroup Geometry_Module
|
||||
* single precision quaternion type */
|
||||
typedef Quaternion<float> Quaternionf;
|
||||
/** \ingroup GeometryModule
|
||||
/** \ingroup Geometry_Module
|
||||
* double precision quaternion type */
|
||||
typedef Quaternion<double> Quaterniond;
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
#ifndef EIGEN_ROTATION2D_H
|
||||
#define EIGEN_ROTATION2D_H
|
||||
|
||||
/** \geometry_module \ingroup GeometryModule
|
||||
/** \geometry_module \ingroup Geometry_Module
|
||||
*
|
||||
* \class Rotation2D
|
||||
*
|
||||
@@ -125,10 +125,10 @@ public:
|
||||
{ return ei_isApprox(m_angle,other.m_angle, prec); }
|
||||
};
|
||||
|
||||
/** \ingroup GeometryModule
|
||||
/** \ingroup Geometry_Module
|
||||
* single precision 2D rotation type */
|
||||
typedef Rotation2D<float> Rotation2Df;
|
||||
/** \ingroup GeometryModule
|
||||
/** \ingroup Geometry_Module
|
||||
* double precision 2D rotation type */
|
||||
typedef Rotation2D<double> Rotation2Dd;
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
#ifndef EIGEN_SCALING_H
|
||||
#define EIGEN_SCALING_H
|
||||
|
||||
/** \geometry_module \ingroup GeometryModule
|
||||
/** \geometry_module \ingroup Geometry_Module
|
||||
*
|
||||
* \class Scaling
|
||||
*
|
||||
@@ -118,7 +118,7 @@ public:
|
||||
|
||||
/** \returns the inverse scaling */
|
||||
inline Scaling inverse() const
|
||||
{ return Scaling(coeffs.cwise().inverse()); }
|
||||
{ return Scaling(coeffs().cwise().inverse()); }
|
||||
|
||||
inline Scaling& operator=(const Scaling& other)
|
||||
{
|
||||
@@ -149,7 +149,7 @@ public:
|
||||
|
||||
};
|
||||
|
||||
/** \addtogroup GeometryModule */
|
||||
/** \addtogroup Geometry_Module */
|
||||
//@{
|
||||
typedef Scaling<float, 2> Scaling2f;
|
||||
typedef Scaling<double,2> Scaling2d;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
// Copyright (C) 2009 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// Eigen is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
@@ -42,7 +43,7 @@ template< typename Other,
|
||||
int OtherCols=Other::ColsAtCompileTime>
|
||||
struct ei_transform_product_impl;
|
||||
|
||||
/** \geometry_module \ingroup GeometryModule
|
||||
/** \geometry_module \ingroup Geometry_Module
|
||||
*
|
||||
* \class Transform
|
||||
*
|
||||
@@ -247,8 +248,11 @@ public:
|
||||
template<typename Derived>
|
||||
inline Transform operator*(const RotationBase<Derived,Dim>& r) const;
|
||||
|
||||
EIGEN_DEPRECATED LinearMatrixType extractRotation(TransformTraits traits = Affine) const { return rotation(traits); }
|
||||
LinearMatrixType rotation(TransformTraits traits = Affine) const;
|
||||
LinearMatrixType rotation() const;
|
||||
template<typename RotationMatrixType, typename ScalingMatrixType>
|
||||
void computeRotationScaling(RotationMatrixType *rotation, ScalingMatrixType *scaling) const;
|
||||
template<typename ScalingMatrixType, typename RotationMatrixType>
|
||||
void computeScalingRotation(ScalingMatrixType *scaling, RotationMatrixType *rotation) const;
|
||||
|
||||
template<typename PositionDerived, typename OrientationType, typename ScaleDerived>
|
||||
Transform& fromPositionOrientationScale(const MatrixBase<PositionDerived> &position,
|
||||
@@ -286,13 +290,13 @@ protected:
|
||||
|
||||
};
|
||||
|
||||
/** \ingroup GeometryModule */
|
||||
/** \ingroup Geometry_Module */
|
||||
typedef Transform<float,2> Transform2f;
|
||||
/** \ingroup GeometryModule */
|
||||
/** \ingroup Geometry_Module */
|
||||
typedef Transform<float,3> Transform3f;
|
||||
/** \ingroup GeometryModule */
|
||||
/** \ingroup Geometry_Module */
|
||||
typedef Transform<double,2> Transform2d;
|
||||
/** \ingroup GeometryModule */
|
||||
/** \ingroup Geometry_Module */
|
||||
typedef Transform<double,3> Transform3d;
|
||||
|
||||
/**************************
|
||||
@@ -590,47 +594,61 @@ inline Transform<Scalar,Dim> Transform<Scalar,Dim>::operator*(const RotationBase
|
||||
return res;
|
||||
}
|
||||
|
||||
/***************************
|
||||
*** Specialial functions ***
|
||||
***************************/
|
||||
/************************
|
||||
*** Special functions ***
|
||||
************************/
|
||||
|
||||
/** \returns the rotation part of the transformation
|
||||
* \nonstableyet
|
||||
*
|
||||
* \param traits allows to optimize the extraction process when the transformion
|
||||
* is known to be not a general aafine transformation. The possible values are:
|
||||
* - Affine which use a QR decomposition (default),
|
||||
* - Isometry which simply returns the linear part !
|
||||
* \svd_module
|
||||
*
|
||||
* \warning this function consider the scaling is positive
|
||||
*
|
||||
* \warning to use this method in the general case (traits==GenericAffine), you need
|
||||
* to include the QR module.
|
||||
*
|
||||
* \sa inverse(), class QR
|
||||
* \sa computeRotationScaling(), computeScalingRotation(), class SVD
|
||||
*/
|
||||
template<typename Scalar, int Dim>
|
||||
typename Transform<Scalar,Dim>::LinearMatrixType
|
||||
Transform<Scalar,Dim>::rotation(TransformTraits traits) const
|
||||
Transform<Scalar,Dim>::rotation() const
|
||||
{
|
||||
ei_assert(traits!=Projective && "you cannot extract a rotation from a non affine transformation");
|
||||
if (traits == Affine)
|
||||
{
|
||||
// FIXME maybe QR should be fixed to return a R matrix with a positive diagonal ??
|
||||
QR<LinearMatrixType> qr(linear());
|
||||
LinearMatrixType matQ = qr.matrixQ();
|
||||
LinearMatrixType matR = qr.matrixR();
|
||||
for (int i=0 ; i<Dim; ++i)
|
||||
if (matR.coeff(i,i)<0)
|
||||
matQ.col(i) = -matQ.col(i);
|
||||
return matQ;
|
||||
}
|
||||
else if (traits == Isometry) // though that's stupid let's handle it !
|
||||
return linear();
|
||||
else
|
||||
{
|
||||
ei_assert("invalid traits value in Transform::extractRotation()");
|
||||
return LinearMatrixType();
|
||||
}
|
||||
LinearMatrixType result;
|
||||
computeRotationScaling(&result, (LinearMatrixType*)0);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/** decomposes the linear part of the transformation as a product rotation x scaling, the scaling being
|
||||
* not necessarily positive.
|
||||
*
|
||||
* If either pointer is zero, the corresponding computation is skipped.
|
||||
*
|
||||
* \nonstableyet
|
||||
*
|
||||
* \svd_module
|
||||
*
|
||||
* \sa computeScalingRotation(), rotation(), class SVD
|
||||
*/
|
||||
template<typename Scalar, int Dim>
|
||||
template<typename RotationMatrixType, typename ScalingMatrixType>
|
||||
void Transform<Scalar,Dim>::computeRotationScaling(RotationMatrixType *rotation, ScalingMatrixType *scaling) const
|
||||
{
|
||||
linear().svd().computeRotationScaling(rotation, scaling);
|
||||
}
|
||||
|
||||
/** decomposes the linear part of the transformation as a product rotation x scaling, the scaling being
|
||||
* not necessarily positive.
|
||||
*
|
||||
* If either pointer is zero, the corresponding computation is skipped.
|
||||
*
|
||||
* \nonstableyet
|
||||
*
|
||||
* \svd_module
|
||||
*
|
||||
* \sa computeRotationScaling(), rotation(), class SVD
|
||||
*/
|
||||
template<typename Scalar, int Dim>
|
||||
template<typename ScalingMatrixType, typename RotationMatrixType>
|
||||
void Transform<Scalar,Dim>::computeScalingRotation(ScalingMatrixType *scaling, RotationMatrixType *rotation) const
|
||||
{
|
||||
linear().svd().computeScalingRotation(scaling, rotation);
|
||||
}
|
||||
|
||||
/** Convenient method to set \c *this from a position, orientation and scale
|
||||
@@ -650,7 +668,9 @@ Transform<Scalar,Dim>::fromPositionOrientationScale(const MatrixBase<PositionDer
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** \returns the inverse transformation matrix according to some given knowledge
|
||||
/** \nonstableyet
|
||||
*
|
||||
* \returns the inverse transformation matrix according to some given knowledge
|
||||
* on \c *this.
|
||||
*
|
||||
* \param traits allows to optimize the inversion process when the transformion
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
#ifndef EIGEN_TRANSLATION_H
|
||||
#define EIGEN_TRANSLATION_H
|
||||
|
||||
/** \geometry_module \ingroup GeometryModule
|
||||
/** \geometry_module \ingroup Geometry_Module
|
||||
*
|
||||
* \class Translation
|
||||
*
|
||||
@@ -152,7 +152,7 @@ public:
|
||||
|
||||
};
|
||||
|
||||
/** \addtogroup GeometryModule */
|
||||
/** \addtogroup Geometry_Module */
|
||||
//@{
|
||||
typedef Translation<float, 2> Translation2f;
|
||||
typedef Translation<double,2> Translation2d;
|
||||
|
||||
@@ -42,17 +42,18 @@
|
||||
* This decomposition provides the generic approach to solving systems of linear equations, computing
|
||||
* the rank, invertibility, inverse, kernel, and determinant.
|
||||
*
|
||||
* This LU decomposition is very stable and well tested with large matrices. Even exact rank computation
|
||||
* works at sizes larger than 1000x1000. However there are use cases where the SVD decomposition is inherently
|
||||
* more stable when dealing with numerically damaged input. For example, computing the kernel is more stable with
|
||||
* SVD because the SVD can determine which singular values are negligible while LU has to work at the level of matrix
|
||||
* coefficients that are less meaningful in this respect.
|
||||
*
|
||||
* The data of the LU decomposition can be directly accessed through the methods matrixLU(),
|
||||
* permutationP(), permutationQ(). Convenience methods matrixL(), matrixU() are also provided.
|
||||
* permutationP(), permutationQ().
|
||||
*
|
||||
* As an exemple, here is how the original matrix can be retrieved, in the square case:
|
||||
* \include class_LU_1.cpp
|
||||
* Output: \verbinclude class_LU_1.out
|
||||
*
|
||||
* When the matrix is not square, matrixL() is no longer very useful: if one needs it, one has
|
||||
* to construct the L matrix by hand, as shown in this example:
|
||||
* \include class_LU_2.cpp
|
||||
* Output: \verbinclude class_LU_2.out
|
||||
* As an exemple, here is how the original matrix can be retrieved:
|
||||
* \include class_LU.cpp
|
||||
* Output: \verbinclude class_LU.out
|
||||
*
|
||||
* \sa MatrixBase::lu(), MatrixBase::determinant(), MatrixBase::inverse(), MatrixBase::computeInverse()
|
||||
*/
|
||||
@@ -108,26 +109,6 @@ template<typename MatrixType> class LU
|
||||
return m_lu;
|
||||
}
|
||||
|
||||
/** \returns an expression of the unit-lower-triangular part of the LU matrix. In the square case,
|
||||
* this is the L matrix. In the non-square, actually obtaining the L matrix takes some
|
||||
* more care, see the documentation of class LU.
|
||||
*
|
||||
* \sa matrixLU(), matrixU()
|
||||
*/
|
||||
inline const Part<MatrixType, UnitLowerTriangular> matrixL() const
|
||||
{
|
||||
return m_lu;
|
||||
}
|
||||
|
||||
/** \returns an expression of the U matrix, i.e. the upper-triangular part of the LU matrix.
|
||||
*
|
||||
* \sa matrixLU(), matrixL()
|
||||
*/
|
||||
inline const Part<MatrixType, UpperTriangular> matrixU() const
|
||||
{
|
||||
return m_lu;
|
||||
}
|
||||
|
||||
/** \returns a vector of integers, whose size is the number of rows of the matrix being decomposed,
|
||||
* representing the P permutation i.e. the permutation of the rows. For its precise meaning,
|
||||
* see the examples given in the documentation of class LU.
|
||||
@@ -360,16 +341,31 @@ LU<MatrixType>::LU(const MatrixType& matrix)
|
||||
int number_of_transpositions = 0;
|
||||
|
||||
RealScalar biggest = RealScalar(0);
|
||||
m_rank = size;
|
||||
for(int k = 0; k < size; ++k)
|
||||
{
|
||||
int row_of_biggest_in_corner, col_of_biggest_in_corner;
|
||||
RealScalar biggest_in_corner;
|
||||
|
||||
biggest_in_corner = m_lu.corner(Eigen::BottomRight, rows-k, cols-k)
|
||||
.cwise().abs()
|
||||
.maxCoeff(&row_of_biggest_in_corner, &col_of_biggest_in_corner);
|
||||
.cwise().abs()
|
||||
.maxCoeff(&row_of_biggest_in_corner, &col_of_biggest_in_corner);
|
||||
row_of_biggest_in_corner += k;
|
||||
col_of_biggest_in_corner += k;
|
||||
if(k==0) biggest = biggest_in_corner;
|
||||
|
||||
// if the corner is negligible, then we have less than full rank, and we can finish early
|
||||
if(ei_isMuchSmallerThan(biggest_in_corner, biggest))
|
||||
{
|
||||
m_rank = k;
|
||||
for(int i = k; i < size; i++)
|
||||
{
|
||||
rows_transpositions.coeffRef(i) = i;
|
||||
cols_transpositions.coeffRef(i) = i;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
rows_transpositions.coeffRef(k) = row_of_biggest_in_corner;
|
||||
cols_transpositions.coeffRef(k) = col_of_biggest_in_corner;
|
||||
if(k != row_of_biggest_in_corner) {
|
||||
@@ -380,12 +376,8 @@ LU<MatrixType>::LU(const MatrixType& matrix)
|
||||
m_lu.col(k).swap(m_lu.col(col_of_biggest_in_corner));
|
||||
++number_of_transpositions;
|
||||
}
|
||||
|
||||
if(k==0) biggest = biggest_in_corner;
|
||||
const Scalar lu_k_k = m_lu.coeff(k,k);
|
||||
if(ei_isMuchSmallerThan(lu_k_k, biggest)) continue;
|
||||
if(k<rows-1)
|
||||
m_lu.col(k).end(rows-k-1) /= lu_k_k;
|
||||
m_lu.col(k).end(rows-k-1) /= m_lu.coeff(k,k);
|
||||
if(k<size-1)
|
||||
for(int col = k + 1; col < cols; ++col)
|
||||
m_lu.col(col).end(rows-k-1) -= m_lu.col(k).end(rows-k-1) * m_lu.coeff(k,col);
|
||||
@@ -400,10 +392,6 @@ LU<MatrixType>::LU(const MatrixType& matrix)
|
||||
std::swap(m_q.coeffRef(k), m_q.coeffRef(cols_transpositions.coeff(k)));
|
||||
|
||||
m_det_pq = (number_of_transpositions%2) ? -1 : 1;
|
||||
|
||||
for(m_rank = 0; m_rank < size; ++m_rank)
|
||||
if(ei_isMuchSmallerThan(m_lu.diagonal().coeff(m_rank), m_lu.diagonal().coeff(0)))
|
||||
break;
|
||||
}
|
||||
|
||||
template<typename MatrixType>
|
||||
@@ -444,8 +432,7 @@ void LU<MatrixType>::computeKernel(KernelMatrixType *result) const
|
||||
.template marked<UpperTriangular>()
|
||||
.solveTriangularInPlace(y);
|
||||
|
||||
for(int i = 0; i < m_rank; ++i)
|
||||
result->row(m_q.coeff(i)) = y.row(i);
|
||||
for(int i = 0; i < m_rank; ++i) result->row(m_q.coeff(i)) = y.row(i);
|
||||
for(int i = m_rank; i < cols; ++i) result->row(m_q.coeff(i)).setZero();
|
||||
for(int k = 0; k < dimker; ++k) result->coeffRef(m_q.coeff(m_rank+k), k) = Scalar(1);
|
||||
}
|
||||
@@ -489,13 +476,13 @@ bool LU<MatrixType>::solve(
|
||||
* So we proceed as follows:
|
||||
* Step 1: compute c = Pb.
|
||||
* Step 2: replace c by the solution x to Lx = c. Exists because L is invertible.
|
||||
* Step 3: compute d such that Ud = c. Check if such d really exists.
|
||||
* Step 4: result = Qd;
|
||||
* Step 3: replace c by the solution x to Ux = c. Check if a solution really exists.
|
||||
* Step 4: result = Qc;
|
||||
*/
|
||||
|
||||
const int rows = m_lu.rows();
|
||||
const int rows = m_lu.rows(), cols = m_lu.cols();
|
||||
ei_assert(b.rows() == rows);
|
||||
const int smalldim = std::min(rows, m_lu.cols());
|
||||
const int smalldim = std::min(rows, cols);
|
||||
|
||||
typename OtherDerived::PlainMatrixType c(b.rows(), b.cols());
|
||||
|
||||
@@ -503,14 +490,14 @@ bool LU<MatrixType>::solve(
|
||||
for(int i = 0; i < rows; ++i) c.row(m_p.coeff(i)) = b.row(i);
|
||||
|
||||
// Step 2
|
||||
Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime,
|
||||
MatrixType::Options,
|
||||
MatrixType::MaxRowsAtCompileTime,
|
||||
MatrixType::MaxRowsAtCompileTime> l(rows, rows);
|
||||
l.setZero();
|
||||
l.corner(Eigen::TopLeft,rows,smalldim)
|
||||
= m_lu.corner(Eigen::TopLeft,rows,smalldim);
|
||||
l.template marked<UnitLowerTriangular>().solveTriangularInPlace(c);
|
||||
m_lu.corner(Eigen::TopLeft,smalldim,smalldim).template marked<UnitLowerTriangular>()
|
||||
.solveTriangularInPlace(
|
||||
c.corner(Eigen::TopLeft, smalldim, c.cols()));
|
||||
if(rows>cols)
|
||||
{
|
||||
c.corner(Eigen::BottomLeft, rows-cols, c.cols())
|
||||
-= m_lu.corner(Eigen::BottomLeft, rows-cols, cols) * c.corner(Eigen::TopLeft, cols, c.cols());
|
||||
}
|
||||
|
||||
// Step 3
|
||||
if(!isSurjective())
|
||||
@@ -522,17 +509,13 @@ bool LU<MatrixType>::solve(
|
||||
if(!ei_isMuchSmallerThan(c.coeff(row,col), biggest_in_c))
|
||||
return false;
|
||||
}
|
||||
Matrix<Scalar, Dynamic, OtherDerived::ColsAtCompileTime,
|
||||
MatrixType::Options,
|
||||
MatrixType::MaxRowsAtCompileTime, OtherDerived::MaxColsAtCompileTime>
|
||||
d(c.corner(TopLeft, m_rank, c.cols()));
|
||||
m_lu.corner(TopLeft, m_rank, m_rank)
|
||||
.template marked<UpperTriangular>()
|
||||
.solveTriangularInPlace(d);
|
||||
.solveTriangularInPlace(c.corner(TopLeft, m_rank, c.cols()));
|
||||
|
||||
// Step 4
|
||||
result->resize(m_lu.cols(), b.cols());
|
||||
for(int i = 0; i < m_rank; ++i) result->row(m_q.coeff(i)) = d.row(i);
|
||||
for(int i = 0; i < m_rank; ++i) result->row(m_q.coeff(i)) = c.row(i);
|
||||
for(int i = m_rank; i < m_lu.cols(); ++i) result->row(m_q.coeff(i)).setZero();
|
||||
return true;
|
||||
}
|
||||
|
||||
6
Eigen/src/LeastSquares/CMakeLists.txt
Normal file
6
Eigen/src/LeastSquares/CMakeLists.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
FILE(GLOB Eigen_LeastSquares_SRCS "*.h")
|
||||
|
||||
INSTALL(FILES
|
||||
${Eigen_LeastSquares_SRCS}
|
||||
DESTINATION ${INCLUDE_INSTALL_DIR}/Eigen/src/LeastSquares
|
||||
)
|
||||
@@ -22,12 +22,12 @@
|
||||
// License and a copy of the GNU General Public License along with
|
||||
// Eigen. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef EIGEN_REGRESSION_H
|
||||
#define EIGEN_REGRESSION_H
|
||||
#ifndef EIGEN_LEASTSQUARES_H
|
||||
#define EIGEN_LEASTSQUARES_H
|
||||
|
||||
/** \ingroup Regression_Module
|
||||
/** \ingroup LeastSquares_Module
|
||||
*
|
||||
* \regression_module
|
||||
* \leastsquares_module
|
||||
*
|
||||
* For a set of points, this function tries to express
|
||||
* one of the coords as a linear (affine) function of the other coords.
|
||||
@@ -128,9 +128,9 @@ void linearRegression(int numPoints,
|
||||
ei_assert((m.adjoint()*m).lu().solve(v, result));
|
||||
}
|
||||
|
||||
/** \ingroup Regression_Module
|
||||
/** \ingroup LeastSquares_Module
|
||||
*
|
||||
* \regression_module
|
||||
* \leastsquares_module
|
||||
*
|
||||
* This function is quite similar to linearRegression(), so we refer to the
|
||||
* documentation of this function and only list here the differences.
|
||||
@@ -195,4 +195,4 @@ void fitHyperplane(int numPoints,
|
||||
}
|
||||
|
||||
|
||||
#endif // EIGEN_REGRESSION_H
|
||||
#endif // EIGEN_LEASTSQUARES_H
|
||||
@@ -57,7 +57,9 @@ template<typename MatrixType> class QR
|
||||
}
|
||||
|
||||
/** \returns whether or not the matrix is of full rank */
|
||||
bool isFullRank() const { return ei_isMuchSmallerThan(m_hCoeffs.cwise().abs().minCoeff(), Scalar(1)); }
|
||||
bool isFullRank() const { return rank() == std::min(m_qr.rows(),m_qr.cols()); }
|
||||
|
||||
int rank() const;
|
||||
|
||||
/** \returns a read-only expression of the matrix R of the actual the QR decomposition */
|
||||
const Part<NestByValue<MatrixRBlockType>, UpperTriangular>
|
||||
@@ -76,13 +78,33 @@ template<typename MatrixType> class QR
|
||||
protected:
|
||||
MatrixType m_qr;
|
||||
VectorType m_hCoeffs;
|
||||
mutable int m_rank;
|
||||
mutable bool m_rankIsUptodate;
|
||||
};
|
||||
|
||||
/** \returns the rank of the matrix of which *this is the QR decomposition. */
|
||||
template<typename MatrixType>
|
||||
int QR<MatrixType>::rank() const
|
||||
{
|
||||
if (!m_rankIsUptodate)
|
||||
{
|
||||
RealScalar maxCoeff = m_qr.diagonal().maxCoeff();
|
||||
int n = std::min(m_qr.rows(),m_qr.cols());
|
||||
m_rank = n;
|
||||
for (int i=0; i<n; ++i)
|
||||
if (ei_isMuchSmallerThan(m_qr.diagonal().coeff(i), maxCoeff))
|
||||
--m_rank;
|
||||
m_rankIsUptodate = true;
|
||||
}
|
||||
return m_rank;
|
||||
}
|
||||
|
||||
#ifndef EIGEN_HIDE_HEAVY_CODE
|
||||
|
||||
template<typename MatrixType>
|
||||
void QR<MatrixType>::_compute(const MatrixType& matrix)
|
||||
{
|
||||
m_rankIsUptodate = false;
|
||||
m_qr = matrix;
|
||||
int rows = matrix.rows();
|
||||
int cols = matrix.cols();
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
FILE(GLOB Eigen_Regression_SRCS "*.h")
|
||||
|
||||
INSTALL(FILES
|
||||
${Eigen_Regression_SRCS}
|
||||
DESTINATION ${INCLUDE_INSTALL_DIR}/Eigen/src/Regression
|
||||
)
|
||||
@@ -79,6 +79,15 @@ template<typename MatrixType> class SVD
|
||||
void compute(const MatrixType& matrix);
|
||||
SVD& sort();
|
||||
|
||||
template<typename UnitaryType, typename PositiveType>
|
||||
void computeUnitaryPositive(UnitaryType *unitary, PositiveType *positive) const;
|
||||
template<typename PositiveType, typename UnitaryType>
|
||||
void computePositiveUnitary(PositiveType *positive, UnitaryType *unitary) const;
|
||||
template<typename RotationType, typename ScalingType>
|
||||
void computeRotationScaling(RotationType *unitary, ScalingType *positive) const;
|
||||
template<typename ScalingType, typename RotationType>
|
||||
void computeScalingRotation(ScalingType *positive, RotationType *unitary) const;
|
||||
|
||||
protected:
|
||||
/** \internal */
|
||||
MatrixUType m_matU;
|
||||
@@ -534,6 +543,95 @@ bool SVD<MatrixType>::solve(const MatrixBase<OtherDerived> &b, ResultType* resul
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Computes the polar decomposition of the matrix, as a product unitary x positive.
|
||||
*
|
||||
* If either pointer is zero, the corresponding computation is skipped.
|
||||
*
|
||||
* Only for square matrices.
|
||||
*
|
||||
* \sa computePositiveUnitary(), computeRotationScaling()
|
||||
*/
|
||||
template<typename MatrixType>
|
||||
template<typename UnitaryType, typename PositiveType>
|
||||
void SVD<MatrixType>::computeUnitaryPositive(UnitaryType *unitary,
|
||||
PositiveType *positive) const
|
||||
{
|
||||
ei_assert(m_matU.cols() == m_matV.cols() && "Polar decomposition is only for square matrices");
|
||||
if(unitary) *unitary = m_matU * m_matV.adjoint();
|
||||
if(positive) *positive = m_matV * m_sigma.asDiagonal() * m_matV.adjoint();
|
||||
}
|
||||
|
||||
/** Computes the polar decomposition of the matrix, as a product positive x unitary.
|
||||
*
|
||||
* If either pointer is zero, the corresponding computation is skipped.
|
||||
*
|
||||
* Only for square matrices.
|
||||
*
|
||||
* \sa computeUnitaryPositive(), computeRotationScaling()
|
||||
*/
|
||||
template<typename MatrixType>
|
||||
template<typename UnitaryType, typename PositiveType>
|
||||
void SVD<MatrixType>::computePositiveUnitary(UnitaryType *positive,
|
||||
PositiveType *unitary) const
|
||||
{
|
||||
ei_assert(m_matU.rows() == m_matV.rows() && "Polar decomposition is only for square matrices");
|
||||
if(unitary) *unitary = m_matU * m_matV.adjoint();
|
||||
if(positive) *positive = m_matU * m_sigma.asDiagonal() * m_matU.adjoint();
|
||||
}
|
||||
|
||||
/** decomposes the matrix as a product rotation x scaling, the scaling being
|
||||
* not necessarily positive.
|
||||
*
|
||||
* If either pointer is zero, the corresponding computation is skipped.
|
||||
*
|
||||
* This method requires the Geometry module.
|
||||
*
|
||||
* \sa computeScalingRotation(), computeUnitaryPositive()
|
||||
*/
|
||||
template<typename MatrixType>
|
||||
template<typename RotationType, typename ScalingType>
|
||||
void SVD<MatrixType>::computeRotationScaling(RotationType *rotation, ScalingType *scaling) const
|
||||
{
|
||||
ei_assert(m_matU.rows() == m_matV.rows() && "Polar decomposition is only for square matrices");
|
||||
Scalar x = (m_matU * m_matV.adjoint()).determinant(); // so x has absolute value 1
|
||||
Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> sv(m_sigma);
|
||||
sv.coeffRef(0) *= x;
|
||||
if(scaling) scaling->lazyAssign(m_matV * sv.asDiagonal() * m_matV.adjoint());
|
||||
if(rotation)
|
||||
{
|
||||
MatrixType m(m_matU);
|
||||
m.col(0) /= x;
|
||||
rotation->lazyAssign(m * m_matV.adjoint());
|
||||
}
|
||||
}
|
||||
|
||||
/** decomposes the matrix as a product scaling x rotation, the scaling being
|
||||
* not necessarily positive.
|
||||
*
|
||||
* If either pointer is zero, the corresponding computation is skipped.
|
||||
*
|
||||
* This method requires the Geometry module.
|
||||
*
|
||||
* \sa computeRotationScaling(), computeUnitaryPositive()
|
||||
*/
|
||||
template<typename MatrixType>
|
||||
template<typename ScalingType, typename RotationType>
|
||||
void SVD<MatrixType>::computeScalingRotation(ScalingType *scaling, RotationType *rotation) const
|
||||
{
|
||||
ei_assert(m_matU.rows() == m_matV.rows() && "Polar decomposition is only for square matrices");
|
||||
Scalar x = (m_matU * m_matV.adjoint()).determinant(); // so x has absolute value 1
|
||||
Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> sv(m_sigma);
|
||||
sv.coeffRef(0) *= x;
|
||||
if(scaling) scaling->lazyAssign(m_matU * sv.asDiagonal() * m_matU.adjoint());
|
||||
if(rotation)
|
||||
{
|
||||
MatrixType m(m_matU);
|
||||
m.col(0) /= x;
|
||||
rotation->lazyAssign(m * m_matV.adjoint());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** \svd_module
|
||||
* \returns the SVD decomposition of \c *this
|
||||
*/
|
||||
|
||||
@@ -55,7 +55,7 @@ void ei_cholmod_configure_matrix(CholmodType& mat)
|
||||
}
|
||||
|
||||
template<typename Scalar, int Flags>
|
||||
cholmod_sparse SparseMatrix<Scalar,Flags>::asCholmodMatrix()
|
||||
cholmod_sparse SparseMatrixBase<Scalar,Flags>::asCholmodMatrix()
|
||||
{
|
||||
cholmod_sparse res;
|
||||
res.nzmax = nonZeros();
|
||||
@@ -108,19 +108,14 @@ cholmod_dense ei_cholmod_map_eigen_to_dense(MatrixBase<Derived>& mat)
|
||||
}
|
||||
|
||||
template<typename Scalar, int Flags>
|
||||
SparseMatrix<Scalar,Flags> SparseMatrix<Scalar,Flags>::Map(cholmod_sparse& cm)
|
||||
MappedSparseMatrix<Scalar,Flags>::MappedSparseMatrix(taucs_ccs_matrix& taucsMat)
|
||||
{
|
||||
SparseMatrix res;
|
||||
res.m_innerSize = cm.nrow;
|
||||
res.m_outerSize = cm.ncol;
|
||||
res.m_outerIndex = reinterpret_cast<int*>(cm.p);
|
||||
SparseArray<Scalar> data = SparseArray<Scalar>::Map(
|
||||
reinterpret_cast<int*>(cm.i),
|
||||
reinterpret_cast<Scalar*>(cm.x),
|
||||
res.m_outerIndex[cm.ncol]);
|
||||
res.m_data.swap(data);
|
||||
res.markAsRValue();
|
||||
return res;
|
||||
m_innerSize = cm.nrow;
|
||||
m_outerSize = cm.ncol;
|
||||
m_outerIndex = reinterpret_cast<int*>(cm.p);
|
||||
m_innerIndices = reinterpret_cast<int*>(cm.i);
|
||||
m_values = reinterpret_cast<Scalar*>(cm.x);
|
||||
m_nnz = res.m_outerIndex[cm.ncol]);
|
||||
}
|
||||
|
||||
template<typename MatrixType>
|
||||
|
||||
230
Eigen/src/Sparse/CompressedStorage.h
Normal file
230
Eigen/src/Sparse/CompressedStorage.h
Normal file
@@ -0,0 +1,230 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
//
|
||||
// Eigen is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 3 of the License, or (at your option) any later version.
|
||||
//
|
||||
// Alternatively, you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of
|
||||
// the License, or (at your option) any later version.
|
||||
//
|
||||
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License and a copy of the GNU General Public License along with
|
||||
// Eigen. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef EIGEN_COMPRESSED_STORAGE_H
|
||||
#define EIGEN_COMPRESSED_STORAGE_H
|
||||
|
||||
/** Stores a sparse set of values as a list of values and a list of indices.
|
||||
*
|
||||
*/
|
||||
template<typename Scalar>
|
||||
class CompressedStorage
|
||||
{
|
||||
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||
public:
|
||||
CompressedStorage()
|
||||
: m_values(0), m_indices(0), m_size(0), m_allocatedSize(0)
|
||||
{}
|
||||
|
||||
CompressedStorage(size_t size)
|
||||
: m_values(0), m_indices(0), m_size(0), m_allocatedSize(0)
|
||||
{
|
||||
resize(size);
|
||||
}
|
||||
|
||||
CompressedStorage(const CompressedStorage& other)
|
||||
: m_values(0), m_indices(0), m_size(0), m_allocatedSize(0)
|
||||
{
|
||||
*this = other;
|
||||
}
|
||||
|
||||
CompressedStorage& operator=(const CompressedStorage& other)
|
||||
{
|
||||
resize(other.size());
|
||||
memcpy(m_values, other.m_values, m_size * sizeof(Scalar));
|
||||
memcpy(m_indices, other.m_indices, m_size * sizeof(int));
|
||||
return *this;
|
||||
}
|
||||
|
||||
void swap(CompressedStorage& other)
|
||||
{
|
||||
std::swap(m_values, other.m_values);
|
||||
std::swap(m_indices, other.m_indices);
|
||||
std::swap(m_size, other.m_size);
|
||||
std::swap(m_allocatedSize, other.m_allocatedSize);
|
||||
}
|
||||
|
||||
~CompressedStorage()
|
||||
{
|
||||
delete[] m_values;
|
||||
delete[] m_indices;
|
||||
}
|
||||
|
||||
void reserve(size_t size)
|
||||
{
|
||||
size_t newAllocatedSize = m_size + size;
|
||||
if (newAllocatedSize > m_allocatedSize)
|
||||
reallocate(newAllocatedSize);
|
||||
}
|
||||
|
||||
void squeeze()
|
||||
{
|
||||
if (m_allocatedSize>m_size)
|
||||
reallocate(m_size);
|
||||
}
|
||||
|
||||
void resize(size_t size, float reserveSizeFactor = 0)
|
||||
{
|
||||
if (m_allocatedSize<size)
|
||||
reallocate(size + size_t(reserveSizeFactor*size));
|
||||
m_size = size;
|
||||
}
|
||||
|
||||
void append(const Scalar& v, int i)
|
||||
{
|
||||
int id = m_size;
|
||||
resize(m_size+1, 1);
|
||||
m_values[id] = v;
|
||||
m_indices[id] = i;
|
||||
}
|
||||
|
||||
inline size_t size() const { return m_size; }
|
||||
inline size_t allocatedSize() const { return m_allocatedSize; }
|
||||
inline void clear() { m_size = 0; }
|
||||
|
||||
inline Scalar& value(size_t i) { return m_values[i]; }
|
||||
inline const Scalar& value(size_t i) const { return m_values[i]; }
|
||||
|
||||
inline int& index(size_t i) { return m_indices[i]; }
|
||||
inline const int& index(size_t i) const { return m_indices[i]; }
|
||||
|
||||
static CompressedStorage Map(int* indices, Scalar* values, size_t size)
|
||||
{
|
||||
CompressedStorage res;
|
||||
res.m_indices = indices;
|
||||
res.m_values = values;
|
||||
res.m_allocatedSize = res.m_size = size;
|
||||
return res;
|
||||
}
|
||||
|
||||
/** \returns the largest \c k such that for all \c j in [0,k) index[\c j]\<\a key */
|
||||
inline int searchLowerIndex(int key) const
|
||||
{
|
||||
return searchLowerIndex(0, m_size, key);
|
||||
}
|
||||
|
||||
/** \returns the largest \c k in [start,end) such that for all \c j in [start,k) index[\c j]\<\a key */
|
||||
inline int searchLowerIndex(size_t start, size_t end, int key) const
|
||||
{
|
||||
while(end>start)
|
||||
{
|
||||
size_t mid = (end+start)>>1;
|
||||
if (m_indices[mid]<key)
|
||||
start = mid+1;
|
||||
else
|
||||
end = mid;
|
||||
}
|
||||
return start;
|
||||
}
|
||||
|
||||
/** \returns the stored value at index \a key
|
||||
* If the value does not exist, then the value \a defaultValue is returned without any insertion. */
|
||||
inline Scalar at(int key, Scalar defaultValue = Scalar(0)) const
|
||||
{
|
||||
if (m_size==0)
|
||||
return defaultValue;
|
||||
else if (key==m_indices[m_size-1])
|
||||
return m_values[m_size-1];
|
||||
// ^^ optimization: let's first check if it is the last coefficient
|
||||
// (very common in high level algorithms)
|
||||
const size_t id = searchLowerIndex(0,m_size-1,key);
|
||||
return ((id<m_size) && (m_indices[id]==key)) ? m_values[id] : defaultValue;
|
||||
}
|
||||
|
||||
/** Like at(), but the search is performed in the range [start,end) */
|
||||
inline Scalar atInRange(size_t start, size_t end, int key, Scalar defaultValue = Scalar(0)) const
|
||||
{
|
||||
if (start==end)
|
||||
return Scalar(0);
|
||||
else if (end>start && key==m_indices[end-1])
|
||||
return m_values[end-1];
|
||||
// ^^ optimization: let's first check if it is the last coefficient
|
||||
// (very common in high level algorithms)
|
||||
const size_t id = searchLowerIndex(start,end-1,key);
|
||||
return ((id<end) && (m_indices[id]==key)) ? m_values[id] : defaultValue;
|
||||
}
|
||||
|
||||
/** \returns a reference to the value at index \a key
|
||||
* If the value does not exist, then the value \a defaultValue is inserted
|
||||
* such that the keys are sorted. */
|
||||
inline Scalar& atWithInsertion(int key, Scalar defaultValue = Scalar(0))
|
||||
{
|
||||
size_t id = searchLowerIndex(0,m_size,key);
|
||||
if (id>=m_size || m_indices[id]!=key)
|
||||
{
|
||||
resize(m_size+1,1);
|
||||
for (size_t j=m_size-1; j>id; --j)
|
||||
{
|
||||
m_indices[j] = m_indices[j-1];
|
||||
m_values[j] = m_values[j-1];
|
||||
}
|
||||
m_indices[id] = key;
|
||||
m_values[id] = defaultValue;
|
||||
}
|
||||
return m_values[id];
|
||||
}
|
||||
|
||||
void prune(Scalar reference, RealScalar epsilon = precision<RealScalar>())
|
||||
{
|
||||
size_t k = 0;
|
||||
size_t n = size();
|
||||
for (size_t i=0; i<n; ++i)
|
||||
{
|
||||
if (!ei_isMuchSmallerThan(value(i), reference, epsilon))
|
||||
{
|
||||
value(k) = value(i);
|
||||
index(k) = index(i);
|
||||
++k;
|
||||
}
|
||||
}
|
||||
resize(k,0);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
inline void reallocate(size_t size)
|
||||
{
|
||||
Scalar* newValues = new Scalar[size];
|
||||
int* newIndices = new int[size];
|
||||
size_t copySize = std::min(size, m_size);
|
||||
// copy
|
||||
memcpy(newValues, m_values, copySize * sizeof(Scalar));
|
||||
memcpy(newIndices, m_indices, copySize * sizeof(int));
|
||||
// delete old stuff
|
||||
delete[] m_values;
|
||||
delete[] m_indices;
|
||||
m_values = newValues;
|
||||
m_indices = newIndices;
|
||||
m_allocatedSize = size;
|
||||
}
|
||||
|
||||
protected:
|
||||
Scalar* m_values;
|
||||
int* m_indices;
|
||||
size_t m_size;
|
||||
size_t m_allocatedSize;
|
||||
|
||||
};
|
||||
|
||||
#endif // EIGEN_COMPRESSED_STORAGE_H
|
||||
@@ -28,307 +28,41 @@
|
||||
/* This file contains the respective InnerIterator definition of the expressions defined in Eigen/Core
|
||||
*/
|
||||
|
||||
template<typename Derived>
|
||||
class MatrixBase<Derived>::InnerIterator
|
||||
/** \class InnerIterator
|
||||
* \brief An InnerIterator allows to loop over the element of a sparse (or dense) matrix or expression
|
||||
*
|
||||
* todo
|
||||
*/
|
||||
|
||||
// generic version for dense matrix and expressions
|
||||
template<typename Derived> class MatrixBase<Derived>::InnerIterator
|
||||
{
|
||||
typedef typename Derived::Scalar Scalar;
|
||||
enum { IsRowMajor = (Derived::Flags&RowMajorBit)==RowMajorBit };
|
||||
public:
|
||||
EIGEN_STRONG_INLINE InnerIterator(const Derived& mat, int outer)
|
||||
: m_matrix(mat), m_inner(0), m_outer(outer), m_end(mat.rows())
|
||||
EIGEN_STRONG_INLINE InnerIterator(const Derived& expr, int outer)
|
||||
: m_expression(expr), m_inner(0), m_outer(outer), m_end(expr.rows())
|
||||
{}
|
||||
|
||||
EIGEN_STRONG_INLINE Scalar value() const
|
||||
{
|
||||
return (Derived::Flags&RowMajorBit) ? m_matrix.coeff(m_outer, m_inner)
|
||||
: m_matrix.coeff(m_inner, m_outer);
|
||||
return (IsRowMajor) ? m_expression.coeff(m_outer, m_inner)
|
||||
: m_expression.coeff(m_inner, m_outer);
|
||||
}
|
||||
|
||||
EIGEN_STRONG_INLINE InnerIterator& operator++() { m_inner++; return *this; }
|
||||
|
||||
EIGEN_STRONG_INLINE int index() const { return m_inner; }
|
||||
inline int row() const { return IsRowMajor ? m_outer : index(); }
|
||||
inline int col() const { return IsRowMajor ? index() : m_outer; }
|
||||
|
||||
EIGEN_STRONG_INLINE operator bool() const { return m_inner < m_end && m_inner>=0; }
|
||||
|
||||
protected:
|
||||
const Derived& m_matrix;
|
||||
const Derived& m_expression;
|
||||
int m_inner;
|
||||
const int m_outer;
|
||||
const int m_end;
|
||||
};
|
||||
|
||||
template<typename MatrixType>
|
||||
class Transpose<MatrixType>::InnerIterator : public MatrixType::InnerIterator
|
||||
{
|
||||
public:
|
||||
|
||||
EIGEN_STRONG_INLINE InnerIterator(const Transpose& trans, int outer)
|
||||
: MatrixType::InnerIterator(trans.m_matrix, outer)
|
||||
{}
|
||||
};
|
||||
|
||||
template<typename MatrixType, int BlockRows, int BlockCols, int PacketAccess, int _DirectAccessStatus>
|
||||
class Block<MatrixType, BlockRows, BlockCols, PacketAccess, _DirectAccessStatus>::InnerIterator
|
||||
{
|
||||
typedef typename Block::Scalar Scalar;
|
||||
typedef typename ei_traits<Block>::_MatrixTypeNested _MatrixTypeNested;
|
||||
typedef typename _MatrixTypeNested::InnerIterator MatrixTypeIterator;
|
||||
public:
|
||||
|
||||
EIGEN_STRONG_INLINE InnerIterator(const Block& block, int outer)
|
||||
: m_iter(block.m_matrix,(Block::Flags&RowMajor) ? block.m_startRow.value() + outer : block.m_startCol.value() + outer),
|
||||
m_start( (Block::Flags&RowMajor) ? block.m_startCol.value() : block.m_startRow.value()),
|
||||
m_end(m_start + ((Block::Flags&RowMajor) ? block.m_blockCols.value() : block.m_blockRows.value())),
|
||||
m_offset( (Block::Flags&RowMajor) ? block.m_startCol.value() : block.m_startRow.value())
|
||||
{
|
||||
while (m_iter.index()>=0 && m_iter.index()<m_start)
|
||||
++m_iter;
|
||||
}
|
||||
|
||||
EIGEN_STRONG_INLINE InnerIterator& operator++()
|
||||
{
|
||||
++m_iter;
|
||||
return *this;
|
||||
}
|
||||
|
||||
EIGEN_STRONG_INLINE Scalar value() const { return m_iter.value(); }
|
||||
|
||||
EIGEN_STRONG_INLINE int index() const { return m_iter.index() - m_offset; }
|
||||
|
||||
EIGEN_STRONG_INLINE operator bool() const { return m_iter && m_iter.index()<m_end; }
|
||||
|
||||
protected:
|
||||
MatrixTypeIterator m_iter;
|
||||
int m_start;
|
||||
int m_end;
|
||||
int m_offset;
|
||||
};
|
||||
|
||||
template<typename MatrixType, int BlockRows, int BlockCols, int PacketAccess>
|
||||
class Block<MatrixType, BlockRows, BlockCols, PacketAccess, IsSparse>::InnerIterator
|
||||
{
|
||||
typedef typename Block::Scalar Scalar;
|
||||
typedef typename ei_traits<Block>::_MatrixTypeNested _MatrixTypeNested;
|
||||
typedef typename _MatrixTypeNested::InnerIterator MatrixTypeIterator;
|
||||
public:
|
||||
|
||||
EIGEN_STRONG_INLINE InnerIterator(const Block& block, int outer)
|
||||
: m_iter(block.m_matrix,(Block::Flags&RowMajor) ? block.m_startRow.value() + outer : block.m_startCol.value() + outer),
|
||||
m_start( (Block::Flags&RowMajor) ? block.m_startCol.value() : block.m_startRow.value()),
|
||||
m_end(m_start + ((Block::Flags&RowMajor) ? block.m_blockCols.value() : block.m_blockRows.value())),
|
||||
m_offset( (Block::Flags&RowMajor) ? block.m_startCol.value() : block.m_startRow.value())
|
||||
{
|
||||
while (m_iter.index()>=0 && m_iter.index()<m_start)
|
||||
++m_iter;
|
||||
}
|
||||
|
||||
EIGEN_STRONG_INLINE InnerIterator& operator++()
|
||||
{
|
||||
++m_iter;
|
||||
return *this;
|
||||
}
|
||||
|
||||
EIGEN_STRONG_INLINE Scalar value() const { return m_iter.value(); }
|
||||
|
||||
EIGEN_STRONG_INLINE int index() const { return m_iter.index() - m_offset; }
|
||||
|
||||
EIGEN_STRONG_INLINE operator bool() const { return m_iter && m_iter.index()<m_end; }
|
||||
|
||||
protected:
|
||||
MatrixTypeIterator m_iter;
|
||||
int m_start;
|
||||
int m_end;
|
||||
int m_offset;
|
||||
};
|
||||
|
||||
template<typename UnaryOp, typename MatrixType>
|
||||
class CwiseUnaryOp<UnaryOp,MatrixType>::InnerIterator
|
||||
{
|
||||
typedef typename CwiseUnaryOp::Scalar Scalar;
|
||||
typedef typename ei_traits<CwiseUnaryOp>::_MatrixTypeNested _MatrixTypeNested;
|
||||
typedef typename _MatrixTypeNested::InnerIterator MatrixTypeIterator;
|
||||
public:
|
||||
|
||||
EIGEN_STRONG_INLINE InnerIterator(const CwiseUnaryOp& unaryOp, int outer)
|
||||
: m_iter(unaryOp.m_matrix,outer), m_functor(unaryOp.m_functor), m_id(-1)
|
||||
{
|
||||
this->operator++();
|
||||
}
|
||||
|
||||
EIGEN_STRONG_INLINE InnerIterator& operator++()
|
||||
{
|
||||
if (m_iter)
|
||||
{
|
||||
m_id = m_iter.index();
|
||||
m_value = m_functor(m_iter.value());
|
||||
++m_iter;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_id = -1;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
EIGEN_STRONG_INLINE Scalar value() const { return m_value; }
|
||||
|
||||
EIGEN_STRONG_INLINE int index() const { return m_id; }
|
||||
|
||||
EIGEN_STRONG_INLINE operator bool() const { return m_id>=0; }
|
||||
|
||||
protected:
|
||||
MatrixTypeIterator m_iter;
|
||||
const UnaryOp& m_functor;
|
||||
Scalar m_value;
|
||||
int m_id;
|
||||
};
|
||||
|
||||
template<typename T> struct ei_is_scalar_product { enum { ret = false }; };
|
||||
template<typename T> struct ei_is_scalar_product<ei_scalar_product_op<T> > { enum { ret = true }; };
|
||||
|
||||
template<typename BinaryOp, typename Lhs, typename Rhs, typename Derived>
|
||||
class CwiseBinaryOpInnerIterator;
|
||||
|
||||
template<typename BinaryOp, typename Lhs, typename Rhs>
|
||||
class CwiseBinaryOp<BinaryOp,Lhs,Rhs>::InnerIterator
|
||||
: public CwiseBinaryOpInnerIterator<BinaryOp,Lhs,Rhs, typename CwiseBinaryOp<BinaryOp,Lhs,Rhs>::InnerIterator>
|
||||
{
|
||||
typedef CwiseBinaryOpInnerIterator<
|
||||
BinaryOp,Lhs,Rhs, typename CwiseBinaryOp<BinaryOp,Lhs,Rhs>::InnerIterator> Base;
|
||||
public:
|
||||
typedef typename CwiseBinaryOp::Scalar Scalar;
|
||||
typedef typename ei_traits<CwiseBinaryOp>::_LhsNested _LhsNested;
|
||||
typedef typename _LhsNested::InnerIterator LhsIterator;
|
||||
typedef typename ei_traits<CwiseBinaryOp>::_RhsNested _RhsNested;
|
||||
typedef typename _RhsNested::InnerIterator RhsIterator;
|
||||
// public:
|
||||
EIGEN_STRONG_INLINE InnerIterator(const CwiseBinaryOp& binOp, int outer)
|
||||
: Base(binOp.m_lhs,binOp.m_rhs,binOp.m_functor,outer)
|
||||
{}
|
||||
};
|
||||
|
||||
template<typename BinaryOp, typename Lhs, typename Rhs, typename Derived>
|
||||
class CwiseBinaryOpInnerIterator
|
||||
{
|
||||
typedef CwiseBinaryOp<BinaryOp,Lhs,Rhs> ExpressionType;
|
||||
typedef typename ExpressionType::Scalar Scalar;
|
||||
typedef typename ei_traits<ExpressionType>::_LhsNested _LhsNested;
|
||||
// typedef typename ei_traits<ExpressionType>::LhsIterator LhsIterator;
|
||||
typedef typename ei_traits<ExpressionType>::_RhsNested _RhsNested;
|
||||
// typedef typename ei_traits<ExpressionType>::RhsIterator RhsIterator;
|
||||
// typedef typename ei_traits<CwiseBinaryOp>::_LhsNested _LhsNested;
|
||||
typedef typename _LhsNested::InnerIterator LhsIterator;
|
||||
// typedef typename ei_traits<CwiseBinaryOp>::_RhsNested _RhsNested;
|
||||
typedef typename _RhsNested::InnerIterator RhsIterator;
|
||||
// enum { IsProduct = ei_is_scalar_product<BinaryOp>::ret };
|
||||
public:
|
||||
|
||||
EIGEN_STRONG_INLINE CwiseBinaryOpInnerIterator(const _LhsNested& lhs, const _RhsNested& rhs,
|
||||
const BinaryOp& functor, int outer)
|
||||
: m_lhsIter(lhs,outer), m_rhsIter(rhs,outer), m_functor(functor), m_id(-1)
|
||||
{
|
||||
this->operator++();
|
||||
}
|
||||
|
||||
EIGEN_STRONG_INLINE Derived& operator++()
|
||||
{
|
||||
if (m_lhsIter && m_rhsIter && (m_lhsIter.index() == m_rhsIter.index()))
|
||||
{
|
||||
m_id = m_lhsIter.index();
|
||||
m_value = m_functor(m_lhsIter.value(), m_rhsIter.value());
|
||||
++m_lhsIter;
|
||||
++m_rhsIter;
|
||||
}
|
||||
else if (m_lhsIter && (!m_rhsIter || (m_lhsIter.index() < m_rhsIter.index())))
|
||||
{
|
||||
m_id = m_lhsIter.index();
|
||||
m_value = m_functor(m_lhsIter.value(), Scalar(0));
|
||||
++m_lhsIter;
|
||||
}
|
||||
else if (m_rhsIter && (!m_lhsIter || (m_lhsIter.index() > m_rhsIter.index())))
|
||||
{
|
||||
m_id = m_rhsIter.index();
|
||||
m_value = m_functor(Scalar(0), m_rhsIter.value());
|
||||
++m_rhsIter;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_id = -1;
|
||||
}
|
||||
return *static_cast<Derived*>(this);
|
||||
}
|
||||
|
||||
EIGEN_STRONG_INLINE Scalar value() const { return m_value; }
|
||||
|
||||
EIGEN_STRONG_INLINE int index() const { return m_id; }
|
||||
|
||||
EIGEN_STRONG_INLINE operator bool() const { return m_id>=0; }
|
||||
|
||||
protected:
|
||||
LhsIterator m_lhsIter;
|
||||
RhsIterator m_rhsIter;
|
||||
const BinaryOp& m_functor;
|
||||
Scalar m_value;
|
||||
int m_id;
|
||||
};
|
||||
/*
|
||||
template<typename T, typename Lhs, typename Rhs, typename Derived>
|
||||
class CwiseBinaryOpInnerIterator<ei_scalar_product_op<T>,Lhs,Rhs,Derived>
|
||||
{
|
||||
typedef typename CwiseBinaryOp::Scalar Scalar;
|
||||
typedef typename ei_traits<CwiseBinaryOp>::_LhsNested _LhsNested;
|
||||
typedef typename _LhsNested::InnerIterator LhsIterator;
|
||||
typedef typename ei_traits<CwiseBinaryOp>::_RhsNested _RhsNested;
|
||||
typedef typename _RhsNested::InnerIterator RhsIterator;
|
||||
public:
|
||||
|
||||
EIGEN_STRONG_INLINE CwiseBinaryOpInnerIterator(const CwiseBinaryOp& binOp, int outer)
|
||||
: m_lhsIter(binOp.m_lhs,outer), m_rhsIter(binOp.m_rhs,outer), m_functor(binOp.m_functor)//, m_id(-1)
|
||||
{
|
||||
//this->operator++();
|
||||
while (m_lhsIter && m_rhsIter && m_lhsIter.index() != m_rhsIter.index())
|
||||
{
|
||||
if (m_lhsIter.index() < m_rhsIter.index())
|
||||
++m_lhsIter;
|
||||
else
|
||||
++m_rhsIter;
|
||||
}
|
||||
}
|
||||
|
||||
EIGEN_STRONG_INLINE Derived& operator++()
|
||||
{
|
||||
// m_id = -1;
|
||||
asm("#beginwhile");
|
||||
while (m_lhsIter && m_rhsIter)
|
||||
{
|
||||
if (m_lhsIter.index() == m_rhsIter.index())
|
||||
{
|
||||
// m_id = m_lhsIter.index();
|
||||
//m_value = m_functor(m_lhsIter.value(), m_rhsIter.value());
|
||||
++m_lhsIter;
|
||||
++m_rhsIter;
|
||||
break;
|
||||
}
|
||||
else if (m_lhsIter.index() < m_rhsIter.index())
|
||||
++m_lhsIter;
|
||||
else
|
||||
++m_rhsIter;
|
||||
}
|
||||
asm("#endwhile");
|
||||
return *static_cast<Derived*>(this);
|
||||
}
|
||||
|
||||
EIGEN_STRONG_INLINE Scalar value() const { return m_functor(m_lhsIter.value(), m_rhsIter.value()); }
|
||||
|
||||
EIGEN_STRONG_INLINE int index() const { return m_lhsIter.index(); }
|
||||
|
||||
EIGEN_STRONG_INLINE operator bool() const { return m_lhsIter && m_rhsIter; }
|
||||
|
||||
protected:
|
||||
LhsIterator m_lhsIter;
|
||||
RhsIterator m_rhsIter;
|
||||
const BinaryOp& m_functor;
|
||||
// Scalar m_value;
|
||||
// int m_id;
|
||||
};*/
|
||||
|
||||
#endif // EIGEN_COREITERATORS_H
|
||||
|
||||
291
Eigen/src/Sparse/DynamicSparseMatrix.h
Normal file
291
Eigen/src/Sparse/DynamicSparseMatrix.h
Normal file
@@ -0,0 +1,291 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
//
|
||||
// Eigen is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 3 of the License, or (at your option) any later version.
|
||||
//
|
||||
// Alternatively, you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of
|
||||
// the License, or (at your option) any later version.
|
||||
//
|
||||
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License and a copy of the GNU General Public License along with
|
||||
// Eigen. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef EIGEN_DYNAMIC_SPARSEMATRIX_H
|
||||
#define EIGEN_DYNAMIC_SPARSEMATRIX_H
|
||||
|
||||
/** \class DynamicSparseMatrix
|
||||
*
|
||||
* \brief A sparse matrix class designed for matrix assembly purpose
|
||||
*
|
||||
* \param _Scalar the scalar type, i.e. the type of the coefficients
|
||||
*
|
||||
* Unlike SparseMatrix, this class provides a much higher degree of flexibility. In particular, it allows
|
||||
* random read/write accesses in log(rho*outer_size) where \c rho is the probability that a coefficient is
|
||||
* nonzero and outer_size is the number of columns if the matrix is column-major and the number of rows
|
||||
* otherwise.
|
||||
*
|
||||
* Internally, the data are stored as a std::vector of compressed vector. The performances of random writes might
|
||||
* decrease as the number of nonzeros per inner-vector increase. In practice, we observed very good performance
|
||||
* till about 100 nonzeros/vector, and the performance remains relatively good till 500 nonzeros/vectors.
|
||||
*
|
||||
* \see SparseMatrix
|
||||
*/
|
||||
template<typename _Scalar, int _Flags>
|
||||
struct ei_traits<DynamicSparseMatrix<_Scalar, _Flags> >
|
||||
{
|
||||
typedef _Scalar Scalar;
|
||||
enum {
|
||||
RowsAtCompileTime = Dynamic,
|
||||
ColsAtCompileTime = Dynamic,
|
||||
MaxRowsAtCompileTime = Dynamic,
|
||||
MaxColsAtCompileTime = Dynamic,
|
||||
Flags = SparseBit | _Flags,
|
||||
CoeffReadCost = NumTraits<Scalar>::ReadCost,
|
||||
SupportedAccessPatterns = OuterRandomAccessPattern
|
||||
};
|
||||
};
|
||||
|
||||
template<typename _Scalar, int _Flags>
|
||||
class DynamicSparseMatrix
|
||||
: public SparseMatrixBase<DynamicSparseMatrix<_Scalar, _Flags> >
|
||||
{
|
||||
public:
|
||||
EIGEN_SPARSE_GENERIC_PUBLIC_INTERFACE(DynamicSparseMatrix)
|
||||
// FIXME: why are these operator already alvailable ???
|
||||
// EIGEN_SPARSE_INHERIT_ASSIGNMENT_OPERATOR(DynamicSparseMatrix, +=)
|
||||
// EIGEN_SPARSE_INHERIT_ASSIGNMENT_OPERATOR(DynamicSparseMatrix, -=)
|
||||
typedef MappedSparseMatrix<Scalar,Flags> Map;
|
||||
|
||||
protected:
|
||||
|
||||
enum { IsRowMajor = Base::IsRowMajor };
|
||||
typedef DynamicSparseMatrix<Scalar,(Flags&~RowMajorBit)|(IsRowMajor?RowMajorBit:0)> TransposedSparseMatrix;
|
||||
|
||||
int m_innerSize;
|
||||
std::vector<CompressedStorage<Scalar> > m_data;
|
||||
|
||||
public:
|
||||
|
||||
inline int rows() const { return IsRowMajor ? outerSize() : m_innerSize; }
|
||||
inline int cols() const { return IsRowMajor ? m_innerSize : outerSize(); }
|
||||
inline int innerSize() const { return m_innerSize; }
|
||||
inline int outerSize() const { return m_data.size(); }
|
||||
inline int innerNonZeros(int j) const { return m_data[j].size(); }
|
||||
|
||||
/** \returns the coefficient value at given position \a row, \a col
|
||||
* This operation involes a log(rho*outer_size) binary search.
|
||||
*/
|
||||
inline Scalar coeff(int row, int col) const
|
||||
{
|
||||
const int outer = IsRowMajor ? row : col;
|
||||
const int inner = IsRowMajor ? col : row;
|
||||
return m_data[outer].at(inner);
|
||||
}
|
||||
|
||||
/** \returns a reference to the coefficient value at given position \a row, \a col
|
||||
* This operation involes a log(rho*outer_size) binary search. If the coefficient does not
|
||||
* exist yet, then a sorted insertion into a sequential buffer is performed.
|
||||
*/
|
||||
inline Scalar& coeffRef(int row, int col)
|
||||
{
|
||||
const int outer = IsRowMajor ? row : col;
|
||||
const int inner = IsRowMajor ? col : row;
|
||||
return m_data[outer].atWithInsertion(inner);
|
||||
}
|
||||
|
||||
class InnerIterator;
|
||||
|
||||
inline void setZero()
|
||||
{
|
||||
for (int j=0; j<outerSize(); ++j)
|
||||
m_data[j].clear();
|
||||
}
|
||||
|
||||
/** \returns the number of non zero coefficients */
|
||||
inline int nonZeros() const
|
||||
{
|
||||
int res = 0;
|
||||
for (int j=0; j<outerSize(); ++j)
|
||||
res += m_data[j].size();
|
||||
return res;
|
||||
}
|
||||
|
||||
/** Set the matrix to zero and reserve the memory for \a reserveSize nonzero coefficients. */
|
||||
inline void startFill(int reserveSize = 1000)
|
||||
{
|
||||
int reserveSizePerVector = std::max(reserveSize/outerSize(),4);
|
||||
for (int j=0; j<outerSize(); ++j)
|
||||
{
|
||||
m_data[j].clear();
|
||||
m_data[j].reserve(reserveSizePerVector);
|
||||
}
|
||||
}
|
||||
|
||||
/** inserts a nonzero coefficient at given coordinates \a row, \a col and returns its reference assuming that:
|
||||
* 1 - the coefficient does not exist yet
|
||||
* 2 - this the coefficient with greater inner coordinate for the given outer coordinate.
|
||||
* In other words, assuming \c *this is column-major, then there must not exists any nonzero coefficient of coordinates
|
||||
* \c i \c x \a col such that \c i >= \a row. Otherwise the matrix is invalid.
|
||||
*
|
||||
* \see fillrand(), coeffRef()
|
||||
*/
|
||||
inline Scalar& fill(int row, int col)
|
||||
{
|
||||
const int outer = IsRowMajor ? row : col;
|
||||
const int inner = IsRowMajor ? col : row;
|
||||
ei_assert(outer<int(m_data.size()) && inner<m_innerSize);
|
||||
ei_assert((m_data[outer].size()==0) || (m_data[outer].index(m_data[outer].size()-1)<inner));
|
||||
m_data[outer].append(0, inner);
|
||||
return m_data[outer].value(m_data[outer].size()-1);
|
||||
}
|
||||
|
||||
/** Like fill() but with random inner coordinates.
|
||||
* Compared to the generic coeffRef(), the unique limitation is that we assume
|
||||
* the coefficient does not exist yet.
|
||||
*/
|
||||
inline Scalar& fillrand(int row, int col)
|
||||
{
|
||||
const int outer = IsRowMajor ? row : col;
|
||||
const int inner = IsRowMajor ? col : row;
|
||||
|
||||
int startId = 0;
|
||||
int id = m_data[outer].size() - 1;
|
||||
m_data[outer].resize(id+2,1);
|
||||
|
||||
while ( (id >= startId) && (m_data[outer].index(id) > inner) )
|
||||
{
|
||||
m_data[outer].index(id+1) = m_data[outer].index(id);
|
||||
m_data[outer].value(id+1) = m_data[outer].value(id);
|
||||
--id;
|
||||
}
|
||||
m_data[outer].index(id+1) = inner;
|
||||
m_data[outer].value(id+1) = 0;
|
||||
return m_data[outer].value(id+1);
|
||||
}
|
||||
|
||||
/** Does nothing. Provided for compatibility with SparseMatrix. */
|
||||
inline void endFill() {}
|
||||
|
||||
void prune(Scalar reference, RealScalar epsilon = precision<RealScalar>())
|
||||
{
|
||||
for (int j=0; j<outerSize(); ++j)
|
||||
m_data[j].prune(reference,epsilon);
|
||||
}
|
||||
|
||||
/** Resize the matrix without preserving the data (the matrix is set to zero)
|
||||
*/
|
||||
void resize(int rows, int cols)
|
||||
{
|
||||
const int outerSize = IsRowMajor ? rows : cols;
|
||||
m_innerSize = IsRowMajor ? cols : rows;
|
||||
setZero();
|
||||
if (int(m_data.size()) != outerSize)
|
||||
{
|
||||
m_data.resize(outerSize);
|
||||
}
|
||||
}
|
||||
|
||||
void resizeAndKeepData(int rows, int cols)
|
||||
{
|
||||
const int outerSize = IsRowMajor ? rows : cols;
|
||||
const int innerSize = IsRowMajor ? cols : rows;
|
||||
if (m_innerSize>innerSize)
|
||||
{
|
||||
// remove all coefficients with innerCoord>=innerSize
|
||||
// TODO
|
||||
std::cerr << "not implemented yet\n";
|
||||
exit(2);
|
||||
}
|
||||
if (m_data.size() != outerSize)
|
||||
{
|
||||
m_data.resize(outerSize);
|
||||
}
|
||||
}
|
||||
|
||||
inline DynamicSparseMatrix()
|
||||
: m_innerSize(0)
|
||||
{
|
||||
ei_assert(innerSize()==0 && outerSize()==0);
|
||||
}
|
||||
|
||||
inline DynamicSparseMatrix(int rows, int cols)
|
||||
: m_innerSize(0)
|
||||
{
|
||||
resize(rows, cols);
|
||||
}
|
||||
|
||||
template<typename OtherDerived>
|
||||
inline DynamicSparseMatrix(const SparseMatrixBase<OtherDerived>& other)
|
||||
: m_innerSize(0)
|
||||
{
|
||||
*this = other.derived();
|
||||
}
|
||||
|
||||
inline DynamicSparseMatrix(const DynamicSparseMatrix& other)
|
||||
: Base(), m_innerSize(0)
|
||||
{
|
||||
*this = other.derived();
|
||||
}
|
||||
|
||||
inline void swap(DynamicSparseMatrix& other)
|
||||
{
|
||||
//EIGEN_DBG_SPARSE(std::cout << "SparseMatrix:: swap\n");
|
||||
std::swap(m_innerSize, other.m_innerSize);
|
||||
//std::swap(m_outerSize, other.m_outerSize);
|
||||
m_data.swap(other.m_data);
|
||||
}
|
||||
|
||||
inline DynamicSparseMatrix& operator=(const DynamicSparseMatrix& other)
|
||||
{
|
||||
if (other.isRValue())
|
||||
{
|
||||
swap(other.const_cast_derived());
|
||||
}
|
||||
else
|
||||
{
|
||||
resize(other.rows(), other.cols());
|
||||
m_data = other.m_data;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename OtherDerived>
|
||||
inline DynamicSparseMatrix& operator=(const SparseMatrixBase<OtherDerived>& other)
|
||||
{
|
||||
return SparseMatrixBase<DynamicSparseMatrix>::operator=(other.derived());
|
||||
}
|
||||
|
||||
/** Destructor */
|
||||
inline ~DynamicSparseMatrix() {}
|
||||
};
|
||||
|
||||
template<typename Scalar, int _Flags>
|
||||
class DynamicSparseMatrix<Scalar,_Flags>::InnerIterator : public SparseVector<Scalar,_Flags>::InnerIterator
|
||||
{
|
||||
typedef typename SparseVector<Scalar,_Flags>::InnerIterator Base;
|
||||
public:
|
||||
InnerIterator(const DynamicSparseMatrix& mat, int outer)
|
||||
: Base(mat.m_data[outer]), m_outer(outer)
|
||||
{}
|
||||
|
||||
inline int row() const { return IsRowMajor ? m_outer : Base::index(); }
|
||||
inline int col() const { return IsRowMajor ? Base::index() : m_outer; }
|
||||
|
||||
|
||||
protected:
|
||||
const int m_outer;
|
||||
};
|
||||
|
||||
#endif // EIGEN_DYNAMIC_SPARSEMATRIX_H
|
||||
171
Eigen/src/Sparse/MappedSparseMatrix.h
Normal file
171
Eigen/src/Sparse/MappedSparseMatrix.h
Normal file
@@ -0,0 +1,171 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
//
|
||||
// Eigen is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 3 of the License, or (at your option) any later version.
|
||||
//
|
||||
// Alternatively, you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of
|
||||
// the License, or (at your option) any later version.
|
||||
//
|
||||
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License and a copy of the GNU General Public License along with
|
||||
// Eigen. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef EIGEN_MAPPED_SPARSEMATRIX_H
|
||||
#define EIGEN_MAPPED_SPARSEMATRIX_H
|
||||
|
||||
/** \class MappedSparseMatrix
|
||||
*
|
||||
* \brief Sparse matrix
|
||||
*
|
||||
* \param _Scalar the scalar type, i.e. the type of the coefficients
|
||||
*
|
||||
* See http://www.netlib.org/linalg/html_templates/node91.html for details on the storage scheme.
|
||||
*
|
||||
*/
|
||||
template<typename _Scalar, int _Flags>
|
||||
struct ei_traits<MappedSparseMatrix<_Scalar, _Flags> > : ei_traits<SparseMatrix<_Scalar, _Flags> >
|
||||
{};
|
||||
|
||||
template<typename _Scalar, int _Flags>
|
||||
class MappedSparseMatrix
|
||||
: public SparseMatrixBase<MappedSparseMatrix<_Scalar, _Flags> >
|
||||
{
|
||||
public:
|
||||
EIGEN_SPARSE_GENERIC_PUBLIC_INTERFACE(MappedSparseMatrix)
|
||||
|
||||
protected:
|
||||
enum { IsRowMajor = Base::IsRowMajor };
|
||||
|
||||
int m_outerSize;
|
||||
int m_innerSize;
|
||||
int m_nnz;
|
||||
int* m_outerIndex;
|
||||
int* m_innerIndices;
|
||||
Scalar* m_values;
|
||||
|
||||
public:
|
||||
|
||||
inline int rows() const { return IsRowMajor ? m_outerSize : m_innerSize; }
|
||||
inline int cols() const { return IsRowMajor ? m_innerSize : m_outerSize; }
|
||||
inline int innerSize() const { return m_innerSize; }
|
||||
inline int outerSize() const { return m_outerSize; }
|
||||
inline int innerNonZeros(int j) const { return m_outerIndex[j+1]-m_outerIndex[j]; }
|
||||
|
||||
//----------------------------------------
|
||||
// direct access interface
|
||||
inline const Scalar* _valuePtr() const { return &m_values; }
|
||||
inline Scalar* _valuePtr() { return &m_values; }
|
||||
|
||||
inline const int* _innerIndexPtr() const { return &m_innerIndices; }
|
||||
inline int* _innerIndexPtr() { return m_innerIndices; }
|
||||
|
||||
inline const int* _outerIndexPtr() const { return m_outerIndex; }
|
||||
inline int* _outerIndexPtr() { return m_outerIndex; }
|
||||
//----------------------------------------
|
||||
|
||||
inline Scalar coeff(int row, int col) const
|
||||
{
|
||||
const int outer = RowMajor ? row : col;
|
||||
const int inner = RowMajor ? col : row;
|
||||
|
||||
int start = m_outerIndex[outer];
|
||||
int end = m_outerIndex[outer+1];
|
||||
if (start==end)
|
||||
return Scalar(0);
|
||||
else if (end>0 && inner==m_innerIndices[end-1])
|
||||
return m_values[end-1];
|
||||
// ^^ optimization: let's first check if it is the last coefficient
|
||||
// (very common in high level algorithms)
|
||||
|
||||
const int* r = std::lower_bound(&m_innerIndices[start],&m_innerIndices[end-1],inner);
|
||||
const int id = r-&m_innerIndices[0];
|
||||
return ((*r==inner) && (id<end)) ? m_values[id] : Scalar(0);
|
||||
}
|
||||
|
||||
inline Scalar& coeffRef(int row, int col)
|
||||
{
|
||||
const int outer = RowMajor ? row : col;
|
||||
const int inner = RowMajor ? col : row;
|
||||
|
||||
int start = m_outerIndex[outer];
|
||||
int end = m_outerIndex[outer+1];
|
||||
ei_assert(end>=start && "you probably called coeffRef on a non finalized matrix");
|
||||
ei_assert(end>start && "coeffRef cannot be called on a zero coefficient");
|
||||
int* r = std::lower_bound(&m_innerIndices[start],&m_innerIndices[end],inner);
|
||||
const int id = r-&m_innerIndices[0];
|
||||
ei_assert((*r==inner) && (id<end) && "coeffRef cannot be called on a zero coefficient");
|
||||
return m_values[id];
|
||||
}
|
||||
|
||||
class InnerIterator;
|
||||
|
||||
/** \returns the number of non zero coefficients */
|
||||
inline int nonZeros() const { return m_nnz; }
|
||||
|
||||
inline MappedSparseMatrix(int rows, int cols, int nnz, int* outerIndexPtr, int* innerIndexPtr, Scalar* valuePtr)
|
||||
: m_outerSize(IsRowMajor?rows:cols), m_innerSize(IsRowMajor?cols:rows), m_nnz(nnz), m_outerIndex(outerIndexPtr),
|
||||
m_innerIndices(innerIndexPtr), m_values(valuePtr)
|
||||
{}
|
||||
|
||||
#ifdef EIGEN_TAUCS_SUPPORT
|
||||
explicit MappedSparseMatrix(taucs_ccs_matrix& taucsMatrix);
|
||||
#endif
|
||||
|
||||
#ifdef EIGEN_CHOLMOD_SUPPORT
|
||||
explicit MappedSparseMatrix(cholmod_sparse& cholmodMatrix);
|
||||
#endif
|
||||
|
||||
#ifdef EIGEN_SUPERLU_SUPPORT
|
||||
explicit MappedSparseMatrix(SluMatrix& sluMatrix);
|
||||
#endif
|
||||
|
||||
/** Empty destructor */
|
||||
inline ~MappedSparseMatrix() {}
|
||||
};
|
||||
|
||||
template<typename Scalar, int _Flags>
|
||||
class MappedSparseMatrix<Scalar,_Flags>::InnerIterator
|
||||
{
|
||||
public:
|
||||
InnerIterator(const MappedSparseMatrix& mat, int outer)
|
||||
: m_matrix(mat), m_outer(outer), m_id(mat._outerIndexPtr[outer]), m_start(m_id), m_end(mat._outerIndexPtr[outer+1])
|
||||
{}
|
||||
|
||||
template<unsigned int Added, unsigned int Removed>
|
||||
InnerIterator(const Flagged<MappedSparseMatrix,Added,Removed>& mat, int outer)
|
||||
: m_matrix(mat._expression()), m_id(m_matrix._outerIndexPtr[outer]),
|
||||
m_start(m_id), m_end(m_matrix._outerIndexPtr[outer+1])
|
||||
{}
|
||||
|
||||
inline InnerIterator& operator++() { m_id++; return *this; }
|
||||
|
||||
inline Scalar value() const { return m_matrix.m_valuePtr[m_id]; }
|
||||
inline Scalar& valueRef() { return const_cast<Scalar&>(m_matrix._valuePtr[m_id]); }
|
||||
|
||||
inline int index() const { return m_matrix._innerIndexPtr(m_id); }
|
||||
inline int row() const { return IsRowMajor ? m_outer : index(); }
|
||||
inline int col() const { return IsRowMajor ? index() : m_outer; }
|
||||
|
||||
inline operator bool() const { return (m_id < m_end) && (m_id>=m_start); }
|
||||
|
||||
protected:
|
||||
const MappedSparseMatrix& m_matrix;
|
||||
const int m_outer;
|
||||
int m_id;
|
||||
const int m_start;
|
||||
const int m_end;
|
||||
};
|
||||
|
||||
#endif // EIGEN_MAPPED_SPARSEMATRIX_H
|
||||
@@ -25,6 +25,10 @@
|
||||
#ifndef EIGEN_RANDOMSETTER_H
|
||||
#define EIGEN_RANDOMSETTER_H
|
||||
|
||||
/** Represents a std::map
|
||||
*
|
||||
* \see RandomSetter
|
||||
*/
|
||||
template<typename Scalar> struct StdMapTraits
|
||||
{
|
||||
typedef int KeyType;
|
||||
@@ -36,20 +40,40 @@ template<typename Scalar> struct StdMapTraits
|
||||
static void setInvalidKey(Type&, const KeyType&) {}
|
||||
};
|
||||
|
||||
#ifdef _HASH_MAP
|
||||
template<typename Scalar> struct GnuHashMapTraits
|
||||
#ifdef EIGEN_UNORDERED_MAP_SUPPORT
|
||||
/** Represents a std::unordered_map
|
||||
*
|
||||
* To use it you need to both define EIGEN_UNORDERED_MAP_SUPPORT and include the unordered_map header file
|
||||
* yourself making sure that unordered_map is defined in the std namespace.
|
||||
*
|
||||
* For instance, with current version of gcc you can either enable C++0x standard (-std=c++0x) or do:
|
||||
* \code
|
||||
* #include <tr1/unordered_map>
|
||||
* #define EIGEN_UNORDERED_MAP_SUPPORT
|
||||
* namespace std {
|
||||
* using std::tr1::unordered_map;
|
||||
* }
|
||||
* \endcode
|
||||
*
|
||||
* \see RandomSetter
|
||||
*/
|
||||
template<typename Scalar> struct StdUnorderedMapTraits
|
||||
{
|
||||
typedef int KeyType;
|
||||
typedef __gnu_cxx::hash_map<KeyType,Scalar> Type;
|
||||
typedef std::unordered_map<KeyType,Scalar> Type;
|
||||
enum {
|
||||
IsSorted = 0
|
||||
};
|
||||
|
||||
static void setInvalidKey(Type&, const KeyType&) {}
|
||||
};
|
||||
#endif
|
||||
#endif // EIGEN_UNORDERED_MAP_SUPPORT
|
||||
|
||||
#ifdef _DENSE_HASH_MAP_H_
|
||||
/** Represents a google::dense_hash_map
|
||||
*
|
||||
* \see RandomSetter
|
||||
*/
|
||||
template<typename Scalar> struct GoogleDenseHashMapTraits
|
||||
{
|
||||
typedef int KeyType;
|
||||
@@ -64,6 +88,10 @@ template<typename Scalar> struct GoogleDenseHashMapTraits
|
||||
#endif
|
||||
|
||||
#ifdef _SPARSE_HASH_MAP_H_
|
||||
/** Represents a google::sparse_hash_map
|
||||
*
|
||||
* \see RandomSetter
|
||||
*/
|
||||
template<typename Scalar> struct GoogleSparseHashMapTraits
|
||||
{
|
||||
typedef int KeyType;
|
||||
@@ -78,7 +106,19 @@ template<typename Scalar> struct GoogleSparseHashMapTraits
|
||||
|
||||
/** \class RandomSetter
|
||||
*
|
||||
* Typical usage:
|
||||
* \brief The RandomSetter is a wrapper object allowing to set/update a sparse matrix with random access
|
||||
*
|
||||
* \param SparseMatrixType the type of the sparse matrix we are updating
|
||||
* \param MapTraits a traits class representing the map implementation used for the temporary sparse storage.
|
||||
* Its default value depends on the system.
|
||||
* \param OuterPacketBits defines the number of rows (or columns) manage by a single map object
|
||||
* as a power of two exponent.
|
||||
*
|
||||
* This class temporarily represents a sparse matrix object using a generic map implementation allowing for
|
||||
* efficient random access. The conversion from the compressed representation to a hash_map object is performed
|
||||
* in the RandomSetter constructor, while the sparse matrix is updated back at destruction time. This strategy
|
||||
* suggest the use of nested blocks as in this example:
|
||||
*
|
||||
* \code
|
||||
* SparseMatrix<double> m(rows,cols);
|
||||
* {
|
||||
@@ -91,11 +131,28 @@ template<typename Scalar> struct GoogleSparseHashMapTraits
|
||||
* // and m is ready to use.
|
||||
* \endcode
|
||||
*
|
||||
* \note for performance and memory consumption reasons it is highly recommended to use
|
||||
* Google's hash library. To do so you have two options:
|
||||
* - include <google/dense_hash_map> yourself \b before Eigen/Sparse header
|
||||
* Since hash_map objects are not fully sorted, representing a full matrix as a single hash_map would
|
||||
* involve a big and costly sort to update the compressed matrix back. To overcome this issue, a RandomSetter
|
||||
* use multiple hash_map, each representing 2^OuterPacketBits columns or rows according to the storage order.
|
||||
* To reach optimal performance, this value should be adjusted according to the average number of nonzeros
|
||||
* per rows/columns.
|
||||
*
|
||||
* The possible values for the template parameter MapTraits are:
|
||||
* - \b StdMapTraits: corresponds to std::map. (does not perform very well)
|
||||
* - \b GnuHashMapTraits: corresponds to __gnu_cxx::hash_map (available only with GCC)
|
||||
* - \b GoogleDenseHashMapTraits: corresponds to google::dense_hash_map (best efficiency, reasonable memory consumption)
|
||||
* - \b GoogleSparseHashMapTraits: corresponds to google::sparse_hash_map (best memory consumption, relatively good performance)
|
||||
*
|
||||
* The default map implementation depends on the availability, and the preferred order is:
|
||||
* GoogleSparseHashMapTraits, GnuHashMapTraits, and finally StdMapTraits.
|
||||
*
|
||||
* For performance and memory consumption reasons it is highly recommended to use one of
|
||||
* the Google's hash_map implementation. To enable the support for them, you have two options:
|
||||
* - \#include <google/dense_hash_map> yourself \b before Eigen/Sparse header
|
||||
* - define EIGEN_GOOGLEHASH_SUPPORT
|
||||
* In the later case the inclusion of <google/dense_hash_map> is made for you.
|
||||
*
|
||||
* \see http://code.google.com/p/google-sparsehash/
|
||||
*/
|
||||
template<typename SparseMatrixType,
|
||||
template <typename T> class MapTraits =
|
||||
@@ -121,11 +178,19 @@ class RandomSetter
|
||||
enum {
|
||||
SwapStorage = 1 - MapTraits<ScalarWrapper>::IsSorted,
|
||||
TargetRowMajor = (SparseMatrixType::Flags & RowMajorBit) ? 1 : 0,
|
||||
SetterRowMajor = SwapStorage ? 1-TargetRowMajor : TargetRowMajor
|
||||
SetterRowMajor = SwapStorage ? 1-TargetRowMajor : TargetRowMajor,
|
||||
IsUpperTriangular = SparseMatrixType::Flags & UpperTriangularBit,
|
||||
IsLowerTriangular = SparseMatrixType::Flags & LowerTriangularBit
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
/** Constructs a random setter object from the sparse matrix \a target
|
||||
*
|
||||
* Note that the initial value of \a target are imported. If you want to re-set
|
||||
* a sparse matrix from scratch, then you must set it to zero first using the
|
||||
* setZero() function.
|
||||
*/
|
||||
inline RandomSetter(SparseMatrixType& target)
|
||||
: mp_target(&target)
|
||||
{
|
||||
@@ -153,6 +218,7 @@ class RandomSetter
|
||||
(*this)(TargetRowMajor?j:it.index(), TargetRowMajor?it.index():j) = it.value();
|
||||
}
|
||||
|
||||
/** Destructor updating back the sparse matrix target */
|
||||
~RandomSetter()
|
||||
{
|
||||
KeyType keyBitsMask = (1<<m_keyBitsOffset)-1;
|
||||
@@ -226,8 +292,11 @@ class RandomSetter
|
||||
delete[] m_hashmaps;
|
||||
}
|
||||
|
||||
/** \returns a reference to the coefficient at given coordinates \a row, \a col */
|
||||
Scalar& operator() (int row, int col)
|
||||
{
|
||||
ei_assert(((!IsUpperTriangular) || (row<=col)) && "Invalid access to an upper triangular matrix");
|
||||
ei_assert(((!IsLowerTriangular) || (col<=row)) && "Invalid access to an upper triangular matrix");
|
||||
const int outer = SetterRowMajor ? row : col;
|
||||
const int inner = SetterRowMajor ? col : row;
|
||||
const int outerMajor = outer >> OuterPacketBits; // index of the packet/map
|
||||
@@ -236,7 +305,11 @@ class RandomSetter
|
||||
return m_hashmaps[outerMajor][key].value;
|
||||
}
|
||||
|
||||
// might be slow
|
||||
/** \returns the number of non zero coefficients
|
||||
*
|
||||
* \note According to the underlying map/hash_map implementation,
|
||||
* this function might be quite expensive.
|
||||
*/
|
||||
int nonZeros() const
|
||||
{
|
||||
int nz = 0;
|
||||
|
||||
@@ -1,144 +0,0 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
//
|
||||
// Eigen is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 3 of the License, or (at your option) any later version.
|
||||
//
|
||||
// Alternatively, you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of
|
||||
// the License, or (at your option) any later version.
|
||||
//
|
||||
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License and a copy of the GNU General Public License along with
|
||||
// Eigen. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef EIGEN_SPARSE_ARRAY_H
|
||||
#define EIGEN_SPARSE_ARRAY_H
|
||||
|
||||
/** Stores a sparse set of values as a list of values and a list of indices.
|
||||
*
|
||||
*/
|
||||
template<typename Scalar>
|
||||
class SparseArray
|
||||
{
|
||||
public:
|
||||
SparseArray()
|
||||
: m_values(0), m_indices(0), m_size(0), m_allocatedSize(0)
|
||||
{}
|
||||
|
||||
SparseArray(int size)
|
||||
: m_values(0), m_indices(0), m_size(0), m_allocatedSize(0)
|
||||
{
|
||||
resize(size);
|
||||
}
|
||||
|
||||
SparseArray(const SparseArray& other)
|
||||
{
|
||||
*this = other;
|
||||
}
|
||||
|
||||
SparseArray& operator=(const SparseArray& other)
|
||||
{
|
||||
resize(other.size());
|
||||
memcpy(m_values, other.m_values, m_size * sizeof(Scalar));
|
||||
memcpy(m_indices, other.m_indices, m_size * sizeof(int));
|
||||
return *this;
|
||||
}
|
||||
|
||||
void swap(SparseArray& other)
|
||||
{
|
||||
std::swap(m_values, other.m_values);
|
||||
std::swap(m_indices, other.m_indices);
|
||||
std::swap(m_size, other.m_size);
|
||||
std::swap(m_allocatedSize, other.m_allocatedSize);
|
||||
}
|
||||
|
||||
~SparseArray()
|
||||
{
|
||||
delete[] m_values;
|
||||
delete[] m_indices;
|
||||
}
|
||||
|
||||
void reserve(int size)
|
||||
{
|
||||
int newAllocatedSize = m_size + size;
|
||||
if (newAllocatedSize > m_allocatedSize)
|
||||
reallocate(newAllocatedSize);
|
||||
}
|
||||
|
||||
void squeeze()
|
||||
{
|
||||
if (m_allocatedSize>m_size)
|
||||
reallocate(m_size);
|
||||
}
|
||||
|
||||
void resize(int size, int reserveSizeFactor = 0)
|
||||
{
|
||||
if (m_allocatedSize<size)
|
||||
reallocate(size + reserveSizeFactor*size);
|
||||
m_size = size;
|
||||
}
|
||||
|
||||
void append(const Scalar& v, int i)
|
||||
{
|
||||
int id = m_size;
|
||||
resize(m_size+1, 1);
|
||||
m_values[id] = v;
|
||||
m_indices[id] = i;
|
||||
}
|
||||
|
||||
int size() const { return m_size; }
|
||||
void clear() { m_size = 0; }
|
||||
|
||||
Scalar& value(int i) { return m_values[i]; }
|
||||
const Scalar& value(int i) const { return m_values[i]; }
|
||||
|
||||
int& index(int i) { return m_indices[i]; }
|
||||
const int& index(int i) const { return m_indices[i]; }
|
||||
|
||||
static SparseArray Map(int* indices, Scalar* values, int size)
|
||||
{
|
||||
SparseArray res;
|
||||
res.m_indices = indices;
|
||||
res.m_values = values;
|
||||
res.m_allocatedSize = res.m_size = size;
|
||||
return res;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
void reallocate(int size)
|
||||
{
|
||||
Scalar* newValues = new Scalar[size];
|
||||
int* newIndices = new int[size];
|
||||
int copySize = std::min(size, m_size);
|
||||
// copy
|
||||
memcpy(newValues, m_values, copySize * sizeof(Scalar));
|
||||
memcpy(newIndices, m_indices, copySize * sizeof(int));
|
||||
// delete old stuff
|
||||
delete[] m_values;
|
||||
delete[] m_indices;
|
||||
m_values = newValues;
|
||||
m_indices = newIndices;
|
||||
m_allocatedSize = size;
|
||||
}
|
||||
|
||||
protected:
|
||||
Scalar* m_values;
|
||||
int* m_indices;
|
||||
int m_size;
|
||||
int m_allocatedSize;
|
||||
|
||||
};
|
||||
|
||||
#endif // EIGEN_SPARSE_ARRAY_H
|
||||
0
Eigen/src/Sparse/SparseAssign.h
Normal file
0
Eigen/src/Sparse/SparseAssign.h
Normal file
@@ -23,9 +23,110 @@
|
||||
// License and a copy of the GNU General Public License along with
|
||||
// Eigen. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef EIGEN_SPARSEBLOCK_H
|
||||
#define EIGEN_SPARSEBLOCK_H
|
||||
#ifndef EIGEN_SPARSE_BLOCK_H
|
||||
#define EIGEN_SPARSE_BLOCK_H
|
||||
|
||||
template<typename MatrixType>
|
||||
struct ei_traits<SparseInnerVector<MatrixType> >
|
||||
{
|
||||
typedef typename ei_traits<MatrixType>::Scalar Scalar;
|
||||
enum {
|
||||
IsRowMajor = (int(MatrixType::Flags)&RowMajorBit)==RowMajorBit,
|
||||
Flags = MatrixType::Flags,
|
||||
RowsAtCompileTime = IsRowMajor ? 1 : MatrixType::RowsAtCompileTime,
|
||||
ColsAtCompileTime = IsRowMajor ? MatrixType::ColsAtCompileTime : 1,
|
||||
CoeffReadCost = MatrixType::CoeffReadCost
|
||||
};
|
||||
};
|
||||
|
||||
template<typename MatrixType>
|
||||
class SparseInnerVector : ei_no_assignment_operator,
|
||||
public SparseMatrixBase<SparseInnerVector<MatrixType> >
|
||||
{
|
||||
enum {
|
||||
IsRowMajor = ei_traits<SparseInnerVector>::IsRowMajor
|
||||
};
|
||||
public:
|
||||
|
||||
EIGEN_SPARSE_GENERIC_PUBLIC_INTERFACE(SparseInnerVector)
|
||||
class InnerIterator;
|
||||
|
||||
inline SparseInnerVector(const MatrixType& matrix, int outer)
|
||||
: m_matrix(matrix), m_outer(outer)
|
||||
{
|
||||
ei_assert( (outer>=0) && (outer<matrix.outerSize()) );
|
||||
}
|
||||
|
||||
EIGEN_STRONG_INLINE int rows() const { return IsRowMajor ? 1 : m_matrix.rows(); }
|
||||
EIGEN_STRONG_INLINE int cols() const { return IsRowMajor ? m_matrix.cols() : 1; }
|
||||
|
||||
protected:
|
||||
|
||||
const typename MatrixType::Nested m_matrix;
|
||||
int m_outer;
|
||||
|
||||
};
|
||||
|
||||
template<typename MatrixType>
|
||||
class SparseInnerVector<MatrixType>::InnerIterator : public MatrixType::InnerIterator
|
||||
{
|
||||
public:
|
||||
inline InnerIterator(const SparseInnerVector& xpr, int outer=0)
|
||||
: MatrixType::InnerIterator(xpr.m_matrix, xpr.m_outer)
|
||||
{
|
||||
ei_assert(outer==0);
|
||||
}
|
||||
};
|
||||
|
||||
/** \returns the i-th row of the matrix \c *this. For row-major matrix only. */
|
||||
template<typename Derived>
|
||||
SparseInnerVector<Derived> SparseMatrixBase<Derived>::row(int i)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT(IsRowMajor,THIS_METHOD_IS_ONLY_FOR_ROW_MAJOR_MATRICES);
|
||||
return innerVector(i);
|
||||
}
|
||||
|
||||
/** \returns the i-th row of the matrix \c *this. For row-major matrix only.
|
||||
* (read-only version) */
|
||||
template<typename Derived>
|
||||
const SparseInnerVector<Derived> SparseMatrixBase<Derived>::row(int i) const
|
||||
{
|
||||
EIGEN_STATIC_ASSERT(IsRowMajor,THIS_METHOD_IS_ONLY_FOR_ROW_MAJOR_MATRICES);
|
||||
return innerVector(i);
|
||||
}
|
||||
|
||||
/** \returns the i-th column of the matrix \c *this. For column-major matrix only. */
|
||||
template<typename Derived>
|
||||
SparseInnerVector<Derived> SparseMatrixBase<Derived>::col(int i)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT(!IsRowMajor,THIS_METHOD_IS_ONLY_FOR_ROW_MAJOR_MATRICES);
|
||||
return innerVector(i);
|
||||
}
|
||||
|
||||
/** \returns the i-th column of the matrix \c *this. For column-major matrix only.
|
||||
* (read-only version) */
|
||||
template<typename Derived>
|
||||
const SparseInnerVector<Derived> SparseMatrixBase<Derived>::col(int i) const
|
||||
{
|
||||
EIGEN_STATIC_ASSERT(!IsRowMajor,THIS_METHOD_IS_ONLY_FOR_ROW_MAJOR_MATRICES);
|
||||
return innerVector(i);
|
||||
}
|
||||
|
||||
/** \returns the \a outer -th column (resp. row) of the matrix \c *this if \c *this
|
||||
* is col-major (resp. row-major).
|
||||
*/
|
||||
template<typename Derived>
|
||||
SparseInnerVector<Derived> SparseMatrixBase<Derived>::innerVector(int outer)
|
||||
{ return SparseInnerVector<Derived>(derived(), outer); }
|
||||
|
||||
/** \returns the \a outer -th column (resp. row) of the matrix \c *this if \c *this
|
||||
* is col-major (resp. row-major). Read-only.
|
||||
*/
|
||||
template<typename Derived>
|
||||
const SparseInnerVector<Derived> SparseMatrixBase<Derived>::innerVector(int outer) const
|
||||
{ return SparseInnerVector<Derived>(derived(), outer); }
|
||||
|
||||
# if 0
|
||||
template<typename MatrixType, int BlockRows, int BlockCols, int PacketAccess>
|
||||
class Block<MatrixType,BlockRows,BlockCols,PacketAccess,IsSparse>
|
||||
: public SparseMatrixBase<Block<MatrixType,BlockRows,BlockCols,PacketAccess,IsSparse> >
|
||||
@@ -117,6 +218,6 @@ public:
|
||||
const ei_int_if_dynamic<ColsAtCompileTime> m_blockCols;
|
||||
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
#endif // EIGEN_SPARSEBLOCK_H
|
||||
#endif // EIGEN_SPARSE_BLOCK_H
|
||||
|
||||
175
Eigen/src/Sparse/SparseCwise.h
Normal file
175
Eigen/src/Sparse/SparseCwise.h
Normal file
@@ -0,0 +1,175 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// Eigen is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 3 of the License, or (at your option) any later version.
|
||||
//
|
||||
// Alternatively, you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of
|
||||
// the License, or (at your option) any later version.
|
||||
//
|
||||
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License and a copy of the GNU General Public License along with
|
||||
// Eigen. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef EIGEN_SPARSE_CWISE_H
|
||||
#define EIGEN_SPARSE_CWISE_H
|
||||
|
||||
/** \internal
|
||||
* convenient macro to defined the return type of a cwise binary operation */
|
||||
#define EIGEN_SPARSE_CWISE_BINOP_RETURN_TYPE(OP) \
|
||||
CwiseBinaryOp<OP<typename ei_traits<ExpressionType>::Scalar>, ExpressionType, OtherDerived>
|
||||
|
||||
#define EIGEN_SPARSE_CWISE_PRODUCT_RETURN_TYPE \
|
||||
SparseCwiseBinaryOp< \
|
||||
ei_scalar_product_op< \
|
||||
typename ei_scalar_product_traits< \
|
||||
typename ei_traits<ExpressionType>::Scalar, \
|
||||
typename ei_traits<OtherDerived>::Scalar \
|
||||
>::ReturnType \
|
||||
>, \
|
||||
ExpressionType, \
|
||||
OtherDerived \
|
||||
>
|
||||
|
||||
/** \internal
|
||||
* convenient macro to defined the return type of a cwise unary operation */
|
||||
#define EIGEN_SPARSE_CWISE_UNOP_RETURN_TYPE(OP) \
|
||||
SparseCwiseUnaryOp<OP<typename ei_traits<ExpressionType>::Scalar>, ExpressionType>
|
||||
|
||||
/** \internal
|
||||
* convenient macro to defined the return type of a cwise comparison to a scalar */
|
||||
/*#define EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(OP) \
|
||||
CwiseBinaryOp<OP<typename ei_traits<ExpressionType>::Scalar>, ExpressionType, \
|
||||
NestByValue<typename ExpressionType::ConstantReturnType> >*/
|
||||
|
||||
template<typename ExpressionType> class SparseCwise
|
||||
{
|
||||
public:
|
||||
|
||||
typedef typename ei_traits<ExpressionType>::Scalar Scalar;
|
||||
typedef typename ei_meta_if<ei_must_nest_by_value<ExpressionType>::ret,
|
||||
ExpressionType, const ExpressionType&>::ret ExpressionTypeNested;
|
||||
typedef CwiseUnaryOp<ei_scalar_add_op<Scalar>, ExpressionType> ScalarAddReturnType;
|
||||
|
||||
inline SparseCwise(const ExpressionType& matrix) : m_matrix(matrix) {}
|
||||
|
||||
/** \internal */
|
||||
inline const ExpressionType& _expression() const { return m_matrix; }
|
||||
|
||||
template<typename OtherDerived>
|
||||
const EIGEN_SPARSE_CWISE_PRODUCT_RETURN_TYPE
|
||||
operator*(const SparseMatrixBase<OtherDerived> &other) const;
|
||||
|
||||
template<typename OtherDerived>
|
||||
const EIGEN_SPARSE_CWISE_PRODUCT_RETURN_TYPE
|
||||
operator*(const MatrixBase<OtherDerived> &other) const;
|
||||
|
||||
// template<typename OtherDerived>
|
||||
// const EIGEN_SPARSE_CWISE_BINOP_RETURN_TYPE(ei_scalar_quotient_op)
|
||||
// operator/(const SparseMatrixBase<OtherDerived> &other) const;
|
||||
//
|
||||
// template<typename OtherDerived>
|
||||
// const EIGEN_SPARSE_CWISE_BINOP_RETURN_TYPE(ei_scalar_quotient_op)
|
||||
// operator/(const MatrixBase<OtherDerived> &other) const;
|
||||
|
||||
template<typename OtherDerived>
|
||||
const EIGEN_SPARSE_CWISE_BINOP_RETURN_TYPE(ei_scalar_min_op)
|
||||
min(const SparseMatrixBase<OtherDerived> &other) const;
|
||||
|
||||
template<typename OtherDerived>
|
||||
const EIGEN_SPARSE_CWISE_BINOP_RETURN_TYPE(ei_scalar_max_op)
|
||||
max(const SparseMatrixBase<OtherDerived> &other) const;
|
||||
|
||||
const EIGEN_SPARSE_CWISE_UNOP_RETURN_TYPE(ei_scalar_abs_op) abs() const;
|
||||
const EIGEN_SPARSE_CWISE_UNOP_RETURN_TYPE(ei_scalar_abs2_op) abs2() const;
|
||||
// const EIGEN_SPARSE_CWISE_UNOP_RETURN_TYPE(ei_scalar_square_op) square() const;
|
||||
// const EIGEN_SPARSE_CWISE_UNOP_RETURN_TYPE(ei_scalar_cube_op) cube() const;
|
||||
// const EIGEN_SPARSE_CWISE_UNOP_RETURN_TYPE(ei_scalar_inverse_op) inverse() const;
|
||||
// const EIGEN_SPARSE_CWISE_UNOP_RETURN_TYPE(ei_scalar_sqrt_op) sqrt() const;
|
||||
// const EIGEN_SPARSE_CWISE_UNOP_RETURN_TYPE(ei_scalar_exp_op) exp() const;
|
||||
// const EIGEN_SPARSE_CWISE_UNOP_RETURN_TYPE(ei_scalar_log_op) log() const;
|
||||
// const EIGEN_SPARSE_CWISE_UNOP_RETURN_TYPE(ei_scalar_cos_op) cos() const;
|
||||
// const EIGEN_SPARSE_CWISE_UNOP_RETURN_TYPE(ei_scalar_sin_op) sin() const;
|
||||
// const EIGEN_SPARSE_CWISE_UNOP_RETURN_TYPE(ei_scalar_pow_op) pow(const Scalar& exponent) const;
|
||||
|
||||
template<typename OtherDerived>
|
||||
inline ExpressionType& operator*=(const SparseMatrixBase<OtherDerived> &other);
|
||||
|
||||
// template<typename OtherDerived>
|
||||
// inline ExpressionType& operator/=(const SparseMatrixBase<OtherDerived> &other);
|
||||
|
||||
/*
|
||||
template<typename OtherDerived> const EIGEN_CWISE_BINOP_RETURN_TYPE(std::less)
|
||||
operator<(const MatrixBase<OtherDerived>& other) const;
|
||||
|
||||
template<typename OtherDerived> const EIGEN_CWISE_BINOP_RETURN_TYPE(std::less_equal)
|
||||
operator<=(const MatrixBase<OtherDerived>& other) const;
|
||||
|
||||
template<typename OtherDerived> const EIGEN_CWISE_BINOP_RETURN_TYPE(std::greater)
|
||||
operator>(const MatrixBase<OtherDerived>& other) const;
|
||||
|
||||
template<typename OtherDerived> const EIGEN_CWISE_BINOP_RETURN_TYPE(std::greater_equal)
|
||||
operator>=(const MatrixBase<OtherDerived>& other) const;
|
||||
|
||||
template<typename OtherDerived> const EIGEN_CWISE_BINOP_RETURN_TYPE(std::equal_to)
|
||||
operator==(const MatrixBase<OtherDerived>& other) const;
|
||||
|
||||
template<typename OtherDerived> const EIGEN_CWISE_BINOP_RETURN_TYPE(std::not_equal_to)
|
||||
operator!=(const MatrixBase<OtherDerived>& other) const;
|
||||
|
||||
// comparisons to a scalar value
|
||||
const EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(std::less)
|
||||
operator<(Scalar s) const;
|
||||
|
||||
const EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(std::less_equal)
|
||||
operator<=(Scalar s) const;
|
||||
|
||||
const EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(std::greater)
|
||||
operator>(Scalar s) const;
|
||||
|
||||
const EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(std::greater_equal)
|
||||
operator>=(Scalar s) const;
|
||||
|
||||
const EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(std::equal_to)
|
||||
operator==(Scalar s) const;
|
||||
|
||||
const EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(std::not_equal_to)
|
||||
operator!=(Scalar s) const;
|
||||
*/
|
||||
|
||||
// allow to extend SparseCwise outside Eigen
|
||||
#ifdef EIGEN_SPARSE_CWISE_PLUGIN
|
||||
#include EIGEN_SPARSE_CWISE_PLUGIN
|
||||
#endif
|
||||
|
||||
protected:
|
||||
ExpressionTypeNested m_matrix;
|
||||
};
|
||||
|
||||
template<typename Derived>
|
||||
inline const SparseCwise<Derived>
|
||||
SparseMatrixBase<Derived>::cwise() const
|
||||
{
|
||||
return derived();
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
inline SparseCwise<Derived>
|
||||
SparseMatrixBase<Derived>::cwise()
|
||||
{
|
||||
return derived();
|
||||
}
|
||||
|
||||
#endif // EIGEN_SPARSE_CWISE_H
|
||||
436
Eigen/src/Sparse/SparseCwiseBinaryOp.h
Normal file
436
Eigen/src/Sparse/SparseCwiseBinaryOp.h
Normal file
@@ -0,0 +1,436 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
//
|
||||
// Eigen is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 3 of the License, or (at your option) any later version.
|
||||
//
|
||||
// Alternatively, you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of
|
||||
// the License, or (at your option) any later version.
|
||||
//
|
||||
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License and a copy of the GNU General Public License along with
|
||||
// Eigen. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef EIGEN_SPARSE_CWISE_BINARY_OP_H
|
||||
#define EIGEN_SPARSE_CWISE_BINARY_OP_H
|
||||
|
||||
// Here we have to handle 3 cases:
|
||||
// 1 - sparse op dense
|
||||
// 2 - dense op sparse
|
||||
// 3 - sparse op sparse
|
||||
// We also need to implement a 4th iterator for:
|
||||
// 4 - dense op dense
|
||||
// Finally, we also need to distinguish between the product and other operations :
|
||||
// configuration returned mode
|
||||
// 1 - sparse op dense product sparse
|
||||
// generic dense
|
||||
// 2 - dense op sparse product sparse
|
||||
// generic dense
|
||||
// 3 - sparse op sparse product sparse
|
||||
// generic sparse
|
||||
// 4 - dense op dense product dense
|
||||
// generic dense
|
||||
|
||||
template<typename BinaryOp, typename Lhs, typename Rhs>
|
||||
struct ei_traits<SparseCwiseBinaryOp<BinaryOp, Lhs, Rhs> >
|
||||
{
|
||||
typedef typename ei_result_of<
|
||||
BinaryOp(
|
||||
typename Lhs::Scalar,
|
||||
typename Rhs::Scalar
|
||||
)
|
||||
>::type Scalar;
|
||||
typedef typename Lhs::Nested LhsNested;
|
||||
typedef typename Rhs::Nested RhsNested;
|
||||
typedef typename ei_unref<LhsNested>::type _LhsNested;
|
||||
typedef typename ei_unref<RhsNested>::type _RhsNested;
|
||||
enum {
|
||||
LhsCoeffReadCost = _LhsNested::CoeffReadCost,
|
||||
RhsCoeffReadCost = _RhsNested::CoeffReadCost,
|
||||
LhsFlags = _LhsNested::Flags,
|
||||
RhsFlags = _RhsNested::Flags,
|
||||
RowsAtCompileTime = Lhs::RowsAtCompileTime,
|
||||
ColsAtCompileTime = Lhs::ColsAtCompileTime,
|
||||
MaxRowsAtCompileTime = Lhs::MaxRowsAtCompileTime,
|
||||
MaxColsAtCompileTime = Lhs::MaxColsAtCompileTime,
|
||||
Flags = (int(LhsFlags) | int(RhsFlags)) & HereditaryBits,
|
||||
CoeffReadCost = LhsCoeffReadCost + RhsCoeffReadCost + ei_functor_traits<BinaryOp>::Cost
|
||||
};
|
||||
};
|
||||
|
||||
template<typename BinaryOp, typename Lhs, typename Rhs>
|
||||
class SparseCwiseBinaryOp : ei_no_assignment_operator,
|
||||
public SparseMatrixBase<SparseCwiseBinaryOp<BinaryOp, Lhs, Rhs> >
|
||||
{
|
||||
public:
|
||||
|
||||
class InnerIterator;
|
||||
|
||||
EIGEN_SPARSE_GENERIC_PUBLIC_INTERFACE(SparseCwiseBinaryOp)
|
||||
typedef typename ei_traits<SparseCwiseBinaryOp>::LhsNested LhsNested;
|
||||
typedef typename ei_traits<SparseCwiseBinaryOp>::RhsNested RhsNested;
|
||||
typedef typename ei_unref<LhsNested>::type _LhsNested;
|
||||
typedef typename ei_unref<RhsNested>::type _RhsNested;
|
||||
|
||||
EIGEN_STRONG_INLINE SparseCwiseBinaryOp(const Lhs& lhs, const Rhs& rhs, const BinaryOp& func = BinaryOp())
|
||||
: m_lhs(lhs), m_rhs(rhs), m_functor(func)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT((ei_functor_allows_mixing_real_and_complex<BinaryOp>::ret
|
||||
? int(ei_is_same_type<typename Lhs::RealScalar, typename Rhs::RealScalar>::ret)
|
||||
: int(ei_is_same_type<typename Lhs::Scalar, typename Rhs::Scalar>::ret)),
|
||||
YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
|
||||
// require the sizes to match
|
||||
EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(Lhs, Rhs)
|
||||
ei_assert(lhs.rows() == rhs.rows() && lhs.cols() == rhs.cols());
|
||||
}
|
||||
|
||||
EIGEN_STRONG_INLINE int rows() const { return m_lhs.rows(); }
|
||||
EIGEN_STRONG_INLINE int cols() const { return m_lhs.cols(); }
|
||||
|
||||
EIGEN_STRONG_INLINE const _LhsNested& lhs() const { return m_lhs; }
|
||||
EIGEN_STRONG_INLINE const _RhsNested& rhs() const { return m_rhs; }
|
||||
EIGEN_STRONG_INLINE const BinaryOp& functor() const { return m_functor; }
|
||||
|
||||
protected:
|
||||
const LhsNested m_lhs;
|
||||
const RhsNested m_rhs;
|
||||
const BinaryOp m_functor;
|
||||
};
|
||||
|
||||
template<typename BinaryOp, typename Lhs, typename Rhs, typename Derived,
|
||||
int _LhsStorageMode = int(Lhs::Flags) & SparseBit,
|
||||
int _RhsStorageMode = int(Rhs::Flags) & SparseBit>
|
||||
class ei_sparse_cwise_binary_op_inner_iterator_selector;
|
||||
|
||||
template<typename BinaryOp, typename Lhs, typename Rhs>
|
||||
class SparseCwiseBinaryOp<BinaryOp,Lhs,Rhs>::InnerIterator
|
||||
: public ei_sparse_cwise_binary_op_inner_iterator_selector<BinaryOp,Lhs,Rhs, typename SparseCwiseBinaryOp<BinaryOp,Lhs,Rhs>::InnerIterator>
|
||||
{
|
||||
public:
|
||||
typedef ei_sparse_cwise_binary_op_inner_iterator_selector<
|
||||
BinaryOp,Lhs,Rhs, InnerIterator> Base;
|
||||
|
||||
EIGEN_STRONG_INLINE InnerIterator(const SparseCwiseBinaryOp& binOp, int outer)
|
||||
: Base(binOp,outer)
|
||||
{}
|
||||
};
|
||||
|
||||
/***************************************************************************
|
||||
* Implementation of inner-iterators
|
||||
***************************************************************************/
|
||||
|
||||
// template<typename T> struct ei_is_scalar_product { enum { ret = false }; };
|
||||
// template<typename T> struct ei_is_scalar_product<ei_scalar_product_op<T> > { enum { ret = true }; };
|
||||
|
||||
// helper class
|
||||
|
||||
|
||||
// sparse - sparse (generic)
|
||||
template<typename BinaryOp, typename Lhs, typename Rhs, typename Derived>
|
||||
class ei_sparse_cwise_binary_op_inner_iterator_selector<BinaryOp, Lhs, Rhs, Derived, IsSparse, IsSparse>
|
||||
{
|
||||
typedef SparseCwiseBinaryOp<BinaryOp, Lhs, Rhs> CwiseBinaryXpr;
|
||||
typedef typename ei_traits<CwiseBinaryXpr>::Scalar Scalar;
|
||||
typedef typename ei_traits<CwiseBinaryXpr>::_LhsNested _LhsNested;
|
||||
typedef typename ei_traits<CwiseBinaryXpr>::_RhsNested _RhsNested;
|
||||
typedef typename _LhsNested::InnerIterator LhsIterator;
|
||||
typedef typename _RhsNested::InnerIterator RhsIterator;
|
||||
public:
|
||||
|
||||
EIGEN_STRONG_INLINE ei_sparse_cwise_binary_op_inner_iterator_selector(const CwiseBinaryXpr& xpr, int outer)
|
||||
: m_lhsIter(xpr.lhs(),outer), m_rhsIter(xpr.rhs(),outer), m_functor(xpr.functor())
|
||||
{
|
||||
this->operator++();
|
||||
}
|
||||
|
||||
EIGEN_STRONG_INLINE Derived& operator++()
|
||||
{
|
||||
if (m_lhsIter && m_rhsIter && (m_lhsIter.index() == m_rhsIter.index()))
|
||||
{
|
||||
m_id = m_lhsIter.index();
|
||||
m_value = m_functor(m_lhsIter.value(), m_rhsIter.value());
|
||||
++m_lhsIter;
|
||||
++m_rhsIter;
|
||||
}
|
||||
else if (m_lhsIter && (!m_rhsIter || (m_lhsIter.index() < m_rhsIter.index())))
|
||||
{
|
||||
m_id = m_lhsIter.index();
|
||||
m_value = m_functor(m_lhsIter.value(), Scalar(0));
|
||||
++m_lhsIter;
|
||||
}
|
||||
else if (m_rhsIter && (!m_lhsIter || (m_lhsIter.index() > m_rhsIter.index())))
|
||||
{
|
||||
m_id = m_rhsIter.index();
|
||||
m_value = m_functor(Scalar(0), m_rhsIter.value());
|
||||
++m_rhsIter;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_id = -1;
|
||||
}
|
||||
return *static_cast<Derived*>(this);
|
||||
}
|
||||
|
||||
EIGEN_STRONG_INLINE Scalar value() const { return m_value; }
|
||||
|
||||
EIGEN_STRONG_INLINE int index() const { return m_id; }
|
||||
EIGEN_STRONG_INLINE int row() const { return m_lhsIter.row(); }
|
||||
EIGEN_STRONG_INLINE int col() const { return m_lhsIter.col(); }
|
||||
|
||||
EIGEN_STRONG_INLINE operator bool() const { return m_id>=0; }
|
||||
|
||||
protected:
|
||||
LhsIterator m_lhsIter;
|
||||
RhsIterator m_rhsIter;
|
||||
const BinaryOp& m_functor;
|
||||
Scalar m_value;
|
||||
int m_id;
|
||||
};
|
||||
|
||||
// sparse - sparse (product)
|
||||
template<typename T, typename Lhs, typename Rhs, typename Derived>
|
||||
class ei_sparse_cwise_binary_op_inner_iterator_selector<ei_scalar_product_op<T>, Lhs, Rhs, Derived, IsSparse, IsSparse>
|
||||
{
|
||||
typedef ei_scalar_product_op<T> BinaryFunc;
|
||||
typedef SparseCwiseBinaryOp<BinaryFunc, Lhs, Rhs> CwiseBinaryXpr;
|
||||
typedef typename CwiseBinaryXpr::Scalar Scalar;
|
||||
typedef typename ei_traits<CwiseBinaryXpr>::_LhsNested _LhsNested;
|
||||
typedef typename _LhsNested::InnerIterator LhsIterator;
|
||||
typedef typename ei_traits<CwiseBinaryXpr>::_RhsNested _RhsNested;
|
||||
typedef typename _RhsNested::InnerIterator RhsIterator;
|
||||
public:
|
||||
|
||||
EIGEN_STRONG_INLINE ei_sparse_cwise_binary_op_inner_iterator_selector(const CwiseBinaryXpr& xpr, int outer)
|
||||
: m_lhsIter(xpr.lhs(),outer), m_rhsIter(xpr.rhs(),outer), m_functor(xpr.functor())
|
||||
{
|
||||
while (m_lhsIter && m_rhsIter && (m_lhsIter.index() != m_rhsIter.index()))
|
||||
{
|
||||
if (m_lhsIter.index() < m_rhsIter.index())
|
||||
++m_lhsIter;
|
||||
else
|
||||
++m_rhsIter;
|
||||
}
|
||||
}
|
||||
|
||||
EIGEN_STRONG_INLINE Derived& operator++()
|
||||
{
|
||||
++m_lhsIter;
|
||||
++m_rhsIter;
|
||||
while (m_lhsIter && m_rhsIter && (m_lhsIter.index() != m_rhsIter.index()))
|
||||
{
|
||||
if (m_lhsIter.index() < m_rhsIter.index())
|
||||
++m_lhsIter;
|
||||
else
|
||||
++m_rhsIter;
|
||||
}
|
||||
return *static_cast<Derived*>(this);
|
||||
}
|
||||
|
||||
EIGEN_STRONG_INLINE Scalar value() const { return m_functor(m_lhsIter.value(), m_rhsIter.value()); }
|
||||
|
||||
EIGEN_STRONG_INLINE int index() const { return m_lhsIter.index(); }
|
||||
EIGEN_STRONG_INLINE int row() const { return m_lhsIter.row(); }
|
||||
EIGEN_STRONG_INLINE int col() const { return m_lhsIter.col(); }
|
||||
|
||||
EIGEN_STRONG_INLINE operator bool() const { return (m_lhsIter && m_rhsIter); }
|
||||
|
||||
protected:
|
||||
LhsIterator m_lhsIter;
|
||||
RhsIterator m_rhsIter;
|
||||
const BinaryFunc& m_functor;
|
||||
};
|
||||
|
||||
// sparse - dense (product)
|
||||
template<typename T, typename Lhs, typename Rhs, typename Derived>
|
||||
class ei_sparse_cwise_binary_op_inner_iterator_selector<ei_scalar_product_op<T>, Lhs, Rhs, Derived, IsSparse, IsDense>
|
||||
{
|
||||
typedef ei_scalar_product_op<T> BinaryFunc;
|
||||
typedef SparseCwiseBinaryOp<BinaryFunc, Lhs, Rhs> CwiseBinaryXpr;
|
||||
typedef typename CwiseBinaryXpr::Scalar Scalar;
|
||||
typedef typename ei_traits<CwiseBinaryXpr>::_LhsNested _LhsNested;
|
||||
typedef typename _LhsNested::InnerIterator LhsIterator;
|
||||
enum { IsRowMajor = (int(Lhs::Flags)&RowMajorBit)==RowMajorBit };
|
||||
public:
|
||||
|
||||
EIGEN_STRONG_INLINE ei_sparse_cwise_binary_op_inner_iterator_selector(const CwiseBinaryXpr& xpr, int outer)
|
||||
: m_xpr(xpr), m_lhsIter(xpr.lhs(),outer), m_functor(xpr.functor()), m_outer(outer)
|
||||
{}
|
||||
|
||||
EIGEN_STRONG_INLINE Derived& operator++()
|
||||
{
|
||||
++m_lhsIter;
|
||||
return *static_cast<Derived*>(this);
|
||||
}
|
||||
|
||||
EIGEN_STRONG_INLINE Scalar value() const
|
||||
{ return m_functor(m_lhsIter.value(),
|
||||
m_xpr.rhs().coeff(IsRowMajor?m_outer:m_lhsIter.index(),IsRowMajor?m_lhsIter.index():m_outer)); }
|
||||
|
||||
EIGEN_STRONG_INLINE int index() const { return m_lhsIter.index(); }
|
||||
EIGEN_STRONG_INLINE int row() const { return m_lhsIter.row(); }
|
||||
EIGEN_STRONG_INLINE int col() const { return m_lhsIter.col(); }
|
||||
|
||||
EIGEN_STRONG_INLINE operator bool() const { return m_lhsIter; }
|
||||
|
||||
protected:
|
||||
const CwiseBinaryXpr& m_xpr;
|
||||
LhsIterator m_lhsIter;
|
||||
const BinaryFunc& m_functor;
|
||||
const int m_outer;
|
||||
};
|
||||
|
||||
// sparse - dense (product)
|
||||
template<typename T, typename Lhs, typename Rhs, typename Derived>
|
||||
class ei_sparse_cwise_binary_op_inner_iterator_selector<ei_scalar_product_op<T>, Lhs, Rhs, Derived, IsDense, IsSparse>
|
||||
{
|
||||
typedef ei_scalar_product_op<T> BinaryFunc;
|
||||
typedef SparseCwiseBinaryOp<BinaryFunc, Lhs, Rhs> CwiseBinaryXpr;
|
||||
typedef typename CwiseBinaryXpr::Scalar Scalar;
|
||||
typedef typename ei_traits<CwiseBinaryXpr>::_RhsNested _RhsNested;
|
||||
typedef typename _RhsNested::InnerIterator RhsIterator;
|
||||
enum { IsRowMajor = (int(Rhs::Flags)&RowMajorBit)==RowMajorBit };
|
||||
public:
|
||||
|
||||
EIGEN_STRONG_INLINE ei_sparse_cwise_binary_op_inner_iterator_selector(const CwiseBinaryXpr& xpr, int outer)
|
||||
: m_xpr(xpr), m_rhsIter(xpr.rhs(),outer), m_functor(xpr.functor()), m_outer(outer)
|
||||
{}
|
||||
|
||||
EIGEN_STRONG_INLINE Derived& operator++()
|
||||
{
|
||||
++m_rhsIter;
|
||||
return *static_cast<Derived*>(this);
|
||||
}
|
||||
|
||||
EIGEN_STRONG_INLINE Scalar value() const
|
||||
{ return m_functor(m_xpr.lhs().coeff(IsRowMajor?m_outer:m_rhsIter.index(),IsRowMajor?m_rhsIter.index():m_outer), m_rhsIter.value()); }
|
||||
|
||||
EIGEN_STRONG_INLINE int index() const { return m_rhsIter.index(); }
|
||||
EIGEN_STRONG_INLINE int row() const { return m_rhsIter.row(); }
|
||||
EIGEN_STRONG_INLINE int col() const { return m_rhsIter.col(); }
|
||||
|
||||
EIGEN_STRONG_INLINE operator bool() const { return m_rhsIter; }
|
||||
|
||||
protected:
|
||||
const CwiseBinaryXpr& m_xpr;
|
||||
RhsIterator m_rhsIter;
|
||||
const BinaryFunc& m_functor;
|
||||
const int m_outer;
|
||||
};
|
||||
|
||||
|
||||
template<typename Derived>
|
||||
template<typename OtherDerived>
|
||||
EIGEN_STRONG_INLINE const SparseCwiseBinaryOp<ei_scalar_difference_op<typename ei_traits<Derived>::Scalar>,
|
||||
Derived, OtherDerived>
|
||||
SparseMatrixBase<Derived>::operator-(const SparseMatrixBase<OtherDerived> &other) const
|
||||
{
|
||||
return SparseCwiseBinaryOp<ei_scalar_difference_op<Scalar>,
|
||||
Derived, OtherDerived>(derived(), other.derived());
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
template<typename OtherDerived>
|
||||
EIGEN_STRONG_INLINE Derived &
|
||||
SparseMatrixBase<Derived>::operator-=(const SparseMatrixBase<OtherDerived> &other)
|
||||
{
|
||||
return *this = derived() - other.derived();
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
template<typename OtherDerived>
|
||||
EIGEN_STRONG_INLINE const SparseCwiseBinaryOp<ei_scalar_sum_op<typename ei_traits<Derived>::Scalar>, Derived, OtherDerived>
|
||||
SparseMatrixBase<Derived>::operator+(const SparseMatrixBase<OtherDerived> &other) const
|
||||
{
|
||||
return SparseCwiseBinaryOp<ei_scalar_sum_op<Scalar>, Derived, OtherDerived>(derived(), other.derived());
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
template<typename OtherDerived>
|
||||
EIGEN_STRONG_INLINE Derived &
|
||||
SparseMatrixBase<Derived>::operator+=(const SparseMatrixBase<OtherDerived>& other)
|
||||
{
|
||||
return *this = derived() + other.derived();
|
||||
}
|
||||
|
||||
template<typename ExpressionType>
|
||||
template<typename OtherDerived>
|
||||
EIGEN_STRONG_INLINE const EIGEN_SPARSE_CWISE_PRODUCT_RETURN_TYPE
|
||||
SparseCwise<ExpressionType>::operator*(const SparseMatrixBase<OtherDerived> &other) const
|
||||
{
|
||||
return EIGEN_SPARSE_CWISE_PRODUCT_RETURN_TYPE(_expression(), other.derived());
|
||||
}
|
||||
|
||||
template<typename ExpressionType>
|
||||
template<typename OtherDerived>
|
||||
EIGEN_STRONG_INLINE const EIGEN_SPARSE_CWISE_PRODUCT_RETURN_TYPE
|
||||
SparseCwise<ExpressionType>::operator*(const MatrixBase<OtherDerived> &other) const
|
||||
{
|
||||
return EIGEN_SPARSE_CWISE_PRODUCT_RETURN_TYPE(_expression(), other.derived());
|
||||
}
|
||||
|
||||
// template<typename ExpressionType>
|
||||
// template<typename OtherDerived>
|
||||
// EIGEN_STRONG_INLINE const EIGEN_SPARSE_CWISE_BINOP_RETURN_TYPE(ei_scalar_quotient_op)
|
||||
// SparseCwise<ExpressionType>::operator/(const SparseMatrixBase<OtherDerived> &other) const
|
||||
// {
|
||||
// return EIGEN_SPARSE_CWISE_BINOP_RETURN_TYPE(ei_scalar_quotient_op)(_expression(), other.derived());
|
||||
// }
|
||||
//
|
||||
// template<typename ExpressionType>
|
||||
// template<typename OtherDerived>
|
||||
// EIGEN_STRONG_INLINE const EIGEN_SPARSE_CWISE_BINOP_RETURN_TYPE(ei_scalar_quotient_op)
|
||||
// SparseCwise<ExpressionType>::operator/(const MatrixBase<OtherDerived> &other) const
|
||||
// {
|
||||
// return EIGEN_SPARSE_CWISE_BINOP_RETURN_TYPE(ei_scalar_quotient_op)(_expression(), other.derived());
|
||||
// }
|
||||
|
||||
template<typename ExpressionType>
|
||||
template<typename OtherDerived>
|
||||
inline ExpressionType& SparseCwise<ExpressionType>::operator*=(const SparseMatrixBase<OtherDerived> &other)
|
||||
{
|
||||
return m_matrix.const_cast_derived() = _expression() * other.derived();
|
||||
}
|
||||
|
||||
// template<typename ExpressionType>
|
||||
// template<typename OtherDerived>
|
||||
// inline ExpressionType& SparseCwise<ExpressionType>::operator/=(const SparseMatrixBase<OtherDerived> &other)
|
||||
// {
|
||||
// return m_matrix.const_cast_derived() = *this / other;
|
||||
// }
|
||||
|
||||
template<typename ExpressionType>
|
||||
template<typename OtherDerived>
|
||||
EIGEN_STRONG_INLINE const EIGEN_SPARSE_CWISE_BINOP_RETURN_TYPE(ei_scalar_min_op)
|
||||
SparseCwise<ExpressionType>::min(const SparseMatrixBase<OtherDerived> &other) const
|
||||
{
|
||||
return EIGEN_SPARSE_CWISE_BINOP_RETURN_TYPE(ei_scalar_min_op)(_expression(), other.derived());
|
||||
}
|
||||
|
||||
template<typename ExpressionType>
|
||||
template<typename OtherDerived>
|
||||
EIGEN_STRONG_INLINE const EIGEN_SPARSE_CWISE_BINOP_RETURN_TYPE(ei_scalar_max_op)
|
||||
SparseCwise<ExpressionType>::max(const SparseMatrixBase<OtherDerived> &other) const
|
||||
{
|
||||
return EIGEN_SPARSE_CWISE_BINOP_RETURN_TYPE(ei_scalar_max_op)(_expression(), other.derived());
|
||||
}
|
||||
|
||||
// template<typename Derived>
|
||||
// template<typename CustomBinaryOp, typename OtherDerived>
|
||||
// EIGEN_STRONG_INLINE const CwiseBinaryOp<CustomBinaryOp, Derived, OtherDerived>
|
||||
// SparseMatrixBase<Derived>::binaryExpr(const SparseMatrixBase<OtherDerived> &other, const CustomBinaryOp& func) const
|
||||
// {
|
||||
// return CwiseBinaryOp<CustomBinaryOp, Derived, OtherDerived>(derived(), other.derived(), func);
|
||||
// }
|
||||
|
||||
#endif // EIGEN_SPARSE_CWISE_BINARY_OP_H
|
||||
183
Eigen/src/Sparse/SparseCwiseUnaryOp.h
Normal file
183
Eigen/src/Sparse/SparseCwiseUnaryOp.h
Normal file
@@ -0,0 +1,183 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
//
|
||||
// Eigen is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 3 of the License, or (at your option) any later version.
|
||||
//
|
||||
// Alternatively, you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of
|
||||
// the License, or (at your option) any later version.
|
||||
//
|
||||
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License and a copy of the GNU General Public License along with
|
||||
// Eigen. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef EIGEN_SPARSE_CWISE_UNARY_OP_H
|
||||
#define EIGEN_SPARSE_CWISE_UNARY_OP_H
|
||||
|
||||
template<typename UnaryOp, typename MatrixType>
|
||||
struct ei_traits<SparseCwiseUnaryOp<UnaryOp, MatrixType> > : ei_traits<MatrixType>
|
||||
{
|
||||
typedef typename ei_result_of<
|
||||
UnaryOp(typename MatrixType::Scalar)
|
||||
>::type Scalar;
|
||||
typedef typename MatrixType::Nested MatrixTypeNested;
|
||||
typedef typename ei_unref<MatrixTypeNested>::type _MatrixTypeNested;
|
||||
enum {
|
||||
CoeffReadCost = _MatrixTypeNested::CoeffReadCost + ei_functor_traits<UnaryOp>::Cost
|
||||
};
|
||||
};
|
||||
|
||||
template<typename UnaryOp, typename MatrixType>
|
||||
class SparseCwiseUnaryOp : ei_no_assignment_operator,
|
||||
public SparseMatrixBase<SparseCwiseUnaryOp<UnaryOp, MatrixType> >
|
||||
{
|
||||
public:
|
||||
|
||||
class InnerIterator;
|
||||
// typedef typename ei_unref<LhsNested>::type _LhsNested;
|
||||
|
||||
EIGEN_SPARSE_GENERIC_PUBLIC_INTERFACE(SparseCwiseUnaryOp)
|
||||
|
||||
inline SparseCwiseUnaryOp(const MatrixType& mat, const UnaryOp& func = UnaryOp())
|
||||
: m_matrix(mat), m_functor(func) {}
|
||||
|
||||
EIGEN_STRONG_INLINE int rows() const { return m_matrix.rows(); }
|
||||
EIGEN_STRONG_INLINE int cols() const { return m_matrix.cols(); }
|
||||
|
||||
// EIGEN_STRONG_INLINE const typename MatrixType::Nested& _matrix() const { return m_matrix; }
|
||||
// EIGEN_STRONG_INLINE const UnaryOp& _functor() const { return m_functor; }
|
||||
|
||||
protected:
|
||||
const typename MatrixType::Nested m_matrix;
|
||||
const UnaryOp m_functor;
|
||||
};
|
||||
|
||||
|
||||
template<typename UnaryOp, typename MatrixType>
|
||||
class SparseCwiseUnaryOp<UnaryOp,MatrixType>::InnerIterator
|
||||
{
|
||||
typedef typename SparseCwiseUnaryOp::Scalar Scalar;
|
||||
typedef typename ei_traits<SparseCwiseUnaryOp>::_MatrixTypeNested _MatrixTypeNested;
|
||||
typedef typename _MatrixTypeNested::InnerIterator MatrixTypeIterator;
|
||||
public:
|
||||
|
||||
EIGEN_STRONG_INLINE InnerIterator(const SparseCwiseUnaryOp& unaryOp, int outer)
|
||||
: m_iter(unaryOp.m_matrix,outer), m_functor(unaryOp.m_functor)
|
||||
{}
|
||||
|
||||
EIGEN_STRONG_INLINE InnerIterator& operator++()
|
||||
{ ++m_iter; return *this; }
|
||||
|
||||
EIGEN_STRONG_INLINE Scalar value() const { return m_functor(m_iter.value()); }
|
||||
|
||||
EIGEN_STRONG_INLINE int index() const { return m_iter.index(); }
|
||||
EIGEN_STRONG_INLINE int row() const { return m_iter.row(); }
|
||||
EIGEN_STRONG_INLINE int col() const { return m_iter.col(); }
|
||||
|
||||
EIGEN_STRONG_INLINE operator bool() const { return m_iter; }
|
||||
|
||||
protected:
|
||||
MatrixTypeIterator m_iter;
|
||||
const UnaryOp& m_functor;
|
||||
};
|
||||
|
||||
template<typename Derived>
|
||||
template<typename CustomUnaryOp>
|
||||
EIGEN_STRONG_INLINE const SparseCwiseUnaryOp<CustomUnaryOp, Derived>
|
||||
SparseMatrixBase<Derived>::unaryExpr(const CustomUnaryOp& func) const
|
||||
{
|
||||
return SparseCwiseUnaryOp<CustomUnaryOp, Derived>(derived(), func);
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
EIGEN_STRONG_INLINE const SparseCwiseUnaryOp<ei_scalar_opposite_op<typename ei_traits<Derived>::Scalar>,Derived>
|
||||
SparseMatrixBase<Derived>::operator-() const
|
||||
{
|
||||
return derived();
|
||||
}
|
||||
|
||||
template<typename ExpressionType>
|
||||
EIGEN_STRONG_INLINE const EIGEN_SPARSE_CWISE_UNOP_RETURN_TYPE(ei_scalar_abs_op)
|
||||
SparseCwise<ExpressionType>::abs() const
|
||||
{
|
||||
return _expression();
|
||||
}
|
||||
|
||||
template<typename ExpressionType>
|
||||
EIGEN_STRONG_INLINE const EIGEN_SPARSE_CWISE_UNOP_RETURN_TYPE(ei_scalar_abs2_op)
|
||||
SparseCwise<ExpressionType>::abs2() const
|
||||
{
|
||||
return _expression();
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
EIGEN_STRONG_INLINE typename SparseMatrixBase<Derived>::ConjugateReturnType
|
||||
SparseMatrixBase<Derived>::conjugate() const
|
||||
{
|
||||
return ConjugateReturnType(derived());
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
EIGEN_STRONG_INLINE const typename SparseMatrixBase<Derived>::RealReturnType
|
||||
SparseMatrixBase<Derived>::real() const { return derived(); }
|
||||
|
||||
template<typename Derived>
|
||||
EIGEN_STRONG_INLINE const typename SparseMatrixBase<Derived>::ImagReturnType
|
||||
SparseMatrixBase<Derived>::imag() const { return derived(); }
|
||||
|
||||
template<typename Derived>
|
||||
template<typename NewType>
|
||||
EIGEN_STRONG_INLINE const SparseCwiseUnaryOp<ei_scalar_cast_op<typename ei_traits<Derived>::Scalar, NewType>, Derived>
|
||||
SparseMatrixBase<Derived>::cast() const
|
||||
{
|
||||
return derived();
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
EIGEN_STRONG_INLINE const SparseCwiseUnaryOp<ei_scalar_multiple_op<typename ei_traits<Derived>::Scalar>, Derived>
|
||||
SparseMatrixBase<Derived>::operator*(const Scalar& scalar) const
|
||||
{
|
||||
return SparseCwiseUnaryOp<ei_scalar_multiple_op<Scalar>, Derived>
|
||||
(derived(), ei_scalar_multiple_op<Scalar>(scalar));
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
EIGEN_STRONG_INLINE const SparseCwiseUnaryOp<ei_scalar_quotient1_op<typename ei_traits<Derived>::Scalar>, Derived>
|
||||
SparseMatrixBase<Derived>::operator/(const Scalar& scalar) const
|
||||
{
|
||||
return SparseCwiseUnaryOp<ei_scalar_quotient1_op<Scalar>, Derived>
|
||||
(derived(), ei_scalar_quotient1_op<Scalar>(scalar));
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
EIGEN_STRONG_INLINE Derived&
|
||||
SparseMatrixBase<Derived>::operator*=(const Scalar& other)
|
||||
{
|
||||
for (int j=0; j<outerSize(); ++j)
|
||||
for (typename Derived::InnerIterator i(derived(),j); i; ++i)
|
||||
i.valueRef() *= other;
|
||||
return derived();
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
EIGEN_STRONG_INLINE Derived&
|
||||
SparseMatrixBase<Derived>::operator/=(const Scalar& other)
|
||||
{
|
||||
for (int j=0; j<outerSize(); ++j)
|
||||
for (typename Derived::InnerIterator i(derived(),j); i; ++i)
|
||||
i.valueRef() /= other;
|
||||
return derived();
|
||||
}
|
||||
|
||||
#endif // EIGEN_SPARSE_CWISE_UNARY_OP_H
|
||||
97
Eigen/src/Sparse/SparseDot.h
Normal file
97
Eigen/src/Sparse/SparseDot.h
Normal file
@@ -0,0 +1,97 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
//
|
||||
// Eigen is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 3 of the License, or (at your option) any later version.
|
||||
//
|
||||
// Alternatively, you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of
|
||||
// the License, or (at your option) any later version.
|
||||
//
|
||||
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License and a copy of the GNU General Public License along with
|
||||
// Eigen. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef EIGEN_SPARSE_DOT_H
|
||||
#define EIGEN_SPARSE_DOT_H
|
||||
|
||||
template<typename Derived>
|
||||
template<typename OtherDerived>
|
||||
typename ei_traits<Derived>::Scalar
|
||||
SparseMatrixBase<Derived>::dot(const MatrixBase<OtherDerived>& other) const
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(OtherDerived)
|
||||
EIGEN_STATIC_ASSERT_SAME_VECTOR_SIZE(Derived,OtherDerived)
|
||||
EIGEN_STATIC_ASSERT((ei_is_same_type<Scalar, typename OtherDerived::Scalar>::ret),
|
||||
YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
|
||||
|
||||
ei_assert(size() == other.size());
|
||||
ei_assert(other.size()>0 && "you are using a non initialized vector");
|
||||
|
||||
typename Derived::InnerIterator i(derived(),0);
|
||||
Scalar res = 0;
|
||||
while (i)
|
||||
{
|
||||
res += i.value() * ei_conj(other.coeff(i.index()));
|
||||
++i;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
template<typename OtherDerived>
|
||||
typename ei_traits<Derived>::Scalar
|
||||
SparseMatrixBase<Derived>::dot(const SparseMatrixBase<OtherDerived>& other) const
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(OtherDerived)
|
||||
EIGEN_STATIC_ASSERT_SAME_VECTOR_SIZE(Derived,OtherDerived)
|
||||
EIGEN_STATIC_ASSERT((ei_is_same_type<Scalar, typename OtherDerived::Scalar>::ret),
|
||||
YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
|
||||
|
||||
ei_assert(size() == other.size());
|
||||
|
||||
typename Derived::InnerIterator i(derived(),0);
|
||||
typename OtherDerived::InnerIterator j(other.derived(),0);
|
||||
Scalar res = 0;
|
||||
while (i && j)
|
||||
{
|
||||
if (i.index()==j.index())
|
||||
{
|
||||
res += i.value() * ei_conj(j.value());
|
||||
++i; ++j;
|
||||
}
|
||||
else if (i.index()<j.index())
|
||||
++i;
|
||||
else
|
||||
++j;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
inline typename NumTraits<typename ei_traits<Derived>::Scalar>::Real
|
||||
SparseMatrixBase<Derived>::squaredNorm() const
|
||||
{
|
||||
return ei_real((*this).cwise().abs2().sum());
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
inline typename NumTraits<typename ei_traits<Derived>::Scalar>::Real
|
||||
SparseMatrixBase<Derived>::norm() const
|
||||
{
|
||||
return ei_sqrt(squaredNorm());
|
||||
}
|
||||
|
||||
#endif // EIGEN_SPARSE_DOT_H
|
||||
97
Eigen/src/Sparse/SparseFlagged.h
Normal file
97
Eigen/src/Sparse/SparseFlagged.h
Normal file
@@ -0,0 +1,97 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
//
|
||||
// Eigen is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 3 of the License, or (at your option) any later version.
|
||||
//
|
||||
// Alternatively, you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of
|
||||
// the License, or (at your option) any later version.
|
||||
//
|
||||
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License and a copy of the GNU General Public License along with
|
||||
// Eigen. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef EIGEN_SPARSE_FLAGGED_H
|
||||
#define EIGEN_SPARSE_FLAGGED_H
|
||||
|
||||
template<typename ExpressionType, unsigned int Added, unsigned int Removed>
|
||||
struct ei_traits<SparseFlagged<ExpressionType, Added, Removed> > : ei_traits<ExpressionType>
|
||||
{
|
||||
enum { Flags = (ExpressionType::Flags | Added) & ~Removed };
|
||||
};
|
||||
|
||||
template<typename ExpressionType, unsigned int Added, unsigned int Removed> class SparseFlagged
|
||||
: public SparseMatrixBase<SparseFlagged<ExpressionType, Added, Removed> >
|
||||
{
|
||||
public:
|
||||
|
||||
EIGEN_SPARSE_GENERIC_PUBLIC_INTERFACE(SparseFlagged)
|
||||
class InnerIterator;
|
||||
class ReverseInnerIterator;
|
||||
|
||||
typedef typename ei_meta_if<ei_must_nest_by_value<ExpressionType>::ret,
|
||||
ExpressionType, const ExpressionType&>::ret ExpressionTypeNested;
|
||||
|
||||
inline SparseFlagged(const ExpressionType& matrix) : m_matrix(matrix) {}
|
||||
|
||||
inline int rows() const { return m_matrix.rows(); }
|
||||
inline int cols() const { return m_matrix.cols(); }
|
||||
|
||||
// FIXME should be keep them ?
|
||||
inline Scalar& coeffRef(int row, int col)
|
||||
{ return m_matrix.const_cast_derived().coeffRef(col, row); }
|
||||
|
||||
inline const Scalar coeff(int row, int col) const
|
||||
{ return m_matrix.coeff(col, row); }
|
||||
|
||||
inline const Scalar coeff(int index) const
|
||||
{ return m_matrix.coeff(index); }
|
||||
|
||||
inline Scalar& coeffRef(int index)
|
||||
{ return m_matrix.const_cast_derived().coeffRef(index); }
|
||||
|
||||
protected:
|
||||
ExpressionTypeNested m_matrix;
|
||||
};
|
||||
|
||||
template<typename ExpressionType, unsigned int Added, unsigned int Removed>
|
||||
class SparseFlagged<ExpressionType,Added,Removed>::InnerIterator : public ExpressionType::InnerIterator
|
||||
{
|
||||
public:
|
||||
|
||||
EIGEN_STRONG_INLINE InnerIterator(const SparseFlagged& xpr, int outer)
|
||||
: ExpressionType::InnerIterator(xpr.m_matrix, outer)
|
||||
{}
|
||||
};
|
||||
|
||||
template<typename ExpressionType, unsigned int Added, unsigned int Removed>
|
||||
class SparseFlagged<ExpressionType,Added,Removed>::ReverseInnerIterator : public ExpressionType::ReverseInnerIterator
|
||||
{
|
||||
public:
|
||||
|
||||
EIGEN_STRONG_INLINE ReverseInnerIterator(const SparseFlagged& xpr, int outer)
|
||||
: ExpressionType::ReverseInnerIterator(xpr.m_matrix, outer)
|
||||
{}
|
||||
};
|
||||
|
||||
template<typename Derived>
|
||||
template<unsigned int Added>
|
||||
inline const SparseFlagged<Derived, Added, 0>
|
||||
SparseMatrixBase<Derived>::marked() const
|
||||
{
|
||||
return derived();
|
||||
}
|
||||
|
||||
#endif // EIGEN_SPARSE_FLAGGED_H
|
||||
41
Eigen/src/Sparse/SparseFuzzy.h
Normal file
41
Eigen/src/Sparse/SparseFuzzy.h
Normal file
@@ -0,0 +1,41 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
//
|
||||
// Eigen is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 3 of the License, or (at your option) any later version.
|
||||
//
|
||||
// Alternatively, you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of
|
||||
// the License, or (at your option) any later version.
|
||||
//
|
||||
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License and a copy of the GNU General Public License along with
|
||||
// Eigen. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef EIGEN_SPARSE_FUZZY_H
|
||||
#define EIGEN_SPARSE_FUZZY_H
|
||||
|
||||
// template<typename Derived>
|
||||
// template<typename OtherDerived>
|
||||
// bool SparseMatrixBase<Derived>::isApprox(
|
||||
// const OtherDerived& other,
|
||||
// typename NumTraits<Scalar>::Real prec
|
||||
// ) const
|
||||
// {
|
||||
// const typename ei_nested<Derived,2>::type nested(derived());
|
||||
// const typename ei_nested<OtherDerived,2>::type otherNested(other.derived());
|
||||
// return (nested - otherNested).cwise().abs2().sum()
|
||||
// <= prec * prec * std::min(nested.cwise().abs2().sum(), otherNested.cwise().abs2().sum());
|
||||
// }
|
||||
|
||||
#endif // EIGEN_SPARSE_FUZZY_H
|
||||
@@ -45,7 +45,7 @@ struct ei_traits<SparseMatrix<_Scalar, _Flags> >
|
||||
MaxColsAtCompileTime = Dynamic,
|
||||
Flags = SparseBit | _Flags,
|
||||
CoeffReadCost = NumTraits<Scalar>::ReadCost,
|
||||
SupportedAccessPatterns = FullyCoherentAccessPattern
|
||||
SupportedAccessPatterns = InnerRandomAccessPattern
|
||||
};
|
||||
};
|
||||
|
||||
@@ -56,27 +56,30 @@ class SparseMatrix
|
||||
: public SparseMatrixBase<SparseMatrix<_Scalar, _Flags> >
|
||||
{
|
||||
public:
|
||||
EIGEN_GENERIC_PUBLIC_INTERFACE(SparseMatrix)
|
||||
EIGEN_SPARSE_GENERIC_PUBLIC_INTERFACE(SparseMatrix)
|
||||
EIGEN_SPARSE_INHERIT_ASSIGNMENT_OPERATOR(SparseMatrix, +=)
|
||||
EIGEN_SPARSE_INHERIT_ASSIGNMENT_OPERATOR(SparseMatrix, -=)
|
||||
// FIXME: why are these operator already alvailable ???
|
||||
// EIGEN_SPARSE_INHERIT_SCALAR_ASSIGNMENT_OPERATOR(SparseMatrix, *=)
|
||||
// EIGEN_SPARSE_INHERIT_SCALAR_ASSIGNMENT_OPERATOR(SparseMatrix, /=)
|
||||
|
||||
typedef MappedSparseMatrix<Scalar,Flags> Map;
|
||||
|
||||
protected:
|
||||
public:
|
||||
|
||||
typedef SparseMatrixBase<SparseMatrix> SparseBase;
|
||||
enum {
|
||||
RowMajor = SparseBase::RowMajor
|
||||
};
|
||||
typedef SparseMatrix<Scalar,(Flags&~RowMajorBit)|(RowMajor?RowMajorBit:0)> TransposedSparseMatrix;
|
||||
enum { IsRowMajor = Base::IsRowMajor };
|
||||
typedef SparseMatrix<Scalar,(Flags&~RowMajorBit)|(IsRowMajor?RowMajorBit:0)> TransposedSparseMatrix;
|
||||
|
||||
int m_outerSize;
|
||||
int m_innerSize;
|
||||
int* m_outerIndex;
|
||||
SparseArray<Scalar> m_data;
|
||||
|
||||
CompressedStorage<Scalar> m_data;
|
||||
|
||||
public:
|
||||
|
||||
inline int rows() const { return RowMajor ? m_outerSize : m_innerSize; }
|
||||
inline int cols() const { return RowMajor ? m_innerSize : m_outerSize; }
|
||||
inline int rows() const { return IsRowMajor ? m_outerSize : m_innerSize; }
|
||||
inline int cols() const { return IsRowMajor ? m_innerSize : m_outerSize; }
|
||||
|
||||
inline int innerSize() const { return m_innerSize; }
|
||||
inline int outerSize() const { return m_outerSize; }
|
||||
inline int innerNonZeros(int j) const { return m_outerIndex[j+1]-m_outerIndex[j]; }
|
||||
@@ -92,35 +95,22 @@ class SparseMatrix
|
||||
|
||||
inline Scalar coeff(int row, int col) const
|
||||
{
|
||||
const int outer = RowMajor ? row : col;
|
||||
const int inner = RowMajor ? col : row;
|
||||
|
||||
int start = m_outerIndex[outer];
|
||||
int end = m_outerIndex[outer+1];
|
||||
if (start==end)
|
||||
return Scalar(0);
|
||||
else if (end>0 && inner==m_data.index(end-1))
|
||||
return m_data.value(end-1);
|
||||
// ^^ optimization: let's first check if it is the last coefficient
|
||||
// (very common in high level algorithms)
|
||||
|
||||
const int* r = std::lower_bound(&m_data.index(start),&m_data.index(end-1),inner);
|
||||
const int id = r-&m_data.index(0);
|
||||
return ((*r==inner) && (id<end)) ? m_data.value(id) : Scalar(0);
|
||||
const int outer = IsRowMajor ? row : col;
|
||||
const int inner = IsRowMajor ? col : row;
|
||||
return m_data.atInRange(m_outerIndex[outer], m_outerIndex[outer+1], inner);
|
||||
}
|
||||
|
||||
inline Scalar& coeffRef(int row, int col)
|
||||
{
|
||||
const int outer = RowMajor ? row : col;
|
||||
const int inner = RowMajor ? col : row;
|
||||
const int outer = IsRowMajor ? row : col;
|
||||
const int inner = IsRowMajor ? col : row;
|
||||
|
||||
int start = m_outerIndex[outer];
|
||||
int end = m_outerIndex[outer+1];
|
||||
ei_assert(end>=start && "you probably called coeffRef on a non finalized matrix");
|
||||
ei_assert(end>start && "coeffRef cannot be called on a zero coefficient");
|
||||
int* r = std::lower_bound(&m_data.index(start),&m_data.index(end),inner);
|
||||
const int id = r-&m_data.index(0);
|
||||
ei_assert((*r==inner) && (id<end) && "coeffRef cannot be called on a zero coefficient");
|
||||
const int id = m_data.searchLowerIndex(start,end-1,inner);
|
||||
ei_assert((id<end) && (m_data.index(id)==inner) && "coeffRef cannot be called on a zero coefficient");
|
||||
return m_data.value(id);
|
||||
}
|
||||
|
||||
@@ -157,8 +147,8 @@ class SparseMatrix
|
||||
*/
|
||||
inline Scalar& fill(int row, int col)
|
||||
{
|
||||
const int outer = RowMajor ? row : col;
|
||||
const int inner = RowMajor ? col : row;
|
||||
const int outer = IsRowMajor ? row : col;
|
||||
const int inner = IsRowMajor ? col : row;
|
||||
|
||||
if (m_outerIndex[outer+1]==0)
|
||||
{
|
||||
@@ -171,7 +161,7 @@ class SparseMatrix
|
||||
}
|
||||
m_outerIndex[outer+1] = m_outerIndex[outer];
|
||||
}
|
||||
assert(m_outerIndex[outer+1] == m_data.size());
|
||||
assert(size_t(m_outerIndex[outer+1]) == m_data.size());
|
||||
int id = m_outerIndex[outer+1];
|
||||
++m_outerIndex[outer+1];
|
||||
|
||||
@@ -183,9 +173,8 @@ class SparseMatrix
|
||||
*/
|
||||
inline Scalar& fillrand(int row, int col)
|
||||
{
|
||||
const int outer = RowMajor ? row : col;
|
||||
const int inner = RowMajor ? col : row;
|
||||
|
||||
const int outer = IsRowMajor ? row : col;
|
||||
const int inner = IsRowMajor ? col : row;
|
||||
if (m_outerIndex[outer+1]==0)
|
||||
{
|
||||
// we start a new inner vector
|
||||
@@ -198,31 +187,40 @@ class SparseMatrix
|
||||
}
|
||||
m_outerIndex[outer+1] = m_outerIndex[outer];
|
||||
}
|
||||
// std::cerr << this << " " << outer << " " << inner << " - " << m_outerIndex[outer] << " " << m_outerIndex[outer+1] << "\n";
|
||||
assert(m_outerIndex[outer+1] == m_data.size() && "invalid outer index");
|
||||
int startId = m_outerIndex[outer];
|
||||
int id = m_outerIndex[outer+1]-1;
|
||||
assert(size_t(m_outerIndex[outer+1]) == m_data.size() && "invalid outer index");
|
||||
size_t startId = m_outerIndex[outer];
|
||||
// FIXME let's make sure sizeof(long int) == sizeof(size_t)
|
||||
size_t id = m_outerIndex[outer+1];
|
||||
++m_outerIndex[outer+1];
|
||||
m_data.resize(id+2);
|
||||
|
||||
while ( (id >= startId) && (m_data.index(id) > inner) )
|
||||
|
||||
float reallocRatio = 1;
|
||||
if (m_data.allocatedSize()<id+1)
|
||||
{
|
||||
m_data.index(id+1) = m_data.index(id);
|
||||
m_data.value(id+1) = m_data.value(id);
|
||||
// we need to reallocate the data, to reduce multiple reallocations
|
||||
// we use a smart resize algorithm based on the current filling ratio
|
||||
// we use float to avoid overflows
|
||||
float nnzEstimate = float(m_outerIndex[outer])*float(m_outerSize)/float(outer);
|
||||
reallocRatio = (nnzEstimate-float(m_data.size()))/float(m_data.size());
|
||||
// let's bounds the realloc ratio to
|
||||
// 1) reduce multiple minor realloc when the matrix is almost filled
|
||||
// 2) avoid to allocate too much memory when the matrix is almost empty
|
||||
reallocRatio = std::min(std::max(reallocRatio,1.5f),8.f);
|
||||
}
|
||||
m_data.resize(id+1,reallocRatio);
|
||||
|
||||
while ( (id > startId) && (m_data.index(id-1) > inner) )
|
||||
{
|
||||
m_data.index(id) = m_data.index(id-1);
|
||||
m_data.value(id) = m_data.value(id-1);
|
||||
--id;
|
||||
}
|
||||
m_data.index(id+1) = inner;
|
||||
//return (m_data.value(id+1) = 0);
|
||||
m_data.value(id+1) = 0;
|
||||
// std::cerr << m_outerIndex[outer] << " " << m_outerIndex[outer+1] << "\n";
|
||||
return m_data.value(id+1);
|
||||
|
||||
m_data.index(id) = inner;
|
||||
return (m_data.value(id) = 0);
|
||||
}
|
||||
|
||||
// inline void
|
||||
|
||||
inline void endFill()
|
||||
{
|
||||
// std::cerr << this << " endFill\n";
|
||||
int size = m_data.size();
|
||||
int i = m_outerSize;
|
||||
// find the last filled column
|
||||
@@ -235,18 +233,41 @@ class SparseMatrix
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
void prune(Scalar reference, RealScalar epsilon = precision<RealScalar>())
|
||||
{
|
||||
int k = 0;
|
||||
for (int j=0; j<m_outerSize; ++j)
|
||||
{
|
||||
int previousStart = m_outerIndex[j];
|
||||
m_outerIndex[j] = k;
|
||||
int end = m_outerIndex[j+1];
|
||||
for (int i=previousStart; i<end; ++i)
|
||||
{
|
||||
if (!ei_isMuchSmallerThan(m_data.value(i), reference, epsilon))
|
||||
{
|
||||
m_data.value(k) = m_data.value(i);
|
||||
m_data.index(k) = m_data.index(i);
|
||||
++k;
|
||||
}
|
||||
}
|
||||
}
|
||||
m_outerIndex[m_outerSize] = k;
|
||||
m_data.resize(k,0);
|
||||
}
|
||||
|
||||
void resize(int rows, int cols)
|
||||
{
|
||||
// std::cerr << this << " resize " << rows << "x" << cols << "\n";
|
||||
const int outerSize = RowMajor ? rows : cols;
|
||||
m_innerSize = RowMajor ? cols : rows;
|
||||
const int outerSize = IsRowMajor ? rows : cols;
|
||||
m_innerSize = IsRowMajor ? cols : rows;
|
||||
m_data.clear();
|
||||
if (m_outerSize != outerSize)
|
||||
{
|
||||
delete[] m_outerIndex;
|
||||
m_outerIndex = new int [outerSize+1];
|
||||
m_outerSize = outerSize;
|
||||
memset(m_outerIndex, 0, (m_outerSize+1)*sizeof(int));
|
||||
}
|
||||
}
|
||||
void resizeNonZeros(int size)
|
||||
@@ -267,14 +288,14 @@ class SparseMatrix
|
||||
}
|
||||
|
||||
template<typename OtherDerived>
|
||||
inline SparseMatrix(const MatrixBase<OtherDerived>& other)
|
||||
inline SparseMatrix(const SparseMatrixBase<OtherDerived>& other)
|
||||
: m_outerSize(0), m_innerSize(0), m_outerIndex(0)
|
||||
{
|
||||
*this = other.derived();
|
||||
}
|
||||
|
||||
inline SparseMatrix(const SparseMatrix& other)
|
||||
: m_outerSize(0), m_innerSize(0), m_outerIndex(0)
|
||||
: Base(), m_outerSize(0), m_innerSize(0), m_outerIndex(0)
|
||||
{
|
||||
*this = other.derived();
|
||||
}
|
||||
@@ -305,7 +326,7 @@ class SparseMatrix
|
||||
}
|
||||
|
||||
template<typename OtherDerived>
|
||||
inline SparseMatrix& operator=(const MatrixBase<OtherDerived>& other)
|
||||
inline SparseMatrix& operator=(const SparseMatrixBase<OtherDerived>& other)
|
||||
{
|
||||
const bool needToTranspose = (Flags & RowMajorBit) != (OtherDerived::Flags & RowMajorBit);
|
||||
if (needToTranspose)
|
||||
@@ -314,9 +335,10 @@ class SparseMatrix
|
||||
// 1 - compute the number of coeffs per dest inner vector
|
||||
// 2 - do the actual copy/eval
|
||||
// Since each coeff of the rhs has to be evaluated twice, let's evauluate it if needed
|
||||
typedef typename ei_nested<OtherDerived,2>::type OtherCopy;
|
||||
OtherCopy otherCopy(other.derived());
|
||||
//typedef typename ei_nested<OtherDerived,2>::type OtherCopy;
|
||||
typedef typename ei_eval<OtherDerived>::type OtherCopy;
|
||||
typedef typename ei_cleantype<OtherCopy>::type _OtherCopy;
|
||||
OtherCopy otherCopy(other.derived());
|
||||
|
||||
resize(other.rows(), other.cols());
|
||||
Eigen::Map<VectorXi>(m_outerIndex,outerSize()).setZero();
|
||||
@@ -379,21 +401,6 @@ class SparseMatrix
|
||||
return s;
|
||||
}
|
||||
|
||||
#ifdef EIGEN_TAUCS_SUPPORT
|
||||
static SparseMatrix Map(taucs_ccs_matrix& taucsMatrix);
|
||||
taucs_ccs_matrix asTaucsMatrix();
|
||||
#endif
|
||||
|
||||
#ifdef EIGEN_CHOLMOD_SUPPORT
|
||||
static SparseMatrix Map(cholmod_sparse& cholmodMatrix);
|
||||
cholmod_sparse asCholmodMatrix();
|
||||
#endif
|
||||
|
||||
#ifdef EIGEN_SUPERLU_SUPPORT
|
||||
static SparseMatrix Map(SluMatrix& sluMatrix);
|
||||
SluMatrix asSluMatrix();
|
||||
#endif
|
||||
|
||||
/** Destructor */
|
||||
inline ~SparseMatrix()
|
||||
{
|
||||
@@ -406,25 +413,29 @@ class SparseMatrix<Scalar,_Flags>::InnerIterator
|
||||
{
|
||||
public:
|
||||
InnerIterator(const SparseMatrix& mat, int outer)
|
||||
: m_matrix(mat), m_id(mat.m_outerIndex[outer]), m_start(m_id), m_end(mat.m_outerIndex[outer+1])
|
||||
: m_matrix(mat), m_outer(outer), m_id(mat.m_outerIndex[outer]), m_start(m_id), m_end(mat.m_outerIndex[outer+1])
|
||||
{}
|
||||
|
||||
template<unsigned int Added, unsigned int Removed>
|
||||
InnerIterator(const Flagged<SparseMatrix,Added,Removed>& mat, int outer)
|
||||
: m_matrix(mat._expression()), m_id(m_matrix.m_outerIndex[outer]),
|
||||
: m_matrix(mat._expression()), m_outer(outer), m_id(m_matrix.m_outerIndex[outer]),
|
||||
m_start(m_id), m_end(m_matrix.m_outerIndex[outer+1])
|
||||
{}
|
||||
|
||||
inline InnerIterator& operator++() { m_id++; return *this; }
|
||||
|
||||
inline Scalar value() const { return m_matrix.m_data.value(m_id); }
|
||||
inline Scalar& valueRef() { return const_cast<Scalar&>(m_matrix.m_data.value(m_id)); }
|
||||
|
||||
inline int index() const { return m_matrix.m_data.index(m_id); }
|
||||
inline int row() const { return IsRowMajor ? m_outer : index(); }
|
||||
inline int col() const { return IsRowMajor ? index() : m_outer; }
|
||||
|
||||
inline operator bool() const { return (m_id < m_end) && (m_id>=m_start); }
|
||||
|
||||
protected:
|
||||
const SparseMatrix& m_matrix;
|
||||
const int m_outer;
|
||||
int m_id;
|
||||
const int m_start;
|
||||
const int m_end;
|
||||
|
||||
@@ -25,47 +25,138 @@
|
||||
#ifndef EIGEN_SPARSEMATRIXBASE_H
|
||||
#define EIGEN_SPARSEMATRIXBASE_H
|
||||
|
||||
template<typename Derived>
|
||||
class SparseMatrixBase : public MatrixBase<Derived>
|
||||
template<typename Derived> class SparseMatrixBase
|
||||
{
|
||||
public:
|
||||
|
||||
typedef MatrixBase<Derived> Base;
|
||||
typedef typename Base::Scalar Scalar;
|
||||
typedef typename Base::RealScalar RealScalar;
|
||||
typedef typename ei_traits<Derived>::Scalar Scalar;
|
||||
// typedef typename Derived::InnerIterator InnerIterator;
|
||||
|
||||
enum {
|
||||
Flags = Base::Flags,
|
||||
RowMajor = ei_traits<Derived>::Flags&RowMajorBit ? 1 : 0
|
||||
|
||||
RowsAtCompileTime = ei_traits<Derived>::RowsAtCompileTime,
|
||||
/**< The number of rows at compile-time. This is just a copy of the value provided
|
||||
* by the \a Derived type. If a value is not known at compile-time,
|
||||
* it is set to the \a Dynamic constant.
|
||||
* \sa MatrixBase::rows(), MatrixBase::cols(), ColsAtCompileTime, SizeAtCompileTime */
|
||||
|
||||
ColsAtCompileTime = ei_traits<Derived>::ColsAtCompileTime,
|
||||
/**< The number of columns at compile-time. This is just a copy of the value provided
|
||||
* by the \a Derived type. If a value is not known at compile-time,
|
||||
* it is set to the \a Dynamic constant.
|
||||
* \sa MatrixBase::rows(), MatrixBase::cols(), RowsAtCompileTime, SizeAtCompileTime */
|
||||
|
||||
|
||||
SizeAtCompileTime = (ei_size_at_compile_time<ei_traits<Derived>::RowsAtCompileTime,
|
||||
ei_traits<Derived>::ColsAtCompileTime>::ret),
|
||||
/**< This is equal to the number of coefficients, i.e. the number of
|
||||
* rows times the number of columns, or to \a Dynamic if this is not
|
||||
* known at compile-time. \sa RowsAtCompileTime, ColsAtCompileTime */
|
||||
|
||||
MaxRowsAtCompileTime = RowsAtCompileTime,
|
||||
MaxColsAtCompileTime = ColsAtCompileTime,
|
||||
|
||||
MaxSizeAtCompileTime = (ei_size_at_compile_time<MaxRowsAtCompileTime,
|
||||
MaxColsAtCompileTime>::ret),
|
||||
|
||||
IsVectorAtCompileTime = RowsAtCompileTime == 1 || ColsAtCompileTime == 1,
|
||||
/**< This is set to true if either the number of rows or the number of
|
||||
* columns is known at compile-time to be equal to 1. Indeed, in that case,
|
||||
* we are dealing with a column-vector (if there is only one column) or with
|
||||
* a row-vector (if there is only one row). */
|
||||
|
||||
Flags = ei_traits<Derived>::Flags,
|
||||
/**< This stores expression \ref flags flags which may or may not be inherited by new expressions
|
||||
* constructed from this one. See the \ref flags "list of flags".
|
||||
*/
|
||||
|
||||
CoeffReadCost = ei_traits<Derived>::CoeffReadCost,
|
||||
/**< This is a rough measure of how expensive it is to read one coefficient from
|
||||
* this expression.
|
||||
*/
|
||||
|
||||
IsRowMajor = Flags&RowMajorBit ? 1 : 0
|
||||
};
|
||||
|
||||
/** \internal the return type of MatrixBase::conjugate() */
|
||||
typedef typename ei_meta_if<NumTraits<Scalar>::IsComplex,
|
||||
const SparseCwiseUnaryOp<ei_scalar_conjugate_op<Scalar>, Derived>,
|
||||
const Derived&
|
||||
>::ret ConjugateReturnType;
|
||||
/** \internal the return type of MatrixBase::real() */
|
||||
typedef CwiseUnaryOp<ei_scalar_real_op<Scalar>, Derived> RealReturnType;
|
||||
/** \internal the return type of MatrixBase::imag() */
|
||||
typedef CwiseUnaryOp<ei_scalar_imag_op<Scalar>, Derived> ImagReturnType;
|
||||
/** \internal the return type of MatrixBase::adjoint() */
|
||||
typedef SparseTranspose</*NestByValue<*/typename ei_cleantype<ConjugateReturnType>::type> /*>*/
|
||||
AdjointReturnType;
|
||||
|
||||
#ifndef EIGEN_PARSED_BY_DOXYGEN
|
||||
/** This is the "real scalar" type; if the \a Scalar type is already real numbers
|
||||
* (e.g. int, float or double) then \a RealScalar is just the same as \a Scalar. If
|
||||
* \a Scalar is \a std::complex<T> then RealScalar is \a T.
|
||||
*
|
||||
* \sa class NumTraits
|
||||
*/
|
||||
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||
|
||||
/** type of the equivalent square matrix */
|
||||
typedef Matrix<Scalar,EIGEN_ENUM_MAX(RowsAtCompileTime,ColsAtCompileTime),
|
||||
EIGEN_ENUM_MAX(RowsAtCompileTime,ColsAtCompileTime)> SquareMatrixType;
|
||||
|
||||
inline const Derived& derived() const { return *static_cast<const Derived*>(this); }
|
||||
inline Derived& derived() { return *static_cast<Derived*>(this); }
|
||||
inline Derived& const_cast_derived() const
|
||||
{ return *static_cast<Derived*>(const_cast<SparseMatrixBase*>(this)); }
|
||||
#endif // not EIGEN_PARSED_BY_DOXYGEN
|
||||
|
||||
SparseMatrixBase()
|
||||
: m_isRValue(false)
|
||||
{}
|
||||
/** \returns the number of rows. \sa cols(), RowsAtCompileTime */
|
||||
inline int rows() const { return derived().rows(); }
|
||||
/** \returns the number of columns. \sa rows(), ColsAtCompileTime*/
|
||||
inline int cols() const { return derived().cols(); }
|
||||
/** \returns the number of coefficients, which is \a rows()*cols().
|
||||
* \sa rows(), cols(), SizeAtCompileTime. */
|
||||
inline int size() const { return rows() * cols(); }
|
||||
/** \returns the number of nonzero coefficients which is in practice the number
|
||||
* of stored coefficients. */
|
||||
inline int nonZeros() const { return derived().nonZeros(); }
|
||||
/** \returns true if either the number of rows or the number of columns is equal to 1.
|
||||
* In other words, this function returns
|
||||
* \code rows()==1 || cols()==1 \endcode
|
||||
* \sa rows(), cols(), IsVectorAtCompileTime. */
|
||||
inline bool isVector() const { return rows()==1 || cols()==1; }
|
||||
/** \returns the size of the storage major dimension,
|
||||
* i.e., the number of columns for a columns major matrix, and the number of rows otherwise */
|
||||
int outerSize() const { return (int(Flags)&RowMajorBit) ? this->rows() : this->cols(); }
|
||||
/** \returns the size of the inner dimension according to the storage order,
|
||||
* i.e., the number of rows for a columns major matrix, and the number of cols otherwise */
|
||||
int innerSize() const { return (int(Flags)&RowMajorBit) ? this->cols() : this->rows(); }
|
||||
|
||||
bool isRValue() const { return m_isRValue; }
|
||||
Derived& markAsRValue() { m_isRValue = true; return derived(); }
|
||||
|
||||
SparseMatrixBase() : m_isRValue(false) { /* TODO check flags */ }
|
||||
|
||||
inline Derived& operator=(const Derived& other)
|
||||
{
|
||||
// std::cout << "Derived& operator=(const Derived& other)\n";
|
||||
if (other.isRValue())
|
||||
derived().swap(other.const_cast_derived());
|
||||
else
|
||||
// if (other.isRValue())
|
||||
// derived().swap(other.const_cast_derived());
|
||||
// else
|
||||
this->operator=<Derived>(other);
|
||||
return derived();
|
||||
}
|
||||
|
||||
|
||||
template<typename OtherDerived>
|
||||
inline Derived& operator=(const MatrixBase<OtherDerived>& other)
|
||||
inline void assignGeneric(const OtherDerived& other)
|
||||
{
|
||||
// std::cout << "Derived& operator=(const MatrixBase<OtherDerived>& other)\n";
|
||||
//const bool transpose = (Flags & RowMajorBit) != (OtherDerived::Flags & RowMajorBit);
|
||||
ei_assert((!((Flags & RowMajorBit) != (OtherDerived::Flags & RowMajorBit))) && "the transpose operation is supposed to be handled in SparseMatrix::operator=");
|
||||
ei_assert(( ((ei_traits<Derived>::SupportedAccessPatterns&OuterRandomAccessPattern)==OuterRandomAccessPattern) ||
|
||||
(!((Flags & RowMajorBit) != (OtherDerived::Flags & RowMajorBit)))) &&
|
||||
"the transpose operation is supposed to be handled in SparseMatrix::operator=");
|
||||
|
||||
const int outerSize = other.outerSize();
|
||||
//typedef typename ei_meta_if<transpose, LinkedVectorMatrix<Scalar,Flags&RowMajorBit>, Derived>::ret TempType;
|
||||
// thanks to shallow copies, we always eval to a tempary
|
||||
@@ -87,9 +178,9 @@ class SparseMatrixBase : public MatrixBase<Derived>
|
||||
temp.endFill();
|
||||
|
||||
derived() = temp.markAsRValue();
|
||||
return derived();
|
||||
}
|
||||
|
||||
|
||||
template<typename OtherDerived>
|
||||
inline Derived& operator=(const SparseMatrixBase<OtherDerived>& other)
|
||||
{
|
||||
@@ -110,7 +201,7 @@ class SparseMatrixBase : public MatrixBase<Derived>
|
||||
Scalar v = it.value();
|
||||
if (v!=Scalar(0))
|
||||
{
|
||||
if (RowMajor) derived().fill(j,it.index()) = v;
|
||||
if (IsRowMajor) derived().fill(j,it.index()) = v;
|
||||
else derived().fill(it.index(),j) = v;
|
||||
}
|
||||
}
|
||||
@@ -118,12 +209,14 @@ class SparseMatrixBase : public MatrixBase<Derived>
|
||||
derived().endFill();
|
||||
}
|
||||
else
|
||||
this->operator=<OtherDerived>(static_cast<const MatrixBase<OtherDerived>&>(other));
|
||||
{
|
||||
assignGeneric(other.derived());
|
||||
}
|
||||
return derived();
|
||||
}
|
||||
|
||||
template<typename Lhs, typename Rhs>
|
||||
inline Derived& operator=(const Product<Lhs,Rhs,SparseProduct>& product);
|
||||
inline Derived& operator=(const SparseProduct<Lhs,Rhs,SparseTimeSparseProduct>& product);
|
||||
|
||||
friend std::ostream & operator << (std::ostream & s, const SparseMatrixBase& m)
|
||||
{
|
||||
@@ -167,6 +260,306 @@ class SparseMatrixBase : public MatrixBase<Derived>
|
||||
return s;
|
||||
}
|
||||
|
||||
const SparseCwiseUnaryOp<ei_scalar_opposite_op<typename ei_traits<Derived>::Scalar>,Derived> operator-() const;
|
||||
|
||||
template<typename OtherDerived>
|
||||
const SparseCwiseBinaryOp<ei_scalar_sum_op<typename ei_traits<Derived>::Scalar>, Derived, OtherDerived>
|
||||
operator+(const SparseMatrixBase<OtherDerived> &other) const;
|
||||
|
||||
template<typename OtherDerived>
|
||||
const SparseCwiseBinaryOp<ei_scalar_difference_op<typename ei_traits<Derived>::Scalar>, Derived, OtherDerived>
|
||||
operator-(const SparseMatrixBase<OtherDerived> &other) const;
|
||||
|
||||
template<typename OtherDerived>
|
||||
Derived& operator+=(const SparseMatrixBase<OtherDerived>& other);
|
||||
template<typename OtherDerived>
|
||||
Derived& operator-=(const SparseMatrixBase<OtherDerived>& other);
|
||||
|
||||
// template<typename Lhs,typename Rhs>
|
||||
// Derived& operator+=(const Flagged<Product<Lhs,Rhs,CacheFriendlyProduct>, 0, EvalBeforeNestingBit | EvalBeforeAssigningBit>& other);
|
||||
|
||||
Derived& operator*=(const Scalar& other);
|
||||
Derived& operator/=(const Scalar& other);
|
||||
|
||||
const SparseCwiseUnaryOp<ei_scalar_multiple_op<typename ei_traits<Derived>::Scalar>, Derived>
|
||||
operator*(const Scalar& scalar) const;
|
||||
const SparseCwiseUnaryOp<ei_scalar_quotient1_op<typename ei_traits<Derived>::Scalar>, Derived>
|
||||
operator/(const Scalar& scalar) const;
|
||||
|
||||
inline friend const SparseCwiseUnaryOp<ei_scalar_multiple_op<typename ei_traits<Derived>::Scalar>, Derived>
|
||||
operator*(const Scalar& scalar, const SparseMatrixBase& matrix)
|
||||
{ return matrix*scalar; }
|
||||
|
||||
|
||||
template<typename OtherDerived>
|
||||
const typename SparseProductReturnType<Derived,OtherDerived>::Type
|
||||
operator*(const SparseMatrixBase<OtherDerived> &other) const;
|
||||
|
||||
// dense * sparse (return a dense object)
|
||||
template<typename OtherDerived> friend
|
||||
const typename SparseProductReturnType<OtherDerived,Derived>::Type
|
||||
operator*(const MatrixBase<OtherDerived>& lhs, const Derived& rhs)
|
||||
{ return typename SparseProductReturnType<OtherDerived,Derived>::Type(lhs.derived(),rhs); }
|
||||
|
||||
template<typename OtherDerived>
|
||||
const typename SparseProductReturnType<Derived,OtherDerived>::Type
|
||||
operator*(const MatrixBase<OtherDerived> &other) const;
|
||||
|
||||
template<typename OtherDerived>
|
||||
Derived& operator*=(const SparseMatrixBase<OtherDerived>& other);
|
||||
|
||||
template<typename OtherDerived>
|
||||
typename ei_plain_matrix_type_column_major<OtherDerived>::type
|
||||
solveTriangular(const MatrixBase<OtherDerived>& other) const;
|
||||
|
||||
template<typename OtherDerived>
|
||||
void solveTriangularInPlace(MatrixBase<OtherDerived>& other) const;
|
||||
|
||||
template<typename OtherDerived> Scalar dot(const MatrixBase<OtherDerived>& other) const;
|
||||
template<typename OtherDerived> Scalar dot(const SparseMatrixBase<OtherDerived>& other) const;
|
||||
RealScalar squaredNorm() const;
|
||||
RealScalar norm() const;
|
||||
// const PlainMatrixType normalized() const;
|
||||
// void normalize();
|
||||
|
||||
SparseTranspose<Derived> transpose() { return derived(); }
|
||||
const SparseTranspose<Derived> transpose() const { return derived(); }
|
||||
// void transposeInPlace();
|
||||
const AdjointReturnType adjoint() const { return conjugate()/*.nestByValue()*/; }
|
||||
|
||||
SparseInnerVector<Derived> row(int i);
|
||||
const SparseInnerVector<Derived> row(int i) const;
|
||||
SparseInnerVector<Derived> col(int j);
|
||||
const SparseInnerVector<Derived> col(int j) const;
|
||||
SparseInnerVector<Derived> innerVector(int outer);
|
||||
const SparseInnerVector<Derived> innerVector(int outer) const;
|
||||
|
||||
// RowXpr row(int i);
|
||||
// const RowXpr row(int i) const;
|
||||
|
||||
// ColXpr col(int i);
|
||||
// const ColXpr col(int i) const;
|
||||
|
||||
// typename BlockReturnType<Derived>::Type block(int startRow, int startCol, int blockRows, int blockCols);
|
||||
// const typename BlockReturnType<Derived>::Type
|
||||
// block(int startRow, int startCol, int blockRows, int blockCols) const;
|
||||
//
|
||||
// typename BlockReturnType<Derived>::SubVectorType segment(int start, int size);
|
||||
// const typename BlockReturnType<Derived>::SubVectorType segment(int start, int size) const;
|
||||
//
|
||||
// typename BlockReturnType<Derived,Dynamic>::SubVectorType start(int size);
|
||||
// const typename BlockReturnType<Derived,Dynamic>::SubVectorType start(int size) const;
|
||||
//
|
||||
// typename BlockReturnType<Derived,Dynamic>::SubVectorType end(int size);
|
||||
// const typename BlockReturnType<Derived,Dynamic>::SubVectorType end(int size) const;
|
||||
//
|
||||
// typename BlockReturnType<Derived>::Type corner(CornerType type, int cRows, int cCols);
|
||||
// const typename BlockReturnType<Derived>::Type corner(CornerType type, int cRows, int cCols) const;
|
||||
//
|
||||
// template<int BlockRows, int BlockCols>
|
||||
// typename BlockReturnType<Derived, BlockRows, BlockCols>::Type block(int startRow, int startCol);
|
||||
// template<int BlockRows, int BlockCols>
|
||||
// const typename BlockReturnType<Derived, BlockRows, BlockCols>::Type block(int startRow, int startCol) const;
|
||||
|
||||
// template<int CRows, int CCols>
|
||||
// typename BlockReturnType<Derived, CRows, CCols>::Type corner(CornerType type);
|
||||
// template<int CRows, int CCols>
|
||||
// const typename BlockReturnType<Derived, CRows, CCols>::Type corner(CornerType type) const;
|
||||
|
||||
// template<int Size> typename BlockReturnType<Derived,Size>::SubVectorType start(void);
|
||||
// template<int Size> const typename BlockReturnType<Derived,Size>::SubVectorType start() const;
|
||||
|
||||
// template<int Size> typename BlockReturnType<Derived,Size>::SubVectorType end();
|
||||
// template<int Size> const typename BlockReturnType<Derived,Size>::SubVectorType end() const;
|
||||
|
||||
// template<int Size> typename BlockReturnType<Derived,Size>::SubVectorType segment(int start);
|
||||
// template<int Size> const typename BlockReturnType<Derived,Size>::SubVectorType segment(int start) const;
|
||||
|
||||
// DiagonalCoeffs<Derived> diagonal();
|
||||
// const DiagonalCoeffs<Derived> diagonal() const;
|
||||
|
||||
// template<unsigned int Mode> Part<Derived, Mode> part();
|
||||
// template<unsigned int Mode> const Part<Derived, Mode> part() const;
|
||||
|
||||
|
||||
// static const ConstantReturnType Constant(int rows, int cols, const Scalar& value);
|
||||
// static const ConstantReturnType Constant(int size, const Scalar& value);
|
||||
// static const ConstantReturnType Constant(const Scalar& value);
|
||||
|
||||
// template<typename CustomNullaryOp>
|
||||
// static const CwiseNullaryOp<CustomNullaryOp, Derived> NullaryExpr(int rows, int cols, const CustomNullaryOp& func);
|
||||
// template<typename CustomNullaryOp>
|
||||
// static const CwiseNullaryOp<CustomNullaryOp, Derived> NullaryExpr(int size, const CustomNullaryOp& func);
|
||||
// template<typename CustomNullaryOp>
|
||||
// static const CwiseNullaryOp<CustomNullaryOp, Derived> NullaryExpr(const CustomNullaryOp& func);
|
||||
|
||||
// static const ConstantReturnType Zero(int rows, int cols);
|
||||
// static const ConstantReturnType Zero(int size);
|
||||
// static const ConstantReturnType Zero();
|
||||
// static const ConstantReturnType Ones(int rows, int cols);
|
||||
// static const ConstantReturnType Ones(int size);
|
||||
// static const ConstantReturnType Ones();
|
||||
// static const IdentityReturnType Identity();
|
||||
// static const IdentityReturnType Identity(int rows, int cols);
|
||||
// static const BasisReturnType Unit(int size, int i);
|
||||
// static const BasisReturnType Unit(int i);
|
||||
// static const BasisReturnType UnitX();
|
||||
// static const BasisReturnType UnitY();
|
||||
// static const BasisReturnType UnitZ();
|
||||
// static const BasisReturnType UnitW();
|
||||
|
||||
// const DiagonalMatrix<Derived> asDiagonal() const;
|
||||
|
||||
// Derived& setConstant(const Scalar& value);
|
||||
// Derived& setZero();
|
||||
// Derived& setOnes();
|
||||
// Derived& setRandom();
|
||||
// Derived& setIdentity();
|
||||
|
||||
Matrix<Scalar,RowsAtCompileTime,ColsAtCompileTime> toDense() const
|
||||
{
|
||||
Matrix<Scalar,RowsAtCompileTime,ColsAtCompileTime> res(rows(),cols());
|
||||
res.setZero();
|
||||
for (int j=0; j<outerSize(); ++j)
|
||||
{
|
||||
for (typename Derived::InnerIterator i(derived(),j); i; ++i)
|
||||
if(IsRowMajor)
|
||||
res.coeffRef(j,i.index()) = i.value();
|
||||
else
|
||||
res.coeffRef(i.index(),j) = i.value();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
template<typename OtherDerived>
|
||||
bool isApprox(const SparseMatrixBase<OtherDerived>& other,
|
||||
RealScalar prec = precision<Scalar>()) const
|
||||
{ return toDense().isApprox(other.toDense(),prec); }
|
||||
|
||||
template<typename OtherDerived>
|
||||
bool isApprox(const MatrixBase<OtherDerived>& other,
|
||||
RealScalar prec = precision<Scalar>()) const
|
||||
{ return toDense().isApprox(other,prec); }
|
||||
// bool isMuchSmallerThan(const RealScalar& other,
|
||||
// RealScalar prec = precision<Scalar>()) const;
|
||||
// template<typename OtherDerived>
|
||||
// bool isMuchSmallerThan(const MatrixBase<OtherDerived>& other,
|
||||
// RealScalar prec = precision<Scalar>()) const;
|
||||
|
||||
// bool isApproxToConstant(const Scalar& value, RealScalar prec = precision<Scalar>()) const;
|
||||
// bool isZero(RealScalar prec = precision<Scalar>()) const;
|
||||
// bool isOnes(RealScalar prec = precision<Scalar>()) const;
|
||||
// bool isIdentity(RealScalar prec = precision<Scalar>()) const;
|
||||
// bool isDiagonal(RealScalar prec = precision<Scalar>()) const;
|
||||
|
||||
// bool isUpperTriangular(RealScalar prec = precision<Scalar>()) const;
|
||||
// bool isLowerTriangular(RealScalar prec = precision<Scalar>()) const;
|
||||
|
||||
// template<typename OtherDerived>
|
||||
// bool isOrthogonal(const MatrixBase<OtherDerived>& other,
|
||||
// RealScalar prec = precision<Scalar>()) const;
|
||||
// bool isUnitary(RealScalar prec = precision<Scalar>()) const;
|
||||
|
||||
// template<typename OtherDerived>
|
||||
// inline bool operator==(const MatrixBase<OtherDerived>& other) const
|
||||
// { return (cwise() == other).all(); }
|
||||
|
||||
// template<typename OtherDerived>
|
||||
// inline bool operator!=(const MatrixBase<OtherDerived>& other) const
|
||||
// { return (cwise() != other).any(); }
|
||||
|
||||
|
||||
template<typename NewType>
|
||||
const SparseCwiseUnaryOp<ei_scalar_cast_op<typename ei_traits<Derived>::Scalar, NewType>, Derived> cast() const;
|
||||
|
||||
/** \returns the matrix or vector obtained by evaluating this expression.
|
||||
*
|
||||
* Notice that in the case of a plain matrix or vector (not an expression) this function just returns
|
||||
* a const reference, in order to avoid a useless copy.
|
||||
*/
|
||||
EIGEN_STRONG_INLINE const typename ei_eval<Derived>::type eval() const
|
||||
{ return typename ei_eval<Derived>::type(derived()); }
|
||||
|
||||
// template<typename OtherDerived>
|
||||
// void swap(const MatrixBase<OtherDerived>& other);
|
||||
|
||||
template<unsigned int Added>
|
||||
const SparseFlagged<Derived, Added, 0> marked() const;
|
||||
// const Flagged<Derived, 0, EvalBeforeNestingBit | EvalBeforeAssigningBit> lazy() const;
|
||||
|
||||
/** \returns number of elements to skip to pass from one row (resp. column) to another
|
||||
* for a row-major (resp. column-major) matrix.
|
||||
* Combined with coeffRef() and the \ref flags flags, it allows a direct access to the data
|
||||
* of the underlying matrix.
|
||||
*/
|
||||
// inline int stride(void) const { return derived().stride(); }
|
||||
|
||||
// inline const NestByValue<Derived> nestByValue() const;
|
||||
|
||||
|
||||
ConjugateReturnType conjugate() const;
|
||||
const RealReturnType real() const;
|
||||
const ImagReturnType imag() const;
|
||||
|
||||
template<typename CustomUnaryOp>
|
||||
const SparseCwiseUnaryOp<CustomUnaryOp, Derived> unaryExpr(const CustomUnaryOp& func = CustomUnaryOp()) const;
|
||||
|
||||
// template<typename CustomBinaryOp, typename OtherDerived>
|
||||
// const CwiseBinaryOp<CustomBinaryOp, Derived, OtherDerived>
|
||||
// binaryExpr(const MatrixBase<OtherDerived> &other, const CustomBinaryOp& func = CustomBinaryOp()) const;
|
||||
|
||||
|
||||
Scalar sum() const;
|
||||
// Scalar trace() const;
|
||||
|
||||
// typename ei_traits<Derived>::Scalar minCoeff() const;
|
||||
// typename ei_traits<Derived>::Scalar maxCoeff() const;
|
||||
|
||||
// typename ei_traits<Derived>::Scalar minCoeff(int* row, int* col = 0) const;
|
||||
// typename ei_traits<Derived>::Scalar maxCoeff(int* row, int* col = 0) const;
|
||||
|
||||
// template<typename BinaryOp>
|
||||
// typename ei_result_of<BinaryOp(typename ei_traits<Derived>::Scalar)>::type
|
||||
// redux(const BinaryOp& func) const;
|
||||
|
||||
// template<typename Visitor>
|
||||
// void visit(Visitor& func) const;
|
||||
|
||||
|
||||
const SparseCwise<Derived> cwise() const;
|
||||
SparseCwise<Derived> cwise();
|
||||
|
||||
// inline const WithFormat<Derived> format(const IOFormat& fmt) const;
|
||||
|
||||
/////////// Array module ///////////
|
||||
/*
|
||||
bool all(void) const;
|
||||
bool any(void) const;
|
||||
|
||||
const PartialRedux<Derived,Horizontal> rowwise() const;
|
||||
const PartialRedux<Derived,Vertical> colwise() const;
|
||||
|
||||
static const CwiseNullaryOp<ei_scalar_random_op<Scalar>,Derived> Random(int rows, int cols);
|
||||
static const CwiseNullaryOp<ei_scalar_random_op<Scalar>,Derived> Random(int size);
|
||||
static const CwiseNullaryOp<ei_scalar_random_op<Scalar>,Derived> Random();
|
||||
|
||||
template<typename ThenDerived,typename ElseDerived>
|
||||
const Select<Derived,ThenDerived,ElseDerived>
|
||||
select(const MatrixBase<ThenDerived>& thenMatrix,
|
||||
const MatrixBase<ElseDerived>& elseMatrix) const;
|
||||
|
||||
template<typename ThenDerived>
|
||||
inline const Select<Derived,ThenDerived, NestByValue<typename ThenDerived::ConstantReturnType> >
|
||||
select(const MatrixBase<ThenDerived>& thenMatrix, typename ThenDerived::Scalar elseScalar) const;
|
||||
|
||||
template<typename ElseDerived>
|
||||
inline const Select<Derived, NestByValue<typename ElseDerived::ConstantReturnType>, ElseDerived >
|
||||
select(typename ElseDerived::Scalar thenScalar, const MatrixBase<ElseDerived>& elseMatrix) const;
|
||||
|
||||
template<int p> RealScalar lpNorm() const;
|
||||
*/
|
||||
|
||||
|
||||
// template<typename OtherDerived>
|
||||
// Scalar dot(const MatrixBase<OtherDerived>& other) const
|
||||
// {
|
||||
@@ -210,6 +603,18 @@ class SparseMatrixBase : public MatrixBase<Derived>
|
||||
// return res;
|
||||
// }
|
||||
|
||||
#ifdef EIGEN_TAUCS_SUPPORT
|
||||
taucs_ccs_matrix asTaucsMatrix();
|
||||
#endif
|
||||
|
||||
#ifdef EIGEN_CHOLMOD_SUPPORT
|
||||
cholmod_sparse asCholmodMatrix();
|
||||
#endif
|
||||
|
||||
#ifdef EIGEN_SUPERLU_SUPPORT
|
||||
SluMatrix asSluMatrix();
|
||||
#endif
|
||||
|
||||
protected:
|
||||
|
||||
bool m_isRValue;
|
||||
|
||||
@@ -25,9 +25,29 @@
|
||||
#ifndef EIGEN_SPARSEPRODUCT_H
|
||||
#define EIGEN_SPARSEPRODUCT_H
|
||||
|
||||
template<typename Lhs, typename Rhs> struct ei_sparse_product_mode
|
||||
{
|
||||
enum {
|
||||
|
||||
value = (Rhs::Flags&Lhs::Flags&SparseBit)==SparseBit
|
||||
? SparseTimeSparseProduct
|
||||
: (Lhs::Flags&SparseBit)==SparseBit
|
||||
? SparseTimeDenseProduct
|
||||
: DenseTimeSparseProduct };
|
||||
};
|
||||
|
||||
template<typename Lhs, typename Rhs, int ProductMode>
|
||||
struct SparseProductReturnType
|
||||
{
|
||||
typedef const typename ei_nested<Lhs,Rhs::RowsAtCompileTime>::type LhsNested;
|
||||
typedef const typename ei_nested<Rhs,Lhs::RowsAtCompileTime>::type RhsNested;
|
||||
|
||||
typedef SparseProduct<LhsNested, RhsNested, ProductMode> Type;
|
||||
};
|
||||
|
||||
// sparse product return type specialization
|
||||
template<typename Lhs, typename Rhs>
|
||||
struct ProductReturnType<Lhs,Rhs,SparseProduct>
|
||||
struct SparseProductReturnType<Lhs,Rhs,SparseTimeSparseProduct>
|
||||
{
|
||||
typedef typename ei_traits<Lhs>::Scalar Scalar;
|
||||
enum {
|
||||
@@ -47,12 +67,11 @@ struct ProductReturnType<Lhs,Rhs,SparseProduct>
|
||||
SparseMatrix<Scalar,0>,
|
||||
const typename ei_nested<Rhs,Lhs::RowsAtCompileTime>::type>::ret RhsNested;
|
||||
|
||||
typedef Product<LhsNested,
|
||||
RhsNested, SparseProduct> Type;
|
||||
typedef SparseProduct<LhsNested, RhsNested, SparseTimeSparseProduct> Type;
|
||||
};
|
||||
|
||||
template<typename LhsNested, typename RhsNested>
|
||||
struct ei_traits<Product<LhsNested, RhsNested, SparseProduct> >
|
||||
template<typename LhsNested, typename RhsNested, int ProductMode>
|
||||
struct ei_traits<SparseProduct<LhsNested, RhsNested, ProductMode> >
|
||||
{
|
||||
// clean the nested types:
|
||||
typedef typename ei_cleantype<LhsNested>::type _LhsNested;
|
||||
@@ -72,12 +91,13 @@ struct ei_traits<Product<LhsNested, RhsNested, SparseProduct> >
|
||||
MaxRowsAtCompileTime = _LhsNested::MaxRowsAtCompileTime,
|
||||
MaxColsAtCompileTime = _RhsNested::MaxColsAtCompileTime,
|
||||
|
||||
LhsRowMajor = LhsFlags & RowMajorBit,
|
||||
RhsRowMajor = RhsFlags & RowMajorBit,
|
||||
// LhsIsRowMajor = (LhsFlags & RowMajorBit)==RowMajorBit,
|
||||
// RhsIsRowMajor = (RhsFlags & RowMajorBit)==RowMajorBit,
|
||||
|
||||
EvalToRowMajor = (RhsFlags & LhsFlags & RowMajorBit),
|
||||
ResultIsSparse = ProductMode==SparseTimeSparseProduct,
|
||||
|
||||
RemovedBits = ~(EvalToRowMajor ? 0 : RowMajorBit),
|
||||
RemovedBits = ~( (EvalToRowMajor ? 0 : RowMajorBit) | (ResultIsSparse ? 0 : SparseBit) ),
|
||||
|
||||
Flags = (int(LhsFlags | RhsFlags) & HereditaryBits & RemovedBits)
|
||||
| EvalBeforeAssigningBit
|
||||
@@ -85,37 +105,54 @@ struct ei_traits<Product<LhsNested, RhsNested, SparseProduct> >
|
||||
|
||||
CoeffReadCost = Dynamic
|
||||
};
|
||||
|
||||
typedef typename ei_meta_if<ResultIsSparse,
|
||||
SparseMatrixBase<SparseProduct<LhsNested, RhsNested, ProductMode> >,
|
||||
MatrixBase<SparseProduct<LhsNested, RhsNested, ProductMode> > >::ret Base;
|
||||
};
|
||||
|
||||
template<typename LhsNested, typename RhsNested> class Product<LhsNested,RhsNested,SparseProduct> : ei_no_assignment_operator,
|
||||
public MatrixBase<Product<LhsNested, RhsNested, SparseProduct> >
|
||||
template<typename LhsNested, typename RhsNested, int ProductMode>
|
||||
class SparseProduct : ei_no_assignment_operator, public ei_traits<SparseProduct<LhsNested, RhsNested, ProductMode> >::Base
|
||||
{
|
||||
public:
|
||||
|
||||
EIGEN_GENERIC_PUBLIC_INTERFACE(Product)
|
||||
EIGEN_GENERIC_PUBLIC_INTERFACE(SparseProduct)
|
||||
|
||||
private:
|
||||
|
||||
typedef typename ei_traits<Product>::_LhsNested _LhsNested;
|
||||
typedef typename ei_traits<Product>::_RhsNested _RhsNested;
|
||||
typedef typename ei_traits<SparseProduct>::_LhsNested _LhsNested;
|
||||
typedef typename ei_traits<SparseProduct>::_RhsNested _RhsNested;
|
||||
|
||||
public:
|
||||
|
||||
template<typename Lhs, typename Rhs>
|
||||
inline Product(const Lhs& lhs, const Rhs& rhs)
|
||||
EIGEN_STRONG_INLINE SparseProduct(const Lhs& lhs, const Rhs& rhs)
|
||||
: m_lhs(lhs), m_rhs(rhs)
|
||||
{
|
||||
ei_assert(lhs.cols() == rhs.rows());
|
||||
|
||||
enum {
|
||||
ProductIsValid = _LhsNested::ColsAtCompileTime==Dynamic
|
||||
|| _RhsNested::RowsAtCompileTime==Dynamic
|
||||
|| int(_LhsNested::ColsAtCompileTime)==int(_RhsNested::RowsAtCompileTime),
|
||||
AreVectors = _LhsNested::IsVectorAtCompileTime && _RhsNested::IsVectorAtCompileTime,
|
||||
SameSizes = EIGEN_PREDICATE_SAME_MATRIX_SIZE(_LhsNested,_RhsNested)
|
||||
};
|
||||
// note to the lost user:
|
||||
// * for a dot product use: v1.dot(v2)
|
||||
// * for a coeff-wise product use: v1.cwise()*v2
|
||||
EIGEN_STATIC_ASSERT(ProductIsValid || !(AreVectors && SameSizes),
|
||||
INVALID_VECTOR_VECTOR_PRODUCT__IF_YOU_WANTED_A_DOT_OR_COEFF_WISE_PRODUCT_YOU_MUST_USE_THE_EXPLICIT_FUNCTIONS)
|
||||
EIGEN_STATIC_ASSERT(ProductIsValid || !(SameSizes && !AreVectors),
|
||||
INVALID_MATRIX_PRODUCT__IF_YOU_WANTED_A_COEFF_WISE_PRODUCT_YOU_MUST_USE_THE_EXPLICIT_FUNCTION)
|
||||
EIGEN_STATIC_ASSERT(ProductIsValid || SameSizes, INVALID_MATRIX_PRODUCT)
|
||||
}
|
||||
|
||||
Scalar coeff(int, int) const { ei_assert(false && "eigen internal error"); }
|
||||
Scalar& coeffRef(int, int) { ei_assert(false && "eigen internal error"); }
|
||||
EIGEN_STRONG_INLINE int rows() const { return m_lhs.rows(); }
|
||||
EIGEN_STRONG_INLINE int cols() const { return m_rhs.cols(); }
|
||||
|
||||
inline int rows() const { return m_lhs.rows(); }
|
||||
inline int cols() const { return m_rhs.cols(); }
|
||||
|
||||
const _LhsNested& lhs() const { return m_lhs; }
|
||||
const _LhsNested& rhs() const { return m_rhs; }
|
||||
EIGEN_STRONG_INLINE const _LhsNested& lhs() const { return m_lhs; }
|
||||
EIGEN_STRONG_INLINE const _RhsNested& rhs() const { return m_rhs; }
|
||||
|
||||
protected:
|
||||
LhsNested m_lhs;
|
||||
@@ -209,7 +246,7 @@ struct ei_sparse_product_selector<Lhs,Rhs,ResultType,RowMajor,RowMajor,ColMajor>
|
||||
{
|
||||
// let's transpose the product to get a column x column product
|
||||
SparseTemporaryType _res(res.cols(), res.rows());
|
||||
ei_sparse_product_selector<Rhs,Lhs,ResultType,ColMajor,ColMajor,ColMajor>
|
||||
ei_sparse_product_selector<Rhs,Lhs,SparseTemporaryType,ColMajor,ColMajor,ColMajor>
|
||||
::run(rhs, lhs, _res);
|
||||
res = _res.transpose();
|
||||
}
|
||||
@@ -231,21 +268,22 @@ struct ei_sparse_product_selector<Lhs,Rhs,ResultType,RowMajor,RowMajor,ColMajor>
|
||||
// by ProductReturnType which transform it to (col col *) by evaluating rhs.
|
||||
|
||||
|
||||
template<typename Derived>
|
||||
template<typename Lhs, typename Rhs>
|
||||
inline Derived& MatrixBase<Derived>::lazyAssign(const Product<Lhs,Rhs,SparseProduct>& product)
|
||||
{
|
||||
// std::cout << "sparse product to dense\n";
|
||||
ei_sparse_product_selector<
|
||||
typename ei_cleantype<Lhs>::type,
|
||||
typename ei_cleantype<Rhs>::type,
|
||||
typename ei_cleantype<Derived>::type>::run(product.lhs(),product.rhs(),derived());
|
||||
return derived();
|
||||
}
|
||||
// template<typename Derived>
|
||||
// template<typename Lhs, typename Rhs>
|
||||
// inline Derived& SparseMatrixBase<Derived>::lazyAssign(const SparseProduct<Lhs,Rhs>& product)
|
||||
// {
|
||||
// // std::cout << "sparse product to dense\n";
|
||||
// ei_sparse_product_selector<
|
||||
// typename ei_cleantype<Lhs>::type,
|
||||
// typename ei_cleantype<Rhs>::type,
|
||||
// typename ei_cleantype<Derived>::type>::run(product.lhs(),product.rhs(),derived());
|
||||
// return derived();
|
||||
// }
|
||||
|
||||
// sparse = sparse * sparse
|
||||
template<typename Derived>
|
||||
template<typename Lhs, typename Rhs>
|
||||
inline Derived& SparseMatrixBase<Derived>::operator=(const Product<Lhs,Rhs,SparseProduct>& product)
|
||||
inline Derived& SparseMatrixBase<Derived>::operator=(const SparseProduct<Lhs,Rhs,SparseTimeSparseProduct>& product)
|
||||
{
|
||||
// std::cout << "sparse product to sparse\n";
|
||||
ei_sparse_product_selector<
|
||||
@@ -255,4 +293,99 @@ inline Derived& SparseMatrixBase<Derived>::operator=(const Product<Lhs,Rhs,Spars
|
||||
return derived();
|
||||
}
|
||||
|
||||
// dense = sparse * dense
|
||||
// template<typename Derived>
|
||||
// template<typename Lhs, typename Rhs>
|
||||
// Derived& MatrixBase<Derived>::lazyAssign(const SparseProduct<Lhs,Rhs,SparseTimeDenseProduct>& product)
|
||||
// {
|
||||
// typedef typename ei_cleantype<Lhs>::type _Lhs;
|
||||
// typedef typename _Lhs::InnerIterator LhsInnerIterator;
|
||||
// enum { LhsIsRowMajor = (_Lhs::Flags&RowMajorBit)==RowMajorBit };
|
||||
// derived().setZero();
|
||||
// for (int j=0; j<product.lhs().outerSize(); ++j)
|
||||
// for (LhsInnerIterator i(product.lhs(),j); i; ++i)
|
||||
// derived().row(LhsIsRowMajor ? j : i.index()) += i.value() * product.rhs().row(LhsIsRowMajor ? i.index() : j);
|
||||
// return derived();
|
||||
// }
|
||||
|
||||
template<typename Derived>
|
||||
template<typename Lhs, typename Rhs>
|
||||
Derived& MatrixBase<Derived>::lazyAssign(const SparseProduct<Lhs,Rhs,SparseTimeDenseProduct>& product)
|
||||
{
|
||||
typedef typename ei_cleantype<Lhs>::type _Lhs;
|
||||
typedef typename ei_cleantype<Rhs>::type _Rhs;
|
||||
typedef typename _Lhs::InnerIterator LhsInnerIterator;
|
||||
enum {
|
||||
LhsIsRowMajor = (_Lhs::Flags&RowMajorBit)==RowMajorBit,
|
||||
LhsIsSelfAdjoint = (_Lhs::Flags&SelfAdjointBit)==SelfAdjointBit,
|
||||
ProcessFirstHalf = LhsIsSelfAdjoint
|
||||
&& ( ((_Lhs::Flags&(UpperTriangularBit|LowerTriangularBit))==0)
|
||||
|| ( (_Lhs::Flags&UpperTriangularBit) && !LhsIsRowMajor)
|
||||
|| ( (_Lhs::Flags&LowerTriangularBit) && LhsIsRowMajor) ),
|
||||
ProcessSecondHalf = LhsIsSelfAdjoint && (!ProcessFirstHalf)
|
||||
};
|
||||
derived().setZero();
|
||||
for (int j=0; j<product.lhs().outerSize(); ++j)
|
||||
{
|
||||
LhsInnerIterator i(product.lhs(),j);
|
||||
if (ProcessSecondHalf && i && (i.index()==j))
|
||||
{
|
||||
derived().row(j) += i.value() * product.rhs().row(j);
|
||||
++i;
|
||||
}
|
||||
Block<Derived,1,Derived::ColsAtCompileTime> foo = derived().row(j);
|
||||
for (; (ProcessFirstHalf ? i && i.index() < j : i) ; ++i)
|
||||
{
|
||||
if (LhsIsSelfAdjoint)
|
||||
{
|
||||
int a = LhsIsRowMajor ? j : i.index();
|
||||
int b = LhsIsRowMajor ? i.index() : j;
|
||||
Scalar v = i.value();
|
||||
derived().row(a) += (v) * product.rhs().row(b);
|
||||
derived().row(b) += ei_conj(v) * product.rhs().row(a);
|
||||
}
|
||||
else if (LhsIsRowMajor)
|
||||
foo += i.value() * product.rhs().row(i.index());
|
||||
else
|
||||
derived().row(i.index()) += i.value() * product.rhs().row(j);
|
||||
}
|
||||
if (ProcessFirstHalf && i && (i.index()==j))
|
||||
derived().row(j) += i.value() * product.rhs().row(j);
|
||||
}
|
||||
return derived();
|
||||
}
|
||||
|
||||
// dense = dense * sparse
|
||||
template<typename Derived>
|
||||
template<typename Lhs, typename Rhs>
|
||||
Derived& MatrixBase<Derived>::lazyAssign(const SparseProduct<Lhs,Rhs,DenseTimeSparseProduct>& product)
|
||||
{
|
||||
typedef typename ei_cleantype<Rhs>::type _Rhs;
|
||||
typedef typename _Rhs::InnerIterator RhsInnerIterator;
|
||||
enum { RhsIsRowMajor = (_Rhs::Flags&RowMajorBit)==RowMajorBit };
|
||||
derived().setZero();
|
||||
for (int j=0; j<product.rhs().outerSize(); ++j)
|
||||
for (RhsInnerIterator i(product.rhs(),j); i; ++i)
|
||||
derived().col(RhsIsRowMajor ? i.index() : j) += i.value() * product.lhs().col(RhsIsRowMajor ? j : i.index());
|
||||
return derived();
|
||||
}
|
||||
|
||||
// sparse * sparse
|
||||
template<typename Derived>
|
||||
template<typename OtherDerived>
|
||||
EIGEN_STRONG_INLINE const typename SparseProductReturnType<Derived,OtherDerived>::Type
|
||||
SparseMatrixBase<Derived>::operator*(const SparseMatrixBase<OtherDerived> &other) const
|
||||
{
|
||||
return typename SparseProductReturnType<Derived,OtherDerived>::Type(derived(), other.derived());
|
||||
}
|
||||
|
||||
// sparse * dense
|
||||
template<typename Derived>
|
||||
template<typename OtherDerived>
|
||||
EIGEN_STRONG_INLINE const typename SparseProductReturnType<Derived,OtherDerived>::Type
|
||||
SparseMatrixBase<Derived>::operator*(const MatrixBase<OtherDerived> &other) const
|
||||
{
|
||||
return typename SparseProductReturnType<Derived,OtherDerived>::Type(derived(), other.derived());
|
||||
}
|
||||
|
||||
#endif // EIGEN_SPARSEPRODUCT_H
|
||||
|
||||
@@ -25,46 +25,16 @@
|
||||
#ifndef EIGEN_SPARSEREDUX_H
|
||||
#define EIGEN_SPARSEREDUX_H
|
||||
|
||||
|
||||
template<typename Derived, int Vectorization, int Unrolling>
|
||||
struct ei_sum_impl<Derived, Vectorization, Unrolling, IsSparse>
|
||||
template<typename Derived>
|
||||
typename ei_traits<Derived>::Scalar
|
||||
SparseMatrixBase<Derived>::sum() const
|
||||
{
|
||||
typedef typename Derived::Scalar Scalar;
|
||||
static Scalar run(const Derived& mat)
|
||||
{
|
||||
ei_assert(mat.rows()>0 && mat.cols()>0 && "you are using a non initialized matrix");
|
||||
Scalar res = 0;
|
||||
for (int j=0; j<mat.outerSize(); ++j)
|
||||
for (typename Derived::InnerIterator iter(mat,j); iter; ++iter)
|
||||
res += iter.value();
|
||||
return res;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Derived1, typename Derived2, int Vectorization, int Unrolling>
|
||||
struct ei_dot_impl<Derived1, Derived2, Vectorization, Unrolling, IsSparse>
|
||||
{
|
||||
typedef typename Derived1::Scalar Scalar;
|
||||
static Scalar run(const Derived1& v1, const Derived2& v2)
|
||||
{
|
||||
ei_assert(v1.size()>0 && "you are using a non initialized vector");
|
||||
typename Derived1::InnerIterator i(v1,0);
|
||||
typename Derived2::InnerIterator j(v2,0);
|
||||
Scalar res = 0;
|
||||
while (i && j)
|
||||
{
|
||||
if (i.index()==j.index())
|
||||
{
|
||||
res += i.value() * ei_conj(j.value());
|
||||
++i; ++j;
|
||||
}
|
||||
else if (i.index()<j.index())
|
||||
++i;
|
||||
else
|
||||
++j;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
};
|
||||
ei_assert(rows()>0 && cols()>0 && "you are using a non initialized matrix");
|
||||
Scalar res = 0;
|
||||
for (int j=0; j<outerSize(); ++j)
|
||||
for (typename Derived::InnerIterator iter(derived(),j); iter; ++iter)
|
||||
res += iter.value();
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif // EIGEN_SPARSEREDUX_H
|
||||
|
||||
85
Eigen/src/Sparse/SparseTranspose.h
Normal file
85
Eigen/src/Sparse/SparseTranspose.h
Normal file
@@ -0,0 +1,85 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
//
|
||||
// Eigen is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 3 of the License, or (at your option) any later version.
|
||||
//
|
||||
// Alternatively, you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of
|
||||
// the License, or (at your option) any later version.
|
||||
//
|
||||
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License and a copy of the GNU General Public License along with
|
||||
// Eigen. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef EIGEN_SPARSETRANSPOSE_H
|
||||
#define EIGEN_SPARSETRANSPOSE_H
|
||||
|
||||
template<typename MatrixType>
|
||||
struct ei_traits<SparseTranspose<MatrixType> > : ei_traits<Transpose<MatrixType> >
|
||||
{};
|
||||
|
||||
template<typename MatrixType> class SparseTranspose
|
||||
: public SparseMatrixBase<SparseTranspose<MatrixType> >
|
||||
{
|
||||
public:
|
||||
|
||||
EIGEN_GENERIC_PUBLIC_INTERFACE(SparseTranspose)
|
||||
|
||||
class InnerIterator;
|
||||
class ReverseInnerIterator;
|
||||
|
||||
inline SparseTranspose(const MatrixType& matrix) : m_matrix(matrix) {}
|
||||
|
||||
//EIGEN_INHERIT_ASSIGNMENT_OPERATORS(SparseTranspose)
|
||||
|
||||
inline int rows() const { return m_matrix.cols(); }
|
||||
inline int cols() const { return m_matrix.rows(); }
|
||||
inline int nonZeros() const { return m_matrix.nonZeros(); }
|
||||
|
||||
// FIXME should be keep them ?
|
||||
inline Scalar& coeffRef(int row, int col)
|
||||
{ return m_matrix.const_cast_derived().coeffRef(col, row); }
|
||||
|
||||
inline const Scalar coeff(int row, int col) const
|
||||
{ return m_matrix.coeff(col, row); }
|
||||
|
||||
inline const Scalar coeff(int index) const
|
||||
{ return m_matrix.coeff(index); }
|
||||
|
||||
inline Scalar& coeffRef(int index)
|
||||
{ return m_matrix.const_cast_derived().coeffRef(index); }
|
||||
|
||||
protected:
|
||||
const typename MatrixType::Nested m_matrix;
|
||||
};
|
||||
|
||||
template<typename MatrixType> class SparseTranspose<MatrixType>::InnerIterator : public MatrixType::InnerIterator
|
||||
{
|
||||
public:
|
||||
|
||||
EIGEN_STRONG_INLINE InnerIterator(const SparseTranspose& trans, int outer)
|
||||
: MatrixType::InnerIterator(trans.m_matrix, outer)
|
||||
{}
|
||||
};
|
||||
|
||||
template<typename MatrixType> class SparseTranspose<MatrixType>::ReverseInnerIterator : public MatrixType::ReverseInnerIterator
|
||||
{
|
||||
public:
|
||||
|
||||
EIGEN_STRONG_INLINE ReverseInnerIterator(const SparseTranspose& xpr, int outer)
|
||||
: MatrixType::ReverseInnerIterator(xpr.m_matrix, outer)
|
||||
{}
|
||||
};
|
||||
|
||||
#endif // EIGEN_SPARSETRANSPOSE_H
|
||||
@@ -31,6 +31,46 @@
|
||||
#define EIGEN_DBG_SPARSE(X) X
|
||||
#endif
|
||||
|
||||
#define EIGEN_SPARSE_INHERIT_ASSIGNMENT_OPERATOR(Derived, Op) \
|
||||
template<typename OtherDerived> \
|
||||
EIGEN_STRONG_INLINE Derived& operator Op(const Eigen::SparseMatrixBase<OtherDerived>& other) \
|
||||
{ \
|
||||
return Base::operator Op(other.derived()); \
|
||||
} \
|
||||
EIGEN_STRONG_INLINE Derived& operator Op(const Derived& other) \
|
||||
{ \
|
||||
return Base::operator Op(other); \
|
||||
}
|
||||
|
||||
#define EIGEN_SPARSE_INHERIT_SCALAR_ASSIGNMENT_OPERATOR(Derived, Op) \
|
||||
template<typename Other> \
|
||||
EIGEN_STRONG_INLINE Derived& operator Op(const Other& scalar) \
|
||||
{ \
|
||||
return Base::operator Op(scalar); \
|
||||
}
|
||||
|
||||
#define EIGEN_SPARSE_INHERIT_ASSIGNMENT_OPERATORS(Derived) \
|
||||
EIGEN_SPARSE_INHERIT_ASSIGNMENT_OPERATOR(Derived, =) \
|
||||
EIGEN_SPARSE_INHERIT_ASSIGNMENT_OPERATOR(Derived, +=) \
|
||||
EIGEN_SPARSE_INHERIT_ASSIGNMENT_OPERATOR(Derived, -=) \
|
||||
EIGEN_SPARSE_INHERIT_SCALAR_ASSIGNMENT_OPERATOR(Derived, *=) \
|
||||
EIGEN_SPARSE_INHERIT_SCALAR_ASSIGNMENT_OPERATOR(Derived, /=)
|
||||
|
||||
#define _EIGEN_SPARSE_GENERIC_PUBLIC_INTERFACE(Derived, BaseClass) \
|
||||
typedef BaseClass Base; \
|
||||
typedef typename Eigen::ei_traits<Derived>::Scalar Scalar; \
|
||||
typedef typename Eigen::NumTraits<Scalar>::Real RealScalar; \
|
||||
typedef typename Eigen::ei_nested<Derived>::type Nested; \
|
||||
enum { RowsAtCompileTime = Eigen::ei_traits<Derived>::RowsAtCompileTime, \
|
||||
ColsAtCompileTime = Eigen::ei_traits<Derived>::ColsAtCompileTime, \
|
||||
Flags = Eigen::ei_traits<Derived>::Flags, \
|
||||
CoeffReadCost = Eigen::ei_traits<Derived>::CoeffReadCost, \
|
||||
SizeAtCompileTime = Base::SizeAtCompileTime, \
|
||||
IsVectorAtCompileTime = Base::IsVectorAtCompileTime };
|
||||
|
||||
#define EIGEN_SPARSE_GENERIC_PUBLIC_INTERFACE(Derived) \
|
||||
_EIGEN_SPARSE_GENERIC_PUBLIC_INTERFACE(Derived, Eigen::SparseMatrixBase<Derived>)
|
||||
|
||||
enum SparseBackend {
|
||||
DefaultBackend,
|
||||
Taucs,
|
||||
@@ -62,19 +102,36 @@ enum {
|
||||
|
||||
template<typename Derived> class SparseMatrixBase;
|
||||
template<typename _Scalar, int _Flags = 0> class SparseMatrix;
|
||||
template<typename _Scalar, int _Flags = 0> class DynamicSparseMatrix;
|
||||
template<typename _Scalar, int _Flags = 0> class SparseVector;
|
||||
template<typename _Scalar, int _Flags = 0> class MappedSparseMatrix;
|
||||
|
||||
const int AccessPatternNotSupported = 0x0;
|
||||
const int AccessPatternSupported = 0x1;
|
||||
template<typename MatrixType> class SparseTranspose;
|
||||
template<typename MatrixType> class SparseInnerVector;
|
||||
template<typename Derived> class SparseCwise;
|
||||
template<typename UnaryOp, typename MatrixType> class SparseCwiseUnaryOp;
|
||||
template<typename BinaryOp, typename Lhs, typename Rhs> class SparseCwiseBinaryOp;
|
||||
template<typename ExpressionType,
|
||||
unsigned int Added, unsigned int Removed> class SparseFlagged;
|
||||
|
||||
template<typename Lhs, typename Rhs> struct ei_sparse_product_mode;
|
||||
template<typename Lhs, typename Rhs, int ProductMode = ei_sparse_product_mode<Lhs,Rhs>::value> struct SparseProductReturnType;
|
||||
|
||||
template<typename MatrixType, int AccessPattern> struct ei_support_access_pattern
|
||||
{
|
||||
enum { ret = (int(ei_traits<MatrixType>::SupportedAccessPatterns) & AccessPattern) == AccessPattern
|
||||
? AccessPatternSupported
|
||||
: AccessPatternNotSupported
|
||||
};
|
||||
};
|
||||
const int CoherentAccessPattern = 0x1;
|
||||
const int InnerRandomAccessPattern = 0x2 | CoherentAccessPattern;
|
||||
const int OuterRandomAccessPattern = 0x4 | CoherentAccessPattern;
|
||||
const int RandomAccessPattern = 0x8 | OuterRandomAccessPattern | InnerRandomAccessPattern;
|
||||
|
||||
// const int AccessPatternNotSupported = 0x0;
|
||||
// const int AccessPatternSupported = 0x1;
|
||||
//
|
||||
// template<typename MatrixType, int AccessPattern> struct ei_support_access_pattern
|
||||
// {
|
||||
// enum { ret = (int(ei_traits<MatrixType>::SupportedAccessPatterns) & AccessPattern) == AccessPattern
|
||||
// ? AccessPatternSupported
|
||||
// : AccessPatternNotSupported
|
||||
// };
|
||||
// };
|
||||
|
||||
template<typename T> class ei_eval<T,IsSparse>
|
||||
{
|
||||
|
||||
@@ -47,66 +47,48 @@ struct ei_traits<SparseVector<_Scalar, _Flags> >
|
||||
MaxColsAtCompileTime = ColsAtCompileTime,
|
||||
Flags = SparseBit | _Flags,
|
||||
CoeffReadCost = NumTraits<Scalar>::ReadCost,
|
||||
SupportedAccessPatterns = FullyCoherentAccessPattern
|
||||
SupportedAccessPatterns = InnerRandomAccessPattern
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
|
||||
template<typename _Scalar, int _Flags>
|
||||
class SparseVector
|
||||
: public SparseMatrixBase<SparseVector<_Scalar, _Flags> >
|
||||
{
|
||||
public:
|
||||
EIGEN_GENERIC_PUBLIC_INTERFACE(SparseVector)
|
||||
EIGEN_SPARSE_GENERIC_PUBLIC_INTERFACE(SparseVector)
|
||||
EIGEN_SPARSE_INHERIT_ASSIGNMENT_OPERATOR(SparseVector, +=)
|
||||
EIGEN_SPARSE_INHERIT_ASSIGNMENT_OPERATOR(SparseVector, -=)
|
||||
|
||||
protected:
|
||||
public:
|
||||
|
||||
typedef SparseMatrixBase<SparseVector> SparseBase;
|
||||
enum {
|
||||
IsColVector = ei_traits<SparseVector>::IsColVector
|
||||
};
|
||||
enum { IsColVector = ei_traits<SparseVector>::IsColVector };
|
||||
|
||||
SparseArray<Scalar> m_data;
|
||||
CompressedStorage<Scalar> m_data;
|
||||
int m_size;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
inline int rows() const { return IsColVector ? m_size : 1; }
|
||||
inline int cols() const { return IsColVector ? 1 : m_size; }
|
||||
inline int innerSize() const { return m_size; }
|
||||
inline int outerSize() const { return 1; }
|
||||
inline int innerNonZeros(int j) const { ei_assert(j==0); return m_size; }
|
||||
EIGEN_STRONG_INLINE int rows() const { return IsColVector ? m_size : 1; }
|
||||
EIGEN_STRONG_INLINE int cols() const { return IsColVector ? 1 : m_size; }
|
||||
EIGEN_STRONG_INLINE int innerSize() const { return m_size; }
|
||||
EIGEN_STRONG_INLINE int outerSize() const { return 1; }
|
||||
EIGEN_STRONG_INLINE int innerNonZeros(int j) const { ei_assert(j==0); return m_size; }
|
||||
|
||||
inline const Scalar* _valuePtr() const { return &m_data.value(0); }
|
||||
inline Scalar* _valuePtr() { return &m_data.value(0); }
|
||||
EIGEN_STRONG_INLINE const Scalar* _valuePtr() const { return &m_data.value(0); }
|
||||
EIGEN_STRONG_INLINE Scalar* _valuePtr() { return &m_data.value(0); }
|
||||
|
||||
inline const int* _innerIndexPtr() const { return &m_data.index(0); }
|
||||
inline int* _innerIndexPtr() { return &m_data.index(0); }
|
||||
EIGEN_STRONG_INLINE const int* _innerIndexPtr() const { return &m_data.index(0); }
|
||||
EIGEN_STRONG_INLINE int* _innerIndexPtr() { return &m_data.index(0); }
|
||||
|
||||
inline Scalar coeff(int row, int col) const
|
||||
{
|
||||
ei_assert((IsColVector ? col : row)==0);
|
||||
return coeff(IsColVector ? row : col);
|
||||
}
|
||||
inline Scalar coeff(int i) const
|
||||
{
|
||||
int start = 0;
|
||||
int end = m_data.size();
|
||||
if (start==end)
|
||||
return Scalar(0);
|
||||
else if (end>0 && i==m_data.index(end-1))
|
||||
return m_data.value(end-1);
|
||||
// ^^ optimization: let's first check if it is the last coefficient
|
||||
// (very common in high level algorithms)
|
||||
|
||||
// TODO move this search to ScalarArray
|
||||
const int* r = std::lower_bound(&m_data.index(start),&m_data.index(end-1),i);
|
||||
const int id = r-&m_data.index(0);
|
||||
return ((*r==i) && (id<end)) ? m_data.value(id) : Scalar(0);
|
||||
}
|
||||
inline Scalar coeff(int i) const { return m_data.at(i); }
|
||||
|
||||
inline Scalar& coeffRef(int row, int col)
|
||||
{
|
||||
@@ -114,16 +96,15 @@ class SparseVector
|
||||
return coeff(IsColVector ? row : col);
|
||||
}
|
||||
|
||||
/** \returns a reference to the coefficient value at given index \a i
|
||||
* This operation involes a log(rho*size) binary search. If the coefficient does not
|
||||
* exist yet, then a sorted insertion into a sequential buffer is performed.
|
||||
*
|
||||
* This insertion might be very costly if the number of nonzeros above \a i is large.
|
||||
*/
|
||||
inline Scalar& coeffRef(int i)
|
||||
{
|
||||
int start = 0;
|
||||
int end = m_data.size();
|
||||
ei_assert(end>=start && "you probably called coeffRef on a non finalized vector");
|
||||
ei_assert(end>start && "coeffRef cannot be called on a zero coefficient");
|
||||
int* r = std::lower_bound(&m_data.index(start),&m_data.index(end),i);
|
||||
const int id = r-&m_data.index(0);
|
||||
ei_assert((*r==i) && (id<end) && "coeffRef cannot be called on a zero coefficient");
|
||||
return m_data.value(id);
|
||||
return m_data.atWithInsertion(i);
|
||||
}
|
||||
|
||||
public:
|
||||
@@ -138,14 +119,32 @@ class SparseVector
|
||||
/**
|
||||
*/
|
||||
inline void reserve(int reserveSize) { m_data.reserve(reserveSize); }
|
||||
|
||||
inline void startFill(int reserve)
|
||||
{
|
||||
setZero();
|
||||
m_data.reserve(reserve);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
inline Scalar& fill(int r, int c)
|
||||
{
|
||||
ei_assert(r==0 || c==0);
|
||||
return fill(IsColVector ? r : c);
|
||||
}
|
||||
|
||||
inline Scalar& fill(int i)
|
||||
{
|
||||
m_data.append(0, i);
|
||||
return m_data.value(m_data.size()-1);
|
||||
}
|
||||
|
||||
inline Scalar& fillrand(int r, int c)
|
||||
{
|
||||
ei_assert(r==0 || c==0);
|
||||
return fillrand(IsColVector ? r : c);
|
||||
}
|
||||
|
||||
/** Like fill() but with random coordinates.
|
||||
*/
|
||||
@@ -153,7 +152,7 @@ class SparseVector
|
||||
{
|
||||
int startId = 0;
|
||||
int id = m_data.size() - 1;
|
||||
m_data.resize(id+2);
|
||||
m_data.resize(id+2,1);
|
||||
|
||||
while ( (id >= startId) && (m_data.index(id) > i) )
|
||||
{
|
||||
@@ -165,6 +164,19 @@ class SparseVector
|
||||
m_data.value(id+1) = 0;
|
||||
return m_data.value(id+1);
|
||||
}
|
||||
|
||||
inline void endFill() {}
|
||||
|
||||
void prune(Scalar reference, RealScalar epsilon = precision<RealScalar>())
|
||||
{
|
||||
m_data.prune(reference,epsilon);
|
||||
}
|
||||
|
||||
void resize(int rows, int cols)
|
||||
{
|
||||
ei_assert(rows==1 || cols==1);
|
||||
resize(IsColVector ? rows : cols);
|
||||
}
|
||||
|
||||
void resize(int newSize)
|
||||
{
|
||||
@@ -174,9 +186,11 @@ class SparseVector
|
||||
|
||||
void resizeNonZeros(int size) { m_data.resize(size); }
|
||||
|
||||
inline SparseVector() : m_size(0) { resize(0, 0); }
|
||||
inline SparseVector() : m_size(0) { resize(0); }
|
||||
|
||||
inline SparseVector(int size) : m_size(0) { resize(size); }
|
||||
|
||||
inline SparseVector(int rows, int cols) : m_size(0) { resize(rows,cols); }
|
||||
|
||||
template<typename OtherDerived>
|
||||
inline SparseVector(const MatrixBase<OtherDerived>& other)
|
||||
@@ -303,26 +317,33 @@ class SparseVector<Scalar,_Flags>::InnerIterator
|
||||
{
|
||||
public:
|
||||
InnerIterator(const SparseVector& vec, int outer=0)
|
||||
: m_vector(vec), m_id(0), m_end(vec.nonZeros())
|
||||
: m_data(vec.m_data), m_id(0), m_end(m_data.size())
|
||||
{
|
||||
ei_assert(outer==0);
|
||||
}
|
||||
|
||||
InnerIterator(const CompressedStorage<Scalar>& data)
|
||||
: m_data(data), m_id(0), m_end(m_data.size())
|
||||
{}
|
||||
|
||||
template<unsigned int Added, unsigned int Removed>
|
||||
InnerIterator(const Flagged<SparseVector,Added,Removed>& vec, int outer)
|
||||
: m_vector(vec._expression()), m_id(0), m_end(m_vector.nonZeros())
|
||||
: m_data(vec._expression().m_data), m_id(0), m_end(m_data.size())
|
||||
{}
|
||||
|
||||
inline InnerIterator& operator++() { m_id++; return *this; }
|
||||
|
||||
inline Scalar value() const { return m_vector.m_data.value(m_id); }
|
||||
inline Scalar value() const { return m_data.value(m_id); }
|
||||
inline Scalar& valueRef() { return const_cast<Scalar&>(m_data.value(m_id)); }
|
||||
|
||||
inline int index() const { return m_vector.m_data.index(m_id); }
|
||||
inline int index() const { return m_data.index(m_id); }
|
||||
inline int row() const { return IsColVector ? index() : 0; }
|
||||
inline int col() const { return IsColVector ? 0 : index(); }
|
||||
|
||||
inline operator bool() const { return (m_id < m_end); }
|
||||
|
||||
protected:
|
||||
const SparseVector& m_vector;
|
||||
const CompressedStorage<Scalar>& m_data;
|
||||
int m_id;
|
||||
const int m_end;
|
||||
};
|
||||
|
||||
@@ -104,12 +104,58 @@ struct SluMatrix : SuperMatrix
|
||||
ei_assert(false && "Scalar type not supported by SuperLU");
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Scalar, int Rows, int Cols, int Options, int MRows, int MCols>
|
||||
static SluMatrix Map(Matrix<Scalar,Rows,Cols,Options,MRows,MCols>& mat)
|
||||
{
|
||||
typedef Matrix<Scalar,Rows,Cols,Options,MRows,MCols> MatrixType;
|
||||
ei_assert( ((Options&RowMajor)!=RowMajor) && "row-major dense matrices is not supported by SuperLU");
|
||||
SluMatrix res;
|
||||
res.setStorageType(SLU_DN);
|
||||
res.setScalarType<Scalar>();
|
||||
res.Mtype = SLU_GE;
|
||||
|
||||
res.nrow = mat.rows();
|
||||
res.ncol = mat.cols();
|
||||
|
||||
res.storage.lda = mat.stride();
|
||||
res.storage.values = mat.data();
|
||||
return res;
|
||||
}
|
||||
|
||||
template<typename MatrixType>
|
||||
static SluMatrix Map(MatrixType& mat)
|
||||
static SluMatrix Map(SparseMatrixBase<MatrixType>& mat)
|
||||
{
|
||||
SluMatrix res;
|
||||
SluMatrixMapHelper<MatrixType>::run(mat, res);
|
||||
if ((MatrixType::Flags&RowMajorBit)==RowMajorBit)
|
||||
{
|
||||
res.setStorageType(SLU_NR);
|
||||
res.nrow = mat.cols();
|
||||
res.ncol = mat.rows();
|
||||
}
|
||||
else
|
||||
{
|
||||
res.setStorageType(SLU_NC);
|
||||
res.nrow = mat.rows();
|
||||
res.ncol = mat.cols();
|
||||
}
|
||||
|
||||
res.Mtype = SLU_GE;
|
||||
|
||||
res.storage.nnz = mat.nonZeros();
|
||||
res.storage.values = mat.derived()._valuePtr();
|
||||
res.storage.innerInd = mat.derived()._innerIndexPtr();
|
||||
res.storage.outerInd = mat.derived()._outerIndexPtr();
|
||||
|
||||
res.setScalarType<typename MatrixType::Scalar>();
|
||||
|
||||
// FIXME the following is not very accurate
|
||||
if (MatrixType::Flags & UpperTriangular)
|
||||
res.Mtype = SLU_TRU;
|
||||
if (MatrixType::Flags & LowerTriangular)
|
||||
res.Mtype = SLU_TRL;
|
||||
if (MatrixType::Flags & SelfAdjoint)
|
||||
ei_assert(false && "SelfAdjoint matrix shape not supported by SuperLU");
|
||||
return res;
|
||||
}
|
||||
};
|
||||
@@ -133,13 +179,13 @@ struct SluMatrixMapHelper<Matrix<Scalar,Rows,Cols,Options,MRows,MCols> >
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Scalar, int Flags>
|
||||
struct SluMatrixMapHelper<SparseMatrix<Scalar,Flags> >
|
||||
template<typename Derived>
|
||||
struct SluMatrixMapHelper<SparseMatrixBase<Derived> >
|
||||
{
|
||||
typedef SparseMatrix<Scalar,Flags> MatrixType;
|
||||
typedef Derived MatrixType;
|
||||
static void run(MatrixType& mat, SluMatrix& res)
|
||||
{
|
||||
if ((Flags&RowMajorBit)==RowMajorBit)
|
||||
if ((MatrixType::Flags&RowMajorBit)==RowMajorBit)
|
||||
{
|
||||
res.setStorageType(SLU_NR);
|
||||
res.nrow = mat.cols();
|
||||
@@ -159,48 +205,43 @@ struct SluMatrixMapHelper<SparseMatrix<Scalar,Flags> >
|
||||
res.storage.innerInd = mat._innerIndexPtr();
|
||||
res.storage.outerInd = mat._outerIndexPtr();
|
||||
|
||||
res.setScalarType<Scalar>();
|
||||
res.setScalarType<typename MatrixType::Scalar>();
|
||||
|
||||
// FIXME the following is not very accurate
|
||||
if (Flags & UpperTriangular)
|
||||
if (MatrixType::Flags & UpperTriangular)
|
||||
res.Mtype = SLU_TRU;
|
||||
if (Flags & LowerTriangular)
|
||||
if (MatrixType::Flags & LowerTriangular)
|
||||
res.Mtype = SLU_TRL;
|
||||
if (Flags & SelfAdjoint)
|
||||
if (MatrixType::Flags & SelfAdjoint)
|
||||
ei_assert(false && "SelfAdjoint matrix shape not supported by SuperLU");
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Scalar, int Flags>
|
||||
SluMatrix SparseMatrix<Scalar,Flags>::asSluMatrix()
|
||||
template<typename Derived>
|
||||
SluMatrix SparseMatrixBase<Derived>::asSluMatrix()
|
||||
{
|
||||
return SluMatrix::Map(*this);
|
||||
return SluMatrix::Map(derived());
|
||||
}
|
||||
|
||||
template<typename Scalar, int Flags>
|
||||
SparseMatrix<Scalar,Flags> SparseMatrix<Scalar,Flags>::Map(SluMatrix& sluMat)
|
||||
MappedSparseMatrix<Scalar,Flags>::MappedSparseMatrix(SluMatrix& sluMat)
|
||||
{
|
||||
SparseMatrix res;
|
||||
if ((Flags&RowMajorBit)==RowMajorBit)
|
||||
{
|
||||
assert(sluMat.Stype == SLU_NR);
|
||||
res.m_innerSize = sluMat.ncol;
|
||||
res.m_outerSize = sluMat.nrow;
|
||||
m_innerSize = sluMat.ncol;
|
||||
m_outerSize = sluMat.nrow;
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(sluMat.Stype == SLU_NC);
|
||||
res.m_innerSize = sluMat.nrow;
|
||||
res.m_outerSize = sluMat.ncol;
|
||||
m_innerSize = sluMat.nrow;
|
||||
m_outerSize = sluMat.ncol;
|
||||
}
|
||||
res.m_outerIndex = sluMat.storage.outerInd;
|
||||
SparseArray<Scalar> data = SparseArray<Scalar>::Map(
|
||||
sluMat.storage.innerInd,
|
||||
reinterpret_cast<Scalar*>(sluMat.storage.values),
|
||||
sluMat.storage.outerInd[res.m_outerSize]);
|
||||
res.m_data.swap(data);
|
||||
res.markAsRValue();
|
||||
return res;
|
||||
m_outerIndex = sluMat.storage.outerInd;
|
||||
m_innerIndices = sluMat.storage.innerInd;
|
||||
m_values = reinterpret_cast<Scalar*>(sluMat.storage.values);
|
||||
m_nnz = sluMat.storage.outerInd[m_outerSize];
|
||||
}
|
||||
|
||||
template<typename MatrixType>
|
||||
|
||||
@@ -25,8 +25,8 @@
|
||||
#ifndef EIGEN_TAUCSSUPPORT_H
|
||||
#define EIGEN_TAUCSSUPPORT_H
|
||||
|
||||
template<typename Scalar, int Flags>
|
||||
taucs_ccs_matrix SparseMatrix<Scalar,Flags>::asTaucsMatrix()
|
||||
template<typename Derived>
|
||||
taucs_ccs_matrix SparseMatrixBase<Derived>::asTaucsMatrix()
|
||||
{
|
||||
taucs_ccs_matrix res;
|
||||
res.n = cols();
|
||||
@@ -63,19 +63,14 @@ taucs_ccs_matrix SparseMatrix<Scalar,Flags>::asTaucsMatrix()
|
||||
}
|
||||
|
||||
template<typename Scalar, int Flags>
|
||||
SparseMatrix<Scalar,Flags> SparseMatrix<Scalar,Flags>::Map(taucs_ccs_matrix& taucsMat)
|
||||
MappedSparseMatrix<Scalar,Flags>::MappedSparseMatrix(taucs_ccs_matrix& taucsMat)
|
||||
{
|
||||
SparseMatrix res;
|
||||
res.m_innerSize = taucsMat.m;
|
||||
res.m_outerSize = taucsMat.n;
|
||||
res.m_outerIndex = taucsMat.colptr;
|
||||
SparseArray<Scalar> data = SparseArray<Scalar>::Map(
|
||||
taucsMat.rowind,
|
||||
reinterpret_cast<Scalar*>(taucsMat.values.v),
|
||||
taucsMat.colptr[taucsMat.n]);
|
||||
res.m_data.swap(data);
|
||||
res.markAsRValue();
|
||||
return res;
|
||||
m_innerSize = taucsMat.m;
|
||||
m_outerSize = taucsMat.n;
|
||||
m_outerIndex = taucsMat.colptr;
|
||||
m_innerIndices = taucsMat.rowind;
|
||||
m_values = reinterpret_cast<Scalar*>(taucsMat.values.v);
|
||||
m_nnz = taucsMat.colptr[taucsMat.n];
|
||||
}
|
||||
|
||||
template<typename MatrixType>
|
||||
|
||||
@@ -144,4 +144,35 @@ struct ei_solve_triangular_selector<Lhs,Rhs,UpperTriangular,ColMajor|IsSparse>
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Derived>
|
||||
template<typename OtherDerived>
|
||||
void SparseMatrixBase<Derived>::solveTriangularInPlace(MatrixBase<OtherDerived>& other) const
|
||||
{
|
||||
ei_assert(derived().cols() == derived().rows());
|
||||
ei_assert(derived().cols() == other.rows());
|
||||
ei_assert(!(Flags & ZeroDiagBit));
|
||||
ei_assert(Flags & (UpperTriangularBit|LowerTriangularBit));
|
||||
|
||||
enum { copy = ei_traits<OtherDerived>::Flags & RowMajorBit };
|
||||
|
||||
typedef typename ei_meta_if<copy,
|
||||
typename ei_plain_matrix_type_column_major<OtherDerived>::type, OtherDerived&>::ret OtherCopy;
|
||||
OtherCopy otherCopy(other.derived());
|
||||
|
||||
ei_solve_triangular_selector<Derived, typename ei_unref<OtherCopy>::type>::run(derived(), otherCopy);
|
||||
|
||||
if (copy)
|
||||
other = otherCopy;
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
template<typename OtherDerived>
|
||||
typename ei_plain_matrix_type_column_major<OtherDerived>::type
|
||||
SparseMatrixBase<Derived>::solveTriangular(const MatrixBase<OtherDerived>& other) const
|
||||
{
|
||||
typename ei_plain_matrix_type_column_major<OtherDerived>::type res(other);
|
||||
solveTriangularInPlace(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif // EIGEN_SPARSETRIANGULARSOLVER_H
|
||||
|
||||
6
Eigen/src/StdVector/CMakeLists.txt
Normal file
6
Eigen/src/StdVector/CMakeLists.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
FILE(GLOB Eigen_StdVector_SRCS "*.h")
|
||||
|
||||
INSTALL(FILES
|
||||
${Eigen_StdVector_SRCS}
|
||||
DESTINATION ${INCLUDE_INSTALL_DIR}/Eigen/src/StdVector
|
||||
)
|
||||
@@ -32,13 +32,24 @@ template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int
|
||||
class ei_unaligned_type<Matrix<_Scalar,_Rows,_Cols,_Options,_MaxRows,_MaxCols> >
|
||||
: public Matrix<_Scalar,_Rows,_Cols,_Options,_MaxRows,_MaxCols>
|
||||
{
|
||||
private:
|
||||
template<typename Other> void _unaligned_copy(const Other& other)
|
||||
{
|
||||
if(other.size() == 0) return;
|
||||
resize(other.rows(), other.cols());
|
||||
ei_assign_impl<ei_unaligned_type,aligned_base,NoVectorization>::run(*this, other);
|
||||
}
|
||||
|
||||
public:
|
||||
typedef Matrix<_Scalar,_Rows,_Cols,_Options,_MaxRows,_MaxCols> aligned_base;
|
||||
ei_unaligned_type() : aligned_base(ei_constructor_without_unaligned_array_assert()) {}
|
||||
ei_unaligned_type(const aligned_base& other) : aligned_base(ei_constructor_without_unaligned_array_assert())
|
||||
{
|
||||
resize(other.rows(), other.cols());
|
||||
ei_assign_impl<ei_unaligned_type,aligned_base,NoVectorization>::run(*this, other);
|
||||
_unaligned_copy(other);
|
||||
}
|
||||
ei_unaligned_type(const ei_unaligned_type& other) : aligned_base(ei_constructor_without_unaligned_array_assert())
|
||||
{
|
||||
_unaligned_copy(other);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -46,14 +57,23 @@ template<typename _Scalar, int _Dim>
|
||||
class ei_unaligned_type<Transform<_Scalar,_Dim> >
|
||||
: public Transform<_Scalar,_Dim>
|
||||
{
|
||||
private:
|
||||
template<typename Other> void _unaligned_copy(const Other& other)
|
||||
{
|
||||
// no resizing here, it's fixed-size anyway
|
||||
ei_assign_impl<MatrixType,MatrixType,NoVectorization>::run(this->matrix(), other.matrix());
|
||||
}
|
||||
public:
|
||||
typedef Transform<_Scalar,_Dim> aligned_base;
|
||||
typedef typename aligned_base::MatrixType MatrixType;
|
||||
ei_unaligned_type() : aligned_base(ei_constructor_without_unaligned_array_assert()) {}
|
||||
ei_unaligned_type(const aligned_base& other) : aligned_base(ei_constructor_without_unaligned_array_assert())
|
||||
{
|
||||
// no resizing here, it's fixed-size anyway
|
||||
ei_assign_impl<MatrixType,MatrixType,NoVectorization>::run(this->matrix(), other.matrix());
|
||||
_unaligned_copy(other);
|
||||
}
|
||||
ei_unaligned_type(const ei_unaligned_type& other) : aligned_base(ei_constructor_without_unaligned_array_assert())
|
||||
{
|
||||
_unaligned_copy(other);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -61,14 +81,23 @@ template<typename _Scalar>
|
||||
class ei_unaligned_type<Quaternion<_Scalar> >
|
||||
: public Quaternion<_Scalar>
|
||||
{
|
||||
private:
|
||||
template<typename Other> void _unaligned_copy(const Other& other)
|
||||
{
|
||||
// no resizing here, it's fixed-size anyway
|
||||
ei_assign_impl<Coefficients,Coefficients,NoVectorization>::run(this->coeffs(), other.coeffs());
|
||||
}
|
||||
public:
|
||||
typedef Quaternion<_Scalar> aligned_base;
|
||||
typedef typename aligned_base::Coefficients Coefficients;
|
||||
ei_unaligned_type() : aligned_base(ei_constructor_without_unaligned_array_assert()) {}
|
||||
ei_unaligned_type(const aligned_base& other) : aligned_base(ei_constructor_without_unaligned_array_assert())
|
||||
{
|
||||
// no resizing here, it's fixed-size anyway
|
||||
ei_assign_impl<Coefficients,Coefficients,NoVectorization>::run(this->coeffs(), other.coeffs());
|
||||
_unaligned_copy(other);
|
||||
}
|
||||
ei_unaligned_type(const ei_unaligned_type& other) : aligned_base(ei_constructor_without_unaligned_array_assert())
|
||||
{
|
||||
_unaligned_copy(other);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
// to api.kde.org's scripts
|
||||
|
||||
// DOXYGEN_SET_PROJECT_NAME = Eigen2
|
||||
// DOXYGEN_SET_PROJECT_NUMBER = "2.0-beta1"
|
||||
// DOXYGEN_SET_PROJECT_NUMBER = "2.0 - trunk"
|
||||
|
||||
// DOXYGEN_SET_CREATE_SUBDIRS = NO
|
||||
// DOXYGEN_SET_BRIEF_MEMBER_DESC = YES
|
||||
@@ -18,7 +18,7 @@
|
||||
// DOXYGEN_SET_MULTILINE_CPP_IS_BRIEF = NO
|
||||
// DOXYGEN_SET_DETAILS_AT_TOP = YES
|
||||
// DOXYGEN_SET_INHERIT_DOCS = YES
|
||||
// DOXYGEN_SET_ALIASES = "only_for_vectors=This is only for vectors (either row-vectors or column-vectors), i.e. matrices which are known at compile-time to have either one row or one column." "array_module=This is defined in the %Array module. \code #include <Eigen/Array> \endcode" "lu_module=This is defined in the %LU module. \code #include <Eigen/LU> \endcode" "cholesky_module=This is defined in the %Cholesky module. \code #include <Eigen/Cholesky> \endcode" "qr_module=This is defined in the %QR module. \code #include <Eigen/QR> \endcode" "svd_module=This is defined in the %SVD module. \code #include <Eigen/SVD> \endcode" "geometry_module=This is defined in the %Geometry module. \code #include <Eigen/Geometry> \endcode" "regression_module=This is defined in the %Regression module. \code #include <Eigen/Regression> \endcode" "addexample=\anchor" "label=\bug" "redstar=<a href='#warningarraymodule' style='color:red;text-decoration: none;'><span style='color:red'>*</span></a>"
|
||||
// DOXYGEN_SET_ALIASES = "only_for_vectors=This is only for vectors (either row-vectors or column-vectors), i.e. matrices which are known at compile-time to have either one row or one column." "array_module=This is defined in the %Array module. \code #include <Eigen/Array> \endcode" "lu_module=This is defined in the %LU module. \code #include <Eigen/LU> \endcode" "cholesky_module=This is defined in the %Cholesky module. \code #include <Eigen/Cholesky> \endcode" "qr_module=This is defined in the %QR module. \code #include <Eigen/QR> \endcode" "svd_module=This is defined in the %SVD module. \code #include <Eigen/SVD> \endcode" "geometry_module=This is defined in the %Geometry module. \code #include <Eigen/Geometry> \endcode" "leastsquares_module=This is defined in the %LeastSquares module. \code #include <Eigen/LeastSquares> \endcode" "addexample=\anchor" "label=\bug" "redstar=<a href='#warningarraymodule' style='color:red;text-decoration: none;'>*</a>" "nonstableyet=\warning This is not considered to be part of the stable public API yet. Changes may happen in future releases. See \ref Experimental \"Experimental parts of Eigen\""
|
||||
// DOXYGEN_SET_DISTRIBUTE_GROUP_DOC = NO
|
||||
// DOXYGEN_SET_SUBGROUPING = YES
|
||||
// DOXYGEN_SET_TYPEDEF_HIDES_STRUCT = NO
|
||||
@@ -84,7 +84,7 @@
|
||||
// DOXYGEN_SET_MACRO_EXPANSION = YES
|
||||
// DOXYGEN_SET_EXPAND_ONLY_PREDEF = YES
|
||||
// DOXYGEN_SET_SEARCH_INCLUDES = YES
|
||||
// DOXYGEN_SET_PREDEFINED = EIGEN_EMPTY_STRUCT EIGEN_PARSED_BY_DOXYGEN EIGEN_VECTORIZE EIGEN_QT_SUPPORT
|
||||
// DOXYGEN_SET_PREDEFINED = EIGEN_EMPTY_STRUCT EIGEN_PARSED_BY_DOXYGEN EIGEN_VECTORIZE EIGEN_QT_SUPPORT EIGEN_STRONG_INLINE=inline
|
||||
// DOXYGEN_SET_EXPAND_AS_DEFINED = EIGEN_MAKE_SCALAR_OPS EIGEN_MAKE_TYPEDEFS EIGEN_MAKE_TYPEDEFS_ALL_SIZES EIGEN_CWISE_UNOP_RETURN_TYPE EIGEN_CWISE_BINOP_RETURN_TYPE
|
||||
// DOXYGEN_SET_SKIP_FUNCTION_MACROS = YES
|
||||
|
||||
@@ -120,6 +120,6 @@ In order to generate the documentation of Eigen, please follow these steps:
|
||||
After doing that, you will find the HTML documentation in the doc/html/ subdirectory of the build directory.
|
||||
|
||||
<h2>Note however that the documentation is available online here:
|
||||
<a href="http://eigen.tuxfamily.org/api/">http://eigen.tuxfamily.org/api</a></h2>
|
||||
<a href="http://eigen.tuxfamily.org/dox/">http://eigen.tuxfamily.org/dox</a></h2>
|
||||
|
||||
*/
|
||||
|
||||
@@ -21,6 +21,7 @@ USING_PART_OF_NAMESPACE_EIGEN
|
||||
|
||||
typedef SCALAR Scalar;
|
||||
typedef Matrix<Scalar,Dynamic,Dynamic> DenseMatrix;
|
||||
typedef Matrix<Scalar,Dynamic,1> DenseVector;
|
||||
typedef SparseMatrix<Scalar> EigenSparseMatrix;
|
||||
|
||||
void fillMatrix(float density, int rows, int cols, EigenSparseMatrix& dst)
|
||||
@@ -90,5 +91,15 @@ void eiToCSparse(const EigenSparseMatrix& src, cs* &dst)
|
||||
dst = cs_compress(aux);
|
||||
// cs_spfree(aux);
|
||||
}
|
||||
#endif // CSPARSE
|
||||
|
||||
#ifndef NOUBLAS
|
||||
#include <boost/numeric/ublas/vector.hpp>
|
||||
#include <boost/numeric/ublas/matrix.hpp>
|
||||
#include <boost/numeric/ublas/io.hpp>
|
||||
#include <boost/numeric/ublas/triangular.hpp>
|
||||
#include <boost/numeric/ublas/vector_sparse.hpp>
|
||||
#include <boost/numeric/ublas/matrix_sparse.hpp>
|
||||
#include <boost/numeric/ublas/vector_of_vector.hpp>
|
||||
|
||||
#endif
|
||||
|
||||
172
bench/sparse_dense_product.cpp
Normal file
172
bench/sparse_dense_product.cpp
Normal file
@@ -0,0 +1,172 @@
|
||||
|
||||
//g++ -O3 -g0 -DNDEBUG sparse_product.cpp -I.. -I/home/gael/Coding/LinearAlgebra/mtl4/ -DDENSITY=0.005 -DSIZE=10000 && ./a.out
|
||||
//g++ -O3 -g0 -DNDEBUG sparse_product.cpp -I.. -I/home/gael/Coding/LinearAlgebra/mtl4/ -DDENSITY=0.05 -DSIZE=2000 && ./a.out
|
||||
// -DNOGMM -DNOMTL -DCSPARSE
|
||||
// -I /home/gael/Coding/LinearAlgebra/CSparse/Include/ /home/gael/Coding/LinearAlgebra/CSparse/Lib/libcsparse.a
|
||||
#ifndef SIZE
|
||||
#define SIZE 10000
|
||||
#endif
|
||||
|
||||
#ifndef DENSITY
|
||||
#define DENSITY 0.01
|
||||
#endif
|
||||
|
||||
#ifndef REPEAT
|
||||
#define REPEAT 1
|
||||
#endif
|
||||
|
||||
#include "BenchSparseUtil.h"
|
||||
|
||||
#ifndef MINDENSITY
|
||||
#define MINDENSITY 0.0004
|
||||
#endif
|
||||
|
||||
#ifndef NBTRIES
|
||||
#define NBTRIES 10
|
||||
#endif
|
||||
|
||||
#define BENCH(X) \
|
||||
timer.reset(); \
|
||||
for (int _j=0; _j<NBTRIES; ++_j) { \
|
||||
timer.start(); \
|
||||
for (int _k=0; _k<REPEAT; ++_k) { \
|
||||
X \
|
||||
} timer.stop(); }
|
||||
|
||||
|
||||
#ifdef CSPARSE
|
||||
cs* cs_sorted_multiply(const cs* a, const cs* b)
|
||||
{
|
||||
cs* A = cs_transpose (a, 1) ;
|
||||
cs* B = cs_transpose (b, 1) ;
|
||||
cs* D = cs_multiply (B,A) ; /* D = B'*A' */
|
||||
cs_spfree (A) ;
|
||||
cs_spfree (B) ;
|
||||
cs_dropzeros (D) ; /* drop zeros from D */
|
||||
cs* C = cs_transpose (D, 1) ; /* C = D', so that C is sorted */
|
||||
cs_spfree (D) ;
|
||||
return C;
|
||||
}
|
||||
#endif
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int rows = SIZE;
|
||||
int cols = SIZE;
|
||||
float density = DENSITY;
|
||||
|
||||
EigenSparseMatrix sm1(rows,cols);
|
||||
DenseVector v1(cols), v2(cols);
|
||||
v1.setRandom();
|
||||
|
||||
BenchTimer timer;
|
||||
for (float density = DENSITY; density>=MINDENSITY; density*=0.5)
|
||||
{
|
||||
fillMatrix(density, rows, cols, sm1);
|
||||
|
||||
// dense matrices
|
||||
#ifdef DENSEMATRIX
|
||||
{
|
||||
std::cout << "Eigen Dense\t" << density*100 << "%\n";
|
||||
DenseMatrix m1(rows,cols);
|
||||
eiToDense(sm1, m1);
|
||||
|
||||
timer.reset();
|
||||
timer.start();
|
||||
for (int k=0; k<REPEAT; ++k)
|
||||
v2 = m1 * v1;
|
||||
timer.stop();
|
||||
std::cout << " a * v:\t" << timer.value() << endl;
|
||||
|
||||
timer.reset();
|
||||
timer.start();
|
||||
for (int k=0; k<REPEAT; ++k)
|
||||
v2 = m1.transpose() * v1;
|
||||
timer.stop();
|
||||
std::cout << " a' * v:\t" << timer.value() << endl;
|
||||
}
|
||||
#endif
|
||||
|
||||
// eigen sparse matrices
|
||||
{
|
||||
std::cout << "Eigen sparse\t" << sm1.nonZeros()/float(sm1.rows()*sm1.cols())*100 << "%\n";
|
||||
|
||||
BENCH(for (int k=0; k<REPEAT; ++k) v2 = sm1 * v1;)
|
||||
std::cout << " a * v:\t" << timer.value() << endl;
|
||||
|
||||
|
||||
BENCH(for (int k=0; k<REPEAT; ++k) { asm("#mya"); v2 = sm1.transpose() * v1; asm("#myb"); })
|
||||
|
||||
std::cout << " a' * v:\t" << timer.value() << endl;
|
||||
}
|
||||
|
||||
// {
|
||||
// DynamicSparseMatrix<Scalar> m1(sm1);
|
||||
// std::cout << "Eigen dyn-sparse\t" << m1.nonZeros()/float(m1.rows()*m1.cols())*100 << "%\n";
|
||||
//
|
||||
// BENCH(for (int k=0; k<REPEAT; ++k) v2 = m1 * v1;)
|
||||
// std::cout << " a * v:\t" << timer.value() << endl;
|
||||
//
|
||||
// BENCH(for (int k=0; k<REPEAT; ++k) v2 = m1.transpose() * v1;)
|
||||
// std::cout << " a' * v:\t" << timer.value() << endl;
|
||||
// }
|
||||
|
||||
// GMM++
|
||||
#ifndef NOGMM
|
||||
{
|
||||
std::cout << "GMM++ sparse\t" << density*100 << "%\n";
|
||||
//GmmDynSparse gmmT3(rows,cols);
|
||||
GmmSparse m1(rows,cols);
|
||||
eiToGmm(sm1, m1);
|
||||
|
||||
std::vector<Scalar> gmmV1(cols), gmmV2(cols);
|
||||
Map<Matrix<Scalar,Dynamic,1> >(&gmmV1[0], cols) = v1;
|
||||
Map<Matrix<Scalar,Dynamic,1> >(&gmmV2[0], cols) = v2;
|
||||
|
||||
timer.reset();
|
||||
timer.start();
|
||||
for (int k=0; k<REPEAT; ++k)
|
||||
gmm::mult(m1, gmmV1, gmmV2);
|
||||
timer.stop();
|
||||
std::cout << " a * v:\t" << timer.value() << endl;
|
||||
|
||||
timer.reset();
|
||||
timer.start();
|
||||
for (int k=0; k<REPEAT; ++k)
|
||||
gmm::mult(gmm::transposed(m1), gmmV1, gmmV2);
|
||||
timer.stop();
|
||||
std::cout << " a' * v:\t" << timer.value() << endl;
|
||||
}
|
||||
#endif
|
||||
|
||||
// MTL4
|
||||
#ifndef NOMTL
|
||||
{
|
||||
std::cout << "MTL4\t" << density*100 << "%\n";
|
||||
MtlSparse m1(rows,cols);
|
||||
eiToMtl(sm1, m1);
|
||||
mtl::dense_vector<Scalar> mtlV1(cols, 1.0);
|
||||
mtl::dense_vector<Scalar> mtlV2(cols, 1.0);
|
||||
|
||||
timer.reset();
|
||||
timer.start();
|
||||
for (int k=0; k<REPEAT; ++k)
|
||||
mtlV2 = m1 * mtlV1;
|
||||
timer.stop();
|
||||
std::cout << " a * v:\t" << timer.value() << endl;
|
||||
|
||||
timer.reset();
|
||||
timer.start();
|
||||
for (int k=0; k<REPEAT; ++k)
|
||||
mtlV2 = trans(m1) * mtlV1;
|
||||
timer.stop();
|
||||
std::cout << " a' * v:\t" << timer.value() << endl;
|
||||
}
|
||||
#endif
|
||||
|
||||
std::cout << "\n\n";
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -137,6 +137,44 @@ int main(int argc, char *argv[])
|
||||
// timer.stop();
|
||||
std::cout << " a * b' :\t" << timer.value() << endl;
|
||||
}
|
||||
|
||||
// eigen dyn-sparse matrices
|
||||
{
|
||||
DynamicSparseMatrix<Scalar> m1(sm1), m2(sm2), m3(sm3);
|
||||
std::cout << "Eigen dyn-sparse\t" << m1.nonZeros()/float(m1.rows()*m1.cols())*100 << "% * "
|
||||
<< m2.nonZeros()/float(m2.rows()*m2.cols())*100 << "%\n";
|
||||
|
||||
// timer.reset();
|
||||
// timer.start();
|
||||
BENCH(for (int k=0; k<REPEAT; ++k) m3 = m1 * m2;)
|
||||
// timer.stop();
|
||||
std::cout << " a * b:\t" << timer.value() << endl;
|
||||
// std::cout << sm3 << "\n";
|
||||
|
||||
timer.reset();
|
||||
timer.start();
|
||||
// std::cerr << "transpose...\n";
|
||||
// EigenSparseMatrix sm4 = sm1.transpose();
|
||||
// std::cout << sm4.nonZeros() << " == " << sm1.nonZeros() << "\n";
|
||||
// exit(1);
|
||||
// std::cerr << "transpose OK\n";
|
||||
// std::cout << sm1 << "\n\n" << sm1.transpose() << "\n\n" << sm4.transpose() << "\n\n";
|
||||
BENCH(for (int k=0; k<REPEAT; ++k) m3 = m1.transpose() * m2;)
|
||||
// timer.stop();
|
||||
std::cout << " a' * b:\t" << timer.value() << endl;
|
||||
|
||||
// timer.reset();
|
||||
// timer.start();
|
||||
BENCH( for (int k=0; k<REPEAT; ++k) m3 = m1.transpose() * m2.transpose(); )
|
||||
// timer.stop();
|
||||
std::cout << " a' * b':\t" << timer.value() << endl;
|
||||
|
||||
// timer.reset();
|
||||
// timer.start();
|
||||
BENCH( for (int k=0; k<REPEAT; ++k) m3 = m1 * m2.transpose(); )
|
||||
// timer.stop();
|
||||
std::cout << " a * b' :\t" << timer.value() << endl;
|
||||
}
|
||||
|
||||
// CSparse
|
||||
#ifdef CSPARSE
|
||||
|
||||
297
bench/sparse_setter.cpp
Normal file
297
bench/sparse_setter.cpp
Normal file
@@ -0,0 +1,297 @@
|
||||
|
||||
//g++ -O3 -g0 -DNDEBUG sparse_product.cpp -I.. -I/home/gael/Coding/LinearAlgebra/mtl4/ -DDENSITY=0.005 -DSIZE=10000 && ./a.out
|
||||
//g++ -O3 -g0 -DNDEBUG sparse_product.cpp -I.. -I/home/gael/Coding/LinearAlgebra/mtl4/ -DDENSITY=0.05 -DSIZE=2000 && ./a.out
|
||||
// -DNOGMM -DNOMTL -DCSPARSE
|
||||
// -I /home/gael/Coding/LinearAlgebra/CSparse/Include/ /home/gael/Coding/LinearAlgebra/CSparse/Lib/libcsparse.a
|
||||
#ifndef SIZE
|
||||
#define SIZE 100000
|
||||
#endif
|
||||
|
||||
#ifndef NBPERROW
|
||||
#define NBPERROW 24
|
||||
#endif
|
||||
|
||||
#ifndef REPEAT
|
||||
#define REPEAT 1
|
||||
#endif
|
||||
|
||||
#ifndef NOGOOGLE
|
||||
#define EIGEN_GOOGLEHASH_SUPPORT
|
||||
#include <google/sparse_hash_map>
|
||||
#endif
|
||||
|
||||
#include "BenchSparseUtil.h"
|
||||
|
||||
#define CHECK_MEM
|
||||
// #define CHECK_MEM std/**/::cout << "check mem\n"; getchar();
|
||||
|
||||
#define BENCH(X) \
|
||||
timer.reset(); \
|
||||
for (int _j=0; _j<NBTRIES; ++_j) { \
|
||||
timer.start(); \
|
||||
for (int _k=0; _k<REPEAT; ++_k) { \
|
||||
X \
|
||||
} timer.stop(); }
|
||||
|
||||
typedef std::vector<Vector2i> Coordinates;
|
||||
typedef std::vector<float> Values;
|
||||
|
||||
EIGEN_DONT_INLINE Scalar* setinnerrand_eigen(const Coordinates& coords, const Values& vals);
|
||||
EIGEN_DONT_INLINE Scalar* setrand_eigen_gnu_hash(const Coordinates& coords, const Values& vals);
|
||||
EIGEN_DONT_INLINE Scalar* setrand_eigen_google_dense(const Coordinates& coords, const Values& vals);
|
||||
EIGEN_DONT_INLINE Scalar* setrand_eigen_google_sparse(const Coordinates& coords, const Values& vals);
|
||||
EIGEN_DONT_INLINE Scalar* setrand_ublas_mapped(const Coordinates& coords, const Values& vals);
|
||||
EIGEN_DONT_INLINE Scalar* setrand_ublas_coord(const Coordinates& coords, const Values& vals);
|
||||
EIGEN_DONT_INLINE Scalar* setrand_ublas_compressed(const Coordinates& coords, const Values& vals);
|
||||
EIGEN_DONT_INLINE Scalar* setrand_ublas_genvec(const Coordinates& coords, const Values& vals);
|
||||
EIGEN_DONT_INLINE Scalar* setrand_mtl(const Coordinates& coords, const Values& vals);
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int rows = SIZE;
|
||||
int cols = SIZE;
|
||||
bool fullyrand = false;
|
||||
//float density = float(NBPERROW)/float(SIZE);
|
||||
|
||||
BenchTimer timer;
|
||||
Coordinates coords;
|
||||
Values values;
|
||||
if(fullyrand)
|
||||
{
|
||||
for (int i=0; i<cols*NBPERROW; ++i)
|
||||
{
|
||||
coords.push_back(Vector2i(ei_random<int>(0,rows-1),ei_random<int>(0,cols-1)));
|
||||
values.push_back(ei_random<Scalar>());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int j=0; j<cols; ++j)
|
||||
for (int i=0; i<NBPERROW; ++i)
|
||||
{
|
||||
coords.push_back(Vector2i(ei_random<int>(0,rows-1),j));
|
||||
values.push_back(ei_random<Scalar>());
|
||||
}
|
||||
}
|
||||
std::cout << "nnz = " << coords.size() << "\n";
|
||||
CHECK_MEM
|
||||
|
||||
// dense matrices
|
||||
#ifdef DENSEMATRIX
|
||||
{
|
||||
timer.reset();
|
||||
timer.start();
|
||||
for (int k=0; k<REPEAT; ++k)
|
||||
setrand_eigen_dense(coords,values);
|
||||
timer.stop();
|
||||
std::cout << "Eigen Dense\t" << timer.value() << "\n";
|
||||
}
|
||||
#endif
|
||||
|
||||
// eigen sparse matrices
|
||||
if (!fullyrand)
|
||||
{
|
||||
timer.reset();
|
||||
timer.start();
|
||||
for (int k=0; k<REPEAT; ++k)
|
||||
setinnerrand_eigen(coords,values);
|
||||
timer.stop();
|
||||
std::cout << "Eigen fillrand\t" << timer.value() << "\n";
|
||||
}
|
||||
{
|
||||
timer.reset();
|
||||
timer.start();
|
||||
for (int k=0; k<REPEAT; ++k)
|
||||
setrand_eigen_gnu_hash(coords,values);
|
||||
timer.stop();
|
||||
std::cout << "Eigen std::map\t" << timer.value() << "\n";
|
||||
}
|
||||
#ifndef NOGOOGLE
|
||||
{
|
||||
timer.reset();
|
||||
timer.start();
|
||||
for (int k=0; k<REPEAT; ++k)
|
||||
setrand_eigen_google_dense(coords,values);
|
||||
timer.stop();
|
||||
std::cout << "Eigen google dense\t" << timer.value() << "\n";
|
||||
}
|
||||
{
|
||||
timer.reset();
|
||||
timer.start();
|
||||
for (int k=0; k<REPEAT; ++k)
|
||||
setrand_eigen_google_sparse(coords,values);
|
||||
timer.stop();
|
||||
std::cout << "Eigen google sparse\t" << timer.value() << "\n";
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef NOUBLAS
|
||||
{
|
||||
timer.reset();
|
||||
timer.start();
|
||||
for (int k=0; k<REPEAT; ++k)
|
||||
setrand_ublas_mapped(coords,values);
|
||||
timer.stop();
|
||||
std::cout << "ublas mapped\t" << timer.value() << "\n";
|
||||
}
|
||||
{
|
||||
timer.reset();
|
||||
timer.start();
|
||||
for (int k=0; k<REPEAT; ++k)
|
||||
setrand_ublas_genvec(coords,values);
|
||||
timer.stop();
|
||||
std::cout << "ublas vecofvec\t" << timer.value() << "\n";
|
||||
}
|
||||
/*{
|
||||
timer.reset();
|
||||
timer.start();
|
||||
for (int k=0; k<REPEAT; ++k)
|
||||
setrand_ublas_compressed(coords,values);
|
||||
timer.stop();
|
||||
std::cout << "ublas comp\t" << timer.value() << "\n";
|
||||
}
|
||||
{
|
||||
timer.reset();
|
||||
timer.start();
|
||||
for (int k=0; k<REPEAT; ++k)
|
||||
setrand_ublas_coord(coords,values);
|
||||
timer.stop();
|
||||
std::cout << "ublas coord\t" << timer.value() << "\n";
|
||||
}*/
|
||||
#endif
|
||||
|
||||
|
||||
// MTL4
|
||||
#ifndef NOMTL
|
||||
{
|
||||
timer.reset();
|
||||
timer.start();
|
||||
for (int k=0; k<REPEAT; ++k)
|
||||
setrand_mtl(coords,values);
|
||||
timer.stop();
|
||||
std::cout << "MTL\t" << timer.value() << "\n";
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
EIGEN_DONT_INLINE Scalar* setinnerrand_eigen(const Coordinates& coords, const Values& vals)
|
||||
{
|
||||
using namespace Eigen;
|
||||
SparseMatrix<Scalar> mat(SIZE,SIZE);
|
||||
mat.startFill(2000000/*coords.size()*/);
|
||||
for (int i=0; i<coords.size(); ++i)
|
||||
{
|
||||
mat.fillrand(coords[i].x(), coords[i].y()) = vals[i];
|
||||
}
|
||||
mat.endFill();
|
||||
CHECK_MEM;
|
||||
return 0;
|
||||
}
|
||||
|
||||
EIGEN_DONT_INLINE Scalar* setrand_eigen_gnu_hash(const Coordinates& coords, const Values& vals)
|
||||
{
|
||||
using namespace Eigen;
|
||||
SparseMatrix<Scalar> mat(SIZE,SIZE);
|
||||
{
|
||||
RandomSetter<SparseMatrix<Scalar>, StdMapTraits > setter(mat);
|
||||
for (int i=0; i<coords.size(); ++i)
|
||||
{
|
||||
setter(coords[i].x(), coords[i].y()) = vals[i];
|
||||
}
|
||||
CHECK_MEM;
|
||||
}
|
||||
return 0;//&mat.coeffRef(coords[0].x(), coords[0].y());
|
||||
}
|
||||
|
||||
#ifndef NOGOOGLE
|
||||
EIGEN_DONT_INLINE Scalar* setrand_eigen_google_dense(const Coordinates& coords, const Values& vals)
|
||||
{
|
||||
using namespace Eigen;
|
||||
SparseMatrix<Scalar> mat(SIZE,SIZE);
|
||||
{
|
||||
RandomSetter<SparseMatrix<Scalar>, GoogleDenseHashMapTraits> setter(mat);
|
||||
for (int i=0; i<coords.size(); ++i)
|
||||
setter(coords[i].x(), coords[i].y()) = vals[i];
|
||||
CHECK_MEM;
|
||||
}
|
||||
return 0;//&mat.coeffRef(coords[0].x(), coords[0].y());
|
||||
}
|
||||
|
||||
EIGEN_DONT_INLINE Scalar* setrand_eigen_google_sparse(const Coordinates& coords, const Values& vals)
|
||||
{
|
||||
using namespace Eigen;
|
||||
SparseMatrix<Scalar> mat(SIZE,SIZE);
|
||||
{
|
||||
RandomSetter<SparseMatrix<Scalar>, GoogleSparseHashMapTraits> setter(mat);
|
||||
for (int i=0; i<coords.size(); ++i)
|
||||
setter(coords[i].x(), coords[i].y()) = vals[i];
|
||||
CHECK_MEM;
|
||||
}
|
||||
return 0;//&mat.coeffRef(coords[0].x(), coords[0].y());
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef NOUBLAS
|
||||
EIGEN_DONT_INLINE Scalar* setrand_ublas_mapped(const Coordinates& coords, const Values& vals)
|
||||
{
|
||||
using namespace boost;
|
||||
using namespace boost::numeric;
|
||||
using namespace boost::numeric::ublas;
|
||||
mapped_matrix<Scalar> aux(SIZE,SIZE);
|
||||
for (int i=0; i<coords.size(); ++i)
|
||||
{
|
||||
aux(coords[i].x(), coords[i].y()) = vals[i];
|
||||
}
|
||||
CHECK_MEM;
|
||||
compressed_matrix<Scalar> mat(aux);
|
||||
return 0;// &mat(coords[0].x(), coords[0].y());
|
||||
}
|
||||
/*EIGEN_DONT_INLINE Scalar* setrand_ublas_coord(const Coordinates& coords, const Values& vals)
|
||||
{
|
||||
using namespace boost;
|
||||
using namespace boost::numeric;
|
||||
using namespace boost::numeric::ublas;
|
||||
coordinate_matrix<Scalar> aux(SIZE,SIZE);
|
||||
for (int i=0; i<coords.size(); ++i)
|
||||
{
|
||||
aux(coords[i].x(), coords[i].y()) = vals[i];
|
||||
}
|
||||
compressed_matrix<Scalar> mat(aux);
|
||||
return 0;//&mat(coords[0].x(), coords[0].y());
|
||||
}
|
||||
EIGEN_DONT_INLINE Scalar* setrand_ublas_compressed(const Coordinates& coords, const Values& vals)
|
||||
{
|
||||
using namespace boost;
|
||||
using namespace boost::numeric;
|
||||
using namespace boost::numeric::ublas;
|
||||
compressed_matrix<Scalar> mat(SIZE,SIZE);
|
||||
for (int i=0; i<coords.size(); ++i)
|
||||
{
|
||||
mat(coords[i].x(), coords[i].y()) = vals[i];
|
||||
}
|
||||
return 0;//&mat(coords[0].x(), coords[0].y());
|
||||
}*/
|
||||
EIGEN_DONT_INLINE Scalar* setrand_ublas_genvec(const Coordinates& coords, const Values& vals)
|
||||
{
|
||||
using namespace boost;
|
||||
using namespace boost::numeric;
|
||||
using namespace boost::numeric::ublas;
|
||||
|
||||
// ublas::vector<coordinate_vector<Scalar> > foo;
|
||||
generalized_vector_of_vector<Scalar, row_major, ublas::vector<coordinate_vector<Scalar> > > aux(SIZE,SIZE);
|
||||
for (int i=0; i<coords.size(); ++i)
|
||||
{
|
||||
aux(coords[i].x(), coords[i].y()) = vals[i];
|
||||
}
|
||||
CHECK_MEM;
|
||||
compressed_matrix<Scalar,row_major> mat(aux);
|
||||
return 0;//&mat(coords[0].x(), coords[0].y());
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef NOMTL
|
||||
EIGEN_DONT_INLINE void setrand_mtl(const Coordinates& coords, const Values& vals);
|
||||
#endif
|
||||
|
||||
@@ -113,6 +113,17 @@ ELSE(WIN32)
|
||||
EXEC_PROGRAM(${GSL_CONFIG}
|
||||
ARGS --libs
|
||||
OUTPUT_VARIABLE GSL_CONFIG_LIBS )
|
||||
|
||||
# extract version
|
||||
EXEC_PROGRAM(${GSL_CONFIG}
|
||||
ARGS --version
|
||||
OUTPUT_VARIABLE GSL_FULL_VERSION )
|
||||
|
||||
# split version as major/minor
|
||||
STRING(REGEX MATCH "(.)\\..*" GSL_VERSION_MAJOR_ "${GSL_FULL_VERSION}")
|
||||
SET(GSL_VERSION_MAJOR ${CMAKE_MATCH_1})
|
||||
STRING(REGEX MATCH ".\\.(.*)" GSL_VERSION_MINOR_ "${GSL_FULL_VERSION}")
|
||||
SET(GSL_VERSION_MINOR ${CMAKE_MATCH_1})
|
||||
|
||||
# split off the link dirs (for rpath)
|
||||
# use regular expression to match wildcard equivalent "-L*<endchar>"
|
||||
|
||||
@@ -10,7 +10,14 @@ find_path(GOOGLEHASH_INCLUDES
|
||||
${INCLUDE_INSTALL_DIR}
|
||||
)
|
||||
|
||||
if(GOOGLEHASH_INCLUDES)
|
||||
# let's make sure it compiles with the current compiler
|
||||
file(WRITE ${CMAKE_BINARY_DIR}/googlehash_test.cpp
|
||||
"#include <google/sparse_hash_map>\n#include <google/dense_hash_map>\nint main(int argc, char** argv) { google::dense_hash_map<int,float> a; google::sparse_hash_map<int,float> b; return 0;}\n")
|
||||
try_compile(GOOGLEHASH_COMPILE ${CMAKE_BINARY_DIR} ${CMAKE_BINARY_DIR}/googlehash_test.cpp OUTPUT_VARIABLE GOOGLEHASH_COMPILE_RESULT)
|
||||
endif(GOOGLEHASH_INCLUDES)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(GOOGLEHASH DEFAULT_MSG GOOGLEHASH_INCLUDES)
|
||||
find_package_handle_standard_args(GOOGLEHASH DEFAULT_MSG GOOGLEHASH_INCLUDES GOOGLEHASH_COMPILE)
|
||||
|
||||
mark_as_advanced(GOOGLEHASH_INCLUDES)
|
||||
|
||||
@@ -16,10 +16,6 @@ if(BLAS_FOUND)
|
||||
)
|
||||
|
||||
find_library(SUPERLU_LIBRARIES superlu PATHS $ENV{SUPERLUDIR} ${LIB_INSTALL_DIR})
|
||||
|
||||
if(SUPERLU_LIBRARIES AND CMAKE_COMPILER_IS_GNUCXX)
|
||||
set(SUPERLU_LIBRARIES ${SUPERLU_LIBRARIES} -lgfortran)
|
||||
endif(SUPERLU_LIBRARIES AND CMAKE_COMPILER_IS_GNUCXX)
|
||||
|
||||
if(SUPERLU_LIBRARIES)
|
||||
set(SUPERLU_LIBRARIES ${SUPERLU_LIBRARIES} ${BLAS_LIBRARIES})
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user