| 1504 | template <typename Scalar_, int Options_, typename StorageIndex_> |
| 1505 | template <typename Derived, typename DupFunctor> |
| 1506 | void SparseMatrix<Scalar_, Options_, StorageIndex_>::collapseDuplicates(DenseBase<Derived>& wi, DupFunctor dup_func) { |
| 1507 | // removes duplicate entries and compresses the matrix |
| 1508 | // the excess allocated memory is not released |
| 1509 | // the inner indices do not need to be sorted, nor is the matrix returned in a sorted state |
| 1510 | eigen_assert(wi.size() == m_innerSize); |
| 1511 | constexpr StorageIndex kEmptyIndexValue(-1); |
| 1512 | wi.setConstant(kEmptyIndexValue); |
| 1513 | StorageIndex count = 0; |
| 1514 | const bool is_compressed = isCompressed(); |
| 1515 | // for each inner-vector, wi[inner_index] will hold the position of first element into the index/value buffers |
| 1516 | for (Index j = 0; j < m_outerSize; ++j) { |
| 1517 | const StorageIndex newBegin = count; |
| 1518 | const StorageIndex end = is_compressed ? m_outerIndex[j + 1] : m_outerIndex[j] + m_innerNonZeros[j]; |
| 1519 | for (StorageIndex k = m_outerIndex[j]; k < end; ++k) { |
| 1520 | StorageIndex i = m_data.index(k); |
| 1521 | if (wi(i) >= newBegin) { |
| 1522 | // entry at k is a duplicate |
| 1523 | // accumulate it into the primary entry located at wi(i) |
| 1524 | m_data.value(wi(i)) = dup_func(m_data.value(wi(i)), m_data.value(k)); |
| 1525 | } else { |
| 1526 | // k is the primary entry in j with inner index i |
| 1527 | // shift it to the left and record its location at wi(i) |
| 1528 | m_data.index(count) = i; |
| 1529 | m_data.value(count) = m_data.value(k); |
| 1530 | wi(i) = count; |
| 1531 | ++count; |
| 1532 | } |
| 1533 | } |
| 1534 | m_outerIndex[j] = newBegin; |
| 1535 | } |
| 1536 | m_outerIndex[m_outerSize] = count; |
| 1537 | m_data.resize(count); |
| 1538 | |
| 1539 | // turn the matrix into compressed form (if it is not already) |
| 1540 | internal::conditional_aligned_delete_auto<StorageIndex, true>(m_innerNonZeros, m_outerSize); |
| 1541 | m_innerNonZeros = 0; |
| 1542 | } |
| 1543 | |
| 1544 | /** \internal */ |
| 1545 | template<typename Scalar, int Options_, typename StorageIndex_> |
no test coverage detected