// 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.h" #include "colon.h" #include template < typename TX, typename TY, typename DerivedR, typename DerivedC> IGL_INLINE void igl::slice( 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); // Build reindexing maps for columns and rows std::vector> RI; RI.resize(xm); for (int i = 0; i < ym; i++) { RI[R(i)].push_back(i); } std::vector> CI; CI.resize(xn); for (int i = 0; i < yn; i++) { CI[C(i)].push_back(i); } // Take a guess at the number of nonzeros (this assumes uniform distribution // not banded or heavily diagonal) std::vector> entries; entries.reserve((X.nonZeros()/(X.rows()*X.cols())) * (ym*yn)); // Iterate over outside for (int k = 0; k < X.outerSize(); ++k) { // Iterate over inside for (typename Eigen::SparseMatrix::InnerIterator it(X, k); it; ++it) { for (auto rit = RI[it.row()].begin(); rit != RI[it.row()].end(); rit++) { for (auto cit = CI[it.col()].begin(); cit != CI[it.col()].end(); cit++) { entries.emplace_back(*rit, *cit, it.value()); } } } } Y.resize(ym, yn); Y.setFromTriplets(entries.begin(), entries.end()); } template IGL_INLINE void igl::slice( const MatX &X, const Eigen::DenseBase &R, const int dim, MatY &Y) { Eigen::Matrix C; switch (dim) { case 1: // boring base case if (X.cols() == 0) { Y.resize(R.size(), 0); return; } igl::colon(0, X.cols() - 1, C); return slice(X, R, C, Y); case 2: // boring base case if (X.rows() == 0) { Y.resize(0, R.size()); return; } igl::colon(0, X.rows() - 1, C); return slice(X, C, R, Y); default: assert(false && "Unsupported dimension"); return; } } template < typename DerivedX, typename DerivedR, typename DerivedC, typename DerivedY> IGL_INLINE void igl::slice( const Eigen::DenseBase &X, const Eigen::DenseBase &R, const Eigen::DenseBase &C, Eigen::PlainObjectBase &Y) { #ifndef NDEBUG int xm = X.rows(); int xn = X.cols(); #endif 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); // Resize output Y.resize(ym, yn); // loop over output rows, then columns for (int i = 0; i < ym; i++) { for (int j = 0; j < yn; j++) { Y(i, j) = X(R(i), C(j)); } } } template IGL_INLINE void igl::slice( const Eigen::DenseBase &X, const Eigen::DenseBase &R, Eigen::PlainObjectBase &Y) { // phony column indices Eigen::Matrix C; C.resize(1); C(0) = 0; return igl::slice(X, R, C, Y); } template IGL_INLINE DerivedX igl::slice( const Eigen::DenseBase &X, const Eigen::DenseBase &R) { DerivedX Y; igl::slice(X, R, Y); return Y; } template IGL_INLINE DerivedX igl::slice( const Eigen::DenseBase &X, const Eigen::DenseBase &R, const int dim) { DerivedX Y; igl::slice(X, R, dim, Y); return Y; } template< class T > IGL_INLINE void igl::slice( const std::vector & unordered, std::vector const & index_map, std::vector & ordered) { // copy for the slice according to index_map, because unordered may also be // ordered std::vector copy = unordered; ordered.resize(index_map.size()); for(int i = 0; i<(int)index_map.size();i++) { ordered[i] = copy[index_map[i]]; } } #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation template void igl::slice, Eigen::Matrix, Eigen::SparseMatrix>(Eigen::SparseMatrix const &, Eigen::DenseBase> const &, int, Eigen::SparseMatrix &); template void igl::slice, Eigen::Array, Eigen::SparseMatrix >(Eigen::SparseMatrix const&, Eigen::DenseBase > const&, int, Eigen::SparseMatrix&); template void igl::slice, Eigen::Matrix, Eigen::SparseMatrix>(Eigen::SparseMatrix const &, Eigen::DenseBase> const &, int, Eigen::SparseMatrix &); template void igl::slice, Eigen::Matrix, Eigen::SparseMatrix>(Eigen::SparseMatrix const &, Eigen::DenseBase> const &, int, Eigen::SparseMatrix &); template void igl::slice, Eigen::Matrix, Eigen::SparseMatrix>(Eigen::SparseMatrix const &, Eigen::DenseBase> const &, int, Eigen::SparseMatrix &); #ifdef WIN32 template void igl::slice(class std::vector > const &,class std::vector > const &,class std::vector > &); template void igl::slice(class std::vector > const &,class std::vector > const &,class std::vector > &); template void igl::slice<__int64>(class std::vector<__int64,class std::allocator<__int64> > const &,class std::vector > const &,class std::vector<__int64,class std::allocator<__int64> > &); #endif template void igl::slice(std::vector > const&, std::vector > const&, std::vector >&); template void igl::slice(std::vector > const&, std::vector > const&, std::vector >&); template void igl::slice(std::vector > const&, std::vector > const&, std::vector >&); template void igl::slice(std::vector > const&, std::vector > const&, std::vector >&); template void igl::slice(std::vector > const&, std::vector > const&, std::vector >&); #include "SortableRow.h" template void igl::slice > >(std::vector >, std::allocator > > > const&, std::vector > const&, std::vector >, std::allocator > > >&); template void igl::slice > >(std::vector >, std::allocator > > > const&, std::vector > const&, std::vector >, std::allocator > > >&); #endif