36 typedef gsEigen::Triplet<T,index_t> Triplet;
37 typedef std::vector<gsEigen::Triplet<T,index_t> > Base;
39 typedef typename Base::iterator iterator;
42 inline void add(
int i,
int j, T value )
43 { this->push_back( Triplet(i,j,value) ); }
45 inline void addSorted(
int i,
int j, T value = 0)
48 iterator pos = std::lower_bound(Base::begin(), Base::end(), t, compTriplet );
49 if ( pos == Base::end() || (pos->row() != t.row() && pos->col() !=t.col()) )
57 bool operator() (
const Triplet & left,
const Triplet & right)
59 return (left.col() < right.col()) ||
60 (left.col() == right.col() && left.row() < right.row()) ;
72template<
typename T,
int _Options,
typename _Index>
75 typedef gsEigen::SparseMatrix<T,_Options,_Index> SparseMatrix;
76 static const int IsRowMajor = SparseMatrix::IsRowMajor;
80 : m_values(NULL), m_indices(NULL),
81 m_end(NULL) , m_outer(0)
87 const _Index oind = mat.outerIndexPtr()[outer];
88 m_values = mat.valuePtr() + oind;
89 m_indices = mat.innerIndexPtr() + oind;
90 m_end = mat.isCompressed() ?
91 mat.innerIndexPtr() + mat.outerIndexPtr()[outer+1] :
92 mat.innerIndexPtr() + oind + mat.innerNonZeroPtr()[outer];
96 { ++m_values; ++m_indices;
return *
this; }
98 inline const T& value()
const {
return *m_values; }
99 inline T& valueRef() {
return const_cast<T&
>(*m_values); }
101 inline _Index index()
const {
return *m_indices; }
102 inline _Index outer()
const {
return m_outer; }
103 inline _Index row()
const {
return IsRowMajor ? m_outer : index(); }
104 inline _Index col()
const {
return IsRowMajor ? index() : m_outer; }
106 inline operator bool()
const {
return (m_indices < m_end); }
110 const _Index * m_indices;
111 const _Index * m_end;
137template<
typename T,
int _Options,
typename _Index>
141 typedef gsEigen::SparseMatrix<T,_Options,_Index> Base;
146 typedef typename gsEigen::Block<Base> Block;
149 typedef typename gsEigen::Block<const Base> constBlock;
158 typedef memory::shared_ptr<gsSparseMatrix>
Ptr;
161 typedef memory::unique_ptr<gsSparseMatrix>
uPtr;
165 typedef typename gsEigen::SparseSelfAdjointView<Base, Lower>
fullView;
169 typedef typename gsEigen::SparseSelfAdjointView<const Base, Lower>
constFullView;
177 template<
typename OtherDerived>
181 template<
typename OtherDerived,
unsigned int UpLo>
186 template<
typename OtherDerived>
190 template<
typename OtherDerived>
191 gsSparseMatrix(
const gsEigen::SparseMatrixBase<OtherDerived>& other) : Base(other) { }
194 template<
typename OtherDerived>
195 gsSparseMatrix(
const gsEigen::ReturnByValue<OtherDerived>& other) : Base(other) { }
197#if !EIGEN_HAS_RVALUE_REFERENCES
205 template<
typename OtherDerived,
int a>
206 gsSparseMatrix & operator=(
const gsEigen::SparseSymmetricPermutationProduct<OtherDerived, a>& other)
208 this->Base::operator=(other);
213 template <
class EigenExpr>
214 gsSparseMatrix& operator= (
const EigenExpr & other)
216 this->Base::operator=(other);
220 using Base::operator=;
225 gsSparseMatrix(
const gsSparseMatrix& other) : Base(other)
226 { Base::operator=(other); }
227 gsSparseMatrix& operator= (
const gsSparseMatrix & other)
228 { Base::operator=(other);
return *
this; }
230 gsSparseMatrix(gsSparseMatrix&& other)
231 { gsSparseMatrix::operator=(std::forward<gsSparseMatrix>(other)); }
233 gsSparseMatrix & operator=(gsSparseMatrix&& other)
261 this->data().squeeze();
264 std::pair<index_t,index_t> dim()
const
265 {
return std::make_pair(this->rows(), this->cols() ); }
267 void reservePerColumn(
const index_t nz)
269 Base::reserve(gsVector<index_t>::Constant(this->outerSize(), nz));
272 void setFrom( gsSparseEntries<T>
const & entries) ;
274 inline T at (_Index i, _Index j )
const {
return this->coeff(i,j); }
275 inline T & at (_Index i, _Index j ) {
return this->coeffRef(i,j); }
277 inline T operator () (_Index i, _Index j )
const {
return this->coeff(i,j); }
278 inline T & operator () (_Index i, _Index j ) {
return this->coeffRef(i,j); }
282 inline void addTo(_Index i, _Index j,
const T val)
284 if (0!=val) this->coeffRef(i,j) += val;
289 inline void insertTo(_Index i, _Index j,
const T val)
292 this->insert(i,j) = val;
295 inline bool isExplicitZero(_Index row, _Index col)
const
297 const _Index outer = gsSparseMatrix::IsRowMajor ? row : col;
298 const _Index inner = gsSparseMatrix::IsRowMajor ? col : row;
299 const _Index end = this->m_innerNonZeros ?
300 this->m_outerIndex[outer] + this->m_innerNonZeros[outer] : this->m_outerIndex[outer+1];
301 const _Index
id = this->m_data.searchLowerIndex(this->m_outerIndex[outer], end-1, inner);
302 return !((
id<end) && ( this->m_data.index(
id)==inner));
308 GISMO_ASSERT(row>=0 && row<this->rows() && col>=0 && col<this->cols(),
"Invalid row/col index.");
309 const _Index outer = gsSparseMatrix::IsRowMajor ? row : col;
310 const _Index inner = gsSparseMatrix::IsRowMajor ? col : row;
311 const _Index start = this->m_outerIndex[outer];
312 const _Index end = this->m_innerNonZeros ?
313 this->m_outerIndex[outer] + this->m_innerNonZeros[outer] : this->m_outerIndex[outer+1];
315 { this->insert(row,col);
return; }
316 const _Index p = this->m_data.searchLowerIndex(start,end-1,inner);
317 if(! ((p<end) && (this->m_data.index(p)==inner)) )
318 this->insert(row,col);
321 inline T& coeffUpdate(_Index row, _Index col)
323 GISMO_ASSERT(row>=0 && row<this->rows() && col>=0 && col<this->cols(),
"Invalid row/col index.");
324 const _Index outer = gsSparseMatrix::IsRowMajor ? row : col;
325 _Index start = this->m_outerIndex[outer];
326 _Index end = this->m_innerNonZeros ? this->m_outerIndex[outer] + this->m_innerNonZeros[outer]
327 : this->m_outerIndex[outer+1];
328 const _Index inner = gsSparseMatrix::IsRowMajor ? col : row;
329 const _Index p = this->m_data.searchLowerIndex(start,end-1,inner);
330 if((p<end) && (this->m_data.index(p)==inner))
331 return this->m_data.value(p);
332 GISMO_ERROR(
"(row,col) = ("<< row <<
","<<col<<
") is not in the matrix (sparsity pattern).");
339 return BlockView(*
this, rowSizes, colSizes);
354 if ( this->isCompressed() )
356 gsWarn<<
"nonZerosPerCol(): Uncompressing the gsSparseMatrix.\n";
362 std::string printSparsity()
const
364 std::ostringstream os;
365 os <<
"Sparsity: "<< std::fixed << std::setprecision(2)
366 <<(double)100*this->nonZeros()/this->size() <<
'%'<<
", nnz: "<<this->size() <<
"\n";
367 for (
index_t i = 0; i!=this->rows(); ++i)
369 for (
index_t j = 0; j!=this->cols(); ++j)
370 os << ( isExplicitZero(i,j) ?
"\u00B7" :
371 ( 0 == this->coeff(i,j) ?
"o" :
"x") );
386 template<
class container>
387 container
innerOf(
const container & outer)
const
389 std::vector<bool> v(this->innerSize(),
false);
391 for (
typename container::const_iterator k =
392 outer.begin(); k!=outer.end(); ++k )
393 for( mIt = this->
begin(*k); mIt; ++mIt)
394 v[mIt.index()] = (0!=mIt.value());
397 inner.reserve( std::count(v.begin(), v.end(),
true) );
398 std::vector<bool>::iterator it = std::find(v.begin(),v.end(),
true);
399 while (v.end() != it)
401 inner.push_back(std::distance(v.begin(),it));
402 it = std::find(++it,v.end(),
true);
409 template<
class container>
411 const container & outer,
420 template<
class container>
422 const container & outer)
const
424 const index_t nr = inner.size();
425 const index_t nc = outer.size();
431 for (
index_t r=0; r!=nr && it;)
434 while(it && inner[r] > it.index()) ++it;
435 if (it)
while(r!=nr && inner[r] < it.index()) ++r;
438 result(r,c) = it.value();
448 upto = math::min(upto, this->outerSize());
451 for (
index_t i = 0; i != upto; ++i, ++v)
452 *v = this->innerVector(i).nonZeros();
459 const index_t r = this->rows(), c = this->cols();
460 const index_t ro = other.rows(), co = other.cols();
462 if (0 == result.size())
return result;
463 result.reserve(this->nonZerosPerInner()
464 .
kron(other.nonZerosPerInner()));
467 for (
index_t k1=0; k1 != (gsSparseMatrix::IsRowMajor?r:c); ++k1)
468 for (it1 = this->
begin(k1); it1; ++it1)
469 for (
index_t k2=0; k2 != (gsSparseMatrix::IsRowMajor?ro:co); ++k2)
470 for (it2 = other.
begin(k2); it2; ++it2)
472 const index_t i = it1.row() * ro + it2.row();
473 const index_t j = it1.col() * co + it2.col();
474 result.insert(i,j) = it1.value() * it2.value();
476 result.makeCompressed();
499template<
typename T,
int _Options,
typename _Index>
inline
500gsSparseMatrix<T, _Options, _Index>::gsSparseMatrix() : Base() { }
502template<
typename T,
int _Options,
typename _Index>
inline
503gsSparseMatrix<T, _Options, _Index>::gsSparseMatrix(_Index rows, _Index cols) : Base(rows,cols) { }
505template<
typename T,
int _Options,
typename _Index>
inline
506void gsSparseMatrix<T, _Options, _Index>::setFrom( gsSparseEntries<T>
const & entries)
507{ this->setFromTriplets(entries.begin(),entries.end() ); }
509template<
typename T,
int _Options,
typename _Index>
void
514 const index_t nr = this->rows();
515 const index_t nc = this->cols();
519 for (
index_t i = 0; i!=nr; ++i)
527 R.tail(nc-c_j) -= R.
at(c_j) * this->row(j).tail(nc-c_j);
531 c_i = 0;
while (c_i!= nc && 0 == R.
at(c_i)) ++c_i;
533 if (c_i == nc )
continue;
534 R.tail(nc-c_i-1).array() /= R.
at(c_i);
537 this->row(i) = R.sparseView();
548 for(
index_t i=0; i != c_j; i++)
549 if( piv[i] > piv[i+1] )
551 std::swap(piv[i], piv[i+1]);
561 for (
index_t i = 0; i!=nr; ++i)
566 if (c_i == nc )
break;
568 for (
index_t j = i+1; j!=nr; ++j)
571 if ( c_j == nc )
break;
572 R.tail(nc-c_j) -= R.
at(c_j) * this->row(j).tail(nc-c_j);
575 this->row(i) = R.sparseView();
579#ifdef GISMO_WITH_PYBIND11
585 void pybind11_init_gsSparseMatrix(pybind11::module &m,
const std::string & typestr)
588 std::string pyclass_name = std::string(
"gsSparseMatrix") + typestr;
589 pybind11::class_<Class>(m, pyclass_name.c_str(), pybind11::buffer_protocol(), pybind11::dynamic_attr())
591 .def(pybind11::init<>())
592 .def(pybind11::init<index_t, index_t>())
594 .def(
"size", &Class::size)
595 .def(
"rows", &Class::rows)
596 .def(
"cols", &Class::cols)
600 .def(
"toDense", &Class::toDense)
609namespace gsEigen {
namespace internal {
610template<
typename T,
int _Options,
typename _Index>
611struct traits<
gismo::gsSparseMatrix<T,_Options,_Index> >:
612gsEigen::internal::traits<gsEigen::SparseMatrix<T,_Options,_Index> > { };
Creates a mapped object or data pointer to a const vector without copying data.
Definition gsAsMatrix.h:285
Represents a block-view of the given matrix.
Definition gsMatrixBlockView.h:32
A matrix with arbitrary coefficient type and fixed or dynamic size.
Definition gsMatrix.h:41
T at(index_t i) const
Returns the i-th element of the vectorization of the matrix.
Definition gsMatrix.h:211
Class that provides a container for triplets (i,j,value) to be filled in a sparse matrix.
Definition gsSparseMatrix.h:34
Iterator over the non-zero entries of a sparse matrix.
Definition gsSparseMatrix.h:74
Sparse matrix class, based on gsEigen::SparseMatrix.
Definition gsSparseMatrix.h:139
gsSparseMatrix kron(const gsSparseMatrix &other) const
Returns the Kronecker product of this with other.
Definition gsSparseMatrix.h:457
gsSparseMatrix(const gsEigen::MatrixBase< OtherDerived > &other)
This constructor allows constructing a gsSparseMatrix from Eigen expressions.
Definition gsSparseMatrix.h:187
uPtr moveToPtr()
This function returns a smart pointer to the matrix. After calling it, the matrix object becomes empt...
Definition gsSparseMatrix.h:247
gsMatrix< T > multiplyBy(const container &inner, const container &outer, const gsMatrix< T > &other)
Definition gsSparseMatrix.h:410
gsAsConstVector< _Index > nonZerosPerCol()
Definition gsSparseMatrix.h:352
gsSparseMatrix(const gsEigen::ReturnByValue< OtherDerived > &other)
This constructor allows constructing a gsSparseMatrix from Eigen expressions.
Definition gsSparseMatrix.h:195
memory::shared_ptr< gsSparseMatrix > Ptr
Shared pointer for gsSparseMatrix.
Definition gsSparseMatrix.h:158
constBlockView blockView(const gsVector< index_t > &rowSizes, const gsVector< index_t > &colSizes) const
Return a const block view of the matrix with rowSizes and colSizes.
Definition gsSparseMatrix.h:343
gsMatrix< T > submatrix(const container &inner, const container &outer) const
Definition gsSparseMatrix.h:421
memory::unique_ptr< gsSparseMatrix > uPtr
Unique pointer for gsSparseMatrix.
Definition gsSparseMatrix.h:161
iterator begin(const index_t outer) const
Returns an iterator to the first non-zero elemenent of column \ a outer (or row outer if the matrix i...
Definition gsSparseMatrix.h:256
void insertExplicitZero(_Index row, _Index col)
Adds an explicit zero, only if (row,col) is not in the matrix.
Definition gsSparseMatrix.h:306
void addTo(_Index i, _Index j, const T val)
Definition gsSparseMatrix.h:282
void rrefInPlace()
Allocates the sparsity pattern.
Definition gsSparseMatrix.h:510
gsEigen::SparseSelfAdjointView< Base, Lower > fullView
Definition gsSparseMatrix.h:165
gsSparseMatrix(const gsEigen::SparseSelfAdjointView< OtherDerived, UpLo > &other)
This constructor allows constructing a gsSparseMatrix from a selfadjoint view.
Definition gsSparseMatrix.h:182
gsSparseMatrix(const gsEigen::SparseMatrixBase< OtherDerived > &other)
This constructor allows constructing a gsSparseMatrix from another sparse expression.
Definition gsSparseMatrix.h:191
container innerOf(const container &outer) const
Definition gsSparseMatrix.h:387
BlockView blockView(const gsVector< index_t > &rowSizes, const gsVector< index_t > &colSizes)
Return a block view of the matrix with rowSizes and colSizes.
Definition gsSparseMatrix.h:336
gsEigen::SparseSelfAdjointView< const Base, Lower > constFullView
Definition gsSparseMatrix.h:169
void insertTo(_Index i, _Index j, const T val)
Definition gsSparseMatrix.h:289
gsSparseMatrix(const gsEigen::EigenBase< OtherDerived > &other)
This constructor allows constructing a gsSparseMatrix from Eigen expressions.
Definition gsSparseMatrix.h:178
A vector with arbitrary coefficient type and fixed or dynamic size.
Definition gsVector.h:37
#define index_t
Definition gsConfig.h:32
#define GISMO_ERROR(message)
Definition gsDebug.h:118
#define gsWarn
Definition gsDebug.h:50
#define GISMO_ASSERT(cond, message)
Definition gsDebug.h:89
The G+Smo namespace, containing all definitions for the library.