| 1469 | template <typename Scalar_, int Options_, typename StorageIndex_> |
| 1470 | template <typename Derived, typename DupFunctor> |
| 1471 | void SparseMatrix<Scalar_, Options_, StorageIndex_>::collapseDuplicates(DenseBase<Derived>& wi, DupFunctor dup_func) { |
| 1472 | // removes duplicate entries and compresses the matrix |
| 1473 | // the excess allocated memory is not released |
| 1474 | // the inner indices do not need to be sorted, nor is the matrix returned in a sorted state |
| 1475 | eigen_assert(wi.size() == m_innerSize); |
| 1476 | constexpr StorageIndex kEmptyIndexValue(-1); |
| 1477 | wi.setConstant(kEmptyIndexValue); |
| 1478 | StorageIndex count = 0; |
| 1479 | const bool is_compressed = isCompressed(); |
| 1480 | // for each inner-vector, wi[inner_index] will hold the position of first element into the index/value buffers |
| 1481 | for (Index j = 0; j < m_outerSize; ++j) { |
| 1482 | const StorageIndex newBegin = count; |
| 1483 | const StorageIndex end = is_compressed ? m_outerIndex[j + 1] : m_outerIndex[j] + m_innerNonZeros[j]; |
| 1484 | for (StorageIndex k = m_outerIndex[j]; k < end; ++k) { |
| 1485 | StorageIndex i = m_data.index(k); |
| 1486 | if (wi(i) >= newBegin) { |
| 1487 | // entry at k is a duplicate |
| 1488 | // accumulate it into the primary entry located at wi(i) |
| 1489 | m_data.value(wi(i)) = dup_func(m_data.value(wi(i)), m_data.value(k)); |
| 1490 | } else { |
| 1491 | // k is the primary entry in j with inner index i |
| 1492 | // shift it to the left and record its location at wi(i) |
| 1493 | m_data.index(count) = i; |
| 1494 | m_data.value(count) = m_data.value(k); |
| 1495 | wi(i) = count; |
| 1496 | ++count; |
| 1497 | } |
| 1498 | } |
| 1499 | m_outerIndex[j] = newBegin; |
| 1500 | } |
| 1501 | m_outerIndex[m_outerSize] = count; |
| 1502 | m_data.resize(count); |
| 1503 | |
| 1504 | // turn the matrix into compressed form (if it is not already) |
| 1505 | internal::conditional_aligned_delete_auto<StorageIndex, true>(m_innerNonZeros, m_outerSize); |
| 1506 | m_innerNonZeros = 0; |
| 1507 | } |
| 1508 | |
| 1509 | /** \internal */ |
| 1510 | template <typename Scalar, int Options_, typename StorageIndex_> |
no test coverage detected