| 1015 | template<typename Scalar, int _Options, typename _StorageIndex> |
| 1016 | template<typename DupFunctor> |
| 1017 | void SparseMatrix<Scalar,_Options,_StorageIndex>::collapseDuplicates(DupFunctor dup_func) |
| 1018 | { |
| 1019 | eigen_assert(!isCompressed()); |
| 1020 | // TODO, in practice we should be able to use m_innerNonZeros for that task |
| 1021 | IndexVector wi(innerSize()); |
| 1022 | wi.fill(-1); |
| 1023 | StorageIndex count = 0; |
| 1024 | // for each inner-vector, wi[inner_index] will hold the position of first element into the index/value buffers |
| 1025 | for(Index j=0; j<outerSize(); ++j) |
| 1026 | { |
| 1027 | StorageIndex start = count; |
| 1028 | Index oldEnd = m_outerIndex[j]+m_innerNonZeros[j]; |
| 1029 | for(Index k=m_outerIndex[j]; k<oldEnd; ++k) |
| 1030 | { |
| 1031 | Index i = m_data.index(k); |
| 1032 | if(wi(i)>=start) |
| 1033 | { |
| 1034 | // we already meet this entry => accumulate it |
| 1035 | m_data.value(wi(i)) = dup_func(m_data.value(wi(i)), m_data.value(k)); |
| 1036 | } |
| 1037 | else |
| 1038 | { |
| 1039 | m_data.value(count) = m_data.value(k); |
| 1040 | m_data.index(count) = m_data.index(k); |
| 1041 | wi(i) = count; |
| 1042 | ++count; |
| 1043 | } |
| 1044 | } |
| 1045 | m_outerIndex[j] = start; |
| 1046 | } |
| 1047 | m_outerIndex[m_outerSize] = count; |
| 1048 | |
| 1049 | // turn the matrix into compressed form |
| 1050 | std::free(m_innerNonZeros); |
| 1051 | m_innerNonZeros = 0; |
| 1052 | m_data.resize(m_outerIndex[m_outerSize]); |
| 1053 | } |
| 1054 | |
| 1055 | template<typename Scalar, int _Options, typename _StorageIndex> |
| 1056 | template<typename OtherDerived> |