mirror of
https://gitlab.com/libeigen/eigen.git
synced 2025-06-04 18:54:00 +08:00
change insert strategy
This commit is contained in:
parent
c54785b071
commit
9463fc95f4
@ -92,6 +92,31 @@ struct traits<Diagonal<const SparseMatrix<Scalar_, Options_, StorageIndex_>, Dia
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename StorageIndex>
|
||||||
|
struct sparse_reserve_op {
|
||||||
|
EIGEN_DEVICE_FUNC sparse_reserve_op(Index begin, Index end, Index size) {
|
||||||
|
Index range = numext::mini(end - begin, size);
|
||||||
|
m_begin = begin;
|
||||||
|
m_end = begin + range;
|
||||||
|
m_val = StorageIndex(size / range);
|
||||||
|
m_remainder = StorageIndex(size % range);
|
||||||
|
}
|
||||||
|
template <typename IndexType>
|
||||||
|
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE StorageIndex operator()(IndexType i) const {
|
||||||
|
if ((i >= m_begin) && (i < m_end))
|
||||||
|
return m_val + ((i - m_begin) < m_remainder ? 1 : 0);
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
StorageIndex m_val, m_remainder;
|
||||||
|
Index m_begin, m_end;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Scalar>
|
||||||
|
struct functor_traits<sparse_reserve_op<Scalar>> {
|
||||||
|
enum { Cost = 1, PacketAccess = false, IsRepeatable = true };
|
||||||
|
};
|
||||||
|
|
||||||
} // end namespace internal
|
} // end namespace internal
|
||||||
|
|
||||||
template<typename Scalar_, int Options_, typename StorageIndex_>
|
template<typename Scalar_, int Options_, typename StorageIndex_>
|
||||||
@ -971,7 +996,7 @@ protected:
|
|||||||
assignFunc.assignCoeff(insertBackUncompressed(j, j), diaEval.coeff(j));
|
assignFunc.assignCoeff(insertBackUncompressed(j, j), diaEval.coeff(j));
|
||||||
// the insertion requires a data move, record insertion location and handle in second pass
|
// the insertion requires a data move, record insertion location and handle in second pass
|
||||||
else {
|
else {
|
||||||
insertionLocations.coeffRef(j) = dst;
|
insertionLocations.coeffRef(j) = StorageIndex(dst);
|
||||||
deferredInsertions++;
|
deferredInsertions++;
|
||||||
// if there is no capacity, all vectors to the right of this are shifted
|
// if there is no capacity, all vectors to the right of this are shifted
|
||||||
if (capacity == 0) shift++;
|
if (capacity == 0) shift++;
|
||||||
@ -1373,9 +1398,7 @@ inline typename SparseMatrix<Scalar_, Options_, StorageIndex_>::Scalar& SparseMa
|
|||||||
template <typename Scalar_, int Options_, typename StorageIndex_>
|
template <typename Scalar_, int Options_, typename StorageIndex_>
|
||||||
EIGEN_STRONG_INLINE typename SparseMatrix<Scalar_, Options_, StorageIndex_>::Scalar&
|
EIGEN_STRONG_INLINE typename SparseMatrix<Scalar_, Options_, StorageIndex_>::Scalar&
|
||||||
SparseMatrix<Scalar_, Options_, StorageIndex_>::insertAtByOuterInner(Index outer, Index inner, Index dst) {
|
SparseMatrix<Scalar_, Options_, StorageIndex_>::insertAtByOuterInner(Index outer, Index inner, Index dst) {
|
||||||
if (isCompressed())
|
uncompress();
|
||||||
return insertCompressedAtByOuterInner(outer, inner, dst);
|
|
||||||
else
|
|
||||||
return insertUncompressedAtByOuterInner(outer, inner, dst);
|
return insertUncompressedAtByOuterInner(outer, inner, dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1429,7 +1452,8 @@ SparseMatrix<Scalar_, Options_, StorageIndex_>::insertCompressedAtByOuterInner(I
|
|||||||
// shift the existing data to the right if necessary
|
// shift the existing data to the right if necessary
|
||||||
if (chunkSize > 0) data().moveChunk(dst, dst + 1, chunkSize);
|
if (chunkSize > 0) data().moveChunk(dst, dst + 1, chunkSize);
|
||||||
// update nonzero counts
|
// update nonzero counts
|
||||||
for (; outer < outerSize(); outer++) outerIndexPtr()[outer + 1]++;
|
typename IndexVector::AlignedMapType outerIndexMap(outerIndexPtr(), outerSize() + 1);
|
||||||
|
outerIndexMap.segment(outer + 1, outerSize() - outer).array() += 1;
|
||||||
// initialize the coefficient
|
// initialize the coefficient
|
||||||
data().index(dst) = StorageIndex(inner);
|
data().index(dst) = StorageIndex(inner);
|
||||||
// return a reference to the coefficient
|
// return a reference to the coefficient
|
||||||
@ -1455,16 +1479,36 @@ SparseMatrix<Scalar_, Options_, StorageIndex_>::insertUncompressedAtByOuterInner
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (target == outerSize()) {
|
if (target == outerSize()) {
|
||||||
// no room for interior insertion, must expand storage
|
// no room for interior insertion (to the right of `outer`)
|
||||||
checkAllocatedSpaceAndMaybeExpand();
|
target = outer;
|
||||||
data().resize(data().size() + 1);
|
Index dst_offset = dst - outerIndexPtr()[target];
|
||||||
// shift the existing data to the right if necessary
|
Index totalCapacity = data().allocatedSize() - data().size();
|
||||||
Index chunkSize = outerIndexPtr()[outerSize()] - dst;
|
eigen_assert(totalCapacity >= 0);
|
||||||
|
if (totalCapacity == 0) {
|
||||||
|
// there is no room left. we must reallocate. reserve space in each vector
|
||||||
|
constexpr StorageIndex kReserveSizePerVector(2);
|
||||||
|
reserveInnerVectors(IndexVector::Constant(outerSize(), kReserveSizePerVector));
|
||||||
|
} else {
|
||||||
|
// dont reallocate, but re-distribute the remaining capacity to the right of `outer`
|
||||||
|
// each vector in the range [outer,outerSize) will receive totalCapacity / (outerSize - outer) nonzero
|
||||||
|
// reservations each vector in the range [outer,remainder) will receive an additional nonzero reservation where
|
||||||
|
// remainder = totalCapacity % (outerSize - outer)
|
||||||
|
typedef internal::sparse_reserve_op<StorageIndex> ReserveSizesOp;
|
||||||
|
typedef CwiseNullaryOp<ReserveSizesOp, IndexVector> ReserveSizesXpr;
|
||||||
|
ReserveSizesXpr reserveSizesXpr(outerSize(), 1, ReserveSizesOp(target, outerSize(), totalCapacity));
|
||||||
|
eigen_assert(reserveSizesXpr.sum() == totalCapacity);
|
||||||
|
reserveInnerVectors(reserveSizesXpr);
|
||||||
|
}
|
||||||
|
Index start = outerIndexPtr()[target];
|
||||||
|
Index end = start + innerNonZeroPtr()[target];
|
||||||
|
dst = start + dst_offset;
|
||||||
|
Index chunkSize = end - dst;
|
||||||
if (chunkSize > 0) data().moveChunk(dst, dst + 1, chunkSize);
|
if (chunkSize > 0) data().moveChunk(dst, dst + 1, chunkSize);
|
||||||
}
|
}
|
||||||
// update nonzero counts
|
// update nonzero counts
|
||||||
innerNonZeroPtr()[outer]++;
|
innerNonZeroPtr()[outer]++;
|
||||||
for (; outer < target; outer++) outerIndexPtr()[outer + 1]++;
|
typename IndexVector::AlignedMapType outerIndexMap(outerIndexPtr(), outerSize() + 1);
|
||||||
|
outerIndexMap.segment(outer + 1, target - outer).array() += 1;
|
||||||
// initialize the coefficient
|
// initialize the coefficient
|
||||||
data().index(dst) = StorageIndex(inner);
|
data().index(dst) = StorageIndex(inner);
|
||||||
// return a reference to the coefficient
|
// return a reference to the coefficient
|
||||||
|
Loading…
x
Reference in New Issue
Block a user