// This file is part of libigl, a simple c++ geometry processing library. // // Copyright (C) 2013 Alec Jacobson // // This Source Code Form is subject to the terms of the Mozilla Public License // v. 2.0. If a copy of the MPL was not distributed with this file, You can // obtain one at http://mozilla.org/MPL/2.0/. #include "slice_sorted.h" #include // TODO: Write a version that works for row-major sparse matrices as well. template IGL_INLINE void igl::slice_sorted(const Eigen::SparseMatrix &X, const Eigen::DenseBase &R, const Eigen::DenseBase &C, Eigen::SparseMatrix &Y) { int xm = X.rows(); int xn = X.cols(); int ym = R.size(); int yn = C.size(); // Special case when R or C is empty if (ym == 0 || yn == 0) { Y.resize(ym, yn); return; } assert(R.minCoeff() >= 0); assert(R.maxCoeff() < xm); assert(C.minCoeff() >= 0); assert(C.maxCoeff() < xn); // Multiplicity count for each row/col using RowIndexType = typename DerivedR::Scalar; using ColIndexType = typename DerivedC::Scalar; std::vector slicedRowStart(xm); std::vector rowRepeat(xm, 0); for (int i = 0; i < ym; ++i) { if (rowRepeat[R(i)] == 0) { slicedRowStart[R(i)] = i; } rowRepeat[R(i)]++; } std::vector columnRepeat(xn, 0); for (int i = 0; i < yn; i++) { columnRepeat[C(i)]++; } // Count number of nnz per outer row/col Eigen::VectorXi nnz(yn); for (int k = 0, c = 0; k < X.outerSize(); ++k) { int cnt = 0; for (typename Eigen::SparseMatrix::InnerIterator it(X, k); it; ++it) { cnt += rowRepeat[it.row()]; } for (int i = 0; i < columnRepeat[k]; ++i, ++c) { nnz(c) = cnt; } } Y.resize(ym, yn); Y.reserve(nnz); // Insert values for (int k = 0, c = 0; k < X.outerSize(); ++k) { for (int i = 0; i < columnRepeat[k]; ++i, ++c) { for (typename Eigen::SparseMatrix::InnerIterator it(X, k); it; ++it) { for (int j = 0, r = slicedRowStart[it.row()]; j < rowRepeat[it.row()]; ++j, ++r) { Y.insert(r, c) = it.value(); } } } } } #ifdef IGL_STATIC_LIBRARY template void igl::slice_sorted, Eigen::Matrix >(Eigen::SparseMatrix const&, Eigen::DenseBase > const&, Eigen::DenseBase > const&, Eigen::SparseMatrix&); #endif