10 #ifndef EIGEN_SKYLINEMATRIX_H
11 #define EIGEN_SKYLINEMATRIX_H
13 #include "SkylineStorage.h"
14 #include "SkylineMatrixBase.h"
16 #include "./InternalHeaderCheck.h"
36 template<
typename Scalar_,
int Options_>
37 struct traits<SkylineMatrix<Scalar_, Options_> > {
38 typedef Scalar_ Scalar;
39 typedef Sparse StorageKind;
46 Flags = SkylineBit | Options_,
47 CoeffReadCost = NumTraits<Scalar>::ReadCost,
52 template<
typename Scalar_,
int Options_>
60 using Base::IsRowMajor;
70 Index* m_colStartIndex;
71 Index* m_rowStartIndex;
76 inline Index rows()
const {
77 return IsRowMajor ? m_outerSize : m_innerSize;
80 inline Index cols()
const {
81 return IsRowMajor ? m_innerSize : m_outerSize;
84 inline Index innerSize()
const {
88 inline Index outerSize()
const {
92 inline Index upperNonZeros()
const {
93 return m_data.upperSize();
96 inline Index lowerNonZeros()
const {
97 return m_data.lowerSize();
101 return m_colStartIndex[j + 1] - m_colStartIndex[j];
105 return m_rowStartIndex[j + 1] - m_rowStartIndex[j];
108 inline const Scalar* _diagPtr()
const {
109 return &m_data.diag(0);
112 inline Scalar* _diagPtr() {
113 return &m_data.diag(0);
116 inline const Scalar* _upperPtr()
const {
117 return &m_data.upper(0);
120 inline Scalar* _upperPtr() {
121 return &m_data.upper(0);
124 inline const Scalar* _lowerPtr()
const {
125 return &m_data.lower(0);
128 inline Scalar* _lowerPtr() {
129 return &m_data.lower(0);
132 inline const Index* _upperProfilePtr()
const {
133 return &m_data.upperProfile(0);
136 inline Index* _upperProfilePtr() {
137 return &m_data.upperProfile(0);
140 inline const Index* _lowerProfilePtr()
const {
141 return &m_data.lowerProfile(0);
144 inline Index* _lowerProfilePtr() {
145 return &m_data.lowerProfile(0);
148 inline Scalar coeff(
Index row,
Index col)
const {
149 const Index outer = IsRowMajor ? row : col;
150 const Index inner = IsRowMajor ? col : row;
152 eigen_assert(outer < outerSize());
153 eigen_assert(inner < innerSize());
156 return this->m_data.diag(outer);
161 const Index minOuterIndex = inner - m_data.upperProfile(inner);
162 if (outer >= minOuterIndex)
163 return this->m_data.upper(m_colStartIndex[inner] + outer - (inner - m_data.upperProfile(inner)));
169 const Index minInnerIndex = outer - m_data.lowerProfile(outer);
170 if (inner >= minInnerIndex)
171 return this->m_data.lower(m_rowStartIndex[outer] + inner - (outer - m_data.lowerProfile(outer)));
175 return m_data.upper(m_colStartIndex[inner] + outer - inner);
179 const Index maxOuterIndex = inner + m_data.upperProfile(inner);
180 if (outer <= maxOuterIndex)
181 return this->m_data.upper(m_colStartIndex[inner] + (outer - inner));
187 const Index maxInnerIndex = outer + m_data.lowerProfile(outer);
189 if (inner <= maxInnerIndex)
190 return this->m_data.lower(m_rowStartIndex[outer] + (inner - outer));
197 inline Scalar& coeffRef(
Index row,
Index col) {
198 const Index outer = IsRowMajor ? row : col;
199 const Index inner = IsRowMajor ? col : row;
201 eigen_assert(outer < outerSize());
202 eigen_assert(inner < innerSize());
205 return this->m_data.diag(outer);
210 const Index minOuterIndex = inner - m_data.upperProfile(inner);
211 eigen_assert(outer >= minOuterIndex &&
"You tried to access a coeff that does not exist in the storage");
212 return this->m_data.upper(m_colStartIndex[inner] + outer - (inner - m_data.upperProfile(inner)));
216 const Index minInnerIndex = outer - m_data.lowerProfile(outer);
217 eigen_assert(inner >= minInnerIndex &&
"You tried to access a coeff that does not exist in the storage");
218 return this->m_data.lower(m_rowStartIndex[outer] + inner - (outer - m_data.lowerProfile(outer)));
223 const Index maxOuterIndex = inner + m_data.upperProfile(inner);
224 eigen_assert(outer <= maxOuterIndex &&
"You tried to access a coeff that does not exist in the storage");
225 return this->m_data.upper(m_colStartIndex[inner] + (outer - inner));
229 const Index maxInnerIndex = outer + m_data.lowerProfile(outer);
230 eigen_assert(inner <= maxInnerIndex &&
"You tried to access a coeff that does not exist in the storage");
231 return this->m_data.lower(m_rowStartIndex[outer] + (inner - outer));
236 inline Scalar coeffDiag(
Index idx)
const {
237 eigen_assert(idx < outerSize());
238 eigen_assert(idx < innerSize());
239 return this->m_data.diag(idx);
242 inline Scalar coeffLower(
Index row,
Index col)
const {
243 const Index outer = IsRowMajor ? row : col;
244 const Index inner = IsRowMajor ? col : row;
246 eigen_assert(outer < outerSize());
247 eigen_assert(inner < innerSize());
248 eigen_assert(inner != outer);
251 const Index minInnerIndex = outer - m_data.lowerProfile(outer);
252 if (inner >= minInnerIndex)
253 return this->m_data.lower(m_rowStartIndex[outer] + inner - (outer - m_data.lowerProfile(outer)));
258 const Index maxInnerIndex = outer + m_data.lowerProfile(outer);
259 if (inner <= maxInnerIndex)
260 return this->m_data.lower(m_rowStartIndex[outer] + (inner - outer));
266 inline Scalar coeffUpper(
Index row,
Index col)
const {
267 const Index outer = IsRowMajor ? row : col;
268 const Index inner = IsRowMajor ? col : row;
270 eigen_assert(outer < outerSize());
271 eigen_assert(inner < innerSize());
272 eigen_assert(inner != outer);
275 const Index minOuterIndex = inner - m_data.upperProfile(inner);
276 if (outer >= minOuterIndex)
277 return this->m_data.upper(m_colStartIndex[inner] + outer - (inner - m_data.upperProfile(inner)));
281 const Index maxOuterIndex = inner + m_data.upperProfile(inner);
282 if (outer <= maxOuterIndex)
283 return this->m_data.upper(m_colStartIndex[inner] + (outer - inner));
289 inline Scalar& coeffRefDiag(
Index idx) {
290 eigen_assert(idx < outerSize());
291 eigen_assert(idx < innerSize());
292 return this->m_data.diag(idx);
295 inline Scalar& coeffRefLower(
Index row,
Index col) {
296 const Index outer = IsRowMajor ? row : col;
297 const Index inner = IsRowMajor ? col : row;
299 eigen_assert(outer < outerSize());
300 eigen_assert(inner < innerSize());
301 eigen_assert(inner != outer);
304 const Index minInnerIndex = outer - m_data.lowerProfile(outer);
305 eigen_assert(inner >= minInnerIndex &&
"You tried to access a coeff that does not exist in the storage");
306 return this->m_data.lower(m_rowStartIndex[outer] + inner - (outer - m_data.lowerProfile(outer)));
308 const Index maxInnerIndex = outer + m_data.lowerProfile(outer);
309 eigen_assert(inner <= maxInnerIndex &&
"You tried to access a coeff that does not exist in the storage");
310 return this->m_data.lower(m_rowStartIndex[outer] + (inner - outer));
314 inline bool coeffExistLower(
Index row,
Index col) {
315 const Index outer = IsRowMajor ? row : col;
316 const Index inner = IsRowMajor ? col : row;
318 eigen_assert(outer < outerSize());
319 eigen_assert(inner < innerSize());
320 eigen_assert(inner != outer);
323 const Index minInnerIndex = outer - m_data.lowerProfile(outer);
324 return inner >= minInnerIndex;
326 const Index maxInnerIndex = outer + m_data.lowerProfile(outer);
327 return inner <= maxInnerIndex;
331 inline Scalar& coeffRefUpper(
Index row,
Index col) {
332 const Index outer = IsRowMajor ? row : col;
333 const Index inner = IsRowMajor ? col : row;
335 eigen_assert(outer < outerSize());
336 eigen_assert(inner < innerSize());
337 eigen_assert(inner != outer);
340 const Index minOuterIndex = inner - m_data.upperProfile(inner);
341 eigen_assert(outer >= minOuterIndex &&
"You tried to access a coeff that does not exist in the storage");
342 return this->m_data.upper(m_colStartIndex[inner] + outer - (inner - m_data.upperProfile(inner)));
344 const Index maxOuterIndex = inner + m_data.upperProfile(inner);
345 eigen_assert(outer <= maxOuterIndex &&
"You tried to access a coeff that does not exist in the storage");
346 return this->m_data.upper(m_colStartIndex[inner] + (outer - inner));
350 inline bool coeffExistUpper(
Index row,
Index col) {
351 const Index outer = IsRowMajor ? row : col;
352 const Index inner = IsRowMajor ? col : row;
354 eigen_assert(outer < outerSize());
355 eigen_assert(inner < innerSize());
356 eigen_assert(inner != outer);
359 const Index minOuterIndex = inner - m_data.upperProfile(inner);
360 return outer >= minOuterIndex;
362 const Index maxOuterIndex = inner + m_data.upperProfile(inner);
363 return outer <= maxOuterIndex;
371 class InnerUpperIterator;
372 class InnerLowerIterator;
374 class OuterUpperIterator;
375 class OuterLowerIterator;
380 std::fill_n(m_colStartIndex, m_outerSize + 1,
Index(0));
381 std::fill_n(m_rowStartIndex, m_outerSize + 1,
Index(0));
386 return m_data.diagSize() + m_data.upperSize() + m_data.lowerSize();
391 m_data.reserve(reserveSize, reserveUpperSize, reserveLowerSize);
403 const Index outer = IsRowMajor ? row : col;
404 const Index inner = IsRowMajor ? col : row;
406 eigen_assert(outer < outerSize());
407 eigen_assert(inner < innerSize());
410 return m_data.diag(col);
415 Index minOuterIndex = 0;
416 minOuterIndex = inner - m_data.upperProfile(inner);
418 if (outer < minOuterIndex)
420 const Index previousProfile = m_data.upperProfile(inner);
422 m_data.upperProfile(inner) = inner - outer;
425 const Index bandIncrement = m_data.upperProfile(inner) - previousProfile;
427 const Index stop = m_colStartIndex[cols()];
428 const Index start = m_colStartIndex[inner];
431 for (
Index innerIdx = stop; innerIdx >= start; innerIdx--) {
432 m_data.upper(innerIdx + bandIncrement) = m_data.upper(innerIdx);
435 for (
Index innerIdx = cols(); innerIdx > inner; innerIdx--) {
436 m_colStartIndex[innerIdx] += bandIncrement;
440 std::fill_n(this->_upperPtr() + start, bandIncrement - 1, Scalar(0));
442 return m_data.upper(m_colStartIndex[inner]);
444 return m_data.upper(m_colStartIndex[inner] + outer - (inner - m_data.upperProfile(inner)));
450 const Index minInnerIndex = outer - m_data.lowerProfile(outer);
451 if (inner < minInnerIndex)
453 const Index previousProfile = m_data.lowerProfile(outer);
454 m_data.lowerProfile(outer) = outer - inner;
456 const Index bandIncrement = m_data.lowerProfile(outer) - previousProfile;
458 const Index stop = m_rowStartIndex[rows()];
459 const Index start = m_rowStartIndex[outer];
462 for (
Index innerIdx = stop; innerIdx >= start; innerIdx--) {
463 m_data.lower(innerIdx + bandIncrement) = m_data.lower(innerIdx);
466 for (
Index innerIdx = rows(); innerIdx > outer; innerIdx--) {
467 m_rowStartIndex[innerIdx] += bandIncrement;
471 std::fill_n(this->_lowerPtr() + start, bandIncrement - 1, Scalar(0));
472 return m_data.lower(m_rowStartIndex[outer]);
474 return m_data.lower(m_rowStartIndex[outer] + inner - (outer - m_data.lowerProfile(outer)));
480 const Index maxOuterIndex = inner + m_data.upperProfile(inner);
481 if (outer > maxOuterIndex)
483 const Index previousProfile = m_data.upperProfile(inner);
484 m_data.upperProfile(inner) = outer - inner;
486 const Index bandIncrement = m_data.upperProfile(inner) - previousProfile;
488 const Index stop = m_rowStartIndex[rows()];
489 const Index start = m_rowStartIndex[inner + 1];
491 for (
Index innerIdx = stop; innerIdx >= start; innerIdx--) {
492 m_data.upper(innerIdx + bandIncrement) = m_data.upper(innerIdx);
495 for (
Index innerIdx = inner + 1; innerIdx < outerSize() + 1; innerIdx++) {
496 m_rowStartIndex[innerIdx] += bandIncrement;
498 std::fill_n(this->_upperPtr() + m_rowStartIndex[inner] + previousProfile + 1, bandIncrement - 1, Scalar(0));
499 return m_data.upper(m_rowStartIndex[inner] + m_data.upperProfile(inner));
501 return m_data.upper(m_rowStartIndex[inner] + (outer - inner));
507 const Index maxInnerIndex = outer + m_data.lowerProfile(outer);
508 if (inner > maxInnerIndex)
510 const Index previousProfile = m_data.lowerProfile(outer);
511 m_data.lowerProfile(outer) = inner - outer;
513 const Index bandIncrement = m_data.lowerProfile(outer) - previousProfile;
515 const Index stop = m_colStartIndex[cols()];
516 const Index start = m_colStartIndex[outer + 1];
518 for (
Index innerIdx = stop; innerIdx >= start; innerIdx--) {
519 m_data.lower(innerIdx + bandIncrement) = m_data.lower(innerIdx);
522 for (
Index innerIdx = outer + 1; innerIdx < outerSize() + 1; innerIdx++) {
523 m_colStartIndex[innerIdx] += bandIncrement;
525 std::fill_n(this->_lowerPtr() + m_colStartIndex[outer] + previousProfile + 1, bandIncrement - 1, Scalar(0));
526 return m_data.lower(m_colStartIndex[outer] + m_data.lowerProfile(outer));
528 return m_data.lower(m_colStartIndex[outer] + (inner - outer));
539 m_data.resize(cols(), cols(), rows(), m_colStartIndex[cols()] + 1, m_rowStartIndex[rows()] + 1);
541 m_data.resize(rows(), cols(), rows(), m_colStartIndex[cols()] + 1, m_rowStartIndex[rows()] + 1);
573 m_data.resize(cols(), rows(), cols(), m_rowStartIndex[cols()] + 1, m_colStartIndex[cols()] + 1);
575 m_data.resize(rows(), rows(), cols(), m_rowStartIndex[rows()] + 1, m_colStartIndex[rows()] + 1);
579 inline void squeeze() {
584 void prune(Scalar reference, RealScalar epsilon = dummy_precision<RealScalar > ()) {
592 const Index diagSize = rows > cols ? cols : rows;
593 m_innerSize = IsRowMajor ? cols : rows;
595 eigen_assert(rows == cols &&
"Skyline matrix must be square matrix");
598 const Index k = (diagSize - 1) / 2;
600 m_data.resize(diagSize, IsRowMajor ? cols : rows, IsRowMajor ? rows : cols,
606 const Index k = diagSize / 2;
607 m_data.resize(diagSize, IsRowMajor ? cols : rows, IsRowMajor ? rows : cols,
612 if (m_colStartIndex && m_rowStartIndex) {
613 delete[] m_colStartIndex;
614 delete[] m_rowStartIndex;
616 m_colStartIndex =
new Index [cols + 1];
617 m_rowStartIndex =
new Index [rows + 1];
618 m_outerSize = diagSize;
623 m_outerSize = diagSize;
624 std::fill_n(m_colStartIndex, cols + 1,
Index(0));
625 std::fill_n(m_rowStartIndex, rows + 1,
Index(0));
632 inline SkylineMatrix()
633 : m_outerSize(-1), m_innerSize(0), m_colStartIndex(0), m_rowStartIndex(0) {
637 inline SkylineMatrix(
size_t rows,
size_t cols)
638 : m_outerSize(0), m_innerSize(0), m_colStartIndex(0), m_rowStartIndex(0) {
642 template<
typename OtherDerived>
643 inline SkylineMatrix(
const SkylineMatrixBase<OtherDerived>& other)
644 : m_outerSize(0), m_innerSize(0), m_colStartIndex(0), m_rowStartIndex(0) {
645 *
this = other.derived();
648 inline SkylineMatrix(
const SkylineMatrix & other)
649 : Base(), m_outerSize(0), m_innerSize(0), m_colStartIndex(0), m_rowStartIndex(0) {
650 *
this = other.derived();
653 inline void swap(SkylineMatrix & other) {
655 std::swap(m_colStartIndex, other.m_colStartIndex);
656 std::swap(m_rowStartIndex, other.m_rowStartIndex);
657 std::swap(m_innerSize, other.m_innerSize);
658 std::swap(m_outerSize, other.m_outerSize);
659 m_data.swap(other.m_data);
662 inline SkylineMatrix & operator=(
const SkylineMatrix & other) {
663 std::cout <<
"SkylineMatrix& operator=(const SkylineMatrix& other)\n";
664 if (other.isRValue()) {
665 swap(other.const_cast_derived());
667 resize(other.rows(), other.cols());
668 memcpy(m_colStartIndex, other.m_colStartIndex, (m_outerSize + 1) * sizeof (Index));
669 memcpy(m_rowStartIndex, other.m_rowStartIndex, (m_outerSize + 1) * sizeof (Index));
670 m_data = other.m_data;
675 template<
typename OtherDerived>
676 inline SkylineMatrix & operator=(
const SkylineMatrixBase<OtherDerived>& other) {
678 if (needToTranspose) {
683 return SkylineMatrixBase<SkylineMatrix>::operator=(other.derived());
687 friend std::ostream & operator <<(std::ostream & s,
const SkylineMatrix & m) {
690 std::cout <<
"upper elements : " << std::endl;
691 for (Index i = 0; i < m.m_data.upperSize(); i++)
692 std::cout << m.m_data.upper(i) <<
"\t";
693 std::cout << std::endl;
694 std::cout <<
"upper profile : " << std::endl;
695 for (Index i = 0; i < m.m_data.upperProfileSize(); i++)
696 std::cout << m.m_data.upperProfile(i) <<
"\t";
697 std::cout << std::endl;
698 std::cout <<
"lower startIdx : " << std::endl;
699 for (Index i = 0; i < m.m_data.upperProfileSize(); i++)
700 std::cout << (IsRowMajor ? m.m_colStartIndex[i] : m.m_rowStartIndex[i]) <<
"\t";
701 std::cout << std::endl;
704 std::cout <<
"lower elements : " << std::endl;
705 for (Index i = 0; i < m.m_data.lowerSize(); i++)
706 std::cout << m.m_data.lower(i) <<
"\t";
707 std::cout << std::endl;
708 std::cout <<
"lower profile : " << std::endl;
709 for (Index i = 0; i < m.m_data.lowerProfileSize(); i++)
710 std::cout << m.m_data.lowerProfile(i) <<
"\t";
711 std::cout << std::endl;
712 std::cout <<
"lower startIdx : " << std::endl;
713 for (Index i = 0; i < m.m_data.lowerProfileSize(); i++)
714 std::cout << (IsRowMajor ? m.m_rowStartIndex[i] : m.m_colStartIndex[i]) <<
"\t";
715 std::cout << std::endl;
717 for (Index rowIdx = 0; rowIdx < m.rows(); rowIdx++) {
718 for (Index colIdx = 0; colIdx < m.cols(); colIdx++) {
719 s << m.coeff(rowIdx, colIdx) <<
"\t";
728 delete[] m_colStartIndex;
729 delete[] m_rowStartIndex;
736 template<
typename Scalar,
int Options_>
741 : m_matrix(mat), m_outer(outer),
742 m_id(Options_ ==
RowMajor ? mat.m_colStartIndex[outer] : mat.m_rowStartIndex[outer] + 1),
744 m_end(Options_ ==
RowMajor ? mat.m_colStartIndex[outer + 1] : mat.m_rowStartIndex[outer + 1] + 1) {
747 inline InnerUpperIterator & operator++() {
752 inline InnerUpperIterator & operator+=(Index shift) {
757 inline Scalar value()
const {
758 return m_matrix.m_data.upper(m_id);
761 inline Scalar* valuePtr() {
762 return const_cast<Scalar*
> (&(m_matrix.m_data.upper(m_id)));
765 inline Scalar& valueRef() {
766 return const_cast<Scalar&
> (m_matrix.m_data.upper(m_id));
769 inline Index index()
const {
770 return IsRowMajor ? m_outer - m_matrix.m_data.upperProfile(m_outer) + (m_id - m_start) :
771 m_outer + (m_id - m_start) + 1;
774 inline Index row()
const {
775 return IsRowMajor ? index() : m_outer;
778 inline Index col()
const {
779 return IsRowMajor ? m_outer : index();
782 inline size_t size()
const {
783 return m_matrix.m_data.upperProfile(m_outer);
786 inline operator bool()
const {
787 return (m_id < m_end) && (m_id >= m_start);
791 const SkylineMatrix& m_matrix;
798 template<
typename Scalar,
int Options_>
799 class SkylineMatrix<Scalar, Options_>::InnerLowerIterator {
802 InnerLowerIterator(
const SkylineMatrix& mat, Index outer)
805 m_id(Options_ ==
RowMajor ? mat.m_rowStartIndex[outer] : mat.m_colStartIndex[outer] + 1),
807 m_end(Options_ ==
RowMajor ? mat.m_rowStartIndex[outer + 1] : mat.m_colStartIndex[outer + 1] + 1) {
810 inline InnerLowerIterator & operator++() {
815 inline InnerLowerIterator & operator+=(Index shift) {
820 inline Scalar value()
const {
821 return m_matrix.m_data.lower(m_id);
824 inline Scalar* valuePtr() {
825 return const_cast<Scalar*
> (&(m_matrix.m_data.lower(m_id)));
828 inline Scalar& valueRef() {
829 return const_cast<Scalar&
> (m_matrix.m_data.lower(m_id));
832 inline Index index()
const {
833 return IsRowMajor ? m_outer - m_matrix.m_data.lowerProfile(m_outer) + (m_id - m_start) :
834 m_outer + (m_id - m_start) + 1;
838 inline Index row()
const {
839 return IsRowMajor ? m_outer : index();
842 inline Index col()
const {
843 return IsRowMajor ? index() : m_outer;
846 inline size_t size()
const {
847 return m_matrix.m_data.lowerProfile(m_outer);
850 inline operator bool()
const {
851 return (m_id < m_end) && (m_id >= m_start);
855 const SkylineMatrix& m_matrix;
Base class of any skyline matrices or skyline expressions.
Definition: SkylineMatrixBase.h:28
EIGEN_CONSTEXPR Index size() const EIGEN_NOEXCEPT
Definition: SkylineMatrixBase.h:117
@ Flags
Definition: SkylineMatrixBase.h:66
The main skyline matrix class.
Definition: SkylineMatrix.h:54
Index nonZeros() const
Definition: SkylineMatrix.h:385
void resize(size_t rows, size_t cols)
Definition: SkylineMatrix.h:591
void finalize()
Definition: SkylineMatrix.h:536
void setZero()
Definition: SkylineMatrix.h:378
void reserve(Index reserveSize, Index reserveUpperSize, Index reserveLowerSize)
Definition: SkylineMatrix.h:390
EIGEN_DONT_INLINE Scalar & insert(Index row, Index col)
Definition: SkylineMatrix.h:402
~SkylineMatrix()
Definition: SkylineMatrix.h:727
Definition: SkylineStorage.h:24
const unsigned int RowMajorBit
Namespace containing all symbols from the Eigen library.
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index