10#ifndef EIGEN_BLOCKSPARSEMATRIX_H
11#define EIGEN_BLOCKSPARSEMATRIX_H
14#include "./InternalHeaderCheck.h"
23template <
typename,
int,
bool>
25template <
typename,
int,
bool>
27template <
typename Scalar_,
int Options_,
int BlockRows_,
int BlockCols_,
typename StorageIndex_>
35 static std::string debugName() {
return "BlockSparseShape"; }
41template <
bool Conj,
typename T>
42std::enable_if_t<Conj, decltype(std::declval<const T&>().adjoint())> adjoint_if(
const T& m) {
46template <
bool Conj,
typename T>
47std::enable_if_t<!Conj, decltype(std::declval<const T&>().transpose())> adjoint_if(
const T& m) {
51struct storage_kind_to_evaluator_kind<BlockSparse> {
52 using Kind = IndexBased;
56struct storage_kind_to_shape<BlockSparse> {
57 using Shape = BlockSparseShape;
60template <
typename Scalar_,
int Options_,
int BlockRows_,
int BlockCols_,
typename StorageIndex_>
61struct traits<BlockSparseMatrix<Scalar_, Options_, BlockRows_, BlockCols_, StorageIndex_>> {
62 using Scalar = Scalar_;
63 using StorageIndex = StorageIndex_;
64 using StorageKind = BlockSparse;
65 using XprKind = MatrixXpr;
67 static constexpr Index RowsAtCompileTime = Dynamic;
68 static constexpr Index ColsAtCompileTime = Dynamic;
69 static constexpr Index MaxRowsAtCompileTime = Dynamic;
70 static constexpr Index MaxColsAtCompileTime = Dynamic;
71 static constexpr int Options = Options_;
72 static constexpr unsigned int Flags = Options_ | NestByRefBit |
LvalueBit;
88template <
typename Scalar_,
int BlockRows_,
int BlockCols_,
int Options_ = ColMajor,
typename StorageIndex_ =
int>
91 using Scalar = Scalar_;
92 using StorageIndex = StorageIndex_;
97 static constexpr int BlockSize = BlockRows_ * BlockCols_;
99 BlockTriplet() =
default;
101 BlockTriplet(StorageIndex blockRow, StorageIndex blockCol,
const BlockType& block)
102 : m_row(blockRow), m_col(blockCol) {
103 BlockMapType{m_value} = block;
106 StorageIndex row()
const {
return m_row; }
107 StorageIndex col()
const {
return m_col; }
109 ConstBlockMapType value()
const {
return ConstBlockMapType(m_value); }
112 StorageIndex m_row = 0;
113 StorageIndex m_col = 0;
115 Scalar m_value[BlockSize];
158template <
typename Scalar_,
int Options_,
int BlockRows_,
int BlockCols_,
typename StorageIndex_ =
int>
159class BlockSparseMatrix
160 :
public EigenBase<BlockSparseMatrix<Scalar_, Options_, BlockRows_, BlockCols_, StorageIndex_>> {
161 EIGEN_STATIC_ASSERT(BlockRows_ >= 1, BLOCKROWS_MUST_BE_A_POSITIVE_COMPILE_TIME_SIZE)
162 EIGEN_STATIC_ASSERT(BlockCols_ >= 1, BLOCKCOLS_MUST_BE_A_POSITIVE_COMPILE_TIME_SIZE)
163 EIGEN_STATIC_ASSERT(std::is_integral<StorageIndex_>::value&& std::is_signed<StorageIndex_>::value,
164 STORAGEINDEX_MUST_BE_A_SIGNED_INTEGRAL_TYPE)
168 EIGEN_STATIC_ASSERT(!(BlockCols_ == 1 && BlockRows_ != 1 &&
bool(Options_ &
RowMajorBit)),
169 INVALID_MATRIX_TEMPLATE_PARAMETERS)
170 EIGEN_STATIC_ASSERT(!(BlockRows_ == 1 && BlockCols_ != 1 && !
bool(Options_ &
RowMajorBit)),
171 INVALID_MATRIX_TEMPLATE_PARAMETERS)
177 using Scalar = Scalar_;
178 using StorageIndex = StorageIndex_;
182 static constexpr int Options = Options_;
183 static constexpr Index BlockRows = BlockRows_;
184 static constexpr Index BlockCols = BlockCols_;
185 static constexpr bool IsRowMajor = Options_ &
RowMajorBit;
186 static constexpr Index BlockSize = BlockRows_ * BlockCols_;
191 static constexpr std::size_t BlockBytes = std::size_t(BlockSize) *
sizeof(Scalar);
192 static constexpr int BlockMapAlignment = ((BlockBytes & (BlockBytes - 1)) == 0 && BlockBytes >= 8)
193 ?
int(numext::mini(BlockBytes, std::size_t(EIGEN_MAX_ALIGN_BYTES)))
215 Index rows() const noexcept {
return (IsRowMajor ? m_blockOuterSize : m_blockInnerSize) * BlockRows_; }
217 Index cols() const noexcept {
return (IsRowMajor ? m_blockInnerSize : m_blockOuterSize) * BlockCols_; }
220 Index blockRows()
const {
return IsRowMajor ? m_blockOuterSize : m_blockInnerSize; }
222 Index blockCols()
const {
return IsRowMajor ? m_blockInnerSize : m_blockOuterSize; }
244 const StorageIndex* outerIndexPtr()
const {
return m_outerIndex.
data(); }
245 StorageIndex* outerIndexPtr() {
return m_outerIndex.
data(); }
246 const StorageIndex* innerIndexPtr()
const {
return m_innerIndex.data(); }
247 StorageIndex* innerIndexPtr() {
return m_innerIndex.data(); }
248 const Scalar* valuePtr()
const {
return m_values.data(); }
249 Scalar* valuePtr() {
return m_values.data(); }
256 ConstBlockMap
blockRef(
Index k)
const {
return ConstBlockMap(m_values.data() + k * BlockSize); }
258 BlockMap
blockRef(
Index k) {
return BlockMap(m_values.data() + k * BlockSize); }
269 class InnerIterator {
271 EIGEN_STRONG_INLINE InnerIterator(
const BlockSparseMatrix& mat,
Index outer)
272 : m_mat(mat), m_id(mat.m_outerIndex(
outer)), m_end(mat.m_outerIndex(
outer + 1)), m_outer(
outer) {}
274 EIGEN_STRONG_INLINE
operator bool()
const {
return m_id < m_end; }
275 EIGEN_STRONG_INLINE InnerIterator& operator++() {
283 EIGEN_STRONG_INLINE
Index index()
const {
return m_mat.m_innerIndex(m_id); }
290 EIGEN_STRONG_INLINE ConstBlockMap
value()
const {
return m_mat.blockRef(m_id); }
293 return BlockMap(
const_cast<Scalar*
>(m_mat.m_values.data()) + m_id * BlockSize);
297 const BlockSparseMatrix& m_mat;
312 m_outerIndex.resize(m_blockOuterSize + 1);
313 m_outerIndex.setZero();
318 m_outerIndex.resize(m_blockOuterSize + 1);
319 m_outerIndex.setZero();
325 if (n >
Index(m_innerIndex.size())) conservativeResizeBlockStorage_(n);
331 if (nnz <
Index(m_innerIndex.size())) conservativeResizeBlockStorage_(nnz);
340 EIGEN_STATIC_ASSERT(BlockRows_ == BlockCols_, THIS_METHOD_IS_ONLY_FOR_SQUARE_BLOCK_MATRICES)
341 Index n = (std::min)(m_blockOuterSize, m_blockInnerSize);
342 m_outerIndex.resize(m_blockOuterSize + 1);
343 resizeBlockStorage_(n);
344 for (
Index i = 0; i <= m_blockOuterSize; ++i) m_outerIndex(i) = StorageIndex((std::min)(i, n));
345 for (StorageIndex i = 0; i < n; ++i) {
358 const StorageIndex_* innerPtr) {
363 resizeBlockStorage_(nnzBlocks);
381 template <
typename InputIterator>
416 eigen_assert(row >= 0 && row <
rows() && col >= 0 && col <
cols());
417 Index bOuter = IsRowMajor ? (row / BlockRows_) : (col / BlockCols_);
418 Index bInner = IsRowMajor ? (col / BlockCols_) : (row / BlockRows_);
419 Index localRow = row % BlockRows_;
420 Index localCol = col % BlockCols_;
421 const StorageIndex* beg = m_innerIndex.data() + m_outerIndex(bOuter);
422 const StorageIndex* fin = m_innerIndex.data() + m_outerIndex(bOuter + 1);
423 const StorageIndex* it = std::lower_bound(beg, fin, StorageIndex(bInner));
424 if (it == fin || *it != bInner)
return Scalar(0);
425 return blockRef(
static_cast<Index>(it - m_innerIndex.data()))(localRow, localCol);
436 constexpr Index OuterB = IsRowMajor ? BlockRows_ : BlockCols_;
437 constexpr Index InnerB = IsRowMajor ? BlockCols_ : BlockRows_;
441 for (
Index out = 0; out < m_blockOuterSize; ++out) {
442 const Index scalarOuterBegin = out * OuterB;
443 if (scalarOuterBegin >= diagSize)
break;
444 const Index scalarOuterEnd = numext::mini(scalarOuterBegin + OuterB, diagSize);
449 Index i = scalarOuterBegin;
450 while (i < scalarOuterEnd) {
451 const Index bInner = i / InnerB;
452 const Index groupEnd = numext::mini((bInner + 1) * InnerB, scalarOuterEnd);
454 const StorageIndex* beg = m_innerIndex.data() + m_outerIndex(out);
455 const StorageIndex* fin = m_innerIndex.data() + m_outerIndex(out + 1);
456 const StorageIndex* it = std::lower_bound(beg, fin, StorageIndex(bInner));
457 if (it != fin && *it == StorageIndex(bInner)) {
458 const ConstBlockMap blk =
blockRef(
static_cast<Index>(it - m_innerIndex.data()));
459 for (
Index j = i; j < groupEnd; ++j) {
460 const Index localRow = IsRowMajor ? (j % OuterB) : (j % InnerB);
461 const Index localCol = IsRowMajor ? (j % InnerB) : (j % OuterB);
462 diag(j) = blk(localRow, localCol);
476 BlockSparseMatrix
operator+(
const BlockSparseMatrix& other)
const {
return disjunctionWith_(other, AddOp_{}); }
479 BlockSparseMatrix
operator-(
const BlockSparseMatrix& other)
const {
return disjunctionWith_(other, SubOp_{}); }
483 return conjunctionWith_(other, CwiseMulOp_{});
487 template <
typename ScalarFunc>
489 return withValues_([&func](
const auto& v) {
return v.unaryExpr(func); });
501 template <
typename ScalarFunc>
502 BlockSparseMatrix
disjunctionExpr(
const BlockSparseMatrix& other, ScalarFunc func)
const {
503 return disjunctionWith_(other, DisjExprAdapter_<ScalarFunc>{func});
508 template <
typename ScalarFunc>
509 BlockSparseMatrix
conjunctionExpr(
const BlockSparseMatrix& other, ScalarFunc func)
const {
510 return conjunctionWith_(other, [&func](
const auto& a,
const auto& b) {
return a.binaryExpr(b, func); });
515 return withValues_([](
const auto& v) {
return -v; });
519 BlockSparseMatrix& operator-=(
const BlockSparseMatrix& other) {
return *
this = *
this - other; }
523 return withValues_([&s](
const auto& v) {
return v * s; });
529 BlockSparseMatrix operator/(
const Scalar& s)
const {
530 return withValues_([&s](
const auto& v) {
return v / s; });
532 BlockSparseMatrix& operator/=(
const Scalar& s) {
return *
this *= (Scalar(1) / s); }
535 friend BlockSparseMatrix
operator*(
const Scalar& s,
const BlockSparseMatrix& m) {
return m * s; }
553 template <
typename OtherDerived>
556 (std::is_same<Scalar, typename OtherDerived::Scalar>::value),
557 YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
571 template <
typename OtherDerived>
573 const BlockSparseMatrix& bsm) {
575 (std::is_same<Scalar_, typename OtherDerived::Scalar>::value),
576 YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
592 template <
int RhsBlockCols>
600 const typename NumTraits<Scalar>::Real& prec = NumTraits<Scalar>::dummy_precision())
const {
601 using RealScalar =
typename NumTraits<Scalar>::Real;
606 RealScalar n2a = m_values.head(
nonZeros()).matrix().squaredNorm();
607 RealScalar n2b = other.m_values.head(other.
nonZeros()).matrix().squaredNorm();
609 RealScalar d2 = diff.m_values.head(diff.
nonZeros()).matrix().squaredNorm();
610 return d2 <= prec * prec * numext::mini(n2a, n2b);
619 BlockSparseMatrix<Scalar_, Options_, BlockCols_, BlockRows_, StorageIndex_>
transpose()
const;
623 BlockSparseMatrix<Scalar_, Options_, BlockCols_, BlockRows_, StorageIndex_>
adjoint()
const;
639 template <
int Mode,
bool DiagIsTriangular = false>
640 BlockSparseTriangularView<BlockSparseMatrix, Mode, DiagIsTriangular>
triangularView()
const {
641 return BlockSparseTriangularView<BlockSparseMatrix, Mode, DiagIsTriangular>(*
this);
660 template <
int UpLo,
bool DiagIsSelfAdjo
int = false>
661 BlockSparseSelfAdjointView<BlockSparseMatrix, UpLo, DiagIsSelfAdjoint>
selfadjointView()
const {
662 EIGEN_STATIC_ASSERT(BlockRows_ == BlockCols_, THIS_METHOD_IS_ONLY_FOR_SQUARE_BLOCK_MATRICES)
663 return BlockSparseSelfAdjointView<BlockSparseMatrix, UpLo, DiagIsSelfAdjoint>(*
this);
668 template <
typename A,
typename B>
669 BlockType operator()(
const A& a,
const B& b)
const {
672 template <
typename A>
673 BlockType lhs(
const A& a)
const {
676 template <
typename B>
677 BlockType rhs(
const B& b)
const {
683 template <
typename A,
typename B>
684 BlockType operator()(
const A& a,
const B& b)
const {
687 template <
typename A>
688 BlockType lhs(
const A& a)
const {
691 template <
typename B>
692 BlockType rhs(
const B& b)
const {
699 template <
typename ScalarFunc>
700 struct DisjExprAdapter_ {
702 template <
typename A,
typename B>
703 BlockType operator()(
const A& a,
const B& b)
const {
704 return a.binaryExpr(b, func_);
706 template <
typename A>
707 BlockType lhs(
const A& a)
const {
708 return a.unaryExpr([
this](
const Scalar& x) {
return func_.lhs(x); });
710 template <
typename B>
711 BlockType rhs(
const B& b)
const {
712 return b.unaryExpr([
this](
const Scalar& x) {
return func_.rhs(x); });
717 template <
typename A,
typename B>
718 BlockType operator()(
const A& a,
const B& b)
const {
719 return a.cwiseProduct(b);
727 template <
typename F>
728 BlockSparseMatrix withValues_(F f)
const {
731 result.m_outerIndex = m_outerIndex;
732 result.m_innerIndex = m_innerIndex.head(nnz);
733 result.m_values = f(m_values.head(nnz * BlockSize));
741 template <
typename Op>
742 BlockSparseMatrix disjunctionWith_(
const BlockSparseMatrix& other, Op op)
const {
744 "BlockSparseMatrix size mismatch");
746 result.resizeBlockStorage_(
nonZeroBlocks() + other.nonZeroBlocks());
748 for (
Index j = 0; j < m_blockOuterSize; ++j) {
749 result.m_outerIndex(j) = StorageIndex_(nnz);
750 Index aId = m_outerIndex(j);
751 Index aEnd = m_outerIndex(j + 1);
752 Index bId = other.m_outerIndex(j);
753 Index bEnd = other.m_outerIndex(j + 1);
754 while (aId < aEnd || bId < bEnd) {
755 bool hasA = aId < aEnd;
756 bool hasB = bId < bEnd;
757 Index aInner = hasA ?
Index(m_innerIndex(aId)) : -1;
758 Index bInner = hasB ?
Index(other.m_innerIndex(bId)) : -1;
761 if (hasA && (!hasB || aInner < bInner)) {
762 result.m_innerIndex(nnz) = StorageIndex_(aInner);
763 result.blockRef(nnz) = op.lhs(
blockRef(aId++));
764 }
else if (hasB && (!hasA || bInner < aInner)) {
765 result.m_innerIndex(nnz) = StorageIndex_(bInner);
766 result.blockRef(nnz) = op.rhs(other.blockRef(bId++));
768 result.m_innerIndex(nnz) = StorageIndex_(aInner);
769 result.blockRef(nnz) = op(
blockRef(aId++), other.blockRef(bId++));
774 result.m_outerIndex(m_blockOuterSize) = StorageIndex_(nnz);
775 result.conservativeResizeBlockStorage_(nnz);
780 template <
typename BinaryOp>
781 BlockSparseMatrix conjunctionWith_(
const BlockSparseMatrix& other, BinaryOp func)
const {
783 "BlockSparseMatrix size mismatch");
785 result.resizeBlockStorage_((std::min)(
nonZeroBlocks(), other.nonZeroBlocks()));
787 for (
Index j = 0; j < m_blockOuterSize; ++j) {
788 result.m_outerIndex(j) = StorageIndex_(nnz);
789 Index aId = m_outerIndex(j);
790 Index aEnd = m_outerIndex(j + 1);
791 Index bId = other.m_outerIndex(j);
792 Index bEnd = other.m_outerIndex(j + 1);
793 while (aId < aEnd && bId < bEnd) {
794 Index aInner = m_innerIndex(aId);
795 Index bInner = other.m_innerIndex(bId);
796 if (aInner < bInner) {
798 }
else if (bInner < aInner) {
801 result.m_innerIndex(nnz) = StorageIndex_(aInner);
802 result.blockRef(nnz) = func(
blockRef(aId++), other.blockRef(bId++));
807 result.m_outerIndex(m_blockOuterSize) = StorageIndex_(nnz);
808 result.conservativeResizeBlockStorage_(nnz);
812 template <
bool Conjugate>
813 BlockSparseMatrix<Scalar_, Options_, BlockCols_, BlockRows_, StorageIndex_> transposeImpl()
const;
816 void resizeBlockStorage_(
Index n) {
817 m_innerIndex.resize(n);
818 m_values.resize(n * BlockSize);
821 void conservativeResizeBlockStorage_(
Index n) {
822 m_innerIndex.conservativeResize(n);
823 m_values.conservativeResize(n * BlockSize);
829 Index m_blockOuterSize = 0;
830 Index m_blockInnerSize = 0;
832 Array<StorageIndex, Dynamic, 1> m_outerIndex =
833 decltype(m_outerIndex)::Zero(m_blockOuterSize + 1);
834 Array<StorageIndex, Dynamic, 1> m_innerIndex;
837 Array<Scalar, Dynamic, 1> m_values;
850 template <
typename SparseMatrixType>
851 class MultiInnerIterator {
852 using StorageIndex =
typename SparseMatrixType::StorageIndex;
853 static constexpr int BlockOuterSize_ = IsRowMajor ? BlockRows_ : BlockCols_;
856 MultiInnerIterator(
const SparseMatrixType& mat,
Index outerBase)
857 : m_outerPtr(mat.outerIndexPtr()),
858 m_innerPtr(mat.innerIndexPtr()),
859 m_valuePtr(mat.valuePtr()),
860 m_outerBase(outerBase) {
861 for (
int k = 0; k < BlockOuterSize_; ++k) m_pos[k] = m_outerPtr[outerBase + k];
865 EIGEN_STRONG_INLINE
operator bool()
const {
return m_valid; }
867 EIGEN_STRONG_INLINE MultiInnerIterator& operator++() {
874 EIGEN_STRONG_INLINE
Index outer()
const {
return m_outerBase + m_active; }
876 EIGEN_STRONG_INLINE StorageIndex index()
const {
return m_innerPtr[m_pos[m_active]]; }
878 EIGEN_STRONG_INLINE Scalar value()
const {
return m_valuePtr[m_pos[m_active]]; }
884 for (
int k = 0; k < BlockOuterSize_; ++k) {
885 if (m_pos[k] < m_outerPtr[m_outerBase + k + 1]) {
886 if (!m_valid || m_innerPtr[m_pos[k]] < m_innerPtr[m_pos[m_active]]) {
894 const StorageIndex* m_outerPtr;
895 const StorageIndex* m_innerPtr;
896 const Scalar* m_valuePtr;
898 StorageIndex m_pos[BlockOuterSize_];
900 bool m_valid =
false;
905 template <
typename,
int,
int,
int,
typename>
906 friend class BlockSparseMatrix;
907 template <
typename,
int,
bool>
908 friend class BlockSparseTriangularView;
909 template <
typename,
int,
bool>
910 friend class BlockSparseSelfAdjointView;
921template <
typename Scalar_,
int Options_,
int BlockRows_,
int BlockCols_,
typename StorageIndex_>
922template <
typename InputIterator>
925 Index n =
static_cast<Index>(std::distance(begin, end));
932 for (InputIterator it = begin; it != end; ++it, ++k) {
933 eigen_assert(it->row() >= 0 && it->row() <
blockRows() &&
"setFromTriplets: block row out of range");
934 eigen_assert(it->col() >= 0 && it->col() <
blockCols() &&
"setFromTriplets: block col out of range");
935 tOuter(k) = IsRowMajor ? StorageIndex(it->row()) : StorageIndex(it->col());
936 tInner(k) = IsRowMajor ? StorageIndex(it->col()) : StorageIndex(it->row());
937 BlockMap(tValues.
data() + k * BlockSize) = it->value();
947 for (
Index i = 0; i < n; ++i) count(tInner(i) + 1)++;
948 for (
Index i = 0; i < m_blockInnerSize; ++i) count(i + 1) += count(i);
949 for (
Index i = 0; i < n; ++i) order(count(tInner(i))++) = i;
953 for (
Index i = 0; i < n; ++i) count(tOuter(i) + 1)++;
954 for (
Index i = 0; i < m_blockOuterSize; ++i) count(i + 1) += count(i);
955 for (
Index i = 0; i < n; ++i) {
956 Index idx = order(i);
957 scratch(count(tOuter(idx))++) = idx;
963 m_outerIndex.resize(m_blockOuterSize + 1);
964 m_outerIndex.setZero();
965 resizeBlockStorage_(n);
971 StorageIndex outer = tOuter(pi);
972 StorageIndex inner = tInner(pi);
974 BlockType block = ConstBlockMap(tValues.
data() + pi * BlockSize);
980 if (tOuter(pk) != outer || tInner(pk) != inner)
break;
981 block += ConstBlockMap(tValues.
data() + pk * BlockSize);
985 m_innerIndex(nnz) = inner;
987 m_outerIndex(outer + 1)++;
992 conservativeResizeBlockStorage_(nnz);
995 for (
Index j = 0; j < m_blockOuterSize; ++j) {
996 m_outerIndex(j + 1) += m_outerIndex(j);
1004template <
typename Scalar_,
int Options_,
int BlockRows_,
int BlockCols_,
typename StorageIndex_>
1014 for (
Index j = 0; j < m_blockOuterSize; ++j) {
1015 for (
Index c = 0; c < BlockCols_; ++c) {
1016 result.startVec(j * BlockCols_ + c);
1017 for (
Index id = m_outerIndex(j);
id < m_outerIndex(j + 1); ++id) {
1018 Index bi = m_innerIndex(
id);
1020 for (
Index r = 0; r < BlockRows_; ++r) {
1021 result.insertBack(bi * BlockRows_ + r, j * BlockCols_ + c) = blk(r, c);
1030 for (
Index bi = 0; bi < m_blockOuterSize; ++bi) {
1031 for (
Index r = 0; r < BlockRows_; ++r) {
1032 result.startVec(bi * BlockRows_ + r);
1033 for (
Index id = m_outerIndex(bi);
id < m_outerIndex(bi + 1); ++id) {
1034 Index j = m_innerIndex(
id);
1036 for (
Index c = 0; c < BlockCols_; ++c) {
1037 result.insertBack(bi * BlockRows_ + r, j * BlockCols_ + c) = blk(r, c);
1052template <
typename Scalar_,
int Options_,
int BlockRows_,
int BlockCols_,
typename StorageIndex_>
1056 eigen_assert(sp.
rows() % BlockRows_ == 0 &&
"matrix rows not divisible by BlockRows");
1057 eigen_assert(sp.
cols() % BlockCols_ == 0 &&
"matrix cols not divisible by BlockCols");
1058 eigen_assert(sp.
isCompressed() &&
"fromSparse requires a compressed SparseMatrix");
1065 constexpr Index BlockOuterSize = IsRowMajor ? BlockRows_ : BlockCols_;
1066 constexpr Index BlockInnerSize = IsRowMajor ? BlockCols_ : BlockRows_;
1067 constexpr StorageIndex_ kEmptyIndex = -1;
1071 BlockSparseMatrix result(bRows, bCols);
1075 for (
Index outerBlock = 0; outerBlock < result.m_blockOuterSize; ++outerBlock) {
1076 StorageIndex_ prevInnerBlock = kEmptyIndex;
1077 for (MultiInnerIterator<SpMat> it(sp, outerBlock * BlockOuterSize); it; ++it) {
1078 StorageIndex_ innerBlock = it.index() / StorageIndex_(BlockInnerSize);
1079 if (innerBlock != prevInnerBlock) {
1080 result.m_outerIndex(outerBlock + 1)++;
1081 prevInnerBlock = innerBlock;
1087 for (
Index j = 0; j < result.m_blockOuterSize; ++j) result.m_outerIndex(j + 1) += result.m_outerIndex(j);
1089 Index nBlocks = result.m_outerIndex(result.m_blockOuterSize);
1090 result.resizeBlockStorage_(nBlocks);
1095 for (
Index outerBlock = 0; outerBlock < result.m_blockOuterSize; ++outerBlock) {
1096 Index blockId = result.m_outerIndex(outerBlock) - 1;
1097 StorageIndex_ prevInnerBlock = kEmptyIndex;
1099 for (MultiInnerIterator<SpMat> it(sp, outerBlock * BlockOuterSize); it; ++it) {
1100 Index absOuter = it.outer();
1101 StorageIndex_ innerIdx = it.index();
1102 StorageIndex_ innerBlock = innerIdx / StorageIndex_(BlockInnerSize);
1104 if (innerBlock != prevInnerBlock) {
1106 result.m_innerIndex(blockId) = innerBlock;
1107 prevInnerBlock = innerBlock;
1113 Index localOuter = absOuter % BlockOuterSize;
1114 Index localInner = innerIdx % BlockInnerSize;
1115 Index offset = localOuter * BlockInnerSize + localInner;
1117 result.m_values(blockId * BlockSize + offset) = it.value();
1128template <
typename Scalar_,
int Options_,
int BlockRows_,
int BlockCols_,
typename StorageIndex_>
1129template <
int RhsBlockCols>
1132 const BlockSparseMatrix<Scalar_, Options_, BlockCols_, RhsBlockCols, StorageIndex_>& rhs)
const {
1133 using RhsMatrix = BlockSparseMatrix<Scalar_, Options_, BlockCols_, RhsBlockCols, StorageIndex_>;
1134 using ResultMatrix = BlockSparseMatrix<Scalar_, Options_, BlockRows_, RhsBlockCols, StorageIndex_>;
1136 constexpr int ResultBlockSize = BlockRows_ * RhsBlockCols;
1138 eigen_assert(
blockCols() == rhs.
blockRows() &&
"BlockSparseMatrix product: lhs.blockCols() != rhs.blockRows()");
1142 ResultMatrix result(cBlockRows, cBlockCols);
1146 Index maskSize = IsRowMajor ? cBlockCols : cBlockRows;
1161 Index cOuterSize = result.m_blockOuterSize;
1162 Index maxResultNnz = cBlockRows * cBlockCols;
1164 result.resizeBlockStorage_(capacity);
1167 for (
Index out = 0; out < cOuterSize; ++out) {
1168 result.m_outerIndex(out) = StorageIndex_(nnz);
1174 for (
Index rhsId = rhs.m_outerIndex(j); rhsId < rhs.m_outerIndex(j + 1); ++rhsId) {
1175 Index k = rhs.m_innerIndex(rhsId);
1176 typename RhsMatrix::ConstBlockMap Bkj = rhs.
blockRef(rhsId);
1177 for (
Index lhsId = m_outerIndex(k); lhsId < m_outerIndex(k + 1); ++lhsId) {
1178 Index bi = m_innerIndex(lhsId);
1179 if (!mask.
coeff(bi)) {
1182 indices(nIndices++) = bi;
1192 for (
Index lhsId = m_outerIndex(bi); lhsId < m_outerIndex(bi + 1); ++lhsId) {
1193 Index k = m_innerIndex(lhsId);
1194 ConstBlockMap Aik =
blockRef(lhsId);
1195 for (
Index rhsId = rhs.m_outerIndex(k); rhsId < rhs.m_outerIndex(k + 1); ++rhsId) {
1196 Index j = rhs.m_innerIndex(rhsId);
1197 if (!mask.
coeff(j)) {
1200 indices(nIndices++) = j;
1209 std::sort(indices.
data(), indices.
data() + nIndices);
1210 if (nnz + nIndices > capacity) {
1211 capacity = numext::mini(maxResultNnz, numext::maxi(2 * capacity, nnz + nIndices));
1212 result.conservativeResizeBlockStorage_(capacity);
1214 for (
Index ki = 0; ki < nIndices; ++ki) {
1215 Index idx = indices(ki);
1216 result.m_innerIndex(nnz) = StorageIndex_(idx);
1223 result.m_outerIndex(cOuterSize) = StorageIndex_(nnz);
1226 result.conservativeResizeBlockStorage_(nnz);
1250template <
typename BSM,
int Mode,
bool DiagIsTriangular = false>
1251class BlockSparseTriangularView {
1253 using Scalar =
typename BSM::Scalar;
1254 using StorageIndex =
typename BSM::StorageIndex;
1255 using BlockType =
typename BSM::BlockType;
1256 using BlockMap =
typename BSM::BlockMap;
1257 using ConstBlockMap =
typename BSM::ConstBlockMap;
1258 static constexpr int BlockRows = BSM::BlockRows;
1259 static constexpr int BlockCols = BSM::BlockCols;
1260 static constexpr int BlockSize = BSM::BlockSize;
1261 static constexpr bool IsRowMajor = BSM::IsRowMajor;
1262 static constexpr bool IsUpper = (Mode &
Upper) != 0;
1264 explicit BlockSparseTriangularView(
const BSM& m) : m_matrix(m) {}
1266 Index rows()
const {
return m_matrix.rows(); }
1267 Index cols()
const {
return m_matrix.cols(); }
1276 const BSM& m = m_matrix;
1277 BSM result(m.blockRows(), m.blockCols());
1278 result.resizeBlockStorage_(m.nonZeroBlocks());
1281 for (Index out = 0; out < m.m_blockOuterSize; ++out) {
1282 result.m_outerIndex(out) = StorageIndex(nnz);
1283 for (Index
id = m.m_outerIndex(out);
id < m.m_outerIndex(out + 1); ++
id) {
1284 Index inner = m.m_innerIndex(
id);
1285 Index bi = IsRowMajor ? out : inner;
1286 Index bj = IsRowMajor ? inner : out;
1287 if (IsUpper ? (bj < bi) : (bj > bi))
continue;
1288 result.m_innerIndex(nnz) = StorageIndex(inner);
1289 result.m_values.template segment<BlockSize>(nnz * BlockSize) =
1290 m.m_values.template segment<BlockSize>(
id * BlockSize);
1291 EIGEN_IF_CONSTEXPR (!DiagIsTriangular) {
1293 BlockMap(result.m_values.data() + nnz * BlockSize).template triangularView<ZeroMode>().setZero();
1298 result.m_outerIndex(m.m_blockOuterSize) = StorageIndex(nnz);
1299 result.conservativeResizeBlockStorage_(nnz);
1309 BSM operator-(
const BlockSparseTriangularView& other)
const {
return eval() - other.eval(); }
1312 template <
int RhsBlockCols>
1315 return eval() * rhs;
1320 template <
typename OtherDerived>
1322 EIGEN_STATIC_ASSERT(
1323 (std::is_same<Scalar, typename OtherDerived::Scalar>::value),
1324 YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
1325 eigen_assert(m_matrix.cols() == rhs.rows() &&
"BlockSparseTriangularView * Dense: dimension mismatch");
1327 ResultType result = ResultType::Zero(m_matrix.rows(), rhs.cols());
1328 for (Index out = 0; out < m_matrix.m_blockOuterSize; ++out) {
1329 for (Index
id = m_matrix.m_outerIndex(out);
id < m_matrix.m_outerIndex(out + 1); ++
id) {
1330 Index inner = m_matrix.m_innerIndex(
id);
1331 Index bi = IsRowMajor ? out : inner;
1332 Index bj = IsRowMajor ? inner : out;
1333 if (IsUpper ? (bj < bi) : (bj > bi))
continue;
1334 constexpr int DiagMode = IsUpper ?
Upper :
Lower;
1335 if (!DiagIsTriangular && bi == bj)
1336 result.template middleRows<BlockRows>(bi * BlockRows).noalias() +=
1337 m_matrix.blockRef(
id).template triangularView<DiagMode>() *
1338 rhs.template middleRows<BlockCols>(bj * BlockCols);
1340 result.template middleRows<BlockRows>(bi * BlockRows).noalias() +=
1341 m_matrix.blockRef(
id) * rhs.template middleRows<BlockCols>(bj * BlockCols);
1347 template <
typename OtherDerived>
1348 friend Matrix<Scalar, OtherDerived::RowsAtCompileTime, Dynamic>
operator*(
const MatrixBase<OtherDerived>& lhs,
1349 const BlockSparseTriangularView& tri) {
1350 EIGEN_STATIC_ASSERT(
1351 (std::is_same<Scalar, typename OtherDerived::Scalar>::value),
1352 YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
1353 eigen_assert(lhs.cols() == tri.m_matrix.rows() &&
"Dense * BlockSparseTriangularView: dimension mismatch");
1354 constexpr bool isRM = BSM::IsRowMajor;
1355 using ResultType = Matrix<Scalar, OtherDerived::RowsAtCompileTime, Dynamic>;
1359 const BSM& m = tri.m_matrix;
1360 const StorageIndex* outerPtr = m.outerIndexPtr();
1361 const StorageIndex* innerPtr = m.innerIndexPtr();
1362 ResultType result = ResultType::Zero(lhs.rows(), m.cols());
1363 for (Index out = 0; out < m.blockOuterSize(); ++out) {
1364 for (Index
id = outerPtr[out];
id < outerPtr[out + 1]; ++id) {
1365 Index inner = innerPtr[id];
1366 Index bi = isRM ? out : inner;
1367 Index bj = isRM ? inner : out;
1368 if (IsUpper ? (bj < bi) : (bj > bi))
continue;
1369 constexpr int DiagMode = IsUpper ?
Upper :
Lower;
1370 if (!DiagIsTriangular && bi == bj)
1371 result.template middleCols<BlockCols>(bj * BlockCols).noalias() +=
1372 lhs.template middleCols<BlockRows>(bi * BlockRows) * m.blockRef(
id).template triangularView<DiagMode>();
1374 result.template middleCols<BlockCols>(bj * BlockCols).noalias() +=
1375 lhs.template middleCols<BlockRows>(bi * BlockRows) * m.blockRef(
id);
1389 template <
typename Derived>
1391 doSolveImpl<false, false>(x.derived());
1396 const BlockSparseTriangularView& m_tri;
1397 template <
typename Derived>
1399 m_tri.template doSolveImpl<true, false>(x.derived());
1405 const BlockSparseTriangularView& m_tri;
1406 template <
typename Derived>
1408 m_tri.template doSolveImpl<true, true>(x.derived());
1413 AdjointReturnType adjoint()
const {
return {*
this}; }
1416 const BSM& m_matrix;
1425 template <
typename Derived>
1426 void doSolveDirect(Derived& x)
const {
1427 EIGEN_STATIC_ASSERT(BlockRows == BlockCols, THIS_METHOD_IS_ONLY_FOR_SQUARE_BLOCK_MATRICES)
1428 constexpr int DiagMode = IsUpper ?
Upper :
Lower;
1429 constexpr bool diagFirst = (IsUpper == BSM::IsRowMajor);
1430 Index nb = m_matrix.blockCols();
1431 eigen_assert(x.rows() == m_matrix.rows() &&
"solveInPlace: size mismatch");
1433 const StorageIndex* innerPtr = m_matrix.innerIndexPtr();
1434 const StorageIndex* outerPtr = m_matrix.outerIndexPtr();
1436 Index outerStart = IsUpper ? nb - 1 : 0;
1437 Index outerEnd = IsUpper ? -1 : nb;
1438 constexpr Index kStep = IsUpper ? -1 : 1;
1440 for (Index k = outerStart; k != outerEnd; k += kStep) {
1441 const StorageIndex* beg = innerPtr + outerPtr[k];
1442 const StorageIndex* end = innerPtr + outerPtr[k + 1];
1443 if (beg == end)
continue;
1444 const StorageIndex* diag_ptr = diagFirst ? beg : end - 1;
1445 const StorageIndex* off_beg = diagFirst ? beg + 1 : beg;
1446 const StorageIndex* off_end = diagFirst ? end : end - 1;
1447 eigen_assert(*diag_ptr == k);
1448 EIGEN_IF_CONSTEXPR (!BSM::IsRowMajor) {
1449 m_matrix.blockRef(diag_ptr - innerPtr)
1450 .template triangularView<DiagMode>()
1451 .solveInPlace(x.template middleRows<BlockRows>(k * BlockRows));
1452 for (
const StorageIndex* it = off_beg; it != off_end; ++it)
1453 x.template middleRows<BlockRows>(*it * BlockRows).noalias() -=
1454 m_matrix.blockRef(it - innerPtr) * x.template middleRows<BlockRows>(k * BlockRows);
1456 for (
const StorageIndex* it = off_beg; it != off_end; ++it)
1457 x.template middleRows<BlockRows>(k * BlockRows).noalias() -=
1458 m_matrix.blockRef(it - innerPtr) * x.template middleRows<BlockRows>(*it * BlockRows);
1459 m_matrix.blockRef(diag_ptr - innerPtr)
1460 .template triangularView<DiagMode>()
1461 .solveInPlace(x.template middleRows<BlockRows>(k * BlockRows));
1471 template <
bool Conjugate,
typename Derived>
1472 void doSolveTransposed(Derived& x)
const {
1473 EIGEN_STATIC_ASSERT(BlockRows == BlockCols, THIS_METHOD_IS_ONLY_FOR_SQUARE_BLOCK_MATRICES)
1474 constexpr int DiagMode = IsUpper ?
Upper :
Lower;
1475 constexpr bool diagFirst = (IsUpper == BSM::IsRowMajor);
1476 Index nb = m_matrix.blockCols();
1477 eigen_assert(x.rows() == m_matrix.rows() &&
"solveInPlace: size mismatch");
1479 const StorageIndex* innerPtr = m_matrix.innerIndexPtr();
1480 const StorageIndex* outerPtr = m_matrix.outerIndexPtr();
1482 Index outerStart = IsUpper ? 0 : nb - 1;
1483 Index outerEnd = IsUpper ? nb : -1;
1484 constexpr Index kStep = IsUpper ? 1 : -1;
1486 for (Index k = outerStart; k != outerEnd; k += kStep) {
1487 const StorageIndex* beg = innerPtr + outerPtr[k];
1488 const StorageIndex* end = innerPtr + outerPtr[k + 1];
1489 if (beg == end)
continue;
1490 const StorageIndex* diag_ptr = diagFirst ? beg : end - 1;
1491 const StorageIndex* off_beg = diagFirst ? beg + 1 : beg;
1492 const StorageIndex* off_end = diagFirst ? end : end - 1;
1493 eigen_assert(*diag_ptr == k);
1494 EIGEN_IF_CONSTEXPR (!BSM::IsRowMajor) {
1495 for (
const StorageIndex* it = off_beg; it != off_end; ++it)
1496 x.template middleRows<BlockRows>(k * BlockRows).noalias() -=
1497 internal::adjoint_if<Conjugate>(m_matrix.blockRef(it - innerPtr)) *
1498 x.template middleRows<BlockRows>(*it * BlockRows);
1499 internal::adjoint_if<Conjugate>(m_matrix.blockRef(diag_ptr - innerPtr).template triangularView<DiagMode>())
1500 .solveInPlace(x.template middleRows<BlockRows>(k * BlockRows));
1502 internal::adjoint_if<Conjugate>(m_matrix.blockRef(diag_ptr - innerPtr).template triangularView<DiagMode>())
1503 .solveInPlace(x.template middleRows<BlockRows>(k * BlockRows));
1504 for (
const StorageIndex* it = off_beg; it != off_end; ++it)
1505 x.template middleRows<BlockRows>(*it * BlockRows).noalias() -=
1506 internal::adjoint_if<Conjugate>(m_matrix.blockRef(it - innerPtr)) *
1507 x.template middleRows<BlockRows>(k * BlockRows);
1512 template <
bool Transposed,
bool Conjugate,
typename Derived>
1513 void doSolveImpl(Derived& x)
const {
1514 EIGEN_IF_CONSTEXPR (!Transposed)
1517 doSolveTransposed<Conjugate>(x);
1538template <
typename BSM,
int UpLo,
bool DiagIsSelfAdjo
int>
1539class BlockSparseSelfAdjointView {
1541 using Scalar =
typename BSM::Scalar;
1542 using StorageIndex =
typename BSM::StorageIndex;
1543 using BlockType =
typename BSM::BlockType;
1544 using BlockMap =
typename BSM::BlockMap;
1545 using ConstBlockMap =
typename BSM::ConstBlockMap;
1546 static constexpr int BlockRows = BSM::BlockRows;
1547 static constexpr int BlockCols = BSM::BlockCols;
1548 static constexpr int BlockSize = BSM::BlockSize;
1549 static constexpr bool IsRowMajor = BSM::IsRowMajor;
1550 static constexpr bool IsUpper = (UpLo &
Upper) != 0;
1552 static constexpr int DiagUpLo = IsUpper ?
Upper :
Lower;
1554 explicit BlockSparseSelfAdjointView(
const BSM& m) : m_matrix(m) {}
1556 Index rows()
const {
return m_matrix.rows(); }
1557 Index cols()
const {
return m_matrix.cols(); }
1566 const BSM& m = m_matrix;
1568 Index nDiag = 0, nOff = 0;
1569 for (Index out = 0; out < m.m_blockOuterSize; ++out)
1570 for (Index
id = m.m_outerIndex(out);
id < m.m_outerIndex(out + 1); ++
id) {
1571 Index inner = m.m_innerIndex(
id);
1572 Index bi = IsRowMajor ? out : inner;
1573 Index bj = IsRowMajor ? inner : out;
1574 if (IsUpper ? (bj < bi) : (bj > bi))
continue;
1581 Index nTotal = nDiag + 2 * nOff;
1587 for (Index out = 0; out < m.m_blockOuterSize; ++out)
1588 for (Index
id = m.m_outerIndex(out);
id < m.m_outerIndex(out + 1); ++
id) {
1589 Index inner = m.m_innerIndex(
id);
1590 Index bi = IsRowMajor ? out : inner;
1591 Index bj = IsRowMajor ? inner : out;
1592 if (IsUpper ? (bj < bi) : (bj > bi))
continue;
1594 brows(k) = StorageIndex(bi);
1595 bcols(k) = StorageIndex(bj);
1596 if (!DiagIsSelfAdjoint && bi == bj)
1597 BlockMap(bvals.
data() + k * BlockSize) = m.blockRef(
id).template selfadjointView<DiagUpLo>();
1599 BlockMap(bvals.
data() + k * BlockSize) = m.blockRef(
id);
1603 brows(k) = StorageIndex(bj);
1604 bcols(k) = StorageIndex(bi);
1605 BlockMap(bvals.
data() + k * BlockSize) = m.blockRef(
id).adjoint();
1612 std::iota(perm.
data(), perm.
data() + nTotal, Index(0));
1613 std::sort(perm.
data(), perm.
data() + nTotal, [&](Index a, Index b) {
1614 StorageIndex ao = IsRowMajor ? brows(a) : bcols(a);
1615 StorageIndex bo = IsRowMajor ? brows(b) : bcols(b);
1616 if (ao != bo) return ao < bo;
1617 return (IsRowMajor ? bcols(a) : brows(a)) < (IsRowMajor ? bcols(b) : brows(b));
1620 BSM result(m.blockRows(), m.blockCols());
1621 result.resizeBlockStorage_(nTotal);
1623 for (Index ki = 0; ki < nTotal; ++ki) {
1624 Index pi = perm(ki);
1625 StorageIndex outer = IsRowMajor ? brows(pi) : bcols(pi);
1626 StorageIndex inner = IsRowMajor ? bcols(pi) : brows(pi);
1627 result.m_outerIndex(outer + 1)++;
1628 result.m_innerIndex(ki) = inner;
1629 result.m_values.template segment<BlockSize>(ki * BlockSize) = bvals.template segment<BlockSize>(pi * BlockSize);
1631 for (Index j = 0; j < result.m_blockOuterSize; ++j) result.m_outerIndex(j + 1) += result.m_outerIndex(j);
1642 BSM operator-(
const BlockSparseSelfAdjointView& other)
const {
return eval() - other.eval(); }
1645 template <
int RhsBlockCols>
1648 return eval() * rhs;
1664 template <
typename OtherDerived>
1666 EIGEN_STATIC_ASSERT(
1667 (std::is_same<Scalar, typename OtherDerived::Scalar>::value),
1668 YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
1669 eigen_assert(m_matrix.cols() == rhs.rows() &&
"BlockSparseSelfAdjointView * Dense: dimension mismatch");
1671 ResultType result = ResultType::Zero(m_matrix.rows(), rhs.cols());
1673 for (Index out = 0; out < m_matrix.m_blockOuterSize; ++out)
1674 for (Index
id = m_matrix.m_outerIndex(out);
id < m_matrix.m_outerIndex(out + 1); ++
id) {
1675 Index inner = m_matrix.m_innerIndex(
id);
1676 Index bi = IsRowMajor ? out : inner;
1677 Index bj = IsRowMajor ? inner : out;
1678 if (IsUpper ? (bj < bi) : (bj > bi))
continue;
1681 EIGEN_IF_CONSTEXPR (DiagIsSelfAdjoint) {
1682 result.template middleRows<BlockRows>(bi * BlockRows).noalias() +=
1683 m_matrix.blockRef(
id) * rhs.template middleRows<BlockCols>(bj * BlockCols);
1689 BlockType diag = m_matrix.blockRef(
id).template selfadjointView<DiagUpLo>();
1690 result.template middleRows<BlockRows>(bi * BlockRows).noalias() +=
1691 diag * rhs.template middleRows<BlockCols>(bj * BlockCols);
1694 result.template middleRows<BlockRows>(bi * BlockRows).noalias() +=
1695 m_matrix.blockRef(
id) * rhs.template middleRows<BlockCols>(bj * BlockCols);
1696 result.template middleRows<BlockRows>(bj * BlockRows).noalias() +=
1697 m_matrix.blockRef(
id).adjoint() * rhs.template middleRows<BlockRows>(bi * BlockRows);
1704 template <
typename OtherDerived>
1706 const BlockSparseSelfAdjointView& view) {
1707 EIGEN_STATIC_ASSERT(
1708 (std::is_same<Scalar, typename OtherDerived::Scalar>::value),
1709 YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
1710 return (view * lhs.adjoint()).adjoint();
1714 const BSM& m_matrix;
1721template <
typename Scalar_,
int Options_,
int BlockRows_,
int BlockCols_,
typename StorageIndex_>
1722template <
bool Conjugate>
1723BlockSparseMatrix<Scalar_, Options_, BlockCols_, BlockRows_, StorageIndex_>
1724BlockSparseMatrix<Scalar_, Options_, BlockRows_, BlockCols_, StorageIndex_>::transposeImpl()
const {
1725 using ResultType = BlockSparseMatrix<Scalar_, Options_, BlockCols_, BlockRows_, StorageIndex_>;
1726 ResultType result(blockCols(), blockRows());
1729 for (Index
id = 0;
id < nonZeroBlocks(); ++id) result.m_outerIndex(m_innerIndex(
id) + 1)++;
1732 for (Index j = 0; j < result.m_blockOuterSize; ++j) result.m_outerIndex(j + 1) += result.m_outerIndex(j);
1734 Index nnz = nonZeroBlocks();
1735 result.resizeBlockStorage_(nnz);
1740 Array<StorageIndex_, Dynamic, 1> pos = result.m_outerIndex.head(result.m_blockOuterSize);
1742 for (Index oldOuter = 0; oldOuter < m_blockOuterSize; ++oldOuter) {
1743 for (Index
id = m_outerIndex(oldOuter);
id < m_outerIndex(oldOuter + 1); ++id) {
1744 Index newOuter = m_innerIndex(
id);
1745 Index insertAt = pos(newOuter)++;
1746 result.m_innerIndex(insertAt) = StorageIndex_(oldOuter);
1747 result.blockRef(insertAt) = internal::adjoint_if<Conjugate>(blockRef(
id));
1753template <
typename Scalar_,
int Options_,
int BlockRows_,
int BlockCols_,
typename StorageIndex_>
1756 return transposeImpl<false>();
1759template <
typename Scalar_,
int Options_,
int BlockRows_,
int BlockCols_,
typename StorageIndex_>
1762 return transposeImpl<true>();
1771template <
typename Lhs,
typename Rhs,
int ProductType>
1772struct generic_product_impl<Lhs, Rhs,
BlockSparseShape, DenseShape, ProductType>
1773 : generic_product_impl_base<Lhs, Rhs, generic_product_impl<Lhs, Rhs, BlockSparseShape, DenseShape, ProductType>> {
1776 template <
typename Dst>
1777 static void scaleAndAddTo(Dst& dst,
const Lhs& lhs,
const Rhs& rhs,
const Scalar& alpha) {
1778 constexpr bool IsRM = (Lhs::Options &
RowMajorBit) != 0;
1779 constexpr int BR = Lhs::BlockRows;
1780 constexpr int BC = Lhs::BlockCols;
1781 const typename Lhs::StorageIndex* outerPtr = lhs.outerIndexPtr();
1782 const typename Lhs::StorageIndex* innerPtr = lhs.innerIndexPtr();
1785 bool a1 = (alpha == Scalar(1));
1786 bool am1 = (alpha == Scalar(-1));
1787 for (Eigen::Index out = 0; out < lhs.blockOuterSize(); ++out) {
1788 for (Eigen::Index
id = outerPtr[out];
id < outerPtr[out + 1]; ++id) {
1789 Eigen::Index inner = innerPtr[id];
1790 Eigen::Index bi = IsRM ? out : inner;
1791 Eigen::Index bj = IsRM ? inner : out;
1792 auto dst_seg = dst.template middleRows<BR>(bi * BR);
1793 auto rhs_seg = rhs.template middleRows<BC>(bj * BC);
1794 if (EIGEN_PREDICT_TRUE(a1))
1795 dst_seg.noalias() += lhs.blockRef(
id) * rhs_seg;
1797 dst_seg.noalias() -= lhs.blockRef(
id) * rhs_seg;
1802 TmpType tmp(BR, rhs.cols());
1803 tmp.noalias() = lhs.blockRef(
id) * rhs_seg;
1804 dst_seg += alpha * tmp;
1814template <
typename Lhs,
typename Rhs,
int ProductType>
1815struct generic_product_impl<Lhs, Rhs, DenseShape, BlockSparseShape, ProductType>
1816 : generic_product_impl_base<Lhs, Rhs, generic_product_impl<Lhs, Rhs, DenseShape, BlockSparseShape, ProductType>> {
1817 using Scalar =
typename Product<Lhs, Rhs>::Scalar;
1819 template <
typename Dst>
1820 static void scaleAndAddTo(Dst& dst,
const Lhs& lhs,
const Rhs& rhs,
const Scalar& alpha) {
1821 constexpr bool IsRM = (Rhs::Options &
RowMajorBit) != 0;
1822 constexpr int BR = Rhs::BlockRows;
1823 constexpr int BC = Rhs::BlockCols;
1824 const typename Rhs::StorageIndex* outerPtr = rhs.outerIndexPtr();
1825 const typename Rhs::StorageIndex* innerPtr = rhs.innerIndexPtr();
1826 bool a1 = (alpha == Scalar(1));
1827 bool am1 = (alpha == Scalar(-1));
1828 for (Eigen::Index out = 0; out < rhs.blockOuterSize(); ++out) {
1829 for (Eigen::Index
id = outerPtr[out];
id < outerPtr[out + 1]; ++id) {
1830 Eigen::Index inner = innerPtr[id];
1831 Eigen::Index bi = IsRM ? out : inner;
1832 Eigen::Index bj = IsRM ? inner : out;
1833 auto dst_seg = dst.template middleCols<BC>(bj * BC);
1834 auto lhs_seg = lhs.template middleCols<BR>(bi * BR);
1835 if (EIGEN_PREDICT_TRUE(a1))
1836 dst_seg.noalias() += lhs_seg * rhs.blockRef(
id);
1838 dst_seg.noalias() -= lhs_seg * rhs.blockRef(
id);
1840 using TmpType = Matrix<Scalar, Lhs::RowsAtCompileTime, BC>;
1841 TmpType tmp(lhs.rows(), BC);
1842 tmp.noalias() = lhs_seg * rhs.blockRef(
id);
1843 dst_seg += alpha * tmp;
General-purpose arrays with easy API for coefficient-wise operations.
Definition Array.h:55
constexpr const Scalar & coeff(Index rowId, Index colId) const
Definition PlainObjectBase.h:187
constexpr Scalar & coeffRef(Index rowId, Index colId)
Definition PlainObjectBase.h:205
Index blockCol() const
Definition BlockSparseMatrix.h:287
Index index() const
Definition BlockSparseMatrix.h:283
BlockMap valueRef()
Definition BlockSparseMatrix.h:292
ConstBlockMap value() const
Definition BlockSparseMatrix.h:290
Index outer() const
Definition BlockSparseMatrix.h:281
Index blockRow() const
Definition BlockSparseMatrix.h:285
A sparse matrix whose stored nonzeros are fixed-size dense blocks.
Definition BlockSparseMatrix.h:160
Index nonZeros() const
Definition BlockSparseMatrix.h:237
Index cols() const noexcept
Definition BlockSparseMatrix.h:217
BlockSparseMatrix operator+(const BlockSparseMatrix &other) const
Definition BlockSparseMatrix.h:476
Matrix< Scalar, Dynamic, 1 > diagonal() const
Definition BlockSparseMatrix.h:435
BlockSparseMatrix()=default
void reserve(Index n)
Definition BlockSparseMatrix.h:324
void setZero()
Definition BlockSparseMatrix.h:317
Index nonZeroBlocks() const
Definition BlockSparseMatrix.h:235
Scalar coeff(Index row, Index col) const
Definition BlockSparseMatrix.h:415
BlockSparseMatrix(Index blockRows, Index blockCols)
Definition BlockSparseMatrix.h:207
Index blockRows() const
Definition BlockSparseMatrix.h:220
Index rows() const noexcept
Definition BlockSparseMatrix.h:215
BlockSparseMatrix cwiseProduct(const BlockSparseMatrix &other) const
Definition BlockSparseMatrix.h:482
void resize(Index blockRows, Index blockCols)
Definition BlockSparseMatrix.h:309
friend BlockSparseMatrix operator*(const Scalar &s, const BlockSparseMatrix &m)
Definition BlockSparseMatrix.h:535
Index allocatedBlocks() const
Definition BlockSparseMatrix.h:239
void setFromOuterInner(Index blockRows, Index blockCols, Index nnzBlocks, const StorageIndex_ *outerPtr, const StorageIndex_ *innerPtr)
Definition BlockSparseMatrix.h:357
Index innerSize() const
Definition BlockSparseMatrix.h:232
Index blockCols() const
Definition BlockSparseMatrix.h:222
BlockSparseMatrix disjunctionExpr(const BlockSparseMatrix &other, ScalarFunc func) const
Definition BlockSparseMatrix.h:502
BlockSparseMatrix< Scalar_, Options_, BlockCols_, BlockRows_, StorageIndex_ > transpose() const
Definition BlockSparseMatrix.h:1755
BlockSparseMatrix conjunctionExpr(const BlockSparseMatrix &other, ScalarFunc func) const
Definition BlockSparseMatrix.h:509
void setFromTriplets(InputIterator begin, InputIterator end)
Definition BlockSparseMatrix.h:923
static BlockSparseMatrix fromSparse(const SparseMatrix< Scalar_, Options_, StorageIndex_ > &sp)
Definition BlockSparseMatrix.h:1054
BlockMap blockRef(Index k)
Definition BlockSparseMatrix.h:258
friend Product< OtherDerived, BlockSparseMatrix, AliasFreeProduct > operator*(const MatrixBase< OtherDerived > &lhs, const BlockSparseMatrix &bsm)
Definition BlockSparseMatrix.h:572
Index blockOuterSize() const
Definition BlockSparseMatrix.h:225
void squeeze()
Definition BlockSparseMatrix.h:329
BlockSparseMatrix operator-(const BlockSparseMatrix &other) const
Definition BlockSparseMatrix.h:479
BlockSparseTriangularView< BlockSparseMatrix, Mode, DiagIsTriangular > triangularView() const
Definition BlockSparseMatrix.h:640
void setIdentity()
Definition BlockSparseMatrix.h:339
BlockSparseSelfAdjointView< BlockSparseMatrix, UpLo, DiagIsSelfAdjoint > selfadjointView() const
Definition BlockSparseMatrix.h:661
Index outerSize() const
Definition BlockSparseMatrix.h:230
BlockSparseMatrix operator-() const
Definition BlockSparseMatrix.h:514
BlockSparseMatrix operator*(const Scalar &s) const
Definition BlockSparseMatrix.h:522
Index blockInnerSize() const
Definition BlockSparseMatrix.h:227
BlockSparseMatrix< Scalar_, Options_, BlockCols_, BlockRows_, StorageIndex_ > adjoint() const
Definition BlockSparseMatrix.h:1761
BlockSparseMatrix unaryExpr(ScalarFunc func) const
Definition BlockSparseMatrix.h:488
Product< BlockSparseMatrix, OtherDerived, AliasFreeProduct > operator*(const MatrixBase< OtherDerived > &rhs) const
Definition BlockSparseMatrix.h:554
ConstBlockMap blockRef(Index k) const
Definition BlockSparseMatrix.h:256
SparseMatrix< Scalar, Options_, StorageIndex_ > toSparse() const
Definition BlockSparseMatrix.h:1006
Lazy block-level self-adjoint (Hermitian) view of a BlockSparseMatrix.
Definition BlockSparseMatrix.h:1539
BSM eval() const
Definition BlockSparseMatrix.h:1565
friend Matrix< Scalar, OtherDerived::RowsAtCompileTime, Dynamic > operator*(const MatrixBase< OtherDerived > &lhs, const BlockSparseSelfAdjointView &view)
Definition BlockSparseMatrix.h:1705
SparseMatrix< Scalar, BSM::Options, StorageIndex > toSparse() const
Definition BlockSparseMatrix.h:1637
Matrix< Scalar, Dynamic, OtherDerived::ColsAtCompileTime > operator*(const MatrixBase< OtherDerived > &rhs) const
Definition BlockSparseMatrix.h:1665
BlockSparseMatrix< Scalar, BSM::Options, BlockRows, RhsBlockCols, StorageIndex > operator*(const BlockSparseMatrix< Scalar, BSM::Options, BlockCols, RhsBlockCols, StorageIndex > &rhs) const
Definition BlockSparseMatrix.h:1646
Lazy block-level triangular view of a BlockSparseMatrix.
Definition BlockSparseMatrix.h:1251
BlockSparseMatrix< Scalar, BSM::Options, BlockRows, RhsBlockCols, StorageIndex > operator*(const BlockSparseMatrix< Scalar, BSM::Options, BlockCols, RhsBlockCols, StorageIndex > &rhs) const
Definition BlockSparseMatrix.h:1313
SparseMatrix< Scalar, BSM::Options, StorageIndex > toSparse() const
Definition BlockSparseMatrix.h:1304
void solveInPlace(MatrixBase< Derived > &x) const
Definition BlockSparseMatrix.h:1390
BSM eval() const
Definition BlockSparseMatrix.h:1274
A (blockRow, blockCol, blockValue) triplet for assembling a BlockSparseMatrix.
Definition BlockSparseMatrix.h:89
A matrix or vector expression mapping an existing array of data.
Definition Map.h:97
Base class for all dense matrices, vectors, and expressions.
Definition MatrixBase.h:53
The matrix class, also used for vectors and row-vectors.
Definition Matrix.h:188
constexpr const Scalar * data() const
Definition PlainObjectBase.h:261
Derived & setZero(Index size)
Definition CwiseNullaryOp.h:536
Expression of the product of two arbitrary matrices or vectors.
Definition Product.h:203
A versatile sparse matrix representation.
Definition SparseMatrix.h:122
bool isCompressed() const
Definition SparseCompressedBase.h:115
Index cols() const
Definition SparseMatrix.h:162
Index rows() const
Definition SparseMatrix.h:160
void reserve(Index reserveSize)
Definition SparseMatrix.h:317
@ StrictlyLower
Definition Constants.h:224
@ StrictlyUpper
Definition Constants.h:226
@ Lower
Definition Constants.h:212
@ Upper
Definition Constants.h:214
constexpr unsigned int LvalueBit
Definition Constants.h:149
constexpr unsigned int RowMajorBit
Definition Constants.h:71
Definition BlockSparseMatrix.h:34
Definition BlockSparseMatrix.h:1404
Definition BlockSparseMatrix.h:1395
Definition BlockSparseMatrix.h:31
Definition EigenBase.h:34
Eigen::Index Index
Definition EigenBase.h:44