Squashed 'third_party/eigen/' changes from 61d72f6..cf794d3


Change-Id: I9b814151b01f49af6337a8605d0c42a3a1ed4c72
git-subtree-dir: third_party/eigen
git-subtree-split: cf794d3b741a6278df169e58461f8529f43bce5d
diff --git a/test/sparse_permutations.cpp b/test/sparse_permutations.cpp
index e4ce1d6..b82ccef 100644
--- a/test/sparse_permutations.cpp
+++ b/test/sparse_permutations.cpp
@@ -1,25 +1,57 @@
 // This file is part of Eigen, a lightweight C++ template library
 // for linear algebra.
 //
-// Copyright (C) 2011 Gael Guennebaud <gael.guennebaud@inria.fr>
+// Copyright (C) 2011-2015 Gael Guennebaud <gael.guennebaud@inria.fr>
 //
 // 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/.
 
+
+static long int nb_transposed_copies;
+#define EIGEN_SPARSE_TRANSPOSED_COPY_PLUGIN {nb_transposed_copies++;}
+#define VERIFY_TRANSPOSITION_COUNT(XPR,N) {\
+    nb_transposed_copies = 0; \
+    XPR; \
+    if(nb_transposed_copies!=N) std::cerr << "nb_transposed_copies == " << nb_transposed_copies << "\n"; \
+    VERIFY( (#XPR) && nb_transposed_copies==N ); \
+  }
+
 #include "sparse.h"
 
+template<typename T>
+bool is_sorted(const T& mat) {
+  for(Index k = 0; k<mat.outerSize(); ++k)
+  {
+    Index prev = -1;
+    for(typename T::InnerIterator it(mat,k); it; ++it)
+    {
+      if(prev>=it.index())
+        return false;
+      prev = it.index();
+    }
+  }
+  return true;
+}
+
+template<typename T>
+typename internal::nested_eval<T,1>::type eval(const T &xpr)
+{
+  VERIFY( int(internal::nested_eval<T,1>::type::Flags&RowMajorBit) == int(internal::evaluator<T>::Flags&RowMajorBit) );
+  return xpr;
+}
+
 template<int OtherStorage, typename SparseMatrixType> void sparse_permutations(const SparseMatrixType& ref)
 {
-  typedef typename SparseMatrixType::Index Index;
-
   const Index rows = ref.rows();
   const Index cols = ref.cols();
   typedef typename SparseMatrixType::Scalar Scalar;
-  typedef typename SparseMatrixType::Index Index;
-  typedef SparseMatrix<Scalar, OtherStorage, Index> OtherSparseMatrixType;
+  typedef typename SparseMatrixType::StorageIndex StorageIndex;
+  typedef SparseMatrix<Scalar, OtherStorage, StorageIndex> OtherSparseMatrixType;
   typedef Matrix<Scalar,Dynamic,Dynamic> DenseMatrix;
-  typedef Matrix<Index,Dynamic,1> VectorI;
+  typedef Matrix<StorageIndex,Dynamic,1> VectorI;
+//   bool IsRowMajor1 = SparseMatrixType::IsRowMajor;
+//   bool IsRowMajor2 = OtherSparseMatrixType::IsRowMajor;
   
   double density = (std::max)(8./(rows*cols), 0.01);
   
@@ -44,58 +76,69 @@
   randomPermutationVector(pi, cols);
   p.indices() = pi;
 
-  res = mat*p;
+  VERIFY( is_sorted( ::eval(mat*p) ));
+  VERIFY( is_sorted( res = mat*p ));
+  VERIFY_TRANSPOSITION_COUNT( ::eval(mat*p), 0);
+  //VERIFY_TRANSPOSITION_COUNT( res = mat*p, IsRowMajor ? 1 : 0 );
   res_d = mat_d*p;
   VERIFY(res.isApprox(res_d) && "mat*p");
 
-  res = p*mat;
+  VERIFY( is_sorted( ::eval(p*mat) ));
+  VERIFY( is_sorted( res = p*mat ));
+  VERIFY_TRANSPOSITION_COUNT( ::eval(p*mat), 0);
   res_d = p*mat_d;
   VERIFY(res.isApprox(res_d) && "p*mat");
 
-  res = mat*p.inverse();
+  VERIFY( is_sorted( (mat*p).eval() ));
+  VERIFY( is_sorted( res = mat*p.inverse() ));
+  VERIFY_TRANSPOSITION_COUNT( ::eval(mat*p.inverse()), 0);
   res_d = mat*p.inverse();
   VERIFY(res.isApprox(res_d) && "mat*inv(p)");
 
-  res = p.inverse()*mat;
+  VERIFY( is_sorted( (p*mat+p*mat).eval() ));
+  VERIFY( is_sorted( res = p.inverse()*mat ));
+  VERIFY_TRANSPOSITION_COUNT( ::eval(p.inverse()*mat), 0);
   res_d = p.inverse()*mat_d;
   VERIFY(res.isApprox(res_d) && "inv(p)*mat");
 
-  res = mat.twistedBy(p);
+  VERIFY( is_sorted( (p * mat * p.inverse()).eval() ));
+  VERIFY( is_sorted( res = mat.twistedBy(p) ));
+  VERIFY_TRANSPOSITION_COUNT( ::eval(p * mat * p.inverse()), 0);
   res_d = (p * mat_d) * p.inverse();
   VERIFY(res.isApprox(res_d) && "p*mat*inv(p)");
 
   
-  res = mat.template selfadjointView<Upper>().twistedBy(p_null);
+  VERIFY( is_sorted( res = mat.template selfadjointView<Upper>().twistedBy(p_null) ));
   res_d = up_sym_d;
   VERIFY(res.isApprox(res_d) && "full selfadjoint upper to full");
   
-  res = mat.template selfadjointView<Lower>().twistedBy(p_null);
+  VERIFY( is_sorted( res = mat.template selfadjointView<Lower>().twistedBy(p_null) ));
   res_d = lo_sym_d;
   VERIFY(res.isApprox(res_d) && "full selfadjoint lower to full");
   
   
-  res = up.template selfadjointView<Upper>().twistedBy(p_null);
+  VERIFY( is_sorted( res = up.template selfadjointView<Upper>().twistedBy(p_null) ));
   res_d = up_sym_d;
   VERIFY(res.isApprox(res_d) && "upper selfadjoint to full");
   
-  res = lo.template selfadjointView<Lower>().twistedBy(p_null);
+  VERIFY( is_sorted( res = lo.template selfadjointView<Lower>().twistedBy(p_null) ));
   res_d = lo_sym_d;
   VERIFY(res.isApprox(res_d) && "lower selfadjoint full");
 
 
-  res = mat.template selfadjointView<Upper>();
+  VERIFY( is_sorted( res = mat.template selfadjointView<Upper>() ));
   res_d = up_sym_d;
   VERIFY(res.isApprox(res_d) && "full selfadjoint upper to full");
 
-  res = mat.template selfadjointView<Lower>();
+  VERIFY( is_sorted( res = mat.template selfadjointView<Lower>() ));
   res_d = lo_sym_d;
   VERIFY(res.isApprox(res_d) && "full selfadjoint lower to full");
 
-  res = up.template selfadjointView<Upper>();
+  VERIFY( is_sorted( res = up.template selfadjointView<Upper>() ));
   res_d = up_sym_d;
   VERIFY(res.isApprox(res_d) && "upper selfadjoint to full");
 
-  res = lo.template selfadjointView<Lower>();
+  VERIFY( is_sorted( res = lo.template selfadjointView<Lower>() ));
   res_d = lo_sym_d;
   VERIFY(res.isApprox(res_d) && "lower selfadjoint full");
 
@@ -152,19 +195,19 @@
   VERIFY(res.isApprox(res_d) && "upper selfadjoint twisted to lower");
 
   
-  res = mat.template selfadjointView<Upper>().twistedBy(p);
+  VERIFY( is_sorted( res = mat.template selfadjointView<Upper>().twistedBy(p) ));
   res_d = (p * up_sym_d) * p.inverse();
   VERIFY(res.isApprox(res_d) && "full selfadjoint upper twisted to full");
   
-  res = mat.template selfadjointView<Lower>().twistedBy(p);
+  VERIFY( is_sorted( res = mat.template selfadjointView<Lower>().twistedBy(p) ));
   res_d = (p * lo_sym_d) * p.inverse();
   VERIFY(res.isApprox(res_d) && "full selfadjoint lower twisted to full");
   
-  res = up.template selfadjointView<Upper>().twistedBy(p);
+  VERIFY( is_sorted( res = up.template selfadjointView<Upper>().twistedBy(p) ));
   res_d = (p * up_sym_d) * p.inverse();
   VERIFY(res.isApprox(res_d) && "upper selfadjoint twisted to full");
   
-  res = lo.template selfadjointView<Lower>().twistedBy(p);
+  VERIFY( is_sorted( res = lo.template selfadjointView<Lower>().twistedBy(p) ));
   res_d = (p * lo_sym_d) * p.inverse();
   VERIFY(res.isApprox(res_d) && "lower selfadjoint twisted to full");
 }
@@ -184,4 +227,10 @@
     CALL_SUBTEST_1((  sparse_permutations_all<double>(s) ));
     CALL_SUBTEST_2((  sparse_permutations_all<std::complex<double> >(s) ));
   }
+
+  VERIFY((internal::is_same<internal::permutation_matrix_product<SparseMatrix<double>,OnTheRight,false,SparseShape>::ReturnType,
+                            internal::nested_eval<Product<SparseMatrix<double>,PermutationMatrix<Dynamic,Dynamic>,AliasFreeProduct>,1>::type>::value));
+
+  VERIFY((internal::is_same<internal::permutation_matrix_product<SparseMatrix<double>,OnTheLeft,false,SparseShape>::ReturnType,
+                            internal::nested_eval<Product<PermutationMatrix<Dynamic,Dynamic>,SparseMatrix<double>,AliasFreeProduct>,1>::type>::value));
 }