Browse Source

Avoid involving Eigen/SparseExtra in slice. (#1370)

* Avoid involving Eigen/SparseExtra in slice.

* Undo merging error...

* Remove more deprecated DynamicSparseMatrix in slice.

* Typo.

* Avoid narrowing error in initializer list.

* Cleanup igl::slice, add igl::slice_sorted, add unit test and benchmarks + update Catch2.

* Missing template.

* Template for Windows.

Co-authored-by: Jérémie Dumas <[email protected]>
Qingnan Zhou 5 years ago
parent
commit
26053f696c

+ 1 - 1
cmake/LibiglDownloadExternal.cmake

@@ -156,7 +156,7 @@ endfunction()
 function(igl_download_catch2)
 function(igl_download_catch2)
 	igl_download_project(catch2
 	igl_download_project(catch2
 		GIT_REPOSITORY https://github.com/catchorg/Catch2.git
 		GIT_REPOSITORY https://github.com/catchorg/Catch2.git
-		GIT_TAG        03d122a35c3f5c398c43095a87bc82ed44642516
+		GIT_TAG        v2.11.0
 	)
 	)
 endfunction()
 endfunction()
 
 

+ 75 - 351
include/igl/slice.cpp

@@ -9,7 +9,6 @@
 #include "colon.h"
 #include "colon.h"
 
 
 #include <vector>
 #include <vector>
-#include <unsupported/Eigen/SparseExtra>
 
 
 template <
 template <
     typename TX,
     typename TX,
@@ -18,11 +17,10 @@ template <
     typename DerivedC>
     typename DerivedC>
 IGL_INLINE void igl::slice(
 IGL_INLINE void igl::slice(
     const Eigen::SparseMatrix<TX> &X,
     const Eigen::SparseMatrix<TX> &X,
-    const Eigen::MatrixBase<DerivedR> &R,
-    const Eigen::MatrixBase<DerivedC> &C,
+    const Eigen::DenseBase<DerivedR> &R,
+    const Eigen::DenseBase<DerivedC> &C,
     Eigen::SparseMatrix<TY> &Y)
     Eigen::SparseMatrix<TY> &Y)
 {
 {
-#if 1
   int xm = X.rows();
   int xm = X.rows();
   int xn = X.cols();
   int xn = X.cols();
   int ym = R.size();
   int ym = R.size();
@@ -40,7 +38,7 @@ IGL_INLINE void igl::slice(
   assert(C.minCoeff() >= 0);
   assert(C.minCoeff() >= 0);
   assert(C.maxCoeff() < xn);
   assert(C.maxCoeff() < xn);
 
 
-  // Build reindexing maps for columns and rows, -1 means not in map
+  // Build reindexing maps for columns and rows
   std::vector<std::vector<typename DerivedR::Scalar>> RI;
   std::vector<std::vector<typename DerivedR::Scalar>> RI;
   RI.resize(xm);
   RI.resize(xm);
   for (int i = 0; i < ym; i++)
   for (int i = 0; i < ym; i++)
@@ -49,268 +47,39 @@ IGL_INLINE void igl::slice(
   }
   }
   std::vector<std::vector<typename DerivedC::Scalar>> CI;
   std::vector<std::vector<typename DerivedC::Scalar>> CI;
   CI.resize(xn);
   CI.resize(xn);
-  // initialize to -1
   for (int i = 0; i < yn; i++)
   for (int i = 0; i < yn; i++)
   {
   {
     CI[C(i)].push_back(i);
     CI[C(i)].push_back(i);
   }
   }
-  // Resize output
-  Eigen::DynamicSparseMatrix<TY, Eigen::RowMajor> dyn_Y(ym, yn);
-  // Take a guess at the number of nonzeros (this assumes uniform distribution
-  // not banded or heavily diagonal)
-  dyn_Y.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<TX>::InnerIterator it(X, k); it; ++it)
-    {
-      typename std::vector<typename DerivedR::Scalar>::iterator rit;
-      typename std::vector<typename DerivedC::Scalar>::iterator cit;
-      for (rit = RI[it.row()].begin(); rit != RI[it.row()].end(); rit++)
-      {
-        for (cit = CI[it.col()].begin(); cit != CI[it.col()].end(); cit++)
-        {
-          dyn_Y.coeffRef(*rit, *cit) = it.value();
-        }
-      }
-    }
-  }
-  Y = Eigen::SparseMatrix<TY>(dyn_Y);
-#else
-
-  // Alec: This is _not_ valid for arbitrary R,C since they don't necessary
-  // representation a strict permutation of the rows and columns: rows or
-  // columns could be removed or replicated. The removal of rows seems to be
-  // handled here (although it's not clear if there is a performance gain when
-  // the #removals >> #remains). If this is sufficiently faster than the
-  // correct code above, one could test whether all entries in R and C are
-  // unique and apply the permutation version if appropriate.
-  //
-
-  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);
-
-  // initialize row and col permutation vectors
-  Eigen::VectorXi rowIndexVec = igl::LinSpaced<Eigen::VectorXi>(xm, 0, xm - 1);
-  Eigen::VectorXi rowPermVec = igl::LinSpaced<Eigen::VectorXi>(xm, 0, xm - 1);
-  for (int i = 0; i < ym; i++)
-  {
-    int pos = rowIndexVec.coeffRef(R(i));
-    if (pos != i)
-    {
-      int &val = rowPermVec.coeffRef(i);
-      std::swap(rowIndexVec.coeffRef(val), rowIndexVec.coeffRef(R(i)));
-      std::swap(rowPermVec.coeffRef(i), rowPermVec.coeffRef(pos));
-    }
-  }
-  Eigen::PermutationMatrix<Eigen::Dynamic, Eigen::Dynamic, int> rowPerm(rowIndexVec);
-
-  Eigen::VectorXi colIndexVec = igl::LinSpaced<Eigen::VectorXi>(xn, 0, xn - 1);
-  Eigen::VectorXi colPermVec = igl::LinSpaced<Eigen::VectorXi>(xn, 0, xn - 1);
-  for (int i = 0; i < yn; i++)
-  {
-    int pos = colIndexVec.coeffRef(C(i));
-    if (pos != i)
-    {
-      int &val = colPermVec.coeffRef(i);
-      std::swap(colIndexVec.coeffRef(val), colIndexVec.coeffRef(C(i)));
-      std::swap(colPermVec.coeffRef(i), colPermVec.coeffRef(pos));
-    }
-  }
-  Eigen::PermutationMatrix<Eigen::Dynamic, Eigen::Dynamic, int> colPerm(colPermVec);
-
-  Eigen::SparseMatrix<T> M = (rowPerm * X);
-  Y = (M * colPerm).block(0, 0, ym, yn);
-#endif
-}
-
-template <
-    typename TX,
-    typename TY,
-    typename DerivedR,
-    typename DerivedC>
-IGL_INLINE void igl::slice(
-    const Eigen::SparseMatrix<TX> &X,
-    const Eigen::ArrayBase<DerivedR> &R,
-    const Eigen::MatrixBase<DerivedC> &C,
-    Eigen::SparseMatrix<TY> &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, -1 means not in map
-  std::vector<std::vector<typename DerivedR::Scalar>> RI;
-  RI.resize(xm);
-  for (int i = 0; i < ym; i++)
-  {
-    RI[R(i)].push_back(i);
-  }
-  std::vector<std::vector<typename DerivedC::Scalar>> CI;
-  CI.resize(xn);
-  // initialize to -1
-  for (int i = 0; i < yn; i++)
-  {
-    CI[C(i)].push_back(i);
-  }
-  // Resize output
-  Eigen::DynamicSparseMatrix<TY, Eigen::RowMajor> dyn_Y(ym, yn);
   // Take a guess at the number of nonzeros (this assumes uniform distribution
   // Take a guess at the number of nonzeros (this assumes uniform distribution
   // not banded or heavily diagonal)
   // not banded or heavily diagonal)
-  dyn_Y.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<TX>::InnerIterator it(X, k); it; ++it)
-    {
-      typename std::vector<typename DerivedR::Scalar>::iterator rit;
-      typename std::vector<typename DerivedC::Scalar>::iterator cit;
-      for (rit = RI[it.row()].begin(); rit != RI[it.row()].end(); rit++)
-      {
-        for (cit = CI[it.col()].begin(); cit != CI[it.col()].end(); cit++)
-        {
-          dyn_Y.coeffRef(*rit, *cit) = it.value();
-        }
-      }
-    }
-  }
-  Y = Eigen::SparseMatrix<TY>(dyn_Y);
-}
+  std::vector<Eigen::Triplet<TY>> entries;
+  entries.reserve((X.nonZeros()/(X.rows()*X.cols())) * (ym*yn));
 
 
-template <
-    typename TX,
-    typename TY,
-    typename DerivedR,
-    typename DerivedC>
-IGL_INLINE void igl::slice(
-    const Eigen::SparseMatrix<TX> &X,
-    const Eigen::MatrixBase<DerivedR> &R,
-    const Eigen::ArrayBase<DerivedC> &C,
-    Eigen::SparseMatrix<TY> &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, -1 means not in map
-  std::vector<std::vector<typename DerivedR::Scalar>> RI;
-  RI.resize(xm);
-  for (int i = 0; i < ym; i++)
-  {
-    RI[R(i)].push_back(i);
-  }
-  std::vector<std::vector<typename DerivedC::Scalar>> CI;
-  CI.resize(xn);
-  // initialize to -1
-  for (int i = 0; i < yn; i++)
-  {
-    CI[C(i)].push_back(i);
-  }
-  // Resize output
-  Eigen::DynamicSparseMatrix<TY, Eigen::RowMajor> dyn_Y(ym, yn);
-  // Take a guess at the number of nonzeros (this assumes uniform distribution
-  // not banded or heavily diagonal)
-  dyn_Y.reserve((X.nonZeros() / (X.rows() * X.cols())) * (ym * yn));
   // Iterate over outside
   // Iterate over outside
   for (int k = 0; k < X.outerSize(); ++k)
   for (int k = 0; k < X.outerSize(); ++k)
   {
   {
     // Iterate over inside
     // Iterate over inside
     for (typename Eigen::SparseMatrix<TX>::InnerIterator it(X, k); it; ++it)
     for (typename Eigen::SparseMatrix<TX>::InnerIterator it(X, k); it; ++it)
     {
     {
-      typename std::vector<typename DerivedR::Scalar>::iterator rit;
-      typename std::vector<typename DerivedC::Scalar>::iterator cit;
-      for (rit = RI[it.row()].begin(); rit != RI[it.row()].end(); rit++)
+      for (auto rit = RI[it.row()].begin(); rit != RI[it.row()].end(); rit++)
       {
       {
-        for (cit = CI[it.col()].begin(); cit != CI[it.col()].end(); cit++)
+        for (auto cit = CI[it.col()].begin(); cit != CI[it.col()].end(); cit++)
         {
         {
-          dyn_Y.coeffRef(*rit, *cit) = it.value();
+          entries.emplace_back(*rit, *cit, it.value());
         }
         }
       }
       }
     }
     }
   }
   }
-  Y = Eigen::SparseMatrix<TY>(dyn_Y);
-}
-
-template <typename MatX, typename DerivedR, typename MatY>
-IGL_INLINE void igl::slice(
-    const MatX &X,
-    const Eigen::MatrixBase<DerivedR> &R,
-    const int dim,
-    MatY &Y)
-{
-  Eigen::Matrix<typename DerivedR::Scalar, Eigen::Dynamic, 1> 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;
-  }
+  Y.resize(ym, yn);
+  Y.setFromTriplets(entries.begin(), entries.end());
 }
 }
 
 
 template <typename MatX, typename DerivedR, typename MatY>
 template <typename MatX, typename DerivedR, typename MatY>
 IGL_INLINE void igl::slice(
 IGL_INLINE void igl::slice(
     const MatX &X,
     const MatX &X,
-    const Eigen::ArrayBase<DerivedR> &R,
+    const Eigen::DenseBase<DerivedR> &R,
     const int dim,
     const int dim,
     MatY &Y)
     MatY &Y)
 {
 {
@@ -347,9 +116,9 @@ template <
     typename DerivedC,
     typename DerivedC,
     typename DerivedY>
     typename DerivedY>
 IGL_INLINE void igl::slice(
 IGL_INLINE void igl::slice(
-    const Eigen::ArrayBase<DerivedX> &X,
-    const Eigen::MatrixBase<DerivedR> &R,
-    const Eigen::MatrixBase<DerivedC> &C,
+    const Eigen::DenseBase<DerivedX> &X,
+    const Eigen::DenseBase<DerivedR> &R,
+    const Eigen::DenseBase<DerivedC> &C,
     Eigen::PlainObjectBase<DerivedY> &Y)
     Eigen::PlainObjectBase<DerivedY> &Y)
 {
 {
 #ifndef NDEBUG
 #ifndef NDEBUG
@@ -383,52 +152,10 @@ IGL_INLINE void igl::slice(
   }
   }
 }
 }
 
 
-template <
-    typename DerivedX,
-    typename DerivedR,
-    typename DerivedC,
-    typename DerivedY>
-IGL_INLINE void igl::slice(
-    const Eigen::MatrixBase<DerivedX> &X,
-    const Eigen::MatrixBase<DerivedR> &R,
-    const Eigen::MatrixBase<DerivedC> &C,
-    Eigen::PlainObjectBase<DerivedY> &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,0), C(j,0));
-    }
-  }
-}
-
 template <typename DerivedX, typename DerivedY, typename DerivedR>
 template <typename DerivedX, typename DerivedY, typename DerivedR>
 IGL_INLINE void igl::slice(
 IGL_INLINE void igl::slice(
-    const Eigen::MatrixBase<DerivedX> &X,
-    const Eigen::MatrixBase<DerivedR> &R,
+    const Eigen::DenseBase<DerivedX> &X,
+    const Eigen::DenseBase<DerivedR> &R,
     Eigen::PlainObjectBase<DerivedY> &Y)
     Eigen::PlainObjectBase<DerivedY> &Y)
 {
 {
   // phony column indices
   // phony column indices
@@ -440,8 +167,8 @@ IGL_INLINE void igl::slice(
 
 
 template <typename DerivedX, typename DerivedR>
 template <typename DerivedX, typename DerivedR>
 IGL_INLINE DerivedX igl::slice(
 IGL_INLINE DerivedX igl::slice(
-    const Eigen::MatrixBase<DerivedX> &X,
-    const Eigen::MatrixBase<DerivedR> &R)
+    const Eigen::DenseBase<DerivedX> &X,
+    const Eigen::DenseBase<DerivedR> &R)
 {
 {
   DerivedX Y;
   DerivedX Y;
   igl::slice(X, R, Y);
   igl::slice(X, R, Y);
@@ -450,8 +177,8 @@ IGL_INLINE DerivedX igl::slice(
 
 
 template <typename DerivedX, typename DerivedR>
 template <typename DerivedX, typename DerivedR>
 IGL_INLINE DerivedX igl::slice(
 IGL_INLINE DerivedX igl::slice(
-    const Eigen::MatrixBase<DerivedX> &X,
-    const Eigen::MatrixBase<DerivedR> &R,
+    const Eigen::DenseBase<DerivedX> &X,
+    const Eigen::DenseBase<DerivedR> &R,
     const int dim)
     const int dim)
 {
 {
   DerivedX Y;
   DerivedX Y;
@@ -460,64 +187,61 @@ IGL_INLINE DerivedX igl::slice(
 }
 }
 
 
 #ifdef IGL_STATIC_LIBRARY
 #ifdef IGL_STATIC_LIBRARY
-// Explicit template instantiation
-// generated by autoexplicit.sh
-template void igl::slice<Eigen::MatrixBase<Eigen::Matrix<float, -1, -1, 0, -1, -1> >, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, -1, 0, -1, -1> > >(Eigen::MatrixBase<Eigen::Matrix<float, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, -1, 0, -1, -1> >&);
-// generated by autoexplicit.sh
-template void igl::slice<Eigen::MatrixBase<Eigen::Matrix<float, -1, 3, 0, -1, 3> >, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, -1, 0, -1, -1> > >(Eigen::MatrixBase<Eigen::Matrix<float, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, -1, 0, -1, -1> >&);
-template void igl::slice<Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>>(Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const &, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const &, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> &);
-template void igl::slice<Eigen::MatrixBase<Eigen::Matrix<double, -1, 1, 0, -1, 1>>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>>(Eigen::MatrixBase<Eigen::Matrix<double, -1, 1, 0, -1, 1>> const &, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const &, int, Eigen::Matrix<double, -1, -1, 0, -1, -1> &);
-template void igl::slice<Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1>>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>>(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1>> const &, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const &, int, Eigen::Matrix<double, -1, -1, 0, -1, -1> &);
-template void igl::slice<Eigen::SparseMatrix<double, 0, int>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::SparseMatrix<double, 0, int>>(Eigen::SparseMatrix<double, 0, int> const &, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const &, int, Eigen::SparseMatrix<double, 0, int> &);
-template void igl::slice<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>>(Eigen::Matrix<double, -1, -1, 0, -1, -1> const &, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const &, int, Eigen::Matrix<double, -1, -1, 0, -1, -1> &);
-template void igl::slice<Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>>(Eigen::MatrixBase<Eigen::Matrix<double, -1, 1, 0, -1, 1>> const &, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const &, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1>> &);
-template void igl::slice<Eigen::SparseMatrix<double, 0, int>, Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::SparseMatrix<double, 0, int>>(Eigen::SparseMatrix<double, 0, int> const &, Eigen::MatrixBase<Eigen::Matrix<double, -1, 1, 0, -1, 1>> const &, int, Eigen::SparseMatrix<double, 0, int> &);
-template void igl::slice<Eigen::SparseMatrix<double, 0, int>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::SparseMatrix<double, 0, int>>(Eigen::SparseMatrix<double, 0, int> const &, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>> const &, int, Eigen::SparseMatrix<double, 0, int> &);
-template void igl::slice<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>>(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1>> const &, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>> const &, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1>> &);
-template void igl::slice<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1>>>(Eigen::Matrix<double, -1, -1, 0, -1, -1> const &, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const &, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1>> &);
-template void igl::slice<Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Block<Eigen::Matrix<int, -1, -1, 0, -1, -1> const, -1, 1, true>>(Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const &, Eigen::MatrixBase<Eigen::Block<Eigen::Matrix<int, -1, -1, 0, -1, -1> const, -1, 1, true>> const &, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> &);
-template Eigen::Matrix<double, -1, -1, 0, -1, -1> igl::slice<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>>(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1>> const &, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const &, int);
-template void igl::slice<Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3>>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 1, -1, 3>>>(Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3>> const &, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const &, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 1, -1, 3>> &);
-template void igl::slice<Eigen::Matrix<float, -1, 1, 0, -1, 1>, Eigen::Matrix<float, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>>(Eigen::MatrixBase<Eigen::Matrix<float, -1, 1, 0, -1, 1>> const &, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const &, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 1, 0, -1, 1>> &);
-template void igl::slice<Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3>>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1>>>(Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3>> const &, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const &, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1>> &);
-template void igl::slice<Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3>>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3>>>(Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3>> const &, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const &, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3>> &);
-template void igl::slice<Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1>>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 1, -1, -1>>>(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1>> const &, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const &, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 1, -1, -1>> &);
-template void igl::slice<Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1>>, Eigen::Matrix<long, -1, 1, 0, -1, 1>, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1>>>(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1>> const &, Eigen::MatrixBase<Eigen::Matrix<long, -1, 1, 0, -1, 1>> const &, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1>> &);
-template void igl::slice<Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 1, -1, -1>>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1>>>(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 1, -1, -1>> const &, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const &, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1>> &);
-template void igl::slice<Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1>>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1>>>(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1>> const &, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const &, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1>> &);
-template void igl::slice<Eigen::MatrixBase<Eigen::Matrix<float, -1, 3, 0, -1, 3>>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 3, 1, -1, 3>>>(Eigen::MatrixBase<Eigen::Matrix<float, -1, 3, 0, -1, 3>> const &, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const &, int, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 3, 1, -1, 3>> &);
-template void igl::slice<Eigen::Matrix<double, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, 3, 1, -1, 3>>(Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 1, -1, 3>> const &, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const &, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const &, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 1, -1, 3>> &);
-template void igl::slice<Eigen::SparseMatrix<bool, 0, int>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::SparseMatrix<bool, 0, int>>(Eigen::SparseMatrix<bool, 0, int> const &, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const &, int, Eigen::SparseMatrix<bool, 0, int> &);
-template Eigen::Matrix<int, -1, -1, 0, -1, -1> igl::slice<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>>(Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>> const &, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>> const &);
-template void igl::slice<Eigen::Matrix<double, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>>(Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 1, -1, 3>> const &, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>> const &, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const &, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1>> &);
-template void igl::slice<Eigen::Matrix<double, -1, -1, 1, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, -1, 1, -1, -1>>(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 1, -1, -1>> const &, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const &, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const &, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 1, -1, -1>> &);
-template void igl::slice<Eigen::Matrix<float, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<float, -1, 3, 1, -1, 3>>(Eigen::MatrixBase<Eigen::Matrix<float, -1, 3, 1, -1, 3>> const &, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const &, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const &, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 3, 1, -1, 3>> &);
-template void igl::slice<Eigen::Matrix<float, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<float, -1, -1, 0, -1, -1>>(Eigen::MatrixBase<Eigen::Matrix<float, -1, 3, 0, -1, 3>> const &, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>> const &, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const &, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, -1, 0, -1, -1>> &);
-template void igl::slice<Eigen::Matrix<float, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<float, -1, -1, 0, -1, -1>>(Eigen::MatrixBase<Eigen::Matrix<float, -1, 3, 1, -1, 3>> const &, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>> const &, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const &, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, -1, 0, -1, -1>> &);
-template void igl::slice<Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>>(Eigen::Matrix<int, -1, 1, 0, -1, 1> const &, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const &, int, Eigen::Matrix<int, -1, 1, 0, -1, 1> &);
-template void igl::slice<Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>>, Eigen::Matrix<long, -1, 1, 0, -1, 1>, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>>>(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>> const &, Eigen::MatrixBase<Eigen::Matrix<long, -1, 1, 0, -1, 1>> const &, int, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>> &);
-template void igl::slice<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>>(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1>> const &, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>> const &, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const &, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1>> &);
-template void igl::slice<Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>>>(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>> const &, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const &, int, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>> &);
-template void igl::slice<Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>>>(Eigen::Matrix<int, -1, 1, 0, -1, 1> const &, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const &, int, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> &);
-template void igl::slice<Eigen::Matrix<long, -1, 1, 0, -1, 1>, Eigen::Matrix<long, -1, 1, 0, -1, 1>, Eigen::PlainObjectBase<Eigen::Matrix<long, -1, 1, 0, -1, 1>>>(Eigen::Matrix<long, -1, 1, 0, -1, 1> const &, Eigen::MatrixBase<Eigen::Matrix<long, -1, 1, 0, -1, 1>> const &, int, Eigen::PlainObjectBase<Eigen::Matrix<long, -1, 1, 0, -1, 1>> &);
-template void igl::slice<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>>>(Eigen::Matrix<int, -1, -1, 0, -1, -1> const &, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>> const &, int, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>> &);
+
+template Eigen::Matrix<double, -1, -1, 0, -1, -1> igl::slice<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>>(Eigen::DenseBase<Eigen::Matrix<double, -1, -1, 0, -1, -1>> const &, Eigen::DenseBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const &, int);
+template Eigen::Matrix<int, -1, -1, 0, -1, -1> igl::slice<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>>(Eigen::DenseBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>> const &, Eigen::DenseBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>> const &);
+template void igl::slice<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>>(Eigen::DenseBase<Eigen::Matrix<double, -1, -1, 0, -1, -1>> const &, Eigen::DenseBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>> const &, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1>> &);
+template void igl::slice<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>>(Eigen::DenseBase<Eigen::Matrix<double, -1, -1, 0, -1, -1>> const &, Eigen::DenseBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>> const &, Eigen::DenseBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const &, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1>> &);
+template void igl::slice<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>>(Eigen::Matrix<double, -1, -1, 0, -1, -1> const &, Eigen::DenseBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const &, int, Eigen::Matrix<double, -1, -1, 0, -1, -1> &);
+template void igl::slice<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>>(Eigen::DenseBase<Eigen::Matrix<double, -1, -1, 0, -1, -1>> const &, Eigen::DenseBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const &, Eigen::DenseBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const &, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1>> &);
+template void igl::slice<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1>>>(Eigen::Matrix<double, -1, -1, 0, -1, -1> const &, Eigen::DenseBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const &, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1>> &);
+template void igl::slice<Eigen::Matrix<double, -1, -1, 1, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, -1, 1, -1, -1>>(Eigen::DenseBase<Eigen::Matrix<double, -1, -1, 1, -1, -1>> const &, Eigen::DenseBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const &, Eigen::DenseBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const &, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 1, -1, -1>> &);
+template void igl::slice<Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>>(Eigen::DenseBase<Eigen::Matrix<double, -1, 1, 0, -1, 1>> const &, Eigen::DenseBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const &, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1>> &);
+template void igl::slice<Eigen::Matrix<double, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>>(Eigen::DenseBase<Eigen::Matrix<double, -1, 3, 1, -1, 3>> const &, Eigen::DenseBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>> const &, Eigen::DenseBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const &, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1>> &);
+template void igl::slice<Eigen::Matrix<double, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, 3, 1, -1, 3>>(Eigen::DenseBase<Eigen::Matrix<double, -1, 3, 1, -1, 3>> const &, Eigen::DenseBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const &, Eigen::DenseBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const &, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 1, -1, 3>> &);
+template void igl::slice<Eigen::Matrix<float, -1, 1, 0, -1, 1>, Eigen::Matrix<float, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>>(Eigen::DenseBase<Eigen::Matrix<float, -1, 1, 0, -1, 1>> const &, Eigen::DenseBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const &, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 1, 0, -1, 1>> &);
+template void igl::slice<Eigen::Matrix<float, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<float, -1, -1, 0, -1, -1>>(Eigen::DenseBase<Eigen::Matrix<float, -1, 3, 0, -1, 3>> const &, Eigen::DenseBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>> const &, Eigen::DenseBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const &, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, -1, 0, -1, -1>> &);
+template void igl::slice<Eigen::Matrix<float, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<float, -1, -1, 0, -1, -1>>(Eigen::DenseBase<Eigen::Matrix<float, -1, 3, 1, -1, 3>> const &, Eigen::DenseBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>> const &, Eigen::DenseBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const &, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, -1, 0, -1, -1>> &);
+template void igl::slice<Eigen::Matrix<float, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<float, -1, 3, 1, -1, 3>>(Eigen::DenseBase<Eigen::Matrix<float, -1, 3, 1, -1, 3>> const &, Eigen::DenseBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const &, Eigen::DenseBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const &, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 3, 1, -1, 3>> &);
+template void igl::slice<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>>>(Eigen::Matrix<int, -1, -1, 0, -1, -1> const &, Eigen::DenseBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>> const &, int, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>> &);
+template void igl::slice<Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Block<Eigen::Matrix<int, -1, -1, 0, -1, -1> const, -1, 1, true>>(Eigen::DenseBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const &, Eigen::DenseBase<Eigen::Block<Eigen::Matrix<int, -1, -1, 0, -1, -1> const, -1, 1, true>> const &, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> &);
+template void igl::slice<Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>>(Eigen::DenseBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const &, Eigen::DenseBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const &, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> &);
+template void igl::slice<Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>>(Eigen::Matrix<int, -1, 1, 0, -1, 1> const &, Eigen::DenseBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const &, int, Eigen::Matrix<int, -1, 1, 0, -1, 1> &);
+template void igl::slice<Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>>>(Eigen::Matrix<int, -1, 1, 0, -1, 1> const &, Eigen::DenseBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const &, int, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> &);
+template void igl::slice<Eigen::Matrix<long, -1, 1, 0, -1, 1>, Eigen::Matrix<long, -1, 1, 0, -1, 1>, Eigen::PlainObjectBase<Eigen::Matrix<long, -1, 1, 0, -1, 1>>>(Eigen::Matrix<long, -1, 1, 0, -1, 1> const &, Eigen::DenseBase<Eigen::Matrix<long, -1, 1, 0, -1, 1>> const &, int, Eigen::PlainObjectBase<Eigen::Matrix<long, -1, 1, 0, -1, 1>> &);
+template void igl::slice<Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::DenseBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, int, Eigen::Matrix<double, -1, -1, 0, -1, -1>&);
+template void igl::slice<Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::DenseBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
+template void igl::slice<Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::DenseBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, int, Eigen::Matrix<double, -1, -1, 0, -1, -1>&);
+template void igl::slice<Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::DenseBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
+template void igl::slice<Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 1, -1, -1> > >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::DenseBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 1, -1, -1> >&);
+template void igl::slice<Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >, Eigen::Matrix<long, -1, 1, 0, -1, 1>, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::DenseBase<Eigen::Matrix<long, -1, 1, 0, -1, 1> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
+template void igl::slice<Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 1, -1, -1> >, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 1, -1, -1> > const&, Eigen::DenseBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
+template void igl::slice<Eigen::MatrixBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> > const&, Eigen::DenseBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, int, Eigen::Matrix<double, -1, -1, 0, -1, -1>&);
+template void igl::slice<Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > >(Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::DenseBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
+template void igl::slice<Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > >(Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::DenseBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&);
+template void igl::slice<Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 1, -1, 3> > >(Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::DenseBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 1, -1, 3> >&);
+template void igl::slice<Eigen::MatrixBase<Eigen::Matrix<float, -1, -1, 0, -1, -1> >, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, -1, 0, -1, -1> > >(Eigen::MatrixBase<Eigen::Matrix<float, -1, -1, 0, -1, -1> > const&, Eigen::DenseBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, -1, 0, -1, -1> >&);
+template void igl::slice<Eigen::MatrixBase<Eigen::Matrix<float, -1, 3, 0, -1, 3> >, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, -1, 0, -1, -1> > >(Eigen::MatrixBase<Eigen::Matrix<float, -1, 3, 0, -1, 3> > const&, Eigen::DenseBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, -1, 0, -1, -1> >&);
+template void igl::slice<Eigen::MatrixBase<Eigen::Matrix<float, -1, 3, 0, -1, 3> >, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 3, 1, -1, 3> > >(Eigen::MatrixBase<Eigen::Matrix<float, -1, 3, 0, -1, 3> > const&, Eigen::DenseBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 3, 1, -1, 3> >&);
+template void igl::slice<Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > >(Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::DenseBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
+template void igl::slice<Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > >(Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::DenseBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
+template void igl::slice<Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >, Eigen::Matrix<long, -1, 1, 0, -1, 1>, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > >(Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::DenseBase<Eigen::Matrix<long, -1, 1, 0, -1, 1> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
+template void igl::slice<Eigen::MatrixBase<Eigen::Matrix<int, -1, 3, 1, -1, 3> >, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 1, -1, 3> > >(Eigen::MatrixBase<Eigen::Matrix<int, -1, 3, 1, -1, 3> > const&, Eigen::DenseBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 1, -1, 3> >&);
+template void igl::slice<Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>>>(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>> const &, Eigen::DenseBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>> const &, int, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>> &);
+template void igl::slice<Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>>>(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>> const &, Eigen::DenseBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const &, int, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>> &);
+template void igl::slice<Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>>, Eigen::Matrix<long, -1, 1, 0, -1, 1>, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>>>(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>> const &, Eigen::DenseBase<Eigen::Matrix<long, -1, 1, 0, -1, 1>> const &, int, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>> &);
+template void igl::slice<Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 1, -1, 3>>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 1, -1, 3>>>(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 1, -1, 3>> const &, Eigen::DenseBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const &, int, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 1, -1, 3>> &);
+template void igl::slice<Eigen::SparseMatrix<bool, 0, int>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::SparseMatrix<bool, 0, int>>(Eigen::SparseMatrix<bool, 0, int> const &, Eigen::DenseBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const &, int, Eigen::SparseMatrix<bool, 0, int> &);
+template void igl::slice<Eigen::SparseMatrix<double, 0, int>, Eigen::Array<int, -1, 1, 0, -1, 1>, Eigen::SparseMatrix<double, 0, int> >(Eigen::SparseMatrix<double, 0, int> const&, Eigen::DenseBase<Eigen::Array<int, -1, 1, 0, -1, 1> > const&, int, Eigen::SparseMatrix<double, 0, int>&);
+template void igl::slice<Eigen::SparseMatrix<double, 0, int>, Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::SparseMatrix<double, 0, int>>(Eigen::SparseMatrix<double, 0, int> const &, Eigen::DenseBase<Eigen::Matrix<double, -1, 1, 0, -1, 1>> const &, int, Eigen::SparseMatrix<double, 0, int> &);
+template void igl::slice<Eigen::SparseMatrix<double, 0, int>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::SparseMatrix<double, 0, int>>(Eigen::SparseMatrix<double, 0, int> const &, Eigen::DenseBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>> const &, int, Eigen::SparseMatrix<double, 0, int> &);
+template void igl::slice<Eigen::SparseMatrix<double, 0, int>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::SparseMatrix<double, 0, int>>(Eigen::SparseMatrix<double, 0, int> const &, Eigen::DenseBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const &, int, Eigen::SparseMatrix<double, 0, int> &);
+
 #ifdef WIN32
 #ifdef WIN32
-template void igl::slice<Eigen::Matrix<__int64, -1, 1, 0, -1, 1>, Eigen::Matrix<__int64, -1, 1, 0, -1, 1>, Eigen::PlainObjectBase<Eigen::Matrix<__int64, -1, 1, 0, -1, 1>>>(Eigen::Matrix<__int64, -1, 1, 0, -1, 1> const &, Eigen::MatrixBase<Eigen::Matrix<__int64, -1, 1, 0, -1, 1>> const &, int, Eigen::PlainObjectBase<Eigen::Matrix<__int64, -1, 1, 0, -1, 1>> &);
-template void igl::slice<Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>>, Eigen::Matrix<__int64, -1, 1, 0, -1, 1>, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>>>(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>> const &, Eigen::MatrixBase<Eigen::Matrix<__int64, -1, 1, 0, -1, 1>> const &, int, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>> &);
-template void igl::slice<class Eigen::MatrixBase<class Eigen::Matrix<int,-1,-1,0,-1,-1> >,class Eigen::Matrix<__int64,-1,1,0,-1,1>,class Eigen::PlainObjectBase<class Eigen::Matrix<int,-1,-1,0,-1,-1> > >(class Eigen::MatrixBase<class Eigen::Matrix<int,-1,-1,0,-1,-1> > const &,class Eigen::MatrixBase<class Eigen::Matrix<__int64,-1,1,0,-1,1> > const &,int,class Eigen::PlainObjectBase<class Eigen::Matrix<int,-1,-1,0,-1,-1> > &);
-#endif
-#if EIGEN_VERSION_AT_LEAST(3, 3, 7)
-#else
-template void igl::slice<Eigen::MatrixBase<Eigen::CwiseUnaryOp<Eigen::internal::scalar_multiple_op<double>, Eigen::Matrix<double, -1, 1, 0, -1, 1> const>>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>>(Eigen::MatrixBase<Eigen::CwiseUnaryOp<Eigen::internal::scalar_multiple_op<double>, Eigen::Matrix<double, -1, 1, 0, -1, 1> const>> const &, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const &, int, Eigen::Matrix<double, -1, -1, 0, -1, -1> &);
+template void igl::slice<class Eigen::DenseBase<class Eigen::Matrix<int,-1,-1,0,-1,-1> >,class Eigen::Matrix<__int64,-1,1,0,-1,1>,class Eigen::PlainObjectBase<class Eigen::Matrix<int,-1,-1,0,-1,-1> > >(class Eigen::DenseBase<class Eigen::Matrix<int,-1,-1,0,-1,-1> > const &,class Eigen::DenseBase<class Eigen::Matrix<__int64,-1,1,0,-1,1> > const &,int,class Eigen::PlainObjectBase<class Eigen::Matrix<int,-1,-1,0,-1,-1> > &);
+template void igl::slice<class Eigen::MatrixBase<class Eigen::Matrix<int,-1,-1,0,-1,-1> >,class Eigen::Matrix<__int64,-1,1,0,-1,1>,class Eigen::PlainObjectBase<class Eigen::Matrix<int,-1,-1,0,-1,-1> > >(class Eigen::MatrixBase<class Eigen::Matrix<int,-1,-1,0,-1,-1> > const &,class Eigen::DenseBase<class Eigen::Matrix<__int64,-1,1,0,-1,1> > const &,int,class Eigen::PlainObjectBase<class Eigen::Matrix<int,-1,-1,0,-1,-1> > &);
+template void igl::slice<Eigen::Matrix<__int64, -1, 1, 0, -1, 1>, Eigen::Matrix<__int64, -1, 1, 0, -1, 1>, Eigen::PlainObjectBase<Eigen::Matrix<__int64, -1, 1, 0, -1, 1>>>(Eigen::Matrix<__int64, -1, 1, 0, -1, 1> const &, Eigen::DenseBase<Eigen::Matrix<__int64, -1, 1, 0, -1, 1>> const &, int, Eigen::PlainObjectBase<Eigen::Matrix<__int64, -1, 1, 0, -1, 1>> &);
+template void igl::slice<Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>>, Eigen::Matrix<__int64, -1, 1, 0, -1, 1>, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>>>(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>> const &, Eigen::DenseBase<Eigen::Matrix<__int64, -1, 1, 0, -1, 1>> const &, int, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>> &);
 #endif
 #endif
-template void igl::slice<Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
-template void igl::slice<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>>(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1>> const &, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const &, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const &, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1>> &);
-template void igl::slice<Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>>>(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>> const &, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>> const &, int, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>> &);
-template void igl::slice<Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 1, -1, 3>>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 1, -1, 3>>>(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 1, -1, 3>> const &, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const &, int, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 1, -1, 3>> &);
-template void igl::slice<Eigen::MatrixBase<Eigen::Matrix<int, -1, 3, 1, -1, 3> >, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 1, -1, 3> > >(Eigen::MatrixBase<Eigen::Matrix<int, -1, 3, 1, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 1, -1, 3> >&);
-template void igl::slice<Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>>>(Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>> const &, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const &, int, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>> &);
-template void igl::slice<Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >, Eigen::Matrix<long, -1, 1, 0, -1, 1>, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > >(Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<long, -1, 1, 0, -1, 1> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
-template void igl::slice<Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>>>(Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>> const &, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>> const &, int, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>> &);
-template void igl::slice<Eigen::SparseMatrix<double, 0, int>, Eigen::Array<int, -1, 1, 0, -1, 1>, Eigen::SparseMatrix<double, 0, int> >(Eigen::SparseMatrix<double, 0, int> const&, Eigen::ArrayBase<Eigen::Array<int, -1, 1, 0, -1, 1> > const&, int, Eigen::SparseMatrix<double, 0, int>&);
-template void igl::slice<Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, int, Eigen::Matrix<double, -1, -1, 0, -1, -1>&);
+
 #endif
 #endif

+ 15 - 52
include/igl/slice.h

@@ -30,29 +30,10 @@ namespace igl
     typename DerivedC>
     typename DerivedC>
   IGL_INLINE void slice(
   IGL_INLINE void slice(
     const Eigen::SparseMatrix<TX>& X,
     const Eigen::SparseMatrix<TX>& X,
-    const Eigen::MatrixBase<DerivedR> & R,
-    const Eigen::MatrixBase<DerivedC> & C,
-    Eigen::SparseMatrix<TY>& Y);
-  template <
-    typename TX,
-    typename TY,
-    typename DerivedR,
-    typename DerivedC>
-  IGL_INLINE void slice(
-    const Eigen::SparseMatrix<TX>& X,
-    const Eigen::ArrayBase<DerivedR> & R,
-    const Eigen::MatrixBase<DerivedC> & C,
-    Eigen::SparseMatrix<TY>& Y);
-  template <
-    typename TX,
-    typename TY,
-    typename DerivedR,
-    typename DerivedC>
-  IGL_INLINE void slice(
-    const Eigen::SparseMatrix<TX>& X,
-    const Eigen::MatrixBase<DerivedR> & R,
-    const Eigen::ArrayBase<DerivedC> & C,
+    const Eigen::DenseBase<DerivedR> & R,
+    const Eigen::DenseBase<DerivedC> & C,
     Eigen::SparseMatrix<TY>& Y);
     Eigen::SparseMatrix<TY>& Y);
+
   // Wrapper to only slice in one direction
   // Wrapper to only slice in one direction
   //
   //
   // Inputs:
   // Inputs:
@@ -65,45 +46,27 @@ namespace igl
     typename MatY>
     typename MatY>
   IGL_INLINE void slice(
   IGL_INLINE void slice(
     const MatX& X,
     const MatX& X,
-    const Eigen::MatrixBase<DerivedR> & R,
-    const int dim,
-    MatY& Y);
-  template <
-    typename MatX,
-    typename DerivedR,
-    typename MatY>
-  IGL_INLINE void slice(
-    const MatX& X,
-    const Eigen::ArrayBase<DerivedR> & R,
+    const Eigen::DenseBase<DerivedR> & R,
     const int dim,
     const int dim,
     MatY& Y);
     MatY& Y);
+
   template <
   template <
     typename DerivedX,
     typename DerivedX,
     typename DerivedR,
     typename DerivedR,
     typename DerivedC,
     typename DerivedC,
     typename DerivedY>
     typename DerivedY>
   IGL_INLINE void slice(
   IGL_INLINE void slice(
-    const Eigen::MatrixBase<DerivedX> & X,
-    const Eigen::MatrixBase<DerivedR> & R,
-    const Eigen::MatrixBase<DerivedC> & C,
+    const Eigen::DenseBase<DerivedX> & X,
+    const Eigen::DenseBase<DerivedR> & R,
+    const Eigen::DenseBase<DerivedC> & C,
     Eigen::PlainObjectBase<DerivedY> & Y);
     Eigen::PlainObjectBase<DerivedY> & Y);
 
 
-  template <
-    typename DerivedX,
-    typename DerivedR,
-    typename DerivedC,
-    typename DerivedY>
-IGL_INLINE void slice(
-    const Eigen::ArrayBase<DerivedX> &X,
-    const Eigen::MatrixBase<DerivedR> &R,
-    const Eigen::MatrixBase<DerivedC> &C,
-    Eigen::PlainObjectBase<DerivedY> &Y);
-
   template <typename DerivedX, typename DerivedY, typename DerivedR>
   template <typename DerivedX, typename DerivedY, typename DerivedR>
   IGL_INLINE void slice(
   IGL_INLINE void slice(
-    const Eigen::MatrixBase<DerivedX> & X,
-    const Eigen::MatrixBase<DerivedR> & R,
+    const Eigen::DenseBase<DerivedX> & X,
+    const Eigen::DenseBase<DerivedR> & R,
     Eigen::PlainObjectBase<DerivedY> & Y);
     Eigen::PlainObjectBase<DerivedY> & Y);
+
   // VectorXi Y = slice(X,R);
   // VectorXi Y = slice(X,R);
   //
   //
   // This templating is bad because the return type might not have the same
   // This templating is bad because the return type might not have the same
@@ -112,12 +75,12 @@ IGL_INLINE void slice(
   // the number of rows in `DerivedX`.
   // the number of rows in `DerivedX`.
   template <typename DerivedX, typename DerivedR>
   template <typename DerivedX, typename DerivedR>
   IGL_INLINE DerivedX slice(
   IGL_INLINE DerivedX slice(
-    const Eigen::MatrixBase<DerivedX> & X,
-    const Eigen::MatrixBase<DerivedR> & R);
+    const Eigen::DenseBase<DerivedX> & X,
+    const Eigen::DenseBase<DerivedR> & R);
   template <typename DerivedX, typename DerivedR>
   template <typename DerivedX, typename DerivedR>
   IGL_INLINE DerivedX slice(
   IGL_INLINE DerivedX slice(
-    const Eigen::MatrixBase<DerivedX>& X,
-    const Eigen::MatrixBase<DerivedR> & R,
+    const Eigen::DenseBase<DerivedX>& X,
+    const Eigen::DenseBase<DerivedR> & R,
     const int dim);
     const int dim);
 
 
 }
 }

+ 6 - 5
include/igl/slice_mask.cpp

@@ -1,12 +1,13 @@
 // This file is part of libigl, a simple c++ geometry processing library.
 // This file is part of libigl, a simple c++ geometry processing library.
-// 
+//
 // Copyright (C) 2015 Alec Jacobson <[email protected]>
 // Copyright (C) 2015 Alec Jacobson <[email protected]>
-// 
-// 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 
+//
+// 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/.
 // obtain one at http://mozilla.org/MPL/2.0/.
 #include "slice_mask.h"
 #include "slice_mask.h"
 #include "slice.h"
 #include "slice.h"
+#include "slice_sorted.h"
 #include "find.h"
 #include "find.h"
 #include <cassert>
 #include <cassert>
 
 
@@ -143,7 +144,7 @@ IGL_INLINE void igl::slice_mask(
   find(R,Ri);
   find(R,Ri);
   Eigen::VectorXi Ci;
   Eigen::VectorXi Ci;
   find(C,Ci);
   find(C,Ci);
-  return slice(X,Ri,Ci,Y);
+  return slice_sorted(X,Ri,Ci,Y);
 }
 }
 
 
 #ifdef IGL_STATIC_LIBRARY
 #ifdef IGL_STATIC_LIBRARY

+ 88 - 0
include/igl/slice_sorted.cpp

@@ -0,0 +1,88 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+//
+// Copyright (C) 2013 Alec Jacobson <[email protected]>
+//
+// 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 <vector>
+
+// TODO: Write a version that works for row-major sparse matrices as well.
+template <typename TX, typename TY, typename DerivedR, typename DerivedC>
+IGL_INLINE void igl::slice_sorted(const Eigen::SparseMatrix<TX> &X,
+                                  const Eigen::DenseBase<DerivedR> &R,
+                                  const Eigen::DenseBase<DerivedC> &C,
+                                  Eigen::SparseMatrix<TY> &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<RowIndexType> slicedRowStart(xm);
+  std::vector<RowIndexType> rowRepeat(xm, 0);
+  for (int i = 0; i < ym; ++i)
+  {
+    if (rowRepeat[R(i)] == 0)
+    {
+      slicedRowStart[R(i)] = i;
+    }
+    rowRepeat[R(i)]++;
+  }
+  std::vector<ColIndexType> 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<TX>::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<TX>::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<double, double, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::SparseMatrix<double, 0, int> const&, Eigen::DenseBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, Eigen::DenseBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, Eigen::SparseMatrix<double, 0, int>&);
+#endif

+ 42 - 0
include/igl/slice_sorted.h

@@ -0,0 +1,42 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+//
+// Copyright (C) 2019 Jérémie Dumas <[email protected]>
+//
+// 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/.
+
+#ifndef IGL_SLICE_SORTED_H
+#define IGL_SLICE_SORTED_H
+
+#include "igl_inline.h"
+#include <Eigen/Dense>
+#include <Eigen/Sparse>
+
+namespace igl
+{
+  // Act like the matlab X(row_indices,col_indices) operator, where row_indices,
+  // col_indices are non-negative integer indices. This version is about 2x faster
+  // than igl::slice, but it assumes that the indices to slice with are already sorted.
+  //
+  // Inputs:
+  //   X  m by n matrix
+  //   R  list of row indices
+  //   C  list of column indices
+  //
+  // Output:
+  //   Y  #R by #C matrix
+  //
+  template <typename TX, typename TY, typename DerivedR, typename DerivedC>
+  IGL_INLINE void slice_sorted(const Eigen::SparseMatrix<TX> &X,
+                               const Eigen::DenseBase<DerivedR> &R,
+                               const Eigen::DenseBase<DerivedC> &C,
+                               Eigen::SparseMatrix<TY> &Y);
+
+}  // namespace igl
+
+#ifndef IGL_STATIC_LIBRARY
+#include "slice_sorted.cpp"
+#endif
+
+#endif

+ 1 - 0
tests/CMakeLists.txt

@@ -27,6 +27,7 @@ add_subdirectory(${LIBIGL_EXTERNAL}/catch2 catch2)
 add_executable(libigl_tests main.cpp test_common.h)
 add_executable(libigl_tests main.cpp test_common.h)
 target_link_libraries(libigl_tests PUBLIC igl::core Catch2::Catch2)
 target_link_libraries(libigl_tests PUBLIC igl::core Catch2::Catch2)
 target_include_directories(libigl_tests PUBLIC ${CMAKE_CURRENT_LIST_DIR})
 target_include_directories(libigl_tests PUBLIC ${CMAKE_CURRENT_LIST_DIR})
+target_compile_definitions(libigl_tests PUBLIC CATCH_CONFIG_ENABLE_BENCHMARKING)
 
 
 # Set DATA_DIR definition
 # Set DATA_DIR definition
 set(DATA_DIR "${CMAKE_CURRENT_SOURCE_DIR}/data/")
 set(DATA_DIR "${CMAKE_CURRENT_SOURCE_DIR}/data/")

+ 79 - 0
tests/include/igl/slice_sorted.cpp

@@ -0,0 +1,79 @@
+#include <test_common.h>
+#include <igl/slice.h>
+#include <igl/slice_sorted.h>
+#include <random>
+
+namespace
+{
+  Eigen::SparseMatrix<double> generate_random_sparse_matrix(int rows, int cols)
+  {
+    std::mt19937 gen;
+    std::uniform_real_distribution<double> dist(0.0, 1.0);
+
+    using T = Eigen::Triplet<double>;
+    std::vector<T> tripletList;
+    for (int i = 0; i < rows; ++i)
+    {
+      for (int j = 0; j < cols; ++j)
+      {
+        auto v_ij = dist(gen);  // generate random number
+        if (v_ij < 0.1)
+        {
+          tripletList.push_back(T(i, j, v_ij));  // if larger than treshold, insert it
+        }
+      }
+    }
+    Eigen::SparseMatrix<double> mat(rows, cols);
+    mat.setFromTriplets(tripletList.begin(), tripletList.end());  // create the matrix
+    return mat;
+  }
+
+}  // namespace
+
+TEST_CASE("slice_sorted: correctness", "[igl]")
+{
+  constexpr int rows = 1e3;
+  constexpr int cols = 1e3;
+
+  Eigen::SparseMatrix<double> M = generate_random_sparse_matrix(rows, cols);
+
+  Eigen::Matrix<int, Eigen::Dynamic, 1> R(rows / 2);
+  Eigen::Matrix<int, Eigen::Dynamic, 1> C(cols / 2);
+  for (int i = 0; i < rows; i += 2) R[i / 2] = i;
+  for (int i = 0; i < cols; i += 2) C[i / 2] = i;
+
+  SECTION("correctness")
+  {
+    // Check for correctness
+    Eigen::SparseMatrix<double> A, B;
+    igl::slice(M, R, C, A);
+    igl::slice_sorted(M, R, C, B);
+    REQUIRE((A - B).norm() == 0);
+  }
+}
+
+TEST_CASE("slice_sorted: benchmark", "[igl]" IGL_DEBUG_OFF)
+{
+  constexpr int rows = 1e3;
+  constexpr int cols = 1e3;
+
+  Eigen::SparseMatrix<double> M = generate_random_sparse_matrix(rows, cols);
+
+  Eigen::Matrix<int, Eigen::Dynamic, 1> R(rows / 2);
+  Eigen::Matrix<int, Eigen::Dynamic, 1> C(cols / 2);
+  for (int i = 0; i < rows; i += 2) R[i / 2] = i;
+  for (int i = 0; i < cols; i += 2) C[i / 2] = i;
+
+  BENCHMARK("igl::slice") {
+    Eigen::SparseMatrix<double> A;
+    igl::slice(M, R, C, A);
+    return A.norm();
+  };
+
+  BENCHMARK("igl::slice_sorted") {
+    Eigen::SparseMatrix<double> A;
+    igl::slice_sorted(M, R, C, A);
+    return A.norm();
+  };
+}
+

+ 8 - 2
tests/test_common.h

@@ -1,8 +1,7 @@
 #pragma once
 #pragma once
 
 
-
 // These are not directly used but would otherwise be included in most files.
 // These are not directly used but would otherwise be included in most files.
-// Leaving them included here. 
+// Leaving them included here.
 #include <igl/read_triangle_mesh.h>
 #include <igl/read_triangle_mesh.h>
 #include <igl/readDMAT.h>
 #include <igl/readDMAT.h>
 
 
@@ -17,6 +16,13 @@
 #include <algorithm>
 #include <algorithm>
 #include <tuple>
 #include <tuple>
 
 
+// Disable lengthy tests in debug mode
+#ifdef NDEBUG
+#define IGL_DEBUG_OFF ""
+#else
+#define IGL_DEBUG_OFF "[!hide]"
+#endif
+
 namespace test_common
 namespace test_common
 {
 {
   template<typename Param, typename Fun>
   template<typename Param, typename Fun>