From 6fdd33d5bad629d796aa956a4f1f57aa92897c57 Mon Sep 17 00:00:00 2001
From: Christophe Geuzaine <cgeuzaine@uliege.be>
Date: Thu, 29 Feb 2024 20:28:42 +0000
Subject: [PATCH] Update gmm

---
 contrib/gmm/gmm.h                           |  61 +-
 contrib/gmm/gmm_MUMPS_interface.h           | 313 +++---
 contrib/gmm/gmm_algobase.h                  | 110 ++-
 contrib/gmm/gmm_arch_config.h               |   7 +
 contrib/gmm/gmm_blas.h                      | 585 ++++++------
 contrib/gmm/gmm_blas_interface.h            | 472 +++++++---
 contrib/gmm/gmm_condition_number.h          |  63 +-
 contrib/gmm/gmm_conjugated.h                | 195 ++--
 contrib/gmm/gmm_def.h                       | 121 +--
 contrib/gmm/gmm_dense_Householder.h         | 141 +--
 contrib/gmm/gmm_dense_lu.h                  | 199 ++--
 contrib/gmm/gmm_dense_matrix_functions.h    | 302 ++++++
 contrib/gmm/gmm_dense_qr.h                  | 399 ++++----
 contrib/gmm/gmm_dense_sylvester.h           |  59 +-
 contrib/gmm/gmm_domain_decomp.h             |  83 +-
 contrib/gmm/gmm_except.h                    | 463 +++++----
 contrib/gmm/gmm_feedback_management.h       | 174 ++++
 contrib/gmm/gmm_inoutput.h                  | 489 +++++-----
 contrib/gmm/gmm_interface.h                 |  83 +-
 contrib/gmm/gmm_interface_bgeot.h           |  59 +-
 contrib/gmm/gmm_iter.h                      | 115 ++-
 contrib/gmm/gmm_iter_solvers.h              |  62 +-
 contrib/gmm/gmm_kernel.h                    |  60 +-
 contrib/gmm/gmm_lapack_interface.h          | 470 +++++----
 contrib/gmm/gmm_least_squares_cg.h          |  59 +-
 contrib/gmm/gmm_matrix.h                    | 599 ++++++------
 contrib/gmm/gmm_modified_gram_schmidt.h     |  76 +-
 contrib/gmm/gmm_opt.h                       | 172 ++--
 contrib/gmm/gmm_precond.h                   |  61 +-
 contrib/gmm/gmm_precond_diagonal.h          |  69 +-
 contrib/gmm/gmm_precond_ildlt.h             | 111 +--
 contrib/gmm/gmm_precond_ildltt.h            | 109 +--
 contrib/gmm/gmm_precond_ilu.h               |  76 +-
 contrib/gmm/gmm_precond_ilut.h              |  94 +-
 contrib/gmm/gmm_precond_ilutp.h             |  71 +-
 contrib/gmm/gmm_precond_mr_approx_inverse.h |  65 +-
 contrib/gmm/gmm_range_basis.h               | 499 ++++++++++
 contrib/gmm/gmm_real_part.h                 | 396 ++++----
 contrib/gmm/gmm_ref.h                       |  63 +-
 contrib/gmm/gmm_scaled.h                    | 249 ++---
 contrib/gmm/gmm_solver_Newton.h             | 137 ---
 contrib/gmm/gmm_solver_Schwarz_additive.h   | 163 +++-
 contrib/gmm/gmm_solver_bfgs.h               |  71 +-
 contrib/gmm/gmm_solver_bicgstab.h           |  64 +-
 contrib/gmm/gmm_solver_cg.h                 | 102 +-
 contrib/gmm/gmm_solver_constrained_cg.h     |  63 +-
 contrib/gmm/gmm_solver_gmres.h              |  68 +-
 contrib/gmm/gmm_solver_idgmres.h            |  59 +-
 contrib/gmm/gmm_solver_qmr.h                |  73 +-
 contrib/gmm/gmm_std.h                       | 267 ++++--
 contrib/gmm/gmm_sub_index.h                 |  93 +-
 contrib/gmm/gmm_sub_matrix.h                |  73 +-
 contrib/gmm/gmm_sub_vector.h                |  74 +-
 contrib/gmm/gmm_superlu_interface.h         |  90 +-
 contrib/gmm/gmm_transposed.h                |  63 +-
 contrib/gmm/gmm_tri_solve.h                 |  91 +-
 contrib/gmm/gmm_vector.h                    | 996 ++++++++++++++++----
 contrib/gmm/gmm_vector_to_matrix.h          |  59 +-
 src/solver/linearSystemCSR.cpp              |   2 +-
 src/solver/linearSystemGmm.h                |   2 +-
 60 files changed, 6325 insertions(+), 4139 deletions(-)
 create mode 100644 contrib/gmm/gmm_arch_config.h
 create mode 100644 contrib/gmm/gmm_dense_matrix_functions.h
 create mode 100644 contrib/gmm/gmm_feedback_management.h
 create mode 100644 contrib/gmm/gmm_range_basis.h
 delete mode 100644 contrib/gmm/gmm_solver_Newton.h

diff --git a/contrib/gmm/gmm.h b/contrib/gmm/gmm.h
index 4aeaa2644f..b7d989a383 100644
--- a/contrib/gmm/gmm.h
+++ b/contrib/gmm/gmm.h
@@ -1,32 +1,33 @@
-// -*- c++ -*- (enables emacs c++ mode)
-//===========================================================================
-//
-// Copyright (C) 2002-2008 Yves Renard
-//
-// This file is a part of GETFEM++
-//
-// Getfem++  is  free software;  you  can  redistribute  it  and/or modify it
-// under  the  terms  of the  GNU  Lesser General Public License as published
-// by  the  Free Software Foundation;  either version 2.1 of the License,  or
-// (at your option) any later version.
-// This program  is  distributed  in  the  hope  that it will be useful,  but
-// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-// or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
-// License for more details.
-// You  should  have received a copy of the GNU Lesser General Public License
-// along  with  this program;  if not, write to the Free Software Foundation,
-// Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
-//
-// As a special exception, you may use this file as part of a free software
-// library without restriction.  Specifically, if other files instantiate
-// templates or use macros or inline functions from this file, or you compile
-// this file and link it with other files to produce an executable, this
-// file does not by itself cause the resulting executable to be covered by
-// the GNU General Public License.  This exception does not however
-// invalidate any other reasons why the executable file might be covered by
-// the GNU General Public License.
-//
-//===========================================================================
+/* -*- c++ -*- (enables emacs c++ mode) */
+/*===========================================================================
+
+ Copyright (C) 2002-2020 Yves Renard
+
+ This file is a part of GetFEM
+
+ GetFEM  is  free software;  you  can  redistribute  it  and/or modify it
+ under  the  terms  of the  GNU  Lesser General Public License as published
+ by  the  Free Software Foundation;  either version 3 of the License,  or
+ (at your option) any later version along with the GCC Runtime Library
+ Exception either version 3.1 or (at your option) any later version.
+ This program  is  distributed  in  the  hope  that it will be useful,  but
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+ License and GCC Runtime Library Exception for more details.
+ You  should  have received a copy of the GNU Lesser General Public License
+ along  with  this program;  if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+
+ As a special exception, you  may use  this file  as it is a part of a free
+ software  library  without  restriction.  Specifically,  if   other  files
+ instantiate  templates  or  use macros or inline functions from this file,
+ or  you compile this  file  and  link  it  with other files  to produce an
+ executable, this file  does  not  by itself cause the resulting executable
+ to be covered  by the GNU Lesser General Public License.  This   exception
+ does not  however  invalidate  any  other  reasons why the executable file
+ might be covered by the GNU Lesser General Public License.
+
+===========================================================================*/
 
 /**@file gmm.h
    @author  Yves Renard <Yves.Renard@insa-lyon.fr>
@@ -46,7 +47,7 @@
 
 #include "gmm_lapack_interface.h"
 #include "gmm_superlu_interface.h"
-#include "gmm_MUMPS_interface.h"
+#include "gmm_range_basis.h"
 
 #include "gmm_domain_decomp.h"
 
diff --git a/contrib/gmm/gmm_MUMPS_interface.h b/contrib/gmm/gmm_MUMPS_interface.h
index a7c14013da..3325690e62 100644
--- a/contrib/gmm/gmm_MUMPS_interface.h
+++ b/contrib/gmm/gmm_MUMPS_interface.h
@@ -1,32 +1,33 @@
-// -*- c++ -*- (enables emacs c++ mode)
-//===========================================================================
-//
-// Copyright (C) 2003-2008 Yves Renard
-//
-// This file is a part of GETFEM++
-//
-// Getfem++  is  free software;  you  can  redistribute  it  and/or modify it
-// under  the  terms  of the  GNU  Lesser General Public License as published
-// by  the  Free Software Foundation;  either version 2.1 of the License,  or
-// (at your option) any later version.
-// This program  is  distributed  in  the  hope  that it will be useful,  but
-// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-// or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
-// License for more details.
-// You  should  have received a copy of the GNU Lesser General Public License
-// along  with  this program;  if not, write to the Free Software Foundation,
-// Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
-//
-// As a special exception, you may use this file as part of a free software
-// library without restriction.  Specifically, if other files instantiate
-// templates or use macros or inline functions from this file, or you compile
-// this file and link it with other files to produce an executable, this
-// file does not by itself cause the resulting executable to be covered by
-// the GNU General Public License.  This exception does not however
-// invalidate any other reasons why the executable file might be covered by
-// the GNU General Public License.
-//
-//===========================================================================
+/* -*- c++ -*- (enables emacs c++ mode) */
+/*===========================================================================
+
+ Copyright (C) 2003-2020 Yves Renard, Julien Pommier
+
+ This file is a part of GetFEM
+
+ GetFEM  is  free software;  you  can  redistribute  it  and/or modify it
+ under  the  terms  of the  GNU  Lesser General Public License as published
+ by  the  Free Software Foundation;  either version 3 of the License,  or
+ (at your option) any later version along with the GCC Runtime Library
+ Exception either version 3.1 or (at your option) any later version.
+ This program  is  distributed  in  the  hope  that it will be useful,  but
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+ License and GCC Runtime Library Exception for more details.
+ You  should  have received a copy of the GNU Lesser General Public License
+ along  with  this program;  if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+
+ As a special exception, you  may use  this file  as it is a part of a free
+ software  library  without  restriction.  Specifically,  if   other  files
+ instantiate  templates  or  use macros or inline functions from this file,
+ or  you compile this  file  and  link  it  with other files  to produce an
+ executable, this file  does  not  by itself cause the resulting executable
+ to be covered  by the GNU Lesser General Public License.  This   exception
+ does not  however  invalidate  any  other  reasons why the executable file
+ might be covered by the GNU Lesser General Public License.
+
+===========================================================================*/
 
 /**@file gmm_MUMPS_interface.h
    @author Yves Renard <Yves.Renard@insa-lyon.fr>,
@@ -34,7 +35,7 @@
    @date December 8, 2005.
    @brief Interface with MUMPS (LU direct solver for sparse matrices).
 */
-#if defined(GMM_USES_MUMPS)
+#if defined(GMM_USES_MUMPS) || defined(HAVE_DMUMPS_C_H)
 
 #ifndef GMM_MUMPS_INTERFACE_H
 #define GMM_MUMPS_INTERFACE_H
@@ -65,34 +66,44 @@ extern "C" {
 
 namespace gmm {
 
+#define ICNTL(I) icntl[(I)-1]
+#define INFO(I) info[(I)-1]
+#define INFOG(I) infog[(I)-1]
+#define RINFOG(I) rinfog[(I)-1]
+
   template <typename T> struct ij_sparse_matrix {
     std::vector<int> irn;
     std::vector<int> jcn;
-    std::vector<T>        a;
+    std::vector<T> a;
+    bool sym;
     
     template <typename L> void store(const L& l, size_type i) {
        typename linalg_traits<L>::const_iterator it = vect_const_begin(l),
-	 ite = vect_const_end(l);
-       for (; it != ite; ++it)
-	 { irn.push_back(i + 1); jcn.push_back(it.index() + 1); a.push_back(*it); }
+         ite = vect_const_end(l);
+       for (; it != ite; ++it) {
+         int ir = (int)i + 1, jc = (int)it.index() + 1;
+         if (*it != T(0) && (!sym || ir >= jc)) 
+         { irn.push_back(ir); jcn.push_back(jc); a.push_back(*it); }
+       }
     }
 
     template <typename L> void build_from(const L& l, row_major) {
       for (size_type i = 0; i < mat_nrows(l); ++i)
-	store(mat_const_row(l, i), i);
+        store(mat_const_row(l, i), i);
     }
 
     template <typename L> void build_from(const L& l, col_major) {
       for (size_type i = 0; i < mat_ncols(l); ++i)
-	store(mat_const_col(l, i), i);
+        store(mat_const_col(l, i), i);
       irn.swap(jcn);
     }
 
-    template <typename L> ij_sparse_matrix(const L& A) {
+    template <typename L> ij_sparse_matrix(const L& A, bool sym_) {
       size_type nz = nnz(A);
+      sym = sym_;
       irn.reserve(nz); jcn.reserve(nz); a.reserve(nz);
       build_from(A,  typename principal_orientation_type<typename
-	       linalg_traits<L>::sub_orientation>::potype());
+                 linalg_traits<L>::sub_orientation>::potype());
     }
   };
 
@@ -100,7 +111,6 @@ namespace gmm {
   /*   MUMPS solve interface                                               */
   /* ********************************************************************* */
 
-
   template <typename T> struct mumps_interf {};
 
   template <> struct mumps_interf<float> {
@@ -129,20 +139,45 @@ namespace gmm {
   };
 
 
+  template <typename MUMPS_STRUCT>
+  static inline bool mumps_error_check(MUMPS_STRUCT &id) {
+    if (id.INFO(1) < 0) {
+      switch (id.INFO(1)) {
+        case -2:
+          GMM_ASSERT1(false, "Solve with MUMPS failed: NZ = " << id.INFO(2)
+                      << " is out of range");
+        case -6 : case -10 :
+          GMM_WARNING1("Solve with MUMPS failed: matrix is singular");
+          return false;
+        case -9:
+          GMM_ASSERT1(false, "Solve with MUMPS failed: error "
+                      << id.INFO(1) << ", increase ICNTL(14)");
+        case -13 :
+          GMM_ASSERT1(false, "Solve with MUMPS failed: not enough memory");
+        default :
+          GMM_ASSERT1(false, "Solve with MUMPS failed with error "
+                      << id.INFO(1));
+      }
+    }
+    return true;
+  }
+
+
   /** MUMPS solve interface  
    *  Works only with sparse or skyline matrices
    */
   template <typename MAT, typename VECTX, typename VECTB>
-  void MUMPS_solve(const MAT &A, const VECTX &X_, const VECTB &B) {
+  bool MUMPS_solve(const MAT &A, const VECTX &X_, const VECTB &B,
+                   bool sym = false, bool distributed = false) {
     VECTX &X = const_cast<VECTX &>(X_);
 
     typedef typename linalg_traits<MAT>::value_type T;
     typedef typename mumps_interf<T>::value_type MUMPS_T;
-    GMM_ASSERT2(gmm::mat_nrows(A) == gmm::mat_ncols(A), "Non square matrix");
+    GMM_ASSERT2(gmm::mat_nrows(A) == gmm::mat_ncols(A), "Non-square matrix");
   
     std::vector<T> rhs(gmm::vect_size(B)); gmm::copy(B, rhs);
-  
-    ij_sparse_matrix<T> AA(A);
+
+    ij_sparse_matrix<T> AA(A, sym);
   
     const int JOB_INIT = -1;
     const int JOB_END = -2;
@@ -150,64 +185,67 @@ namespace gmm {
 
     typename mumps_interf<T>::MUMPS_STRUC_C id;
 
+    int rank(0);
 #ifdef GMM_USES_MPI
-    int rank;
     MPI_Comm_rank(MPI_COMM_WORLD, &rank);
 #endif
     
     id.job = JOB_INIT;
     id.par = 1;
-    id.sym = 0;
+    id.sym = sym ? 2 : 0;
     id.comm_fortran = USE_COMM_WORLD;
     mumps_interf<T>::mumps_c(id);
     
-#ifdef GMM_USES_MPI
-    if (rank == 0) {
-#endif
-      id.n = gmm::mat_nrows(A);
-      id.nz = AA.irn.size();
-      id.irn = &(AA.irn[0]);
-      id.jcn = &(AA.jcn[0]);
-      id.a = (MUMPS_T*)(&(AA.a[0]));
-      id.rhs = (MUMPS_T*)(&(rhs[0]));
-#ifdef GMM_USES_MPI
+    if (rank == 0 || distributed) {
+      id.n = int(gmm::mat_nrows(A));
+      if (distributed) {
+        id.nz_loc = int(AA.irn.size());
+        id.irn_loc = &(AA.irn[0]);
+        id.jcn_loc = &(AA.jcn[0]);
+        id.a_loc = (MUMPS_T*)(&(AA.a[0]));
+      } else {
+        id.nz = int(AA.irn.size());
+        id.irn = &(AA.irn[0]);
+        id.jcn = &(AA.jcn[0]);
+        id.a = (MUMPS_T*)(&(AA.a[0]));
+      }
+      if (rank == 0)
+        id.rhs = (MUMPS_T*)(&(rhs[0]));
     }
-#endif
 
-#define ICNTL(I) icntl[(I)-1]
-#define INFO(I) info[(I)-1]
-    id.ICNTL(1) = -1; id.ICNTL(2) = -1; id.ICNTL(3) = -1; id.ICNTL(4) = 0;
-    id.job = 6;
-    
-    id.ICNTL(14) += 40; /* small boost to the workspace size as we have encountered some problem
-			   who did not fit in the default settings of mumps.. 
-			   by default, ICNTL(14) = 15 or 20
-		       */
+    id.ICNTL(1) = -1; // output stream for error messages
+    id.ICNTL(2) = -1; // output stream for other messages
+    id.ICNTL(3) = -1; // output stream for global information
+    id.ICNTL(4) = 0;  // verbosity level
+
+    if (distributed)
+      id.ICNTL(5) = 0;  // assembled input matrix (default)
+
+    id.ICNTL(14) += 80; /* small boost to the workspace size as we have encountered some problem
+                           who did not fit in the default settings of mumps.. 
+                           by default, ICNTL(14) = 15 or 20
+                        */
     //cout << "ICNTL(14): " << id.ICNTL(14) << "\n";
 
+    if (distributed)
+      id.ICNTL(18) = 3; // strategy for distributed input matrix
+
+    // id.ICNTL(22) = 1;   /* enables out-of-core support */
+
+    id.job = 6;
     mumps_interf<T>::mumps_c(id);
-    if (id.INFO(1) < 0) {
-      switch (id.INFO(1)) {
-	case -6 : case -10 :
-	  GMM_ASSERT1(false, "Solve with MUMPS failed: matrix is singular");
-	case -13 :
-	  GMM_ASSERT1(false, "Solve with MUMPS failed: not enough memory");
-        case -9:
-	  GMM_ASSERT1(false, "Solve with MUMPS failed: error " << id.INFO(1)
-		      << ", increase ICNTL(14)");
-	default :
-	  GMM_ASSERT1(false, "Solve with MUMPS failed with error "
-		      << id.INFO(1));
-      }
-    }
+    bool ok = mumps_error_check(id);
 
     id.job = JOB_END;
     mumps_interf<T>::mumps_c(id);
 
+#ifdef GMM_USES_MPI
+    MPI_Bcast(&(rhs[0]),id.n,gmm::mpi_type(T()),0,MPI_COMM_WORLD);
+#endif
+
     gmm::copy(rhs, X);
 
-#undef ICNTL
-#undef INFO
+    return ok;
 
   }
 
@@ -217,17 +255,31 @@ namespace gmm {
    *  Works only with sparse or skyline matrices
    */
   template <typename MAT, typename VECTX, typename VECTB>
-  void MUMPS_distributed_matrix_solve(const MAT &A, const VECTX &X_,
-				      const VECTB &B) {
-    VECTX &X = const_cast<VECTX &>(X_);
+  bool MUMPS_distributed_matrix_solve(const MAT &A, const VECTX &X_,
+                                      const VECTB &B, bool sym = false) {
+    return MUMPS_solve(A, X_, B, sym, true);
+  }
 
-    typedef typename linalg_traits<MAT>::value_type T;
+
+
+  template<typename T>
+  inline T real_or_complex(std::complex<T> a) { return a.real(); }
+  template<typename T>
+  inline T real_or_complex(T &a) { return a; }
+
+
+  /** Evaluate matrix determinant with MUMPS  
+   *  Works only with sparse or skyline matrices
+   */
+  template <typename MAT, typename T = typename linalg_traits<MAT>::value_type>
+  T MUMPS_determinant(const MAT &A, int &exponent,
+                      bool sym = false, bool distributed = false) {
+    exponent = 0;
     typedef typename mumps_interf<T>::value_type MUMPS_T;
+    typedef typename number_traits<T>::magnitude_type R;
     GMM_ASSERT2(gmm::mat_nrows(A) == gmm::mat_ncols(A), "Non-square matrix");
   
-    std::vector<T> rhs(gmm::vect_size(B)); gmm::copy(B, rhs);
-  
-    ij_sparse_matrix<T> AA(A);
+    ij_sparse_matrix<T> AA(A, sym);
   
     const int JOB_INIT = -1;
     const int JOB_END = -2;
@@ -235,68 +287,65 @@ namespace gmm {
 
     typename mumps_interf<T>::MUMPS_STRUC_C id;
 
+    int rank(0);
 #ifdef GMM_USES_MPI
-    int rank;
     MPI_Comm_rank(MPI_COMM_WORLD, &rank);
 #endif
     
     id.job = JOB_INIT;
     id.par = 1;
-    id.sym = 0;
+    id.sym = sym ? 2 : 0;
     id.comm_fortran = USE_COMM_WORLD;
     mumps_interf<T>::mumps_c(id);
     
-    id.n = gmm::mat_nrows(A);
-    id.nz_loc = AA.irn.size();
-    id.irn_loc = &(AA.irn[0]);
-    id.jcn_loc = &(AA.jcn[0]);
-    id.a_loc = (MUMPS_T*)(&(AA.a[0]));
-
-#ifdef GMM_USES_MPI
-    if (rank == 0) {
-#endif
-      id.rhs = (MUMPS_T*)(&(rhs[0]));
-#ifdef GMM_USES_MPI
+    if (rank == 0 || distributed) {
+      id.n = int(gmm::mat_nrows(A));
+      if (distributed) {
+        id.nz_loc = int(AA.irn.size());
+        id.irn_loc = &(AA.irn[0]);
+        id.jcn_loc = &(AA.jcn[0]);
+        id.a_loc = (MUMPS_T*)(&(AA.a[0]));
+      } else {
+        id.nz = int(AA.irn.size());
+        id.irn = &(AA.irn[0]);
+        id.jcn = &(AA.jcn[0]);
+        id.a = (MUMPS_T*)(&(AA.a[0]));
+      }
     }
-#endif
 
-#define ICNTL(I) icntl[(I)-1]
-#define INFO(I) info[(I)-1]
-    id.ICNTL(1) = -1; id.ICNTL(2) = 6; // id.ICNTL(2) = -1;
-    id.ICNTL(3) = 6;
-    // id.ICNTL(3) = -1; 
-    id.ICNTL(4) = 2;
-    id.ICNTL(5)=0; id.ICNTL(18)=3;
-    id.job = 6;
+    id.ICNTL(1) = -1; // output stream for error messages
+    id.ICNTL(2) = -1; // output stream for other messages
+    id.ICNTL(3) = -1; // output stream for global information
+    id.ICNTL(4) = 0;  // verbosity level
+
+    if (distributed)
+      id.ICNTL(5) = 0;  // assembled input matrix (default)
+
+//    id.ICNTL(14) += 80; // small boost to the workspace size 
+
+    if (distributed)
+      id.ICNTL(18) = 3; // strategy for distributed input matrix
+
+    id.ICNTL(31) = 1;   // only factorization, no solution to follow
+    id.ICNTL(33) = 1;   // request determinant calculation
+
+    id.job = 4; // abalysis (job=1) + factorization (job=2)
     mumps_interf<T>::mumps_c(id);
-    if (id.INFO(1) < 0) {
-      switch (id.INFO(1)) {
-      case -6 : case -10 :
-	GMM_ASSERT1(false, "Solve with MUMPS failed: matrix is singular");
-      case -13:
-	GMM_ASSERT1(false, "Solve with MUMPS failed: not enough memory");
-      case -9:
-	GMM_ASSERT1(false, "Solve with MUMPS failed: error " << id.INFO(1)
-		    << ", increase ICNTL(14)");
-      default :
-	GMM_ASSERT1(false, "Solve with MUMPS failed with error " <<id.INFO(1));
-      }
-    }
+    mumps_error_check(id);
+
+    T det = real_or_complex(std::complex<R>(id.RINFOG(12),id.RINFOG(13)));
+    exponent = id.INFOG(34);
 
     id.job = JOB_END;
     mumps_interf<T>::mumps_c(id);
-#ifdef GMM_USES_MPI
-    MPI_Bcast(&(rhs[0]),id.n,gmm::mpi_type(T()),0,MPI_COMM_WORLD);
-#endif
-    gmm::copy(rhs, X);
-
-#undef ICNTL
-#undef INFO
 
+    return det;
   }
 
-
-
+#undef ICNTL
+#undef INFO
+#undef INFOG
+#undef RINFOG
 
 }
 
diff --git a/contrib/gmm/gmm_algobase.h b/contrib/gmm/gmm_algobase.h
index 1b72ac217b..b07b6d93ae 100644
--- a/contrib/gmm/gmm_algobase.h
+++ b/contrib/gmm/gmm_algobase.h
@@ -1,32 +1,33 @@
-// -*- c++ -*- (enables emacs c++ mode)
-//===========================================================================
-//
-// Copyright (C) 2000-2008 Yves Renard
-//
-// This file is a part of GETFEM++
-//
-// Getfem++  is  free software;  you  can  redistribute  it  and/or modify it
-// under  the  terms  of the  GNU  Lesser General Public License as published
-// by  the  Free Software Foundation;  either version 2.1 of the License,  or
-// (at your option) any later version.
-// This program  is  distributed  in  the  hope  that it will be useful,  but
-// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-// or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
-// License for more details.
-// You  should  have received a copy of the GNU Lesser General Public License
-// along  with  this program;  if not, write to the Free Software Foundation,
-// Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
-//
-// As a special exception, you may use this file as part of a free software
-// library without restriction.  Specifically, if other files instantiate
-// templates or use macros or inline functions from this file, or you compile
-// this file and link it with other files to produce an executable, this
-// file does not by itself cause the resulting executable to be covered by
-// the GNU General Public License.  This exception does not however
-// invalidate any other reasons why the executable file might be covered by
-// the GNU General Public License.
-//
-//===========================================================================
+/* -*- c++ -*- (enables emacs c++ mode) */
+/*===========================================================================
+
+ Copyright (C) 2000-2020 Yves Renard
+
+ This file is a part of GetFEM
+
+ GetFEM  is  free software;  you  can  redistribute  it  and/or modify it
+ under  the  terms  of the  GNU  Lesser General Public License as published
+ by  the  Free Software Foundation;  either version 3 of the License,  or
+ (at your option) any later version along with the GCC Runtime Library
+ Exception either version 3.1 or (at your option) any later version.
+ This program  is  distributed  in  the  hope  that it will be useful,  but
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+ License and GCC Runtime Library Exception for more details.
+ You  should  have received a copy of the GNU Lesser General Public License
+ along  with  this program;  if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+
+ As a special exception, you  may use  this file  as it is a part of a free
+ software  library  without  restriction.  Specifically,  if   other  files
+ instantiate  templates  or  use macros or inline functions from this file,
+ or  you compile this  file  and  link  it  with other files  to produce an
+ executable, this file  does  not  by itself cause the resulting executable
+ to be covered  by the GNU Lesser General Public License.  This   exception
+ does not  however  invalidate  any  other  reasons why the executable file
+ might be covered by the GNU Lesser General Public License.
+
+===========================================================================*/
 
 /** @file gmm_algobase.h 
    @author  Yves Renard <Yves.Renard@insa-lyon.fr>
@@ -48,39 +49,36 @@ namespace gmm {
   /* ********************************************************************* */
   
   template <class T>
-    struct less : public std::binary_function<T, T, int> {
+    struct less {
     inline int operator()(const T& x, const T& y) const
     { return (x < y) ? -1 : ((y < x) ? 1 : 0); }
   };
 
-  template<> struct less<int> : public std::binary_function<int, int, int>
-  { int operator()(int x, int y) const { return x-y; } };
-  template<> struct less<char> : public std::binary_function<char, char, int>
-  { int operator()(char x, char y) const { return int(x-y); } };
-  template<> struct less<short> : public std::binary_function<short,short,int>
-  { int operator()(short x, short y) const { return int(x-y); } };
-  template<> struct less<unsigned char>
-     : public std::binary_function<unsigned char, unsigned char, int> {
+  template<> struct less<int> {
+    int operator()(int x, int y) const { return x-y; } };
+  template<> struct less<char> {
+    int operator()(char x, char y) const { return int(x-y); } };
+  template<> struct less<short> {
+    int operator()(short x, short y) const { return int(x-y); } };
+  template<> struct less<unsigned char> {
     int operator()(unsigned char x, unsigned char y) const
     { return int(x)-int(y); }
   };
   
 
   template <class T>
-    struct greater : public std::binary_function<T, T, int> {
+    struct greater {
     inline int operator()(const T& x, const T& y) const
     { return (y < x) ? -1 : ((x < y) ? 1 : 0); }
   };
 
-  template<> struct greater<int> : public std::binary_function<int, int, int>
-  { int operator()(int x, int y) const { return y-x; } };
-  template<> struct greater<char> : public std::binary_function<char,char,int>
-  { int operator()(char x, char y) const { return int(y-x); } };
-  template<> struct greater<short>
-      : public std::binary_function<short, short, int>
-  { int operator()(short x, short y) const { return int(y-x); } };
-  template<> struct greater<unsigned char>
-    : public std::binary_function<unsigned char, unsigned char, int> {
+  template<> struct greater<int> {
+    int operator()(int x, int y) const { return y-x; } };
+  template<> struct greater<char> {
+    int operator()(char x, char y) const { return int(y-x); } };
+  template<> struct greater<short> {
+    int operator()(short x, short y) const { return int(y-x); } };
+  template<> struct greater<unsigned char> {
     int operator()(unsigned char x, unsigned char y) const
       { return int(y)-int(x); }
   };
@@ -88,7 +86,7 @@ namespace gmm {
   template <typename T> inline T my_abs(T a) { return (a < T(0)) ? T(-a) : a; }
   
   template <class T>
-    struct approx_less : public std::binary_function<T, T, int> { 
+    struct approx_less { 
     double eps;
     inline int operator()(const T &x, const T &y) const
     { if (my_abs(x - y) <= eps) return 0; if (x < y) return -1; return 1; }
@@ -96,7 +94,7 @@ namespace gmm {
   };
 
   template <class T>
-    struct approx_greater : public std::binary_function<T, T, int> { 
+    struct approx_greater { 
     double eps;
     inline int operator()(const T &x, const T &y) const
     { if (my_abs(x - y) <= eps) return 0; if (x > y) return -1; return 1; }
@@ -109,12 +107,13 @@ namespace gmm {
     int i;
     for ( ; b1 != e1 && b2 != e2; ++b1, ++b2)
       if ((i = c(*b1, *b2)) != 0) return i;
-    if (b1 != e1) return 1; if (b2 != e2) return -1; return 0; 
+    if (b1 != e1) return 1;
+    if (b2 != e2) return -1;
+    return 0; 
   }
 
   template<class CONT, class COMP = gmm::less<typename CONT::value_type> >
-    struct lexicographical_less : public std::binary_function<CONT, CONT, int>
-  { 
+    struct lexicographical_less {
     COMP c;
     int operator()(const CONT &x, const CONT &y) const {
       return gmm::lexicographical_compare(x.begin(), x.end(),
@@ -124,8 +123,7 @@ namespace gmm {
   };
 
   template<class CONT, class COMP = gmm::less<typename CONT::value_type> >
-  struct lexicographical_greater
-    : public std::binary_function<CONT, CONT, int> { 
+  struct lexicographical_greater {
     COMP c;
     int operator()(const CONT &x, const CONT &y) const {
       return -gmm::lexicographical_compare(x.begin(), x.end(),
@@ -181,7 +179,7 @@ namespace gmm {
     size_t n = 1;
     typename std::iterator_traits<ITER>::value_type res = *first++;
     while (first != last) { res += *first; ++first; ++n; }
-    res /= n;
+    res /= float(n);
     return res;
   }
 
diff --git a/contrib/gmm/gmm_arch_config.h b/contrib/gmm/gmm_arch_config.h
new file mode 100644
index 0000000000..8d3ce66fb2
--- /dev/null
+++ b/contrib/gmm/gmm_arch_config.h
@@ -0,0 +1,7 @@
+#  ifndef _SRC_GMM_GMM_ARCH_CONFIG_H
+#define _SRC_GMM_GMM_ARCH_CONFIG_H 1
+// enable the following line for OpenMP support
+// #define GMM_HAVE_OPENMP
+//
+/* once: _SRC_GMM_GMM_ARCH_CONFIG_H */
+#endif
diff --git a/contrib/gmm/gmm_blas.h b/contrib/gmm/gmm_blas.h
index d239b8dfa8..21721303a2 100644
--- a/contrib/gmm/gmm_blas.h
+++ b/contrib/gmm/gmm_blas.h
@@ -1,32 +1,33 @@
-// -*- c++ -*- (enables emacs c++ mode)
-//===========================================================================
-//
-// Copyright (C) 2002-2008 Yves Renard
-//
-// This file is a part of GETFEM++
-//
-// Getfem++  is  free software;  you  can  redistribute  it  and/or modify it
-// under  the  terms  of the  GNU  Lesser General Public License as published
-// by  the  Free Software Foundation;  either version 2.1 of the License,  or
-// (at your option) any later version.
-// This program  is  distributed  in  the  hope  that it will be useful,  but
-// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-// or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
-// License for more details.
-// You  should  have received a copy of the GNU Lesser General Public License
-// along  with  this program;  if not, write to the Free Software Foundation,
-// Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
-//
-// As a special exception, you may use this file as part of a free software
-// library without restriction.  Specifically, if other files instantiate
-// templates or use macros or inline functions from this file, or you compile
-// this file and link it with other files to produce an executable, this
-// file does not by itself cause the resulting executable to be covered by
-// the GNU General Public License.  This exception does not however
-// invalidate any other reasons why the executable file might be covered by
-// the GNU General Public License.
-//
-//===========================================================================
+/* -*- c++ -*- (enables emacs c++ mode) */
+/*===========================================================================
+
+ Copyright (C) 2002-2020 Yves Renard
+
+ This file is a part of GetFEM
+
+ GetFEM  is  free software;  you  can  redistribute  it  and/or modify it
+ under  the  terms  of the  GNU  Lesser General Public License as published
+ by  the  Free Software Foundation;  either version 3 of the License,  or
+ (at your option) any later version along with the GCC Runtime Library
+ Exception either version 3.1 or (at your option) any later version.
+ This program  is  distributed  in  the  hope  that it will be useful,  but
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+ License and GCC Runtime Library Exception for more details.
+ You  should  have received a copy of the GNU Lesser General Public License
+ along  with  this program;  if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+
+ As a special exception, you  may use  this file  as it is a part of a free
+ software  library  without  restriction.  Specifically,  if   other  files
+ instantiate  templates  or  use macros or inline functions from this file,
+ or  you compile this  file  and  link  it  with other files  to produce an
+ executable, this file  does  not  by itself cause the resulting executable
+ to be covered  by the GNU Lesser General Public License.  This   exception
+ does not  however  invalidate  any  other  reasons why the executable file
+ might be covered by the GNU Lesser General Public License.
+
+===========================================================================*/
 
 /**@file gmm_blas.h
    @author  Yves Renard <Yves.Renard@insa-lyon.fr>
@@ -57,7 +58,7 @@ namespace gmm {
   /** clear (fill with zeros) a vector or matrix. */
   template <typename L> inline void clear(L &l)
   { linalg_traits<L>::do_clear(l); }
-  /** @cond DOXY_SHOW_ALL_FUNCTIONS 
+  /** @cond DOXY_SHOW_ALL_FUNCTIONS
       skip all these redundant definitions in doxygen documentation..
    */
   template <typename L> inline void clear(const L &l)
@@ -68,9 +69,8 @@ namespace gmm {
   { return nnz(l, typename linalg_traits<L>::linalg_type()); }
 
   ///@cond DOXY_SHOW_ALL_FUNCTIONS
-  template <typename L> inline size_type nnz(const L& l, abstract_vector) { 
-    typename linalg_traits<L>::const_iterator it = vect_const_begin(l),
-      ite = vect_const_end(l);
+  template <typename L> inline size_type nnz(const L& l, abstract_vector) {
+    auto it = vect_const_begin(l), ite = vect_const_end(l);
     size_type res(0);
     for (; it != ite; ++it) ++res;
     return res;
@@ -86,7 +86,7 @@ namespace gmm {
     for (size_type i = 0; i < mat_nrows(l); ++i)
       res += nnz(mat_const_row(l, i));
     return res;
-  } 
+  }
 
   template <typename L> inline size_type nnz(const L& l, col_major) {
     size_type res(0);
@@ -125,7 +125,7 @@ namespace gmm {
 	l(i,j) = x;
   }
 
-  /** fill a vector or matrix with random value (uniform [0,1]). */
+  /** fill a vector or matrix with random value (uniform [-1,1]). */
   template <typename L> inline void fill_random(L& l)
   { fill_random(l, typename linalg_traits<L>::linalg_type()); }
 
@@ -163,10 +163,11 @@ namespace gmm {
   template <typename L> inline
   void fill_random(L& l, double cfill, abstract_vector) {
     typedef typename linalg_traits<L>::value_type T;
-    size_type ntot = std::min(vect_size(l), size_type(vect_size(l)*cfill) + 1);
+    size_type ntot = std::min(vect_size(l),
+			      size_type(double(vect_size(l))*cfill) + 1);
     for (size_type nb = 0; nb < ntot;) {
       size_type i = gmm::irandom(vect_size(l));
-      if (l[i] == T(0)) { 
+      if (l[i] == T(0)) {
 	l[i] = gmm::random(typename linalg_traits<L>::value_type());
 	++nb;
       }
@@ -224,7 +225,7 @@ namespace gmm {
   void resize(M &, size_type, size_type, linalg_const)
   { GMM_ASSERT1(false, "You cannot resize a reference"); }
 
-  ///@endcond 
+  ///@endcond
   /** resize a matrix */
   template <typename M> inline
   void resize(M &v, size_type m, size_type n)
@@ -243,13 +244,13 @@ namespace gmm {
   void reshape(M &, size_type, size_type, linalg_const)
   { GMM_ASSERT1(false, "You cannot reshape a reference"); }
 
-  ///@endcond 
+  ///@endcond
   /** reshape a matrix */
   template <typename M> inline
   void reshape(M &v, size_type m, size_type n)
   { reshape(v, m, n, typename linalg_traits<M>::is_reference()); }
   ///@cond DOXY_SHOW_ALL_FUNCTIONS
-  
+
 
   /* ******************************************************************** */
   /*		Scalar product                             		  */
@@ -260,9 +261,10 @@ namespace gmm {
   template <typename V1, typename V2> inline
   typename strongest_value_type<V1,V2>::value_type
     vect_sp(const V1 &v1, const V2 &v2) {
-    GMM_ASSERT2(vect_size(v1) == vect_size(v2), "dimensions mismatch");
+    GMM_ASSERT2(vect_size(v1) == vect_size(v2), "dimensions mismatch, "
+                << vect_size(v1) << " !=" << vect_size(v2));
     return vect_sp(v1, v2,
-		   typename linalg_traits<V1>::storage_type(), 
+		   typename linalg_traits<V1>::storage_type(),
 		   typename linalg_traits<V2>::storage_type());
   }
 
@@ -282,17 +284,17 @@ namespace gmm {
   template <typename MATSP, typename V1, typename V2> inline
     typename strongest_value_type3<V1,V2,MATSP>::value_type
     vect_sp_with_mat(const MATSP &ps, const V1 &v1, const V2 &v2, row_major) {
-    return vect_sp_with_matr(ps, v1, v2, 
+    return vect_sp_with_matr(ps, v1, v2,
 			     typename linalg_traits<V2>::storage_type());
   }
 
-  template <typename MATSP, typename V1, typename V2> inline 
+  template <typename MATSP, typename V1, typename V2> inline
     typename strongest_value_type3<V1,V2,MATSP>::value_type
     vect_sp_with_matr(const MATSP &ps, const V1 &v1, const V2 &v2,
 		      abstract_sparse) {
     GMM_ASSERT2(vect_size(v1) == mat_ncols(ps) &&
-		vect_size(v2) == mat_nrows(ps), "dimensions mismatch");
-    //size_type nr = mat_nrows(ps);
+                vect_size(v2) == mat_nrows(ps), "dimensions mismatch");
+    mat_nrows(ps);
     typename linalg_traits<V2>::const_iterator
       it = vect_const_begin(v2), ite = vect_const_end(v2);
     typename strongest_value_type3<V1,V2,MATSP>::value_type res(0);
@@ -312,7 +314,7 @@ namespace gmm {
     vect_sp_with_matr(const MATSP &ps, const V1 &v1, const V2 &v2,
 		      abstract_dense) {
     GMM_ASSERT2(vect_size(v1) == mat_ncols(ps) &&
-		vect_size(v2) == mat_nrows(ps), "dimensions mismatch");
+                vect_size(v2) == mat_nrows(ps), "dimensions mismatch");
     typename linalg_traits<V2>::const_iterator
       it = vect_const_begin(v2), ite = vect_const_end(v2);
     typename strongest_value_type3<V1,V2,MATSP>::value_type res(0);
@@ -338,7 +340,7 @@ namespace gmm {
     vect_sp_with_matc(const MATSP &ps, const V1 &v1, const V2 &v2,
 		      abstract_sparse) {
     GMM_ASSERT2(vect_size(v1) == mat_ncols(ps) &&
-		vect_size(v2) == mat_nrows(ps),"dimensions mismatch");
+                vect_size(v2) == mat_nrows(ps), "dimensions mismatch");
     typename linalg_traits<V1>::const_iterator
       it = vect_const_begin(v1), ite = vect_const_end(v1);
     typename strongest_value_type3<V1,V2,MATSP>::value_type res(0);
@@ -358,7 +360,7 @@ namespace gmm {
     vect_sp_with_matc(const MATSP &ps, const V1 &v1, const V2 &v2,
 		      abstract_dense) {
     GMM_ASSERT2(vect_size(v1) == mat_ncols(ps) &&
-		vect_size(v2) == mat_nrows(ps), "dimensions mismatch");
+                vect_size(v2) == mat_nrows(ps), "dimensions mismatch");
     typename linalg_traits<V1>::const_iterator
       it = vect_const_begin(v1), ite = vect_const_end(v1);
     typename strongest_value_type3<V1,V2,MATSP>::value_type res(0);
@@ -378,7 +380,7 @@ namespace gmm {
 		   abstract_null_type) {
     typename temporary_vector<V1>::vector_type w(mat_nrows(ps));
     GMM_WARNING2("Warning, a temporary is used in scalar product\n");
-    mult(ps, v1, w); 
+    mult(ps, v1, w);
     return vect_sp(w, v2);
   }
 
@@ -391,7 +393,7 @@ namespace gmm {
     for (; it != ite; ++it, ++it2) res += (*it) * (*it2);
     return res;
   }
-  
+
   template <typename IT1, typename V> inline
     typename strongest_numeric_type<typename std::iterator_traits<IT1>::value_type,
 				    typename linalg_traits<V>::value_type>::T
@@ -431,10 +433,8 @@ namespace gmm {
     typename strongest_value_type<V1,V2>::value_type
     vect_sp(const V1 &v1, const V2 &v2, abstract_skyline, abstract_skyline) {
     typedef typename strongest_value_type<V1,V2>::value_type T;
-    typename linalg_traits<V1>::const_iterator it1 = vect_const_begin(v1),
-      ite1 =  vect_const_end(v1);
-    typename linalg_traits<V2>::const_iterator it2 = vect_const_begin(v2),
-      ite2 =  vect_const_end(v2);
+    auto it1 = vect_const_begin(v1), ite1 =  vect_const_end(v1);
+    auto it2 = vect_const_begin(v2), ite2 =  vect_const_end(v2);
     size_type n = std::min(ite1.index(), ite2.index());
     size_type l = std::max(it1.index(), it2.index());
 
@@ -478,7 +478,7 @@ namespace gmm {
     typename linalg_traits<V2>::const_iterator it2 = vect_const_begin(v2),
       ite2 = vect_const_end(v2);
     typename strongest_value_type<V1,V2>::value_type res(0);
-    
+
     while (it1 != ite1 && it2 != ite2) {
       if (it1.index() == it2.index())
 	{ res += (*it1) * *it2; ++it1; ++it2; }
@@ -500,7 +500,7 @@ namespace gmm {
 	    typename linalg_and<typename linalg_traits<V1>::index_sorted,
 	    typename linalg_traits<V2>::index_sorted>::bool_type());
   }
-  
+
   /* ******************************************************************** */
   /*		Hermitian product                             		  */
   /* ******************************************************************** */
@@ -521,14 +521,14 @@ namespace gmm {
   /* ******************************************************************** */
   /*		Trace of a matrix                             		  */
   /* ******************************************************************** */
-  
+
   /** Trace of a matrix */
    template <typename M>
    typename linalg_traits<M>::value_type
    mat_trace(const M &m) {
      typedef typename linalg_traits<M>::value_type T;
      T res(0);
-     for (size_type i = 0; i < std::max(mat_nrows(m), mat_ncols(m)); ++i)
+     for (size_type i = 0; i < std::min(mat_nrows(m), mat_ncols(m)); ++i)
        res += m(i,i);
      return res;
   }
@@ -537,39 +537,36 @@ namespace gmm {
   /*		Euclidean norm                             		  */
   /* ******************************************************************** */
 
-  /** Euclidean norm of a vector. */
+  /** squared Euclidean norm of a vector. */
   template <typename V>
   typename number_traits<typename linalg_traits<V>::value_type>
   ::magnitude_type
   vect_norm2_sqr(const V &v) {
     typedef typename linalg_traits<V>::value_type T;
     typedef typename number_traits<T>::magnitude_type R;
-    typename linalg_traits<V>::const_iterator
-      it = vect_const_begin(v), ite = vect_const_end(v);
+    auto it = vect_const_begin(v), ite = vect_const_end(v);
     R res(0);
     for (; it != ite; ++it) res += gmm::abs_sqr(*it);
     return res;
   }
 
-  /** squared Euclidean norm of a vector. */
+  /** Euclidean norm of a vector. */
   template <typename V> inline
    typename number_traits<typename linalg_traits<V>::value_type>
-   ::magnitude_type 
+   ::magnitude_type
   vect_norm2(const V &v)
   { return sqrt(vect_norm2_sqr(v)); }
-  
+
 
   /** squared Euclidean distance between two vectors */
   template <typename V1, typename V2> inline
    typename number_traits<typename linalg_traits<V1>::value_type>
    ::magnitude_type
-  vect_dist2_sqr(const V1 &v1, const V2 &v2) { // not fully optimized 
+  vect_dist2_sqr(const V1 &v1, const V2 &v2) { // not fully optimized
     typedef typename linalg_traits<V1>::value_type T;
     typedef typename number_traits<T>::magnitude_type R;
-    typename linalg_traits<V1>::const_iterator
-      it1 = vect_const_begin(v1), ite1 = vect_const_end(v1);
-    typename linalg_traits<V2>::const_iterator
-      it2 = vect_const_begin(v2), ite2 = vect_const_end(v2);
+    auto it1 = vect_const_begin(v1), ite1 = vect_const_end(v1);
+    auto it2 = vect_const_begin(v2), ite2 = vect_const_end(v2);
     size_type k1(0), k2(0);
     R res(0);
     while (it1 != ite1 && it2 != ite2) {
@@ -582,17 +579,17 @@ namespace gmm {
 	res += gmm::abs_sqr(*it2 - *it1); ++it1; ++k1; ++it2; ++k2;
       }
       else if (i1 < i2) {
-	res += gmm::abs_sqr(*it1); ++it1; ++k1; 
+	res += gmm::abs_sqr(*it1); ++it1; ++k1;
       }
       else  {
-	res += gmm::abs_sqr(*it2); ++it2; ++k2; 
+	res += gmm::abs_sqr(*it2); ++it2; ++k2;
       }
     }
     while (it1 != ite1) { res += gmm::abs_sqr(*it1); ++it1; }
     while (it2 != ite2) { res += gmm::abs_sqr(*it2); ++it2; }
     return res;
   }
- 
+
   /** Euclidean distance between two vectors */
   template <typename V1, typename V2> inline
    typename number_traits<typename linalg_traits<V1>::value_type>
@@ -647,30 +644,92 @@ namespace gmm {
   typename number_traits<typename linalg_traits<V>::value_type>
   ::magnitude_type
   vect_norm1(const V &v) {
-    typename linalg_traits<V>::const_iterator
-      it = vect_const_begin(v), ite = vect_const_end(v);
+    auto it = vect_const_begin(v), ite = vect_const_end(v);
     typename number_traits<typename linalg_traits<V>::value_type>
 	::magnitude_type res(0);
     for (; it != ite; ++it) res += gmm::abs(*it);
     return res;
   }
 
+  /** 1-distance between two vectors */
+  template <typename V1, typename V2> inline
+   typename number_traits<typename linalg_traits<V1>::value_type>
+   ::magnitude_type
+  vect_dist1(const V1 &v1, const V2 &v2) { // not fully optimized
+    typedef typename linalg_traits<V1>::value_type T;
+    typedef typename number_traits<T>::magnitude_type R;
+    auto it1 = vect_const_begin(v1), ite1 = vect_const_end(v1);
+    auto it2 = vect_const_begin(v2), ite2 = vect_const_end(v2);
+    size_type k1(0), k2(0);
+    R res(0);
+    while (it1 != ite1 && it2 != ite2) {
+      size_type i1 = index_of_it(it1, k1,
+				 typename linalg_traits<V1>::storage_type());
+      size_type i2 = index_of_it(it2, k2,
+				 typename linalg_traits<V2>::storage_type());
+
+      if (i1 == i2) {
+	res += gmm::abs(*it2 - *it1); ++it1; ++k1; ++it2; ++k2;
+      }
+      else if (i1 < i2) {
+	res += gmm::abs(*it1); ++it1; ++k1;
+      }
+      else  {
+	res += gmm::abs(*it2); ++it2; ++k2;
+      }
+    }
+    while (it1 != ite1) { res += gmm::abs(*it1); ++it1; }
+    while (it2 != ite2) { res += gmm::abs(*it2); ++it2; }
+    return res;
+  }
+
   /* ******************************************************************** */
   /*		vector Infinity norm                              	  */
   /* ******************************************************************** */
   /** Infinity norm of a vector. */
   template <typename V>
   typename number_traits<typename linalg_traits<V>::value_type>
-  ::magnitude_type 
+  ::magnitude_type
   vect_norminf(const V &v) {
-    typename linalg_traits<V>::const_iterator
-      it = vect_const_begin(v), ite = vect_const_end(v);
-      typename number_traits<typename linalg_traits<V>::value_type>
-	::magnitude_type res(0);
+    auto it = vect_const_begin(v), ite = vect_const_end(v);
+    typename number_traits<typename linalg_traits<V>::value_type>
+      ::magnitude_type res(0);
     for (; it != ite; ++it) res = std::max(res, gmm::abs(*it));
     return res;
   }
 
+  /** Infinity distance between two vectors */
+  template <typename V1, typename V2> inline
+   typename number_traits<typename linalg_traits<V1>::value_type>
+   ::magnitude_type
+  vect_distinf(const V1 &v1, const V2 &v2) { // not fully optimized
+    typedef typename linalg_traits<V1>::value_type T;
+    typedef typename number_traits<T>::magnitude_type R;
+    auto it1 = vect_const_begin(v1), ite1 = vect_const_end(v1);
+    auto it2 = vect_const_begin(v2), ite2 = vect_const_end(v2);
+    size_type k1(0), k2(0);
+    R res(0);
+    while (it1 != ite1 && it2 != ite2) {
+      size_type i1 = index_of_it(it1, k1,
+				 typename linalg_traits<V1>::storage_type());
+      size_type i2 = index_of_it(it2, k2,
+				 typename linalg_traits<V2>::storage_type());
+
+      if (i1 == i2) {
+	res = std::max(res, gmm::abs(*it2 - *it1)); ++it1; ++k1; ++it2; ++k2;
+      }
+      else if (i1 < i2) {
+	res = std::max(res, gmm::abs(*it1)); ++it1; ++k1;
+      }
+      else  {
+	res = std::max(res, gmm::abs(*it2)); ++it2; ++k2;
+      }
+    }
+    while (it1 != ite1) { res = std::max(res, gmm::abs(*it1)); ++it1; }
+    while (it2 != ite2) { res = std::max(res, gmm::abs(*it2)); ++it2; }
+    return res;
+  }
+
   /* ******************************************************************** */
   /*		matrix norm1                                    	  */
   /* ******************************************************************** */
@@ -693,13 +752,11 @@ namespace gmm {
     typedef typename linalg_traits<M>::value_type T;
     typedef typename number_traits<T>::magnitude_type R;
     typedef typename linalg_traits<M>::storage_type store_type;
-    
+
     std::vector<R> aux(mat_ncols(m));
     for (size_type i = 0; i < mat_nrows(m); ++i) {
-      typedef typename linalg_traits<M>::const_sub_row_type row_type;
-      row_type row = mat_const_row(m, i);
-      typename linalg_traits<row_type>::const_iterator
-	it = vect_const_begin(row), ite = vect_const_end(row);
+      typename linalg_traits<M>::const_sub_row_type row = mat_const_row(m, i);
+      auto it = vect_const_begin(row), ite = vect_const_end(row);
       for (size_type k = 0; it != ite; ++it, ++k)
 	aux[index_of_it(it, k, store_type())] += gmm::abs(*it);
     }
@@ -749,13 +806,11 @@ namespace gmm {
     typedef typename linalg_traits<M>::value_type T;
     typedef typename number_traits<T>::magnitude_type R;
     typedef typename linalg_traits<M>::storage_type store_type;
-    
+
     std::vector<R> aux(mat_nrows(m));
     for (size_type i = 0; i < mat_ncols(m); ++i) {
-      typedef typename linalg_traits<M>::const_sub_col_type col_type;
-      col_type col = mat_const_col(m, i);
-      typename linalg_traits<col_type>::const_iterator
-	it = vect_const_begin(col), ite = vect_const_end(col);
+      typename linalg_traits<M>::const_sub_col_type col = mat_const_col(m, i);
+      auto it = vect_const_begin(col), ite = vect_const_end(col);
       for (size_type k = 0; it != ite; ++it, ++k)
 	aux[index_of_it(it, k, store_type())] += gmm::abs(*it);
     }
@@ -822,7 +877,7 @@ namespace gmm {
   /*		Clean                                    		  */
   /* ******************************************************************** */
   /** Clean a vector or matrix (replace near-zero entries with zeroes).   */
-  
+
   template <typename L> inline void clean(L &l, double threshold);
 
   ///@cond DOXY_SHOW_ALL_FUNCTIONS
@@ -830,7 +885,7 @@ namespace gmm {
   template <typename L, typename T>
   void clean(L &l, double threshold, abstract_dense, T) {
     typedef typename number_traits<T>::magnitude_type R;
-    typename linalg_traits<L>::iterator it = vect_begin(l), ite = vect_end(l);
+    auto it = vect_begin(l), ite = vect_end(l);
     for (; it != ite; ++it)
       if (gmm::abs(*it) < R(threshold)) *it = T(0);
   }
@@ -842,16 +897,16 @@ namespace gmm {
   template <typename L, typename T>
   void clean(L &l, double threshold, abstract_sparse, T) {
     typedef typename number_traits<T>::magnitude_type R;
-    typename linalg_traits<L>::iterator it = vect_begin(l), ite = vect_end(l);
+    auto it = vect_begin(l), ite = vect_end(l);
     std::vector<size_type> ind;
     for (; it != ite; ++it)
       if (gmm::abs(*it) < R(threshold)) ind.push_back(it.index());
     for (size_type i = 0; i < ind.size(); ++i) l[ind[i]] = T(0);
   }
-  
+
   template <typename L, typename T>
   void clean(L &l, double threshold, abstract_dense, std::complex<T>) {
-    typename linalg_traits<L>::iterator it = vect_begin(l), ite = vect_end(l);
+    auto it = vect_begin(l), ite = vect_end(l);
     for (; it != ite; ++it){
       if (gmm::abs((*it).real()) < T(threshold))
 	*it = std::complex<T>(T(0), (*it).imag());
@@ -866,14 +921,14 @@ namespace gmm {
 
   template <typename L, typename T>
   void clean(L &l, double threshold, abstract_sparse, std::complex<T>) {
-    typename linalg_traits<L>::iterator it = vect_begin(l), ite = vect_end(l);
+    auto it = vect_begin(l), ite = vect_end(l);
     std::vector<size_type> ind;
     for (; it != ite; ++it) {
       bool r = (gmm::abs((*it).real()) < T(threshold));
       bool i = (gmm::abs((*it).imag()) < T(threshold));
       if (r && i) ind.push_back(it.index());
-      else if (r) (*it).real() = T(0);
-      else if (i) (*it).imag() = T(0);
+      else if (r) *it = std::complex<T>(T(0), (*it).imag());
+      else if (i) *it = std::complex<T>((*it).real(), T(0));
     }
     for (size_type i = 0; i < ind.size(); ++i)
       l[ind[i]] = std::complex<T>(T(0),T(0));
@@ -906,7 +961,7 @@ namespace gmm {
 
   template <typename L> inline void clean(L &l, double threshold)
   { clean(l, threshold, typename linalg_traits<L>::linalg_type()); }
- 
+
   template <typename L> inline void clean(const L &l, double threshold)
   { gmm::clean(linalg_const_cast(l), threshold); }
 
@@ -914,16 +969,16 @@ namespace gmm {
   /*		Copy                                    		  */
   /* ******************************************************************** */
   ///@endcond
-  /** Copy vectors or matrices. 
+  /** Copy vectors or matrices.
       @param l1 source vector or matrix.
       @param l2 destination.
   */
   template <typename L1, typename L2> inline
-  void copy(const L1& l1, L2& l2) { 
+  void copy(const L1& l1, L2& l2) {
     if ((const void *)(&l1) != (const void *)(&l2)) {
       if (same_origin(l1,l2))
 	GMM_WARNING2("Warning : a conflict is possible in copy\n");
-     
+
       copy(l1, l2, typename linalg_traits<L1>::linalg_type(),
 	   typename linalg_traits<L2>::linalg_type());
     }
@@ -935,7 +990,8 @@ namespace gmm {
 
   template <typename L1, typename L2> inline
   void copy(const L1& l1, L2& l2, abstract_vector, abstract_vector) {
-    GMM_ASSERT2(vect_size(l1) == vect_size(l2), "dimensions mismatch");
+    GMM_ASSERT2(vect_size(l1) == vect_size(l2), "dimensions mismatch, "
+                << vect_size(l1) << " !=" << vect_size(l2));
     copy_vect(l1, l2, typename linalg_traits<L1>::storage_type(),
 	      typename linalg_traits<L2>::storage_type());
   }
@@ -949,27 +1005,23 @@ namespace gmm {
 	     typename linalg_traits<L2>::sub_orientation());
   }
 
-  template <typename V1, typename V2, typename C1, typename C2> inline 
+  template <typename V1, typename V2, typename C1, typename C2> inline
   void copy_vect(const V1 &v1, const V2 &v2, C1, C2)
   { copy_vect(v1, const_cast<V2 &>(v2), C1(), C2()); }
-  
+
 
   template <typename L1, typename L2>
   void copy_mat_by_row(const L1& l1, L2& l2) {
     size_type nbr = mat_nrows(l1);
     for (size_type i = 0; i < nbr; ++i)
-      copy_vect(mat_const_row(l1, i), mat_row(l2, i),
-      		typename linalg_traits<L1>::storage_type(),
-		typename linalg_traits<L2>::storage_type());
+      copy(mat_const_row(l1, i), mat_row(l2, i));
   }
 
   template <typename L1, typename L2>
   void copy_mat_by_col(const L1 &l1, L2 &l2) {
     size_type nbc = mat_ncols(l1);
     for (size_type i = 0; i < nbc; ++i) {
-      copy_vect(mat_const_col(l1, i), mat_col(l2, i),
-      		typename linalg_traits<L1>::storage_type(),
-		typename linalg_traits<L2>::storage_type());
+      copy(mat_const_col(l1, i), mat_col(l2, i));
     }
   }
 
@@ -1028,7 +1080,7 @@ namespace gmm {
   template <typename L1, typename L2> inline
   void copy_mat(const L1& l1, L2& l2, col_and_row, col_and_row)
   { copy_mat_by_col(l1, l2); }
-  
+
   template <typename L1, typename L2> inline
   void copy_mat_mixed_rc(const L1& l1, L2& l2, size_type i) {
     copy_mat_mixed_rc(l1, l2, i, typename linalg_traits<L1>::storage_type());
@@ -1036,24 +1088,21 @@ namespace gmm {
 
   template <typename L1, typename L2>
   void copy_mat_mixed_rc(const L1& l1, L2& l2, size_type i, abstract_sparse) {
-    typename linalg_traits<L1>::const_iterator
-      it  = vect_const_begin(l1), ite = vect_const_end(l1);
+    auto it  = vect_const_begin(l1), ite = vect_const_end(l1);
     for (; it != ite; ++it)
       l2(i, it.index()) = *it;
   }
 
   template <typename L1, typename L2>
   void copy_mat_mixed_rc(const L1& l1, L2& l2, size_type i, abstract_skyline) {
-    typename linalg_traits<L1>::const_iterator
-      it  = vect_const_begin(l1), ite = vect_const_end(l1);
+    auto it  = vect_const_begin(l1), ite = vect_const_end(l1);
     for (; it != ite; ++it)
       l2(i, it.index()) = *it;
   }
 
   template <typename L1, typename L2>
   void copy_mat_mixed_rc(const L1& l1, L2& l2, size_type i, abstract_dense) {
-    typename linalg_traits<L1>::const_iterator
-      it  = vect_const_begin(l1), ite = vect_const_end(l1);
+    auto it  = vect_const_begin(l1), ite = vect_const_end(l1);
     for (size_type j = 0; it != ite; ++it, ++j) l2(i, j) = *it;
   }
 
@@ -1064,22 +1113,19 @@ namespace gmm {
 
   template <typename L1, typename L2>
   void copy_mat_mixed_cr(const L1& l1, L2& l2, size_type i, abstract_sparse) {
-    typename linalg_traits<L1>::const_iterator
-      it  = vect_const_begin(l1), ite = vect_const_end(l1);
+    auto it  = vect_const_begin(l1), ite = vect_const_end(l1);
     for (; it != ite; ++it) l2(it.index(), i) = *it;
   }
 
   template <typename L1, typename L2>
   void copy_mat_mixed_cr(const L1& l1, L2& l2, size_type i, abstract_skyline) {
-    typename linalg_traits<L1>::const_iterator
-      it  = vect_const_begin(l1), ite = vect_const_end(l1);
+    auto it  = vect_const_begin(l1), ite = vect_const_end(l1);
     for (; it != ite; ++it) l2(it.index(), i) = *it;
   }
 
   template <typename L1, typename L2>
   void copy_mat_mixed_cr(const L1& l1, L2& l2, size_type i, abstract_dense) {
-    typename linalg_traits<L1>::const_iterator
-      it  = vect_const_begin(l1), ite = vect_const_end(l1);
+    auto it  = vect_const_begin(l1), ite = vect_const_end(l1);
     for (size_type j = 0; it != ite; ++it, ++j) l2(j, i) = *it;
   }
 
@@ -1090,7 +1136,7 @@ namespace gmm {
     for (size_type i = 0; i < nbr; ++i)
       copy_mat_mixed_rc(mat_const_row(l1, i), l2, i);
   }
-  
+
   template <typename L1, typename L2>
   void copy_mat(const L1& l1, L2& l2, col_major, row_major) {
     clear(l2);
@@ -1098,7 +1144,7 @@ namespace gmm {
     for (size_type i = 0; i < nbc; ++i)
       copy_mat_mixed_cr(mat_const_col(l1, i), l2, i);
   }
-  
+
   template <typename L1, typename L2> inline
   void copy_vect(const L1 &l1, L2 &l2, abstract_dense, abstract_dense) {
     std::copy(vect_const_begin(l1), vect_const_end(l1), vect_begin(l2));
@@ -1106,15 +1152,13 @@ namespace gmm {
 
   template <typename L1, typename L2> inline // to be optimised ?
   void copy_vect(const L1 &l1, L2 &l2, abstract_skyline, abstract_skyline) {
-    typename linalg_traits<L1>::const_iterator it1 = vect_const_begin(l1),
-      ite1 = vect_const_end(l1);
+    auto it1 = vect_const_begin(l1), ite1 = vect_const_end(l1);
     while (it1 != ite1 && *it1 == typename linalg_traits<L1>::value_type(0))
       ++it1;
 
     if (ite1 - it1 > 0) {
       clear(l2);
-      typename linalg_traits<L2>::iterator it2 = vect_begin(l2), 
-	ite2 = vect_end(l2);
+      auto it2 = vect_begin(l2), ite2 = vect_end(l2);
       while (*(ite1-1) == typename linalg_traits<L1>::value_type(0)) ite1--;
 
       if (it2 == ite2) {
@@ -1137,56 +1181,54 @@ namespace gmm {
       }
     }
   }
-  
+
   template <typename L1, typename L2>
   void copy_vect(const L1& l1, L2& l2, abstract_sparse, abstract_dense) {
     clear(l2);
-    typename linalg_traits<L1>::const_iterator
-      it  = vect_const_begin(l1), ite = vect_const_end(l1);
+    auto it  = vect_const_begin(l1), ite = vect_const_end(l1);
     for (; it != ite; ++it) { l2[it.index()] = *it; }
   }
 
   template <typename L1, typename L2>
   void copy_vect(const L1& l1, L2& l2, abstract_sparse, abstract_skyline) {
     clear(l2);
-    typename linalg_traits<L1>::const_iterator
-      it  = vect_const_begin(l1), ite = vect_const_end(l1);
+    auto it  = vect_const_begin(l1), ite = vect_const_end(l1);
     for (; it != ite; ++it) l2[it.index()] = *it;
   }
 
   template <typename L1, typename L2>
   void copy_vect(const L1& l1, L2& l2, abstract_skyline, abstract_dense) {
     typedef typename linalg_traits<L1>::value_type T;
-    typedef typename linalg_traits<L1>::const_iterator l1_const_iterator;
-    typedef typename linalg_traits<L2>::iterator l2_iterator;
-    l1_const_iterator it = vect_const_begin(l1), ite = vect_const_end(l1);
+    auto it = vect_const_begin(l1), ite = vect_const_end(l1);
     if (it == ite)
       gmm::clear(l2);
     else {
-      l2_iterator it2 = vect_begin(l2), ite2 = vect_end(l2);
-      
+      auto it2 = vect_begin(l2), ite2 = vect_end(l2);
+
       size_type i = it.index(), j;
       for (j = 0; j < i; ++j, ++it2) *it2 = T(0);
       for (; it != ite; ++it, ++it2) *it2 = *it;
       for (; it2 != ite2; ++it2) *it2 = T(0);
     }
   }
-    
+
   template <typename L1, typename L2>
   void copy_vect(const L1& l1, L2& l2, abstract_sparse, abstract_sparse) {
-    typename linalg_traits<L1>::const_iterator
-      it  = vect_const_begin(l1), ite = vect_const_end(l1);
+    auto  it  = vect_const_begin(l1), ite = vect_const_end(l1);
     clear(l2);
-    for (; it != ite; ++it)
+    // cout << "copy " << l1 << " of size " << vect_size(l1) << " nnz = " << nnz(l1) << endl;
+    for (; it != ite; ++it) {
+      // cout << "*it = " << *it << endl;
+      // cout << "it.index() = " << it.index() << endl;
       if (*it != (typename linalg_traits<L1>::value_type)(0))
 	l2[it.index()] = *it;
+    }
   }
-  
+
   template <typename L1, typename L2>
   void copy_vect(const L1& l1, L2& l2, abstract_dense, abstract_sparse) {
     clear(l2);
-    typename linalg_traits<L1>::const_iterator
-      it  = vect_const_begin(l1), ite = vect_const_end(l1);
+    auto  it  = vect_const_begin(l1), ite = vect_const_end(l1);
     for (size_type i = 0; it != ite; ++it, ++i)
       if (*it != (typename linalg_traits<L1>::value_type)(0))
 	l2[i] = *it;
@@ -1195,27 +1237,25 @@ namespace gmm {
   template <typename L1, typename L2> // to be optimised ...
   void copy_vect(const L1& l1, L2& l2, abstract_dense, abstract_skyline) {
     clear(l2);
-    typename linalg_traits<L1>::const_iterator
-      it  = vect_const_begin(l1), ite = vect_const_end(l1);
+    auto  it  = vect_const_begin(l1), ite = vect_const_end(l1);
     for (size_type i = 0; it != ite; ++it, ++i)
       if (*it != (typename linalg_traits<L1>::value_type)(0))
 	l2[i] = *it;
   }
 
-  
+
   template <typename L1, typename L2>
   void copy_vect(const L1& l1, L2& l2, abstract_skyline, abstract_sparse) {
     clear(l2);
-    typename linalg_traits<L1>::const_iterator
-      it  = vect_const_begin(l1), ite = vect_const_end(l1);
+    auto  it  = vect_const_begin(l1), ite = vect_const_end(l1);
     for (; it != ite; ++it)
       if (*it != (typename linalg_traits<L1>::value_type)(0))
 	l2[it.index()] = *it;
   }
 
   /* ******************************************************************** */
-  /*		Matrix and vector addition                             	  */
-  /*   algorithms are built in order to avoid some conflicts whith        */
+  /*   Matrix and vector addition                                         */
+  /*   algorithms are built in order to avoid some conflicts with         */
   /*   repeated arguments or with overlapping part of a same object.      */
   /*   In the latter case, conflicts are still possible.                  */
   /* ******************************************************************** */
@@ -1235,38 +1275,38 @@ namespace gmm {
 
   template <typename L1, typename L2> inline
     void add_spec(const L1& l1, L2& l2, abstract_vector) {
-    GMM_ASSERT2(vect_size(l1) == vect_size(l2), "dimensions mismatch");
+    GMM_ASSERT2(vect_size(l1) == vect_size(l2), "dimensions mismatch, "
+                << vect_size(l1) << " !=" << vect_size(l2));
     add(l1, l2, typename linalg_traits<L1>::storage_type(),
 	typename linalg_traits<L2>::storage_type());
   }
 
   template <typename L1, typename L2> inline
     void add_spec(const L1& l1, L2& l2, abstract_matrix) {
-    GMM_ASSERT2(mat_nrows(l1)==mat_nrows(l2) &&
-                mat_ncols(l1)==mat_ncols(l2), "dimensions mismatch");
+    GMM_ASSERT2(mat_nrows(l1)==mat_nrows(l2) && mat_ncols(l1)==mat_ncols(l2),
+                "dimensions mismatch l1 is " << mat_nrows(l1) << "x"
+		<< mat_ncols(l1) << " and l2 is " << mat_nrows(l2)
+		<< "x" << mat_ncols(l2));
     add(l1, l2, typename linalg_traits<L1>::sub_orientation(),
 	typename linalg_traits<L2>::sub_orientation());
   }
 
   template <typename L1, typename L2>
   void add(const L1& l1, L2& l2, row_major, row_major) {
-    typename linalg_traits<L1>::const_row_iterator it1 = mat_row_begin(l1),
-      ite = mat_row_end(l1);
-    typename linalg_traits<L2>::row_iterator it2 = mat_row_begin(l2);
+    auto it1 = mat_row_begin(l1), ite = mat_row_end(l1);
+    auto it2 = mat_row_begin(l2);
     for ( ; it1 != ite; ++it1, ++it2)
       add(linalg_traits<L1>::row(it1), linalg_traits<L2>::row(it2));
   }
 
   template <typename L1, typename L2>
   void add(const L1& l1, L2& l2, col_major, col_major) {
-    typename linalg_traits<L1>::const_col_iterator
-      it1 = mat_col_const_begin(l1),
-      ite = mat_col_const_end(l1);
+    auto it1 = mat_col_const_begin(l1), ite = mat_col_const_end(l1);
     typename linalg_traits<L2>::col_iterator it2 = mat_col_begin(l2);
     for ( ; it1 != ite; ++it1, ++it2)
       add(linalg_traits<L1>::col(it1),  linalg_traits<L2>::col(it2));
   }
-  
+
     template <typename L1, typename L2> inline
   void add_mat_mixed_rc(const L1& l1, L2& l2, size_type i) {
     add_mat_mixed_rc(l1, l2, i, typename linalg_traits<L1>::storage_type());
@@ -1274,22 +1314,19 @@ namespace gmm {
 
   template <typename L1, typename L2>
   void add_mat_mixed_rc(const L1& l1, L2& l2, size_type i, abstract_sparse) {
-    typename linalg_traits<L1>::const_iterator
-      it  = vect_const_begin(l1), ite = vect_const_end(l1);
+    auto it  = vect_const_begin(l1), ite = vect_const_end(l1);
     for (; it != ite; ++it) l2(i, it.index()) += *it;
   }
 
   template <typename L1, typename L2>
   void add_mat_mixed_rc(const L1& l1, L2& l2, size_type i, abstract_skyline) {
-    typename linalg_traits<L1>::const_iterator
-      it  = vect_const_begin(l1), ite = vect_const_end(l1);
+    auto it  = vect_const_begin(l1), ite = vect_const_end(l1);
     for (; it != ite; ++it) l2(i, it.index()) += *it;
   }
 
   template <typename L1, typename L2>
   void add_mat_mixed_rc(const L1& l1, L2& l2, size_type i, abstract_dense) {
-    typename linalg_traits<L1>::const_iterator
-      it  = vect_const_begin(l1), ite = vect_const_end(l1);
+    auto it  = vect_const_begin(l1), ite = vect_const_end(l1);
     for (size_type j = 0; it != ite; ++it, ++j) l2(i, j) += *it;
   }
 
@@ -1300,22 +1337,19 @@ namespace gmm {
 
   template <typename L1, typename L2>
   void add_mat_mixed_cr(const L1& l1, L2& l2, size_type i, abstract_sparse) {
-    typename linalg_traits<L1>::const_iterator
-      it  = vect_const_begin(l1), ite = vect_const_end(l1);
+    auto it  = vect_const_begin(l1), ite = vect_const_end(l1);
     for (; it != ite; ++it) l2(it.index(), i) += *it;
   }
 
   template <typename L1, typename L2>
   void add_mat_mixed_cr(const L1& l1, L2& l2, size_type i, abstract_skyline) {
-    typename linalg_traits<L1>::const_iterator
-      it  = vect_const_begin(l1), ite = vect_const_end(l1);
+    auto it  = vect_const_begin(l1), ite = vect_const_end(l1);
     for (; it != ite; ++it) l2(it.index(), i) += *it;
   }
 
   template <typename L1, typename L2>
   void add_mat_mixed_cr(const L1& l1, L2& l2, size_type i, abstract_dense) {
-    typename linalg_traits<L1>::const_iterator
-      it  = vect_const_begin(l1), ite = vect_const_end(l1);
+    auto it  = vect_const_begin(l1), ite = vect_const_end(l1);
     for (size_type j = 0; it != ite; ++it, ++j) l2(j, i) += *it;
   }
 
@@ -1325,7 +1359,7 @@ namespace gmm {
     for (size_type i = 0; i < nbr; ++i)
       add_mat_mixed_rc(mat_const_row(l1, i), l2, i);
   }
-  
+
   template <typename L1, typename L2>
   void add(const L1& l1, L2& l2, col_major, row_major) {
     size_type nbc = mat_ncols(l1);
@@ -1403,8 +1437,10 @@ namespace gmm {
 
   template <typename L1, typename L2, typename L3> inline
     void add_spec(const L1& l1, const L2& l2, L3& l3, abstract_vector) {
-    GMM_ASSERT2(vect_size(l1) == vect_size(l2) &&
-		vect_size(l1) == vect_size(l3), "dimensions mismatch");
+    GMM_ASSERT2(vect_size(l1) == vect_size(l2), "dimensions mismatch, "
+                << vect_size(l1) << " !=" << vect_size(l2));
+    GMM_ASSERT2(vect_size(l1) == vect_size(l3), "dimensions mismatch, "
+                << vect_size(l1) << " !=" << vect_size(l3));
     if ((const void *)(&l1) == (const void *)(&l3))
       add(l2, l3);
     else if ((const void *)(&l2) == (const void *)(&l3))
@@ -1435,16 +1471,16 @@ namespace gmm {
     IT3 it = it3;
     for (; it != ite3; ++it) *it = T(0);
     for (; it1 != ite1; ++it1) *(it3 + it1.index()) = *it1;
-    for (; it2 != ite2; ++it2) *(it3 + it2.index()) += *it2;    
+    for (; it2 != ite2; ++it2) *(it3 + it2.index()) += *it2;
   }
-  
+
   template <typename L1, typename L2, typename L3> inline
   void add(const L1& l1, const L2& l2, L3& l3,
 	   abstract_dense, abstract_dense, abstract_dense) {
     add_full_(vect_const_begin(l1), vect_const_begin(l2),
 	      vect_begin(l3), vect_end(l3));
   }
-  
+
   // generic function for add(v1, v2, v3).
   // Need to be specialized to optimize particular additions.
   template <typename L1, typename L2, typename L3,
@@ -1458,12 +1494,12 @@ namespace gmm {
     add_almost_full_(vect_const_begin(l1), vect_const_end(l1),
 		     vect_const_begin(l2), vect_begin(l3), vect_end(l3));
   }
-  
+
   template <typename L1, typename L2, typename L3> inline
   void add(const L1& l1, const L2& l2, L3& l3,
 	   abstract_dense, abstract_sparse, abstract_dense)
   { add(l2, l1, l3, abstract_sparse(), abstract_dense(), abstract_dense()); }
-  
+
   template <typename L1, typename L2, typename L3> inline
   void add(const L1& l1, const L2& l2, L3& l3,
 	   abstract_sparse, abstract_sparse, abstract_dense) {
@@ -1475,10 +1511,8 @@ namespace gmm {
 
   template <typename L1, typename L2, typename L3>
   void add_spspsp(const L1& l1, const L2& l2, L3& l3, linalg_true) {
-    typename linalg_traits<L1>::const_iterator
-      it1 = vect_const_begin(l1), ite1 = vect_const_end(l1);
-    typename linalg_traits<L2>::const_iterator
-      it2 = vect_const_begin(l2), ite2 = vect_const_end(l2);
+    auto it1 = vect_const_begin(l1), ite1 = vect_const_end(l1);
+    auto it2 = vect_const_begin(l2), ite2 = vect_const_end(l2);
     clear(l3);
     while (it1 != ite1 && it2 != ite2) {
       ptrdiff_t d = it1.index() - it2.index();
@@ -1490,13 +1524,13 @@ namespace gmm {
 	{ l3[it1.index()] = *it1 + *it2; ++it1; ++it2; }
     }
     for (; it1 != ite1; ++it1) l3[it1.index()] += *it1;
-    for (; it2 != ite2; ++it2) l3[it2.index()] += *it2;   
+    for (; it2 != ite2; ++it2) l3[it2.index()] += *it2;
   }
 
   template <typename L1, typename L2, typename L3>
   void add_spspsp(const L1& l1, const L2& l2, L3& l3, linalg_false)
   { copy(l2, l3); add(l2, l3); }
-  
+
   template <typename L1, typename L2, typename L3>
   void add(const L1& l1, const L2& l2, L3& l3,
 	   abstract_sparse, abstract_sparse, abstract_sparse) {
@@ -1507,23 +1541,20 @@ namespace gmm {
 
   template <typename L1, typename L2>
   void add(const L1& l1, L2& l2, abstract_dense, abstract_dense) {
-    typename linalg_traits<L1>::const_iterator it1 = vect_const_begin(l1); 
-    typename linalg_traits<L2>::iterator
-             it2 = vect_begin(l2), ite = vect_end(l2);
+    auto it1 = vect_const_begin(l1);
+    auto it2 = vect_begin(l2), ite = vect_end(l2);
     for (; it2 != ite; ++it2, ++it1) *it2 += *it1;
   }
 
   template <typename L1, typename L2>
   void add(const L1& l1, L2& l2, abstract_dense, abstract_skyline) {
-    typedef typename linalg_traits<L1>::const_iterator const_l1_iterator;
-    typedef typename linalg_traits<L2>::iterator l2_iterator;
     typedef typename linalg_traits<L1>::value_type T;
 
-    const_l1_iterator it1 = vect_const_begin(l1), ite1 = vect_const_end(l1); 
+    auto it1 = vect_const_begin(l1), ite1 = vect_const_end(l1);
     size_type i1 = 0, ie1 = vect_size(l1);
     while (it1 != ite1 && *it1 == T(0)) { ++it1; ++i1; }
     if (it1 != ite1) {
-      l2_iterator it2 = vect_begin(l2), ite2 = vect_end(l2);
+      auto it2 = vect_begin(l2), ite2 = vect_end(l2);
       while (ie1 && *(ite1-1) == T(0)) { ite1--; --ie1; }
 
       if (it2 == ite2 || i1 < it2.index()) {
@@ -1543,42 +1574,37 @@ namespace gmm {
 
   template <typename L1, typename L2>
   void add(const L1& l1, L2& l2, abstract_skyline, abstract_dense) {
-    typename linalg_traits<L1>::const_iterator it1 = vect_const_begin(l1),
-      ite1 = vect_const_end(l1);
+    auto it1 = vect_const_begin(l1), ite1 = vect_const_end(l1);
     if (it1 != ite1) {
-      typename linalg_traits<L2>::iterator it2 = vect_begin(l2);
+      auto it2 = vect_begin(l2);
       it2 += it1.index();
       for (; it1 != ite1; ++it2, ++it1) *it2 += *it1;
     }
   }
 
-  
+
   template <typename L1, typename L2>
   void add(const L1& l1, L2& l2, abstract_sparse, abstract_dense) {
-    typename linalg_traits<L1>::const_iterator
-      it1 = vect_const_begin(l1), ite1 = vect_const_end(l1);
+    auto it1 = vect_const_begin(l1), ite1 = vect_const_end(l1);
     for (; it1 != ite1; ++it1) l2[it1.index()] += *it1;
   }
-  
+
   template <typename L1, typename L2>
   void add(const L1& l1, L2& l2, abstract_sparse, abstract_sparse) {
-    typename linalg_traits<L1>::const_iterator
-      it1 = vect_const_begin(l1), ite1 = vect_const_end(l1);
+    auto it1 = vect_const_begin(l1), ite1 = vect_const_end(l1);
     for (; it1 != ite1; ++it1) l2[it1.index()] += *it1;
   }
 
   template <typename L1, typename L2>
   void add(const L1& l1, L2& l2, abstract_sparse, abstract_skyline) {
-    typename linalg_traits<L1>::const_iterator
-      it1 = vect_const_begin(l1), ite1 = vect_const_end(l1);
+    auto it1 = vect_const_begin(l1), ite1 = vect_const_end(l1);
     for (; it1 != ite1; ++it1) l2[it1.index()] += *it1;
   }
 
 
   template <typename L1, typename L2>
   void add(const L1& l1, L2& l2, abstract_skyline, abstract_sparse) {
-    typename linalg_traits<L1>::const_iterator
-      it1 = vect_const_begin(l1), ite1 = vect_const_end(l1);
+    auto it1 = vect_const_begin(l1), ite1 = vect_const_end(l1);
     for (; it1 != ite1; ++it1)
       if (*it1 != typename linalg_traits<L1>::value_type(0))
 	l2[it1.index()] += *it1;
@@ -1586,16 +1612,14 @@ namespace gmm {
 
   template <typename L1, typename L2>
   void add(const L1& l1, L2& l2, abstract_skyline, abstract_skyline) {
-    typedef typename linalg_traits<L1>::const_iterator const_l1_iterator;
-    typedef typename linalg_traits<L2>::iterator l2_iterator;
     typedef typename linalg_traits<L1>::value_type T1;
     typedef typename linalg_traits<L2>::value_type T2;
 
-    const_l1_iterator it1 = vect_const_begin(l1), ite1 = vect_const_end(l1);
-    
+    auto it1 = vect_const_begin(l1), ite1 = vect_const_end(l1);
+
     while (it1 != ite1 && *it1 == T1(0)) ++it1;
     if (ite1 != it1) {
-      l2_iterator it2 = vect_begin(l2), ite2 = vect_end(l2);
+      auto it2 = vect_begin(l2), ite2 = vect_end(l2);
       while (*(ite1-1) == T1(0)) ite1--;
       if (it2 == ite2 || it1.index() < it2.index()) {
 	l2[it1.index()] = T2(0);
@@ -1603,20 +1627,19 @@ namespace gmm {
       }
       if (ite1.index() > ite2.index()) {
 	l2[ite1.index() - 1] = T2(0);
-	it2 = vect_begin(l2); 
+	it2 = vect_begin(l2);
       }
       it2 += it1.index() - it2.index();
       for (; it1 != ite1; ++it1, ++it2) *it2 += *it1;
     }
   }
-  
+
   template <typename L1, typename L2>
   void add(const L1& l1, L2& l2, abstract_dense, abstract_sparse) {
-    typename linalg_traits<L1>::const_iterator
-      it1 = vect_const_begin(l1), ite1 = vect_const_end(l1);
+    auto  it1 = vect_const_begin(l1), ite1 = vect_const_end(l1);
     for (size_type i = 0; it1 != ite1; ++it1, ++i)
       if (*it1 != typename linalg_traits<L1>::value_type(0)) l2[i] += *it1;
-  } 
+  }
 
   /* ******************************************************************** */
   /*		Matrix-vector mult                                    	  */
@@ -1668,7 +1691,7 @@ namespace gmm {
   template <typename L1, typename L2, typename L3>
   void mult_by_row(const L1& l1, const L2& l2, L3& l3, abstract_skyline) {
     typedef typename  linalg_traits<L3>::value_type T;
-    clear(l3); 
+    clear(l3);
     size_type nr = mat_nrows(l1);
     for (size_type i = 0; i < nr; ++i) {
       T aux = vect_sp(mat_const_row(l1, i), l2);
@@ -1679,8 +1702,7 @@ namespace gmm {
   template <typename L1, typename L2, typename L3>
   void mult_by_row(const L1& l1, const L2& l2, L3& l3, abstract_dense) {
     typename linalg_traits<L3>::iterator it=vect_begin(l3), ite=vect_end(l3);
-    typename linalg_traits<L1>::const_row_iterator
-      itr = mat_row_const_begin(l1); 
+    auto itr = mat_row_const_begin(l1);
     for (; it != ite; ++it, ++itr)
       *it = vect_sp(linalg_traits<L1>::row(itr), l2,
 		    typename linalg_traits<L1>::storage_type(),
@@ -1699,8 +1721,7 @@ namespace gmm {
   void mult_by_col(const L1& l1, const L2& l2, L3& l3, abstract_sparse) {
     typedef typename linalg_traits<L2>::value_type T;
     clear(l3);
-    typename linalg_traits<L2>::const_iterator it = vect_const_begin(l2),
-      ite = vect_const_end(l2);
+    auto it = vect_const_begin(l2), ite = vect_const_end(l2);
     for (; it != ite; ++it)
       if (*it != T(0)) add(scaled(mat_const_col(l1, it.index()), *it), l3);
   }
@@ -1708,9 +1729,8 @@ namespace gmm {
   template <typename L1, typename L2, typename L3>
   void mult_by_col(const L1& l1, const L2& l2, L3& l3, abstract_skyline) {
     typedef typename linalg_traits<L2>::value_type T;
-    clear(l3); 
-    typename linalg_traits<L2>::const_iterator it = vect_const_begin(l2),
-      ite = vect_const_end(l2);
+    clear(l3);
+    auto it = vect_const_begin(l2), ite = vect_const_end(l2);
     for (; it != ite; ++it)
       if (*it != T(0)) add(scaled(mat_const_col(l1, it.index()), *it), l3);
   }
@@ -1753,7 +1773,7 @@ namespace gmm {
 
   template <typename L1, typename L2, typename L3, typename L4> inline
   void mult(const L1& l1, const L2& l2, const L3& l3, const L4& l4)
-  { mult(l1, l2, l3, linalg_const_cast(l4)); } 
+  { mult(l1, l2, l3, linalg_const_cast(l4)); }
 
   ///@endcond
   /** Multiply-accumulate. l3 += l1*l2; */
@@ -1778,7 +1798,7 @@ namespace gmm {
 
   template <typename L1, typename L2, typename L3> inline
   void mult_add(const L1& l1, const L2& l2, const L3& l3)
-  { mult_add(l1, l2, linalg_const_cast(l3)); } 
+  { mult_add(l1, l2, linalg_const_cast(l3)); }
 
   template <typename L1, typename L2, typename L3>
   void mult_add_by_row(const L1& l1, const L2& l2, L3& l3, abstract_sparse) {
@@ -1802,9 +1822,8 @@ namespace gmm {
 
   template <typename L1, typename L2, typename L3>
   void mult_add_by_row(const L1& l1, const L2& l2, L3& l3, abstract_dense) {
-    typename linalg_traits<L3>::iterator it=vect_begin(l3), ite=vect_end(l3);
-    typename linalg_traits<L1>::const_row_iterator
-      itr = mat_row_const_begin(l1);
+    auto it=vect_begin(l3), ite=vect_end(l3);
+    auto itr = mat_row_const_begin(l1);
     for (; it != ite; ++it, ++itr)
       *it += vect_sp(linalg_traits<L1>::row(itr), l2);
   }
@@ -1818,8 +1837,7 @@ namespace gmm {
 
   template <typename L1, typename L2, typename L3>
   void mult_add_by_col(const L1& l1, const L2& l2, L3& l3, abstract_sparse) {
-    typename linalg_traits<L2>::const_iterator it = vect_const_begin(l2),
-      ite = vect_const_end(l2);
+    auto it = vect_const_begin(l2), ite = vect_const_end(l2);
     for (; it != ite; ++it)
       if (*it != typename linalg_traits<L2>::value_type(0))
 	add(scaled(mat_const_col(l1, it.index()), *it), l3);
@@ -1827,8 +1845,7 @@ namespace gmm {
 
   template <typename L1, typename L2, typename L3>
   void mult_add_by_col(const L1& l1, const L2& l2, L3& l3, abstract_skyline) {
-    typename linalg_traits<L2>::const_iterator it = vect_const_begin(l2),
-      ite = vect_const_end(l2);
+    auto it = vect_const_begin(l2), ite = vect_const_end(l2);
     for (; it != ite; ++it)
       if (*it != typename linalg_traits<L2>::value_type(0))
 	add(scaled(mat_const_col(l1, it.index()), *it), l3);
@@ -1854,7 +1871,7 @@ namespace gmm {
   /* ******************************************************************** */
   /*		Matrix-matrix mult                                    	  */
   /* ******************************************************************** */
-  
+
 
   struct g_mult {};  // generic mult, less optimized
   struct c_mult {};  // col x col -> col mult
@@ -1935,10 +1952,8 @@ namespace gmm {
     typedef typename temporary_matrix<L3>::matrix_type temp_mat_type;
     size_type n = mat_ncols(l1);
     if (n == 0) { gmm::clear(l3); return; }
-    GMM_ASSERT2(n == mat_nrows(l2) &&
-                mat_nrows(l1) == mat_nrows(l3) &&
-                mat_ncols(l2) == mat_ncols(l3),
-		"dimensions mismatch");
+    GMM_ASSERT2(n == mat_nrows(l2) && mat_nrows(l1) == mat_nrows(l3) &&
+                mat_ncols(l2) == mat_ncols(l3),	"dimensions mismatch");
 
     if (same_origin(l2, l3) || same_origin(l1, l3)) {
       GMM_WARNING2("A temporary is used for mult");
@@ -1993,16 +2008,15 @@ namespace gmm {
     if (is_sparse(l1) && is_sparse(l2)) {
       GMM_WARNING3("Inefficient row matrix - col matrix mult for "
 		  "sparse matrices, using temporary");
-      mult_row_col_with_temp(l1, l2, l3, 
+      mult_row_col_with_temp(l1, l2, l3,
 			     typename principal_orientation_type<typename
 			     linalg_traits<L3>::sub_orientation>::potype());
     }
     else {
-      typename linalg_traits<L2>::const_col_iterator
-	it2b = linalg_traits<L2>::col_begin(l2), it2,
+      auto it2b = linalg_traits<L2>::col_begin(l2), it2 = it2b,
 	ite = linalg_traits<L2>::col_end(l2);
       size_type i,j, k = mat_nrows(l1);
-      
+
       for (i = 0; i < k; ++i) {
 	typename linalg_traits<L1>::const_sub_row_type r1=mat_const_row(l1, i);
 	for (it2 = it2b, j = 0; it2 != ite; ++it2, ++j)
@@ -2037,8 +2051,7 @@ namespace gmm {
     size_type nn = mat_nrows(l3);
     for (size_type i = 0; i < nn; ++i) {
       typename linalg_traits<L1>::const_sub_row_type rl1=mat_const_row(l1, i);
-      typename linalg_traits<typename linalg_traits<L1>::const_sub_row_type>::
-	const_iterator it = vect_const_begin(rl1), ite = vect_const_end(rl1);
+      auto it = vect_const_begin(rl1), ite = vect_const_end(rl1);
       for (; it != ite; ++it)
 	add(scaled(mat_const_row(l2, it.index()), *it), mat_row(l3, i));
     }
@@ -2079,9 +2092,8 @@ namespace gmm {
     clear(l3);
     size_type nn = mat_ncols(l3);
     for (size_type i = 0; i < nn; ++i) {
-      typename linalg_traits<L2>::const_sub_col_type rc2=mat_const_col(l2, i);
-      typename linalg_traits<typename linalg_traits<L2>::const_sub_col_type>::
-	const_iterator it = vect_const_begin(rc2), ite = vect_const_end(rc2);
+      typename linalg_traits<L2>::const_sub_col_type rc2 = mat_const_col(l2, i);
+      auto it = vect_const_begin(rc2), ite = vect_const_end(rc2);
       for (; it != ite; ++it)
 	add(scaled(mat_const_col(l1, it.index()), *it), mat_col(l3, i));
     }
@@ -2106,7 +2118,7 @@ namespace gmm {
 		 abstract_skyline, ORIEN)
   { mult_spec(l1, l2, l3, c_mult(), abstract_sparse(), ORIEN()); }
 
-  
+
   // col - row matrix-matrix mult
 
   template <typename L1, typename L2, typename L3> inline
@@ -2131,9 +2143,8 @@ namespace gmm {
     clear(l3);
     size_type nn = mat_ncols(l1);
     for (size_type i = 0; i < nn; ++i) {
-      typename linalg_traits<L1>::const_sub_col_type rc1=mat_const_col(l1, i);
-      typename linalg_traits<typename linalg_traits<L1>::const_sub_col_type>::
-	const_iterator it = vect_const_begin(rc1), ite = vect_const_end(rc1);
+      typename linalg_traits<L1>::const_sub_col_type rc1 = mat_const_col(l1, i);
+      auto it = vect_const_begin(rc1), ite = vect_const_end(rc1);
       for (; it != ite; ++it)
 	add(scaled(mat_const_row(l2, i), *it), mat_row(l3, it.index()));
     }
@@ -2142,7 +2153,7 @@ namespace gmm {
   template <typename L1, typename L2, typename L3> inline
   void mult_spec(const L1& l1, const L2& l2, L3& l3, crmult, abstract_skyline)
   { mult_spec(l1, l2, l3, crmult(), abstract_sparse()); }
-  
+
 
   /* ******************************************************************** */
   /*		Symmetry test.                                     	  */
@@ -2163,8 +2174,8 @@ namespace gmm {
   }
   ///@cond DOXY_SHOW_ALL_FUNCTIONS
 
-  template <typename MAT> 
-  bool is_symmetric(const MAT &A, magnitude_of_linalg(MAT) tol, 
+  template <typename MAT>
+  bool is_symmetric(const MAT &A, magnitude_of_linalg(MAT) tol,
 		    abstract_dense) {
     size_type m = mat_nrows(A);
     for (size_type i = 1; i < m; ++i)
@@ -2173,43 +2184,39 @@ namespace gmm {
     return true;
   }
 
-  template <typename MAT> 
-  bool is_symmetric(const MAT &A, magnitude_of_linalg(MAT) tol, 
+  template <typename MAT>
+  bool is_symmetric(const MAT &A, magnitude_of_linalg(MAT) tol,
 		    abstract_sparse) {
     return is_symmetric(A, tol, typename principal_orientation_type<typename
 			linalg_traits<MAT>::sub_orientation>::potype());
   }
 
-  template <typename MAT> 
-  bool is_symmetric(const MAT &A, magnitude_of_linalg(MAT) tol, 
+  template <typename MAT>
+  bool is_symmetric(const MAT &A, magnitude_of_linalg(MAT) tol,
 		    row_major) {
     for (size_type i = 0; i < mat_nrows(A); ++i) {
-      typedef typename linalg_traits<MAT>::const_sub_row_type row_type;
-      row_type row = mat_const_row(A, i);
-      typename linalg_traits<row_type>::const_iterator
-	it = vect_const_begin(row), ite = vect_const_end(row);
+      typename linalg_traits<MAT>::const_sub_row_type row = mat_const_row(A, i);
+      auto it = vect_const_begin(row), ite = vect_const_end(row);
       for (; it != ite; ++it)
 	if (gmm::abs(*it - A(it.index(), i)) > tol) return false;
     }
     return true;
   }
 
-  template <typename MAT> 
-  bool is_symmetric(const MAT &A, magnitude_of_linalg(MAT) tol, 
+  template <typename MAT>
+  bool is_symmetric(const MAT &A, magnitude_of_linalg(MAT) tol,
 		    col_major) {
     for (size_type i = 0; i < mat_ncols(A); ++i) {
-      typedef typename linalg_traits<MAT>::const_sub_col_type col_type;
-      col_type col = mat_const_col(A, i);
-      typename linalg_traits<col_type>::const_iterator
-	it = vect_const_begin(col), ite = vect_const_end(col);
+      typename linalg_traits<MAT>::const_sub_col_type col = mat_const_col(A, i);
+      auto it = vect_const_begin(col), ite = vect_const_end(col);
       for (; it != ite; ++it)
 	if (gmm::abs(*it - A(i, it.index())) > tol) return false;
     }
     return true;
   }
 
-  template <typename MAT> 
-  bool is_symmetric(const MAT &A, magnitude_of_linalg(MAT) tol, 
+  template <typename MAT>
+  bool is_symmetric(const MAT &A, magnitude_of_linalg(MAT) tol,
 		    abstract_skyline)
   { return is_symmetric(A, tol, abstract_sparse()); }
 
@@ -2228,7 +2235,7 @@ namespace gmm {
   }
   ///@cond DOXY_SHOW_ALL_FUNCTIONS
 
-  template <typename MAT> 
+  template <typename MAT>
   bool is_hermitian(const MAT &A, magnitude_of_linalg(MAT) tol,
 		    abstract_dense) {
     size_type m = mat_nrows(A);
@@ -2238,43 +2245,39 @@ namespace gmm {
     return true;
   }
 
-  template <typename MAT> 
-  bool is_hermitian(const MAT &A, magnitude_of_linalg(MAT) tol, 
+  template <typename MAT>
+  bool is_hermitian(const MAT &A, magnitude_of_linalg(MAT) tol,
 		    abstract_sparse) {
     return is_hermitian(A, tol, typename principal_orientation_type<typename
 			linalg_traits<MAT>::sub_orientation>::potype());
   }
 
-  template <typename MAT> 
-  bool is_hermitian(const MAT &A, magnitude_of_linalg(MAT) tol, 
+  template <typename MAT>
+  bool is_hermitian(const MAT &A, magnitude_of_linalg(MAT) tol,
 		    row_major) {
     for (size_type i = 0; i < mat_nrows(A); ++i) {
-      typedef typename linalg_traits<MAT>::const_sub_row_type row_type;
-      row_type row = mat_const_row(A, i);
-      typename linalg_traits<row_type>::const_iterator
-	it = vect_const_begin(row), ite = vect_const_end(row);
+      typename linalg_traits<MAT>::const_sub_row_type row = mat_const_row(A, i);
+      auto it = vect_const_begin(row), ite = vect_const_end(row);
       for (; it != ite; ++it)
 	if (gmm::abs(gmm::conj(*it) - A(it.index(), i)) > tol) return false;
     }
     return true;
   }
 
-  template <typename MAT> 
-  bool is_hermitian(const MAT &A, magnitude_of_linalg(MAT) tol, 
+  template <typename MAT>
+  bool is_hermitian(const MAT &A, magnitude_of_linalg(MAT) tol,
 		    col_major) {
     for (size_type i = 0; i < mat_ncols(A); ++i) {
-      typedef typename linalg_traits<MAT>::const_sub_col_type col_type;
-      col_type col = mat_const_col(A, i);
-      typename linalg_traits<col_type>::const_iterator
-	it = vect_const_begin(col), ite = vect_const_end(col);
+      typename linalg_traits<MAT>::const_sub_col_type col = mat_const_col(A, i);
+      auto it = vect_const_begin(col), ite = vect_const_end(col);
       for (; it != ite; ++it)
 	if (gmm::abs(gmm::conj(*it) - A(i, it.index())) > tol) return false;
     }
     return true;
   }
 
-  template <typename MAT> 
-  bool is_hermitian(const MAT &A, magnitude_of_linalg(MAT) tol, 
+  template <typename MAT>
+  bool is_hermitian(const MAT &A, magnitude_of_linalg(MAT) tol,
 		    abstract_skyline)
   { return is_hermitian(A, tol, abstract_sparse()); }
   ///@endcond
diff --git a/contrib/gmm/gmm_blas_interface.h b/contrib/gmm/gmm_blas_interface.h
index 44e1dd8b72..c724a3b41e 100644
--- a/contrib/gmm/gmm_blas_interface.h
+++ b/contrib/gmm/gmm_blas_interface.h
@@ -1,35 +1,36 @@
-// -*- c++ -*- (enables emacs c++ mode)
-//===========================================================================
-//
-// Copyright (C) 2003-2008 Yves Renard
-//
-// This file is a part of GETFEM++
-//
-// Getfem++  is  free software;  you  can  redistribute  it  and/or modify it
-// under  the  terms  of the  GNU  Lesser General Public License as published
-// by  the  Free Software Foundation;  either version 2.1 of the License,  or
-// (at your option) any later version.
-// This program  is  distributed  in  the  hope  that it will be useful,  but
-// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-// or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
-// License for more details.
-// You  should  have received a copy of the GNU Lesser General Public License
-// along  with  this program;  if not, write to the Free Software Foundation,
-// Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
-//
-// As a special exception, you may use this file as part of a free software
-// library without restriction.  Specifically, if other files instantiate
-// templates or use macros or inline functions from this file, or you compile
-// this file and link it with other files to produce an executable, this
-// file does not by itself cause the resulting executable to be covered by
-// the GNU General Public License.  This exception does not however
-// invalidate any other reasons why the executable file might be covered by
-// the GNU General Public License.
-//
-//===========================================================================
+/* -*- c++ -*- (enables emacs c++ mode) */
+/*===========================================================================
+
+ Copyright (C) 2003-2020 Yves Renard
+
+ This file is a part of GetFEM
+
+ GetFEM  is  free software;  you  can  redistribute  it  and/or modify it
+ under  the  terms  of the  GNU  Lesser General Public License as published
+ by  the  Free Software Foundation;  either version 3 of the License,  or
+ (at your option) any later version along with the GCC Runtime Library
+ Exception either version 3.1 or (at your option) any later version.
+ This program  is  distributed  in  the  hope  that it will be useful,  but
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+ License and GCC Runtime Library Exception for more details.
+ You  should  have received a copy of the GNU Lesser General Public License
+ along  with  this program;  if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+
+ As a special exception, you  may use  this file  as it is a part of a free
+ software  library  without  restriction.  Specifically,  if   other  files
+ instantiate  templates  or  use macros or inline functions from this file,
+ or  you compile this  file  and  link  it  with other files  to produce an
+ executable, this file  does  not  by itself cause the resulting executable
+ to be covered  by the GNU Lesser General Public License.  This   exception
+ does not  however  invalidate  any  other  reasons why the executable file
+ might be covered by the GNU Lesser General Public License.
+
+===========================================================================*/
 
 /**@file gmm_blas_interface.h
-   @author  Caroline Lecalvez, Caroline.Lecalvez@gmm.insa-tlse.fr, Yves Renard <Yves.Renard@insa-lyon.fr>
+   @author  Yves Renard <Yves.Renard@insa-lyon.fr>
    @date October 7, 2003.
    @brief gmm interface for fortran BLAS.
 */
@@ -46,9 +47,17 @@
 
 namespace gmm {
 
+  // Use ./configure --enable-blas-interface to activate this interface.
+
 #define GMMLAPACK_TRACE(f) 
   // #define GMMLAPACK_TRACE(f) cout << "function " << f << " called" << endl;
 
+#if defined(WeirdNEC) || defined(GMM_USE_BLAS64_INTERFACE)
+  #define BLAS_INT long
+#else // By default BLAS_INT will just be int in C
+  #define BLAS_INT int
+#endif
+  
   /* ********************************************************************* */
   /* Operations interfaced for T = float, double, std::complex<float>      */
   /*    or std::complex<double> :                                          */
@@ -127,6 +136,12 @@ namespace gmm {
   /* lower_tri_solve(conjugated(dense_matrix<T>), std::vector<T>, k, b)    */
   /* upper_tri_solve(conjugated(dense_matrix<T>), std::vector<T>, k, b)    */
   /*                                                                       */
+  /* rank_one_update(dense_matrix<T>, std::vector<T>, std::vector<T>)      */
+  /* rank_one_update(dense_matrix<T>, scaled(std::vector<T>),              */
+  /*                                  std::vector<T>)                      */
+  /* rank_one_update(dense_matrix<T>, std::vector<T>,                      */
+  /*                                  scaled(std::vector<T>))              */
+  /*                                                                       */
   /* ********************************************************************* */
 
   /* ********************************************************************* */
@@ -141,9 +156,15 @@ namespace gmm {
   /* ********************************************************************* */
   /* BLAS functions used.                                                  */
   /* ********************************************************************* */
-  extern "C" void daxpy_(const int *n, const double *alpha, const double *x, const int *incx, double *y, const int *incy);
   extern "C" {
-    void sgemm_(...); void dgemm_(...); void cgemm_(...); void zgemm_(...);
+    void daxpy_(const BLAS_INT *n, const double *alpha, const double *x,
+                const BLAS_INT *incx, double *y, const BLAS_INT *incy);
+    void dgemm_(const char *tA, const char *tB, const BLAS_INT *m,
+                const BLAS_INT *n, const BLAS_INT *k, const double *alpha,
+                const double *A, const BLAS_INT *ldA, const double *B,
+                const BLAS_INT *ldB, const double *beta, double *C,
+                const BLAS_INT *ldC);
+    void sgemm_(...); void cgemm_(...); void zgemm_(...);
     void sgemv_(...); void dgemv_(...); void cgemv_(...); void zgemv_(...);
     void strsv_(...); void dtrsv_(...); void ctrsv_(...); void ztrsv_(...);
     void saxpy_(...); /*void daxpy_(...); */void caxpy_(...); void zaxpy_(...);
@@ -152,18 +173,21 @@ namespace gmm {
     BLAS_C cdotc_(...); BLAS_Z zdotc_(...);
     BLAS_S snrm2_(...); BLAS_D dnrm2_(...);
     BLAS_S scnrm2_(...); BLAS_D dznrm2_(...);
+    void  sger_(...); void  dger_(...); void  cgerc_(...); void  zgerc_(...); 
   }
 
+#if 1
+
   /* ********************************************************************* */
   /* vect_norm2(x).                                                        */
   /* ********************************************************************* */
 
-  # define nrm2_interface(param1, trans1, blas_name, base_type)            \
-  inline number_traits<base_type >::magnitude_type                         \
-    vect_norm2(param1(base_type)) {                                        \
-    GMMLAPACK_TRACE("nrm2_interface");                                     \
-    int inc(1), n(vect_size(x)); trans1(base_type);                        \
-    return blas_name(&n, &x[0], &inc);                                     \
+# define nrm2_interface(param1, trans1, blas_name, base_type)		   \
+  inline number_traits<base_type >::magnitude_type			   \
+  vect_norm2(param1(base_type)) {					   \
+    GMMLAPACK_TRACE("nrm2_interface");					   \
+    BLAS_INT inc(1), n(BLAS_INT(vect_size(x))); trans1(base_type);         \
+    return blas_name(&n, &x[0], &inc);					   \
   }
 
 # define nrm2_p1(base_type) const std::vector<base_type > &x
@@ -178,11 +202,12 @@ namespace gmm {
   /* vect_sp(x, y).                                                        */
   /* ********************************************************************* */
 
-  # define dot_interface(param1, trans1, mult1, param2, trans2, mult2,     \
+# define dot_interface(param1, trans1, mult1, param2, trans2, mult2,	   \
                          blas_name, base_type)                             \
   inline base_type vect_sp(param1(base_type), param2(base_type)) {         \
     GMMLAPACK_TRACE("dot_interface");                                      \
-    trans1(base_type); trans2(base_type); int inc(1), n(vect_size(y));     \
+    trans1(base_type); trans2(base_type);                                  \
+    BLAS_INT inc(1), n(BLAS_INT(vect_size(y)));                            \
     return mult1 mult2 blas_name(&n, &x[0], &inc, &y[0], &inc);            \
   }
 
@@ -204,20 +229,32 @@ namespace gmm {
          const_cast<std::vector<base_type > &>(*(linalg_origin(y_)));      \
          base_type b(y_.r)
 
-  dot_interface(dot_p1, dot_trans1, , dot_p2, dot_trans2, , sdot_ , BLAS_S)
-  dot_interface(dot_p1, dot_trans1, , dot_p2, dot_trans2, , ddot_ , BLAS_D)
-  dot_interface(dot_p1, dot_trans1, , dot_p2, dot_trans2, , cdotu_, BLAS_C)
-  dot_interface(dot_p1, dot_trans1, , dot_p2, dot_trans2, , zdotu_, BLAS_Z)
+  dot_interface(dot_p1, dot_trans1, (BLAS_S), dot_p2, dot_trans2, (BLAS_S),
+		sdot_ , BLAS_S)
+  dot_interface(dot_p1, dot_trans1, (BLAS_D), dot_p2, dot_trans2, (BLAS_D),
+		ddot_ , BLAS_D)
+  dot_interface(dot_p1, dot_trans1, (BLAS_C), dot_p2, dot_trans2, (BLAS_C),
+		cdotu_, BLAS_C)
+  dot_interface(dot_p1, dot_trans1, (BLAS_Z), dot_p2, dot_trans2, (BLAS_Z),
+		zdotu_, BLAS_Z)
   
-  dot_interface(dot_p1_s, dot_trans1_s, a*, dot_p2, dot_trans2, ,sdot_ ,BLAS_S)
-  dot_interface(dot_p1_s, dot_trans1_s, a*, dot_p2, dot_trans2, ,ddot_ ,BLAS_D)
-  dot_interface(dot_p1_s, dot_trans1_s, a*, dot_p2, dot_trans2, ,cdotu_,BLAS_C)
-  dot_interface(dot_p1_s, dot_trans1_s, a*, dot_p2, dot_trans2, ,zdotu_,BLAS_Z)
+  dot_interface(dot_p1_s, dot_trans1_s, a*, dot_p2, dot_trans2, (BLAS_S),
+		sdot_ ,BLAS_S)
+  dot_interface(dot_p1_s, dot_trans1_s, a*, dot_p2, dot_trans2, (BLAS_D),
+		ddot_ ,BLAS_D)
+  dot_interface(dot_p1_s, dot_trans1_s, a*, dot_p2, dot_trans2, (BLAS_C),
+		cdotu_,BLAS_C)
+  dot_interface(dot_p1_s, dot_trans1_s, a*, dot_p2, dot_trans2, (BLAS_Z),
+		zdotu_,BLAS_Z)
   
-  dot_interface(dot_p1, dot_trans1, , dot_p2_s, dot_trans2_s, b*,sdot_ ,BLAS_S)
-  dot_interface(dot_p1, dot_trans1, , dot_p2_s, dot_trans2_s, b*,ddot_ ,BLAS_D)
-  dot_interface(dot_p1, dot_trans1, , dot_p2_s, dot_trans2_s, b*,cdotu_,BLAS_C)
-  dot_interface(dot_p1, dot_trans1, , dot_p2_s, dot_trans2_s, b*,zdotu_,BLAS_Z)
+  dot_interface(dot_p1, dot_trans1, (BLAS_S), dot_p2_s, dot_trans2_s, b*,
+		sdot_ ,BLAS_S)
+  dot_interface(dot_p1, dot_trans1, (BLAS_D), dot_p2_s, dot_trans2_s, b*,
+		ddot_ ,BLAS_D)
+  dot_interface(dot_p1, dot_trans1, (BLAS_C), dot_p2_s, dot_trans2_s, b*,
+		cdotu_,BLAS_C)
+  dot_interface(dot_p1, dot_trans1, (BLAS_Z), dot_p2_s, dot_trans2_s, b*,
+		  zdotu_,BLAS_Z)
 
   dot_interface(dot_p1_s,dot_trans1_s,a*,dot_p2_s,dot_trans2_s,b*,sdot_ ,
 		BLAS_S)
@@ -233,11 +270,12 @@ namespace gmm {
   /* vect_hp(x, y).                                                        */
   /* ********************************************************************* */
 
-  # define dotc_interface(param1, trans1, mult1, param2, trans2, mult2,    \
-                         blas_name, base_type)                             \
+# define dotc_interface(param1, trans1, mult1, param2, trans2, mult2,	   \
+			blas_name, base_type)				   \
   inline base_type vect_hp(param1(base_type), param2(base_type)) {         \
     GMMLAPACK_TRACE("dotc_interface");                                     \
-    trans1(base_type); trans2(base_type); int inc(1), n(vect_size(y));     \
+    trans1(base_type); trans2(base_type);                                  \
+    BLAS_INT inc(1), n(BLAS_INT(vect_size(y)));                            \
     return mult1 mult2 blas_name(&n, &x[0], &inc, &y[0], &inc);            \
   }
 
@@ -259,28 +297,32 @@ namespace gmm {
          const_cast<std::vector<base_type > &>(*(linalg_origin(y_)));      \
          base_type b(gmm::conj(y_.r))
 
-  dotc_interface(dotc_p1, dotc_trans1, , dotc_p2, dotc_trans2, ,sdot_ ,BLAS_S)
-  dotc_interface(dotc_p1, dotc_trans1, , dotc_p2, dotc_trans2, ,ddot_ ,BLAS_D)
-  dotc_interface(dotc_p1, dotc_trans1, , dotc_p2, dotc_trans2, ,cdotc_,BLAS_C)
-  dotc_interface(dotc_p1, dotc_trans1, , dotc_p2, dotc_trans2, ,zdotc_,BLAS_Z)
+  dotc_interface(dotc_p1, dotc_trans1, (BLAS_S), dotc_p2, dotc_trans2,
+		 (BLAS_S),sdot_ ,BLAS_S)
+  dotc_interface(dotc_p1, dotc_trans1, (BLAS_D), dotc_p2, dotc_trans2,
+		 (BLAS_D),ddot_ ,BLAS_D)
+  dotc_interface(dotc_p1, dotc_trans1, (BLAS_C), dotc_p2, dotc_trans2,
+		 (BLAS_C),cdotc_,BLAS_C)
+  dotc_interface(dotc_p1, dotc_trans1, (BLAS_Z), dotc_p2, dotc_trans2,
+		 (BLAS_Z),zdotc_,BLAS_Z)
   
-  dotc_interface(dotc_p1_s, dotc_trans1_s, a*, dotc_p2, dotc_trans2, ,sdot_,
-		 BLAS_S)
-  dotc_interface(dotc_p1_s, dotc_trans1_s, a*, dotc_p2, dotc_trans2, ,ddot_ ,
-		 BLAS_D)
-  dotc_interface(dotc_p1_s, dotc_trans1_s, a*, dotc_p2, dotc_trans2, ,cdotc_,
-		 BLAS_C)
-  dotc_interface(dotc_p1_s, dotc_trans1_s, a*, dotc_p2, dotc_trans2, ,zdotc_,
-		 BLAS_Z)
+  dotc_interface(dotc_p1_s, dotc_trans1_s, a*, dotc_p2, dotc_trans2,
+		 (BLAS_S),sdot_, BLAS_S)
+  dotc_interface(dotc_p1_s, dotc_trans1_s, a*, dotc_p2, dotc_trans2,
+		 (BLAS_D),ddot_ , BLAS_D)
+  dotc_interface(dotc_p1_s, dotc_trans1_s, a*, dotc_p2, dotc_trans2,
+		 (BLAS_C),cdotc_, BLAS_C)
+  dotc_interface(dotc_p1_s, dotc_trans1_s, a*, dotc_p2, dotc_trans2,
+		 (BLAS_Z),zdotc_, BLAS_Z)
   
-  dotc_interface(dotc_p1, dotc_trans1, , dotc_p2_s, dotc_trans2_s, b*,sdot_ ,
-		 BLAS_S)
-  dotc_interface(dotc_p1, dotc_trans1, , dotc_p2_s, dotc_trans2_s, b*,ddot_ ,
-		 BLAS_D)
-  dotc_interface(dotc_p1, dotc_trans1, , dotc_p2_s, dotc_trans2_s, b*,cdotc_,
-		 BLAS_C)
-  dotc_interface(dotc_p1, dotc_trans1, , dotc_p2_s, dotc_trans2_s, b*,zdotc_,
-		 BLAS_Z)
+  dotc_interface(dotc_p1, dotc_trans1, (BLAS_S), dotc_p2_s, dotc_trans2_s,
+		 b*,sdot_ , BLAS_S)
+  dotc_interface(dotc_p1, dotc_trans1, (BLAS_D), dotc_p2_s, dotc_trans2_s,
+		 b*,ddot_ , BLAS_D)
+  dotc_interface(dotc_p1, dotc_trans1, (BLAS_C), dotc_p2_s, dotc_trans2_s,
+		 b*,cdotc_, BLAS_C)
+  dotc_interface(dotc_p1, dotc_trans1, (BLAS_Z), dotc_p2_s, dotc_trans2_s,
+		   b*,zdotc_, BLAS_Z)
 
   dotc_interface(dotc_p1_s,dotc_trans1_s,a*,dotc_p2_s,dotc_trans2_s,b*,sdot_ ,
 		 BLAS_S)
@@ -294,12 +336,101 @@ namespace gmm {
   /* ********************************************************************* */
   /* add(x, y).                                                            */
   /* ********************************************************************* */
+  template<size_type N, class V1, class V2>
+  inline void add_fixed(const V1 &x, V2 &y)
+  {
+    for(size_type i = 0; i != N; ++i) y[i] += x[i];
+  }
+
+  template<class V1, class V2>
+  inline void add_for_short_vectors(const V1 &x, V2 &y, size_type n)
+  {
+    switch(n)
+    {
+      case  1: add_fixed<1>(x, y);  break;
+      case  2: add_fixed<2>(x, y);  break;
+      case  3: add_fixed<3>(x, y);  break;
+      case  4: add_fixed<4>(x, y);  break;
+      case  5: add_fixed<5>(x, y);  break;
+      case  6: add_fixed<6>(x, y);  break;
+      case  7: add_fixed<7>(x, y);  break;
+      case  8: add_fixed<8>(x, y);  break;
+      case  9: add_fixed<9>(x, y);  break;
+      case 10: add_fixed<10>(x, y); break;
+      case 11: add_fixed<11>(x, y); break;
+      case 12: add_fixed<12>(x, y); break;
+      case 13: add_fixed<13>(x, y); break;
+      case 14: add_fixed<14>(x, y); break;
+      case 15: add_fixed<15>(x, y); break;
+      case 16: add_fixed<16>(x, y); break;
+      case 17: add_fixed<17>(x, y); break;
+      case 18: add_fixed<18>(x, y); break;
+      case 19: add_fixed<19>(x, y); break;
+      case 20: add_fixed<20>(x, y); break;
+      case 21: add_fixed<21>(x, y); break;
+      case 22: add_fixed<22>(x, y); break;
+      case 23: add_fixed<23>(x, y); break;
+      case 24: add_fixed<24>(x, y); break;
+      default: GMM_ASSERT2(false, "add_for_short_vectors used with unsupported size"); break;
+    }
+  }
+
+  template<size_type N, class V1, class V2, class T>
+  inline void add_fixed(const V1 &x, V2 &y, const T &a)
+  {
+    for(size_type i = 0; i != N; ++i) y[i] += a*x[i];
+  }
+
+  template<class V1, class V2, class T>
+  inline void add_for_short_vectors(const V1 &x, V2 &y, const T &a, size_type n)
+  {
+    switch(n)
+    {
+    case  1: add_fixed<1>(x, y, a);  break;
+      case  2: add_fixed<2>(x, y, a);  break;
+      case  3: add_fixed<3>(x, y, a);  break;
+      case  4: add_fixed<4>(x, y, a);  break;
+      case  5: add_fixed<5>(x, y, a);  break;
+      case  6: add_fixed<6>(x, y, a);  break;
+      case  7: add_fixed<7>(x, y, a);  break;
+      case  8: add_fixed<8>(x, y, a);  break;
+      case  9: add_fixed<9>(x, y, a);  break;
+      case 10: add_fixed<10>(x, y, a); break;
+      case 11: add_fixed<11>(x, y, a); break;
+      case 12: add_fixed<12>(x, y, a); break;
+      case 13: add_fixed<13>(x, y, a); break;
+      case 14: add_fixed<14>(x, y, a); break;
+      case 15: add_fixed<15>(x, y, a); break;
+      case 16: add_fixed<16>(x, y, a); break;
+      case 17: add_fixed<17>(x, y, a); break;
+      case 18: add_fixed<18>(x, y, a); break;
+      case 19: add_fixed<19>(x, y, a); break;
+      case 20: add_fixed<20>(x, y, a); break;
+      case 21: add_fixed<21>(x, y, a); break;
+      case 22: add_fixed<22>(x, y, a); break;
+      case 23: add_fixed<23>(x, y, a); break;
+      case 24: add_fixed<24>(x, y, a); break;
+      default: GMM_ASSERT2(false, "add_for_short_vectors used with unsupported size"); break;
+    }
+  }
+
 
 # define axpy_interface(param1, trans1, blas_name, base_type)              \
   inline void add(param1(base_type), std::vector<base_type > &y) {         \
     GMMLAPACK_TRACE("axpy_interface");                                     \
-    int inc(1), n(vect_size(y)); trans1(base_type);                        \
-    blas_name(&n, &a, &x[0], &inc, &y[0], &inc);                           \
+    BLAS_INT inc(1), n(BLAS_INT(vect_size(y))); trans1(base_type);         \
+    if(n == 0) return;                                                     \
+    else if(n < 25) add_for_short_vectors(x, y, n);                        \
+    else blas_name(&n, &a, &x[0], &inc, &y[0], &inc);                      \
+  }
+
+# define axpy2_interface(param1, trans1, blas_name, base_type)             \
+  inline void add(param1(base_type), std::vector<base_type > &y) {         \
+    GMMLAPACK_TRACE("axpy_interface");                                     \
+    BLAS_INT inc(1), n(BLAS_INT(vect_size(y))); trans1(base_type);         \
+    if(n == 0) return;                                                     \
+    else if(n < 25) add_for_short_vectors(x, y, a, n);                     \
+    else blas_name(&n, &a, &x[0], &inc, &y[0], &inc);                      \
   }
 
 # define axpy_p1(base_type) const std::vector<base_type > &x
@@ -316,10 +447,10 @@ namespace gmm {
   axpy_interface(axpy_p1, axpy_trans1, caxpy_, BLAS_C)
   axpy_interface(axpy_p1, axpy_trans1, zaxpy_, BLAS_Z)
   
-  axpy_interface(axpy_p1_s, axpy_trans1_s, saxpy_, BLAS_S)
-  axpy_interface(axpy_p1_s, axpy_trans1_s, daxpy_, BLAS_D)
-  axpy_interface(axpy_p1_s, axpy_trans1_s, caxpy_, BLAS_C)
-  axpy_interface(axpy_p1_s, axpy_trans1_s, zaxpy_, BLAS_Z)
+  axpy2_interface(axpy_p1_s, axpy_trans1_s, saxpy_, BLAS_S)
+  axpy2_interface(axpy_p1_s, axpy_trans1_s, daxpy_, BLAS_D)
+  axpy2_interface(axpy_p1_s, axpy_trans1_s, caxpy_, BLAS_C)
+  axpy2_interface(axpy_p1_s, axpy_trans1_s, zaxpy_, BLAS_Z)
   
 
   /* ********************************************************************* */
@@ -332,7 +463,8 @@ namespace gmm {
               std::vector<base_type > &z, orien) {                         \
     GMMLAPACK_TRACE("gemv_interface");                                     \
     trans1(base_type); trans2(base_type); base_type beta(1);               \
-    int m(mat_nrows(A)), lda(m), n(mat_ncols(A)), inc(1);                  \
+    BLAS_INT m(BLAS_INT(mat_nrows(A))), lda(m);                            \
+    BLAS_INT n(BLAS_INT(mat_ncols(A))), inc(1);                            \
     if (m && n) blas_name(&t, &m, &n, &alpha, &A(0,0), &lda, &x[0], &inc,  \
                           &beta, &z[0], &inc);                             \
     else gmm::clear(z);                                                    \
@@ -454,7 +586,8 @@ namespace gmm {
               std::vector<base_type > &z, orien) {                         \
     GMMLAPACK_TRACE("gemv_interface2");                                    \
     trans1(base_type); trans2(base_type); base_type beta(0);               \
-    int m(mat_nrows(A)), lda(m), n(mat_ncols(A)), inc(1);                  \
+    BLAS_INT m(BLAS_INT(mat_nrows(A))), lda(m);                            \
+    BLAS_INT n(BLAS_INT(mat_ncols(A))), inc(1);                            \
     if (m && n)                                                            \
       blas_name(&t, &m, &n, &alpha, &A(0,0), &lda, &x[0], &inc, &beta,     \
                 &z[0], &inc);                                              \
@@ -541,6 +674,66 @@ namespace gmm {
   gemv_interface2(gem_p1_c, gem_trans1_c, gemv_p2_s, gemv_trans2_s, zgemv_,
 		  BLAS_Z, row_major)
 
+
+  /* ********************************************************************* */
+  /* Rank one update.                                                      */
+  /* ********************************************************************* */
+
+# define ger_interface(blas_name, base_type)                               \
+  inline void rank_one_update(const dense_matrix<base_type > &A,           \
+			      const std::vector<base_type > &V,	   	   \
+			      const std::vector<base_type > &W) {	   \
+    GMMLAPACK_TRACE("ger_interface");                                      \
+    BLAS_INT m(BLAS_INT(mat_nrows(A))), lda = m;                           \
+    BLAS_INT n(BLAS_INT(mat_ncols(A)));                                    \
+    BLAS_INT incx = 1, incy = 1;                                           \
+    base_type alpha(1);                                                    \
+    if (m && n)								   \
+      blas_name(&m, &n, &alpha, &V[0], &incx, &W[0], &incy, &A(0,0), &lda);\
+  }
+
+  ger_interface(sger_, BLAS_S)
+  ger_interface(dger_, BLAS_D)
+  ger_interface(cgerc_, BLAS_C)
+  ger_interface(zgerc_, BLAS_Z)
+
+# define ger_interface_sn(blas_name, base_type)                            \
+  inline void rank_one_update(const dense_matrix<base_type > &A,	   \
+			      gemv_p2_s(base_type),			   \
+			      const std::vector<base_type > &W) {	   \
+    GMMLAPACK_TRACE("ger_interface");                                      \
+    gemv_trans2_s(base_type); 						   \
+    BLAS_INT m(BLAS_INT(mat_nrows(A))), lda = m;                           \
+    BLAS_INT n(BLAS_INT(mat_ncols(A)));                                    \
+    BLAS_INT incx = 1, incy = 1;                                           \
+    if (m && n)								   \
+      blas_name(&m, &n, &alpha, &x[0], &incx, &W[0], &incy, &A(0,0), &lda);\
+  }
+
+  ger_interface_sn(sger_, BLAS_S)
+  ger_interface_sn(dger_, BLAS_D)
+  ger_interface_sn(cgerc_, BLAS_C)
+  ger_interface_sn(zgerc_, BLAS_Z)
+
+# define ger_interface_ns(blas_name, base_type)                            \
+  inline void rank_one_update(const dense_matrix<base_type > &A,	   \
+			      const std::vector<base_type > &V,		   \
+			      gemv_p2_s(base_type)) {			   \
+    GMMLAPACK_TRACE("ger_interface");                                      \
+    gemv_trans2_s(base_type); 						   \
+    BLAS_INT m(BLAS_INT(mat_nrows(A))), lda = m;                           \
+    BLAS_INT n(BLAS_INT(mat_ncols(A)));                                    \
+    BLAS_INT incx = 1, incy = 1;                                           \
+    base_type al2 = gmm::conj(alpha);					   \
+    if (m && n)								   \
+      blas_name(&m, &n, &al2, &V[0], &incx, &x[0], &incy, &A(0,0), &lda);  \
+  }
+
+  ger_interface_ns(sger_, BLAS_S)
+  ger_interface_ns(dger_, BLAS_D)
+  ger_interface_ns(cgerc_, BLAS_C)
+  ger_interface_ns(zgerc_, BLAS_Z)
+
   /* ********************************************************************* */
   /* dense matrix x dense matrix multiplication.                           */
   /* ********************************************************************* */
@@ -551,8 +744,10 @@ namespace gmm {
             dense_matrix<base_type > &C, c_mult) {                         \
     GMMLAPACK_TRACE("gemm_interface_nn");                                  \
     const char t = 'N';                                                    \
-    int m = mat_nrows(A), lda = m, k = mat_ncols(A), n = mat_ncols(B);     \
-    int ldb = k, ldc = m;                                                  \
+    BLAS_INT m(BLAS_INT(mat_nrows(A))), lda = m;                           \
+    BLAS_INT k(BLAS_INT(mat_ncols(A)));                                    \
+    BLAS_INT n(BLAS_INT(mat_ncols(B)));                                    \
+    BLAS_INT ldb = k, ldc = m;                                             \
     base_type alpha(1), beta(0);                                           \
     if (m && k && n)                                                       \
       blas_name(&t, &t, &m, &n, &k, &alpha,                                \
@@ -571,15 +766,16 @@ namespace gmm {
 
 # define gemm_interface_tn(blas_name, base_type, is_const)                 \
   inline void mult_spec(                                                   \
-         const transposed_col_ref<is_const dense_matrix<base_type > *> &A_,\
+         const transposed_col_ref<is_const<base_type > *> &A_,\
          const dense_matrix<base_type > &B,                                \
          dense_matrix<base_type > &C, rcmult) {                            \
     GMMLAPACK_TRACE("gemm_interface_tn");                                  \
     dense_matrix<base_type > &A                                            \
          = const_cast<dense_matrix<base_type > &>(*(linalg_origin(A_)));   \
     const char t = 'T', u = 'N';                                           \
-    int m = mat_ncols(A), k = mat_nrows(A), n = mat_ncols(B), lda = k;     \
-    int ldb = k, ldc = m;                                                  \
+    BLAS_INT m(BLAS_INT(mat_ncols(A))), k(BLAS_INT(mat_nrows(A)));         \
+    BLAS_INT n(BLAS_INT(mat_ncols(B)));                                    \
+    BLAS_INT lda = k, ldb = k, ldc = m;                                    \
     base_type alpha(1), beta(0);                                           \
     if (m && k && n)                                                       \
       blas_name(&t, &u, &m, &n, &k, &alpha,                                \
@@ -587,14 +783,14 @@ namespace gmm {
     else gmm::clear(C);                                                    \
   }
 
-  gemm_interface_tn(sgemm_, BLAS_S,)
-  gemm_interface_tn(dgemm_, BLAS_D,)
-  gemm_interface_tn(cgemm_, BLAS_C,)
-  gemm_interface_tn(zgemm_, BLAS_Z,)
-  gemm_interface_tn(sgemm_, BLAS_S, const)
-  gemm_interface_tn(dgemm_, BLAS_D, const)
-  gemm_interface_tn(cgemm_, BLAS_C, const)
-  gemm_interface_tn(zgemm_, BLAS_Z, const)
+  gemm_interface_tn(sgemm_, BLAS_S, dense_matrix)
+  gemm_interface_tn(dgemm_, BLAS_D, dense_matrix)
+  gemm_interface_tn(cgemm_, BLAS_C, dense_matrix)
+  gemm_interface_tn(zgemm_, BLAS_Z, dense_matrix)
+  gemm_interface_tn(sgemm_, BLAS_S, const dense_matrix)
+  gemm_interface_tn(dgemm_, BLAS_D, const dense_matrix)
+  gemm_interface_tn(cgemm_, BLAS_C, const dense_matrix)
+  gemm_interface_tn(zgemm_, BLAS_Z, const dense_matrix)
 
   /* ********************************************************************* */
   /* dense matrix x transposed(dense matrix) multiplication.               */
@@ -602,14 +798,16 @@ namespace gmm {
 
 # define gemm_interface_nt(blas_name, base_type, is_const)                 \
   inline void mult_spec(const dense_matrix<base_type > &A,                 \
-         const transposed_col_ref<is_const dense_matrix<base_type > *> &B_,\
+		     const transposed_col_ref<is_const<base_type > *> &B_, \
          dense_matrix<base_type > &C, r_mult) {                            \
     GMMLAPACK_TRACE("gemm_interface_nt");                                  \
     dense_matrix<base_type > &B                                            \
         = const_cast<dense_matrix<base_type > &>(*(linalg_origin(B_)));    \
     const char t = 'N', u = 'T';                                           \
-    int m = mat_nrows(A), lda = m, k = mat_ncols(A), n = mat_nrows(B);     \
-    int ldb = n, ldc = m;                                                  \
+    BLAS_INT m(BLAS_INT(mat_nrows(A))), lda = m;                           \
+    BLAS_INT k(BLAS_INT(mat_ncols(A)));                                    \
+    BLAS_INT n(BLAS_INT(mat_nrows(B)));                                    \
+    BLAS_INT ldb = n, ldc = m;                                             \
     base_type alpha(1), beta(0);                                           \
     if (m && k && n)                                                       \
       blas_name(&t, &u, &m, &n, &k, &alpha,                                \
@@ -617,14 +815,14 @@ namespace gmm {
     else gmm::clear(C);                                                    \
   }
 
-  gemm_interface_nt(sgemm_, BLAS_S,)
-  gemm_interface_nt(dgemm_, BLAS_D,)
-  gemm_interface_nt(cgemm_, BLAS_C,)
-  gemm_interface_nt(zgemm_, BLAS_Z,)
-  gemm_interface_nt(sgemm_, BLAS_S, const)
-  gemm_interface_nt(dgemm_, BLAS_D, const)
-  gemm_interface_nt(cgemm_, BLAS_C, const)
-  gemm_interface_nt(zgemm_, BLAS_Z, const)
+  gemm_interface_nt(sgemm_, BLAS_S, dense_matrix)
+  gemm_interface_nt(dgemm_, BLAS_D, dense_matrix)
+  gemm_interface_nt(cgemm_, BLAS_C, dense_matrix)
+  gemm_interface_nt(zgemm_, BLAS_Z, dense_matrix)
+  gemm_interface_nt(sgemm_, BLAS_S, const dense_matrix)
+  gemm_interface_nt(dgemm_, BLAS_D, const dense_matrix)
+  gemm_interface_nt(cgemm_, BLAS_C, const dense_matrix)
+  gemm_interface_nt(zgemm_, BLAS_Z, const dense_matrix)
 
   /* ********************************************************************* */
   /* transposed(dense matrix) x transposed(dense matrix) multiplication.   */
@@ -632,17 +830,18 @@ namespace gmm {
 
 # define gemm_interface_tt(blas_name, base_type, isA_const, isB_const)     \
   inline void mult_spec(                                                   \
-        const transposed_col_ref<isA_const dense_matrix<base_type > *> &A_,\
-        const transposed_col_ref<isB_const dense_matrix<base_type > *> &B_,\
-        dense_matrix<base_type > &C, r_mult) {                             \
+	       const transposed_col_ref<isA_const <base_type > *> &A_,	   \
+               const transposed_col_ref<isB_const <base_type > *> &B_,	   \
+	       dense_matrix<base_type > &C, r_mult) {			   \
     GMMLAPACK_TRACE("gemm_interface_tt");                                  \
     dense_matrix<base_type > &A                                            \
         = const_cast<dense_matrix<base_type > &>(*(linalg_origin(A_)));    \
     dense_matrix<base_type > &B                                            \
         = const_cast<dense_matrix<base_type > &>(*(linalg_origin(B_)));    \
     const char t = 'T', u = 'T';                                           \
-    int m = mat_ncols(A), k = mat_nrows(A), n = mat_nrows(B), lda = k;     \
-    int ldb = n, ldc = m;                                                  \
+    BLAS_INT m(BLAS_INT(mat_ncols(A))), k(BLAS_INT(mat_nrows(A)));         \
+    BLAS_INT n(BLAS_INT(mat_nrows(B)));                                    \
+    BLAS_INT lda = k, ldb = n, ldc = m;					   \
     base_type alpha(1), beta(0);                                           \
     if (m && k && n)                                                       \
       blas_name(&t, &u, &m, &n, &k, &alpha,                                \
@@ -650,22 +849,22 @@ namespace gmm {
     else gmm::clear(C);                                                    \
   }
 
-  gemm_interface_tt(sgemm_, BLAS_S,,)
-  gemm_interface_tt(dgemm_, BLAS_D,,)
-  gemm_interface_tt(cgemm_, BLAS_C,,)
-  gemm_interface_tt(zgemm_, BLAS_Z,,)
-  gemm_interface_tt(sgemm_, BLAS_S, const,)
-  gemm_interface_tt(dgemm_, BLAS_D, const,)
-  gemm_interface_tt(cgemm_, BLAS_C, const,)
-  gemm_interface_tt(zgemm_, BLAS_Z, const,)
-  gemm_interface_tt(sgemm_, BLAS_S,, const)
-  gemm_interface_tt(dgemm_, BLAS_D,, const)
-  gemm_interface_tt(cgemm_, BLAS_C,, const)
-  gemm_interface_tt(zgemm_, BLAS_Z,, const)
-  gemm_interface_tt(sgemm_, BLAS_S, const, const)
-  gemm_interface_tt(dgemm_, BLAS_D, const, const)
-  gemm_interface_tt(cgemm_, BLAS_C, const, const)
-  gemm_interface_tt(zgemm_, BLAS_Z, const, const)
+  gemm_interface_tt(sgemm_, BLAS_S, dense_matrix, dense_matrix)
+  gemm_interface_tt(dgemm_, BLAS_D, dense_matrix, dense_matrix)
+  gemm_interface_tt(cgemm_, BLAS_C, dense_matrix, dense_matrix)
+  gemm_interface_tt(zgemm_, BLAS_Z, dense_matrix, dense_matrix)
+  gemm_interface_tt(sgemm_, BLAS_S, const dense_matrix, dense_matrix)
+  gemm_interface_tt(dgemm_, BLAS_D, const dense_matrix, dense_matrix)
+  gemm_interface_tt(cgemm_, BLAS_C, const dense_matrix, dense_matrix)
+  gemm_interface_tt(zgemm_, BLAS_Z, const dense_matrix, dense_matrix)
+  gemm_interface_tt(sgemm_, BLAS_S, dense_matrix, const dense_matrix)
+  gemm_interface_tt(dgemm_, BLAS_D, dense_matrix, const dense_matrix)
+  gemm_interface_tt(cgemm_, BLAS_C, dense_matrix, const dense_matrix)
+  gemm_interface_tt(zgemm_, BLAS_Z, dense_matrix, const dense_matrix)
+  gemm_interface_tt(sgemm_, BLAS_S, const dense_matrix, const dense_matrix)
+  gemm_interface_tt(dgemm_, BLAS_D, const dense_matrix, const dense_matrix)
+  gemm_interface_tt(cgemm_, BLAS_C, const dense_matrix, const dense_matrix)
+  gemm_interface_tt(zgemm_, BLAS_Z, const dense_matrix, const dense_matrix)
 
 
   /* ********************************************************************* */
@@ -681,8 +880,9 @@ namespace gmm {
     dense_matrix<base_type > &A                                            \
           = const_cast<dense_matrix<base_type > &>(*(linalg_origin(A_)));  \
     const char t = 'C', u = 'N';                                           \
-    int m = mat_ncols(A), k = mat_nrows(A), n = mat_ncols(B), lda = k;     \
-    int ldb = k, ldc = m;                                                  \
+    BLAS_INT m(BLAS_INT(mat_ncols(A))), k(BLAS_INT(mat_nrows(A)));         \
+    BLAS_INT n(BLAS_INT(mat_ncols(B)));                                    \
+    BLAS_INT lda = k, ldb = k, ldc = m;					   \
     base_type alpha(1), beta(0);                                           \
     if (m && k && n)                                                       \
       blas_name(&t, &u, &m, &n, &k, &alpha,                                \
@@ -707,8 +907,9 @@ namespace gmm {
     dense_matrix<base_type > &B                                            \
          = const_cast<dense_matrix<base_type > &>(*(linalg_origin(B_)));   \
     const char t = 'N', u = 'C';                                           \
-    int m = mat_nrows(A), lda = m, k = mat_ncols(A), n = mat_nrows(B);     \
-    int ldb = n, ldc = m;                                                  \
+    BLAS_INT m(BLAS_INT(mat_nrows(A))), lda = m;                           \
+    BLAS_INT k(BLAS_INT(mat_ncols(A)));                                    \
+    BLAS_INT n(BLAS_INT(mat_nrows(B))), ldb = n, ldc = m;                  \
     base_type alpha(1), beta(0);                                           \
     if (m && k && n)                                                       \
       blas_name(&t, &u, &m, &n, &k, &alpha,                                \
@@ -736,8 +937,8 @@ namespace gmm {
     dense_matrix<base_type > &B                                            \
         = const_cast<dense_matrix<base_type > &>(*(linalg_origin(B_)));    \
     const char t = 'C', u = 'C';                                           \
-    int m = mat_ncols(A), k = mat_nrows(A), lda = k, n = mat_nrows(B);     \
-    int ldb = n, ldc = m;                                                  \
+    BLAS_INT m(BLAS_INT(mat_ncols(A))), k(BLAS_INT(mat_nrows(A)));         \
+    BLAS_INT lda = k, n(BLAS_INT(mat_nrows(B))), ldb = n, ldc = m;         \
     base_type alpha(1), beta(0);                                           \
     if (m && k && n)                                                       \
       blas_name(&t, &u, &m, &n, &k, &alpha,                                \
@@ -759,7 +960,7 @@ namespace gmm {
                               size_type k, bool is_unit) {                 \
     GMMLAPACK_TRACE("trsv_interface");                                     \
     loru; trans1(base_type); char d = is_unit ? 'U' : 'N';                 \
-    int lda(mat_nrows(A)), inc(1), n(k);                                   \
+    BLAS_INT lda(BLAS_INT(mat_nrows(A))), inc(1), n = BLAS_INT(k);         \
     if (lda) blas_name(&l, &t, &d, &n, &A(0,0), &lda, &x[0], &inc);        \
   }
 
@@ -846,6 +1047,7 @@ namespace gmm {
   trsv_interface(upper_tri_solve, trsv_lower, gem_p1_c, gem_trans1_c,
 		 ztrsv_, BLAS_Z)
   
+#endif
 }
 
 #endif // GMM_BLAS_INTERFACE_H
diff --git a/contrib/gmm/gmm_condition_number.h b/contrib/gmm/gmm_condition_number.h
index 4b9f2506cf..d5b9738673 100644
--- a/contrib/gmm/gmm_condition_number.h
+++ b/contrib/gmm/gmm_condition_number.h
@@ -1,32 +1,33 @@
-// -*- c++ -*- (enables emacs c++ mode)
-//===========================================================================
-//
-// Copyright (C) 2003-2008 Yves Renard
-//
-// This file is a part of GETFEM++
-//
-// Getfem++  is  free software;  you  can  redistribute  it  and/or modify it
-// under  the  terms  of the  GNU  Lesser General Public License as published
-// by  the  Free Software Foundation;  either version 2.1 of the License,  or
-// (at your option) any later version.
-// This program  is  distributed  in  the  hope  that it will be useful,  but
-// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-// or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
-// License for more details.
-// You  should  have received a copy of the GNU Lesser General Public License
-// along  with  this program;  if not, write to the Free Software Foundation,
-// Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
-//
-// As a special exception, you may use this file as part of a free software
-// library without restriction.  Specifically, if other files instantiate
-// templates or use macros or inline functions from this file, or you compile
-// this file and link it with other files to produce an executable, this
-// file does not by itself cause the resulting executable to be covered by
-// the GNU General Public License.  This exception does not however
-// invalidate any other reasons why the executable file might be covered by
-// the GNU General Public License.
-//
-//===========================================================================
+/* -*- c++ -*- (enables emacs c++ mode) */
+/*===========================================================================
+
+ Copyright (C) 2003-2020 Yves Renard, Julien Pommier
+
+ This file is a part of GetFEM
+
+ GetFEM  is  free software;  you  can  redistribute  it  and/or modify it
+ under  the  terms  of the  GNU  Lesser General Public License as published
+ by  the  Free Software Foundation;  either version 3 of the License,  or
+ (at your option) any later version along with the GCC Runtime Library
+ Exception either version 3.1 or (at your option) any later version.
+ This program  is  distributed  in  the  hope  that it will be useful,  but
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+ License and GCC Runtime Library Exception for more details.
+ You  should  have received a copy of the GNU Lesser General Public License
+ along  with  this program;  if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+
+ As a special exception, you  may use  this file  as it is a part of a free
+ software  library  without  restriction.  Specifically,  if   other  files
+ instantiate  templates  or  use macros or inline functions from this file,
+ or  you compile this  file  and  link  it  with other files  to produce an
+ executable, this file  does  not  by itself cause the resulting executable
+ to be covered  by the GNU Lesser General Public License.  This   exception
+ does not  however  invalidate  any  other  reasons why the executable file
+ might be covered by the GNU Lesser General Public License.
+
+===========================================================================*/
 
 /**@file gmm_condition_number.h
    @author  Yves Renard <Yves.Renard@insa-lyon.fr>, Julien Pommier <Julien.Pommier@insa-toulouse.fr>
@@ -59,6 +60,10 @@ namespace gmm {
     typedef typename linalg_traits<MAT>::value_type T;
     typedef typename number_traits<T>::magnitude_type R;
 
+    // Added because of errors in complex with zero det
+    if (sizeof(T) != sizeof(R) && gmm::abs(gmm::lu_det(M)) == R(0))
+      return  gmm::default_max(R());
+      
     size_type m = mat_nrows(M), n = mat_ncols(M);
     emax = emin = R(0);
     std::vector<R> eig(m+n);
diff --git a/contrib/gmm/gmm_conjugated.h b/contrib/gmm/gmm_conjugated.h
index 2f18837743..2ff8ad1980 100644
--- a/contrib/gmm/gmm_conjugated.h
+++ b/contrib/gmm/gmm_conjugated.h
@@ -1,32 +1,33 @@
-// -*- c++ -*- (enables emacs c++ mode)
-//===========================================================================
-//
-// Copyright (C) 2003-2008 Yves Renard
-//
-// This file is a part of GETFEM++
-//
-// Getfem++  is  free software;  you  can  redistribute  it  and/or modify it
-// under  the  terms  of the  GNU  Lesser General Public License as published
-// by  the  Free Software Foundation;  either version 2.1 of the License,  or
-// (at your option) any later version.
-// This program  is  distributed  in  the  hope  that it will be useful,  but
-// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-// or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
-// License for more details.
-// You  should  have received a copy of the GNU Lesser General Public License
-// along  with  this program;  if not, write to the Free Software Foundation,
-// Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
-//
-// As a special exception, you may use this file as part of a free software
-// library without restriction.  Specifically, if other files instantiate
-// templates or use macros or inline functions from this file, or you compile
-// this file and link it with other files to produce an executable, this
-// file does not by itself cause the resulting executable to be covered by
-// the GNU General Public License.  This exception does not however
-// invalidate any other reasons why the executable file might be covered by
-// the GNU General Public License.
-//
-//===========================================================================
+/* -*- c++ -*- (enables emacs c++ mode) */
+/*===========================================================================
+
+ Copyright (C) 2003-2020 Yves Renard
+
+ This file is a part of GetFEM
+
+ GetFEM  is  free software;  you  can  redistribute  it  and/or modify it
+ under  the  terms  of the  GNU  Lesser General Public License as published
+ by  the  Free Software Foundation;  either version 3 of the License,  or
+ (at your option) any later version along with the GCC Runtime Library
+ Exception either version 3.1 or (at your option) any later version.
+ This program  is  distributed  in  the  hope  that it will be useful,  but
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+ License and GCC Runtime Library Exception for more details.
+ You  should  have received a copy of the GNU Lesser General Public License
+ along  with  this program;  if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+
+ As a special exception, you  may use  this file  as it is a part of a free
+ software  library  without  restriction.  Specifically,  if   other  files
+ instantiate  templates  or  use macros or inline functions from this file,
+ or  you compile this  file  and  link  it  with other files  to produce an
+ executable, this file  does  not  by itself cause the resulting executable
+ to be covered  by the GNU Lesser General Public License.  This   exception
+ does not  however  invalidate  any  other  reasons why the executable file
+ might be covered by the GNU Lesser General Public License.
+
+===========================================================================*/
 
 /**@file gmm_conjugated.h
    @author  Yves Renard <Yves.Renard@insa-lyon.fr>
@@ -194,40 +195,6 @@ namespace gmm {
     { return gmm::conj(linalg_traits<M>::access(begin_+j, i)); }
   };
 
-  template <typename M>
-  struct linalg_traits<conjugated_row_matrix_const_ref<M> > {
-    typedef conjugated_row_matrix_const_ref<M> this_type;
-    typedef typename linalg_traits<M>::origin_type origin_type;
-    typedef linalg_const is_reference;
-    typedef abstract_matrix linalg_type;
-    typedef typename linalg_traits<M>::value_type value_type;
-    typedef value_type reference;
-    typedef typename linalg_traits<M>::storage_type storage_type;
-    typedef typename linalg_traits<M>::const_sub_row_type vector_type;
-    typedef conjugated_vector_const_ref<vector_type> sub_col_type;
-    typedef conjugated_vector_const_ref<vector_type> const_sub_col_type;
-    typedef conjugated_row_const_iterator<M> col_iterator;
-    typedef conjugated_row_const_iterator<M> const_col_iterator;
-    typedef abstract_null_type const_sub_row_type;
-    typedef abstract_null_type sub_row_type;
-    typedef abstract_null_type const_row_iterator;
-    typedef abstract_null_type row_iterator;
-    typedef col_major sub_orientation;
-    typedef typename linalg_traits<M>::index_sorted index_sorted;
-    static inline size_type ncols(const this_type &m) { return m.nc; }
-    static inline size_type nrows(const this_type &m) { return m.nr; }
-    static inline const_sub_col_type col(const const_col_iterator &it)
-    { return conjugated(linalg_traits<M>::row(it.it)); }
-    static inline const_col_iterator col_begin(const this_type &m)
-    { return const_col_iterator(m.begin_); }
-    static inline const_col_iterator col_end(const this_type &m)
-    { return const_col_iterator(m.end_); }
-    static inline const origin_type* origin(const this_type &m)
-    { return m.origin; }
-    static value_type access(const const_col_iterator &it, size_type i)
-    { return gmm::conj(linalg_traits<M>::access(it.it, i)); }
-  };
-
   template<typename M> std::ostream &operator <<
   (std::ostream &o, const conjugated_row_matrix_const_ref<M>& m)
   { gmm::write(o,m); return o; }
@@ -286,39 +253,7 @@ namespace gmm {
     { return gmm::conj(linalg_traits<M>::access(begin_+i, j)); }
   };
 
-  template <typename M>
-  struct linalg_traits<conjugated_col_matrix_const_ref<M> > {
-    typedef conjugated_col_matrix_const_ref<M> this_type;
-    typedef typename linalg_traits<M>::origin_type origin_type;
-    typedef linalg_const is_reference;
-    typedef abstract_matrix linalg_type;
-    typedef typename linalg_traits<M>::value_type value_type;
-    typedef value_type reference;
-    typedef typename linalg_traits<M>::storage_type storage_type;
-    typedef typename linalg_traits<M>::const_sub_col_type vector_type;
-    typedef conjugated_vector_const_ref<vector_type> sub_row_type;
-    typedef conjugated_vector_const_ref<vector_type> const_sub_row_type;
-    typedef conjugated_col_const_iterator<M> row_iterator;
-    typedef conjugated_col_const_iterator<M> const_row_iterator;
-    typedef abstract_null_type const_sub_col_type;
-    typedef abstract_null_type sub_col_type;
-    typedef abstract_null_type const_col_iterator;
-    typedef abstract_null_type col_iterator;
-    typedef row_major sub_orientation;
-    typedef typename linalg_traits<M>::index_sorted index_sorted;
-    static inline size_type nrows(const this_type &m) { return m.nr; }
-    static inline size_type ncols(const this_type &m) { return m.nc; }
-    static inline const_sub_row_type row(const const_row_iterator &it)
-    { return conjugated(linalg_traits<M>::col(it.it)); }
-    static inline const_row_iterator row_begin(const this_type &m)
-    { return const_row_iterator(m.begin_); }
-    static inline const_row_iterator row_end(const this_type &m)
-    { return const_row_iterator(m.end_); }
-    static inline const origin_type* origin(const this_type &m)
-    { return m.origin; }
-    static value_type access(const const_row_iterator &it, size_type i)
-    { return gmm::conj(linalg_traits<M>::access(it.it, i)); }
-  };
+
 
   template<typename M> std::ostream &operator <<
   (std::ostream &o, const conjugated_col_matrix_const_ref<M>& m)
@@ -386,6 +321,74 @@ namespace gmm {
   template <typename L> inline
   conjugated_col_matrix_const_ref<L> conjugated(const L &v, col_major)
   { return conjugated_col_matrix_const_ref<L>(v); }
+
+  template <typename M>
+  struct linalg_traits<conjugated_row_matrix_const_ref<M> > {
+    typedef conjugated_row_matrix_const_ref<M> this_type;
+    typedef typename linalg_traits<M>::origin_type origin_type;
+    typedef linalg_const is_reference;
+    typedef abstract_matrix linalg_type;
+    typedef typename linalg_traits<M>::value_type value_type;
+    typedef value_type reference;
+    typedef typename linalg_traits<M>::storage_type storage_type;
+    typedef typename org_type<typename linalg_traits<M>::const_sub_row_type>::t vector_type;
+    typedef conjugated_vector_const_ref<vector_type> sub_col_type;
+    typedef conjugated_vector_const_ref<vector_type> const_sub_col_type;
+    typedef conjugated_row_const_iterator<M> col_iterator;
+    typedef conjugated_row_const_iterator<M> const_col_iterator;
+    typedef abstract_null_type const_sub_row_type;
+    typedef abstract_null_type sub_row_type;
+    typedef abstract_null_type const_row_iterator;
+    typedef abstract_null_type row_iterator;
+    typedef col_major sub_orientation;
+    typedef typename linalg_traits<M>::index_sorted index_sorted;
+    static inline size_type ncols(const this_type &m) { return m.nc; }
+    static inline size_type nrows(const this_type &m) { return m.nr; }
+    static inline const_sub_col_type col(const const_col_iterator &it)
+    { return conjugated(linalg_traits<M>::row(it.it)); }
+    static inline const_col_iterator col_begin(const this_type &m)
+    { return const_col_iterator(m.begin_); }
+    static inline const_col_iterator col_end(const this_type &m)
+    { return const_col_iterator(m.end_); }
+    static inline const origin_type* origin(const this_type &m)
+    { return m.origin; }
+    static value_type access(const const_col_iterator &it, size_type i)
+    { return gmm::conj(linalg_traits<M>::access(it.it, i)); }
+  };
+  
+  template <typename M>
+  struct linalg_traits<conjugated_col_matrix_const_ref<M> > {
+    typedef conjugated_col_matrix_const_ref<M> this_type;
+    typedef typename linalg_traits<M>::origin_type origin_type;
+    typedef linalg_const is_reference;
+    typedef abstract_matrix linalg_type;
+    typedef typename linalg_traits<M>::value_type value_type;
+    typedef value_type reference;
+    typedef typename linalg_traits<M>::storage_type storage_type;
+    typedef typename org_type<typename linalg_traits<M>::const_sub_col_type>::t vector_type;
+    typedef conjugated_vector_const_ref<vector_type> sub_row_type;
+    typedef conjugated_vector_const_ref<vector_type> const_sub_row_type;
+    typedef conjugated_col_const_iterator<M> row_iterator;
+    typedef conjugated_col_const_iterator<M> const_row_iterator;
+    typedef abstract_null_type const_sub_col_type;
+    typedef abstract_null_type sub_col_type;
+    typedef abstract_null_type const_col_iterator;
+    typedef abstract_null_type col_iterator;
+    typedef row_major sub_orientation;
+    typedef typename linalg_traits<M>::index_sorted index_sorted;
+    static inline size_type nrows(const this_type &m) { return m.nr; }
+    static inline size_type ncols(const this_type &m) { return m.nc; }
+    static inline const_sub_row_type row(const const_row_iterator &it)
+    { return conjugated(linalg_traits<M>::col(it.it)); }
+    static inline const_row_iterator row_begin(const this_type &m)
+    { return const_row_iterator(m.begin_); }
+    static inline const_row_iterator row_end(const this_type &m)
+    { return const_row_iterator(m.end_); }
+    static inline const origin_type* origin(const this_type &m)
+    { return m.origin; }
+    static value_type access(const const_row_iterator &it, size_type i)
+    { return gmm::conj(linalg_traits<M>::access(it.it, i)); }
+  };
   
   ///@endcond
   
diff --git a/contrib/gmm/gmm_def.h b/contrib/gmm/gmm_def.h
index e71e33d1a5..25468c7880 100644
--- a/contrib/gmm/gmm_def.h
+++ b/contrib/gmm/gmm_def.h
@@ -1,32 +1,33 @@
-// -*- c++ -*- (enables emacs c++ mode)
-//===========================================================================
-//
-// Copyright (C) 2002-2008 Yves Renard
-//
-// This file is a part of GETFEM++
-//
-// Getfem++  is  free software;  you  can  redistribute  it  and/or modify it
-// under  the  terms  of the  GNU  Lesser General Public License as published
-// by  the  Free Software Foundation;  either version 2.1 of the License,  or
-// (at your option) any later version.
-// This program  is  distributed  in  the  hope  that it will be useful,  but
-// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-// or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
-// License for more details.
-// You  should  have received a copy of the GNU Lesser General Public License
-// along  with  this program;  if not, write to the Free Software Foundation,
-// Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
-//
-// As a special exception, you may use this file as part of a free software
-// library without restriction.  Specifically, if other files instantiate
-// templates or use macros or inline functions from this file, or you compile
-// this file and link it with other files to produce an executable, this
-// file does not by itself cause the resulting executable to be covered by
-// the GNU General Public License.  This exception does not however
-// invalidate any other reasons why the executable file might be covered by
-// the GNU General Public License.
-//
-//===========================================================================
+/* -*- c++ -*- (enables emacs c++ mode) */
+/*===========================================================================
+
+ Copyright (C) 2002-2020 Yves Renard
+
+ This file is a part of GetFEM
+
+ GetFEM  is  free software;  you  can  redistribute  it  and/or modify it
+ under  the  terms  of the  GNU  Lesser General Public License as published
+ by  the  Free Software Foundation;  either version 3 of the License,  or
+ (at your option) any later version along with the GCC Runtime Library
+ Exception either version 3.1 or (at your option) any later version.
+ This program  is  distributed  in  the  hope  that it will be useful,  but
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+ License and GCC Runtime Library Exception for more details.
+ You  should  have received a copy of the GNU Lesser General Public License
+ along  with  this program;  if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+
+ As a special exception, you  may use  this file  as it is a part of a free
+ software  library  without  restriction.  Specifically,  if   other  files
+ instantiate  templates  or  use macros or inline functions from this file,
+ or  you compile this  file  and  link  it  with other files  to produce an
+ executable, this file  does  not  by itself cause the resulting executable
+ to be covered  by the GNU Lesser General Public License.  This   exception
+ does not  however  invalidate  any  other  reasons why the executable file
+ might be covered by the GNU Lesser General Public License.
+
+===========================================================================*/
 
 /**@file gmm_def.h
    @author  Yves Renard <Yves.Renard@insa-lyon.fr>
@@ -220,23 +221,33 @@ namespace gmm {
   };
 
   /* ******************************************************************** */
-  /*  types to deal with const object representing a modifiable reference */
+  /* Original type from a pointer or a reference.                         */
+  /* ******************************************************************** */
+
+  template <typename V> struct org_type            { typedef V t; };
+  template <typename V> struct org_type<V *>       { typedef V t; };
+  template <typename V> struct org_type<const V *> { typedef V t; };
+  template <typename V> struct org_type<V &>       { typedef V t; };
+  template <typename V> struct org_type<const V &> { typedef V t; };
+
+  /* ******************************************************************** */
+  /*  Types to deal with const object representing a modifiable reference */
   /* ******************************************************************** */
   
   template <typename PT, typename R> struct mref_type_ 
   { typedef abstract_null_type return_type; };
   template <typename L, typename R> struct mref_type_<L *, R>
-  { typedef L & return_type; };
+  { typedef typename org_type<L>::t & return_type; };
   template <typename L, typename R> struct mref_type_<const L *, R>
-  { typedef const L & return_type; };
+  { typedef const typename org_type<L>::t & return_type; };
   template <typename L> struct mref_type_<L *, linalg_const>
-  { typedef const L & return_type; };
+  { typedef const typename org_type<L>::t & return_type; };
   template <typename L> struct mref_type_<const L *, linalg_const>
-  { typedef const L & return_type; };
+  { typedef const typename org_type<L>::t & return_type; };
   template <typename L> struct mref_type_<const L *, linalg_modifiable>
-  { typedef L & return_type; };
+  { typedef typename org_type<L>::t & return_type; };
   template <typename L> struct mref_type_<L *, linalg_modifiable>
-  { typedef L & return_type; };
+  { typedef typename org_type<L>::t & return_type; };
 
   template <typename PT> struct mref_type {
     typedef typename std::iterator_traits<PT>::value_type L;
@@ -254,7 +265,7 @@ namespace gmm {
   template <typename L, typename R> struct cref_type_
   { typedef abstract_null_type return_type; };
   template <typename L> struct cref_type_<L, linalg_modifiable>
-  { typedef L & return_type; };
+  { typedef typename org_type<L>::t & return_type; };
   template <typename L> struct cref_type {
     typedef typename cref_type_<L, 
       typename linalg_traits<L>::is_reference>::return_type return_type;
@@ -349,23 +360,24 @@ namespace gmm {
   /*		Operations on scalars                         		  */
   /* ******************************************************************** */
 
-  template <typename T> inline T sqr(T a) { return a * a; }
+  template <typename T> inline T sqr(T a) { return T(a * a); }
   template <typename T> inline T abs(T a) { return (a < T(0)) ? T(-a) : a; }
   template <typename T> inline T abs(std::complex<T> a)
-  { T x = a.real(), y = a.imag(); return ::sqrt(x*x+y*y); }
-  template <typename T> inline T abs_sqr(T a) { return a*a; }
+  { T x = a.real(), y = a.imag(); return T(::sqrt(x*x+y*y)); }
+  template <typename T> inline T abs_sqr(T a) { return T(a*a); }
   template <typename T> inline T abs_sqr(std::complex<T> a)
   { return gmm::sqr(a.real()) + gmm::sqr(a.imag()); }
   template <typename T> inline T pos(T a) { return (a < T(0)) ? T(0) : a; }
   template <typename T> inline T neg(T a) { return (a < T(0)) ? T(-a) : T(0); }
   template <typename T> inline T sgn(T a) { return (a < T(0)) ? T(-1) : T(1); }
+  template <typename T> inline T Heaviside(T a) { return (a < T(0)) ? T(0) : T(1); }
   inline double random() { return double(rand())/(RAND_MAX+0.5); }
   template <typename T> inline T random(T)
   { return T(rand()*2.0)/(T(RAND_MAX)+T(1)/T(2)) - T(1); }
   template <typename T> inline std::complex<T> random(std::complex<T>)
   { return std::complex<T>(gmm::random(T()), gmm::random(T())); }
   template <typename T> inline T irandom(T max)
-  { return T(gmm::random() * max); }
+  { return T(gmm::random() * double(max)); }
   template <typename T> inline T conj(T a) { return a; }
   template <typename T> inline std::complex<T> conj(std::complex<T> a)
   { return std::conj(a); }
@@ -373,14 +385,14 @@ namespace gmm {
   template <typename T> inline T real(std::complex<T> a) { return a.real(); }
   template <typename T> inline T imag(T ) { return T(0); }
   template <typename T> inline T imag(std::complex<T> a) { return a.imag(); }  
-  template <typename T> inline T sqrt(T a) { return ::sqrt(a); }
+  template <typename T> inline T sqrt(T a) { return T(::sqrt(a)); }
   template <typename T> inline std::complex<T> sqrt(std::complex<T> a) {
     T x = a.real(), y = a.imag();
     if (x == T(0)) {
-      T t = ::sqrt(gmm::abs(y) / T(2));
+      T t = T(::sqrt(gmm::abs(y) / T(2)));
       return std::complex<T>(t, y < T(0) ? -t : t);
     }
-    T t = ::sqrt(T(2) * (gmm::abs(a) + gmm::abs(x))), u = t / T(2);
+    T t = T(::sqrt(T(2) * (gmm::abs(a) + gmm::abs(x)))), u = t / T(2);
     return x > T(0) ? std::complex<T>(u, y / t)
       : std::complex<T>(gmm::abs(y) / t, y < T(0) ? -u : u);
   }
@@ -407,13 +419,6 @@ namespace gmm {
 # define magnitude_of_linalg(M) typename number_traits<typename \
                     linalg_traits<M>::value_type>::magnitude_type
   
-  template<typename T> inline std::complex<T> operator*(const std::complex<T>& a, int b) {
-    return a*T(b);
-  }
-  template<typename T> inline std::complex<T> operator*(int b, const std::complex<T>& a) {
-    return a*T(b);
-  }
-
   /* ******************************************************************** */
   /*  types promotion                                                     */
   /* ******************************************************************** */
@@ -481,6 +486,7 @@ namespace gmm {
 
   template <typename T> class wsvector;
   template <typename T> class rsvector;
+  template <typename T> class dsvector;
   template<typename T> struct sparse_vector_type 
   { typedef wsvector<T> vector_type; };
 
@@ -917,22 +923,21 @@ namespace gmm {
   template <typename IT, typename ORG, typename VECT> inline
   void set_to_end(IT &, ORG, const VECT *, linalg_const) { }
 
-
   template <typename IT, typename ORG, typename VECT> inline
   void set_to_begin(IT &, ORG, VECT *v, linalg_modifiable)
-  { GMM_ASSERT3(!is_sparse(*v), "internal_error"); v = 0; }
+  { GMM_ASSERT3(!is_sparse(*v), "internal_error"); (void)v; }
 
   template <typename IT, typename ORG, typename VECT> inline
   void set_to_begin(IT &, ORG, const VECT *v, linalg_modifiable)
-  { GMM_ASSERT3(!is_sparse(*v), "internal_error"); v = 0; }
+  { GMM_ASSERT3(!is_sparse(*v), "internal_error"); (void)v; }
  
   template <typename IT, typename ORG, typename VECT> inline
   void set_to_end(IT &, ORG, VECT *v, linalg_modifiable)
-  { GMM_ASSERT3(!is_sparse(*v), "internal_error"); v = 0; }
+  { GMM_ASSERT3(!is_sparse(*v), "internal_error"); (void)v; }
   
   template <typename IT, typename ORG, typename VECT> inline
   void set_to_end(IT &, ORG, const VECT *v, linalg_modifiable)
-  { GMM_ASSERT3(!is_sparse(*v), "internal_error"); v = 0; }
+  { GMM_ASSERT3(!is_sparse(*v), "internal_error"); (void)v; }
 
   /* ******************************************************************** */
   /*		General index for certain algorithms.         		  */
@@ -959,7 +964,7 @@ namespace gmm {
       if (numeric_limits<T>::is_specialized)
 	tol = numeric_limits<T>::epsilon();
       else {
-	int i=sizeof(T)/4; while(i-- > 0) tol*=T(1E-8); 
+	int i=int(sizeof(T)/4); while(i-- > 0) tol*=T(1E-8); 
 	GMM_WARNING1("The numeric type " << typeid(T).name()
 		    << " has no numeric_limits defined !!\n"
 		    << "Taking " << tol << " as default tolerance");
@@ -1049,7 +1054,7 @@ namespace gmm {
     typename linalg_traits<L>::const_iterator it = vect_const_begin(l),
       ite = vect_const_end(l);
     for (; it != ite; ++it) 
-      o << " (r" << it.index() << "," << cast_char(*it) << ")";
+      o << " (r" << it.index() << ", " << cast_char(*it) << ")";
   }
 
   template <typename L> void write(std::ostream &o, const L &l,
diff --git a/contrib/gmm/gmm_dense_Householder.h b/contrib/gmm/gmm_dense_Householder.h
index 9e34c1ab3e..ea010ed5ad 100644
--- a/contrib/gmm/gmm_dense_Householder.h
+++ b/contrib/gmm/gmm_dense_Householder.h
@@ -1,32 +1,33 @@
-// -*- c++ -*- (enables emacs c++ mode)
-//===========================================================================
-//
-// Copyright (C) 2003-2008 Yves Renard
-//
-// This file is a part of GETFEM++
-//
-// Getfem++  is  free software;  you  can  redistribute  it  and/or modify it
-// under  the  terms  of the  GNU  Lesser General Public License as published
-// by  the  Free Software Foundation;  either version 2.1 of the License,  or
-// (at your option) any later version.
-// This program  is  distributed  in  the  hope  that it will be useful,  but
-// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-// or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
-// License for more details.
-// You  should  have received a copy of the GNU Lesser General Public License
-// along  with  this program;  if not, write to the Free Software Foundation,
-// Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
-//
-// As a special exception, you may use this file as part of a free software
-// library without restriction.  Specifically, if other files instantiate
-// templates or use macros or inline functions from this file, or you compile
-// this file and link it with other files to produce an executable, this
-// file does not by itself cause the resulting executable to be covered by
-// the GNU General Public License.  This exception does not however
-// invalidate any other reasons why the executable file might be covered by
-// the GNU General Public License.
-//
-//===========================================================================
+/* -*- c++ -*- (enables emacs c++ mode) */
+/*===========================================================================
+
+ Copyright (C) 2003-2020 Yves Renard, Caroline Lecalvez
+
+ This file is a part of GetFEM
+
+ GetFEM  is  free software;  you  can  redistribute  it  and/or modify it
+ under  the  terms  of the  GNU  Lesser General Public License as published
+ by  the  Free Software Foundation;  either version 3 of the License,  or
+ (at your option) any later version along with the GCC Runtime Library
+ Exception either version 3.1 or (at your option) any later version.
+ This program  is  distributed  in  the  hope  that it will be useful,  but
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+ License and GCC Runtime Library Exception for more details.
+ You  should  have received a copy of the GNU Lesser General Public License
+ along  with  this program;  if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+
+ As a special exception, you  may use  this file  as it is a part of a free
+ software  library  without  restriction.  Specifically,  if   other  files
+ instantiate  templates  or  use macros or inline functions from this file,
+ or  you compile this  file  and  link  it  with other files  to produce an
+ executable, this file  does  not  by itself cause the resulting executable
+ to be covered  by the GNU Lesser General Public License.  This   exception
+ does not  however  invalidate  any  other  reasons why the executable file
+ might be covered by the GNU Lesser General Public License.
+
+===========================================================================*/
 
 /**@file gmm_dense_Householder.h
    @author Caroline Lecalvez <Caroline.Lecalvez@gmm.insa-toulouse.fr>
@@ -49,17 +50,17 @@ namespace gmm {
 
   template <typename Matrix, typename VecX, typename VecY>
   inline void rank_one_update(Matrix &A, const VecX& x,
-			      const VecY& y, row_major) {
+                              const VecY& y, row_major) {
     typedef typename linalg_traits<Matrix>::value_type T;
     size_type N = mat_nrows(A);
     GMM_ASSERT2(N <= vect_size(x) && mat_ncols(A) <= vect_size(y),
-	       "dimensions mismatch");
+                "dimensions mismatch");
     typename linalg_traits<VecX>::const_iterator itx = vect_const_begin(x);
     for (size_type i = 0; i < N; ++i, ++itx) {
       typedef typename linalg_traits<Matrix>::sub_row_type row_type;
       row_type row = mat_row(A, i);
-      typename linalg_traits<row_type>::iterator
-	it = vect_begin(row), ite = vect_end(row);
+      typename linalg_traits<typename org_type<row_type>::t>::iterator
+        it = vect_begin(row), ite = vect_end(row);
       typename linalg_traits<VecY>::const_iterator ity = vect_const_begin(y);
       T tx = *itx;
       for (; it != ite; ++it, ++ity) *it += conj_product(*ity, tx);
@@ -68,30 +69,30 @@ namespace gmm {
 
   template <typename Matrix, typename VecX, typename VecY>
   inline void rank_one_update(Matrix &A, const VecX& x,
-			      const VecY& y, col_major) {
+                              const VecY& y, col_major) {
     typedef typename linalg_traits<Matrix>::value_type T;
     size_type M = mat_ncols(A);
     GMM_ASSERT2(mat_nrows(A) <= vect_size(x) && M <= vect_size(y),
-		"dimensions mismatch");
+                "dimensions mismatch");
     typename linalg_traits<VecY>::const_iterator ity = vect_const_begin(y);
     for (size_type i = 0; i < M; ++i, ++ity) {
       typedef typename linalg_traits<Matrix>::sub_col_type col_type;
       col_type col = mat_col(A, i);
-      typename linalg_traits<col_type>::iterator
-	it = vect_begin(col), ite = vect_end(col);
+      typename linalg_traits<typename org_type<col_type>::t>::iterator
+        it = vect_begin(col), ite = vect_end(col);
       typename linalg_traits<VecX>::const_iterator itx = vect_const_begin(x);
       T ty = *ity;
       for (; it != ite; ++it, ++itx) *it += conj_product(ty, *itx);
     }
   }
-  
+
   ///@endcond
   template <typename Matrix, typename VecX, typename VecY>
   inline void rank_one_update(const Matrix &AA, const VecX& x,
-			      const VecY& y) {
+                              const VecY& y) {
     Matrix& A = const_cast<Matrix&>(AA);
     rank_one_update(A, x, y, typename principal_orientation_type<typename
-		    linalg_traits<Matrix>::sub_orientation>::potype());
+                    linalg_traits<Matrix>::sub_orientation>::potype());
   }
   ///@cond DOXY_SHOW_ALL_FUNCTIONS
 
@@ -101,55 +102,55 @@ namespace gmm {
 
   template <typename Matrix, typename VecX, typename VecY>
   inline void rank_two_update(Matrix &A, const VecX& x,
-			      const VecY& y, row_major) {
+                              const VecY& y, row_major) {
     typedef typename linalg_traits<Matrix>::value_type value_type;
     size_type N = mat_nrows(A);
     GMM_ASSERT2(N <= vect_size(x) && mat_ncols(A) <= vect_size(y),
-		"dimensions mismatch");
+                "dimensions mismatch");
     typename linalg_traits<VecX>::const_iterator itx1 = vect_const_begin(x);
     typename linalg_traits<VecY>::const_iterator ity2 = vect_const_begin(y);
     for (size_type i = 0; i < N; ++i, ++itx1, ++ity2) {
       typedef typename linalg_traits<Matrix>::sub_row_type row_type;
       row_type row = mat_row(A, i);
-      typename linalg_traits<row_type>::iterator
-	it = vect_begin(row), ite = vect_end(row);
+      typename linalg_traits<typename org_type<row_type>::t>::iterator
+        it = vect_begin(row), ite = vect_end(row);
       typename linalg_traits<VecX>::const_iterator itx2 = vect_const_begin(x);
       typename linalg_traits<VecY>::const_iterator ity1 = vect_const_begin(y);
       value_type tx = *itx1, ty = *ity2;
       for (; it != ite; ++it, ++ity1, ++itx2)
-	*it += conj_product(*ity1, tx) + conj_product(*itx2, ty);
+        *it += conj_product(*ity1, tx) + conj_product(*itx2, ty);
     }
   }
 
   template <typename Matrix, typename VecX, typename VecY>
   inline void rank_two_update(Matrix &A, const VecX& x,
-			      const VecY& y, col_major) {
+                              const VecY& y, col_major) {
     typedef typename linalg_traits<Matrix>::value_type value_type;
     size_type M = mat_ncols(A);
     GMM_ASSERT2(mat_nrows(A) <= vect_size(x) && M <= vect_size(y),
-		"dimensions mismatch");
+                "dimensions mismatch");
     typename linalg_traits<VecX>::const_iterator itx2 = vect_const_begin(x);
     typename linalg_traits<VecY>::const_iterator ity1 = vect_const_begin(y);
     for (size_type i = 0; i < M; ++i, ++ity1, ++itx2) {
       typedef typename linalg_traits<Matrix>::sub_col_type col_type;
       col_type col = mat_col(A, i);
-      typename linalg_traits<col_type>::iterator
-	it = vect_begin(col), ite = vect_end(col);
+      typename linalg_traits<typename org_type<col_type>::t>::iterator
+        it = vect_begin(col), ite = vect_end(col);
       typename linalg_traits<VecX>::const_iterator itx1 = vect_const_begin(x);
       typename linalg_traits<VecY>::const_iterator ity2 = vect_const_begin(y);
       value_type ty = *ity1, tx = *itx2;
       for (; it != ite; ++it, ++itx1, ++ity2)
-	*it += conj_product(ty, *itx1) + conj_product(tx, *ity2); 
+        *it += conj_product(ty, *itx1) + conj_product(tx, *ity2);
     }
   }
-  
+
   ///@endcond
   template <typename Matrix, typename VecX, typename VecY>
   inline void rank_two_update(const Matrix &AA, const VecX& x,
-			      const VecY& y) {
+                              const VecY& y) {
     Matrix& A = const_cast<Matrix&>(AA);
     rank_two_update(A, x, y, typename principal_orientation_type<typename
-		    linalg_traits<Matrix>::sub_orientation>::potype());
+                    linalg_traits<Matrix>::sub_orientation>::potype());
   }
   ///@cond DOXY_SHOW_ALL_FUNCTIONS
 
@@ -161,11 +162,11 @@ namespace gmm {
     VECT &V = const_cast<VECT &>(VV);
     typedef typename linalg_traits<VECT>::value_type T;
     typedef typename number_traits<T>::magnitude_type R;
-    
+
     R mu = vect_norm2(V), abs_v0 = gmm::abs(V[0]);
     if (mu != R(0))
       gmm::scale(V, (abs_v0 == R(0)) ? T(R(1) / mu)
-		 : (safe_divide(T(abs_v0), V[0]) / (abs_v0 + mu)));
+                 : (safe_divide(T(abs_v0), V[0]) / (abs_v0 + mu)));
     if (gmm::real(V[vect_size(V)-1]) * R(0) != R(0)) gmm::clear(V);
     V[0] = T(1);
   }
@@ -179,47 +180,47 @@ namespace gmm {
     R mu = vect_norm2(V), abs_v0 = gmm::abs(V[m-1]);
     if (mu != R(0))
       gmm::scale(V, (abs_v0 == R(0)) ? T(R(1) / mu)
-		 : ((abs_v0 / V[m-1]) / (abs_v0 + mu)));
+                 : ((abs_v0 / V[m-1]) / (abs_v0 + mu)));
     if (gmm::real(V[0]) * R(0) != R(0)) gmm::clear(V);
     V[m-1] = T(1);
   }
-  
+
   /* ********************************************************************* */
   /*    Householder updates  (complex and real version)                    */
   /* ********************************************************************* */
 
   // multiply A to the left by the reflector stored in V. W is a temporary.
   template <typename MAT, typename VECT1, typename VECT2> inline
-    void row_house_update(const MAT &AA, const VECT1 &V, const VECT2 &WW) {
+  void row_house_update(const MAT &AA, const VECT1 &V, const VECT2 &WW) {
     VECT2 &W = const_cast<VECT2 &>(WW); MAT &A = const_cast<MAT &>(AA);
     typedef typename linalg_traits<MAT>::value_type value_type;
     typedef typename number_traits<value_type>::magnitude_type magnitude_type;
 
     gmm::mult(conjugated(A),
-	      scaled(V, value_type(magnitude_type(-2)/vect_norm2_sqr(V))), W);
+              scaled(V, value_type(magnitude_type(-2)/vect_norm2_sqr(V))), W);
     rank_one_update(A, V, W);
   }
 
   // multiply A to the right by the reflector stored in V. W is a temporary.
   template <typename MAT, typename VECT1, typename VECT2> inline
-    void col_house_update(const MAT &AA, const VECT1 &V, const VECT2 &WW) {
+  void col_house_update(const MAT &AA, const VECT1 &V, const VECT2 &WW) {
     VECT2 &W = const_cast<VECT2 &>(WW); MAT &A = const_cast<MAT &>(AA);
     typedef typename linalg_traits<MAT>::value_type value_type;
     typedef typename number_traits<value_type>::magnitude_type magnitude_type;
-    
+
     gmm::mult(A,
-	      scaled(V, value_type(magnitude_type(-2)/vect_norm2_sqr(V))), W);
+              scaled(V, value_type(magnitude_type(-2)/vect_norm2_sqr(V))), W);
     rank_one_update(A, W, V);
   }
 
   ///@endcond
 
   /* ********************************************************************* */
-  /*    Hessemberg reduction with Householder.                             */
+  /*    Hessenberg reduction with Householder.                             */
   /* ********************************************************************* */
 
   template <typename MAT1, typename MAT2>
-    void Hessenberg_reduction(const MAT1& AA, const MAT2 &QQ, bool compute_Q){
+  void Hessenberg_reduction(const MAT1& AA, const MAT2 &QQ, bool compute_Q){
     MAT1& A = const_cast<MAT1&>(AA); MAT2& Q = const_cast<MAT2&>(QQ);
     typedef typename linalg_traits<MAT1>::value_type value_type;
     if (compute_Q) gmm::copy(identity_matrix(), Q);
@@ -242,9 +243,9 @@ namespace gmm {
   /*    Householder tridiagonalization for symmetric matrices              */
   /* ********************************************************************* */
 
-  template <typename MAT1, typename MAT2> 
+  template <typename MAT1, typename MAT2>
   void Householder_tridiagonalization(const MAT1 &AA, const MAT2 &QQ,
-				     bool compute_q) {
+                                      bool compute_q) {
     MAT1 &A = const_cast<MAT1 &>(AA); MAT2 &Q = const_cast<MAT2 &>(QQ);
     typedef typename linalg_traits<MAT1>::value_type T;
     typedef typename number_traits<T>::magnitude_type R;
@@ -255,9 +256,9 @@ namespace gmm {
 
     for (size_type k = 1; k+1 < n; ++k) { // not optimized ...
       sub_interval SUBI(k, n-k);
-      v.resize(n-k); p.resize(n-k); w.resize(n-k); 
-      for (size_type l = k; l < n; ++l) 
-	{ v[l-k] = w[l-k] = A(l, k-1); A(l, k-1) = A(k-1, l) = T(0); }
+      v.resize(n-k); p.resize(n-k); w.resize(n-k);
+      for (size_type l = k; l < n; ++l)
+        { v[l-k] = w[l-k] = A(l, k-1); A(l, k-1) = A(k-1, l) = T(0); }
       house_vector(v);
       R norm = vect_norm2_sqr(v);
       A(k-1, k) = gmm::conj(A(k, k-1) = w[0] - T(2)*v[0]*vect_hp(w, v)/norm);
@@ -309,7 +310,7 @@ namespace gmm {
     for (size_type j = 0; j < mat_nrows(A); ++j)
       Apply_Givens_rotation_right(A(j,i), A(j,k), c, s);
   }
-  
+
 }
 
 #endif
diff --git a/contrib/gmm/gmm_dense_lu.h b/contrib/gmm/gmm_dense_lu.h
index 23ca9b8a12..33fbbcb198 100644
--- a/contrib/gmm/gmm_dense_lu.h
+++ b/contrib/gmm/gmm_dense_lu.h
@@ -1,90 +1,64 @@
-// -*- c++ -*- (enables emacs c++ mode)
-//===========================================================================
-//
-// Copyright (C) 2003-2008 Yves Renard
-//
-// This file is a part of GETFEM++
-//
-// Getfem++  is  free software;  you  can  redistribute  it  and/or modify it
-// under  the  terms  of the  GNU  Lesser General Public License as published
-// by  the  Free Software Foundation;  either version 2.1 of the License,  or
-// (at your option) any later version.
-// This program  is  distributed  in  the  hope  that it will be useful,  but
-// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-// or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
-// License for more details.
-// You  should  have received a copy of the GNU Lesser General Public License
-// along  with  this program;  if not, write to the Free Software Foundation,
-// Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
-//
-// As a special exception, you may use this file as part of a free software
-// library without restriction.  Specifically, if other files instantiate
-// templates or use macros or inline functions from this file, or you compile
-// this file and link it with other files to produce an executable, this
-// file does not by itself cause the resulting executable to be covered by
-// the GNU General Public License.  This exception does not however
-// invalidate any other reasons why the executable file might be covered by
-// the GNU General Public License.
-//
-//===========================================================================
+/* -*- c++ -*- (enables emacs c++ mode) */
+/*===========================================================================
+
+ Copyright (C) 2003-2020 Yves Renard
+
+ This file is a part of GetFEM
+
+ GetFEM  is  free software;  you  can  redistribute  it  and/or modify it
+ under  the  terms  of the  GNU  Lesser General Public License as published
+ by  the  Free Software Foundation;  either version 3 of the License,  or
+ (at your option) any later version along with the GCC Runtime Library
+ Exception either version 3.1 or (at your option) any later version.
+ This program  is  distributed  in  the  hope  that it will be useful,  but
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+ License and GCC Runtime Library Exception for more details.
+ You  should  have received a copy of the GNU Lesser General Public License
+ along  with  this program;  if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+
+ As a special exception, you  may use  this file  as it is a part of a free
+ software  library  without  restriction.  Specifically,  if   other  files
+ instantiate  templates  or  use macros or inline functions from this file,
+ or  you compile this  file  and  link  it  with other files  to produce an
+ executable, this file  does  not  by itself cause the resulting executable
+ to be covered  by the GNU Lesser General Public License.  This   exception
+ does not  however  invalidate  any  other  reasons why the executable file
+ might be covered by the GNU Lesser General Public License.
+
+===========================================================================*/
 
 // This file is a modified version of lu.h from MTL.
 // See http://osl.iu.edu/research/mtl/
 // Following the corresponding Copyright notice.
 //===========================================================================
-// Copyright (c) 2001-2003 The Trustees of Indiana University.
-// All rights reserved.
-// Copyright (c) 1998-2001 University of Notre Dame. All rights reserved.
-// Authors: Andrew Lumsdaine, Jeremy G. Siek, Lie-Quan Lee
-//
-// This file is part of the Matrix Template Library
-//
-// Indiana University has the exclusive rights to license this product under
-// the following license.
 //
+// Copyright (c) 1998-2020, University of Notre Dame. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are met:
-//   1.  All redistributions of source code must retain the above  copyright
-//       notice, the list of authors in the original source code,  this list
-//       of conditions and the disclaimer listed in this license;
-//   2.  All redistributions in binary form must reproduce the above
-//       copyright notice, this list of conditions and the disclaimer listed
-//       in this license in the documentation and/or other materials provided
-//       with the distribution;
-//   3.  Any documentation included with all redistributions must include the
-//       following acknowledgement:
-//	"This product includes software developed at the University of
-//       Notre Dame and the Pervasive Technology Labs at Indiana University.
-//       For technical information contact Andrew Lumsdaine at the Pervasive
-//       Technology Labs at Indiana University. 
-//	 For administrative and license questions contact the Advanced
-//       Research and Technology Institute at 1100 Waterway Blvd.
-//       Indianapolis, Indiana 46202, phone 317-274-5905, fax  317-274-5902."
-//	 Alternatively, this acknowledgement may appear in the software
-//       itself, and wherever such third-party acknowledgments normally appear.
-//   4.  The name "MTL" shall not be used to endorse or promote  products
-//       derived from this software without prior written  permission from
-//       Indiana University. For written permission, please  contact Indiana
-//       University Advanced Research & Technology  Institute.
-//   5.  Products derived from this software may not be called "MTL", nor
-//       may "MTL" appear in their name, without  prior written permission
-//       of Indiana University Advanced Research & Technology Institute.
 //
-// Indiana University provides no reassurances that the source code provided
-// does not infringe the patent or any other intellectual property rights of
-// any other entity. Indiana University disclaims any liability to any
-// recipient for claims brought by any other entity based on infringement of 
-// intellectual property rights or otherwise.
+//    * Redistributions of source code must retain the above copyright
+//      notice, this list of conditions and the following disclaimer.
+//    * Redistributions in binary form must reproduce the above copyright
+//      notice, this list of conditions and the following disclaimer in the
+//      documentation and/or other materials provided with the distribution.
+//    * Neither the name of the University of Notre Dame nor the
+//      names of its contributors may be used to endorse or promote products
+//      derived from this software without specific prior written permission.
+//
+// THIS SOFTWARE  IS  PROVIDED  BY  THE TRUSTEES  OF  INDIANA UNIVERSITY  AND
+// CONTRIBUTORS  ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,  INCLUDING,
+// BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND  FITNESS
+// FOR  A PARTICULAR PURPOSE ARE DISCLAIMED. IN  NO  EVENT SHALL THE TRUSTEES
+// OF INDIANA UNIVERSITY AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY,  OR CONSEQUENTIAL DAMAGES (INCLUDING,  BUT
+// NOT  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA,  OR PROFITS;  OR BUSINESS  INTERRUPTION)  HOWEVER  CAUSED AND ON ANY
+// THEORY  OF  LIABILITY,  WHETHER  IN  CONTRACT,  STRICT  LIABILITY, OR TORT
+// (INCLUDING  NEGLIGENCE  OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+// THIS  SOFTWARE,  EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 //
-// LICENSEE UNDERSTANDS THAT SOFTWARE IS PROVIDED "AS IS" FOR WHICH NO
-// WARRANTIES AS TO CAPABILITIES OR ACCURACY ARE MADE. INDIANA UNIVERSITY
-// GIVES NO WARRANTIES AND MAKES NO REPRESENTATION THAT SOFTWARE IS FREE OF
-// INFRINGEMENT OF THIRD PARTY PATENT, COPYRIGHT, OR OTHER PROPRIETARY RIGHTS. 
-// INDIANA UNIVERSITY MAKES NO WARRANTIES THAT SOFTWARE IS FREE FROM "BUGS",
-// "VIRUSES", "TROJAN HORSES", "TRAP DOORS", "WORMS", OR OTHER HARMFUL CODE.
-// LICENSEE ASSUMES THE ENTIRE RISK AS TO THE PERFORMANCE OF SOFTWARE AND/OR
-// ASSOCIATED MATERIALS, AND TO THE PERFORMANCE AND VALIDITY OF 
-// INFORMATION GENERATED USING SOFTWARE.
 //===========================================================================
 
 /**@file gmm_dense_lu.h
@@ -96,10 +70,50 @@
 #define GMM_DENSE_LU_H
 
 #include "gmm_dense_Householder.h"
-#include "gmm_opt.h"
 
 namespace gmm {
 
+  /* ********************************************************************** */
+  /* IPVT structure.                                                        */
+  /* ********************************************************************** */
+  // For compatibility with lapack version with 64 or 32 bit integer.
+  // Should be replaced by std::vector<size_type> if 32 bit integer version
+  // of lapack is not used anymore (and lapack_ipvt_int set to size_type)
+
+  // Do not use iterators of this interface container
+  class lapack_ipvt : public std::vector<size_type> {
+    bool is_int64;
+    size_type &operator[](size_type i)
+    { return std::vector<size_type>::operator[](i); }
+    size_type operator[] (size_type i) const
+    { return std::vector<size_type>::operator[](i); }
+    void begin(void) const {}
+    void begin(void) {}
+    void end(void) const {}
+    void end(void) {}
+    
+  public:
+    void set_to_int32() { is_int64 = false; }
+    const size_type *pfirst() const
+    { return &(*(std::vector<size_type>::begin())); }
+    size_type *pfirst() { return &(*(std::vector<size_type>::begin())); }
+    
+    lapack_ipvt(size_type n) :  std::vector<size_type>(n), is_int64(true) {}
+    
+    size_type get(size_type i) const {
+      const size_type *p = pfirst();
+      return is_int64 ? p[i] : size_type(((const int *)(p))[i]);
+    }
+    void set(size_type i, size_type val) {
+      size_type *p = pfirst();
+      if (is_int64) p[i] = val; else ((int *)(p))[i] = int(val);
+    }
+  };
+}
+
+#include "gmm_opt.h"
+
+namespace gmm {
 
   /** LU Factorization of a general (dense) matrix (real or complex).
   
@@ -111,8 +125,8 @@ namespace gmm {
   The pivot indices in ipvt are indexed starting from 1
   so that this is compatible with LAPACK (Fortran).
   */
-  template <typename DenseMatrix, typename Pvector>
-  size_type lu_factor(DenseMatrix& A, Pvector& ipvt) {
+  template <typename DenseMatrix>
+  size_type lu_factor(DenseMatrix& A, lapack_ipvt& ipvt) {
     typedef typename linalg_traits<DenseMatrix>::value_type T;
     typedef typename number_traits<T>::magnitude_type R;
     size_type info(0), i, j, jp, M(mat_nrows(A)), N(mat_ncols(A));
@@ -120,14 +134,14 @@ namespace gmm {
     std::vector<T> c(M), r(N);
     
     GMM_ASSERT2(ipvt.size()+1 >= NN, "IPVT too small");
-    for (i = 0; i+1 < NN; ++i) ipvt[i] = i;
+    for (i = 0; i+1 < NN; ++i) ipvt.set(i, i);
       
     if (M || N) {
       for (j = 0; j+1 < NN; ++j) {
 	R max = gmm::abs(A(j,j)); jp = j;
 	for (i = j+1; i < M; ++i)		   /* find pivot.          */
 	  if (gmm::abs(A(i,j)) > max) { jp = i; max = gmm::abs(A(i,j)); }
-	ipvt[j] = jp + 1;
+	ipvt.set(j, jp + 1);
 	
 	if (max == R(0)) { info = j + 1; break; }
         if (jp != j) for (i = 0; i < N; ++i) std::swap(A(jp, i), A(j, i));
@@ -137,7 +151,7 @@ namespace gmm {
 	rank_one_update(sub_matrix(A, sub_interval(j+1, M-j-1),
 				 sub_interval(j+1, N-j-1)), c, conjugated(r));
       }
-      ipvt[j] = j + 1;
+      ipvt.set(NN-1, NN);
     }
     return info;
   }
@@ -151,7 +165,7 @@ namespace gmm {
     typedef typename linalg_traits<DenseMatrix>::value_type T;
     copy(b, x);
     for(size_type i = 0; i < pvector.size(); ++i) {
-      size_type perm = pvector[i]-1;     // permutations stored in 1's offset
+      size_type perm = pvector.get(i)-1;   // permutations stored in 1's offset
       if(i != perm) { T aux = x[i]; x[i] = x[perm]; x[perm] = aux; }
     }
     /* solve  Ax = b  ->  LUx = b  ->  Ux = L^-1 b.                        */
@@ -163,7 +177,7 @@ namespace gmm {
   void lu_solve(const DenseMatrix &A, VectorX &x, const VectorB &b) {
     typedef typename linalg_traits<DenseMatrix>::value_type T;
     dense_matrix<T> B(mat_nrows(A), mat_ncols(A));
-    std::vector<int> ipvt(mat_nrows(A));
+    lapack_ipvt ipvt(mat_nrows(A));
     gmm::copy(A, B);
     size_type info = lu_factor(B, ipvt);
     GMM_ASSERT1(!info, "Singular system, pivot = " << info);
@@ -179,10 +193,9 @@ namespace gmm {
     lower_tri_solve(transposed(LU), x, false);
     upper_tri_solve(transposed(LU), x, true);
     for(size_type i = pvector.size(); i > 0; --i) {
-      size_type perm = pvector[i-1]-1;    // permutations stored in 1's offset
+      size_type perm = pvector.get(i-1)-1; // permutations stored in 1's offset
       if(i-1 != perm) { T aux = x[i-1]; x[i-1] = x[perm]; x[perm] = aux; }
     }
-
   }
 
 
@@ -233,15 +246,15 @@ namespace gmm {
       return the determinant */
   template <typename DenseMatrix>
   typename linalg_traits<DenseMatrix>::value_type
-  lu_inverse(const DenseMatrix& A_) {
+  lu_inverse(const DenseMatrix& A_, bool doassert = true) {
     typedef typename linalg_traits<DenseMatrix>::value_type T;
     DenseMatrix& A = const_cast<DenseMatrix&>(A_);
     dense_matrix<T> B(mat_nrows(A), mat_ncols(A));
-    std::vector<int> ipvt(mat_nrows(A));
+    lapack_ipvt ipvt(mat_nrows(A));
     gmm::copy(A, B);
     size_type info = lu_factor(B, ipvt);
-    GMM_ASSERT1(!info, "Non invertible matrix, pivot = " << info);
-    lu_inverse(B, ipvt, A);
+    if (doassert) GMM_ASSERT1(!info, "Non invertible matrix, pivot = "<<info);
+    if (!info) lu_inverse(B, ipvt, A);
     return lu_det(B, ipvt);
   }
 
@@ -254,7 +267,7 @@ namespace gmm {
     for (size_type j = 0; j < std::min(mat_nrows(LU), mat_ncols(LU)); ++j)
       det *= LU(j,j);
     for(size_type i = 0; i < pvector.size(); ++i)
-      if (i != size_type(pvector[i]-1)) { det = -det; }
+      if (i != size_type(pvector.get(i)-1)) { det = -det; }
     return det;
   }
 
@@ -263,7 +276,7 @@ namespace gmm {
   lu_det(const DenseMatrix& A) {
     typedef typename linalg_traits<DenseMatrix>::value_type T;
     dense_matrix<T> B(mat_nrows(A), mat_ncols(A));
-    std::vector<int> ipvt(mat_nrows(A));
+    lapack_ipvt ipvt(mat_nrows(A));
     gmm::copy(A, B);
     lu_factor(B, ipvt);
     return lu_det(B, ipvt);
diff --git a/contrib/gmm/gmm_dense_matrix_functions.h b/contrib/gmm/gmm_dense_matrix_functions.h
new file mode 100644
index 0000000000..3cd18b6020
--- /dev/null
+++ b/contrib/gmm/gmm_dense_matrix_functions.h
@@ -0,0 +1,302 @@
+/* -*- c++ -*- (enables emacs c++ mode) */
+/*===========================================================================
+
+ Copyright (C) 2014-2020 Konstantinos Poulios
+
+ This file is a part of GetFEM
+
+ GetFEM  is  free software;  you  can  redistribute  it  and/or modify it
+ under  the  terms  of the  GNU  Lesser General Public License as published
+ by  the  Free Software Foundation;  either version 3 of the License,  or
+ (at your option) any later version along with the GCC Runtime Library
+ Exception either version 3.1 or (at your option) any later version.
+ This program  is  distributed  in  the  hope  that it will be useful,  but
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+ License and GCC Runtime Library Exception for more details.
+ You  should  have received a copy of the GNU Lesser General Public License
+ along  with  this program;  if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+
+ As a special exception, you  may use  this file  as it is a part of a free
+ software  library  without  restriction.  Specifically,  if   other  files
+ instantiate  templates  or  use macros or inline functions from this file,
+ or  you compile this  file  and  link  it  with other files  to produce an
+ executable, this file  does  not  by itself cause the resulting executable
+ to be covered  by the GNU Lesser General Public License.  This   exception
+ does not  however  invalidate  any  other  reasons why the executable file
+ might be covered by the GNU Lesser General Public License.
+
+===========================================================================*/
+
+/**@file gmm_dense_matrix_functions.h
+   @author  Konstantinos Poulios <poulios.konstantinos@gmail.com>
+   @date December 10, 2014.
+   @brief Common matrix functions for dense matrices.
+*/
+#ifndef GMM_DENSE_MATRIX_FUNCTIONS_H
+#define GMM_DENSE_MATRIX_FUNCTIONS_H
+
+
+namespace gmm {
+
+
+  /**
+     Matrix square root for upper triangular matrices (from GNU Octave).
+  */
+  template <typename T>
+  void sqrtm_utri_inplace(dense_matrix<T>& A)
+  {
+    typedef typename number_traits<T>::magnitude_type R;
+    bool singular = false;
+
+    // The following code is equivalent to this triple loop:
+    //
+    //   n = rows (A);
+    //   for j = 1:n
+    //     A(j,j) = sqrt (A(j,j));
+    //     for i = j-1:-1:1
+    //       A(i,j) /= (A(i,i) + A(j,j));
+    //       k = 1:i-1;
+    //   t storing a    A(k,j) -= A(k,i) * A(i,j);
+    //     endfor
+    //   endfor
+
+    R tol = R(0); // default_tol(R()) * gmm::mat_maxnorm(A);
+
+    const size_type n = mat_nrows(A);
+    for (int j=0; j < int(n); j++) {
+      typename dense_matrix<T>::iterator colj = A.begin() + j*n;
+      if (gmm::abs(colj[j]) > tol)
+        colj[j] = gmm::sqrt(colj[j]);
+      else
+        singular = true;
+
+      for (int i=j-1; i >= 0; i--) {
+        typename dense_matrix<T>::const_iterator coli = A.begin() + i*n;
+        T colji = colj[i] = safe_divide(colj[i], (coli[i] + colj[j]));
+        for (int k = 0; k < i; k++)
+          colj[k] -= coli[k] * colji;
+      }
+    }
+
+    if (singular)
+      GMM_WARNING1("Matrix is singular, may not have a square root");
+  }
+
+
+  template <typename T>
+  void sqrtm(const dense_matrix<std::complex<T> >& A,
+             dense_matrix<std::complex<T> >& SQRTMA)
+  {
+    GMM_ASSERT1(gmm::mat_nrows(A) == gmm::mat_ncols(A),
+                "Matrix square root requires a square matrix");
+    gmm::resize(SQRTMA, gmm::mat_nrows(A), gmm::mat_ncols(A));
+    dense_matrix<std::complex<T> > S(A), Q(A), TMP(A);
+    #if defined(GMM_USES_LAPACK)
+    schur(TMP, S, Q);
+    #else
+    GMM_ASSERT1(false, "Please recompile with lapack and blas librairies "
+                "to use sqrtm matrix function.");
+    #endif
+    sqrtm_utri_inplace(S);
+    gmm::mult(Q, S, TMP);
+    gmm::mult(TMP, gmm::transposed(Q), SQRTMA);
+  }
+
+  template <typename T>
+  void sqrtm(const dense_matrix<T>& A,
+             dense_matrix<std::complex<T> >& SQRTMA)
+  {
+    dense_matrix<std::complex<T> > cA(mat_nrows(A), mat_ncols(A));
+    gmm::copy(A, gmm::real_part(cA));
+    sqrtm(cA, SQRTMA);
+  }
+
+  template <typename T>
+  void sqrtm(const dense_matrix<T>& A, dense_matrix<T>& SQRTMA)
+  {
+    dense_matrix<std::complex<T> > cA(mat_nrows(A), mat_ncols(A));
+    gmm::copy(A, gmm::real_part(cA));
+    dense_matrix<std::complex<T> > cSQRTMA(cA);
+    sqrtm(cA, cSQRTMA);
+    gmm::resize(SQRTMA, gmm::mat_nrows(A), gmm::mat_ncols(A));
+    gmm::copy(gmm::real_part(cSQRTMA), SQRTMA);
+//    dense_matrix<std::complex<T1> >::const_reference
+//      it = cSQRTMA.begin(), ite = cSQRTMA.end();
+//    dense_matrix<std::complex<T1> >::reference
+//      rit = SQRTMA.begin();
+//    for (; it != ite; ++it, ++rit) *rit = it->real();
+  }
+
+
+  /**
+   Matrix logarithm for upper triangular matrices (from GNU/Octave)
+  */
+  template <typename T>
+  void logm_utri_inplace(dense_matrix<T>& S)
+  {
+    typedef typename number_traits<T>::magnitude_type R;
+
+    size_type n = gmm::mat_nrows(S);
+    GMM_ASSERT1(n == gmm::mat_ncols(S),
+                "Matrix logarithm is not defined for non-square matrices");
+    for (size_type i=0; i < n-1; ++i)
+      if (gmm::abs(S(i+1,i)) > default_tol(T())) {
+        GMM_ASSERT1(false, "An upper triangular matrix is expected");
+        break;
+      }
+    for (size_type i=0; i < n-1; ++i)
+      if (gmm::real(S(i,i)) <= -default_tol(R()) &&
+          gmm::abs(gmm::imag(S(i,i))) <= default_tol(R())) {
+        GMM_ASSERT1(false, "Principal matrix logarithm is not defined "
+                           "for matrices with negative eigenvalues");
+        break;
+      }
+
+    // Algorithm 11.9 in "Function of matrices", by N. Higham
+    R theta[] = { R(0),R(0),R(1.61e-2),R(5.38e-2),R(1.13e-1),R(1.86e-1),R(2.6429608311114350e-1) };
+
+    R scaling(1);
+    size_type p(0), m(6), opt_iters(100);
+    for (size_type k=0; k < opt_iters; ++k, scaling *= R(2)) {
+      dense_matrix<T> auxS(S);
+      for (size_type i = 0; i < n; ++i) auxS(i,i) -= R(1);
+      R tau = gmm::mat_norm1(auxS);
+      if (tau <= theta[6]) {
+        ++p;
+        size_type j1(6), j2(6);
+        for (size_type j=0; j < 6; ++j)
+          if (tau <= theta[j]) { j1 = j; break; }
+        for (size_type j=0; j < j1; ++j)
+          if (tau <= 2*theta[j]) { j2 = j; break; }
+        if (j1 - j2 <= 1 || p == 2) { m = j1; break; }
+      }
+      sqrtm_utri_inplace(S);
+      if (k == opt_iters-1)
+        GMM_WARNING1 ("Maximum number of square roots exceeded; "
+                      "the calculated matrix logarithm may still be accurate");
+    }
+
+    for (size_type i = 0; i < n; ++i) S(i,i) -= R(1);
+
+    if (m > 0) {
+
+      std::vector<R> nodes, wts;
+      switch(m) {
+      case 0: {
+        R nodes_[] = { R(0.5) };
+        R wts_[] = { R(1) };
+        nodes.assign(nodes_, nodes_+m+1);
+        wts.assign(wts_, wts_+m+1);
+        } break;
+      case 1: {
+        R nodes_[] = { R(0.211324865405187),R(0.788675134594813) };
+        R wts_[] = { R(0.5),R(0.5) };
+        nodes.assign(nodes_, nodes_+m+1);
+        wts.assign(wts_, wts_+m+1);
+        } break;
+      case 2: {
+        R nodes_[] = { R(0.112701665379258),R(0.500000000000000),R(0.887298334620742) };
+        R wts_[] = { R(0.277777777777778),R(0.444444444444444),R(0.277777777777778) };
+        nodes.assign(nodes_, nodes_+m+1);
+        wts.assign(wts_, wts_+m+1);
+        } break;
+      case 3: {
+        R nodes_[] = { R(0.0694318442029737),R(0.3300094782075718),R(0.6699905217924281),R(0.9305681557970263) };
+        R wts_[] = { R(0.173927422568727),R(0.326072577431273),R(0.326072577431273),R(0.173927422568727) };
+        nodes.assign(nodes_, nodes_+m+1);
+        wts.assign(wts_, wts_+m+1);
+        } break;
+      case 4: {
+        R nodes_[] = { R(0.0469100770306681),R(0.2307653449471584),R(0.5000000000000000),R(0.7692346550528415),R(0.9530899229693319) };
+        R wts_[] = { R(0.118463442528095),R(0.239314335249683),R(0.284444444444444),R(0.239314335249683),R(0.118463442528094) };
+        nodes.assign(nodes_, nodes_+m+1);
+        wts.assign(wts_, wts_+m+1);
+        } break;
+      case 5: {
+        R nodes_[] = { R(0.0337652428984240),R(0.1693953067668678),R(0.3806904069584015),R(0.6193095930415985),R(0.8306046932331322),R(0.9662347571015761) };
+        R wts_[] = { R(0.0856622461895853),R(0.1803807865240693),R(0.2339569672863452),R(0.2339569672863459),R(0.1803807865240693),R(0.0856622461895852) };
+        nodes.assign(nodes_, nodes_+m+1);
+        wts.assign(wts_, wts_+m+1);
+        } break;
+      case 6: {
+        R nodes_[] = { R(0.0254460438286208),R(0.1292344072003028),R(0.2970774243113015),R(0.4999999999999999),R(0.7029225756886985),R(0.8707655927996973),R(0.9745539561713792) };
+        R wts_[] = { R(0.0647424830844348),R(0.1398526957446384),R(0.1909150252525594),R(0.2089795918367343),R(0.1909150252525595),R(0.1398526957446383),R(0.0647424830844349) };
+        nodes.assign(nodes_, nodes_+m+1);
+        wts.assign(wts_, wts_+m+1);
+        } break;
+      }
+
+      dense_matrix<T> auxS1(S), auxS2(S);
+      std::vector<T> auxvec(n);
+      gmm::clear(S);
+      for (size_type j=0; j <= m; ++j) {
+        gmm::copy(gmm::scaled(auxS1, nodes[j]), auxS2);
+        gmm::add(gmm::identity_matrix(), auxS2);
+        // S += wts[i] * auxS1 * inv(auxS2)
+        for (size_type i=0; i < n; ++i) {
+          gmm::copy(gmm::mat_row(auxS1, i), auxvec);
+          gmm::lower_tri_solve(gmm::transposed(auxS2), auxvec, false);
+          gmm::add(gmm::scaled(auxvec, wts[j]), gmm::mat_row(S, i));
+        }
+      }
+    }
+    gmm::scale(S, scaling);
+  }
+
+  /**
+   Matrix logarithm (from GNU/Octave)
+  */
+  template <typename T>
+  void logm(const dense_matrix<T>& A, dense_matrix<T>& LOGMA)
+  {
+    typedef typename number_traits<T>::magnitude_type R;
+    size_type n = gmm::mat_nrows(A);
+    GMM_ASSERT1(n == gmm::mat_ncols(A),
+                "Matrix logarithm is not defined for non-square matrices");
+    dense_matrix<T> S(A), Q(A);
+    #if defined(GMM_USES_LAPACK)
+    schur(A, S, Q); // A = Q * S * Q^T
+    #else
+    GMM_ASSERT1(false, "Please recompile with lapack and blas librairies "
+                "to use logm matrix function.");
+    #endif
+
+    bool convert_to_complex(false);
+    if (!is_complex(T()))
+      for (size_type i=0; i < n-1; ++i)
+        if (gmm::abs(S(i+1,i)) > default_tol(T())) {
+          convert_to_complex = true;
+          break;
+        }
+
+    gmm::resize(LOGMA, n, n);
+    if (convert_to_complex) {
+      dense_matrix<std::complex<R> > cS(n,n), cQ(n,n), auxmat(n,n);
+      gmm::copy(gmm::real_part(S), gmm::real_part(cS));
+      gmm::copy(gmm::real_part(Q), gmm::real_part(cQ));
+      block2x2_reduction(cS, cQ, default_tol(R())*R(3));
+      for (size_type j=0; j < n-1; ++j)
+        for (size_type i=j+1; i < n; ++i)
+          cS(i,j) = T(0);
+      logm_utri_inplace(cS);
+      gmm::mult(cQ, cS, auxmat);
+      gmm::mult(auxmat, gmm::transposed(cQ), cS);
+      // Remove small complex values which may have entered calculation
+      gmm::copy(gmm::real_part(cS), LOGMA);
+//      GMM_ASSERT1(gmm::mat_norm1(gmm::imag_part(cS)) < n*default_tol(T()),
+//                  "Internal error, imag part should be zero");
+    } else {
+      dense_matrix<T> auxmat(n,n);
+      logm_utri_inplace(S);
+      gmm::mult(Q, S, auxmat);
+      gmm::mult(auxmat, gmm::transposed(Q), LOGMA);
+    }
+
+  }
+
+}
+
+#endif
+
diff --git a/contrib/gmm/gmm_dense_qr.h b/contrib/gmm/gmm_dense_qr.h
index d9effa28f1..1fcf03f566 100644
--- a/contrib/gmm/gmm_dense_qr.h
+++ b/contrib/gmm/gmm_dense_qr.h
@@ -1,32 +1,33 @@
-// -*- c++ -*- (enables emacs c++ mode)
-//===========================================================================
-//
-// Copyright (C) 2003-2008 Yves Renard
-//
-// This file is a part of GETFEM++
-//
-// Getfem++  is  free software;  you  can  redistribute  it  and/or modify it
-// under  the  terms  of the  GNU  Lesser General Public License as published
-// by  the  Free Software Foundation;  either version 2.1 of the License,  or
-// (at your option) any later version.
-// This program  is  distributed  in  the  hope  that it will be useful,  but
-// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-// or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
-// License for more details.
-// You  should  have received a copy of the GNU Lesser General Public License
-// along  with  this program;  if not, write to the Free Software Foundation,
-// Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
-//
-// As a special exception, you may use this file as part of a free software
-// library without restriction.  Specifically, if other files instantiate
-// templates or use macros or inline functions from this file, or you compile
-// this file and link it with other files to produce an executable, this
-// file does not by itself cause the resulting executable to be covered by
-// the GNU General Public License.  This exception does not however
-// invalidate any other reasons why the executable file might be covered by
-// the GNU General Public License.
-//
-//===========================================================================
+/* -*- c++ -*- (enables emacs c++ mode) */
+/*===========================================================================
+
+ Copyright (C) 2003-2020 Yves Renard
+
+ This file is a part of GetFEM
+
+ GetFEM  is  free software;  you  can  redistribute  it  and/or modify it
+ under  the  terms  of the  GNU  Lesser General Public License as published
+ by  the  Free Software Foundation;  either version 3 of the License,  or
+ (at your option) any later version along with the GCC Runtime Library
+ Exception either version 3.1 or (at your option) any later version.
+ This program  is  distributed  in  the  hope  that it will be useful,  but
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+ License and GCC Runtime Library Exception for more details.
+ You  should  have received a copy of the GNU Lesser General Public License
+ along  with  this program;  if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+
+ As a special exception, you  may use  this file  as it is a part of a free
+ software  library  without  restriction.  Specifically,  if   other  files
+ instantiate  templates  or  use macros or inline functions from this file,
+ or  you compile this  file  and  link  it  with other files  to produce an
+ executable, this file  does  not  by itself cause the resulting executable
+ to be covered  by the GNU Lesser General Public License.  This   exception
+ does not  however  invalidate  any  other  reasons why the executable file
+ might be covered by the GNU Lesser General Public License.
+
+===========================================================================*/
 
 /**@file gmm_dense_qr.h
    @author  Caroline Lecalvez, Caroline.Lecalvez@gmm.insa-tlse.fr, Yves Renard <Yves.Renard@insa-lyon.fr>
@@ -45,7 +46,7 @@ namespace gmm {
      QR factorization using Householder method (complex and real version).
   */
   template <typename MAT1>
-  void qr_factor(const MAT1 &A_) { 
+  void qr_factor(const MAT1 &A_) {
     MAT1 &A = const_cast<MAT1 &>(A_);
     typedef typename linalg_traits<MAT1>::value_type value_type;
 
@@ -66,12 +67,12 @@ namespace gmm {
     }
   }
 
-  
+
   // QR comes from QR_factor(QR) where the upper triangular part stands for R
   // and the lower part contains the Householder reflectors.
   // A <- AQ
   template <typename MAT1, typename MAT2>
-  void apply_house_right(const MAT1 &QR, const MAT2 &A_) { 
+  void apply_house_right(const MAT1 &QR, const MAT2 &A_) {
     MAT2 &A = const_cast<MAT2 &>(A_);
     typedef typename linalg_traits<MAT1>::value_type T;
     size_type m = mat_nrows(QR), n = mat_ncols(QR);
@@ -83,7 +84,7 @@ namespace gmm {
       V.resize(m-j);
       for (size_type i = j+1; i < m; ++i) V[i-j] = QR(i, j);
       col_house_update(sub_matrix(A, sub_interval(0, mat_nrows(A)),
-				  sub_interval(j, m-j)), V, W);
+                                  sub_interval(j, m-j)), V, W);
     }
   }
 
@@ -91,7 +92,7 @@ namespace gmm {
   // and the lower part contains the Householder reflectors.
   // A <- Q*A
   template <typename MAT1, typename MAT2>
-  void apply_house_left(const MAT1 &QR, const MAT2 &A_) { 
+  void apply_house_left(const MAT1 &QR, const MAT2 &A_) {
     MAT2 &A = const_cast<MAT2 &>(A_);
     typedef typename linalg_traits<MAT1>::value_type T;
     size_type m = mat_nrows(QR), n = mat_ncols(QR);
@@ -103,20 +104,20 @@ namespace gmm {
       V.resize(m-j);
       for (size_type i = j+1; i < m; ++i) V[i-j] = QR(i, j);
       row_house_update(sub_matrix(A, sub_interval(j, m-j),
-				  sub_interval(0, mat_ncols(A))), V, W);
+                                  sub_interval(0, mat_ncols(A))), V, W);
     }
-  }  
+  }
 
   /** Compute the QR factorization, where Q is assembled. */
   template <typename MAT1, typename MAT2, typename MAT3>
-    void qr_factor(const MAT1 &A, const MAT2 &QQ, const MAT3 &RR) { 
-    MAT2 &Q = const_cast<MAT2 &>(QQ); MAT3 &R = const_cast<MAT3 &>(RR); 
+    void qr_factor(const MAT1 &A, const MAT2 &QQ, const MAT3 &RR) {
+    MAT2 &Q = const_cast<MAT2 &>(QQ); MAT3 &R = const_cast<MAT3 &>(RR);
     typedef typename linalg_traits<MAT1>::value_type value_type;
 
     size_type m = mat_nrows(A), n = mat_ncols(A);
     GMM_ASSERT2(m >= n, "dimensions mismatch");
     gmm::copy(A, Q);
-    
+
     std::vector<value_type> W(m);
     dense_matrix<value_type> VV(m, n);
 
@@ -127,22 +128,22 @@ namespace gmm {
       house_vector(sub_vector(mat_col(VV,j), SUBI));
 
       row_house_update(sub_matrix(Q, SUBI, SUBJ),
-		       sub_vector(mat_col(VV,j), SUBI), sub_vector(W, SUBJ));
+                       sub_vector(mat_col(VV,j), SUBI), sub_vector(W, SUBJ));
     }
 
     gmm::copy(sub_matrix(Q, sub_interval(0, n), sub_interval(0, n)), R);
     gmm::copy(identity_matrix(), Q);
-    
+
     for (size_type j = n-1; j != size_type(-1); --j) {
       sub_interval SUBI(j, m-j), SUBJ(j, n-j);
-      row_house_update(sub_matrix(Q, SUBI, SUBJ), 
-		       sub_vector(mat_col(VV,j), SUBI), sub_vector(W, SUBJ));
+      row_house_update(sub_matrix(Q, SUBI, SUBJ),
+                       sub_vector(mat_col(VV,j), SUBI), sub_vector(W, SUBJ));
     }
   }
 
   ///@cond DOXY_SHOW_ALL_FUNCTIONS
-  template <typename TA, typename TV, typename Ttol, 
-	    typename MAT, typename VECT>
+  template <typename TA, typename TV, typename Ttol,
+            typename MAT, typename VECT>
   void extract_eig(const MAT &A, VECT &V, Ttol tol, TA, TV) {
     size_type n = mat_nrows(A);
     if (n == 0) return;
@@ -150,57 +151,57 @@ namespace gmm {
     Ttol tol_i = tol * gmm::abs(A(0,0)), tol_cplx = tol_i;
     for (size_type i = 0; i < n; ++i) {
       if (i < n-1) {
-	tol_i = (gmm::abs(A(i,i))+gmm::abs(A(i+1,i+1)))*tol;
-	tol_cplx = std::max(tol_cplx, tol_i);
+        tol_i = (gmm::abs(A(i,i))+gmm::abs(A(i+1,i+1)))*tol;
+        tol_cplx = std::max(tol_cplx, tol_i);
       }
       if ((i < n-1) && gmm::abs(A(i+1,i)) >= tol_i) {
-	TA tr = A(i,i) + A(i+1, i+1);
-	TA det = A(i,i)*A(i+1, i+1) - A(i,i+1)*A(i+1, i);
-	TA delta = tr*tr - TA(4) * det;
-	if (delta < -tol_cplx) {
-	  GMM_WARNING1("A complex eigenvalue has been detected : "
-		      << std::complex<TA>(tr/TA(2), gmm::sqrt(-delta)/TA(2)));
-	  V[i] = V[i+1] = tr / TA(2);
-	}
-	else {
-	  delta = std::max(TA(0), delta);
-	  V[i  ] = TA(tr + gmm::sqrt(delta))/ TA(2);
-	  V[i+1] = TA(tr -  gmm::sqrt(delta))/ TA(2);
-	}
-	++i;
+        TA tr = A(i,i) + A(i+1, i+1);
+        TA det = A(i,i)*A(i+1, i+1) - A(i,i+1)*A(i+1, i);
+        TA delta = tr*tr - TA(4) * det;
+        if (delta < -tol_cplx) {
+          GMM_WARNING1("A complex eigenvalue has been detected : "
+                      << std::complex<TA>(tr/TA(2), gmm::sqrt(-delta)/TA(2)));
+          V[i] = V[i+1] = tr / TA(2);
+        }
+        else {
+          delta = std::max(TA(0), delta);
+          V[i  ] = TA(tr + gmm::sqrt(delta))/ TA(2);
+          V[i+1] = TA(tr -  gmm::sqrt(delta))/ TA(2);
+        }
+        ++i;
       }
       else
-	V[i] = TV(A(i,i));
+        V[i] = TV(A(i,i));
     }
   }
 
-  template <typename TA, typename TV, typename Ttol, 
-	    typename MAT, typename VECT>
+  template <typename TA, typename TV, typename Ttol,
+            typename MAT, typename VECT>
   void extract_eig(const MAT &A, VECT &V, Ttol tol, TA, std::complex<TV>) {
     size_type n = mat_nrows(A);
     tol *= Ttol(2);
     for (size_type i = 0; i < n; ++i)
       if ((i == n-1) ||
-	  gmm::abs(A(i+1,i)) < (gmm::abs(A(i,i))+gmm::abs(A(i+1,i+1)))*tol)
-	V[i] = std::complex<TV>(A(i,i));
+          gmm::abs(A(i+1,i)) < (gmm::abs(A(i,i))+gmm::abs(A(i+1,i+1)))*tol)
+        V[i] = std::complex<TV>(A(i,i));
       else {
-	TA tr = A(i,i) + A(i+1, i+1);
-	TA det = A(i,i)*A(i+1, i+1) - A(i,i+1)*A(i+1, i);
-	TA delta = tr*tr - TA(4) * det;
-	if (delta < TA(0)) {
-	  V[i] = std::complex<TV>(tr / TA(2), gmm::sqrt(-delta) / TA(2));
-	  V[i+1] = std::complex<TV>(tr / TA(2), -gmm::sqrt(-delta)/ TA(2));
-	}
-	else {
-	  V[i  ] = TA(tr + gmm::sqrt(delta)) / TA(2);
-	  V[i+1] = TA(tr -  gmm::sqrt(delta)) / TA(2);
-	}
-	++i;
+        TA tr = A(i,i) + A(i+1, i+1);
+        TA det = A(i,i)*A(i+1, i+1) - A(i,i+1)*A(i+1, i);
+        TA delta = tr*tr - TA(4) * det;
+        if (delta < TA(0)) {
+          V[i] = std::complex<TV>(tr / TA(2), gmm::sqrt(-delta) / TA(2));
+          V[i+1] = std::complex<TV>(tr / TA(2), -gmm::sqrt(-delta)/ TA(2));
+        }
+        else {
+          V[i  ] = TA(tr + gmm::sqrt(delta)) / TA(2);
+          V[i+1] = TA(tr -  gmm::sqrt(delta)) / TA(2);
+        }
+        ++i;
       }
   }
 
   template <typename TA, typename TV, typename Ttol,
-	    typename MAT, typename VECT>
+            typename MAT, typename VECT>
   void extract_eig(const MAT &A, VECT &V, Ttol tol, std::complex<TA>, TV) {
     typedef std::complex<TA> T;
     size_type n = mat_nrows(A);
@@ -209,50 +210,50 @@ namespace gmm {
     Ttol tol_i = tol * gmm::abs(A(0,0)), tol_cplx = tol_i;
     for (size_type i = 0; i < n; ++i) {
       if (i < n-1) {
-	tol_i = (gmm::abs(A(i,i))+gmm::abs(A(i+1,i+1)))*tol;
-	tol_cplx = std::max(tol_cplx, tol_i);
+        tol_i = (gmm::abs(A(i,i))+gmm::abs(A(i+1,i+1)))*tol;
+        tol_cplx = std::max(tol_cplx, tol_i);
       }
       if ((i == n-1) || gmm::abs(A(i+1,i)) < tol_i) {
-	if (gmm::abs(std::imag(A(i,i))) > tol_cplx)
-	  GMM_WARNING1("A complex eigenvalue has been detected : "
-		      << T(A(i,i)) << " : "  << gmm::abs(std::imag(A(i,i)))
-		      / gmm::abs(std::real(A(i,i))) << " : " << tol_cplx);
-	V[i] = std::real(A(i,i));
+        if (gmm::abs(std::imag(A(i,i))) > tol_cplx)
+          GMM_WARNING1("A complex eigenvalue has been detected : "
+                      << T(A(i,i)) << " : "  << gmm::abs(std::imag(A(i,i)))
+                      / gmm::abs(std::real(A(i,i))) << " : " << tol_cplx);
+        V[i] = std::real(A(i,i));
       }
       else {
-	T tr = A(i,i) + A(i+1, i+1);
-	T det = A(i,i)*A(i+1, i+1) - A(i,i+1)*A(i+1, i);
-	T delta = tr*tr - TA(4) * det;
-	T a1 = (tr + gmm::sqrt(delta)) / TA(2);
-	T a2 = (tr - gmm::sqrt(delta)) / TA(2);
-	if (gmm::abs(std::imag(a1)) > tol_cplx)
-	  GMM_WARNING1("A complex eigenvalue has been detected : " << a1);
-	if (gmm::abs(std::imag(a2)) > tol_cplx)
-	  GMM_WARNING1("A complex eigenvalue has been detected : " << a2);
-
-	V[i] = std::real(a1); V[i+1] = std::real(a2);
-	++i;
+        T tr = A(i,i) + A(i+1, i+1);
+        T det = A(i,i)*A(i+1, i+1) - A(i,i+1)*A(i+1, i);
+        T delta = tr*tr - TA(4) * det;
+        T a1 = (tr + gmm::sqrt(delta)) / TA(2);
+        T a2 = (tr - gmm::sqrt(delta)) / TA(2);
+        if (gmm::abs(std::imag(a1)) > tol_cplx)
+          GMM_WARNING1("A complex eigenvalue has been detected : " << a1);
+        if (gmm::abs(std::imag(a2)) > tol_cplx)
+          GMM_WARNING1("A complex eigenvalue has been detected : " << a2);
+
+        V[i] = std::real(a1); V[i+1] = std::real(a2);
+        ++i;
       }
     }
   }
 
   template <typename TA, typename TV, typename Ttol,
-	    typename MAT, typename VECT>
+            typename MAT, typename VECT>
   void extract_eig(const MAT &A, VECT &V, Ttol tol,
-		   std::complex<TA>, std::complex<TV>) {
+                   std::complex<TA>, std::complex<TV>) {
     size_type n = mat_nrows(A);
     tol *= Ttol(2);
     for (size_type i = 0; i < n; ++i)
       if ((i == n-1) ||
-	  gmm::abs(A(i+1,i)) < (gmm::abs(A(i,i))+gmm::abs(A(i+1,i+1)))*tol)
-	V[i] = std::complex<TV>(A(i,i));
+          gmm::abs(A(i+1,i)) < (gmm::abs(A(i,i))+gmm::abs(A(i+1,i+1)))*tol)
+        V[i] = std::complex<TV>(A(i,i));
       else {
-	std::complex<TA> tr = A(i,i) + A(i+1, i+1);
-	std::complex<TA> det = A(i,i)*A(i+1, i+1) - A(i,i+1)*A(i+1, i);
-	std::complex<TA> delta = tr*tr - TA(4) * det;
-	V[i] = (tr + gmm::sqrt(delta)) / TA(2);
-	V[i+1] = (tr - gmm::sqrt(delta)) / TA(2);
-	++i;
+        std::complex<TA> tr = A(i,i) + A(i+1, i+1);
+        std::complex<TA> det = A(i,i)*A(i+1, i+1) - A(i,i+1)*A(i+1, i);
+        std::complex<TA> delta = tr*tr - TA(4) * det;
+        V[i] = (tr + gmm::sqrt(delta)) / TA(2);
+        V[i+1] = (tr - gmm::sqrt(delta)) / TA(2);
+        ++i;
       }
   }
 
@@ -263,8 +264,8 @@ namespace gmm {
   template <typename MAT, typename Ttol, typename VECT> inline
   void extract_eig(const MAT &A, const VECT &V, Ttol tol) {
     extract_eig(A, const_cast<VECT&>(V), tol,
-		typename linalg_traits<MAT>::value_type(),
-		typename linalg_traits<VECT>::value_type());
+                typename linalg_traits<MAT>::value_type(),
+                typename linalg_traits<VECT>::value_type());
   }
 
   /* ********************************************************************* */
@@ -280,21 +281,21 @@ namespace gmm {
     if (n <= 2) { q = n; p = 0; }
     else {
       for (size_type i = 1; i < n-q; ++i)
-	if (gmm::abs(A(i,i-1)) < (gmm::abs(A(i,i))+ gmm::abs(A(i-1,i-1)))*tol
-	    || gmm::abs(A(i,i-1)) < rmin)
-	  A(i,i-1) = T(0);
-      
+        if (gmm::abs(A(i,i-1)) < (gmm::abs(A(i,i))+ gmm::abs(A(i-1,i-1)))*tol
+            || gmm::abs(A(i,i-1)) < rmin)
+          A(i,i-1) = T(0);
+
       while ((q < n-1 && A(n-1-q, n-2-q) == T(0)) ||
-	     (q < n-2 && A(n-2-q, n-3-q) == T(0))) ++q;
+             (q < n-2 && A(n-2-q, n-3-q) == T(0))) ++q;
       if (q >= n-2) q = n;
       p = n-q; if (p) --p; if (p) --p;
       while (p > 0 && A(p,p-1) != T(0)) --p;
     }
   }
-  
+
   template <typename MAT, typename Ttol> inline
   void symmetric_qr_stop_criterion(const MAT &AA, size_type &p, size_type &q,
-				Ttol tol) {
+                                Ttol tol) {
     typedef typename linalg_traits<MAT>::value_type T;
     typedef typename number_traits<T>::magnitude_type R;
     R rmin = default_min(R()) * R(2);
@@ -303,10 +304,10 @@ namespace gmm {
     if (n <= 1) { q = n; p = 0; }
     else {
       for (size_type i = 1; i < n-q; ++i)
-	if (gmm::abs(A(i,i-1)) < (gmm::abs(A(i,i))+ gmm::abs(A(i-1,i-1)))*tol
-	    || gmm::abs(A(i,i-1)) < rmin)
-	  A(i,i-1) = T(0);
-      
+        if (gmm::abs(A(i,i-1)) < (gmm::abs(A(i,i))+ gmm::abs(A(i-1,i-1)))*tol
+            || gmm::abs(A(i,i-1)) < rmin)
+          A(i,i-1) = T(0);
+
       while (q < n-1 && A(n-1-q, n-2-q) == T(0)) ++q;
       if (q >= n-1) q = n;
       p = n-q; if (p) --p; if (p) --p;
@@ -316,7 +317,7 @@ namespace gmm {
 
   template <typename VECT1, typename VECT2, typename Ttol> inline
   void symmetric_qr_stop_criterion(const VECT1 &diag, const VECT2 &sdiag_,
-				   size_type &p, size_type &q, Ttol tol) {
+                                   size_type &p, size_type &q, Ttol tol) {
     typedef typename linalg_traits<VECT2>::value_type T;
     typedef typename number_traits<T>::magnitude_type R;
     R rmin = default_min(R()) * R(2);
@@ -325,8 +326,8 @@ namespace gmm {
     if (n <= 1) { q = n; p = 0; return; }
     for (size_type i = 1; i < n-q; ++i)
       if (gmm::abs(sdiag[i-1]) < (gmm::abs(diag[i])+ gmm::abs(diag[i-1]))*tol
-	  || gmm::abs(sdiag[i-1]) < rmin)
-	sdiag[i-1] = T(0);
+          || gmm::abs(sdiag[i-1]) < rmin)
+        sdiag[i-1] = T(0);
     while (q < n-1 && sdiag[n-2-q] == T(0)) ++q;
     if (q >= n-1) q = n;
     p = n-q; if (p) --p; if (p) --p;
@@ -343,30 +344,30 @@ namespace gmm {
     typedef typename number_traits<T>::magnitude_type R;
 
     size_type n = mat_nrows(H), nq = mat_nrows(Q);
+    if (n < 2) return;
     sub_interval SUBQ(0, nq), SUBL(0, 2);
     std::vector<T> v(2), w(std::max(n, nq)); v[0] = T(1);
-    if (n < 2) return;
     tol *= Ttol(2);
     Ttol tol_i = tol * gmm::abs(H(0,0)), tol_cplx = tol_i;
     for (size_type i = 0; i < n-1; ++i) {
       tol_i = (gmm::abs(H(i,i))+gmm::abs(H(i+1,i+1)))*tol;
       tol_cplx = std::max(tol_cplx, tol_i);
-      
+
       if (gmm::abs(H(i+1,i)) > tol_i) { // 2x2 block detected
-	T tr = (H(i+1, i+1) - H(i,i)) / T(2);
-	T delta = tr*tr + H(i,i+1)*H(i+1, i);
-	
-	if (is_complex(T()) || gmm::real(delta) >= R(0)) {
-	  sub_interval SUBI(i, 2);
-	  T theta = (tr - gmm::sqrt(delta)) / H(i+1,i);
-	  R a = gmm::abs(theta);
-	  v[1] = (a == R(0)) ? T(-1)
-	    : gmm::conj(theta) * (R(1) - gmm::sqrt(a*a + R(1)) / a);
-	  row_house_update(sub_matrix(H, SUBI), v, sub_vector(w, SUBL));
-	  col_house_update(sub_matrix(H, SUBI), v, sub_vector(w, SUBL));
-	  col_house_update(sub_matrix(Q, SUBQ, SUBI), v, sub_vector(w, SUBQ));
-	}
-	++i;
+        T tr = (H(i+1, i+1) - H(i,i)) / T(2);
+        T delta = tr*tr + H(i,i+1)*H(i+1, i);
+
+        if (is_complex(T()) || gmm::real(delta) >= R(0)) {
+          sub_interval SUBI(i, 2);
+          T theta = (tr - gmm::sqrt(delta)) / H(i+1,i);
+          R a = gmm::abs(theta);
+          v[1] = (a == R(0)) ? T(-1)
+            : gmm::conj(theta) * (R(1) - gmm::sqrt(a*a + R(1)) / a);
+          row_house_update(sub_matrix(H, SUBI), v, sub_vector(w, SUBL));
+          col_house_update(sub_matrix(H, SUBI), v, sub_vector(w, SUBL));
+          col_house_update(sub_matrix(Q, SUBQ, SUBI), v, sub_vector(w, SUBQ));
+        }
+        ++i;
       }
     }
   }
@@ -385,16 +386,16 @@ namespace gmm {
   // Very slow method. Use implicit_qr_method instead.
   template <typename MAT1, typename VECT, typename MAT2>
     void rudimentary_qr_algorithm(const MAT1 &A, const VECT &eigval_,
-				  const MAT2 &eigvect_,
-				  tol_type_for_qr tol = default_tol_for_qr,
-				  bool compvect = true) {
+                                  const MAT2 &eigvect_,
+                                  tol_type_for_qr tol = default_tol_for_qr,
+                                  bool compvect = true) {
     VECT &eigval = const_cast<VECT &>(eigval_);
     MAT2 &eigvect = const_cast<MAT2 &>(eigvect_);
 
     typedef typename linalg_traits<MAT1>::value_type value_type;
 
     size_type n = mat_nrows(A), p, q = 0, ite = 0;
-    dense_matrix<value_type> Q(n, n), R(n,n), A1(n,n); 
+    dense_matrix<value_type> Q(n, n), R(n,n), A1(n,n);
     gmm::copy(A, A1);
 
     Hessenberg_reduction(A1, eigvect, compvect);
@@ -404,20 +405,20 @@ namespace gmm {
       qr_factor(A1, Q, R);
       gmm::mult(R, Q, A1);
       if (compvect) { gmm::mult(eigvect, Q, R); gmm::copy(R, eigvect); }
-      
+
       qr_stop_criterion(A1, p, q, tol);
       ++ite;
       GMM_ASSERT1(ite < n*1000, "QR algorithm failed");
     }
     if (compvect) block2x2_reduction(A1, Q, tol);
-    extract_eig(A1, eigval, tol); 
+    extract_eig(A1, eigval, tol);
   }
 
   template <typename MAT1, typename VECT>
     void rudimentary_qr_algorithm(const MAT1 &a, VECT &eigval,
-				  tol_type_for_qr tol = default_tol_for_qr) {
+                                  tol_type_for_qr tol = default_tol_for_qr) {
     dense_matrix<typename linalg_traits<MAT1>::value_type> m(0,0);
-    rudimentary_qr_algorithm(a, eigval, m, tol, false); 
+    rudimentary_qr_algorithm(a, eigval, m, tol, false);
   }
 
   /* ********************************************************************* */
@@ -428,8 +429,8 @@ namespace gmm {
     void Francis_qr_step(const MAT1& HH, const MAT2 &QQ, bool compute_Q) {
     MAT1& H = const_cast<MAT1&>(HH); MAT2& Q = const_cast<MAT2&>(QQ);
     typedef typename linalg_traits<MAT1>::value_type value_type;
-    size_type n = mat_nrows(H), nq = mat_nrows(Q); 
-    
+    size_type n = mat_nrows(H), nq = mat_nrows(Q);
+
     std::vector<value_type> v(3), w(std::max(n, nq));
 
     value_type s = H(n-2, n-2) + H(n-1, n-1);
@@ -445,12 +446,12 @@ namespace gmm {
       house_vector(v);
       size_type r = std::min(k+4, n), q = (k==0) ? 0 : k-1;
       sub_interval SUBI(k, 3), SUBJ(0, r), SUBK(q, n-q);
-      
+
       row_house_update(sub_matrix(H, SUBI, SUBK),  v, sub_vector(w, SUBK));
       col_house_update(sub_matrix(H, SUBJ, SUBI),  v, sub_vector(w, SUBJ));
-      
+
       if (compute_Q)
-       	col_house_update(sub_matrix(Q, SUBQ, SUBI),  v, sub_vector(w, SUBQ));
+        col_house_update(sub_matrix(Q, SUBQ, SUBI),  v, sub_vector(w, SUBQ));
 
       x = H(k+1, k); y = H(k+2, k);
       if (k < n-3) z = H(k+3, k);
@@ -471,7 +472,7 @@ namespace gmm {
 
   template <typename MAT1, typename MAT2, typename Ttol>
   void Wilkinson_double_shift_qr_step(const MAT1& HH, const MAT2 &QQ,
-				      Ttol tol, bool exc, bool compute_Q) {
+                                      Ttol tol, bool exc, bool compute_Q) {
     MAT1& H = const_cast<MAT1&>(HH); MAT2& Q = const_cast<MAT2&>(QQ);
     typedef typename linalg_traits<MAT1>::value_type T;
     typedef typename number_traits<T>::magnitude_type R;
@@ -480,7 +481,7 @@ namespace gmm {
     std::vector<T> v(3), w(std::max(n, nq));
     const R dat1(0.75), dat2(-0.4375);
     T h33, h44, h43h34, v1(0), v2(0), v3(0);
-    
+
     if (exc) {                    /* Exceptional shift.                    */
       R s = gmm::abs(H(n-1, n-2)) + gmm::abs(H(n-2, n-3));
       h33 = h44 = dat1 * s;
@@ -517,13 +518,13 @@ namespace gmm {
       house_vector(v);
       size_type r = std::min(k+4, n), q = (k==0) ? 0 : k-1;
       sub_interval SUBI(k, 3), SUBJ(0, r), SUBK(q, n-q);
-      
+
       row_house_update(sub_matrix(H, SUBI, SUBK),  v, sub_vector(w, SUBK));
       col_house_update(sub_matrix(H, SUBJ, SUBI),  v, sub_vector(w, SUBJ));
       if (k > m-1) { H(k+1, k-1) = T(0); if (k < n-3) H(k+2, k-1) = T(0); }
-      
+
       if (compute_Q)
-       	col_house_update(sub_matrix(Q, SUBQ, SUBI),  v, sub_vector(w, SUBQ));
+        col_house_update(sub_matrix(Q, SUBQ, SUBI),  v, sub_vector(w, SUBQ));
 
       v1 = H(k+1, k); v2 = H(k+2, k);
       if (k < n-3) v3 = H(k+3, k);
@@ -543,13 +544,13 @@ namespace gmm {
 
   // QR method for real or complex square matrices based on an
   // implicit QR factorisation. eigval has to be a complex vector
-  // if A has complex eigeinvalues. complexity about 10n^3, 25n^3 if
+  // if A has complex eigenvalues. Complexity about 10n^3, 25n^3 if
   // eigenvectors are computed
   template <typename MAT1, typename VECT, typename MAT2>
     void implicit_qr_algorithm(const MAT1 &A, const VECT &eigval_,
-			       const MAT2 &Q_, 
-			       tol_type_for_qr tol = default_tol_for_qr,
-			       bool compvect = true) {
+                               const MAT2 &Q_,
+                               tol_type_for_qr tol = default_tol_for_qr,
+                               bool compvect = true) {
     VECT &eigval = const_cast<VECT &>(eigval_);
     MAT2 &Q = const_cast<MAT2 &>(Q_);
     typedef typename linalg_traits<MAT1>::value_type value_type;
@@ -561,15 +562,15 @@ namespace gmm {
     gmm::copy(A, H);
     Hessenberg_reduction(H, Q, compvect);
     qr_stop_criterion(H, p, q, tol);
-    
+
     while (q < n) {
       sub_interval SUBI(p, n-p-q), SUBJ(0, mat_ncols(Q));
       if (compvect) SUBK = SUBI;
 //       Francis_qr_step(sub_matrix(H, SUBI),
-// 		      sub_matrix(Q, SUBJ, SUBK), compvect);
-      Wilkinson_double_shift_qr_step(sub_matrix(H, SUBI), 
-				     sub_matrix(Q, SUBJ, SUBK),
-				     tol, (its == 10 || its == 20), compvect);
+//                       sub_matrix(Q, SUBJ, SUBK), compvect);
+      Wilkinson_double_shift_qr_step(sub_matrix(H, SUBI),
+                                     sub_matrix(Q, SUBJ, SUBK),
+                                     tol, (its == 10 || its == 20), compvect);
       q_old = q;
       qr_stop_criterion(H, p, q, tol*2);
       if (q != q_old) its = 0;
@@ -583,18 +584,18 @@ namespace gmm {
 
   template <typename MAT1, typename VECT>
     void implicit_qr_algorithm(const MAT1 &a, VECT &eigval,
-			       tol_type_for_qr tol = default_tol_for_qr) {
-    dense_matrix<typename linalg_traits<MAT1>::value_type> m(0,0);
-    implicit_qr_algorithm(a, eigval, m, tol, false); 
+                               tol_type_for_qr tol = default_tol_for_qr) {
+    dense_matrix<typename linalg_traits<MAT1>::value_type> m(1,1);
+    implicit_qr_algorithm(a, eigval, m, tol, false);
   }
 
   /* ********************************************************************* */
   /*    Implicit symmetric QR step with Wilkinson Shift.                   */
   /* ********************************************************************* */
 
-  template <typename MAT1, typename MAT2> 
+  template <typename MAT1, typename MAT2>
     void symmetric_Wilkinson_qr_step(const MAT1& MM, const MAT2 &ZZ,
-				     bool compute_z) {
+                                     bool compute_z) {
     MAT1& M = const_cast<MAT1&>(MM); MAT2& Z = const_cast<MAT2&>(ZZ);
     typedef typename linalg_traits<MAT1>::value_type T;
     typedef typename number_traits<T>::magnitude_type R;
@@ -603,8 +604,8 @@ namespace gmm {
     for (size_type i = 0; i < n; ++i) {
       M(i, i) = T(gmm::real(M(i, i)));
       if (i > 0) {
-	T a = (M(i, i-1) + gmm::conj(M(i-1, i)))/R(2);
-	M(i, i-1) = a; M(i-1, i) = gmm::conj(a);
+        T a = (M(i, i-1) + gmm::conj(M(i-1, i)))/R(2);
+        M(i, i-1) = a; M(i-1, i) = gmm::conj(a);
       }
     }
 
@@ -633,9 +634,9 @@ namespace gmm {
 
   }
 
-  template <typename VECT1, typename VECT2, typename MAT> 
+  template <typename VECT1, typename VECT2, typename MAT>
   void symmetric_Wilkinson_qr_step(const VECT1& diag_, const VECT2& sdiag_,
-				   const MAT &ZZ, bool compute_z) {
+                                   const MAT &ZZ, bool compute_z) {
     VECT1& diag = const_cast<VECT1&>(diag_);
     VECT2& sdiag = const_cast<VECT2&>(sdiag_);
     MAT& Z = const_cast<MAT&>(ZZ);
@@ -682,8 +683,8 @@ namespace gmm {
       a20 = a31; a21 = a32; a31 = T(0);
 
       if (k < n-1) {
-	sdiag[k] = (gmm::conj(a23) + a32) / R(2);
-	a22 = T(diag[k+1]); a32 = sdiag[k+1]; a23 = gmm::conj(a32);
+        sdiag[k] = (gmm::conj(a23) + a32) / R(2);
+        a22 = T(diag[k+1]); a32 = sdiag[k+1]; a23 = gmm::conj(a32);
       }
     }
   }
@@ -698,9 +699,9 @@ namespace gmm {
   // complexity about 4n^3/3, 9n^3 if eigenvectors are computed
   template <typename MAT1, typename VECT, typename MAT2>
   void symmetric_qr_algorithm_old(const MAT1 &A, const VECT &eigval_,
-			      const MAT2 &eigvect_,
-			      tol_type_for_qr tol = default_tol_for_qr,
-			      bool compvect = true) {
+                              const MAT2 &eigvect_,
+                              tol_type_for_qr tol = default_tol_for_qr,
+                              bool compvect = true) {
     VECT &eigval = const_cast<VECT &>(eigval_);
     MAT2 &eigvect = const_cast<MAT2 &>(eigvect_);
     typedef typename linalg_traits<MAT1>::value_type T;
@@ -712,30 +713,30 @@ namespace gmm {
     gmm::copy(A, Tri);
 
     Householder_tridiagonalization(Tri, eigvect, compvect);
-    
+
     symmetric_qr_stop_criterion(Tri, p, q, tol);
-    
+
     while (q < n) {
 
       sub_interval SUBI(p, n-p-q), SUBJ(0, mat_ncols(eigvect)), SUBK(p, n-p-q);
       if (!compvect) SUBK = sub_interval(0,0);
-      symmetric_Wilkinson_qr_step(sub_matrix(Tri, SUBI), 
-				  sub_matrix(eigvect, SUBJ, SUBK), compvect);
-      
+      symmetric_Wilkinson_qr_step(sub_matrix(Tri, SUBI),
+                                  sub_matrix(eigvect, SUBJ, SUBK), compvect);
+
       symmetric_qr_stop_criterion(Tri, p, q, tol*R(2));
       ++ite;
       GMM_ASSERT1(ite < n*100, "QR algorithm failed. Probably, your matrix"
-		  " is not real symmetric or complex hermitian");
+                  " is not real symmetric or complex hermitian");
     }
-    
+
     extract_eig(Tri, eigval, tol);
   }
 
   template <typename MAT1, typename VECT, typename MAT2>
   void symmetric_qr_algorithm(const MAT1 &A, const VECT &eigval_,
-			      const MAT2 &eigvect_,
-			      tol_type_for_qr tol = default_tol_for_qr,
-			      bool compvect = true) {
+                              const MAT2 &eigvect_,
+                              tol_type_for_qr tol = default_tol_for_qr,
+                              bool compvect = true) {
     VECT &eigval = const_cast<VECT &>(eigval_);
     MAT2 &eigvect = const_cast<MAT2 &>(eigvect_);
     typedef typename linalg_traits<MAT1>::value_type T;
@@ -754,29 +755,29 @@ namespace gmm {
     std::vector<T> sdiag(n);
     for (size_type i = 0; i < n; ++i)
       { diag[i] = gmm::real(Tri(i, i)); if (i+1 < n) sdiag[i] = Tri(i+1, i); }
-    
+
     symmetric_qr_stop_criterion(diag, sdiag, p, q, tol);
-    
+
     while (q < n) {
       sub_interval SUBI(p, n-p-q), SUBJ(0, mat_ncols(eigvect)), SUBK(p, n-p-q);
       if (!compvect) SUBK = sub_interval(0,0);
-      
+
       symmetric_Wilkinson_qr_step(sub_vector(diag, SUBI),
-				  sub_vector(sdiag, SUBI),
-				  sub_matrix(eigvect, SUBJ, SUBK), compvect);
+                                  sub_vector(sdiag, SUBI),
+                                  sub_matrix(eigvect, SUBJ, SUBK), compvect);
 
-      symmetric_qr_stop_criterion(diag, sdiag, p, q, tol*R(2));
+      symmetric_qr_stop_criterion(diag, sdiag, p, q, tol*R(3));
       ++ite;
       GMM_ASSERT1(ite < n*100, "QR algorithm failed.");
     }
-    
+
     gmm::copy(diag, eigval);
   }
 
 
   template <typename MAT1, typename VECT>
     void symmetric_qr_algorithm(const MAT1 &a, VECT &eigval,
-				tol_type_for_qr tol = default_tol_for_qr) {
+                                tol_type_for_qr tol = default_tol_for_qr) {
     dense_matrix<typename linalg_traits<MAT1>::value_type> m(0,0);
     symmetric_qr_algorithm(a, eigval, m, tol, false);
   }
diff --git a/contrib/gmm/gmm_dense_sylvester.h b/contrib/gmm/gmm_dense_sylvester.h
index 5a4c8fa46b..88c9724d31 100644
--- a/contrib/gmm/gmm_dense_sylvester.h
+++ b/contrib/gmm/gmm_dense_sylvester.h
@@ -1,32 +1,33 @@
-// -*- c++ -*- (enables emacs c++ mode)
-//===========================================================================
-//
-// Copyright (C) 2003-2008 Yves Renard
-//
-// This file is a part of GETFEM++
-//
-// Getfem++  is  free software;  you  can  redistribute  it  and/or modify it
-// under  the  terms  of the  GNU  Lesser General Public License as published
-// by  the  Free Software Foundation;  either version 2.1 of the License,  or
-// (at your option) any later version.
-// This program  is  distributed  in  the  hope  that it will be useful,  but
-// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-// or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
-// License for more details.
-// You  should  have received a copy of the GNU Lesser General Public License
-// along  with  this program;  if not, write to the Free Software Foundation,
-// Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
-//
-// As a special exception, you may use this file as part of a free software
-// library without restriction.  Specifically, if other files instantiate
-// templates or use macros or inline functions from this file, or you compile
-// this file and link it with other files to produce an executable, this
-// file does not by itself cause the resulting executable to be covered by
-// the GNU General Public License.  This exception does not however
-// invalidate any other reasons why the executable file might be covered by
-// the GNU General Public License.
-//
-//===========================================================================
+/* -*- c++ -*- (enables emacs c++ mode) */
+/*===========================================================================
+
+ Copyright (C) 2003-2020 Yves Renard
+
+ This file is a part of GetFEM
+
+ GetFEM  is  free software;  you  can  redistribute  it  and/or modify it
+ under  the  terms  of the  GNU  Lesser General Public License as published
+ by  the  Free Software Foundation;  either version 3 of the License,  or
+ (at your option) any later version along with the GCC Runtime Library
+ Exception either version 3.1 or (at your option) any later version.
+ This program  is  distributed  in  the  hope  that it will be useful,  but
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+ License and GCC Runtime Library Exception for more details.
+ You  should  have received a copy of the GNU Lesser General Public License
+ along  with  this program;  if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+
+ As a special exception, you  may use  this file  as it is a part of a free
+ software  library  without  restriction.  Specifically,  if   other  files
+ instantiate  templates  or  use macros or inline functions from this file,
+ or  you compile this  file  and  link  it  with other files  to produce an
+ executable, this file  does  not  by itself cause the resulting executable
+ to be covered  by the GNU Lesser General Public License.  This   exception
+ does not  however  invalidate  any  other  reasons why the executable file
+ might be covered by the GNU Lesser General Public License.
+
+===========================================================================*/
 
 /** @file gmm_dense_sylvester.h
     @author  Yves Renard <Yves.Renard@insa-lyon.fr>
diff --git a/contrib/gmm/gmm_domain_decomp.h b/contrib/gmm/gmm_domain_decomp.h
index 674296004a..9bf663a214 100644
--- a/contrib/gmm/gmm_domain_decomp.h
+++ b/contrib/gmm/gmm_domain_decomp.h
@@ -1,32 +1,33 @@
-// -*- c++ -*- (enables emacs c++ mode)
-//===========================================================================
-//
-// Copyright (C) 2004-2008 Yves Renard
-//
-// This file is a part of GETFEM++
-//
-// Getfem++  is  free software;  you  can  redistribute  it  and/or modify it
-// under  the  terms  of the  GNU  Lesser General Public License as published
-// by  the  Free Software Foundation;  either version 2.1 of the License,  or
-// (at your option) any later version.
-// This program  is  distributed  in  the  hope  that it will be useful,  but
-// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-// or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
-// License for more details.
-// You  should  have received a copy of the GNU Lesser General Public License
-// along  with  this program;  if not, write to the Free Software Foundation,
-// Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
-//
-// As a special exception, you may use this file as part of a free software
-// library without restriction.  Specifically, if other files instantiate
-// templates or use macros or inline functions from this file, or you compile
-// this file and link it with other files to produce an executable, this
-// file does not by itself cause the resulting executable to be covered by
-// the GNU General Public License.  This exception does not however
-// invalidate any other reasons why the executable file might be covered by
-// the GNU General Public License.
-//
-//===========================================================================
+/* -*- c++ -*- (enables emacs c++ mode) */
+/*===========================================================================
+
+ Copyright (C) 2004-2020 Yves Renard
+
+ This file is a part of GetFEM
+
+ GetFEM  is  free software;  you  can  redistribute  it  and/or modify it
+ under  the  terms  of the  GNU  Lesser General Public License as published
+ by  the  Free Software Foundation;  either version 3 of the License,  or
+ (at your option) any later version along with the GCC Runtime Library
+ Exception either version 3.1 or (at your option) any later version.
+ This program  is  distributed  in  the  hope  that it will be useful,  but
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+ License and GCC Runtime Library Exception for more details.
+ You  should  have received a copy of the GNU Lesser General Public License
+ along  with  this program;  if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+
+ As a special exception, you  may use  this file  as it is a part of a free
+ software  library  without  restriction.  Specifically,  if   other  files
+ instantiate  templates  or  use macros or inline functions from this file,
+ or  you compile this  file  and  link  it  with other files  to produce an
+ executable, this file  does  not  by itself cause the resulting executable
+ to be covered  by the GNU Lesser General Public License.  This   exception
+ does not  however  invalidate  any  other  reasons why the executable file
+ might be covered by the GNU Lesser General Public License.
+
+===========================================================================*/
 
 /** @file gmm_domain_decomp.h
    @author  Yves Renard <Yves.Renard@insa-lyon.fr>
@@ -66,7 +67,7 @@ namespace gmm {
 	pmin[k] = std::min(pmin[k], pts[i][k]);
 	pmax[k] = std::max(pmax[k], pts[i][k]);
       }
-
+    
     std::vector<size_type> nbsub(dim), mult(dim);
     std::vector<int> pts1(dim), pts2(dim);
     size_type nbtotsub = 1;
@@ -74,15 +75,15 @@ namespace gmm {
       nbsub[k] = size_type((pmax[k] - pmin[k]) / msize)+1;
       mult[k] = nbtotsub; nbtotsub *= nbsub[k];
     }
-
+    
     std::vector<map_type> subs(nbtotsub);
     // points ventilation
     std::vector<size_type> ns(dim), na(dim), nu(dim);
     for (size_type i = 0; i < nbpts; ++i) {
       for (int k = 0; k < dim; ++k) {
-	double a = (pts[i][k] - pmin[k]) / msize;
-	ns[k] = size_type(a) - 1; na[k] = 0;
-	pts1[k] = int(a + overlap); pts2[k] = int(ceil(a-1.0-overlap));
+          double a = (pts[i][k] - pmin[k]) / msize;
+          ns[k] = size_type(a) - 1; na[k] = 0;
+          pts1[k] = int(a + overlap); pts2[k] = int(ceil(a-1.0-overlap));
       }
       size_type sum = 0;
       do {
@@ -105,19 +106,19 @@ namespace gmm {
     size_type nbmaxinsub = 0;
     for (size_type i = 0; i < nbtotsub; ++i)
       nbmaxinsub = std::max(nbmaxinsub, subs[i].size());
-
+    
     std::fill(ns.begin(), ns.end(), size_type(0));
     for (size_type i = 0; i < nbtotsub; ++i) {
       if (subs[i].size() > 0 && subs[i].size() < nbmaxinsub / 10) {
-
+	
 	for (int k = 0; k < dim; ++k) nu[k] = ns[k];
 	size_type nbmax = 0, imax = 0;
-
+	
 	for (int l = 0; l < dim; ++l) {
 	  nu[l]--;
 	  for (int m = 0; m < 2; ++m, nu[l]+=2) {
 	    bool ok = true;
-	    for (int k = 0; k < dim && ok; ++k)
+	    for (int k = 0; k < dim && ok; ++k) 
 	      if (nu[k] >= nbsub[k]) ok = false;
 	    if (ok) {
 	      size_type ind = ns[0];
@@ -128,7 +129,7 @@ namespace gmm {
 	  }
 	  nu[l]--;
 	}
-
+	
 	if (nbmax > subs[i].size()) {
 	  for (map_type::iterator it=subs[i].begin(); it!=subs[i].end(); ++it)
 	    subs[imax][it->first] = void_type();
@@ -138,7 +139,7 @@ namespace gmm {
       for (int k = 0; k < dim; ++k)
 	{ ns[k]++; if (ns[k] < nbsub[k]) break; ns[k] = 0; }
     }
-
+    
     // delete empty domains.
     size_type effnb = 0;
     for (size_type i = 0; i < nbtotsub; ++i) {
@@ -156,7 +157,7 @@ namespace gmm {
 	vB[i](it->first, j) = value_type(1);
     }
   }
-
+  
 
 }
 
diff --git a/contrib/gmm/gmm_except.h b/contrib/gmm/gmm_except.h
index 022ec28cd4..3b38aa16d3 100644
--- a/contrib/gmm/gmm_except.h
+++ b/contrib/gmm/gmm_except.h
@@ -1,32 +1,33 @@
-// -*- c++ -*- (enables emacs c++ mode)
-//===========================================================================
-//
-// Copyright (C) 2002-2008 Yves Renard
-//
-// This file is a part of GETFEM++
-//
-// Getfem++  is  free software;  you  can  redistribute  it  and/or modify it
-// under  the  terms  of the  GNU  Lesser General Public License as published
-// by  the  Free Software Foundation;  either version 2.1 of the License,  or
-// (at your option) any later version.
-// This program  is  distributed  in  the  hope  that it will be useful,  but
-// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-// or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
-// License for more details.
-// You  should  have received a copy of the GNU Lesser General Public License
-// along  with  this program;  if not, write to the Free Software Foundation,
-// Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
-//
-// As a special exception, you may use this file as part of a free software
-// library without restriction.  Specifically, if other files instantiate
-// templates or use macros or inline functions from this file, or you compile
-// this file and link it with other files to produce an executable, this
-// file does not by itself cause the resulting executable to be covered by
-// the GNU General Public License.  This exception does not however
-// invalidate any other reasons why the executable file might be covered by
-// the GNU General Public License.
-//
-//===========================================================================
+/* -*- c++ -*- (enables emacs c++ mode) */
+/*===========================================================================
+
+ Copyright (C) 2002-2020 Yves Renard
+
+ This file is a part of GetFEM
+
+ GetFEM  is  free software;  you  can  redistribute  it  and/or modify it
+ under  the  terms  of the  GNU  Lesser General Public License as published
+ by  the  Free Software Foundation;  either version 3 of the License,  or
+ (at your option) any later version along with the GCC Runtime Library
+ Exception either version 3.1 or (at your option) any later version.
+ This program  is  distributed  in  the  hope  that it will be useful,  but
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+ License and GCC Runtime Library Exception for more details.
+ You  should  have received a copy of the GNU Lesser General Public License
+ along  with  this program;  if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+
+ As a special exception, you  may use  this file  as it is a part of a free
+ software  library  without  restriction.  Specifically,  if   other  files
+ instantiate  templates  or  use macros or inline functions from this file,
+ or  you compile this  file  and  link  it  with other files  to produce an
+ executable, this file  does  not  by itself cause the resulting executable
+ to be covered  by the GNU Lesser General Public License.  This   exception
+ does not  however  invalidate  any  other  reasons why the executable file
+ might be covered by the GNU Lesser General Public License.
+
+===========================================================================*/
 
 /** @file gmm_except.h
     @author Yves Renard <Yves.Renard@insa-lyon.fr>
@@ -38,25 +39,39 @@
 #ifndef GMM_EXCEPT_H__
 #define GMM_EXCEPT_H__
 
+#include <sstream>
 #include "gmm_std.h"
+#include "gmm_feedback_management.h"
+
+
+//provides external implementation of gmm_exception and logging.
 
 namespace gmm {
 
 /* *********************************************************************** */
-/*	Getfem++ generic errors.                     			   */
+/*        GetFEM generic errors.                                         */
 /* *********************************************************************** */
 
+  // std logic_error with error level information
   class gmm_error: public std::logic_error {
   public:
-    gmm_error(const std::string& what_arg): std::logic_error (what_arg) {}
+    gmm_error(const std::string& what_arg, int errorLevel = 1):
+      std::logic_error (what_arg), errorLevel_(errorLevel) {}
+    int errLevel() const { return errorLevel_; }
+
+  private:
+    int errorLevel_;
   };
 
 #ifdef GETFEM_HAVE_PRETTY_FUNCTION
 #  define GMM_PRETTY_FUNCTION __PRETTY_FUNCTION__
-#else
+#elif _MSC_VER
+#  define GMM_PRETTY_FUNCTION __FUNCTION__
+#else 
 #  define GMM_PRETTY_FUNCTION ""
 #endif
 
+
   // Errors : GMM_THROW should not be used on its own.
   //          GMM_ASSERT1 : Non-maskable errors. Typically for in/ouput and
   //               when the test do not significantly reduces the performance.
@@ -65,77 +80,105 @@ namespace gmm {
   //               defined.
   //          GMM_ASSERT3 : For internal checks. Hidden by default. Active
   //               only when DEBUG_MODE is defined.
-
-#ifdef __EXCEPTIONS
+  // __EXCEPTIONS is defined by gcc, _CPPUNWIND is defined by visual c++
+#if defined(__EXCEPTIONS) || defined(_CPPUNWIND)
   inline void short_error_throw(const char *file, int line, const char *func,
-				const char *errormsg) {
-    std::stringstream msg;
-    msg << "Error in " << file << ", line " << line << " " << func
-	<< ": \n" << errormsg << ends;
-    throw gmm::gmm_error(msg.str());
+                                const char *errormsg) {
+    std::stringstream msg__;
+    msg__ << "Error in " << file << ", line " << line << " " << func
+          << ": \n" << errormsg << std::ends;
+    throw gmm::gmm_error(msg__.str());
   }
-# define GMM_THROW_(type, errormsg) {					\
-    std::stringstream msg;						\
-    msg << "Error in " << __FILE__ << ", line "				\
-	<< __LINE__ << " " << GMM_PRETTY_FUNCTION << ": \n"		\
-	<< errormsg << ends;						\
-    throw (type)(msg.str());						\
+# define GMM_THROW_(type, errormsg) {                         \
+    std::stringstream msg__;                                  \
+    msg__ << "Error in " << __FILE__ << ", line "             \
+          << __LINE__ << " " << GMM_PRETTY_FUNCTION << ": \n" \
+          << errormsg << std::ends;                           \
+    throw (type)(msg__.str());                                \
   }
+
+# define GMM_THROW_AT_LEVEL(errormsg, level)                  \
+  {                                                           \
+  std::stringstream msg;                                      \
+  msg << "Error in " << __FILE__ << ", line "                 \
+  << __LINE__ << " " << GMM_PRETTY_FUNCTION << ": \n"         \
+  << errormsg << std::ends;                                   \
+  throw gmm::gmm_error(msg.str(), level);                     \
+  }
+
 #else
+#ifndef _MSC_VER
+# define abort_no_return() ::abort()
+#else
+// apparently ::abort() on windows is not declared with __declspec(noreturn) so the compiler spits a lot of warnings when abort is used.
+# define abort_no_return() { assert("GMM ABORT"==0); throw "GMM ABORT"; }
+#endif
+
   inline void short_error_throw(const char *file, int line, const char *func,
-				const char *errormsg) {
-    std::stringstream msg;
-    msg << "Error in " << file << ", line " << line << " " << func
-	<< ": \n" << errormsg << ends;
-    ::abort();
+                                const char *errormsg) {
+    std::stringstream msg__;
+    msg__ << "Error in " << file << ", line " << line << " " << func
+          << ": \n" << errormsg << std::ends;
+    std::cerr << msg__.str() << std::endl;
+    abort_no_return();
   }
-# define GMM_THROW_(type, errormsg) {					\
-    std::stringstream msg;						\
-    msg << "Error in " << __FILE__ << ", line "				\
-	<< __LINE__ << " " << GMM_PRETTY_FUNCTION << ": \n"		\
-	<< errormsg   << ends;						\
-    ::abort();								\
+
+# define GMM_THROW_(type, errormsg) {                         \
+    std::stringstream msg__;                                  \
+    msg__ << "Error in " << __FILE__ << ", line "             \
+          << __LINE__ << " " << GMM_PRETTY_FUNCTION << ": \n" \
+          << errormsg;                                        \
+    std::cerr << msg__.str() << std::endl;                    \
+    abort_no_return();                                        \
+  }
+
+# define GMM_THROW_AT_LEVEL(errormsg, level)                  \
+  {                                                           \
+  std::stringstream msg__;                                    \
+  msg__ << "Error in " << __FILE__ << ", line "               \
+  << __LINE__ << " " << GMM_PRETTY_FUNCTION << ": \n"         \
+  << errormsg <<  " at level " << level;                      \
+  std::cerr << msg__.str()  << std::endl;                     \
+  abort_no_return();                                          \
   }
 #endif
 
-# define GMM_ASSERT1(test, errormsg)		        		\
-  { if (!(test)) GMM_THROW_(gmm::gmm_error, errormsg); }
 
-  // inline void GMM_THROW() IS_DEPRECATED;
-  inline void GMM_THROW() {}
+inline void GMM_THROW() {}
 #define GMM_THROW(a, b) { GMM_THROW_(a,b); gmm::GMM_THROW(); }
 
+# define GMM_THROW_DEFAULT(errormsg) GMM_THROW_AT_LEVEL(errormsg, 1)
+
+// This allows not to compile some assertions 
+#ifndef GMM_ASSERT_LEVEL
 #if defined(NDEBUG)
-# define GMM_ASSERT2(test, errormsg)
-# define GMM_ASSERT3(test, errormsg)
-#elif !defined(GMM_FULL_NDEBUG)
-# define GMM_ASSERT2(test, errormsg)				        \
-  { if (!(test)) gmm::short_error_throw(__FILE__, __LINE__,		\
-				   GMM_PRETTY_FUNCTION, errormsg); }
-# define GMM_ASSERT3(test, errormsg)				        \
-  { if (!(test)) gmm::short_error_throw(__FILE__, __LINE__,		\
-				   GMM_PRETTY_FUNCTION, errormsg); }
+# define GMM_ASSERT_LEVEL 1
+#elif defined(DEBUG_MODE)
+# define GMM_ASSERT_LEVEL 3
 #else
-# define GMM_ASSERT2(test, errormsg)          				\
-  { if (!(test)) gmm::short_error_throw(__FILE__, __LINE__,		\
-				   GMM_PRETTY_FUNCTION, errormsg); }
-# define GMM_ASSERT3(test, errormsg)
+# define GMM_ASSERT_LEVEL 2
+#endif
 #endif
 
-/* *********************************************************************** */
-/*	Getfem++ warnings.                         			   */
-/* *********************************************************************** */
 
-  // This allows to dynamically hide warnings
-  struct warning_level {
-    static int level(int l = -2)
-    { static int level_ = 3; return (l != -2) ? (level_ = l) : level_; }
-  };
+# define GMM_ASSERT1(test, errormsg) { if (!(test)) GMM_THROW_AT_LEVEL(errormsg, 1); }
 
-  inline void set_warning_level(int l) { warning_level::level(std::max(0,l)); }
-  inline int  get_warning_level(void)  { return warning_level::level(-2); }
+#if GMM_ASSERT_LEVEL < 2
+# define GMM_ASSERT2(test, errormsg) {}
+# define GMM_ASSERT3(test, errormsg) {}
+#elif GMM_ASSERT_LEVEL < 3
+# define GMM_ASSERT2(test, errormsg){ if (!(test)) GMM_THROW_AT_LEVEL(errormsg, 2); }
+# define GMM_ASSERT3(test, errormsg){}
+#else
+# define GMM_ASSERT2(test, errormsg){ if (!(test)) GMM_THROW_AT_LEVEL(errormsg, 2); }
+# define GMM_ASSERT3(test, errormsg){ if (!(test)) GMM_THROW_AT_LEVEL(errormsg, 3); }
+#endif
 
-  // This allow not too compile some Warnings
+/* *********************************************************************** */
+/*        GetFEM warnings.                                               */
+/* *********************************************************************** */
+
+  // This allows not to compile some Warnings
 #ifndef GMM_WARNING_LEVEL
 # define GMM_WARNING_LEVEL 4
 #endif
@@ -146,58 +189,51 @@ namespace gmm {
   //                  3 remark
   //                  4 ignored by default.
 
-#define GMM_WARNING_MSG(level_, thestr)  {			       \
-      std::stringstream msg;                                           \
-      msg << "Level " << level_ << " Warning in " << __FILE__ << ", line " \
-          << __LINE__ << ": " << thestr << ends;		       \
-       std::cerr << msg.str() << std::endl;                            \
-    }
+#define GMM_WARNING_MSG(level_, thestr)  {                                                \
+  std::stringstream msg__;                                                                \
+  msg__ << "Level " << level_ << " Warning in " << __FILE__ << ", line "                  \
+  << __LINE__ << ": " << thestr;                                                          \
+  gmm::feedback_manager::manage()->send(msg__.str(), gmm::FeedbackType::WARNING, level_); \
+}
 
 #define GMM_WARNING0(thestr) GMM_WARNING_MSG(0, thestr)
 
+
 #if GMM_WARNING_LEVEL > 0
 # define GMM_WARNING1(thestr)                                           \
-  { if (1 <= gmm::warning_level::level()) GMM_WARNING_MSG(1, thestr) }
+  { if (1 <= gmm::feedback_manager::warning_level()) GMM_WARNING_MSG(1, thestr) }
 #else
 # define GMM_WARNING1(thestr) {}
 #endif
 
 #if GMM_WARNING_LEVEL > 1
 # define GMM_WARNING2(thestr)                                           \
-  { if (2 <= gmm::warning_level::level()) GMM_WARNING_MSG(2, thestr) }
+  { if (2 <= gmm::feedback_manager::warning_level()) GMM_WARNING_MSG(2, thestr) }
 #else
-# define GMM_WARNING1(thestr) {}
+# define GMM_WARNING2(thestr) {}
 #endif
 
 #if GMM_WARNING_LEVEL > 2
 # define GMM_WARNING3(thestr)                                           \
-  { if (3 <= gmm::warning_level::level()) GMM_WARNING_MSG(3, thestr) }
+  { if (3 <= gmm::feedback_manager::warning_level()) GMM_WARNING_MSG(3, thestr) }
 #else
-# define GMM_WARNING1(thestr) {}
+# define GMM_WARNING3(thestr) {}
 #endif
 
 #if GMM_WARNING_LEVEL > 3
 # define GMM_WARNING4(thestr)                                           \
-  { if (4 <= gmm::warning_level::level()) GMM_WARNING_MSG(4, thestr) }
+  { if (4 <= gmm::feedback_manager::warning_level()) GMM_WARNING_MSG(4, thestr) }
 #else
-# define GMM_WARNING1(thestr) {}
+# define GMM_WARNING4(thestr) {}
 #endif
 
 /* *********************************************************************** */
-/*	Getfem++ traces.                         			   */
+/*        GetFEM traces.                                                 */
 /* *********************************************************************** */
 
-  // This allows to dynamically hide traces
-  struct traces_level {
-    static int level(int l = -2)
-    { static int level_ = 3; return (l != -2) ? (level_ = l) : level_; }
-  };
-
-  inline void set_traces_level(int l) { traces_level::level(std::max(0,l)); }
-
   // This allow not too compile some Warnings
 #ifndef GMM_TRACES_LEVEL
-# define GMM_TRACES_LEVEL 3
+# define GMM_TRACES_LEVEL 4
 #endif
 
   // Traces levels : 0 always printed
@@ -207,127 +243,164 @@ namespace gmm {
   //                 4 Susceptible to occur very often (>1000).
 
 #define GMM_TRACE_MSG_MPI     // for Parallelized version
-#define GMM_TRACE_MSG(level_, thestr)  {			       \
-    GMM_TRACE_MSG_MPI {						       \
-      std::stringstream msg;                                           \
-      msg << "Trace " << level_ << " in " << __FILE__ << ", line "      \
-          << __LINE__ << ": " << thestr				       \
-          << ends;						       \
-      std::cout << msg.str() << std::endl;			       \
-    }                                                                  \
-  }
+#define GMM_TRACE_MSG(level_, thestr)  {                                        \
+  GMM_TRACE_MSG_MPI {                                                           \
+    std::stringstream msg__;                                                    \
+    msg__ << "Trace " << level_ << " in " << __FILE__ << ", line "              \
+          << __LINE__ << ": " << thestr;                                        \
+    gmm::feedback_manager::send(msg__.str(), gmm::FeedbackType::TRACE, level_); \
+  }                                                                             \
+}
+
+#define GMM_TRACE_SIMPLE_MSG(level_, thestr)  {                               \
+  GMM_TRACE_MSG_MPI {                                                         \
+  std::stringstream msg__;                                                    \
+  msg__ << "Trace " << level_ << ": " << thestr;                              \
+  gmm::feedback_manager::send(msg__.str(), gmm::FeedbackType::TRACE, level_); \
+  }                                                                           \
+}
 
 #define GMM_TRACE0(thestr) GMM_TRACE_MSG(0, thestr)
+#define GMM_SIMPLE_TRACE0(thestr) GMM_TRACE_MSG_SIMPLE(0, thestr)
 
 #if GMM_TRACES_LEVEL > 0
-# define GMM_TRACE1(thestr)						\
-  { if (1 <= gmm::traces_level::level()) GMM_TRACE_MSG(1, thestr) }
+# define GMM_TRACE1(thestr)                                                          \
+  { if (1 <= gmm::feedback_manager::traces_level()) GMM_TRACE_MSG(1, thestr) }
+# define GMM_SIMPLE_TRACE1(thestr)                                                  \
+  { if (1 <= gmm::feedback_manager::traces_level()) GMM_TRACE_SIMPLE_MSG(1, thestr) }
 #else
 # define GMM_TRACE1(thestr) {}
+# define GMM_SIMPLE_TRACE1(thestr) {}
 #endif
 
 #if GMM_TRACES_LEVEL > 1
-# define GMM_TRACE2(thestr)						\
-  { if (2 <= gmm::traces_level::level()) GMM_TRACE_MSG(2, thestr) }
+# define GMM_TRACE2(thestr)                                                           \
+  { if (2 <= gmm::feedback_manager::traces_level()) GMM_TRACE_MSG(2, thestr) }
+# define GMM_SIMPLE_TRACE2(thestr)                                                   \
+  { if (2 <= gmm::feedback_manager::traces_level()) GMM_TRACE_SIMPLE_MSG(2, thestr) }
 #else
 # define GMM_TRACE2(thestr) {}
+# define GMM_SIMPLE_TRACE2(thestr) {}
 #endif
 
 #if GMM_TRACES_LEVEL > 2
-# define GMM_TRACE3(thestr)						\
-  { if (3 <= gmm::traces_level::level()) GMM_TRACE_MSG(3, thestr) }
+# define GMM_TRACE3(thestr)                                                        \
+  { if (3 <= gmm::feedback_manager::traces_level()) GMM_TRACE_MSG(3, thestr) }
+# define GMM_SIMPLE_TRACE3(thestr)                                                \
+  { if (3 <= gmm::feedback_manager::traces_level()) GMM_TRACE_SIMPLE_MSG(3, thestr) }
 #else
 # define GMM_TRACE3(thestr) {}
+# define GMM_SIMPLE_TRACE3(thestr) {}
 #endif
 
 #if GMM_TRACES_LEVEL > 3
-# define GMM_TRACE4(thestr)						\
-  { if (4 <= gmm::traces_level::level()) GMM_TRACE_MSG(4, thestr) }
+# define GMM_TRACE4(thestr)                                                         \
+  { if (4 <= gmm::feedback_manager::traces_level()) GMM_TRACE_MSG(4, thestr) }
+# define GMM_SIMPLE_TRACE4(thestr)                                                 \
+  { if (4 <= gmm::feedback_manager::traces_level()) GMM_TRACE_SIMPLE_MSG(4, thestr) }
 #else
 # define GMM_TRACE4(thestr) {}
+# define GMM_SIMPLE_TRACE4(thestr) {}
 #endif
 
-
-  /* ********************************************************************* */
-  /*    Definitions for compatibility with old versions.        	   */
-  /* ********************************************************************* */
-
-  using std::invalid_argument;
-
-  struct dimension_error : public std::logic_error
-  { dimension_error(const std::string& w): std::logic_error(w) {} };
-  struct file_not_found_error : public std::logic_error
-  { file_not_found_error(const std::string& w): std::logic_error (w) {} };
-  struct internal_error : public std::logic_error
-  { internal_error(const std::string& w): std::logic_error(w) {} };
-  struct failure_error : public std::logic_error
-  { failure_error(const std::string& w): std::logic_error (w) {} };
-  struct not_linear_error : public std::logic_error
-  { not_linear_error(const std::string& w): std::logic_error (w) {} };
-  struct to_be_done_error : public std::logic_error
-  { to_be_done_error(const std::string& w): std::logic_error (w) {} };
-
-#define GMM_STANDARD_CATCH_ERROR   catch(std::logic_error e)	\
-    {								\
-      cerr << "============================================\n";	\
-      cerr << "|      An error has been detected !!!      |\n";	\
-      cerr << "============================================\n";	\
-      cerr << e.what() << endl << endl;				\
-      exit(1);							\
-    }								\
-  catch(std::runtime_error e)					\
-    {								\
-      cerr << "============================================\n";	\
-      cerr << "|      An error has been detected !!!      |\n";	\
-      cerr << "============================================\n";	\
-      cerr << e.what() << endl << endl;				\
-      exit(1);							\
-    }								\
-  catch(std::bad_alloc) {					\
-    cerr << "============================================\n";	\
-    cerr << "|  A bad allocation has been detected !!!  |\n";	\
-    cerr << "============================================\n";	\
-    exit(1);							\
-  }								\
-  catch(std::bad_typeid) {					\
-    cerr << "============================================\n";	\
-    cerr << "|  A bad typeid     has been detected !!!  |\n";	\
-    cerr << "============================================\n";	\
-    exit(1);							\
-  }								\
-  catch(std::bad_exception) {					\
-    cerr << "============================================\n";	\
-    cerr << "|  A bad exception  has been detected !!!  |\n";	\
-    cerr << "============================================\n";	\
-    exit(1);							\
-  }								\
-  catch(std::bad_cast) {					\
-    cerr << "============================================\n";	\
-    cerr << "|    A bad cast  has been detected !!!     |\n";	\
-    cerr << "============================================\n";	\
-    exit(1);							\
-  }								\
-  catch(...) {							\
-    cerr << "============================================\n";	\
-    cerr << "|  An unknown error has been detected !!!  |\n";	\
-    cerr << "============================================\n";	\
-    exit(1);							\
+#define GMM_STANDARD_CATCH_ERROR                                           \
+  catch(const gmm::gmm_error &e)                                           \
+  {                                                                        \
+    std::stringstream strStream;                                           \
+    strStream << "============================================\n";         \
+    strStream << "|    A GMM error has been detected !!!     |\n";         \
+    strStream << "============================================\n";         \
+    strStream << e.what() << std::endl << std::endl;                       \
+    gmm::feedback_manager::send(strStream.str(),                           \
+                               gmm::FeedbackType::ASSERT, e.errLevel());   \
+    gmm::feedback_manager::terminating_action();                           \
+  }                                                                        \
+  catch(const std::logic_error &e)                                         \
+  {                                                                        \
+    std::stringstream strStream;                                           \
+    strStream << "============================================\n";         \
+    strStream << "|       An error has been detected !!!     |\n";         \
+    strStream << "============================================\n";         \
+    strStream << e.what() << std::endl << std::endl;                       \
+    gmm::feedback_manager::send(strStream.str(),                           \
+                               gmm::FeedbackType::ASSERT, 0);              \
+    gmm::feedback_manager::terminating_action();                           \
+  }                                                                        \
+  catch(const std::runtime_error &e)                                       \
+  {                                                                        \
+    std::stringstream strStream;                                           \
+    strStream << "============================================\n";         \
+    strStream << "| A runtime error has been detected !!!    |\n";         \
+    strStream << "============================================\n";         \
+    strStream << e.what() << std::endl << std::endl;                       \
+    gmm::feedback_manager::send(strStream.str(),                           \
+                               gmm::FeedbackType::ASSERT, 0);              \
+    gmm::feedback_manager::terminating_action();                           \
+  }                                                                        \
+  catch(const std::bad_alloc &)                                            \
+  {                                                                        \
+    std::stringstream strStream;                                           \
+    strStream << "============================================\n";         \
+    strStream << "| A bad allocation has been detected !!!   |\n";         \
+    strStream << "============================================\n";         \
+    gmm::feedback_manager::send(strStream.str(),                           \
+                               gmm::FeedbackType::ASSERT, 0);              \
+    gmm::feedback_manager::terminating_action();                           \
+  }                                                                        \
+  catch(const std::bad_typeid &)                                           \
+  {                                                                        \
+    std::stringstream strStream;                                           \
+    strStream << "============================================\n";         \
+    strStream << "|  A bad typeid has been detected !!!      |\n";         \
+    strStream << "============================================\n";         \
+    gmm::feedback_manager::send(strStream.str(),                           \
+                               gmm::FeedbackType::ASSERT, 0);              \
+    gmm::feedback_manager::terminating_action();                           \
+  }                                                                        \
+  catch(const std::bad_exception &)                                        \
+  {                                                                        \
+    std::stringstream strStream;                                           \
+    strStream << "============================================\n";         \
+    strStream << "|  A bad exception has been detected !!!   |\n";         \
+    strStream << "============================================\n";         \
+    gmm::feedback_manager::send(strStream.str(),                           \
+                               gmm::FeedbackType::ASSERT, 0);              \
+    gmm::feedback_manager::terminating_action();                           \
+  }                                                                        \
+  catch(const std::bad_cast &)                                             \
+  {                                                                        \
+    std::stringstream strStream;                                           \
+    strStream << "============================================\n";         \
+    strStream << "|      A bad_cast has been detected !!!    |\n";         \
+    strStream << "============================================\n";         \
+    gmm::feedback_manager::send(strStream.str(),                           \
+                               gmm::FeedbackType::ASSERT, 0);              \
+    gmm::feedback_manager::terminating_action();                           \
+  }                                                                        \
+  catch(...)                                                               \
+  {                                                                        \
+    std::stringstream strStream;                                           \
+    strStream << "============================================\n";         \
+    strStream << "|  An unknown error has been detected !!!  |\n";         \
+    strStream << "============================================\n";         \
+    gmm::feedback_manager::send(strStream.str(),                           \
+                               gmm::FeedbackType::ASSERT, 0);              \
+    gmm::feedback_manager::terminating_action();                           \
   }
   //   catch(ios_base::failure) {
-  //     cerr << "============================================\n";
-  //     cerr << "| A ios_base::failure has been detected !!!|\n";
-  //     cerr << "============================================\n";
+  //     std::cerr << "============================================\n";
+  //     std::cerr << "| A ios_base::failure has been detected !!!|\n";
+  //     std::cerr << "============================================\n";
   //     exit(1);
   //   }
 
 #if defined(__GNUC__) && (__GNUC__ > 3)
-# define GMM_SET_EXCEPTION_DEBUG				\
+# define GMM_SET_EXCEPTION_DEBUG                                \
   std::set_terminate(__gnu_cxx::__verbose_terminate_handler);
 #else
 # define GMM_SET_EXCEPTION_DEBUG
 #endif
 
-}
-
+} // namespace gmm
 
 #endif /* GMM_EXCEPT_H__ */
diff --git a/contrib/gmm/gmm_feedback_management.h b/contrib/gmm/gmm_feedback_management.h
new file mode 100644
index 0000000000..d2b1396121
--- /dev/null
+++ b/contrib/gmm/gmm_feedback_management.h
@@ -0,0 +1,174 @@
+/* -*- c++ -*- (enables emacs c++ mode) */
+/*===========================================================================
+
+ Copyright (C) 2002-2020 Yves Renard
+
+ This file is a part of GetFEM
+
+ GetFEM  is  free software;  you  can  redistribute  it  and/or modify it
+ under  the  terms  of the  GNU  Lesser General Public License as published
+ by  the  Free Software Foundation;  either version 3 of the License,  or
+ (at your option) any later version along with the GCC Runtime Library
+ Exception either version 3.1 or (at your option) any later version.
+ This program  is  distributed  in  the  hope  that it will be useful,  but
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+ License and GCC Runtime Library Exception for more details.
+ You  should  have received a copy of the GNU Lesser General Public License
+ along  with  this program;  if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+
+ As a special exception, you  may use  this file  as it is a part of a free
+ software  library  without  restriction.  Specifically,  if   other  files
+ instantiate  templates  or  use macros or inline functions from this file,
+ or  you compile this  file  and  link  it  with other files  to produce an
+ executable, this file  does  not  by itself cause the resulting executable
+ to be covered  by the GNU Lesser General Public License.  This   exception
+ does not  however  invalidate  any  other  reasons why the executable file
+ might be covered by the GNU Lesser General Public License.
+
+===========================================================================*/
+
+/** @file gmm_feedback_management.h
+    @date July 03, 2017.
+    @brief Support for run time management of trace, warning and assert
+           feedback.
+*/
+
+#ifndef GMM_FEEDBACK_MANAGEMENT_H__
+#define GMM_FEEDBACK_MANAGEMENT_H__
+#include <iostream>
+#include <string>
+#include <memory>
+
+namespace gmm {
+
+/* *********************************************************************** */
+/*	GetFEM warnings.                         			   */
+/* *********************************************************************** */
+
+// This allows to dynamically hide warnings
+struct warning_level {
+  static int level(int l = -2)
+  { static int level_ = 3; return (l != -2) ? (level_ = l) : level_; }
+};
+
+inline void set_warning_level(int l) { warning_level::level(l>0 ? l : 0); }
+inline int  get_warning_level(void)  { return warning_level::level(-2); }
+
+/* *********************************************************************** */
+/*	GetFEM traces.                         			   */
+/* *********************************************************************** */
+
+// This allows to dynamically hide traces
+struct traces_level {
+  static int level(int l = -2)
+  { static int level_ = 3; return (l != -2) ? (level_ = l) : level_; }
+};
+
+inline void set_traces_level(int l) { traces_level::level(l>0 ? l : 0); }
+inline int  get_traces_level(void)  { return traces_level::level(); }
+
+
+/* *********************************************************************** */
+/*	GetFEM feedback management                  			   */
+/* *********************************************************************** */
+
+enum class FeedbackType {
+  TRACE = 0,
+  WARNING,
+  ASSERT
+};
+
+// Abstract class providing feedback management interface.
+// The interface consist of three functions:
+//   * for sending feedback message
+//   * for getting traces level
+//   * for getting warning level
+//   * for action to be done after feedback is handled
+struct base_feedback_handler {
+  virtual ~base_feedback_handler() = default;
+  virtual void send(const std::string &message, FeedbackType messageType, size_t level) = 0;
+  virtual size_t traces_level() { return get_traces_level(); }
+  virtual size_t warning_level() { return get_warning_level(); }
+  virtual void terminating_action() = 0;
+};
+
+
+// Provides the default implementation of feedback handling.
+struct default_feedback_handler final : public base_feedback_handler {
+  void send(const std::string &message, FeedbackType, size_t) override {
+    std::cerr << message << std::endl;
+  }
+  void terminating_action() override {
+    std::exit(1);
+  }
+};
+
+// This class acts as a run-time dispatcher for sending feedback
+// messages and getting trace and warning levels.
+class feedback_manager {
+public:
+    // Management actions
+    enum Action {
+       SET,      // Sets the feedback handler, releasing the one previously set.
+       GET,      // Returns currently managed handler (it is still managed).
+       REPLACE,  // Replace manager with a new one, stop managing the old one
+                 // and returns it unmanaged to the caller. The caller is
+                 // then responsible for managing the memory of the handler.
+    };
+
+    // Steals the pointer to a messenger object that provides
+    // feedback handling implementation.
+    //
+    // Example:
+    //   feedback_manager::manage(new default_feedback_handler);
+    //
+    static base_feedback_handler* manage(enum Action action=GET, base_feedback_handler *pHandler=nullptr);
+    static void send(const std::string &message, FeedbackType type, size_t level);
+    static size_t traces_level();
+    static size_t warning_level();
+    // Action to be taken when feedback handling is done
+    static void terminating_action();
+};
+
+// Depending on action either gets, sets or replaces feedback handler. Setting handler to null resets
+// it to gmm::default_feedback_handler.
+inline base_feedback_handler* feedback_manager::manage(enum Action action, base_feedback_handler *pHandler) {
+  static std::unique_ptr<base_feedback_handler> pHandler_ =
+    std::unique_ptr<base_feedback_handler>(new default_feedback_handler);
+  base_feedback_handler *rethandler = nullptr;
+  switch(action) {
+    case SET:
+      pHandler_.reset(pHandler != nullptr ? pHandler : new default_feedback_handler);
+      rethandler =  pHandler_.get();
+      break;
+    case GET:
+      rethandler = pHandler_.get();
+      break;
+    case REPLACE:
+      rethandler = pHandler_.release();
+      pHandler_.reset(pHandler != nullptr ? pHandler : new default_feedback_handler);
+      break;
+  }
+  return rethandler;
+}
+
+inline void feedback_manager::send(const std::string &message, FeedbackType type, size_t level) {
+  feedback_manager::manage()->send(message, type, level);
+}
+
+inline void feedback_manager::terminating_action() {
+  feedback_manager::manage()->terminating_action();
+}
+
+inline size_t feedback_manager::traces_level() {
+  return feedback_manager::manage()->traces_level();
+}
+
+inline size_t feedback_manager::warning_level() {
+  return feedback_manager::manage()->warning_level();
+}
+
+} // namespace gmm
+#endif /* GMM_FEEDBACK_MANAGEMENT_H__ */
diff --git a/contrib/gmm/gmm_inoutput.h b/contrib/gmm/gmm_inoutput.h
index b6f907a2e4..9bb51713ee 100644
--- a/contrib/gmm/gmm_inoutput.h
+++ b/contrib/gmm/gmm_inoutput.h
@@ -1,32 +1,33 @@
-// -*- c++ -*- (enables emacs c++ mode)
-//===========================================================================
-//
-// Copyright (C) 2003-2008 Yves Renard
-//
-// This file is a part of GETFEM++
-//
-// Getfem++  is  free software;  you  can  redistribute  it  and/or modify it
-// under  the  terms  of the  GNU  Lesser General Public License as published
-// by  the  Free Software Foundation;  either version 2.1 of the License,  or
-// (at your option) any later version.
-// This program  is  distributed  in  the  hope  that it will be useful,  but
-// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-// or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
-// License for more details.
-// You  should  have received a copy of the GNU Lesser General Public License
-// along  with  this program;  if not, write to the Free Software Foundation,
-// Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
-//
-// As a special exception, you may use this file as part of a free software
-// library without restriction.  Specifically, if other files instantiate
-// templates or use macros or inline functions from this file, or you compile
-// this file and link it with other files to produce an executable, this
-// file does not by itself cause the resulting executable to be covered by
-// the GNU General Public License.  This exception does not however
-// invalidate any other reasons why the executable file might be covered by
-// the GNU General Public License.
-//
-//===========================================================================
+/* -*- c++ -*- (enables emacs c++ mode) */
+/*===========================================================================
+
+ Copyright (C) 2003-2020 Yves Renard, Julien Pommier
+
+ This file is a part of GetFEM
+
+ GetFEM  is  free software;  you  can  redistribute  it  and/or modify it
+ under  the  terms  of the  GNU  Lesser General Public License as published
+ by  the  Free Software Foundation;  either version 3 of the License,  or
+ (at your option) any later version along with the GCC Runtime Library
+ Exception either version 3.1 or (at your option) any later version.
+ This program  is  distributed  in  the  hope  that it will be useful,  but
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+ License and GCC Runtime Library Exception for more details.
+ You  should  have received a copy of the GNU Lesser General Public License
+ along  with  this program;  if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+
+ As a special exception, you  may use  this file  as it is a part of a free
+ software  library  without  restriction.  Specifically,  if   other  files
+ instantiate  templates  or  use macros or inline functions from this file,
+ or  you compile this  file  and  link  it  with other files  to produce an
+ executable, this file  does  not  by itself cause the resulting executable
+ to be covered  by the GNU Lesser General Public License.  This   exception
+ does not  however  invalidate  any  other  reasons why the executable file
+ might be covered by the GNU Lesser General Public License.
+
+===========================================================================*/
 
 /**@file gmm_inoutput.h
    @author Yves Renard <Yves.Renard@insa-lyon.fr>
@@ -50,10 +51,10 @@ namespace gmm {
   /*************************************************************************/
 
   // Fri Aug 15 16:29:47 EDT 1997
-  //
+  // 
   //                      Harwell-Boeing File I/O in C
   //                               V. 1.0
-  //
+  // 
   //          National Institute of Standards and Technology, MD.
   //                            K.A. Remington
   // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
@@ -66,8 +67,8 @@ namespace gmm {
   // supporting documentation.
   //
   // Neither the Author nor the Institution (National Institute of Standards
-  // and Technology) make any representations about the suitability of this
-  // software for any purpose. This software is provided "as is" without
+  // and Technology) make any representations about the suitability of this 
+  // software for any purpose. This software is provided "as is" without 
   // expressed or implied warranty.
   // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
@@ -84,7 +85,7 @@ namespace gmm {
     }
     return *width;
   }
-
+  
   inline int ParseRfmt(const char *fmt, int* perline, int* width,
 		       int* prec, int* flag) {
     char p;
@@ -108,7 +109,7 @@ namespace gmm {
     *flag = p;
     return *width;
   }
-
+      
   /** matrix input/output for Harwell-Boeing format */
   struct HarwellBoeing_IO {
     int nrows() const { return Nrow; }
@@ -123,17 +124,17 @@ namespace gmm {
     /** open filename and reads header */
     void open(const char *filename);
     /** read the opened file */
-    template <typename T, int shift> void read(csc_matrix<T, shift>& A);
+    template <typename T, typename IND_TYPE, int shift> void read(csc_matrix<T, IND_TYPE, shift>& A);
     template <typename MAT> void read(MAT &M) IS_DEPRECATED;
-    template <typename T, int shift>
-    static void write(const char *filename, const csc_matrix<T, shift>& A);
-    template <typename T, int shift>
-    static void write(const char *filename, const csc_matrix<T, shift>& A,
+    template <typename T, typename IND_TYPE, int shift>
+    static void write(const char *filename, const csc_matrix<T, IND_TYPE, shift>& A);
+    template <typename T, typename IND_TYPE, int shift>
+    static void write(const char *filename, const csc_matrix<T, IND_TYPE, shift>& A,
 		      const std::vector<T> &rhs);
-    template <typename T, typename INDI, typename INDJ, int shift>
+    template <typename T, typename INDI, typename INDJ, int shift> 
     static void write(const char *filename,
 		      const csc_matrix_ref<T*, INDI*, INDJ*, shift>& A);
-    template <typename T, typename INDI, typename INDJ, int shift>
+    template <typename T, typename INDI, typename INDJ, int shift> 
     static void write(const char *filename,
 		      const csc_matrix_ref<T*, INDI*, INDJ*, shift>& A,
 		      const std::vector<T> &rhs);
@@ -146,21 +147,22 @@ namespace gmm {
     char Title[73], Key[9], Rhstype[4], Type[4];
     int Nrow, Ncol, Nnzero, Nrhs;
     char Ptrfmt[17], Indfmt[17], Valfmt[21], Rhsfmt[21];
-    int Ptrcrd, Indcrd, Valcrd, Rhscrd;
+    int Ptrcrd, Indcrd, Valcrd, Rhscrd; 
     int lcount;
 
 
     void close() { if (f) fclose(f); clear(); }
-    void clear() {
+    void clear() { 
       Nrow = Ncol = Nnzero = Nrhs = 0; f = 0; lcount = 0;
-      memset(Type, 0, sizeof Type);
-      memset(Key, 0, sizeof Key);
-      memset(Title, 0, sizeof Title);
+      memset(Type, 0, sizeof Type); 
+      memset(Key, 0, sizeof Key); 
+      memset(Title, 0, sizeof Title); 
     }
-    char *getline(char *buf) {
-      if(fgets(buf, BUFSIZ, f) == NULL) return buf; ++lcount;
+    char *getline(char *buf) { 
+      char *p = fgets(buf, BUFSIZ, f); ++lcount;
       int s = SECURE_NONCHAR_SSCANF(buf,"%*s");
-      GMM_ASSERT1(s >= 0, "blank line in HB file at line " << lcount);
+      GMM_ASSERT1(s >= 0 && p != 0,
+		  "blank line in HB file at line " << lcount);
       return buf;
     }
 
@@ -173,19 +175,19 @@ namespace gmm {
       SECURE_STRNCPY(s, 100, p, len); s[len] = 0;
       if ( Valflag != 'F' && !strchr(s,'E')) {
 	/* insert a char prefix for exp */
-	int last = strlen(s);
+	int last = int(strlen(s));
 	for (int j=last+1;j>=0;j--) {
 	  s[j] = s[j-1];
 	  if ( s[j] == '+' || s[j] == '-' ) {
-	    s[j-1] = Valflag;
+	    s[j-1] = char(Valflag);                    
 	    break;
 	  }
 	}
       }
       return atof(s);
     }
-    template <typename IND_TYPE>
-    int readHB_data(IND_TYPE colptr[], IND_TYPE rowind[],
+    template <typename IND_TYPE>   
+    int readHB_data(IND_TYPE colptr[], IND_TYPE rowind[], 
 		    double val[]) {
       /***********************************************************************/
       /*  This function opens and reads the specified file, interpreting its */
@@ -208,8 +210,10 @@ namespace gmm {
       int i,ind,col,offset,count;
       int Ptrperline, Ptrwidth, Indperline, Indwidth;
       int Valperline, Valwidth, Valprec, Nentries;
-      int Valflag;           /* Indicates 'E','D', or 'F' float format */
+      int Valflag = 'D';           /* Indicates 'E','D', or 'F' float format */
       char line[BUFSIZ];
+      gmm::standard_locale sl;
+
 
       /*  Parse the array input formats from Line 3 of HB file  */
       ParseIfmt(Ptrfmt,&Ptrperline,&Ptrwidth);
@@ -217,13 +221,11 @@ namespace gmm {
       if ( Type[0] != 'P' ) {          /* Skip if pattern only  */
 	ParseRfmt(Valfmt,&Valperline,&Valwidth,&Valprec,&Valflag);
       }
-
-      cout << "Valwidth = " << Valwidth << endl; getchar();
-
+    
       /*  Read column pointer array:   */
       offset = 0;         /* if base 0 storage is declared (via macro def),  */
       /* then storage entries are offset by 1            */
-
+    
       for (count = 0, i=0;i<Ptrcrd;i++) {
 	getline(line);
 	for (col = 0, ind = 0;ind<Ptrperline;ind++) {
@@ -232,8 +234,8 @@ namespace gmm {
 	  count++; col += Ptrwidth;
 	}
       }
-
-      /*  Read row index array:  */
+    
+      /*  Read row index array:  */    
       for (count = 0, i=0;i<Indcrd;i++) {
 	getline(line);
 	for (col = 0, ind = 0;ind<Indperline;ind++) {
@@ -242,12 +244,12 @@ namespace gmm {
 	  count++; col += Indwidth;
 	}
       }
-
+    
       /*  Read array of values:  */
       if ( Type[0] != 'P' ) {          /* Skip if pattern only  */
 	if ( Type[0] == 'C' ) Nentries = 2*Nnzero;
 	else Nentries = Nnzero;
-
+      
 	count = 0;
 	for (i=0;i<Valcrd;i++) {
 	  getline(line);
@@ -266,7 +268,7 @@ namespace gmm {
       return 1;
     }
   };
-
+  
   inline void HarwellBoeing_IO::open(const char *filename) {
     int Totcrd,Neltvl,Nrhsix;
     char line[BUFSIZ];
@@ -284,7 +286,7 @@ namespace gmm {
     Totcrd = Ptrcrd = Indcrd = Valcrd = Rhscrd = 0;
     SECURE_NONCHAR_SSCANF(getline(line), "%d%d%d%d%d", &Totcrd, &Ptrcrd,
 			  &Indcrd, &Valcrd, &Rhscrd);
-
+    
     /* Third line: */
     Nrow = Ncol = Nnzero = Neltvl = 0;
 #ifdef GMM_SECURE_CRT
@@ -295,8 +297,8 @@ namespace gmm {
 	       &Neltvl) < 1)
 #endif
       IOHBTerminate("Invalid Type info, line 3 of Harwell-Boeing file.\n");
-    for (size_type i = 0; i < 3; ++i) Type[i] = toupper(Type[i]);
-
+    for (size_type i = 0; i < 3; ++i) Type[i] = char(toupper(Type[i]));
+    
       /*  Fourth line:  */
 #ifdef GMM_SECURE_CRT
     if ( sscanf_s(getline(line), "%c%c%c%c",Ptrfmt, 16,Indfmt, 16,Valfmt,
@@ -305,11 +307,11 @@ namespace gmm {
     if ( sscanf(getline(line), "%16c%16c%20c%20c",Ptrfmt,Indfmt,Valfmt,
 		Rhsfmt) < 3)
 #endif
-      IOHBTerminate("Invalid format info, line 4 of Harwell-Boeing file.\n");
+      IOHBTerminate("Invalid format info, line 4 of Harwell-Boeing file.\n"); 
     Ptrfmt[16] = Indfmt[16] = Valfmt[20] = Rhsfmt[20] = 0;
-
+    
     /*  (Optional) Fifth line: */
-    if (Rhscrd != 0 ) {
+    if (Rhscrd != 0 ) { 
       Nrhs = Nrhsix = 0;
 #ifdef GMM_SECURE_CRT
       if ( sscanf_s(getline(line), "%c%d%d", Rhstype, 3, &Nrhs, &Nrhsix) != 1)
@@ -322,10 +324,10 @@ namespace gmm {
   }
 
   /* only valid for double and complex<double> csc matrices */
-  template <typename T, int shift> void
-  HarwellBoeing_IO::read(csc_matrix<T, shift>& A) {
+  template <typename T, typename IND_TYPE, int shift> void
+  HarwellBoeing_IO::read(csc_matrix<T, IND_TYPE, shift>& A) {
 
-    typedef typename csc_matrix<T, shift>::IND_TYPE IND_TYPE;
+    // typedef typename csc_matrix<T, shift>::IND_TYPE IND_TYPE;
 
     GMM_ASSERT1(f, "no file opened!");
     GMM_ASSERT1(Type[0] != 'P',
@@ -334,33 +336,31 @@ namespace gmm {
 		"Bad HB matrix format (file contains a REAL matrix)");
     GMM_ASSERT1(is_complex_double__(T()) || Type[0] != 'C',
 		"Bad HB matrix format (file contains a COMPLEX matrix)");
-    if (A.pr) { delete[] A.pr; delete[] A.ir; delete[] A.jc; }
     A.nc = ncols(); A.nr = nrows();
-    A.pr = 0;
-    A.jc = new IND_TYPE[ncols()+1];
-    A.ir = new IND_TYPE[nnz()];
-    A.pr = new T[nnz()];
-    readHB_data(A.jc, A.ir, (double*)A.pr);
+    A.jc.resize(ncols()+1);
+    A.ir.resize(nnz());
+    A.pr.resize(nnz());
+    readHB_data(&A.jc[0], &A.ir[0], (double*)&A.pr[0]);
     for (int i = 0; i <= ncols(); ++i) { A.jc[i] += shift; A.jc[i] -= 1; }
     for (int i = 0; i < nnz(); ++i)    { A.ir[i] += shift; A.ir[i] -= 1; }
   }
 
-  template <typename MAT> void
+  template <typename MAT> void 
   HarwellBoeing_IO::read(MAT &M) {
     csc_matrix<typename gmm::linalg_traits<MAT>::value_type> csc;
-    read(csc);
+    read(csc); 
     resize(M, mat_nrows(csc), mat_ncols(csc));
     copy(csc, M);
   }
-
-  template <typename IND_TYPE>
+  
+  template <typename IND_TYPE> 
   inline int writeHB_mat_double(const char* filename, int M, int N, int nz,
 				const IND_TYPE colptr[],
-				const IND_TYPE rowind[],
+				const IND_TYPE rowind[], 
 				const double val[], int Nrhs,
 				const double rhs[], const double guess[],
 				const double exact[], const char* Title,
-				const char* Key, const char* Type,
+				const char* Key, const char* Type, 
 				const char* Ptrfmt, const char* Indfmt,
 				const char* Valfmt, const char* Rhsfmt,
 				const char* Rhstype, int shift) {
@@ -382,34 +382,38 @@ namespace gmm {
     int Valperline, Valwidth, Valprec;
     int Valflag;           /* Indicates 'E','D', or 'F' float format */
     char pformat[16],iformat[16],vformat[19],rformat[19];
-
+    //    char *pValflag, *pRhsflag;
+    gmm::standard_locale sl;
+    
     if ( Type[0] == 'C' )
       { nvalentries = 2*nz; nrhsentries = 2*M; }
     else
       { nvalentries = nz; nrhsentries = M; }
-
+    
     if ( filename != NULL ) {
       SECURE_FOPEN(&out_file, filename, "w");
       GMM_ASSERT1(out_file != NULL, "Error: Cannot open file: " << filename);
     } else out_file = stdout;
-
+    
     if ( Ptrfmt == NULL ) Ptrfmt = "(8I10)";
     ParseIfmt(Ptrfmt, &Ptrperline, &Ptrwidth);
     SECURE_SPRINTF1(pformat,sizeof(pformat),"%%%dd",Ptrwidth);
     ptrcrd = (N+1)/Ptrperline;
     if ( (N+1)%Ptrperline != 0) ptrcrd++;
-
+    
     if ( Indfmt == NULL ) Indfmt =  Ptrfmt;
     ParseIfmt(Indfmt, &Indperline, &Indwidth);
     SECURE_SPRINTF1(iformat,sizeof(iformat), "%%%dd",Indwidth);
     indcrd = nz/Indperline;
     if ( nz%Indperline != 0) indcrd++;
-
+    
     if ( Type[0] != 'P' ) {          /* Skip if pattern only  */
       if ( Valfmt == NULL ) Valfmt = "(4E21.13)";
       ParseRfmt(Valfmt, &Valperline, &Valwidth, &Valprec, &Valflag);
-      //Gmsh fix: this is invalid, as Valfmt is a const char*
-      //if (Valflag == 'D') *strchr(Valfmt,'D') = 'E';
+//       if (Valflag == 'D') {
+//         pValflag = (char *) strchr(Valfmt,'D');
+//         *pValflag = 'E';
+//       }
       if (Valflag == 'F')
 	SECURE_SPRINTF2(vformat, sizeof(vformat), "%% %d.%df", Valwidth,
 			Valprec);
@@ -419,7 +423,7 @@ namespace gmm {
       valcrd = nvalentries/Valperline;
       if ( nvalentries%Valperline != 0) valcrd++;
     } else valcrd = 0;
-
+    
     if ( Nrhs > 0 ) {
       if ( Rhsfmt == NULL ) Rhsfmt = Valfmt;
       ParseRfmt(Rhsfmt,&Rhsperline,&Rhswidth,&Rhsprec, &Rhsflag);
@@ -427,20 +431,22 @@ namespace gmm {
 	SECURE_SPRINTF2(rformat,sizeof(rformat), "%% %d.%df",Rhswidth,Rhsprec);
       else
 	SECURE_SPRINTF2(rformat,sizeof(rformat), "%% %d.%dE",Rhswidth,Rhsprec);
-      //Gmsh fix: this is invalid, as Rhsfmt is a const char*
-      //if (Rhsflag == 'D') *strchr(Rhsfmt,'D') = 'E';
-      rhscrd = nrhsentries/Rhsperline;
+//       if (Valflag == 'D') {
+//         pRhsflag = (char *) strchr(Rhsfmt,'D');
+//         *pRhsflag = 'E';
+//       }
+      rhscrd = nrhsentries/Rhsperline; 
       if ( nrhsentries%Rhsperline != 0) rhscrd++;
       if ( Rhstype[1] == 'G' ) rhscrd+=rhscrd;
       if ( Rhstype[2] == 'X' ) rhscrd+=rhscrd;
       rhscrd*=Nrhs;
     } else rhscrd = 0;
-
+    
     totcrd = 4+ptrcrd+indcrd+valcrd+rhscrd;
-
-
+    
+    
     /*  Print header information:  */
-
+    
     fprintf(out_file,"%-72s%-8s\n%14d%14d%14d%14d%14d\n",Title, Key, totcrd,
 	    ptrcrd, indcrd, valcrd, rhscrd);
     fprintf(out_file,"%3s%11s%14d%14d%14d%14d\n",Type,"          ", M, N, nz, 0);
@@ -452,38 +458,38 @@ namespace gmm {
     }
     else
       fprintf(out_file,"\n");
-
+    
     offset = 1 - shift;  /* if base 0 storage is declared (via macro def), */
     /* then storage entries are offset by 1           */
-
+    
     /*  Print column pointers:   */
     for (i = 0; i < N+1; i++) {
       entry = colptr[i]+offset;
       fprintf(out_file,pformat,entry);
       if ( (i+1)%Ptrperline == 0 ) fprintf(out_file,"\n");
     }
-
+    
     if ( (N+1) % Ptrperline != 0 ) fprintf(out_file,"\n");
-
+    
     /*  Print row indices:       */
     for (i=0;i<nz;i++) {
       entry = rowind[i]+offset;
       fprintf(out_file,iformat,entry);
       if ( (i+1)%Indperline == 0 ) fprintf(out_file,"\n");
     }
-
+    
     if ( nz % Indperline != 0 ) fprintf(out_file,"\n");
-
+    
     /*  Print values:            */
-
+    
     if ( Type[0] != 'P' ) {          /* Skip if pattern only  */
       for (i=0;i<nvalentries;i++) {
 	fprintf(out_file,vformat,val[i]);
 	if ( (i+1)%Valperline == 0 ) fprintf(out_file,"\n");
       }
-
+      
       if ( nvalentries % Valperline != 0 ) fprintf(out_file,"\n");
-
+      
       /*  Print right hand sides:  */
       acount = 1;
       linemod=0;
@@ -524,31 +530,33 @@ namespace gmm {
     GMM_ASSERT1(s == 0, "Error closing file in writeHB_mat_double().");
     return 1;
   }
-
-  template <typename T, int shift> void
+  
+  template <typename T, typename IND_TYPE, int shift> void
   HarwellBoeing_IO::write(const char *filename,
-			  const csc_matrix<T, shift>& A) {
-    write(filename, csc_matrix_ref<T*, unsigned*, unsigned *, shift>
-	  (A.pr, A.ir, A.jc, A.nr, A.nc));
+			  const csc_matrix<T, IND_TYPE, shift>& A) {
+    write(filename, csc_matrix_ref<const T*, const unsigned*,
+	  const unsigned *, shift>
+	  (&A.pr[0], &A.ir[0], &A.jc[0], A.nr, A.nc));
   }
 
-  template <typename T, int shift> void
+  template <typename T, typename IND_TYPE, int shift> void
   HarwellBoeing_IO::write(const char *filename,
-			  const csc_matrix<T, shift>& A,
+			  const csc_matrix<T, IND_TYPE, shift>& A,
 			  const std::vector<T> &rhs) {
-    write(filename, csc_matrix_ref<T*, unsigned*, unsigned *, shift>
-	  (A.pr, A.ir, A.jc, A.nr, A.nc), rhs);
+    write(filename, csc_matrix_ref<const T*, const unsigned*,
+	  const unsigned *, shift>
+	  (&A.pr[0], &A.ir[0], &A.jc[0], A.nr, A.nc), rhs);
   }
 
   template <typename T, typename INDI, typename INDJ, int shift> void
   HarwellBoeing_IO::write(const char *filename,
 			  const csc_matrix_ref<T*, INDI*, INDJ*, shift>& A) {
-    const char *t = 0;
+    const char *t = 0;    
     if (is_complex_double__(T()))
       if (mat_nrows(A) == mat_ncols(A)) t = "CUA"; else t = "CRA";
     else
       if (mat_nrows(A) == mat_ncols(A)) t = "RUA"; else t = "RRA";
-    writeHB_mat_double(filename, mat_nrows(A), mat_ncols(A),
+    writeHB_mat_double(filename, int(mat_nrows(A)), int(mat_ncols(A)),
 		       A.jc[mat_ncols(A)], A.jc, A.ir,
 		       (const double *)A.pr,
 		       0, 0, 0, 0, "GETFEM++ CSC MATRIX", "CSCMAT",
@@ -565,7 +573,7 @@ namespace gmm {
     else
       if (mat_nrows(A) == mat_ncols(A)) t = "RUA"; else t = "RRA";
     int Nrhs = gmm::vect_size(rhs) / mat_nrows(A);
-    writeHB_mat_double(filename, mat_nrows(A), mat_ncols(A),
+    writeHB_mat_double(filename, int(mat_nrows(A)), int(mat_ncols(A)),
 		       A.jc[mat_ncols(A)], A.jc, A.ir,
 		       (const double *)A.pr,
 		       Nrhs, (const double *)(&rhs[0]), 0, 0,
@@ -573,21 +581,21 @@ namespace gmm {
 		       t, 0, 0, 0, 0, "F  ", shift);
   }
 
-
+  
   template <typename MAT> void
   HarwellBoeing_IO::write(const char *filename, const MAT& A) {
-    gmm::csc_matrix<typename gmm::linalg_traits<MAT>::value_type>
+    gmm::csc_matrix<typename gmm::linalg_traits<MAT>::value_type> 
       tmp(gmm::mat_nrows(A), gmm::mat_ncols(A));
-    gmm::copy(A,tmp);
+    gmm::copy(A,tmp); 
     HarwellBoeing_IO::write(filename, tmp);
   }
 
   /** save a "double" or "std::complex<double>" csc matrix into a
       HarwellBoeing file
   */
-  template <typename T, int shift> inline void
+  template <typename T, typename IND_TYPE, int shift> inline void
   Harwell_Boeing_save(const std::string &filename,
-		      const csc_matrix<T, shift>& A)
+		      const csc_matrix<T, IND_TYPE, shift>& A)
   { HarwellBoeing_IO::write(filename.c_str(), A); }
 
   /** save a reference on "double" or "std::complex<double>" csc matrix
@@ -603,9 +611,9 @@ namespace gmm {
   */
   template <typename MAT> inline void
   Harwell_Boeing_save(const std::string &filename, const MAT& A) {
-    gmm::csc_matrix<typename gmm::linalg_traits<MAT>::value_type>
+    gmm::csc_matrix<typename gmm::linalg_traits<MAT>::value_type> 
       tmp(gmm::mat_nrows(A), gmm::mat_ncols(A));
-    gmm::copy(A, tmp);
+    gmm::copy(A, tmp); 
     HarwellBoeing_IO::write(filename.c_str(), tmp);
   }
 
@@ -623,8 +631,8 @@ namespace gmm {
   /** load a "double" or "std::complex<double>" csc matrix from a
       HarwellBoeing file
   */
-  template <typename T, int shift> void
-  Harwell_Boeing_load(const std::string &filename, csc_matrix<T, shift>& A) {
+  template <typename T, typename IND_TYPE, int shift> void
+  Harwell_Boeing_load(const std::string &filename, csc_matrix<T, IND_TYPE, shift>& A) {
     HarwellBoeing_IO h(filename.c_str()); h.read(A);
   }
 
@@ -645,7 +653,7 @@ namespace gmm {
   /*                                                                       */
   /*************************************************************************/
 
-  /*
+  /* 
    *   Matrix Market I/O library for ANSI C
    *
    *   See http://math.nist.gov/MatrixMarket for details.
@@ -662,22 +670,22 @@ namespace gmm {
   /******************* MM_typecode query functions *************************/
 
 #define mm_is_matrix(typecode)	        ((typecode)[0]=='M')
-
+  
 #define mm_is_sparse(typecode)	        ((typecode)[1]=='C')
 #define mm_is_coordinate(typecode)      ((typecode)[1]=='C')
 #define mm_is_dense(typecode)	        ((typecode)[1]=='A')
 #define mm_is_array(typecode)	        ((typecode)[1]=='A')
-
+  
 #define mm_is_complex(typecode)	        ((typecode)[2]=='C')
 #define mm_is_real(typecode)	        ((typecode)[2]=='R')
 #define mm_is_pattern(typecode)	        ((typecode)[2]=='P')
 #define mm_is_integer(typecode)         ((typecode)[2]=='I')
-
+  
 #define mm_is_symmetric(typecode)       ((typecode)[3]=='S')
 #define mm_is_general(typecode)	        ((typecode)[3]=='G')
 #define mm_is_skew(typecode)	        ((typecode)[3]=='K')
 #define mm_is_hermitian(typecode)       ((typecode)[3]=='H')
-
+  
   /******************* MM_typecode modify fucntions ************************/
 
 #define mm_set_matrix(typecode)	        ((*typecode)[0]='M')
@@ -719,7 +727,7 @@ namespace gmm {
 
    MM_matrix_typecode: 4-character sequence
 
-	                object 	    sparse/   	data        storage
+	                object 	    sparse/   	data        storage 
 	                            dense     	type        scheme
 
    string position:	 [0]        [1]		[2]         [3]
@@ -734,7 +742,7 @@ namespace gmm {
 #define MM_MTX_STR	   "matrix"
 #define MM_ARRAY_STR	   "array"
 #define MM_DENSE_STR	   "array"
-#define MM_COORDINATE_STR  "coordinate"
+#define MM_COORDINATE_STR  "coordinate" 
 #define MM_SPARSE_STR	   "coordinate"
 #define MM_COMPLEX_STR	   "complex"
 #define MM_REAL_STR	   "real"
@@ -750,9 +758,9 @@ namespace gmm {
     const char *types[4] = {0,0,0,0};
     /*    int error =0; */
     /*   int i; */
-
+    
     /* check for MTX type */
-    if (mm_is_matrix(matcode))
+    if (mm_is_matrix(matcode)) 
       types[0] = MM_MTX_STR;
     /*
       else
@@ -766,7 +774,7 @@ namespace gmm {
         types[1] = MM_DENSE_STR;
       else
         return NULL;
-
+    
     /* check for element data type */
     if (mm_is_real(matcode))
       types[2] = MM_REAL_STR;
@@ -781,8 +789,8 @@ namespace gmm {
 	    types[2] = MM_INT_STR;
 	  else
 	    return NULL;
-
-
+    
+    
     /* check for symmetry type */
     if (mm_is_general(matcode))
       types[3] = MM_GENERAL_STR;
@@ -794,26 +802,27 @@ namespace gmm {
       types[3] = MM_SKEW_STR;
     else
       return NULL;
-
+    
     SECURE_SPRINTF4(buffer, sizeof(buffer), "%s %s %s %s", types[0], types[1],
 		    types[2], types[3]);
     return SECURE_STRDUP(buffer);
-
+    
   }
-
+  
   inline int mm_read_banner(FILE *f, MM_typecode *matcode) {
     char line[MM_MAX_LINE_LENGTH];
     char banner[MM_MAX_TOKEN_LENGTH];
-    char mtx[MM_MAX_TOKEN_LENGTH];
+    char mtx[MM_MAX_TOKEN_LENGTH]; 
     char crd[MM_MAX_TOKEN_LENGTH];
     char data_type[MM_MAX_TOKEN_LENGTH];
     char storage_scheme[MM_MAX_TOKEN_LENGTH];
     char *p;
+    gmm::standard_locale sl;
     /*    int ret_code; */
-
-    mm_clear_typecode(matcode);
-
-    if (fgets(line, MM_MAX_LINE_LENGTH, f) == NULL)
+    
+    mm_clear_typecode(matcode);  
+    
+    if (fgets(line, MM_MAX_LINE_LENGTH, f) == NULL) 
       return MM_PREMATURE_EOF;
 
 #ifdef GMM_SECURE_CRT
@@ -827,10 +836,10 @@ namespace gmm {
 #endif
       return MM_PREMATURE_EOF;
 
-    for (p=mtx; *p!='\0'; *p=tolower(*p),p++);  /* convert to lower case */
-    for (p=crd; *p!='\0'; *p=tolower(*p),p++);
-    for (p=data_type; *p!='\0'; *p=tolower(*p),p++);
-    for (p=storage_scheme; *p!='\0'; *p=tolower(*p),p++);
+    for (p=mtx; *p!='\0'; *p=char(tolower(*p)),p++) {};  /* convert to lower case */
+    for (p=crd; *p!='\0'; *p=char(tolower(*p)),p++) {};  
+    for (p=data_type; *p!='\0'; *p=char(tolower(*p)),p++) {};
+    for (p=storage_scheme; *p!='\0'; *p=char(tolower(*p)),p++) {};
 
     /* check for banner */
     if (strncmp(banner, MatrixMarketBanner, strlen(MatrixMarketBanner)) != 0)
@@ -853,7 +862,7 @@ namespace gmm {
 	mm_set_dense(matcode);
       else
         return MM_UNSUPPORTED_TYPE;
-
+    
 
     /* third field */
 
@@ -870,7 +879,7 @@ namespace gmm {
 	    mm_set_integer(matcode);
 	  else
 	    return MM_UNSUPPORTED_TYPE;
-
+    
 
     /* fourth field */
 
@@ -887,7 +896,7 @@ namespace gmm {
 	    mm_set_skew(matcode);
 	  else
 	    return MM_UNSUPPORTED_TYPE;
-
+        
     return 0;
   }
 
@@ -895,48 +904,48 @@ namespace gmm {
     char line[MM_MAX_LINE_LENGTH];
     /* int ret_code;*/
     int num_items_read;
-
+    
     /* set return null parameter values, in case we exit with errors */
     *M = *N = *nz = 0;
-
+    
     /* now continue scanning until you reach the end-of-comments */
     do {
-      if (fgets(line,MM_MAX_LINE_LENGTH,f) == NULL)
+      if (fgets(line,MM_MAX_LINE_LENGTH,f) == NULL) 
 	return MM_PREMATURE_EOF;
     } while (line[0] == '%');
-
+    
     /* line[] is either blank or has M,N, nz */
     if (SECURE_NONCHAR_SSCANF(line, "%d %d %d", M, N, nz) == 3) return 0;
     else
-      do {
-	num_items_read = SECURE_NONCHAR_FSCANF(f, "%d %d %d", M, N, nz);
+      do { 
+	num_items_read = SECURE_NONCHAR_FSCANF(f, "%d %d %d", M, N, nz); 
 	if (num_items_read == EOF) return MM_PREMATURE_EOF;
       }
       while (num_items_read != 3);
-
+    
     return 0;
   }
 
 
-  inline int mm_read_mtx_crd_data(FILE *f, int, int, int nz, int I[],
+  inline int mm_read_mtx_crd_data(FILE *f, int, int, int nz, int II[],
 				  int J[], double val[], MM_typecode matcode) {
     int i;
     if (mm_is_complex(matcode)) {
       for (i=0; i<nz; i++)
-	if (SECURE_NONCHAR_FSCANF(f, "%d %d %lg %lg", &I[i], &J[i],
+	if (SECURE_NONCHAR_FSCANF(f, "%d %d %lg %lg", &II[i], &J[i],
 				  &val[2*i], &val[2*i+1])
 	    != 4) return MM_PREMATURE_EOF;
     }
     else if (mm_is_real(matcode)) {
       for (i=0; i<nz; i++) {
-	if (SECURE_NONCHAR_FSCANF(f, "%d %d %lg\n", &I[i], &J[i], &val[i])
+	if (SECURE_NONCHAR_FSCANF(f, "%d %d %lg\n", &II[i], &J[i], &val[i])
 	    != 3) return MM_PREMATURE_EOF;
-
+	
       }
     }
     else if (mm_is_pattern(matcode)) {
       for (i=0; i<nz; i++)
-	if (SECURE_NONCHAR_FSCANF(f, "%d %d", &I[i], &J[i])
+	if (SECURE_NONCHAR_FSCANF(f, "%d %d", &II[i], &J[i])
 	    != 2) return MM_PREMATURE_EOF;
     }
     else return MM_UNSUPPORTED_TYPE;
@@ -945,50 +954,50 @@ namespace gmm {
   }
 
   inline int mm_write_mtx_crd(const char *fname, int M, int N, int nz,
-			      int I[], int J[], const double val[],
+			      int II[], int J[], const double val[],
 			      MM_typecode matcode) {
     FILE *f;
     int i;
-
-    if (strcmp(fname, "stdout") == 0)
+    
+    if (strcmp(fname, "stdout") == 0) 
       f = stdout;
     else {
       SECURE_FOPEN(&f, fname, "w");
       if (f == NULL)
         return MM_COULD_NOT_WRITE_FILE;
     }
-
+    
     /* print banner followed by typecode */
     fprintf(f, "%s ", MatrixMarketBanner);
     char *str = mm_typecode_to_str(matcode);
     fprintf(f, "%s\n", str);
     free(str);
-
+    
     /* print matrix sizes and nonzeros */
     fprintf(f, "%d %d %d\n", M, N, nz);
-
+    
     /* print values */
     if (mm_is_pattern(matcode))
       for (i=0; i<nz; i++)
-	fprintf(f, "%d %d\n", I[i], J[i]);
+	fprintf(f, "%d %d\n", II[i], J[i]);
     else
       if (mm_is_real(matcode))
         for (i=0; i<nz; i++)
-	  fprintf(f, "%d %d %20.16g\n", I[i], J[i], val[i]);
+	  fprintf(f, "%d %d %20.16g\n", II[i], J[i], val[i]);
       else
 	if (mm_is_complex(matcode))
 	  for (i=0; i<nz; i++)
-            fprintf(f, "%d %d %20.16g %20.16g\n", I[i], J[i], val[2*i],
+            fprintf(f, "%d %d %20.16g %20.16g\n", II[i], J[i], val[2*i], 
 		    val[2*i+1]);
 	else {
 	  if (f != stdout) fclose(f);
 	  return MM_UNSUPPORTED_TYPE;
 	}
-
-    if (f !=stdout) fclose(f);
+    
+    if (f !=stdout) fclose(f); 
     return 0;
   }
-
+  
 
   /** matrix input/output for MatrixMarket storage */
   class MatrixMarket_IO {
@@ -1013,13 +1022,13 @@ namespace gmm {
     /* read opened file */
     template <typename Matrix> void read(Matrix &A);
     /* write a matrix */
-    template <typename T, int shift> static void
-    write(const char *filename, const csc_matrix<T, shift>& A);
-    template <typename T, typename INDI, typename INDJ, int shift> static void
+    template <typename T, typename IND_TYPE, int shift> static void 
+    write(const char *filename, const csc_matrix<T, IND_TYPE, shift>& A);  
+    template <typename T, typename INDI, typename INDJ, int shift> static void 
     write(const char *filename,
-	  const csc_matrix_ref<T*, INDI*, INDJ*, shift>& A);
-    template <typename MAT> static void
-    write(const char *filename, const MAT& A);
+	  const csc_matrix_ref<T*, INDI*, INDJ*, shift>& A);  
+    template <typename MAT> static void 
+    write(const char *filename, const MAT& A);  
   };
 
   /** load a matrix-market file */
@@ -1029,8 +1038,8 @@ namespace gmm {
     mm.read(A);
   }
   /** write a matrix-market file */
-  template <typename T, int shift> void
-  MatrixMarket_save(const char *filename, const csc_matrix<T, shift>& A) {
+  template <typename T, typename IND_TYPE, int shift> void
+  MatrixMarket_save(const char *filename, const csc_matrix<T, IND_TYPE, shift>& A) {
     MatrixMarket_IO mm; mm.write(filename, A);
   }
 
@@ -1042,6 +1051,7 @@ namespace gmm {
 
 
   inline void MatrixMarket_IO::open(const char *filename) {
+    gmm::standard_locale sl;
     if (f) { fclose(f); }
     SECURE_FOPEN(&f, filename, "r");
     GMM_ASSERT1(f, "Sorry, cannot open file " << filename);
@@ -1056,13 +1066,14 @@ namespace gmm {
 	       "the file does only contain the pattern of a sparse matrix");
     int s5 = mm_is_skew(matcode);
     GMM_ASSERT1(s5 == 0, "not currently supporting skew symmetric");
-    isSymmetric = mm_is_symmetric(matcode) || mm_is_hermitian(matcode);
-    isHermitian = mm_is_hermitian(matcode);
+    isSymmetric = mm_is_symmetric(matcode) || mm_is_hermitian(matcode); 
+    isHermitian = mm_is_hermitian(matcode); 
     isComplex =   mm_is_complex(matcode);
     mm_read_mtx_crd_size(f, &row, &col, &nz);
   }
 
   template <typename Matrix> void MatrixMarket_IO::read(Matrix &A) {
+    gmm::standard_locale sl;
     typedef typename linalg_traits<Matrix>::value_type T;
     GMM_ASSERT1(f, "no file opened!");
     GMM_ASSERT1(!is_complex_double__(T()) || isComplex,
@@ -1071,61 +1082,101 @@ namespace gmm {
 		"Bad MM matrix format (real matrix expected)");
     A = Matrix(row, col);
     gmm::clear(A);
-
-    std::vector<int> I(nz), J(nz);
+    
+    std::vector<int> II(nz), J(nz);
     std::vector<typename Matrix::value_type> PR(nz);
-    mm_read_mtx_crd_data(f, row, col, nz, &I[0], &J[0],
+    mm_read_mtx_crd_data(f, row, col, nz, &II[0], &J[0],
 			 (double*)&PR[0], matcode);
-
-    for (size_type i = 0; i < size_type(nz); ++i) A(I[i]-1, J[i]-1) = PR[i];
+    
+    for (size_type i = 0; i < size_type(nz); ++i) {
+        A(II[i]-1, J[i]-1) = PR[i];
+
+        // FIXED MM Format
+        if (mm_is_hermitian(matcode) && (II[i] != J[i]) ) {
+            A(J[i]-1, II[i]-1) = gmm::conj(PR[i]);
+        }
+
+        if (mm_is_symmetric(matcode) && (II[i] != J[i]) ) {
+            A(J[i]-1, II[i]-1) = PR[i];
+        }
+
+        if (mm_is_skew(matcode) && (II[i] != J[i]) ) {
+            A(J[i]-1, II[i]-1) = -PR[i];
+        }
+    }
   }
 
-  template <typename T, int shift> void
-  MatrixMarket_IO::write(const char *filename, const csc_matrix<T, shift>& A) {
-    write(filename, csc_matrix_ref<T*,unsigned*,unsigned*,shift>
-	  (A.pr, A.ir, A.jc, A.nr, A.nc));
+  template <typename T, typename IND_TYPE, int shift> void 
+  MatrixMarket_IO::write(const char *filename, const csc_matrix<T, IND_TYPE, shift>& A) {
+    write(filename, csc_matrix_ref<const T*, const unsigned*,
+	  const unsigned*,shift>
+	  (&A.pr[0], &A.ir[0], &A.jc[0], A.nr, A.nc));
   }
 
-  template <typename T, typename INDI, typename INDJ, int shift> void
-  MatrixMarket_IO::write(const char *filename,
+  template <typename T, typename INDI, typename INDJ, int shift> void 
+  MatrixMarket_IO::write(const char *filename, 
 			 const csc_matrix_ref<T*, INDI*, INDJ*, shift>& A) {
+    gmm::standard_locale sl;
     static MM_typecode t1 = {'M', 'C', 'R', 'G'};
     static MM_typecode t2 = {'M', 'C', 'C', 'G'};
     MM_typecode t;
-
+    
     if (is_complex_double__(T())) std::copy(&(t2[0]), &(t2[0])+4, &(t[0]));
     else std::copy(&(t1[0]), &(t1[0])+4, &(t[0]));
     size_type nz = A.jc[mat_ncols(A)];
-    std::vector<int> I(nz), J(nz);
-    for (size_type j=0; j < mat_ncols(A); ++j) {
+    std::vector<int> II(nz), J(nz);
+    for (size_type j=0; j < mat_ncols(A); ++j) {      
       for (size_type i = A.jc[j]; i < A.jc[j+1]; ++i) {
-	I[i] = A.ir[i] + 1 - shift;
-	J[i] = j + 1;
+	II[i] = A.ir[i] + 1 - shift;
+	J[i] = int(j + 1);
       }
     }
-    mm_write_mtx_crd(filename, mat_nrows(A), mat_ncols(A),
-		     nz, &I[0], &J[0], (const double *)A.pr, t);
+    mm_write_mtx_crd(filename, int(mat_nrows(A)), int(mat_ncols(A)),
+		     int(nz), &II[0], &J[0], (const double *)A.pr, t);
   }
 
 
   template <typename MAT> void
   MatrixMarket_IO::write(const char *filename, const MAT& A) {
-    gmm::csc_matrix<typename gmm::linalg_traits<MAT>::value_type>
+    gmm::csc_matrix<typename gmm::linalg_traits<MAT>::value_type> 
       tmp(gmm::mat_nrows(A), gmm::mat_ncols(A));
-    gmm::copy(A,tmp);
+    gmm::copy(A,tmp); 
     MatrixMarket_IO::write(filename, tmp);
   }
 
-  template<typename VEC> static void vecsave(std::string fname, const VEC& V) {
-    std::ofstream f(fname.c_str()); f.precision(16);
-    for (size_type i=0; i < gmm::vect_size(V); ++i) f << V[i] << "\n";
-  }
+  template<typename VEC> static void vecsave(std::string fname, const VEC& V,
+                                             bool binary=false, std::string Vformat="") {
+    if (binary) {
+      std::ofstream f(fname.c_str(), std::ofstream::binary);
+      for (size_type i=0; i < gmm::vect_size(V); ++i)
+        f.write(reinterpret_cast<const char*>(&V[i]), sizeof(V[i]));
+    }
+    else {
+      if (Vformat.empty()){
+        std::ofstream f(fname.c_str()); f.imbue(std::locale("C"));
+        f.precision(16);
+        for (size_type i=0; i < gmm::vect_size(V); ++i) f << V[i] << "\n";
+      }
+      else {
+        FILE* f = fopen(fname.c_str(), "w");
+        for (size_type i=0; i < gmm::vect_size(V); ++i) fprintf(f, Vformat.c_str(), V[i]);
+        fclose(f);
+      }
+    }
+  } 
 
-  template<typename VEC> static void vecload(std::string fname,
-					     const VEC& V_) {
+  template<typename VEC> static void vecload(std::string fname, const VEC& V_,
+                                             bool binary=false) {
     VEC &V(const_cast<VEC&>(V_));
-    std::ifstream f(fname.c_str());
-    for (size_type i=0; i < gmm::vect_size(V); ++i) f >> V[i];
+    if (binary) {
+      std::ifstream f(fname.c_str(), std::ifstream::binary);
+      for (size_type i=0; i < gmm::vect_size(V); ++i)
+        f.read(reinterpret_cast<char*>(&V[i]), sizeof(V[i]));
+    }
+    else {
+      std::ifstream f(fname.c_str()); f.imbue(std::locale("C"));
+      for (size_type i=0; i < gmm::vect_size(V); ++i) f >> V[i];
+    }
   }
 }
 
diff --git a/contrib/gmm/gmm_interface.h b/contrib/gmm/gmm_interface.h
index 5f197f6bcf..6635a25b1b 100644
--- a/contrib/gmm/gmm_interface.h
+++ b/contrib/gmm/gmm_interface.h
@@ -1,32 +1,33 @@
-// -*- c++ -*- (enables emacs c++ mode)
-//===========================================================================
-//
-// Copyright (C) 2002-2008 Yves Renard
-//
-// This file is a part of GETFEM++
-//
-// Getfem++  is  free software;  you  can  redistribute  it  and/or modify it
-// under  the  terms  of the  GNU  Lesser General Public License as published
-// by  the  Free Software Foundation;  either version 2.1 of the License,  or
-// (at your option) any later version.
-// This program  is  distributed  in  the  hope  that it will be useful,  but
-// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-// or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
-// License for more details.
-// You  should  have received a copy of the GNU Lesser General Public License
-// along  with  this program;  if not, write to the Free Software Foundation,
-// Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
-//
-// As a special exception, you may use this file as part of a free software
-// library without restriction.  Specifically, if other files instantiate
-// templates or use macros or inline functions from this file, or you compile
-// this file and link it with other files to produce an executable, this
-// file does not by itself cause the resulting executable to be covered by
-// the GNU General Public License.  This exception does not however
-// invalidate any other reasons why the executable file might be covered by
-// the GNU General Public License.
-//
-//===========================================================================
+/* -*- c++ -*- (enables emacs c++ mode) */
+/*===========================================================================
+
+ Copyright (C) 2002-2020 Yves Renard
+
+ This file is a part of GetFEM
+
+ GetFEM  is  free software;  you  can  redistribute  it  and/or modify it
+ under  the  terms  of the  GNU  Lesser General Public License as published
+ by  the  Free Software Foundation;  either version 3 of the License,  or
+ (at your option) any later version along with the GCC Runtime Library
+ Exception either version 3.1 or (at your option) any later version.
+ This program  is  distributed  in  the  hope  that it will be useful,  but
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+ License and GCC Runtime Library Exception for more details.
+ You  should  have received a copy of the GNU Lesser General Public License
+ along  with  this program;  if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+
+ As a special exception, you  may use  this file  as it is a part of a free
+ software  library  without  restriction.  Specifically,  if   other  files
+ instantiate  templates  or  use macros or inline functions from this file,
+ or  you compile this  file  and  link  it  with other files  to produce an
+ executable, this file  does  not  by itself cause the resulting executable
+ to be covered  by the GNU Lesser General Public License.  This   exception
+ does not  however  invalidate  any  other  reasons why the executable file
+ might be covered by the GNU Lesser General Public License.
+
+===========================================================================*/
 
 
 /**@file gmm_interface.h
@@ -193,6 +194,12 @@ namespace gmm {
   std::ostream &operator << (std::ostream &o, const simple_vector_ref<PT>& v)
   { gmm::write(o,v); return o; }
 
+  template <typename T, typename alloc>
+  simple_vector_ref<const std::vector<T,alloc> *>
+    vref(const std::vector<T, alloc> &vv)
+  { return simple_vector_ref<const std::vector<T,alloc> *>(vv); }
+  
+
   /* ********************************************************************* */
   /*		                                         		   */
   /*		Traits for S.T.L. object                     		   */
@@ -229,13 +236,9 @@ namespace gmm {
     { return it[i]; }
     static void resize(this_type &v, size_type n) { v.resize(n); }
   };
-}
-namespace std {
-  template <typename T> ostream &operator <<
-  (std::ostream &o, const vector<T>& m) { gmm::write(o,m); return o; }
-}
-namespace gmm {
 
+  
+  
   template <typename T>
   inline size_type nnz(const std::vector<T>& l) { return l.size(); }
 
@@ -702,7 +705,7 @@ namespace gmm {
     size_type ncols(void) const { return nc; }
    
     value_type operator()(size_type i, size_type j) const
-      { return mat_col(*this, i)[j]; }
+      { return mat_row(*this, i)[j]; }
   };
   
   template <typename PT1, typename PT2, typename PT3, int shift>
@@ -831,8 +834,8 @@ namespace gmm {
     }
     
     void fill(T a, T b = T(0)) { 
-      std::fill(begin_, end()+nbc*nbl, b);
-      iterator p = begin_, e = end()+nbc*nbl;
+      std::fill(begin_, begin_+nbc*nbl, b);
+      iterator p = begin_, e = begin_+nbc*nbl;
       while (p < e) { *p = a; p += nbl+1; }
     }
     inline size_type nrows(void) const { return nbl; }
@@ -957,8 +960,8 @@ namespace gmm {
     }
     
     void fill(T a, T b = T(0)) { 
-      std::fill(begin_, end()+nbc*nbl, b);
-      iterator p = begin_, e = end()+nbc*nbl;
+      std::fill(begin_, begin_+nbc*nbl, b);
+      iterator p = begin_, e = begin_+nbc*nbl;
       while (p < e) { *p = a; p += nbc+1; }
     }
     inline size_type nrows(void) const { return nbl; }
diff --git a/contrib/gmm/gmm_interface_bgeot.h b/contrib/gmm/gmm_interface_bgeot.h
index baa8e77568..69a34bdf41 100644
--- a/contrib/gmm/gmm_interface_bgeot.h
+++ b/contrib/gmm/gmm_interface_bgeot.h
@@ -1,32 +1,33 @@
-// -*- c++ -*- (enables emacs c++ mode)
-//===========================================================================
-//
-// Copyright (C) 2002-2008 Yves Renard
-//
-// This file is a part of GETFEM++
-//
-// Getfem++  is  free software;  you  can  redistribute  it  and/or modify it
-// under  the  terms  of the  GNU  Lesser General Public License as published
-// by  the  Free Software Foundation;  either version 2.1 of the License,  or
-// (at your option) any later version.
-// This program  is  distributed  in  the  hope  that it will be useful,  but
-// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-// or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
-// License for more details.
-// You  should  have received a copy of the GNU Lesser General Public License
-// along  with  this program;  if not, write to the Free Software Foundation,
-// Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
-//
-// As a special exception, you may use this file as part of a free software
-// library without restriction.  Specifically, if other files instantiate
-// templates or use macros or inline functions from this file, or you compile
-// this file and link it with other files to produce an executable, this
-// file does not by itself cause the resulting executable to be covered by
-// the GNU General Public License.  This exception does not however
-// invalidate any other reasons why the executable file might be covered by
-// the GNU General Public License.
-//
-//===========================================================================
+/* -*- c++ -*- (enables emacs c++ mode) */
+/*===========================================================================
+
+ Copyright (C) 2002-2020 Yves Renard
+
+ This file is a part of GetFEM
+
+ GetFEM  is  free software;  you  can  redistribute  it  and/or modify it
+ under  the  terms  of the  GNU  Lesser General Public License as published
+ by  the  Free Software Foundation;  either version 3 of the License,  or
+ (at your option) any later version along with the GCC Runtime Library
+ Exception either version 3.1 or (at your option) any later version.
+ This program  is  distributed  in  the  hope  that it will be useful,  but
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+ License and GCC Runtime Library Exception for more details.
+ You  should  have received a copy of the GNU Lesser General Public License
+ along  with  this program;  if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+
+ As a special exception, you  may use  this file  as it is a part of a free
+ software  library  without  restriction.  Specifically,  if   other  files
+ instantiate  templates  or  use macros or inline functions from this file,
+ or  you compile this  file  and  link  it  with other files  to produce an
+ executable, this file  does  not  by itself cause the resulting executable
+ to be covered  by the GNU Lesser General Public License.  This   exception
+ does not  however  invalidate  any  other  reasons why the executable file
+ might be covered by the GNU Lesser General Public License.
+
+===========================================================================*/
 
 /**@file gmm_interface_bgeot.h
    @author  Yves Renard <Yves.Renard@insa-lyon.fr>
diff --git a/contrib/gmm/gmm_iter.h b/contrib/gmm/gmm_iter.h
index 3a593db7a6..b8db9ddc96 100644
--- a/contrib/gmm/gmm_iter.h
+++ b/contrib/gmm/gmm_iter.h
@@ -1,32 +1,33 @@
-// -*- c++ -*- (enables emacs c++ mode)
-//===========================================================================
-//
-// Copyright (C) 2002-2008 Yves Renard
-//
-// This file is a part of GETFEM++
-//
-// Getfem++  is  free software;  you  can  redistribute  it  and/or modify it
-// under  the  terms  of the  GNU  Lesser General Public License as published
-// by  the  Free Software Foundation;  either version 2.1 of the License,  or
-// (at your option) any later version.
-// This program  is  distributed  in  the  hope  that it will be useful,  but
-// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-// or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
-// License for more details.
-// You  should  have received a copy of the GNU Lesser General Public License
-// along  with  this program;  if not, write to the Free Software Foundation,
-// Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
-//
-// As a special exception, you may use this file as part of a free software
-// library without restriction.  Specifically, if other files instantiate
-// templates or use macros or inline functions from this file, or you compile
-// this file and link it with other files to produce an executable, this
-// file does not by itself cause the resulting executable to be covered by
-// the GNU General Public License.  This exception does not however
-// invalidate any other reasons why the executable file might be covered by
-// the GNU General Public License.
-//
-//===========================================================================
+/* -*- c++ -*- (enables emacs c++ mode) */
+/*===========================================================================
+
+ Copyright (C) 2002-2020 Yves Renard
+
+ This file is a part of GetFEM
+
+ GetFEM  is  free software;  you  can  redistribute  it  and/or modify it
+ under  the  terms  of the  GNU  Lesser General Public License as published
+ by  the  Free Software Foundation;  either version 3 of the License,  or
+ (at your option) any later version along with the GCC Runtime Library
+ Exception either version 3.1 or (at your option) any later version.
+ This program  is  distributed  in  the  hope  that it will be useful,  but
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+ License and GCC Runtime Library Exception for more details.
+ You  should  have received a copy of the GNU Lesser General Public License
+ along  with  this program;  if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+
+ As a special exception, you  may use  this file  as it is a part of a free
+ software  library  without  restriction.  Specifically,  if   other  files
+ instantiate  templates  or  use macros or inline functions from this file,
+ or  you compile this  file  and  link  it  with other files  to produce an
+ executable, this file  does  not  by itself cause the resulting executable
+ to be covered  by the GNU Lesser General Public License.  This   exception
+ does not  however  invalidate  any  other  reasons why the executable file
+ might be covered by the GNU Lesser General Public License.
+
+===========================================================================*/
 
 /**@file gmm_iter.h
    @author  Yves Renard <Yves.Renard@insa-lyon.fr>
@@ -38,6 +39,7 @@
 #define GMM_ITER_H__
 
 #include "gmm_kernel.h"
+#include <iomanip>
 
 namespace gmm {
 
@@ -55,6 +57,8 @@ namespace gmm {
     int noise;         /* if noise > 0 iterations are printed.             */
     double resmax;     /* maximum residu.                                  */
     double resminreach, resadd;
+    double diverged_res; /* Threshold beyond which the iterative           */
+                       /* is considered to diverge.                        */
     size_type nit;     /* iteration number.                                */
     double res;        /* last computed residu.                            */
     std::string name;  /* eventually, name of the method.                  */
@@ -64,12 +68,14 @@ namespace gmm {
 
     void init(void) { 
       nit = 0; res = 0.0; written = false; 
-      resminreach = 1E50; resadd = 0.0; 
+      resminreach = 1E200; resadd = 0.0; 
       callback = 0;
     }
 
-    iteration(double r = 1.0E-8, int noi = 0, size_type mit = size_type(-1))
-      : rhsn(1.0), maxiter(mit), noise(noi), resmax(r) { init(); }
+    iteration(double r = 1.0E-8, int noi = 0, size_type mit = size_type(-1),
+              double div_res = 1E200)
+      : rhsn(1.0), maxiter(mit), noise(noi), resmax(r), diverged_res(div_res)
+    { init(); }
 
     void  operator ++(int) {  nit++; written = false; resadd += res; }
     void  operator ++() { (*this)++; }
@@ -85,12 +91,17 @@ namespace gmm {
     void set_resmax(double r) { resmax = r; }
 
     double get_res() const { return res; }
+    void enforce_converged(bool c = true)
+    { if (c) res = double(0); else res = rhsn * resmax + double(1); }
 
     /* change the user-definable callback, called after each iteration */
     void set_callback(void (*t)(const gmm::iteration&)) {
       callback = t;
     }
 
+    double get_diverged_residual(void) const { return diverged_res; }
+    void set_diverged_residual(double r) { diverged_res = r; }
+
     size_type get_iteration(void) const { return nit; }
     void set_iteration(size_type i) { nit = i; }
     
@@ -100,30 +111,42 @@ namespace gmm {
     double get_rhsnorm(void) const { return rhsn; }
     void set_rhsnorm(double r) { rhsn = r; }
     
-    bool converged(void) { return res <= rhsn * resmax; }
+    bool converged(void) {
+      return !isnan(res) && res <= rhsn * resmax;
+    }
     bool converged(double nr) { 
-      res = gmm::abs(nr); resminreach = std::min(resminreach, res);
+      res = gmm::abs(nr);
+      resminreach = std::min(resminreach, res);
       return converged();
     }
     template <typename VECT> bool converged(const VECT &v)
     { return converged(gmm::vect_norm2(v)); }
+    bool diverged(void) {
+      return isnan(res) || (nit>=maxiter)
+                        || (res>=rhsn*diverged_res && nit > 4);
+    }
+    bool diverged(double nr) {
+      res = gmm::abs(nr);
+      resminreach = std::min(resminreach, res);
+      return diverged();
+    }
 
     bool finished(double nr) {
       if (callback) callback(*this);
       if (noise > 0 && !written) {
-	double a = (rhsn == 0) ? 1.0 : rhsn;
-	converged(nr);
-	cout << name << " iter " << nit << " residual "
-	     << gmm::abs(nr) / a;
-// 	if (nit % 100 == 0 && nit > 0) {
-// 	  cout << " (residual min " << resminreach / a << " mean val "
-// 	       << resadd / (100.0 * a) << " )";
-// 	  resadd = 0.0;
-// 	}
-	cout <<  endl;
-	written = true;
+        double a = (rhsn == 0) ? 1.0 : rhsn;
+        converged(nr);
+        cout << name << " iter " << std::setw(3) << nit << " residual "
+             << std::setw(12) << gmm::abs(nr) / a;
+//         if (nit % 100 == 0 && nit > 0) {
+//           cout << " (residual min " << resminreach / a << " mean val "
+//                << resadd / (100.0 * a) << " )";
+//           resadd = 0.0;
+//         }
+        cout <<  endl;
+        written = true;
       }
-      return (nit >= maxiter || converged(nr));
+      return (converged(nr) || diverged(nr));
     }
     template <typename VECT> bool finished_vect(const VECT &v)
     { return finished(double(gmm::vect_norm2(v))); }
diff --git a/contrib/gmm/gmm_iter_solvers.h b/contrib/gmm/gmm_iter_solvers.h
index 4e782c7739..a2406f352c 100644
--- a/contrib/gmm/gmm_iter_solvers.h
+++ b/contrib/gmm/gmm_iter_solvers.h
@@ -1,32 +1,33 @@
-// -*- c++ -*- (enables emacs c++ mode)
-//===========================================================================
-//
-// Copyright (C) 2002-2008 Yves Renard
-//
-// This file is a part of GETFEM++
-//
-// Getfem++  is  free software;  you  can  redistribute  it  and/or modify it
-// under  the  terms  of the  GNU  Lesser General Public License as published
-// by  the  Free Software Foundation;  either version 2.1 of the License,  or
-// (at your option) any later version.
-// This program  is  distributed  in  the  hope  that it will be useful,  but
-// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-// or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
-// License for more details.
-// You  should  have received a copy of the GNU Lesser General Public License
-// along  with  this program;  if not, write to the Free Software Foundation,
-// Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
-//
-// As a special exception, you may use this file as part of a free software
-// library without restriction.  Specifically, if other files instantiate
-// templates or use macros or inline functions from this file, or you compile
-// this file and link it with other files to produce an executable, this
-// file does not by itself cause the resulting executable to be covered by
-// the GNU General Public License.  This exception does not however
-// invalidate any other reasons why the executable file might be covered by
-// the GNU General Public License.
-//
-//===========================================================================
+/* -*- c++ -*- (enables emacs c++ mode) */
+/*===========================================================================
+
+ Copyright (C) 2002-2020 Yves Renard
+
+ This file is a part of GetFEM
+
+ GetFEM  is  free software;  you  can  redistribute  it  and/or modify it
+ under  the  terms  of the  GNU  Lesser General Public License as published
+ by  the  Free Software Foundation;  either version 3 of the License,  or
+ (at your option) any later version along with the GCC Runtime Library
+ Exception either version 3.1 or (at your option) any later version.
+ This program  is  distributed  in  the  hope  that it will be useful,  but
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+ License and GCC Runtime Library Exception for more details.
+ You  should  have received a copy of the GNU Lesser General Public License
+ along  with  this program;  if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+
+ As a special exception, you  may use  this file  as it is a part of a free
+ software  library  without  restriction.  Specifically,  if   other  files
+ instantiate  templates  or  use macros or inline functions from this file,
+ or  you compile this  file  and  link  it  with other files  to produce an
+ executable, this file  does  not  by itself cause the resulting executable
+ to be covered  by the GNU Lesser General Public License.  This   exception
+ does not  however  invalidate  any  other  reasons why the executable file
+ might be covered by the GNU Lesser General Public License.
+
+===========================================================================*/
 
 /**@file gmm_iter_solvers.h
    @author  Yves Renard <Yves.Renard@insa-lyon.fr>
@@ -69,7 +70,8 @@ namespace gmm {
     c = std::max(a, b); a = std::min(a, b); b = c;
     while (d > tol) {
       c = b - (b - a) * (Gb / (Gb - Ga)); /* regula falsi.     */
-      if (c > b) c = b; if (c < a) c = a; 
+      if (c > b) c = b;
+      if (c < a) c = a; 
       Gc = G(c);
       if (Gc*Gb > 0) { b = c; Gb = Gc; } else { a = c; Ga = Gc; }
       c = (b + a) / 2.0 ; Gc = G(c); /* Dichotomie.                       */
diff --git a/contrib/gmm/gmm_kernel.h b/contrib/gmm/gmm_kernel.h
index e8fd9a4bb0..7fdae24816 100644
--- a/contrib/gmm/gmm_kernel.h
+++ b/contrib/gmm/gmm_kernel.h
@@ -1,32 +1,33 @@
-// -*- c++ -*- (enables emacs c++ mode)
-//===========================================================================
-//
-// Copyright (C) 2002-2008 Yves Renard
-//
-// This file is a part of GETFEM++
-//
-// Getfem++  is  free software;  you  can  redistribute  it  and/or modify it
-// under  the  terms  of the  GNU  Lesser General Public License as published
-// by  the  Free Software Foundation;  either version 2.1 of the License,  or
-// (at your option) any later version.
-// This program  is  distributed  in  the  hope  that it will be useful,  but
-// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-// or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
-// License for more details.
-// You  should  have received a copy of the GNU Lesser General Public License
-// along  with  this program;  if not, write to the Free Software Foundation,
-// Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
-//
-// As a special exception, you may use this file as part of a free software
-// library without restriction.  Specifically, if other files instantiate
-// templates or use macros or inline functions from this file, or you compile
-// this file and link it with other files to produce an executable, this
-// file does not by itself cause the resulting executable to be covered by
-// the GNU General Public License.  This exception does not however
-// invalidate any other reasons why the executable file might be covered by
-// the GNU General Public License.
-//
-//===========================================================================
+/* -*- c++ -*- (enables emacs c++ mode) */
+/*===========================================================================
+
+ Copyright (C) 2002-2020 Yves Renard
+
+ This file is a part of GetFEM
+
+ GetFEM  is  free software;  you  can  redistribute  it  and/or modify it
+ under  the  terms  of the  GNU  Lesser General Public License as published
+ by  the  Free Software Foundation;  either version 3 of the License,  or
+ (at your option) any later version along with the GCC Runtime Library
+ Exception either version 3.1 or (at your option) any later version.
+ This program  is  distributed  in  the  hope  that it will be useful,  but
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+ License and GCC Runtime Library Exception for more details.
+ You  should  have received a copy of the GNU Lesser General Public License
+ along  with  this program;  if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+
+ As a special exception, you  may use  this file  as it is a part of a free
+ software  library  without  restriction.  Specifically,  if   other  files
+ instantiate  templates  or  use macros or inline functions from this file,
+ or  you compile this  file  and  link  it  with other files  to produce an
+ executable, this file  does  not  by itself cause the resulting executable
+ to be covered  by the GNU Lesser General Public License.  This   exception
+ does not  however  invalidate  any  other  reasons why the executable file
+ might be covered by the GNU Lesser General Public License.
+
+===========================================================================*/
 
 /**@file gmm_kernel.h 
    @author  Yves Renard <Yves.Renard@insa-lyon.fr>
@@ -48,6 +49,7 @@
 #include "gmm_matrix.h"
 #include "gmm_tri_solve.h"
 #include "gmm_blas_interface.h"
+#include "gmm_lapack_interface.h"
 
 
 #endif //  GMM_KERNEL_H__
diff --git a/contrib/gmm/gmm_lapack_interface.h b/contrib/gmm/gmm_lapack_interface.h
index ea5edb4500..37bc48f5c0 100644
--- a/contrib/gmm/gmm_lapack_interface.h
+++ b/contrib/gmm/gmm_lapack_interface.h
@@ -1,32 +1,33 @@
-// -*- c++ -*- (enables emacs c++ mode)
-//===========================================================================
-//
-// Copyright (C) 2003-2008 Yves Renard
-//
-// This file is a part of GETFEM++
-//
-// Getfem++  is  free software;  you  can  redistribute  it  and/or modify it
-// under  the  terms  of the  GNU  Lesser General Public License as published
-// by  the  Free Software Foundation;  either version 2.1 of the License,  or
-// (at your option) any later version.
-// This program  is  distributed  in  the  hope  that it will be useful,  but
-// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-// or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
-// License for more details.
-// You  should  have received a copy of the GNU Lesser General Public License
-// along  with  this program;  if not, write to the Free Software Foundation,
-// Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
-//
-// As a special exception, you may use this file as part of a free software
-// library without restriction.  Specifically, if other files instantiate
-// templates or use macros or inline functions from this file, or you compile
-// this file and link it with other files to produce an executable, this
-// file does not by itself cause the resulting executable to be covered by
-// the GNU General Public License.  This exception does not however
-// invalidate any other reasons why the executable file might be covered by
-// the GNU General Public License.
-//
-//===========================================================================
+/* -*- c++ -*- (enables emacs c++ mode) */
+/*===========================================================================
+
+ Copyright (C) 2003-2020 Yves Renard
+
+ This file is a part of GetFEM
+
+ GetFEM  is  free software;  you  can  redistribute  it  and/or modify it
+ under  the  terms  of the  GNU  Lesser General Public License as published
+ by  the  Free Software Foundation;  either version 3 of the License,  or
+ (at your option) any later version along with the GCC Runtime Library
+ Exception either version 3.1 or (at your option) any later version.
+ This program  is  distributed  in  the  hope  that it will be useful,  but
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+ License and GCC Runtime Library Exception for more details.
+ You  should  have received a copy of the GNU Lesser General Public License
+ along  with  this program;  if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+
+ As a special exception, you  may use  this file  as it is a part of a free
+ software  library  without  restriction.  Specifically,  if   other  files
+ instantiate  templates  or  use macros or inline functions from this file,
+ or  you compile this  file  and  link  it  with other files  to produce an
+ executable, this file  does  not  by itself cause the resulting executable
+ to be covered  by the GNU Lesser General Public License.  This   exception
+ does not  however  invalidate  any  other  reasons why the executable file
+ might be covered by the GNU Lesser General Public License.
+
+===========================================================================*/
 
 /**@file gmm_lapack_interface.h
    @author  Yves Renard <Yves.Renard@insa-lyon.fr>
@@ -34,8 +35,6 @@
    @brief gmm interface for LAPACK
 */
 
-#if defined(GMM_USES_LAPACK) || defined(GMM_USES_ATLAS)
-
 #ifndef GMM_LAPACK_INTERFACE_H
 #define GMM_LAPACK_INTERFACE_H
 
@@ -44,35 +43,46 @@
 #include "gmm_dense_qr.h"
 
 
+#if defined(GMM_USES_LAPACK)
+
 namespace gmm {
 
-  /* ********************************************************************* */
-  /* Operations interfaced for T = float, double, std::complex<float>      */
-  /*    or std::complex<double> :                                          */
-  /*                                                                       */
-  /* lu_factor(dense_matrix<T>, std::vector<int>)                          */
-  /* lu_solve(dense_matrix<T>, std::vector<T>, std::vector<T>)             */
-  /* lu_solve(dense_matrix<T>, std::vector<int>, std::vector<T>,           */
-  /*          std::vector<T>)                                              */
-  /* lu_solve_transposed(dense_matrix<T>, std::vector<int>, std::vector<T>,*/
-  /*          std::vector<T>)                                              */
-  /* lu_inverse(dense_matrix<T>)                                           */
-  /* lu_inverse(dense_matrix<T>, std::vector<int>, dense_matrix<T>)        */
-  /*                                                                       */
-  /* qr_factor(dense_matrix<T>, dense_matrix<T>, dense_matrix<T>)          */
-  /*                                                                       */
-  /* implicit_qr_algorithm(dense_matrix<T>, std::vector<T>)                */
-  /* implicit_qr_algorithm(dense_matrix<T>, std::vector<T>,                */
-  /*                       dense_matrix<T>)                                */
-  /* implicit_qr_algorithm(dense_matrix<T>, std::vector<std::complex<T> >) */
-  /* implicit_qr_algorithm(dense_matrix<T>, std::vector<std::complex<T> >, */
-  /*                       dense_matrix<T>)                                */
-  /*                                                                       */
-  /* ********************************************************************* */
-
-  /* ********************************************************************* */
-  /* LAPACK functions used.                                                */
-  /* ********************************************************************* */
+  /* ********************************************************************** */
+  /* Operations interfaced for T = float, double, std::complex<float>       */
+  /*    or std::complex<double> :                                           */
+  /*                                                                        */
+  /* lu_factor(dense_matrix<T>, std::vector<long>)                          */
+  /* lu_solve(dense_matrix<T>, std::vector<T>, std::vector<T>)              */
+  /* lu_solve(dense_matrix<T>, std::vector<long>, std::vector<T>,           */
+  /*          std::vector<T>)                                               */
+  /* lu_solve_transposed(dense_matrix<T>, std::vector<long>, std::vector<T>,*/
+  /*          std::vector<T>)                                               */
+  /* lu_inverse(dense_matrix<T>)                                            */
+  /* lu_inverse(dense_matrix<T>, std::vector<long>, dense_matrix<T>)        */
+  /*                                                                        */
+  /* qr_factor(dense_matrix<T>, dense_matrix<T>, dense_matrix<T>)           */
+  /*                                                                        */
+  /* implicit_qr_algorithm(dense_matrix<T>, std::vector<T>)                 */
+  /* implicit_qr_algorithm(dense_matrix<T>, std::vector<T>,                 */
+  /*                       dense_matrix<T>)                                 */
+  /* implicit_qr_algorithm(dense_matrix<T>, std::vector<std::complex<T> >)  */
+  /* implicit_qr_algorithm(dense_matrix<T>, std::vector<std::complex<T> >,  */
+  /*                       dense_matrix<T>)                                 */
+  /*                                                                        */
+  /* geev_interface_right                                                   */
+  /* geev_interface_left                                                    */
+  /*                                                                        */
+  /* schur(dense_matrix<T>, dense_matrix<T>, dense_matrix<T>)               */
+  /*                                                                        */
+  /* svd(dense_matrix<T>, dense_matrix<T>, dense_matrix<T>, std::vector<T>) */
+  /* svd(dense_matrix<T>, dense_matrix<T>, dense_matrix<T>,                 */
+  /*     std::vector<std::complex<T> >)                                     */
+  /*                                                                        */
+  /* ********************************************************************** */
+
+  /* ********************************************************************** */
+  /* LAPACK functions used.                                                 */
+  /* ********************************************************************** */
 
   extern "C" {
     void sgetrf_(...); void dgetrf_(...); void cgetrf_(...); void zgetrf_(...);
@@ -83,18 +93,25 @@ namespace gmm {
     void sormqr_(...); void dormqr_(...); void cunmqr_(...); void zunmqr_(...);
     void sgees_ (...); void dgees_ (...); void cgees_ (...); void zgees_ (...);
     void sgeev_ (...); void dgeev_ (...); void cgeev_ (...); void zgeev_ (...);
+    void sgeesx_(...); void dgeesx_(...); void cgeesx_(...); void zgeesx_(...);
+    void sgesvd_(...); void dgesvd_(...); void cgesvd_(...); void zgesvd_(...);
   }
-
-  /* ********************************************************************* */
-  /* LU decomposition.                                                     */
-  /* ********************************************************************* */
-
-# define getrf_interface(lapack_name, base_type) inline                    \
-  size_type lu_factor(dense_matrix<base_type > &A, std::vector<int> &ipvt){\
-    GMMLAPACK_TRACE("getrf_interface");                                    \
-    int m(mat_nrows(A)), n(mat_ncols(A)), lda(m), info(0);                 \
-    if (m && n) lapack_name(&m, &n, &A(0,0), &lda, &ipvt[0], &info);       \
-    return size_type(info);                                                \
+  
+  /* ********************************************************************** */
+  /* LU decomposition.                                                      */
+  /* ********************************************************************** */
+  
+# define getrf_interface(lapack_name, base_type) inline                      \
+    size_type lu_factor(dense_matrix<base_type > &A, lapack_ipvt &ipvt){     \
+    GMMLAPACK_TRACE("getrf_interface");                                      \
+    BLAS_INT m = BLAS_INT(mat_nrows(A)), n = BLAS_INT(mat_ncols(A)), lda(m); \
+    long info(-1L);                                                          \
+    if (m && n) lapack_name(&m, &n, &A(0,0), &lda, ipvt.pfirst(), &info);    \
+    if ((sizeof(BLAS_INT) == 4) ||                                            \
+        ((info & 0xFFFFFFFF00000000L) && !(info & 0x00000000FFFFFFFFL)))     \
+      /* For compatibility with lapack version with 32 bit integer. */	     \
+      ipvt.set_to_int32();						     \
+    return size_type(int(info & 0x00000000FFFFFFFFL));			     \
   }
 
   getrf_interface(sgetrf_, BLAS_S)
@@ -108,13 +125,13 @@ namespace gmm {
 
 # define getrs_interface(f_name, trans1, lapack_name, base_type) inline    \
   void f_name(const dense_matrix<base_type > &A,                           \
-	      const std::vector<int> &ipvt, std::vector<base_type > &x,    \
-	      const std::vector<base_type > &b) {                          \
+              const lapack_ipvt &ipvt, std::vector<base_type > &x,	   \
+              const std::vector<base_type > &b) {                          \
     GMMLAPACK_TRACE("getrs_interface");                                    \
-    int n(mat_nrows(A)), info, nrhs(1);                                    \
+    BLAS_INT n = BLAS_INT(mat_nrows(A)), info(0), nrhs(1);                 \
     gmm::copy(b, x); trans1;                                               \
     if (n)                                                                 \
-      lapack_name(&t, &n, &nrhs, &(A(0,0)),&n,&ipvt[0], &x[0], &n, &info); \
+      lapack_name(&t,&n,&nrhs,&(A(0,0)),&n,ipvt.pfirst(),&x[0],&n,&info);  \
   }
   
 # define getrs_trans_n const char t = 'N'
@@ -135,17 +152,18 @@ namespace gmm {
 
 # define getri_interface(lapack_name, base_type) inline                    \
   void lu_inverse(const dense_matrix<base_type > &LU,                      \
-       std::vector<int> &ipvt, const dense_matrix<base_type > &A_) {       \
+	    const lapack_ipvt &ipvt, const dense_matrix<base_type > &A_) { \
     GMMLAPACK_TRACE("getri_interface");                                    \
     dense_matrix<base_type >&                                              \
     A = const_cast<dense_matrix<base_type > &>(A_);                        \
-    int n(mat_nrows(A)), info, lwork(-1); base_type work1;                 \
+    BLAS_INT n = BLAS_INT(mat_nrows(A)), info(0), lwork(-1);               \
+    base_type work1;                                                       \
     if (n) {                                                               \
       gmm::copy(LU, A);                                                    \
-      lapack_name(&n, &A(0,0), &n, &ipvt[0], &work1, &lwork, &info);       \
+      lapack_name(&n, &A(0,0), &n, ipvt.pfirst(), &work1, &lwork, &info);  \
       lwork = int(gmm::real(work1));                                       \
-      std::vector<base_type > work(lwork);                                 \
-      lapack_name(&n, &A(0,0), &n, &ipvt[0], &work[0], &lwork, &info);     \
+      std::vector<base_type> work(lwork);                                  \
+      lapack_name(&n, &A(0,0), &n, ipvt.pfirst(), &work[0], &lwork,&info); \
     }                                                                      \
   }
 
@@ -154,23 +172,24 @@ namespace gmm {
   getri_interface(cgetri_, BLAS_C)
   getri_interface(zgetri_, BLAS_Z)
 
+  /* ********************************************************************** */
+  /* QR factorization.                                                      */
+  /* ********************************************************************** */
 
-  /* ********************************************************************* */
-  /* QR factorization.                                                     */
-  /* ********************************************************************* */
-
-# define geqrf_interface(lapack_name1, base_type) inline		   \
-  void qr_factor(dense_matrix<base_type > &A){			           \
-    GMMLAPACK_TRACE("geqrf_interface");				           \
-    int m(mat_nrows(A)), n(mat_ncols(A)), info, lwork(-1); base_type work1;\
-    if (m && n) {							   \
-      std::vector<base_type > tau(n);					   \
+# define geqrf_interface(lapack_name1, base_type) inline                   \
+  void qr_factor(dense_matrix<base_type > &A){                             \
+    GMMLAPACK_TRACE("geqrf_interface");                                    \
+    BLAS_INT m = BLAS_INT(mat_nrows(A)), n=BLAS_INT(mat_ncols(A));         \
+    BLAS_INT info(0), lwork(-1);                                           \
+    base_type work1;                                                       \
+    if (m && n) {                                                          \
+      std::vector<base_type > tau(n);                                      \
       lapack_name1(&m, &n, &A(0,0), &m, &tau[0], &work1  , &lwork, &info); \
-      lwork = int(gmm::real(work1));					   \
-      std::vector<base_type > work(lwork);				   \
+      lwork = BLAS_INT(gmm::real(work1));                                  \
+      std::vector<base_type > work(lwork);                                 \
       lapack_name1(&m, &n, &A(0,0), &m, &tau[0], &work[0], &lwork, &info); \
-      GMM_ASSERT1(!info, "QR factorization failed");			   \
-    }									   \
+      GMM_ASSERT1(!info, "QR factorization failed");                       \
+    }                                                                      \
   }
     
   geqrf_interface(sgeqrf_, BLAS_S)
@@ -184,18 +203,20 @@ namespace gmm {
   void qr_factor(const dense_matrix<base_type > &A,                        \
        dense_matrix<base_type > &Q, dense_matrix<base_type > &R) {         \
     GMMLAPACK_TRACE("geqrf_interface2");                                   \
-    int m(mat_nrows(A)), n(mat_ncols(A)), info, lwork(-1); base_type work1;\
-    if (m && n) {                                                          \
-      gmm::copy(A, Q);                                                     \
+    BLAS_INT m = BLAS_INT(mat_nrows(A)), n=BLAS_INT(mat_ncols(A));         \
+    BLAS_INT info(0), lwork(-1);                                           \
+    base_type work1;                                                       \
+    if (m && n) {							   \
+      std::copy(A.begin(), A.end(), Q.begin());				   \
       std::vector<base_type > tau(n);                                      \
       lapack_name1(&m, &n, &Q(0,0), &m, &tau[0], &work1  , &lwork, &info); \
-      lwork = int(gmm::real(work1));                                       \
+      lwork = BLAS_INT(gmm::real(work1));                                  \
       std::vector<base_type > work(lwork);                                 \
       lapack_name1(&m, &n, &Q(0,0), &m, &tau[0], &work[0], &lwork, &info); \
       GMM_ASSERT1(!info, "QR factorization failed");                       \
       base_type *p = &R(0,0), *q = &Q(0,0);                                \
-      for (int j = 0; j < n; ++j, q += m-n)                                \
-        for (int i = 0; i < n; ++i, ++p, ++q)                              \
+      for (BLAS_INT j = 0; j < n; ++j, q += m-n)                           \
+        for (BLAS_INT i = 0; i < n; ++i, ++p, ++q)                         \
           *p = (j < i) ? base_type(0) : *q;                                \
       lapack_name2(&m, &n, &n, &Q(0,0), &m,&tau[0],&work[0],&lwork,&info); \
     }                                                                      \
@@ -207,9 +228,9 @@ namespace gmm {
   geqrf_interface2(cgeqrf_, cungqr_, BLAS_C)
   geqrf_interface2(zgeqrf_, zungqr_, BLAS_Z)
   
-  /* ********************************************************************* */
-  /* QR algorithm for eigenvalues search.                                  */
-  /* ********************************************************************* */
+  /* ********************************************************************** */
+  /* QR algorithm for eigenvalues search.                                   */
+  /* ********************************************************************** */
 
 # define gees_interface(lapack_name, base_type)                            \
   template <typename VECT> inline void implicit_qr_algorithm(              \
@@ -218,17 +239,18 @@ namespace gmm {
          double tol=gmm::default_tol(base_type()), bool compvect = true) { \
     GMMLAPACK_TRACE("gees_interface");                                     \
     typedef bool (*L_fp)(...);  L_fp p = 0;                                \
-    int n(mat_nrows(A)), info, lwork(-1), sdim; base_type work1;           \
+    BLAS_INT n=BLAS_INT(mat_nrows(A)), info(0), lwork(-1), sdim;           \
+    base_type work1;                                                       \
     if (!n) return;                                                        \
     dense_matrix<base_type > H(n,n); gmm::copy(A, H);                      \
     char jobvs = (compvect ? 'V' : 'N'), sort = 'N';                       \
     std::vector<double> rwork(n), eigv1(n), eigv2(n);                      \
     lapack_name(&jobvs, &sort, p, &n, &H(0,0), &n, &sdim, &eigv1[0],       \
                 &eigv2[0], &Q(0,0), &n, &work1, &lwork, &rwork[0], &info); \
-    lwork = int(gmm::real(work1));                                         \
+    lwork = BLAS_INT(gmm::real(work1));                                    \
     std::vector<base_type > work(lwork);                                   \
     lapack_name(&jobvs, &sort, p, &n, &H(0,0), &n, &sdim, &eigv1[0],       \
-		&eigv2[0], &Q(0,0), &n, &work[0], &lwork, &rwork[0],&info);\
+                &eigv2[0], &Q(0,0), &n, &work[0], &lwork, &rwork[0],&info);\
     GMM_ASSERT1(!info, "QR algorithm failed");                             \
     extract_eig(H, const_cast<VECT &>(eigval_), tol);                      \
   }
@@ -240,14 +262,15 @@ namespace gmm {
          double tol=gmm::default_tol(base_type()), bool compvect = true) { \
     GMMLAPACK_TRACE("gees_interface2");                                    \
     typedef bool (*L_fp)(...);  L_fp p = 0;                                \
-    int n(mat_nrows(A)), info, lwork(-1), sdim; base_type work1;           \
+    BLAS_INT n=BLAS_INT(mat_nrows(A)), info(0), lwork(-1), sdim;           \
+    base_type work1;                                                       \
     if (!n) return;                                                        \
     dense_matrix<base_type > H(n,n); gmm::copy(A, H);                      \
     char jobvs = (compvect ? 'V' : 'N'), sort = 'N';                       \
     std::vector<double> rwork(n), eigvv(n*2);                              \
     lapack_name(&jobvs, &sort, p, &n, &H(0,0), &n, &sdim, &eigvv[0],       \
                 &Q(0,0), &n, &work1, &lwork, &rwork[0], &rwork[0], &info); \
-    lwork = int(gmm::real(work1));                                         \
+    lwork = BLAS_INT(gmm::real(work1));                                    \
     std::vector<base_type > work(lwork);                                   \
     lapack_name(&jobvs, &sort, p, &n, &H(0,0), &n, &sdim, &eigvv[0],       \
                 &Q(0,0), &n, &work[0], &lwork, &rwork[0], &rwork[0],&info);\
@@ -260,103 +283,202 @@ namespace gmm {
   gees_interface2(cgees_, BLAS_C)
   gees_interface2(zgees_, BLAS_Z)
 
-# define geev_int_right(lapack_name, base_type)			           \
-  template <typename VECT> inline void geev_interface_right(               \
+
+# define jobv_right char jobvl = 'N', jobvr = 'V';
+# define jobv_left char jobvl = 'V', jobvr = 'N';
+
+# define geev_interface(lapack_name, base_type, side)                      \
+  template <typename VECT> inline void geev_interface_ ## side(            \
          const dense_matrix<base_type > &A,  const VECT &eigval_,          \
-         dense_matrix<base_type > &Q) {		                           \
+         dense_matrix<base_type > &Q) {                                    \
     GMMLAPACK_TRACE("geev_interface");                                     \
-    int n(mat_nrows(A)), info, lwork(-1); base_type work1;                 \
+    BLAS_INT n = BLAS_INT(mat_nrows(A)), info(0), lwork(-1);               \
+    base_type work1;                                                       \
     if (!n) return;                                                        \
     dense_matrix<base_type > H(n,n); gmm::copy(A, H);                      \
-    char jobvl = 'N', jobvr = 'V';                                         \
+    jobv_ ## side                                                          \
     std::vector<base_type > eigvr(n), eigvi(n);                            \
     lapack_name(&jobvl, &jobvr, &n, &H(0,0), &n, &eigvr[0], &eigvi[0],     \
-		&Q(0,0), &n, &Q(0,0), &n, &work1, &lwork, &info);   	   \
-    lwork = int(gmm::real(work1));                                         \
+                &Q(0,0), &n, &Q(0,0), &n, &work1, &lwork, &info);          \
+    lwork = BLAS_INT(gmm::real(work1));                                    \
     std::vector<base_type > work(lwork);                                   \
     lapack_name(&jobvl, &jobvr, &n, &H(0,0), &n, &eigvr[0], &eigvi[0],     \
-		&Q(0,0), &n, &Q(0,0), &n, &work[0], &lwork, &info);    	   \
+                &Q(0,0), &n, &Q(0,0), &n, &work[0], &lwork, &info);        \
     GMM_ASSERT1(!info, "QR algorithm failed");                             \
-    gmm::copy(eigvr, gmm::real_part(const_cast<VECT &>(eigval_)));	   \
-    gmm::copy(eigvi, gmm::imag_part(const_cast<VECT &>(eigval_)));	   \
+    gmm::copy(eigvr, gmm::real_part(const_cast<VECT &>(eigval_)));         \
+    gmm::copy(eigvi, gmm::imag_part(const_cast<VECT &>(eigval_)));         \
   }
 
-# define geev_int_rightc(lapack_name, base_type)			   \
-  template <typename VECT> inline void geev_interface_right(               \
+# define geev_interface2(lapack_name, base_type, side)                     \
+  template <typename VECT> inline void geev_interface_ ## side(            \
          const dense_matrix<base_type > &A,  const VECT &eigval_,          \
-         dense_matrix<base_type > &Q) {		                           \
+         dense_matrix<base_type > &Q) {                                    \
     GMMLAPACK_TRACE("geev_interface");                                     \
-    int n(mat_nrows(A)), info, lwork(-1); base_type work1;                 \
+    BLAS_INT n = BLAS_INT(mat_nrows(A)), info(0), lwork(-1);               \
+    base_type work1;                                                       \
     if (!n) return;                                                        \
     dense_matrix<base_type > H(n,n); gmm::copy(A, H);                      \
-    char jobvl = 'N', jobvr = 'V';                                         \
-    std::vector<double> rwork(2*n);                                        \
+    jobv_ ## side                                                          \
+    std::vector<base_type::value_type> rwork(2*n);                         \
     std::vector<base_type> eigv(n);                                        \
     lapack_name(&jobvl, &jobvr, &n, &H(0,0), &n, &eigv[0], &Q(0,0), &n,    \
-		&Q(0,0), &n, &work1, &lwork, &rwork[0], &info);	   	   \
-    lwork = int(gmm::real(work1));                                         \
+                &Q(0,0), &n, &work1, &lwork, &rwork[0], &info);            \
+    lwork = BLAS_INT(gmm::real(work1));                                    \
     std::vector<base_type > work(lwork);                                   \
     lapack_name(&jobvl, &jobvr, &n, &H(0,0), &n, &eigv[0], &Q(0,0), &n,    \
-		&Q(0,0), &n, &work[0], &lwork,  &rwork[0],  &info);	   \
+                &Q(0,0), &n, &work[0], &lwork,  &rwork[0],  &info);        \
     GMM_ASSERT1(!info, "QR algorithm failed");                             \
-    gmm::copy(eigv, const_cast<VECT &>(eigval_));			   \
+    gmm::copy(eigv, const_cast<VECT &>(eigval_));                          \
   }
 
-  geev_int_right(sgeev_, BLAS_S)
-  geev_int_right(dgeev_, BLAS_D)
-  geev_int_rightc(cgeev_, BLAS_C)
-  geev_int_rightc(zgeev_, BLAS_Z)
+  geev_interface(sgeev_, BLAS_S, right)
+  geev_interface(dgeev_, BLAS_D, right)
+  geev_interface2(cgeev_, BLAS_C, right)
+  geev_interface2(zgeev_, BLAS_Z, right)
 
-# define geev_int_left(lapack_name, base_type)                             \
-  template <typename VECT> inline void geev_interface_left(                \
-         const dense_matrix<base_type > &A,  const VECT &eigval_,          \
-         dense_matrix<base_type > &Q) {	 	                           \
-    GMMLAPACK_TRACE("geev_interface");                                     \
-    int n(mat_nrows(A)), info, lwork(-1); base_type work1;                 \
-    if (!n) return;                                                        \
-    dense_matrix<base_type > H(n,n); gmm::copy(A, H);                      \
-    char jobvl = 'V', jobvr = 'N';                                         \
-    std::vector<base_type > eigvr(n), eigvi(n);                            \
-    lapack_name(&jobvl, &jobvr, &n, &H(0,0), &n, &eigvr[0], &eigvi[0],     \
-		&Q(0,0), &n, &Q(0,0), &n, &work1, &lwork, &info);   	   \
-    lwork = int(gmm::real(work1));                                         \
-    std::vector<base_type > work(lwork);                                   \
-    lapack_name(&jobvl, &jobvr, &n, &H(0,0), &n, &eigvr[0], &eigvi[0],     \
-		&Q(0,0), &n, &Q(0,0), &n, &work[0], &lwork, &info);    	   \
-    GMM_ASSERT1(!info, "QR algorithm failed");                             \
-    gmm::copy(eigvr, gmm::real_part(const_cast<VECT &>(eigval_)));	   \
-    gmm::copy(eigvi, gmm::imag_part(const_cast<VECT &>(eigval_)));	   \
+  geev_interface(sgeev_, BLAS_S, left)
+  geev_interface(dgeev_, BLAS_D, left)
+  geev_interface2(cgeev_, BLAS_C, left)
+  geev_interface2(zgeev_, BLAS_Z, left) 
+    
+
+  /* ********************************************************************** */
+  /* SCHUR algorithm:                                                       */
+  /*  A = Q*S*(Q^T), with Q orthogonal and S upper quasi-triangula          */
+  /* ********************************************************************** */
+
+# define geesx_interface(lapack_name, base_type) inline                 \
+  void schur(dense_matrix<base_type> &A,                                \
+             dense_matrix<base_type> &S,                                \
+             dense_matrix<base_type> &Q) {                              \
+    GMMLAPACK_TRACE("geesx_interface");                                 \
+    BLAS_INT m = BLAS_INT(mat_nrows(A)), n = BLAS_INT(mat_ncols(A));    \
+    GMM_ASSERT1(m == n, "Schur decomposition requires square matrix");  \
+    char jobvs = 'V', sort = 'N', sense = 'N';                          \
+    bool select = false;                                                \
+    BLAS_INT lwork = 8*n, sdim = 0, liwork = 1;                         \
+    std::vector<base_type> work(lwork), wr(n), wi(n);                   \
+    std::vector<BLAS_INT> iwork(liwork);                                \
+    std::vector<BLAS_INT> bwork(1);                                     \
+    resize(S, n, n); copy(A, S);                                        \
+    resize(Q, n, n);                                                    \
+    base_type rconde(0), rcondv(0);                                     \
+    BLAS_INT info(0);							\
+    lapack_name(&jobvs, &sort, &select, &sense, &n, &S(0,0), &n,        \
+                &sdim, &wr[0], &wi[0], &Q(0,0), &n, &rconde, &rcondv,   \
+                &work[0], &lwork, &iwork[0], &liwork, &bwork[0], &info);\
+    GMM_ASSERT1(!info, "SCHUR algorithm failed");			\
   }
 
-# define geev_int_leftc(lapack_name, base_type)	  		           \
-  template <typename VECT> inline void geev_interface_left(                \
-         const dense_matrix<base_type > &A,  const VECT &eigval_,          \
-         dense_matrix<base_type > &Q) {		                           \
-    GMMLAPACK_TRACE("geev_interface");                                     \
-    int n(mat_nrows(A)), info, lwork(-1); base_type work1;                 \
-    if (!n) return;                                                        \
-    dense_matrix<base_type > H(n,n); gmm::copy(A, H);                      \
-    char jobvl = 'V', jobvr = 'N';                                         \
-    std::vector<double> rwork(2*n);                                        \
-    std::vector<base_type> eigv(n);                                        \
-    lapack_name(&jobvl, &jobvr, &n, &H(0,0), &n, &eigv[0], &Q(0,0), &n,    \
-		&Q(0,0), &n, &work1, &lwork, &rwork[0], &info);	   	   \
-    lwork = int(gmm::real(work1));                                         \
-    std::vector<base_type > work(lwork);                                   \
-    lapack_name(&jobvl, &jobvr, &n, &H(0,0), &n, &eigv[0], &Q(0,0), &n,    \
-		&Q(0,0), &n, &work[0], &lwork,  &rwork[0],  &info);	   \
-    GMM_ASSERT1(!info, "QR algorithm failed");                             \
-    gmm::copy(eigv, const_cast<VECT &>(eigval_));			   \
+# define geesx_interface2(lapack_name, base_type) inline                \
+  void schur(dense_matrix<base_type> &A,                                \
+             dense_matrix<base_type> &S,                                \
+             dense_matrix<base_type> &Q) {                              \
+    GMMLAPACK_TRACE("geesx_interface");                                 \
+    BLAS_INT m = BLAS_INT(mat_nrows(A)), n = BLAS_INT(mat_ncols(A));    \
+    GMM_ASSERT1(m == n, "Schur decomposition requires square matrix");  \
+    char jobvs = 'V', sort = 'N', sense = 'N';                          \
+    bool select = false;                                                \
+    BLAS_INT lwork = 8*n, sdim = 0;                                     \
+    std::vector<base_type::value_type> rwork(lwork);                    \
+    std::vector<base_type> work(lwork), w(n);                           \
+    std::vector<BLAS_INT> bwork(1);                                     \
+    resize(S, n, n); copy(A, S);                                        \
+    resize(Q, n, n);                                                    \
+    base_type rconde(0), rcondv(0);                                     \
+    BLAS_INT info(0);							\
+    lapack_name(&jobvs, &sort, &select, &sense, &n, &S(0,0), &n,        \
+                &sdim, &w[0], &Q(0,0), &n, &rconde, &rcondv,            \
+                &work[0], &lwork, &rwork[0], &bwork[0], &info);         \
+    GMM_ASSERT1(!info, "SCHUR algorithm failed");                       \
+  }
+
+  geesx_interface(sgeesx_, BLAS_S)
+  geesx_interface(dgeesx_, BLAS_D)
+  geesx_interface2(cgeesx_, BLAS_C)
+  geesx_interface2(zgeesx_, BLAS_Z)
+
+  template <typename MAT>
+  void schur(const MAT &A_, MAT &S, MAT &Q) {
+   MAT A(A_);
+   schur(A, S, Q);
   }
 
-  geev_int_left(sgeev_, BLAS_S)
-  geev_int_left(dgeev_, BLAS_D)
-  geev_int_leftc(cgeev_, BLAS_C)
-  geev_int_leftc(zgeev_, BLAS_Z) 
+
+  /* ********************************************************************** */
+  /* Interface to SVD. Does not correspond to a Gmm++ functionnality.       */
+  /* Author : Sebastian Nowozin <sebastian.nowozin@tuebingen.mpg.de>        */
+  /* ********************************************************************** */
+    
+# define gesvd_interface(lapack_name, base_type) inline                 \
+  void svd(dense_matrix<base_type> &X,                                  \
+           dense_matrix<base_type> &U,                                  \
+           dense_matrix<base_type> &Vtransposed,                        \
+           std::vector<base_type> &sigma) {                             \
+    GMMLAPACK_TRACE("gesvd_interface");                                 \
+    BLAS_INT m = BLAS_INT(mat_nrows(X)), n = BLAS_INT(mat_ncols(X));    \
+    BLAS_INT mn_min = m < n ? m : n;                                    \
+    sigma.resize(mn_min);                                               \
+    std::vector<base_type> work(15 * mn_min);                           \
+    BLAS_INT lwork = BLAS_INT(work.size());                             \
+    resize(U, m, m);                                                    \
+    resize(Vtransposed, n, n);                                          \
+    char job = 'A';                                                     \
+    BLAS_INT info(0);							\
+    lapack_name(&job, &job, &m, &n, &X(0,0), &m, &sigma[0], &U(0,0),    \
+                &m, &Vtransposed(0,0), &n, &work[0], &lwork, &info);    \
+  }
+
+# define cgesvd_interface(lapack_name, base_type, base_type2) inline    \
+  void svd(dense_matrix<base_type> &X,                                  \
+           dense_matrix<base_type> &U,                                  \
+           dense_matrix<base_type> &Vtransposed,                        \
+           std::vector<base_type2> &sigma) {                            \
+    GMMLAPACK_TRACE("gesvd_interface");                                 \
+    BLAS_INT m = BLAS_INT(mat_nrows(X)), n = BLAS_INT(mat_ncols(X));    \
+    BLAS_INT mn_min = m < n ? m : n;                                    \
+    sigma.resize(mn_min);                                               \
+    std::vector<base_type> work(15 * mn_min);                           \
+    std::vector<base_type2> rwork(5 * mn_min);                          \
+    BLAS_INT lwork = BLAS_INT(work.size());                             \
+    resize(U, m, m);                                                    \
+    resize(Vtransposed, n, n);                                          \
+    char job = 'A';                                                     \
+    BLAS_INT info(0);							\
+    lapack_name(&job, &job, &m, &n, &X(0,0), &m, &sigma[0], &U(0,0),    \
+                &m, &Vtransposed(0,0), &n, &work[0], &lwork,            \
+                &rwork[0], &info);                                      \
+  }
+  
+  gesvd_interface(sgesvd_, BLAS_S)
+  gesvd_interface(dgesvd_, BLAS_D)
+  cgesvd_interface(cgesvd_, BLAS_C, BLAS_S)
+  cgesvd_interface(zgesvd_, BLAS_Z, BLAS_D)
+
+  template <typename MAT, typename VEC>
+  void svd(const MAT &X_, MAT &U, MAT &Vtransposed, VEC &sigma) {
+   MAT X(X_);
+   svd(X, U, Vtransposed, sigma);
+  }
     
 
+
+
 }
 
-#endif // GMM_LAPACK_INTERFACE_H
+#else
+
+namespace gmm
+{
+template <typename MAT>
+void schur(const MAT &A_, MAT &S, MAT &Q)
+{
+  GMM_ASSERT1(false, "Use of function schur(A,S,Q) requires GetFEM "
+              "to be built with Lapack");
+}
+
+}// namespace gmm
 
-#endif // GMM_USES_LAPACK || GMM_USES_ATLAS
+#endif // GMM_USES_LAPACK
+
+#endif // GMM_LAPACK_INTERFACE_H
diff --git a/contrib/gmm/gmm_least_squares_cg.h b/contrib/gmm/gmm_least_squares_cg.h
index 711d3348a2..e4e22ae007 100644
--- a/contrib/gmm/gmm_least_squares_cg.h
+++ b/contrib/gmm/gmm_least_squares_cg.h
@@ -1,32 +1,33 @@
-// -*- c++ -*- (enables emacs c++ mode)
-//===========================================================================
-//
-// Copyright (C) 2002-2008 Yves Renard
-//
-// This file is a part of GETFEM++
-//
-// Getfem++  is  free software;  you  can  redistribute  it  and/or modify it
-// under  the  terms  of the  GNU  Lesser General Public License as published
-// by  the  Free Software Foundation;  either version 2.1 of the License,  or
-// (at your option) any later version.
-// This program  is  distributed  in  the  hope  that it will be useful,  but
-// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-// or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
-// License for more details.
-// You  should  have received a copy of the GNU Lesser General Public License
-// along  with  this program;  if not, write to the Free Software Foundation,
-// Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
-//
-// As a special exception, you may use this file as part of a free software
-// library without restriction.  Specifically, if other files instantiate
-// templates or use macros or inline functions from this file, or you compile
-// this file and link it with other files to produce an executable, this
-// file does not by itself cause the resulting executable to be covered by
-// the GNU General Public License.  This exception does not however
-// invalidate any other reasons why the executable file might be covered by
-// the GNU General Public License.
-//
-//===========================================================================
+/* -*- c++ -*- (enables emacs c++ mode) */
+/*===========================================================================
+
+ Copyright (C) 2002-2020 Yves Renard, Benjamin Schleimer
+
+ This file is a part of GetFEM
+
+ GetFEM  is  free software;  you  can  redistribute  it  and/or modify it
+ under  the  terms  of the  GNU  Lesser General Public License as published
+ by  the  Free Software Foundation;  either version 3 of the License,  or
+ (at your option) any later version along with the GCC Runtime Library
+ Exception either version 3.1 or (at your option) any later version.
+ This program  is  distributed  in  the  hope  that it will be useful,  but
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+ License and GCC Runtime Library Exception for more details.
+ You  should  have received a copy of the GNU Lesser General Public License
+ along  with  this program;  if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+
+ As a special exception, you  may use  this file  as it is a part of a free
+ software  library  without  restriction.  Specifically,  if   other  files
+ instantiate  templates  or  use macros or inline functions from this file,
+ or  you compile this  file  and  link  it  with other files  to produce an
+ executable, this file  does  not  by itself cause the resulting executable
+ to be covered  by the GNU Lesser General Public License.  This   exception
+ does not  however  invalidate  any  other  reasons why the executable file
+ might be covered by the GNU Lesser General Public License.
+
+===========================================================================*/
 
 /**@file gmm_leastsquares_cg.h
    @author Benjamin Schleimer <bensch128  (at) yahoo (dot) com>
diff --git a/contrib/gmm/gmm_matrix.h b/contrib/gmm/gmm_matrix.h
index 09946f09e5..771a246f45 100644
--- a/contrib/gmm/gmm_matrix.h
+++ b/contrib/gmm/gmm_matrix.h
@@ -1,32 +1,33 @@
-// -*- c++ -*- (enables emacs c++ mode)
-//===========================================================================
-//
-// Copyright (C) 2002-2008 Yves Renard
-//
-// This file is a part of GETFEM++
-//
-// Getfem++  is  free software;  you  can  redistribute  it  and/or modify it
-// under  the  terms  of the  GNU  Lesser General Public License as published
-// by  the  Free Software Foundation;  either version 2.1 of the License,  or
-// (at your option) any later version.
-// This program  is  distributed  in  the  hope  that it will be useful,  but
-// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-// or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
-// License for more details.
-// You  should  have received a copy of the GNU Lesser General Public License
-// along  with  this program;  if not, write to the Free Software Foundation,
-// Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
-//
-// As a special exception, you may use this file as part of a free software
-// library without restriction.  Specifically, if other files instantiate
-// templates or use macros or inline functions from this file, or you compile
-// this file and link it with other files to produce an executable, this
-// file does not by itself cause the resulting executable to be covered by
-// the GNU General Public License.  This exception does not however
-// invalidate any other reasons why the executable file might be covered by
-// the GNU General Public License.
-//
-//===========================================================================
+/* -*- c++ -*- (enables emacs c++ mode) */
+/*===========================================================================
+
+ Copyright (C) 2002-2020 Yves Renard
+
+ This file is a part of GetFEM
+
+ GetFEM  is  free software;  you  can  redistribute  it  and/or modify it
+ under  the  terms  of the  GNU  Lesser General Public License as published
+ by  the  Free Software Foundation;  either version 3 of the License,  or
+ (at your option) any later version along with the GCC Runtime Library
+ Exception either version 3.1 or (at your option) any later version.
+ This program  is  distributed  in  the  hope  that it will be useful,  but
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+ License and GCC Runtime Library Exception for more details.
+ You  should  have received a copy of the GNU Lesser General Public License
+ along  with  this program;  if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+
+ As a special exception, you  may use  this file  as it is a part of a free
+ software  library  without  restriction.  Specifically,  if   other  files
+ instantiate  templates  or  use macros or inline functions from this file,
+ or  you compile this  file  and  link  it  with other files  to produce an
+ executable, this file  does  not  by itself cause the resulting executable
+ to be covered  by the GNU Lesser General Public License.  This   exception
+ does not  however  invalidate  any  other  reasons why the executable file
+ might be covered by the GNU Lesser General Public License.
+
+===========================================================================*/
 
 /** @file gmm_matrix.h
    @author  Yves Renard <Yves.Renard@insa-lyon.fr>
@@ -47,9 +48,9 @@ namespace gmm
 {
 
   /* ******************************************************************** */
-  /*		                                            		  */
-  /*		Identity matrix                         		  */
-  /*		                                            		  */
+  /*                                                                      */
+  /*            Identity matrix                                           */
+  /*                                                                      */
   /* ******************************************************************** */
 
   struct identity_matrix {
@@ -63,14 +64,14 @@ namespace gmm
       v1(i,i) += typename linalg_traits<M>::value_type(1);
   }
   template <typename M> inline
-  void add(const identity_matrix &I, const M &v1)
-  { add(I, linalg_const_cast(v1)); }
+  void add(const identity_matrix &II, const M &v1)
+  { add(II, linalg_const_cast(v1)); }
 
   template <typename V1, typename V2> inline
   void mult(const identity_matrix&, const V1 &v1, V2 &v2)
   { copy(v1, v2); }
   template <typename V1, typename V2> inline
-  void mult(const identity_matrix&, const V1 &v1, const V2 &v2) 
+  void mult(const identity_matrix&, const V1 &v1, const V2 &v2)
   { copy(v1, v2); }
   template <typename V1, typename V2, typename V3> inline
   void mult(const identity_matrix&, const V1 &v1, const V2 &v2, V3 &v3)
@@ -82,25 +83,25 @@ namespace gmm
   void left_mult(const identity_matrix&, const V1 &v1, V2 &v2)
   { copy(v1, v2); }
   template <typename V1, typename V2> inline
-  void left_mult(const identity_matrix&, const V1 &v1, const V2 &v2) 
+  void left_mult(const identity_matrix&, const V1 &v1, const V2 &v2)
   { copy(v1, v2); }
   template <typename V1, typename V2> inline
   void right_mult(const identity_matrix&, const V1 &v1, V2 &v2)
   { copy(v1, v2); }
   template <typename V1, typename V2> inline
-  void right_mult(const identity_matrix&, const V1 &v1, const V2 &v2) 
+  void right_mult(const identity_matrix&, const V1 &v1, const V2 &v2)
   { copy(v1, v2); }
   template <typename V1, typename V2> inline
   void transposed_left_mult(const identity_matrix&, const V1 &v1, V2 &v2)
   { copy(v1, v2); }
   template <typename V1, typename V2> inline
-  void transposed_left_mult(const identity_matrix&, const V1 &v1,const V2 &v2) 
+  void transposed_left_mult(const identity_matrix&, const V1 &v1,const V2 &v2)
   { copy(v1, v2); }
   template <typename V1, typename V2> inline
   void transposed_right_mult(const identity_matrix&, const V1 &v1, V2 &v2)
   { copy(v1, v2); }
   template <typename V1, typename V2> inline
-  void transposed_right_mult(const identity_matrix&,const V1 &v1,const V2 &v2) 
+  void transposed_right_mult(const identity_matrix&,const V1 &v1,const V2 &v2)
   { copy(v1, v2); }
   template <typename M> void copy_ident(const identity_matrix&, M &m) {
     size_type i = 0, n = std::min(mat_nrows(m), mat_ncols(m));
@@ -108,7 +109,7 @@ namespace gmm
     for (; i < n; ++i) m(i,i) = typename linalg_traits<M>::value_type(1);
   }
   template <typename M> inline void copy(const identity_matrix&, M &m)
-  { copy_ident(identity_matrix(), m); } 
+  { copy_ident(identity_matrix(), m); }
   template <typename M> inline void copy(const identity_matrix &, const M &m)
   { copy_ident(identity_matrix(), linalg_const_cast(m)); }
   template <typename V1, typename V2> inline
@@ -123,24 +124,24 @@ namespace gmm
   inline bool is_identity(const identity_matrix&) { return true; }
 
   /* ******************************************************************** */
-  /*		                                            		  */
-  /*		Row matrix                                   		  */
-  /*		                                            		  */
+  /*                                                                      */
+  /*            Row matrix                                                */
+  /*                                                                      */
   /* ******************************************************************** */
 
   template<typename V> class row_matrix {
   protected :
     std::vector<V> li; /* array of rows.                                  */
     size_type nc;
-    
+
   public :
-    
+
     typedef typename linalg_traits<V>::reference reference;
     typedef typename linalg_traits<V>::value_type value_type;
-    
+
     row_matrix(size_type r, size_type c) : li(r, V(c)), nc(c) {}
     row_matrix(void) : nc(0) {}
-    reference operator ()(size_type l, size_type c) 
+    reference operator ()(size_type l, size_type c)
     { return li[l][c]; }
     value_type operator ()(size_type l, size_type c) const
     { return li[l][c]; }
@@ -150,19 +151,19 @@ namespace gmm
 
     typename std::vector<V>::iterator begin(void)
     { return li.begin(); }
-    typename std::vector<V>::iterator end(void)  
+    typename std::vector<V>::iterator end(void)
     { return li.end(); }
     typename std::vector<V>::const_iterator begin(void) const
     { return li.begin(); }
     typename std::vector<V>::const_iterator end(void) const
     { return li.end(); }
-    
-    
+
+
     V& row(size_type i) { return li[i]; }
     const V& row(size_type i) const { return li[i]; }
     V& operator[](size_type i) { return li[i]; }
     const V& operator[](size_type i) const { return li[i]; }
-    
+
     inline size_type nrows(void) const { return li.size(); }
     inline size_type ncols(void) const { return nc;        }
 
@@ -171,9 +172,13 @@ namespace gmm
   };
 
   template<typename V> void row_matrix<V>::resize(size_type m, size_type n) {
+    size_type nr = std::min(nrows(), m);
     li.resize(m);
-    for (size_type i=0; i < m; ++i) gmm::resize(li[i], n);
-    nc = n;
+    for (size_type i=nr; i < m; ++i) gmm::resize(li[i], n);
+    if (n != nc) {
+      for (size_type i=0; i < nr; ++i) gmm::resize(li[i], n);
+      nc = n;
+    }
   }
 
 
@@ -188,8 +193,8 @@ namespace gmm
     typedef typename linalg_traits<V>::value_type value_type;
     typedef typename linalg_traits<V>::reference reference;
     typedef typename linalg_traits<V>::storage_type storage_type;
-    typedef simple_vector_ref<V *> sub_row_type;
-    typedef simple_vector_ref<const V *> const_sub_row_type;
+    typedef V & sub_row_type;
+    typedef const V & const_sub_row_type;
     typedef typename std::vector<V>::iterator row_iterator;
     typedef typename std::vector<V>::const_iterator const_row_iterator;
     typedef abstract_null_type sub_col_type;
@@ -208,7 +213,7 @@ namespace gmm
     { return m.end(); }
     static const_sub_row_type row(const const_row_iterator &it)
     { return const_sub_row_type(*it); }
-    static sub_row_type row(const row_iterator &it) 
+    static sub_row_type row(const row_iterator &it)
     { return sub_row_type(*it); }
     static origin_type* origin(this_type &m) { return &m; }
     static const origin_type* origin(const this_type &m) { return &m; }
@@ -227,21 +232,21 @@ namespace gmm
     (std::ostream &o, const row_matrix<V>& m) { gmm::write(o,m); return o; }
 
   /* ******************************************************************** */
-  /*		                                            		  */
-  /*		Column matrix                                		  */
-  /*		                                            		  */
+  /*                                                                      */
+  /*            Column matrix                                             */
+  /*                                                                      */
   /* ******************************************************************** */
 
   template<typename V> class col_matrix {
   protected :
     std::vector<V> li; /* array of columns.                               */
     size_type nr;
-    
+
   public :
-    
+
     typedef typename linalg_traits<V>::reference reference;
     typedef typename linalg_traits<V>::value_type value_type;
-    
+
     col_matrix(size_type r, size_type c) : li(c, V(r)), nr(r) { }
     col_matrix(void) : nr(0) {}
     reference operator ()(size_type l, size_type c)
@@ -259,13 +264,13 @@ namespace gmm
 
     typename std::vector<V>::iterator begin(void)
     { return li.begin(); }
-    typename std::vector<V>::iterator end(void)  
+    typename std::vector<V>::iterator end(void)
     { return li.end(); }
     typename std::vector<V>::const_iterator begin(void) const
     { return li.begin(); }
     typename std::vector<V>::const_iterator end(void) const
     { return li.end(); }
-    
+
     inline size_type ncols(void) const { return li.size(); }
     inline size_type nrows(void) const { return nr; }
 
@@ -274,9 +279,13 @@ namespace gmm
   };
 
   template<typename V> void col_matrix<V>::resize(size_type m, size_type n) {
+    size_type nc = std::min(ncols(), n);
     li.resize(n);
-    for (size_type i=0; i < n; ++i) gmm::resize(li[i], m);
-    nr = m;
+    for (size_type i=nc; i < n; ++i) gmm::resize(li[i], m);
+    if (m != nr) {
+      for (size_type i=0; i < nc; ++i) gmm::resize(li[i], m);
+      nr = m;
+    }
   }
 
   template<typename V> void col_matrix<V>::clear_mat()
@@ -290,8 +299,8 @@ namespace gmm
     typedef typename linalg_traits<V>::value_type value_type;
     typedef typename linalg_traits<V>::reference reference;
     typedef typename linalg_traits<V>::storage_type storage_type;
-    typedef simple_vector_ref<V *> sub_col_type;
-    typedef simple_vector_ref<const V *> const_sub_col_type;
+    typedef V &sub_col_type;
+    typedef const V &const_sub_col_type;
     typedef typename std::vector<V>::iterator col_iterator;
     typedef typename std::vector<V>::const_iterator const_col_iterator;
     typedef abstract_null_type sub_row_type;
@@ -309,9 +318,9 @@ namespace gmm
     static const_col_iterator col_end(const this_type &m)
     { return m.end(); }
     static const_sub_col_type col(const const_col_iterator &it)
-    { return const_sub_col_type(*it); }
-    static sub_col_type col(const col_iterator &it) 
-    { return sub_col_type(*it); }
+    { return *it; }
+    static sub_col_type col(const col_iterator &it)
+    { return *it; }
     static origin_type* origin(this_type &m) { return &m; }
     static const origin_type* origin(const this_type &m) { return &m; }
     static void do_clear(this_type &m) { m.clear_mat(); }
@@ -329,9 +338,9 @@ namespace gmm
     (std::ostream &o, const col_matrix<V>& m) { gmm::write(o,m); return o; }
 
   /* ******************************************************************** */
-  /*		                                            		  */
-  /*		Dense matrix                                		  */
-  /*		                                            		  */
+  /*                                                                      */
+  /*            Dense matrix                                              */
+  /*                                                                      */
   /* ******************************************************************** */
 
   template<typename T> class dense_matrix : public std::vector<T> {
@@ -339,30 +348,36 @@ namespace gmm
     typedef typename std::vector<T>::size_type size_type;
     typedef typename std::vector<T>::iterator iterator;
     typedef typename std::vector<T>::const_iterator const_iterator;
-    
+    typedef typename std::vector<T>::reference reference;
+    typedef typename std::vector<T>::const_reference const_reference;
+
   protected:
     size_type nbc, nbl;
-    
+
   public:
-    
-    inline const T& operator ()(size_type l, size_type c) const {
+
+    inline const_reference operator ()(size_type l, size_type c) const {
       GMM_ASSERT2(l < nbl && c < nbc, "out of range");
       return *(this->begin() + c*nbl+l);
     }
-    inline T& operator ()(size_type l, size_type c) {
+    inline reference operator ()(size_type l, size_type c) {
       GMM_ASSERT2(l < nbl && c < nbc, "out of range");
       return *(this->begin() + c*nbl+l);
     }
 
+    std::vector<T> &as_vector(void) { return *this; }
+    const std::vector<T> &as_vector(void) const { return *this; }
+
     void resize(size_type, size_type);
+    void base_resize(size_type, size_type);
     void reshape(size_type, size_type);
-    
+
     void fill(T a, T b = T(0));
     inline size_type nrows(void) const { return nbl; }
     inline size_type ncols(void) const { return nbc; }
     void swap(dense_matrix<T> &m)
     { std::vector<T>::swap(m); std::swap(nbc, m.nbc); std::swap(nbl, m.nbl); }
-    
+
     dense_matrix(size_type l, size_type c)
       : std::vector<T>(c*l), nbc(c), nbl(l)  {}
     dense_matrix(void) { nbl = nbc = 0; }
@@ -373,30 +388,34 @@ namespace gmm
     nbl = m; nbc = n;
   }
 
+  template<typename T> void dense_matrix<T>::base_resize(size_type m,
+                                                         size_type n)
+  { std::vector<T>::resize(n*m); nbl = m; nbc = n; }
+
   template<typename T> void dense_matrix<T>::resize(size_type m, size_type n) {
     if (n*m > nbc*nbl) std::vector<T>::resize(n*m);
     if (m < nbl) {
       for (size_type i = 1; i < std::min(nbc, n); ++i)
-	std::copy(this->begin()+i*nbl, this->begin()+(i*nbl+m),
-		  this->begin()+i*m);
+        std::copy(this->begin()+i*nbl, this->begin()+(i*nbl+m),
+                  this->begin()+i*m);
       for (size_type i = std::min(nbc, n); i < n; ++i)
-	std::fill(this->begin()+(i*m), this->begin()+(i+1)*m, T(0));
+        std::fill(this->begin()+(i*m), this->begin()+(i+1)*m, T(0));
       }
     else if (m > nbl) { /* do nothing when the nb of rows does not change */
       for (size_type i = std::min(nbc, n); i > 1; --i)
-	std::copy(this->begin()+(i-1)*nbl, this->begin()+i*nbl,
-		  this->begin()+(i-1)*m);
+        std::copy(this->begin()+(i-1)*nbl, this->begin()+i*nbl,
+                  this->begin()+(i-1)*m);
       for (size_type i = 0; i < std::min(nbc, n); ++i)
-	std::fill(this->begin()+(i*m+nbl), this->begin()+(i+1)*m, T(0));
+        std::fill(this->begin()+(i*m+nbl), this->begin()+(i+1)*m, T(0));
     }
     if (n*m < nbc*nbl) std::vector<T>::resize(n*m);
     nbl = m; nbc = n;
   }
-  
+
   template<typename T> void dense_matrix<T>::fill(T a, T b) {
     std::fill(this->begin(), this->end(), b);
     size_type n = std::min(nbl, nbc);
-    if (a != b) for (size_type i = 0; i < n; ++i) (*this)(i,i) = a; 
+    if (a != b) for (size_type i = 0; i < n; ++i) (*this)(i,i) = a;
   }
 
   template <typename T> struct linalg_traits<dense_matrix<T> > {
@@ -408,25 +427,25 @@ namespace gmm
     typedef T& reference;
     typedef abstract_dense storage_type;
     typedef tab_ref_reg_spaced_with_origin<typename this_type::iterator,
-					   this_type> sub_row_type;
+                                           this_type> sub_row_type;
     typedef tab_ref_reg_spaced_with_origin<typename this_type::const_iterator,
-					   this_type> const_sub_row_type;
+                                           this_type> const_sub_row_type;
     typedef dense_compressed_iterator<typename this_type::iterator,
-				      typename this_type::iterator,
-				      this_type *> row_iterator;
+                                      typename this_type::iterator,
+                                      this_type *> row_iterator;
     typedef dense_compressed_iterator<typename this_type::const_iterator,
-				      typename this_type::iterator,
-				      const this_type *> const_row_iterator;
-    typedef tab_ref_with_origin<typename this_type::iterator, 
-				this_type> sub_col_type;
+                                      typename this_type::iterator,
+                                      const this_type *> const_row_iterator;
+    typedef tab_ref_with_origin<typename this_type::iterator,
+                                this_type> sub_col_type;
     typedef tab_ref_with_origin<typename this_type::const_iterator,
-				this_type> const_sub_col_type;
+                                this_type> const_sub_col_type;
     typedef dense_compressed_iterator<typename this_type::iterator,
-				      typename this_type::iterator,
-				      this_type *> col_iterator;
+                                      typename this_type::iterator,
+                                      this_type *> col_iterator;
     typedef dense_compressed_iterator<typename this_type::const_iterator,
-				      typename this_type::iterator,
-				      const this_type *> const_col_iterator;
+                                      typename this_type::iterator,
+                                      const this_type *> const_col_iterator;
     typedef col_and_row sub_orientation;
     typedef linalg_true index_sorted;
     static size_type nrows(const this_type &m) { return m.nrows(); }
@@ -471,19 +490,19 @@ namespace gmm
   template<typename T> std::ostream &operator <<
     (std::ostream &o, const dense_matrix<T>& m) { gmm::write(o,m); return o; }
 
+
   /* ******************************************************************** */
   /*                                                                      */
-  /*	        Read only compressed sparse column matrix                 */
+  /*             Read only compressed sparse column matrix                */
   /*                                                                      */
   /* ******************************************************************** */
 
-  template <typename T, int shift = 0>
+  template <typename T, typename IND_TYPE = unsigned int, int shift = 0>
   struct csc_matrix {
-    typedef unsigned int IND_TYPE;
 
-    T *pr;        // values.
-    IND_TYPE *ir; // row indices.
-    IND_TYPE *jc; // column repartition on pr and ir.
+    std::vector<T> pr;
+    std::vector<IND_TYPE> ir;
+    std::vector<IND_TYPE> jc;
     size_type nc, nr;
 
     typedef T value_type;
@@ -498,79 +517,75 @@ namespace gmm
     template <typename PT1, typename PT2, typename PT3, int cshift>
     void init_with(const csc_matrix_ref<PT1,PT2,PT3,cshift>& B)
     { init_with_good_format(B); }
-    template <typename U, int cshift>    
-    void init_with(const csc_matrix<U, cshift>& B)
+    template <typename U, int cshift>
+    void init_with(const csc_matrix<U, IND_TYPE, cshift>& B)
     { init_with_good_format(B); }
 
     void init_with_identity(size_type n);
 
-    csc_matrix(void) : pr(0), ir(0), jc(0), nc(0), nr(0) {}
+    csc_matrix(void) :  nc(0), nr(0) {}
     csc_matrix(size_type nnr, size_type nnc);
-    ~csc_matrix() { if (pr) { delete[] pr; delete[] ir; delete[] jc; } }
 
     size_type nrows(void) const { return nr; }
     size_type ncols(void) const { return nc; }
-    void swap(csc_matrix<T, shift> &m) { 
-      std::swap(pr, m.pr); 
-      std::swap(ir,m.ir); std::swap(jc, m.jc); 
-      std::swap(nc, m.nc); std::swap(nr,m.nr);
+    void swap(csc_matrix<T, IND_TYPE, shift> &m) {
+      std::swap(pr, m.pr);
+      std::swap(ir, m.ir); std::swap(jc, m.jc);
+      std::swap(nc, m.nc); std::swap(nr, m.nr);
     }
     value_type operator()(size_type i, size_type j) const
     { return mat_col(*this, j)[i]; }
   };
 
-  template <typename T, int shift> template<typename Matrix>
-  void csc_matrix<T, shift>::init_with_good_format(const Matrix &B) {
+  template <typename T, typename IND_TYPE, int shift> template<typename Matrix>
+  void csc_matrix<T, IND_TYPE, shift>::init_with_good_format(const Matrix &B) {
     typedef typename linalg_traits<Matrix>::const_sub_col_type col_type;
-    if (pr) { delete[] pr; delete[] ir; delete[] jc; }
     nc = mat_ncols(B); nr = mat_nrows(B);
-    jc = new IND_TYPE[nc+1];
+    jc.resize(nc+1);
     jc[0] = shift;
     for (size_type j = 0; j < nc; ++j) {
-      jc[j+1] = jc[j] + nnz(mat_const_col(B, j));
+      jc[j+1] = IND_TYPE(jc[j] + nnz(mat_const_col(B, j)));
     }
-    pr = new T[jc[nc]];
-    ir = new IND_TYPE[jc[nc]];
+    pr.resize(jc[nc]);
+    ir.resize(jc[nc]);
     for (size_type j = 0; j < nc; ++j) {
       col_type col = mat_const_col(B, j);
-      typename linalg_traits<col_type>::const_iterator
-	it = vect_const_begin(col), ite = vect_const_end(col);
-      for (size_type k = 0; it != ite; ++it, ++k)
-	{ pr[jc[j]-shift+k] = *it; ir[jc[j]-shift+k] = it.index() + shift; }
+      typename linalg_traits<typename org_type<col_type>::t>::const_iterator
+        it = vect_const_begin(col), ite = vect_const_end(col);
+      for (size_type k = 0; it != ite; ++it, ++k) {
+        pr[jc[j]-shift+k] = *it;
+        ir[jc[j]-shift+k] = IND_TYPE(it.index() + shift);
+      }
     }
   }
-  
-  template <typename T, int shift> template <typename Matrix>
-  void csc_matrix<T, shift>::init_with(const Matrix &A) {
+
+  template <typename T, typename IND_TYPE, int shift>
+  template <typename Matrix>
+  void csc_matrix<T, IND_TYPE, shift>::init_with(const Matrix &A) {
     col_matrix<wsvector<T> > B(mat_nrows(A), mat_ncols(A));
     copy(A, B);
     init_with_good_format(B);
   }
-  
-  template <typename T, int shift>
-  void csc_matrix<T, shift>::init_with_identity(size_type n) {
-    if (pr) { delete[] pr; delete[] ir; delete[] jc; }
-    nc = nr = n; 
-    pr = new T[nc];
-    ir = new IND_TYPE[nc];
-    jc = new IND_TYPE[nc+1];
+
+  template <typename T, typename IND_TYPE, int shift>
+  void csc_matrix<T, IND_TYPE, shift>::init_with_identity(size_type n) {
+    nc = nr = n;
+    pr.resize(nc); ir.resize(nc); jc.resize(nc+1);
     for (size_type j = 0; j < nc; ++j)
       { ir[j] = jc[j] = shift + j; pr[j] = T(1); }
     jc[nc] = shift + nc;
   }
-  
-  template <typename T, int shift>
-  csc_matrix<T, shift>::csc_matrix(size_type nnr, size_type nnc)
+
+  template <typename T, typename IND_TYPE, int shift>
+  csc_matrix<T, IND_TYPE, shift>::csc_matrix(size_type nnr, size_type nnc)
     : nc(nnc), nr(nnr) {
-    pr = new T[1];  ir = new IND_TYPE[1];
-    jc = new IND_TYPE[nc+1];
+    pr.resize(1);  ir.resize(1); jc.resize(nc+1);
     for (size_type j = 0; j <= nc; ++j) jc[j] = shift;
   }
 
-  template <typename T, int shift>
-  struct linalg_traits<csc_matrix<T, shift> > {
-    typedef csc_matrix<T, shift> this_type;
-    typedef typename this_type::IND_TYPE IND_TYPE;
+  template <typename T, typename IND_TYPE, int shift>
+  struct linalg_traits<csc_matrix<T, IND_TYPE, shift> > {
+    typedef csc_matrix<T, IND_TYPE, shift> this_type;
     typedef linalg_const is_reference;
     typedef abstract_matrix linalg_type;
     typedef T value_type;
@@ -585,7 +600,7 @@ namespace gmm
     typedef cs_vector_ref<const T *, const IND_TYPE *, shift>
     const_sub_col_type;
     typedef sparse_compressed_iterator<const T *, const IND_TYPE *,
-				       const IND_TYPE *, shift>
+                                       const IND_TYPE *, shift>
     const_col_iterator;
     typedef abstract_null_type col_iterator;
     typedef col_major sub_orientation;
@@ -593,47 +608,47 @@ namespace gmm
     static size_type nrows(const this_type &m) { return m.nrows(); }
     static size_type ncols(const this_type &m) { return m.ncols(); }
     static const_col_iterator col_begin(const this_type &m)
-    { return const_col_iterator(m.pr, m.ir, m.jc, m.nr, m.pr); }
-    static const_col_iterator col_end(const this_type &m)
-    { return const_col_iterator(m.pr, m.ir, m.jc + m.nc, m.nr, m.pr); }
+    { return const_col_iterator(&m.pr[0],&m.ir[0],&m.jc[0], m.nr, &m.pr[0]); }
+    static const_col_iterator col_end(const this_type &m) {
+      return const_col_iterator(&m.pr[0],&m.ir[0],&m.jc[0]+m.nc,
+                                m.nr,&m.pr[0]);
+    }
     static const_sub_col_type col(const const_col_iterator &it) {
       return const_sub_col_type(it.pr + *(it.jc) - shift,
-				it.ir + *(it.jc) - shift,
-				*(it.jc + 1) - *(it.jc), it.n);
+                                it.ir + *(it.jc) - shift,
+                                *(it.jc + 1) - *(it.jc), it.n);
     }
-    static const origin_type* origin(const this_type &m) { return m.pr; }
+    static const origin_type* origin(const this_type &m) { return &m.pr[0]; }
     static void do_clear(this_type &m) { m.do_clear(); }
     static value_type access(const const_col_iterator &itcol, size_type j)
     { return col(itcol)[j]; }
   };
 
-  template <typename T, int shift>
+  template <typename T, typename IND_TYPE, int shift>
   std::ostream &operator <<
-    (std::ostream &o, const csc_matrix<T, shift>& m)
+    (std::ostream &o, const csc_matrix<T, IND_TYPE, shift>& m)
   { gmm::write(o,m); return o; }
-  
-  template <typename T, int shift>
-  inline void copy(const identity_matrix &, csc_matrix<T, shift>& M)
+
+  template <typename T, typename IND_TYPE, int shift>
+  inline void copy(const identity_matrix &, csc_matrix<T, IND_TYPE, shift>& M)
   { M.init_with_identity(mat_nrows(M)); }
 
-  template <typename Matrix, typename T, int shift>
-  inline void copy(const Matrix &A, csc_matrix<T, shift>& M)
+  template <typename Matrix, typename T, typename IND_TYPE, int shift>
+  inline void copy(const Matrix &A, csc_matrix<T, IND_TYPE, shift>& M)
   { M.init_with(A); }
 
   /* ******************************************************************** */
   /*                                                                      */
-  /*	        Read only compressed sparse row matrix                    */
+  /*             Read only compressed sparse row matrix                   */
   /*                                                                      */
   /* ******************************************************************** */
 
-  template <typename T, int shift = 0>
+  template <typename T, typename IND_TYPE = unsigned int, int shift = 0>
   struct csr_matrix {
 
-    typedef unsigned int IND_TYPE;
-
-    T *pr;        // values.
-    IND_TYPE *ir; // col indices.
-    IND_TYPE *jc; // row repartition on pr and ir.
+    std::vector<T> pr;        // values.
+    std::vector<IND_TYPE> ir; // col indices.
+    std::vector<IND_TYPE> jc; // row repartition on pr and ir.
     size_type nc, nr;
 
     typedef T value_type;
@@ -649,82 +664,77 @@ namespace gmm
     void init_with(const csr_matrix_ref<PT1,PT2,PT3,cshift>& B)
     { init_with_good_format(B); }
     template <typename U, int cshift>
-    void init_with(const csr_matrix<U, cshift>& B)
+    void init_with(const csr_matrix<U, IND_TYPE, cshift>& B)
     { init_with_good_format(B); }
 
     template <typename Matrix> void init_with(const Matrix &A);
     void init_with_identity(size_type n);
 
-    csr_matrix(void) : pr(0), ir(0), jc(0), nc(0), nr(0) {}
+    csr_matrix(void) : nc(0), nr(0) {}
     csr_matrix(size_type nnr, size_type nnc);
-    ~csr_matrix() { if (pr) { delete[] pr; delete[] ir; delete[] jc; } }
 
     size_type nrows(void) const { return nr; }
     size_type ncols(void) const { return nc; }
-    void swap(csr_matrix<T, shift> &m) { 
-      std::swap(pr, m.pr); 
-      std::swap(ir,m.ir); std::swap(jc, m.jc); 
+    void swap(csr_matrix<T, IND_TYPE, shift> &m) {
+      std::swap(pr, m.pr);
+      std::swap(ir,m.ir); std::swap(jc, m.jc);
       std::swap(nc, m.nc); std::swap(nr,m.nr);
     }
-   
+
     value_type operator()(size_type i, size_type j) const
     { return mat_row(*this, i)[j]; }
   };
-  
-  template <typename T, int shift> template <typename Matrix>
-  void csr_matrix<T, shift>::init_with_good_format(const Matrix &B) {
+
+  template <typename T, typename IND_TYPE, int shift> template <typename Matrix>
+  void csr_matrix<T, IND_TYPE, shift>::init_with_good_format(const Matrix &B) {
     typedef typename linalg_traits<Matrix>::const_sub_row_type row_type;
-    if (pr) { delete[] pr; delete[] ir; delete[] jc; }
     nc = mat_ncols(B); nr = mat_nrows(B);
-    jc = new IND_TYPE[nr+1];
+    jc.resize(nr+1);
     jc[0] = shift;
     for (size_type j = 0; j < nr; ++j) {
-      jc[j+1] = jc[j] + nnz(mat_const_row(B, j));
+      jc[j+1] = IND_TYPE(jc[j] + nnz(mat_const_row(B, j)));
     }
-    pr = new T[jc[nr]];
-    ir = new IND_TYPE[jc[nr]];
+    pr.resize(jc[nr]);
+    ir.resize(jc[nr]);
     for (size_type j = 0; j < nr; ++j) {
       row_type row = mat_const_row(B, j);
-      typename linalg_traits<row_type>::const_iterator
-	it = vect_const_begin(row), ite = vect_const_end(row);
-      for (size_type k = 0; it != ite; ++it, ++k)
-	{ pr[jc[j]-shift+k] = *it; ir[jc[j]-shift+k] = it.index()+shift; }
+      typename linalg_traits<typename org_type<row_type>::t>::const_iterator
+        it = vect_const_begin(row), ite = vect_const_end(row);
+      for (size_type k = 0; it != ite; ++it, ++k) {
+        pr[jc[j]-shift+k] = *it;
+        ir[jc[j]-shift+k] = IND_TYPE(it.index()+shift);
+      }
     }
   }
 
-  template <typename T, int shift> template <typename Matrix> 
-  void csr_matrix<T, shift>::init_with(const Matrix &A) { 
-    row_matrix<wsvector<T> > B(mat_nrows(A), mat_ncols(A)); 
-    copy(A, B); 
+  template <typename T, typename IND_TYPE, int shift> template <typename Matrix>
+  void csr_matrix<T, IND_TYPE, shift>::init_with(const Matrix &A) {
+    row_matrix<wsvector<T> > B(mat_nrows(A), mat_ncols(A));
+    copy(A, B);
     init_with_good_format(B);
   }
 
-  template <typename T, int shift> 
-  void csr_matrix<T, shift>::init_with_identity(size_type n) {
-    if (pr) { delete[] pr; delete[] ir; delete[] jc; }
-    nc = nr = n; 
-    pr = new T[nr];
-    ir = new IND_TYPE[nr];
-    jc = new IND_TYPE[nr+1];
+  template <typename T, typename IND_TYPE, int shift>
+  void csr_matrix<T, IND_TYPE, shift>::init_with_identity(size_type n) {
+    nc = nr = n;
+    pr.resize(nr); ir.resize(nr); jc.resize(nr+1);
     for (size_type j = 0; j < nr; ++j)
       { ir[j] = jc[j] = shift + j; pr[j] = T(1); }
     jc[nr] = shift + nr;
   }
 
-  template <typename T, int shift>
-  csr_matrix<T, shift>::csr_matrix(size_type nnr, size_type nnc)
+  template <typename T, typename IND_TYPE, int shift>
+  csr_matrix<T, IND_TYPE, shift>::csr_matrix(size_type nnr, size_type nnc)
     : nc(nnc), nr(nnr) {
-    pr = new T[1];  ir = new IND_TYPE[1];
-    jc = new IND_TYPE[nr+1];
+    pr.resize(1);  ir.resize(1); jc.resize(nr+1);
     for (size_type j = 0; j < nr; ++j) jc[j] = shift;
     jc[nr] = shift;
   }
 
 
-  template <typename T, int shift>
-  struct linalg_traits<csr_matrix<T, shift> > {
-    typedef csr_matrix<T, shift> this_type;
-    typedef typename this_type::IND_TYPE IND_TYPE;
+  template <typename T, typename IND_TYPE, int shift>
+  struct linalg_traits<csr_matrix<T, IND_TYPE, shift> > {
+    typedef csr_matrix<T, IND_TYPE, shift> this_type;
     typedef linalg_const is_reference;
     typedef abstract_matrix linalg_type;
     typedef T value_type;
@@ -739,7 +749,7 @@ namespace gmm
     typedef cs_vector_ref<const T *, const IND_TYPE *, shift>
     const_sub_row_type;
     typedef sparse_compressed_iterator<const T *, const IND_TYPE *,
-				       const IND_TYPE *, shift>
+                                       const IND_TYPE *, shift>
     const_row_iterator;
     typedef abstract_null_type row_iterator;
     typedef row_major sub_orientation;
@@ -747,37 +757,37 @@ namespace gmm
     static size_type nrows(const this_type &m) { return m.nrows(); }
     static size_type ncols(const this_type &m) { return m.ncols(); }
     static const_row_iterator row_begin(const this_type &m)
-    { return const_row_iterator(m.pr, m.ir, m.jc, m.nc, m.pr); }
+    { return const_row_iterator(&m.pr[0], &m.ir[0], &m.jc[0], m.nc, &m.pr[0]); }
     static const_row_iterator row_end(const this_type &m)
-    { return const_row_iterator(m.pr, m.ir, m.jc + m.nr, m.nc, m.pr); }
+    { return const_row_iterator(&m.pr[0], &m.ir[0], &m.jc[0] + m.nr, m.nc, &m.pr[0]); }
     static const_sub_row_type row(const const_row_iterator &it) {
       return const_sub_row_type(it.pr + *(it.jc) - shift,
-				it.ir + *(it.jc) - shift,
-				*(it.jc + 1) - *(it.jc), it.n);
+                                it.ir + *(it.jc) - shift,
+                                *(it.jc + 1) - *(it.jc), it.n);
     }
-    static const origin_type* origin(const this_type &m) { return m.pr; }
+    static const origin_type* origin(const this_type &m) { return &m.pr[0]; }
     static void do_clear(this_type &m) { m.do_clear(); }
     static value_type access(const const_row_iterator &itrow, size_type j)
     { return row(itrow)[j]; }
   };
 
-  template <typename T, int shift>
+  template <typename T, typename IND_TYPE, int shift>
   std::ostream &operator <<
-    (std::ostream &o, const csr_matrix<T, shift>& m)
+    (std::ostream &o, const csr_matrix<T, IND_TYPE, shift>& m)
   { gmm::write(o,m); return o; }
-  
-  template <typename T, int shift>
-  inline void copy(const identity_matrix &, csr_matrix<T, shift>& M)
+
+  template <typename T, typename IND_TYPE, int shift>
+  inline void copy(const identity_matrix &, csr_matrix<T, IND_TYPE, shift>& M)
   { M.init_with_identity(mat_nrows(M)); }
 
-  template <typename Matrix, typename T, int shift>
-  inline void copy(const Matrix &A, csr_matrix<T, shift>& M)
+  template <typename Matrix, typename T, typename IND_TYPE, int shift>
+  inline void copy(const Matrix &A, csr_matrix<T, IND_TYPE, shift>& M)
   { M.init_with(A); }
 
   /* ******************************************************************** */
-  /*		                                            		  */
-  /*		Block matrix                                		  */
-  /*		                                            		  */
+  /*                                                                      */
+  /*             Block matrix                                             */
+  /*                                                                      */
   /* ******************************************************************** */
 
   template <typename MAT> class block_matrix {
@@ -797,7 +807,7 @@ namespace gmm
     size_type ncolblocks(void) const { return ncolblocks_; }
     const sub_interval &subrowinterval(size_type i) const { return introw[i]; }
     const sub_interval &subcolinterval(size_type i) const { return intcol[i]; }
-    const MAT &block(size_type i, size_type j) const 
+    const MAT &block(size_type i, size_type j) const
     { return blocks[j*ncolblocks_+i]; }
     MAT &block(size_type i, size_type j)
     { return blocks[j*ncolblocks_+i]; }
@@ -806,20 +816,20 @@ namespace gmm
     value_type operator() (size_type i, size_type j) const {
       size_type k, l;
       for (k = 0; k < nrowblocks_; ++k)
-	if (i >= introw[k].min && i <  introw[k].max) break;
+        if (i >= introw[k].min && i <  introw[k].max) break;
       for (l = 0; l < nrowblocks_; ++l)
-	if (j >= introw[l].min && j <  introw[l].max) break;
+        if (j >= introw[l].min && j <  introw[l].max) break;
       return (block(k, l))(i - introw[k].min, j - introw[l].min);
     }
     reference operator() (size_type i, size_type j) {
       size_type k, l;
       for (k = 0; k < nrowblocks_; ++k)
-	if (i >= introw[k].min && i <  introw[k].max) break;
+        if (i >= introw[k].min && i <  introw[k].max) break;
       for (l = 0; l < nrowblocks_; ++l)
-	if (j >= introw[l].min && j <  introw[l].max) break;
+        if (j >= introw[l].min && j <  introw[l].max) break;
       return (block(k, l))(i - introw[k].min, j - introw[l].min);
     }
-    
+
     template <typename CONT> void resize(const CONT &c1, const CONT &c2);
     template <typename CONT> block_matrix(const CONT &c1, const CONT &c2)
     { resize(c1, c2); }
@@ -850,17 +860,17 @@ namespace gmm
     static origin_type* origin(this_type &m) { return &m; }
     static const origin_type* origin(const this_type &m) { return &m; }
     static void do_clear(this_type &m) { m.do_clear(); }
-    // access to be done ...    
+    // access to be done ...
     static void resize(this_type &, size_type , size_type)
     { GMM_ASSERT1(false, "Sorry, to be done"); }
     static void reshape(this_type &, size_type , size_type)
     { GMM_ASSERT1(false, "Sorry, to be done"); }
   };
 
-  template <typename MAT> void block_matrix<MAT>::do_clear(void) { 
+  template <typename MAT> void block_matrix<MAT>::do_clear(void) {
     for (size_type j = 0; j < ncolblocks_; ++j)
       for (size_type i = 0; i < nrowblocks_; ++i)
-	clear(block(i,j));
+        clear(block(i,j));
   }
 
   template <typename MAT> template <typename CONT>
@@ -872,8 +882,8 @@ namespace gmm
     for (size_type j = 0, l = 0; j < ncolblocks_; ++j) {
       intcol[j] = sub_interval(l, c2[j]); l += c2[j];
       for (size_type i = 0, k = 0; i < nrowblocks_; ++i) {
-	if (j == 0) { introw[i] = sub_interval(k, c1[i]); k += c1[i]; }
-	block(i, j) = MAT(c1[i], c2[j]);
+        if (j == 0) { introw[i] = sub_interval(k, c1[i]); k += c1[i]; }
+        block(i, j) = MAT(c1[i], c2[j]);
       }
     }
   }
@@ -882,14 +892,14 @@ namespace gmm
   void copy(const block_matrix<M1> &m1, M2 &m2) {
     for (size_type j = 0; j < m1.ncolblocks(); ++j)
       for (size_type i = 0; i < m1.nrowblocks(); ++i)
-	copy(m1.block(i,j), sub_matrix(m2, m1.subrowinterval(i), 
-				       m1.subcolinterval(j)));
+        copy(m1.block(i,j), sub_matrix(m2, m1.subrowinterval(i),
+                                       m1.subcolinterval(j)));
   }
 
   template <typename M1, typename M2>
   void copy(const block_matrix<M1> &m1, const M2 &m2)
   { copy(m1, linalg_const_cast(m2)); }
-  
+
 
   template <typename MAT, typename V1, typename V2>
   void mult(const block_matrix<MAT> &m, const V1 &v1, V2 &v2) {
@@ -897,9 +907,9 @@ namespace gmm
     typename sub_vector_type<V2 *, sub_interval>::vector_type sv;
     for (size_type i = 0; i < m.nrowblocks() ; ++i)
       for (size_type j = 0; j < m.ncolblocks() ; ++j) {
-	sv = sub_vector(v2, m.subrowinterval(i));
-	mult(m.block(i,j),
-	     sub_vector(v1, m.subcolinterval(j)), sv, sv);
+        sv = sub_vector(v2, m.subrowinterval(i));
+        mult(m.block(i,j),
+             sub_vector(v1, m.subcolinterval(j)), sv, sv);
       }
   }
 
@@ -908,16 +918,16 @@ namespace gmm
     typename sub_vector_type<V3 *, sub_interval>::vector_type sv;
     for (size_type i = 0; i < m.nrowblocks() ; ++i)
       for (size_type j = 0; j < m.ncolblocks() ; ++j) {
-	sv = sub_vector(v3, m.subrowinterval(i));
-	if (j == 0)
-	  mult(m.block(i,j),
-	       sub_vector(v1, m.subcolinterval(j)),
-	       sub_vector(v2, m.subrowinterval(i)), sv);
-	else
-	  mult(m.block(i,j),
-	       sub_vector(v1, m.subcolinterval(j)), sv, sv);
+        sv = sub_vector(v3, m.subrowinterval(i));
+        if (j == 0)
+          mult(m.block(i,j),
+               sub_vector(v1, m.subcolinterval(j)),
+               sub_vector(v2, m.subrowinterval(i)), sv);
+        else
+          mult(m.block(i,j),
+               sub_vector(v1, m.subcolinterval(j)), sv, sv);
       }
-    
+
   }
 
   template <typename MAT, typename V1, typename V2>
@@ -925,22 +935,24 @@ namespace gmm
   { mult(m, v1, linalg_const_cast(v2)); }
 
   template <typename MAT, typename V1, typename V2, typename V3>
-  void mult(const block_matrix<MAT> &m, const V1 &v1, const V2 &v2, 
-	    const V3 &v3)
+  void mult(const block_matrix<MAT> &m, const V1 &v1, const V2 &v2,
+            const V3 &v3)
   { mult_const(m, v1, v2, linalg_const_cast(v3)); }
 
 }
   /* ******************************************************************** */
-  /*		                                            		  */
-  /*		Distributed matrices                                	  */
-  /*		                                            		  */
+  /*                                                                      */
+  /*             Distributed matrices                                     */
+  /*                                                                      */
   /* ******************************************************************** */
 
 #ifdef GMM_USES_MPI
-#include <mpi.h>
- 
-namespace gmm { 
-  
+# include <mpi.h>
+
+namespace gmm {
+
+
+
   template <typename T> inline MPI_Datatype mpi_type(T)
   { GMM_ASSERT1(false, "Sorry unsupported type"); return MPI_FLOAT; }
   inline MPI_Datatype mpi_type(double) { return MPI_DOUBLE; }
@@ -952,13 +964,8 @@ namespace gmm {
 #endif
   inline MPI_Datatype mpi_type(int) { return MPI_INT; }
   inline MPI_Datatype mpi_type(unsigned int) { return MPI_UNSIGNED; }
-  inline MPI_Datatype mpi_type(size_t) {
-    if (sizeof(int) == sizeof(size_t)) return MPI_UNSIGNED;
-    if (sizeof(long) == sizeof(size_t)) return MPI_UNSIGNED_LONG;
-    return MPI_LONG_LONG;
-  }
-
-
+  inline MPI_Datatype mpi_type(long) { return MPI_LONG; }
+  inline MPI_Datatype mpi_type(unsigned long) { return MPI_UNSIGNED_LONG; }
 
   template <typename MAT> struct mpi_distributed_matrix {
     MAT M;
@@ -969,7 +976,7 @@ namespace gmm {
     const MAT &local_matrix(void) const { return M; }
     MAT &local_matrix(void) { return M; }
   };
-  
+
   template <typename MAT> inline MAT &eff_matrix(MAT &m) { return m; }
   template <typename MAT> inline
   const MAT &eff_matrix(const MAT &m) { return m; }
@@ -977,29 +984,29 @@ namespace gmm {
   MAT &eff_matrix(mpi_distributed_matrix<MAT> &m) { return m.M; }
   template <typename MAT> inline
   const MAT &eff_matrix(const mpi_distributed_matrix<MAT> &m) { return m.M; }
-  
+
 
   template <typename MAT1, typename MAT2>
   inline void copy(const mpi_distributed_matrix<MAT1> &m1,
-		   mpi_distributed_matrix<MAT2> &m2)
+                   mpi_distributed_matrix<MAT2> &m2)
   { copy(eff_matrix(m1), eff_matrix(m2)); }
   template <typename MAT1, typename MAT2>
   inline void copy(const mpi_distributed_matrix<MAT1> &m1,
-		   const mpi_distributed_matrix<MAT2> &m2)
+                   const mpi_distributed_matrix<MAT2> &m2)
   { copy(m1.M, m2.M); }
-  
+
   template <typename MAT1, typename MAT2>
   inline void copy(const mpi_distributed_matrix<MAT1> &m1, MAT2 &m2)
   { copy(m1.M, m2); }
   template <typename MAT1, typename MAT2>
   inline void copy(const mpi_distributed_matrix<MAT1> &m1, const MAT2 &m2)
   { copy(m1.M, m2); }
-  
+
 
   template <typename MATSP, typename V1, typename V2> inline
   typename strongest_value_type3<V1,V2,MATSP>::value_type
   vect_sp(const mpi_distributed_matrix<MATSP> &ps, const V1 &v1,
-	  const V2 &v2) {
+          const V2 &v2) {
     typedef typename strongest_value_type3<V1,V2,MATSP>::value_type T;
     T res = vect_sp(ps.M, v1, v2), rest;
     MPI_Allreduce(&res, &rest, 1, mpi_type(T()), MPI_SUM,MPI_COMM_WORLD);
@@ -1008,7 +1015,7 @@ namespace gmm {
 
   template <typename MAT, typename V1, typename V2>
   inline void mult_add(const mpi_distributed_matrix<MAT> &m, const V1 &v1,
-		       V2 &v2) {
+                       V2 &v2) {
     typedef typename linalg_traits<V2>::value_type T;
     std::vector<T> v3(vect_size(v2)), v4(vect_size(v2));
     static double tmult_tot = 0.0;
@@ -1018,7 +1025,7 @@ namespace gmm {
     if (is_sparse(v2)) GMM_WARNING2("Using a plain temporary, here.");
     double t_ref2 = MPI_Wtime();
     MPI_Allreduce(&(v3[0]), &(v4[0]),gmm::vect_size(v2), mpi_type(T()),
-		  MPI_SUM,MPI_COMM_WORLD);
+                  MPI_SUM,MPI_COMM_WORLD);
     tmult_tot2 = MPI_Wtime()-t_ref2;
     cout << "reduce mult mpi = " << tmult_tot2 << endl;
     gmm::add(v4, v2);
@@ -1028,59 +1035,59 @@ namespace gmm {
 
   template <typename MAT, typename V1, typename V2>
   void mult_add(const mpi_distributed_matrix<MAT> &m, const V1 &v1,
-		const V2 &v2_)
+                const V2 &v2_)
   { mult_add(m, v1, const_cast<V2 &>(v2_)); }
 
   template <typename MAT, typename V1, typename V2>
   inline void mult(const mpi_distributed_matrix<MAT> &m, const V1 &v1,
-		   const V2 &v2_)
+                   const V2 &v2_)
   { V2 &v2 = const_cast<V2 &>(v2_); clear(v2); mult_add(m, v1, v2); }
 
   template <typename MAT, typename V1, typename V2>
   inline void mult(const mpi_distributed_matrix<MAT> &m, const V1 &v1,
-		   V2 &v2)
+                   V2 &v2)
   { clear(v2); mult_add(m, v1, v2); }
 
   template <typename MAT, typename V1, typename V2, typename V3>
   inline void mult(const mpi_distributed_matrix<MAT> &m, const V1 &v1,
-		   const V2 &v2, const V3 &v3_)
+                   const V2 &v2, const V3 &v3_)
   { V3 &v3 = const_cast<V3 &>(v3_); gmm::copy(v2, v3); mult_add(m, v1, v3); }
 
   template <typename MAT, typename V1, typename V2, typename V3>
   inline void mult(const mpi_distributed_matrix<MAT> &m, const V1 &v1,
-		   const V2 &v2, V3 &v3)
+                   const V2 &v2, V3 &v3)
   { gmm::copy(v2, v3); mult_add(m, v1, v3); }
-  
+
 
   template <typename MAT> inline
-  size_type mat_nrows(const mpi_distributed_matrix<MAT> &M) 
+  size_type mat_nrows(const mpi_distributed_matrix<MAT> &M)
   { return mat_nrows(M.M); }
   template <typename MAT> inline
-  size_type mat_ncols(const mpi_distributed_matrix<MAT> &M) 
+  size_type mat_ncols(const mpi_distributed_matrix<MAT> &M)
   { return mat_nrows(M.M); }
   template <typename MAT> inline
   void resize(mpi_distributed_matrix<MAT> &M, size_type m, size_type n)
   { resize(M.M, m, n); }
   template <typename MAT> inline void clear(mpi_distributed_matrix<MAT> &M)
   { clear(M.M); }
-  
+
 
   // For compute reduced system
   template <typename MAT1, typename MAT2> inline
   void mult(const MAT1 &M1, const mpi_distributed_matrix<MAT2> &M2,
-	    mpi_distributed_matrix<MAT2> &M3)
+            mpi_distributed_matrix<MAT2> &M3)
   { mult(M1, M2.M, M3.M); }
   template <typename MAT1, typename MAT2> inline
   void mult(const mpi_distributed_matrix<MAT2> &M2,
-	    const MAT1 &M1, mpi_distributed_matrix<MAT2> &M3)
+            const MAT1 &M1, mpi_distributed_matrix<MAT2> &M3)
   { mult(M2.M, M1, M3.M); }
   template <typename MAT1, typename MAT2, typename MAT3> inline
   void mult(const MAT1 &M1, const mpi_distributed_matrix<MAT2> &M2,
-		   MAT3 &M3)
+                   MAT3 &M3)
   { mult(M1, M2.M, M3); }
   template <typename MAT1, typename MAT2, typename MAT3> inline
   void mult(const MAT1 &M1, const mpi_distributed_matrix<MAT2> &M2,
-		   const MAT3 &M3)
+                   const MAT3 &M3)
   { mult(M1, M2.M, M3); }
 
   template <typename M, typename SUBI1, typename SUBI2>
@@ -1101,16 +1108,16 @@ namespace gmm {
   template <typename MAT, typename SUBI1, typename SUBI2>  inline
   typename select_return<typename sub_matrix_type<const MAT *, SUBI1, SUBI2>
   ::matrix_type, typename sub_matrix_type<MAT *, SUBI1, SUBI2>::matrix_type,
-			 const MAT *>::return_type
+                         const MAT *>::return_type
   sub_matrix(const mpi_distributed_matrix<MAT> &m, const SUBI1 &si1,
-	     const SUBI2 &si2)
+             const SUBI2 &si2)
   { return sub_matrix(m.M, si1, si2);  }
 
   template <typename M, typename SUBI1>  inline
     typename select_return<typename sub_matrix_type<const M *, SUBI1, SUBI1>
     ::matrix_type, typename sub_matrix_type<M *, SUBI1, SUBI1>::matrix_type,
     M *>::return_type
-  sub_matrix(mpi_distributed_matrix<M> &m, const SUBI1 &si1) 
+  sub_matrix(mpi_distributed_matrix<M> &m, const SUBI1 &si1)
   { return sub_matrix(m.M, si1, si1); }
 
   template <typename M, typename SUBI1>  inline
@@ -1121,11 +1128,11 @@ namespace gmm {
   { return sub_matrix(m.M, si1, si1); }
 
 
-  template <typename L> struct transposed_return<const mpi_distributed_matrix<L> *> 
+  template <typename L> struct transposed_return<const mpi_distributed_matrix<L> *>
   { typedef abstract_null_type return_type; };
-  template <typename L> struct transposed_return<mpi_distributed_matrix<L> *> 
+  template <typename L> struct transposed_return<mpi_distributed_matrix<L> *>
   { typedef abstract_null_type return_type; };
-  
+
   template <typename L> inline typename transposed_return<const L *>::return_type
   transposed(const mpi_distributed_matrix<L> &l)
   { return transposed(l.M); }
@@ -1174,11 +1181,11 @@ namespace std {
   template <typename T>
   void swap(gmm::dense_matrix<T> &m1, gmm::dense_matrix<T> &m2)
   { m1.swap(m2); }
-  template <typename T, int shift> void 
-  swap(gmm::csc_matrix<T,shift> &m1, gmm::csc_matrix<T,shift> &m2)
+  template <typename T, typename IND_TYPE, int shift> void
+  swap(gmm::csc_matrix<T, IND_TYPE, shift> &m1, gmm::csc_matrix<T, IND_TYPE, shift> &m2)
   { m1.swap(m2); }
-  template <typename T, int shift> void 
-  swap(gmm::csr_matrix<T,shift> &m1, gmm::csr_matrix<T,shift> &m2)
+  template <typename T, typename IND_TYPE, int shift> void
+  swap(gmm::csr_matrix<T, IND_TYPE, shift> &m1, gmm::csr_matrix<T, IND_TYPE, shift> &m2)
   { m1.swap(m2); }
 }
 
diff --git a/contrib/gmm/gmm_modified_gram_schmidt.h b/contrib/gmm/gmm_modified_gram_schmidt.h
index 213cf7a7e0..fa45917641 100644
--- a/contrib/gmm/gmm_modified_gram_schmidt.h
+++ b/contrib/gmm/gmm_modified_gram_schmidt.h
@@ -1,30 +1,60 @@
-// -*- c++ -*- (enables emacs c++ mode)
+/* -*- c++ -*- (enables emacs c++ mode) */
+/*===========================================================================
+
+ Copyright (C) 2002-2020 Yves Renard
+
+ This file is a part of GetFEM
+
+ GetFEM  is  free software;  you  can  redistribute  it  and/or modify it
+ under  the  terms  of the  GNU  Lesser General Public License as published
+ by  the  Free Software Foundation;  either version 3 of the License,  or
+ (at your option) any later version along with the GCC Runtime Library
+ Exception either version 3.1 or (at your option) any later version.
+ This program  is  distributed  in  the  hope  that it will be useful,  but
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+ License and GCC Runtime Library Exception for more details.
+ You  should  have received a copy of the GNU Lesser General Public License
+ along  with  this program;  if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+
+ As a special exception, you  may use  this file  as it is a part of a free
+ software  library  without  restriction.  Specifically,  if   other  files
+ instantiate  templates  or  use macros or inline functions from this file,
+ or  you compile this  file  and  link  it  with other files  to produce an
+ executable, this file  does  not  by itself cause the resulting executable
+ to be covered  by the GNU Lesser General Public License.  This   exception
+ does not  however  invalidate  any  other  reasons why the executable file
+ might be covered by the GNU Lesser General Public License.
+
+===========================================================================*/
+
 //===========================================================================
 //
-// Copyright (C) 1997-2008 Yves Renard
-//
-// This file is a part of GETFEM++
+// Copyright (c) 1998-2020, University of Notre Dame. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
 //
-// Getfem++  is  free software;  you  can  redistribute  it  and/or modify it
-// under  the  terms  of the  GNU  Lesser General Public License as published
-// by  the  Free Software Foundation;  either version 2.1 of the License,  or
-// (at your option) any later version.
-// This program  is  distributed  in  the  hope  that it will be useful,  but
-// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-// or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
-// License for more details.
-// You  should  have received a copy of the GNU Lesser General Public License
-// along  with  this program;  if not, write to the Free Software Foundation,
-// Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+//    * Redistributions of source code must retain the above copyright
+//      notice, this list of conditions and the following disclaimer.
+//    * Redistributions in binary form must reproduce the above copyright
+//      notice, this list of conditions and the following disclaimer in the
+//      documentation and/or other materials provided with the distribution.
+//    * Neither the name of the University of Notre Dame nor the
+//      names of its contributors may be used to endorse or promote products
+//      derived from this software without specific prior written permission.
 //
-// As a special exception, you may use this file as part of a free software
-// library without restriction.  Specifically, if other files instantiate
-// templates or use macros or inline functions from this file, or you compile
-// this file and link it with other files to produce an executable, this
-// file does not by itself cause the resulting executable to be covered by
-// the GNU General Public License.  This exception does not however
-// invalidate any other reasons why the executable file might be covered by
-// the GNU General Public License.
+// THIS SOFTWARE  IS  PROVIDED  BY  THE TRUSTEES  OF  INDIANA UNIVERSITY  AND
+// CONTRIBUTORS  ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,  INCLUDING,
+// BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND  FITNESS
+// FOR  A PARTICULAR PURPOSE ARE DISCLAIMED. IN  NO  EVENT SHALL THE TRUSTEES
+// OF INDIANA UNIVERSITY AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY,  OR CONSEQUENTIAL DAMAGES (INCLUDING,  BUT
+// NOT  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA,  OR PROFITS;  OR BUSINESS  INTERRUPTION)  HOWEVER  CAUSED AND ON ANY
+// THEORY  OF  LIABILITY,  WHETHER  IN  CONTRACT,  STRICT  LIABILITY, OR TORT
+// (INCLUDING  NEGLIGENCE  OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+// THIS  SOFTWARE,  EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 //
 //===========================================================================
 
diff --git a/contrib/gmm/gmm_opt.h b/contrib/gmm/gmm_opt.h
index 2dfd9f89b2..46cfd6f943 100644
--- a/contrib/gmm/gmm_opt.h
+++ b/contrib/gmm/gmm_opt.h
@@ -1,32 +1,33 @@
-// -*- c++ -*- (enables emacs c++ mode)
-//===========================================================================
-//
-// Copyright (C) 2003-2008 Yves Renard
-//
-// This file is a part of GETFEM++
-//
-// Getfem++  is  free software;  you  can  redistribute  it  and/or modify it
-// under  the  terms  of the  GNU  Lesser General Public License as published
-// by  the  Free Software Foundation;  either version 2.1 of the License,  or
-// (at your option) any later version.
-// This program  is  distributed  in  the  hope  that it will be useful,  but
-// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-// or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
-// License for more details.
-// You  should  have received a copy of the GNU Lesser General Public License
-// along  with  this program;  if not, write to the Free Software Foundation,
-// Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
-//
-// As a special exception, you may use this file as part of a free software
-// library without restriction.  Specifically, if other files instantiate
-// templates or use macros or inline functions from this file, or you compile
-// this file and link it with other files to produce an executable, this
-// file does not by itself cause the resulting executable to be covered by
-// the GNU General Public License.  This exception does not however
-// invalidate any other reasons why the executable file might be covered by
-// the GNU General Public License.
-//
-//===========================================================================
+/* -*- c++ -*- (enables emacs c++ mode) */
+/*===========================================================================
+
+ Copyright (C) 2003-2020 Yves Renard
+
+ This file is a part of GetFEM
+
+ GetFEM  is  free software;  you  can  redistribute  it  and/or modify it
+ under  the  terms  of the  GNU  Lesser General Public License as published
+ by  the  Free Software Foundation;  either version 3 of the License,  or
+ (at your option) any later version along with the GCC Runtime Library
+ Exception either version 3.1 or (at your option) any later version.
+ This program  is  distributed  in  the  hope  that it will be useful,  but
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+ License and GCC Runtime Library Exception for more details.
+ You  should  have received a copy of the GNU Lesser General Public License
+ along  with  this program;  if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+
+ As a special exception, you  may use  this file  as it is a part of a free
+ software  library  without  restriction.  Specifically,  if   other  files
+ instantiate  templates  or  use macros or inline functions from this file,
+ or  you compile this  file  and  link  it  with other files  to produce an
+ executable, this file  does  not  by itself cause the resulting executable
+ to be covered  by the GNU Lesser General Public License.  This   exception
+ does not  however  invalidate  any  other  reasons why the executable file
+ might be covered by the GNU Lesser General Public License.
+
+===========================================================================*/
 
 /**@file gmm_opt.h
    @author  Yves Renard <Yves.Renard@insa-lyon.fr>
@@ -36,6 +37,8 @@
 #ifndef GMM_OPT_H__
 #define GMM_OPT_H__
 
+#include <gmm_dense_lu.h>
+
 namespace gmm {
 
   /* ********************************************************************* */
@@ -50,73 +53,80 @@ namespace gmm {
       switch (n) {
       case 1 : return (*p);
       case 2 : return (*p) * (*(p+3)) - (*(p+1)) * (*(p+2));
-      case 3 : return (*p) * ((*(p+4)) * (*(p+8)) - (*(p+5)) * (*(p+7)))
-		 - (*(p+1)) * ((*(p+3)) * (*(p+8)) - (*(p+5)) * (*(p+6)))
-		 + (*(p+2)) * ((*(p+3)) * (*(p+7)) - (*(p+4)) * (*(p+6)));
+// Not stable for nearly singular matrices
+//       case 3 : return (*p) * ((*(p+4)) * (*(p+8)) - (*(p+5)) * (*(p+7)))
+//                  - (*(p+1)) * ((*(p+3)) * (*(p+8)) - (*(p+5)) * (*(p+6)))
+//                  + (*(p+2)) * ((*(p+3)) * (*(p+7)) - (*(p+4)) * (*(p+6)));
       default :
-	{
-	  dense_matrix<T> B(mat_nrows(A), mat_ncols(A));
-	  std::vector<size_type> ipvt(mat_nrows(A));
-	  gmm::copy(A, B);
-	  lu_factor(B, ipvt);
-	  return lu_det(B, ipvt);	
-	}
+        {
+          dense_matrix<T> B(mat_nrows(A), mat_ncols(A));
+          lapack_ipvt ipvt(mat_nrows(A));
+          gmm::copy(A, B);
+          lu_factor(B, ipvt);
+          return lu_det(B, ipvt);
+        }
       }
     }
     return T(1);
   }
 
-  template <typename T> T lu_inverse(const dense_matrix<T> &A_) {
+
+  template <typename T> T lu_inverse(const dense_matrix<T> &A_,
+                                     bool doassert = true) {
     dense_matrix<T>& A = const_cast<dense_matrix<T> &>(A_);
     size_type N = mat_nrows(A);
     T det(1);
     if (N) {
       T *p = &(A(0,0));
-      if (N <= 3) {
-	switch (N) {
-	  case 1 : {
-	    det = *p;
-	    GMM_ASSERT1(det!=T(0), "non invertible matrix");
-	    *p = T(1) / det; 
-	  } break;
-	  case 2 : {
-	    det = (*p) * (*(p+3)) - (*(p+1)) * (*(p+2));
-	    GMM_ASSERT1(det!=T(0), "non invertible matrix");
-	    std::swap(*p, *(p+3));
-	    *p++ /= det; *p++ /= -det; *p++ /= -det; *p++ /= det; 
-	  } break;
-	  case 3 : {
-	    T a, b, c, d, e, f, g, h, i;
-	    a =   (*(p+4)) * (*(p+8)) - (*(p+5)) * (*(p+7));
-	    b = - (*(p+1)) * (*(p+8)) + (*(p+2)) * (*(p+7));
-	    c =   (*(p+1)) * (*(p+5)) - (*(p+2)) * (*(p+4));
-	    d = - (*(p+3)) * (*(p+8)) + (*(p+5)) * (*(p+6));
-	    e =   (*(p+0)) * (*(p+8)) - (*(p+2)) * (*(p+6));
-	    f = - (*(p+0)) * (*(p+5)) + (*(p+2)) * (*(p+3));
-	    g =   (*(p+3)) * (*(p+7)) - (*(p+4)) * (*(p+6));
-	    h = - (*(p+0)) * (*(p+7)) + (*(p+1)) * (*(p+6));
-	    i =   (*(p+0)) * (*(p+4)) - (*(p+1)) * (*(p+3));
-	    det = (*p) * a + (*(p+1)) * d + (*(p+2)) * g;
-	    GMM_ASSERT1(det!=T(0), "non invertible matrix");
-	    *p++ = a / det; *p++ = b / det; *p++ = c / det; 
-	    *p++ = d / det; *p++ = e / det; *p++ = f / det; 
-	    *p++ = g / det; *p++ = h / det; *p++ = i / det; 
-	  } break;
-	}
-      }
-      else {
-	dense_matrix<T> B(mat_nrows(A), mat_ncols(A));
-	std::vector<int> ipvt(mat_nrows(A));
-	gmm::copy(A, B);
-	size_type info = lu_factor(B, ipvt);
-	GMM_ASSERT1(!info, "non invertible matrix");
-	lu_inverse(B, ipvt, A);
-	return lu_det(B, ipvt);
+      switch (N) {
+        case 1 : {
+          det = *p;
+          if (doassert) GMM_ASSERT1(det!=T(0), "non invertible matrix");
+          if (det == T(0)) break;
+          *p = T(1) / det;
+        } break;
+        case 2 : {
+          det = (*p) * (*(p+3)) - (*(p+1)) * (*(p+2));
+          if (doassert) GMM_ASSERT1(det!=T(0), "non invertible matrix");
+          if (det == T(0)) break;
+          std::swap(*p, *(p+3));
+          *p++ /= det; *p++ /= -det; *p++ /= -det; *p++ /= det;
+        } break;
+        default : {
+          if (N == 3) { // not stable for nearly singular matrices
+            T a, b, c, d, e, f, g, h, i;
+            a =   (*(p+4)) * (*(p+8)) - (*(p+5)) * (*(p+7));
+            b = - (*(p+1)) * (*(p+8)) + (*(p+2)) * (*(p+7));
+            c =   (*(p+1)) * (*(p+5)) - (*(p+2)) * (*(p+4));
+            d = - (*(p+3)) * (*(p+8)) + (*(p+5)) * (*(p+6));
+            e =   (*(p+0)) * (*(p+8)) - (*(p+2)) * (*(p+6));
+            f = - (*(p+0)) * (*(p+5)) + (*(p+2)) * (*(p+3));
+            g =   (*(p+3)) * (*(p+7)) - (*(p+4)) * (*(p+6));
+            h = - (*(p+0)) * (*(p+7)) + (*(p+1)) * (*(p+6));
+            i =   (*(p+0)) * (*(p+4)) - (*(p+1)) * (*(p+3));
+            det = (*p) * a + (*(p+1)) * d + (*(p+2)) * g;
+            if (std::abs(det) > 1e-5) {
+              *p++ = a / det; *p++ = b / det; *p++ = c / det;
+              *p++ = d / det; *p++ = e / det; *p++ = f / det;
+              *p++ = g / det; *p++ = h / det; *p++ = i / det;
+              break;
+            }
+          }
+          dense_matrix<T> B(mat_nrows(A), mat_ncols(A));
+          lapack_ipvt ipvt(mat_nrows(A));
+          gmm::copy(A, B);
+          size_type info = lu_factor(B, ipvt);
+          GMM_ASSERT1(!info, "non invertible matrix");
+          lu_inverse(B, ipvt, A);
+          det = lu_det(B, ipvt);
+          break;
+        }
       }
     }
     return det;
   }
-  
+
+
 }
 
 #endif //  GMM_OPT_H__
diff --git a/contrib/gmm/gmm_precond.h b/contrib/gmm/gmm_precond.h
index 7e95dc83fa..17405a2c40 100644
--- a/contrib/gmm/gmm_precond.h
+++ b/contrib/gmm/gmm_precond.h
@@ -1,32 +1,33 @@
-// -*- c++ -*- (enables emacs c++ mode)
-//===========================================================================
-//
-// Copyright (C) 2004-2008 Yves Renard
-//
-// This file is a part of GETFEM++
-//
-// Getfem++  is  free software;  you  can  redistribute  it  and/or modify it
-// under  the  terms  of the  GNU  Lesser General Public License as published
-// by  the  Free Software Foundation;  either version 2.1 of the License,  or
-// (at your option) any later version.
-// This program  is  distributed  in  the  hope  that it will be useful,  but
-// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-// or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
-// License for more details.
-// You  should  have received a copy of the GNU Lesser General Public License
-// along  with  this program;  if not, write to the Free Software Foundation,
-// Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
-//
-// As a special exception, you may use this file as part of a free software
-// library without restriction.  Specifically, if other files instantiate
-// templates or use macros or inline functions from this file, or you compile
-// this file and link it with other files to produce an executable, this
-// file does not by itself cause the resulting executable to be covered by
-// the GNU General Public License.  This exception does not however
-// invalidate any other reasons why the executable file might be covered by
-// the GNU General Public License.
-//
-//===========================================================================
+/* -*- c++ -*- (enables emacs c++ mode) */
+/*===========================================================================
+
+ Copyright (C) 2004-2020 Yves Renard
+
+ This file is a part of GetFEM
+
+ GetFEM  is  free software;  you  can  redistribute  it  and/or modify it
+ under  the  terms  of the  GNU  Lesser General Public License as published
+ by  the  Free Software Foundation;  either version 3 of the License,  or
+ (at your option) any later version along with the GCC Runtime Library
+ Exception either version 3.1 or (at your option) any later version.
+ This program  is  distributed  in  the  hope  that it will be useful,  but
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+ License and GCC Runtime Library Exception for more details.
+ You  should  have received a copy of the GNU Lesser General Public License
+ along  with  this program;  if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+
+ As a special exception, you  may use  this file  as it is a part of a free
+ software  library  without  restriction.  Specifically,  if   other  files
+ instantiate  templates  or  use macros or inline functions from this file,
+ or  you compile this  file  and  link  it  with other files  to produce an
+ executable, this file  does  not  by itself cause the resulting executable
+ to be covered  by the GNU Lesser General Public License.  This   exception
+ does not  however  invalidate  any  other  reasons why the executable file
+ might be covered by the GNU Lesser General Public License.
+
+===========================================================================*/
 #ifndef GMM_PRECOND_H
 #define GMM_PRECOND_H
 
@@ -41,7 +42,7 @@
 /* Preconditioner concept :                                                */
 /*                                                                         */
 /* A the matrix, P the preconditioner PA well conditioned.                 */
-/* PRECOND precontioner type.                                              */
+/* PRECOND preconditioner type.                                            */
 /* mult(P, v, w) :  w <- P v                                               */
 /* transposed_mult(P, v, w)       : w <- transposed(P) v                   */
 /* left_mult(P, v, w)             : see qmr solver                         */
diff --git a/contrib/gmm/gmm_precond_diagonal.h b/contrib/gmm/gmm_precond_diagonal.h
index f6dee5a9ef..c8ccebc664 100644
--- a/contrib/gmm/gmm_precond_diagonal.h
+++ b/contrib/gmm/gmm_precond_diagonal.h
@@ -1,32 +1,33 @@
-// -*- c++ -*- (enables emacs c++ mode)
-//===========================================================================
-//
-// Copyright (C) 2003-2008 Yves Renard
-//
-// This file is a part of GETFEM++
-//
-// Getfem++  is  free software;  you  can  redistribute  it  and/or modify it
-// under  the  terms  of the  GNU  Lesser General Public License as published
-// by  the  Free Software Foundation;  either version 2.1 of the License,  or
-// (at your option) any later version.
-// This program  is  distributed  in  the  hope  that it will be useful,  but
-// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-// or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
-// License for more details.
-// You  should  have received a copy of the GNU Lesser General Public License
-// along  with  this program;  if not, write to the Free Software Foundation,
-// Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
-//
-// As a special exception, you may use this file as part of a free software
-// library without restriction.  Specifically, if other files instantiate
-// templates or use macros or inline functions from this file, or you compile
-// this file and link it with other files to produce an executable, this
-// file does not by itself cause the resulting executable to be covered by
-// the GNU General Public License.  This exception does not however
-// invalidate any other reasons why the executable file might be covered by
-// the GNU General Public License.
-//
-//===========================================================================
+/* -*- c++ -*- (enables emacs c++ mode) */
+/*===========================================================================
+
+ Copyright (C) 2003-2020 Yves Renard
+
+ This file is a part of GetFEM
+
+ GetFEM  is  free software;  you  can  redistribute  it  and/or modify it
+ under  the  terms  of the  GNU  Lesser General Public License as published
+ by  the  Free Software Foundation;  either version 3 of the License,  or
+ (at your option) any later version along with the GCC Runtime Library
+ Exception either version 3.1 or (at your option) any later version.
+ This program  is  distributed  in  the  hope  that it will be useful,  but
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+ License and GCC Runtime Library Exception for more details.
+ You  should  have received a copy of the GNU Lesser General Public License
+ along  with  this program;  if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+
+ As a special exception, you  may use  this file  as it is a part of a free
+ software  library  without  restriction.  Specifically,  if   other  files
+ instantiate  templates  or  use macros or inline functions from this file,
+ or  you compile this  file  and  link  it  with other files  to produce an
+ executable, this file  does  not  by itself cause the resulting executable
+ to be covered  by the GNU Lesser General Public License.  This   exception
+ does not  however  invalidate  any  other  reasons why the executable file
+ might be covered by the GNU Lesser General Public License.
+
+===========================================================================*/
 
 /**@file gmm_precond_diagonal.h
    @author  Yves Renard <Yves.Renard@insa-lyon.fr>
@@ -91,9 +92,9 @@ namespace gmm {
   void transposed_mult(const diagonal_precond<Matrix>& P,const V1 &v1,V2 &v2) {
     mult(P, v1, v2);
   }
-
+  
   // # define DIAG_LEFT_MULT_SQRT
-
+  
   template <typename Matrix, typename V1, typename V2> inline
   void left_mult(const diagonal_precond<Matrix>& P, const V1 &v1, V2 &v2) {
     GMM_ASSERT2(P.diag.size() == vect_size(v2), "dimensions mismatch");
@@ -112,10 +113,10 @@ namespace gmm {
 
   template <typename Matrix, typename V1, typename V2> inline
   void right_mult(const diagonal_precond<Matrix>& P, const V1 &v1, V2 &v2) {
-    //typedef typename linalg_traits<Matrix>::value_type T;
+    // typedef typename linalg_traits<Matrix>::value_type T;
     GMM_ASSERT2(P.diag.size() == vect_size(v2), "dimensions mismatch");
     copy(v1, v2);
-#   ifdef DIAG_LEFT_MULT_SQRT
+#   ifdef DIAG_LEFT_MULT_SQRT    
     for (size_type i= 0; i < P.diag.size(); ++i) v2[i] *= gmm::sqrt(P.diag[i]);
 #   endif
   }
@@ -127,5 +128,5 @@ namespace gmm {
 
 }
 
-#endif
+#endif 
 
diff --git a/contrib/gmm/gmm_precond_ildlt.h b/contrib/gmm/gmm_precond_ildlt.h
index 5c4eece9a6..226213ea4f 100644
--- a/contrib/gmm/gmm_precond_ildlt.h
+++ b/contrib/gmm/gmm_precond_ildlt.h
@@ -1,40 +1,40 @@
-// -*- c++ -*- (enables emacs c++ mode)
-//===========================================================================
-//
-// Copyright (C) 2003-2008 Yves Renard
-//
-// This file is a part of GETFEM++
-//
-// Getfem++  is  free software;  you  can  redistribute  it  and/or modify it
-// under  the  terms  of the  GNU  Lesser General Public License as published
-// by  the  Free Software Foundation;  either version 2.1 of the License,  or
-// (at your option) any later version.
-// This program  is  distributed  in  the  hope  that it will be useful,  but
-// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-// or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
-// License for more details.
-// You  should  have received a copy of the GNU Lesser General Public License
-// along  with  this program;  if not, write to the Free Software Foundation,
-// Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
-//
-// As a special exception, you may use this file as part of a free software
-// library without restriction.  Specifically, if other files instantiate
-// templates or use macros or inline functions from this file, or you compile
-// this file and link it with other files to produce an executable, this
-// file does not by itself cause the resulting executable to be covered by
-// the GNU General Public License.  This exception does not however
-// invalidate any other reasons why the executable file might be covered by
-// the GNU General Public License.
-//
-//===========================================================================
+/* -*- c++ -*- (enables emacs c++ mode) */
+/*===========================================================================
+
+ Copyright (C) 2003-2020 Yves Renard
+
+ This file is a part of GetFEM
+
+ GetFEM  is  free software;  you  can  redistribute  it  and/or modify it
+ under  the  terms  of the  GNU  Lesser General Public License as published
+ by  the  Free Software Foundation;  either version 3 of the License,  or
+ (at your option) any later version along with the GCC Runtime Library
+ Exception either version 3.1 or (at your option) any later version.
+ This program  is  distributed  in  the  hope  that it will be useful,  but
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+ License and GCC Runtime Library Exception for more details.
+ You  should  have received a copy of the GNU Lesser General Public License
+ along  with  this program;  if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+
+ As a special exception, you  may use  this file  as it is a part of a free
+ software  library  without  restriction.  Specifically,  if   other  files
+ instantiate  templates  or  use macros or inline functions from this file,
+ or  you compile this  file  and  link  it  with other files  to produce an
+ executable, this file  does  not  by itself cause the resulting executable
+ to be covered  by the GNU Lesser General Public License.  This   exception
+ does not  however  invalidate  any  other  reasons why the executable file
+ might be covered by the GNU Lesser General Public License.
+
+===========================================================================*/
 
 // This file is a modified version of cholesky.h from ITL.
 // See http://osl.iu.edu/research/itl/
 // Following the corresponding Copyright notice.
 //===========================================================================
 //
-// Copyright (c) 1997-2001, The Trustees of Indiana University.
-// All rights reserved.
+// Copyright (c) 1998-2020, University of Notre Dame. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are met:
 //
@@ -43,7 +43,7 @@
 //    * Redistributions in binary form must reproduce the above copyright
 //      notice, this list of conditions and the following disclaimer in the
 //      documentation and/or other materials provided with the distribution.
-//    * Neither the name of the University of California, Berkeley nor the
+//    * Neither the name of the University of Notre Dame nor the
 //      names of its contributors may be used to endorse or promote products
 //      derived from this software without specific prior written permission.
 //
@@ -144,7 +144,7 @@ namespace gmm {
       for (Tri_loc = 0, i = 0; i < n; ++i) {
 	typedef typename linalg_traits<M>::const_sub_row_type row_type;
 	row_type row = mat_const_row(A, i);
-        typename linalg_traits<row_type>::const_iterator
+        typename linalg_traits<typename org_type<row_type>::t>::const_iterator
 	  it = vect_const_begin(row), ite = vect_const_end(row);
 
 	if (count) { Tri_val[Tri_loc] = T(0); Tri_ind[Tri_loc] = i; }
@@ -235,51 +235,6 @@ namespace gmm {
   { copy(v1, v2); gmm::lower_tri_solve(gmm::conjugated(P.U), v2, true); }
 
 
-
-  // for compatibility with old versions
-
-  template <typename Matrix>
-  struct cholesky_precond : public ildlt_precond<Matrix> {
-    cholesky_precond(const Matrix& A) : ildlt_precond<Matrix>(A) {}
-    cholesky_precond(void) {}
-  } IS_DEPRECATED;
-
-  template <typename Matrix, typename V1, typename V2> inline
-  void mult(const cholesky_precond<Matrix>& P, const V1 &v1, V2 &v2) {
-    gmm::copy(v1, v2);
-    gmm::lower_tri_solve(gmm::conjugated(P.U), v2, true);
-    for (size_type i = 0; i < mat_nrows(P.U); ++i) v2[i] /= P.D(i);
-    gmm::upper_tri_solve(P.U, v2, true);
-  }
-
-  template <typename Matrix, typename V1, typename V2> inline
-  void transposed_mult(const cholesky_precond<Matrix>& P,const V1 &v1,V2 &v2)
-  { mult(P, v1, v2); }
-
-  template <typename Matrix, typename V1, typename V2> inline
-  void left_mult(const cholesky_precond<Matrix>& P, const V1 &v1, V2 &v2) {
-    copy(v1, v2);
-    gmm::lower_tri_solve(gmm::conjugated(P.U), v2, true);
-    for (size_type i = 0; i < mat_nrows(P.U); ++i) v2[i] /= P.D(i);
-  }
-
-  template <typename Matrix, typename V1, typename V2> inline
-  void right_mult(const cholesky_precond<Matrix>& P, const V1 &v1, V2 &v2)
-  { copy(v1, v2); gmm::upper_tri_solve(P.U, v2, true);  }
-
-  template <typename Matrix, typename V1, typename V2> inline
-  void transposed_left_mult(const cholesky_precond<Matrix>& P, const V1 &v1,
-			    V2 &v2) {
-    copy(v1, v2);
-    gmm::upper_tri_solve(P.U, v2, true);
-    for (size_type i = 0; i < mat_nrows(P.U); ++i) v2[i] /= P.D(i);
-  }
-
-  template <typename Matrix, typename V1, typename V2> inline
-  void transposed_right_mult(const cholesky_precond<Matrix>& P, const V1 &v1,
-			     V2 &v2)
-  { copy(v1, v2); gmm::lower_tri_solve(gmm::conjugated(P.U), v2, true); }
-  
 }
 
 #endif 
diff --git a/contrib/gmm/gmm_precond_ildltt.h b/contrib/gmm/gmm_precond_ildltt.h
index 8afa9e7c25..54713df9e7 100644
--- a/contrib/gmm/gmm_precond_ildltt.h
+++ b/contrib/gmm/gmm_precond_ildltt.h
@@ -1,32 +1,33 @@
-// -*- c++ -*- (enables emacs c++ mode)
-//===========================================================================
-//
-// Copyright (C) 2003-2008 Yves Renard
-//
-// This file is a part of GETFEM++
-//
-// Getfem++  is  free software;  you  can  redistribute  it  and/or modify it
-// under  the  terms  of the  GNU  Lesser General Public License as published
-// by  the  Free Software Foundation;  either version 2.1 of the License,  or
-// (at your option) any later version.
-// This program  is  distributed  in  the  hope  that it will be useful,  but
-// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-// or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
-// License for more details.
-// You  should  have received a copy of the GNU Lesser General Public License
-// along  with  this program;  if not, write to the Free Software Foundation,
-// Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
-//
-// As a special exception, you may use this file as part of a free software
-// library without restriction.  Specifically, if other files instantiate
-// templates or use macros or inline functions from this file, or you compile
-// this file and link it with other files to produce an executable, this
-// file does not by itself cause the resulting executable to be covered by
-// the GNU General Public License.  This exception does not however
-// invalidate any other reasons why the executable file might be covered by
-// the GNU General Public License.
-//
-//===========================================================================
+/* -*- c++ -*- (enables emacs c++ mode) */
+/*===========================================================================
+
+ Copyright (C) 2003-2020 Yves Renard
+
+ This file is a part of GetFEM
+
+ GetFEM  is  free software;  you  can  redistribute  it  and/or modify it
+ under  the  terms  of the  GNU  Lesser General Public License as published
+ by  the  Free Software Foundation;  either version 3 of the License,  or
+ (at your option) any later version along with the GCC Runtime Library
+ Exception either version 3.1 or (at your option) any later version.
+ This program  is  distributed  in  the  hope  that it will be useful,  but
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+ License and GCC Runtime Library Exception for more details.
+ You  should  have received a copy of the GNU Lesser General Public License
+ along  with  this program;  if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+
+ As a special exception, you  may use  this file  as it is a part of a free
+ software  library  without  restriction.  Specifically,  if   other  files
+ instantiate  templates  or  use macros or inline functions from this file,
+ or  you compile this  file  and  link  it  with other files  to produce an
+ executable, this file  does  not  by itself cause the resulting executable
+ to be covered  by the GNU Lesser General Public License.  This   exception
+ does not  however  invalidate  any  other  reasons why the executable file
+ might be covered by the GNU Lesser General Public License.
+
+===========================================================================*/
 
 /**@file gmm_precond_ildltt.h
    @author  Yves Renard <Yves.Renard@insa-lyon.fr>
@@ -65,7 +66,9 @@ namespace gmm {
     void do_ildltt(const Matrix&, col_major);
 
   public:
-    void build_with(const Matrix& A) {
+    void build_with(const Matrix& A, int k_ = -1, double eps_ = double(-1)) {
+      if (k_ >= 0) K = k_;
+      if (eps_ >= double(0)) eps = eps_;
       gmm::resize(U, mat_nrows(A), mat_ncols(A));
       indiag.resize(std::min(mat_nrows(A), mat_ncols(A)));
       do_ildltt(A, typename principal_orientation_type<typename
@@ -165,52 +168,6 @@ namespace gmm {
 			     V2 &v2)
   { copy(v1, v2); gmm::lower_tri_solve(gmm::conjugated(P.U), v2, true); }
 
-
-  // for compatibility with old versions
-
-  template <typename Matrix>
-  struct choleskyt_precond : public ildltt_precond<Matrix>{
-    choleskyt_precond(const Matrix& A, int k_, double eps_)
-      : ildltt_precond<Matrix>(A, k_, eps_) {}
-    choleskyt_precond(void) {}
-  } IS_DEPRECATED;
-
-  template <typename Matrix, typename V1, typename V2> inline
-  void mult(const choleskyt_precond<Matrix>& P, const V1 &v1, V2 &v2) {
-    gmm::copy(v1, v2);
-    gmm::lower_tri_solve(gmm::conjugated(P.U), v2, true);
-    for (size_type i = 0; i < P.indiag.size(); ++i) v2[i] *= P.indiag[i];
-    gmm::upper_tri_solve(P.U, v2, true);
-  }
-
-  template <typename Matrix, typename V1, typename V2> inline
-  void transposed_mult(const choleskyt_precond<Matrix>& P,const V1 &v1, V2 &v2)
-  { mult(P, v1, v2); }
-
-  template <typename Matrix, typename V1, typename V2> inline
-  void left_mult(const choleskyt_precond<Matrix>& P, const V1 &v1, V2 &v2) {
-    copy(v1, v2);
-    gmm::lower_tri_solve(gmm::conjugated(P.U), v2, true);
-    for (size_type i = 0; i < P.indiag.size(); ++i) v2[i] *= P.indiag[i];
-  }
-
-  template <typename Matrix, typename V1, typename V2> inline
-  void right_mult(const choleskyt_precond<Matrix>& P, const V1 &v1, V2 &v2)
-  { copy(v1, v2); gmm::upper_tri_solve(P.U, v2, true); }
-
-  template <typename Matrix, typename V1, typename V2> inline
-  void transposed_left_mult(const choleskyt_precond<Matrix>& P, const V1 &v1,
-			    V2 &v2) {
-    copy(v1, v2);
-    gmm::upper_tri_solve(P.U, v2, true);
-    for (size_type i = 0; i < P.indiag.size(); ++i) v2[i] *= P.indiag[i];
-  }
-
-  template <typename Matrix, typename V1, typename V2> inline
-  void transposed_right_mult(const choleskyt_precond<Matrix>& P, const V1 &v1,
-			     V2 &v2)
-  { copy(v1, v2); gmm::lower_tri_solve(gmm::conjugated(P.U), v2, true); }
-
 }
 
 #endif 
diff --git a/contrib/gmm/gmm_precond_ilu.h b/contrib/gmm/gmm_precond_ilu.h
index 4d5f5fae77..25d322d03d 100644
--- a/contrib/gmm/gmm_precond_ilu.h
+++ b/contrib/gmm/gmm_precond_ilu.h
@@ -1,40 +1,40 @@
-// -*- c++ -*- (enables emacs c++ mode)
-//===========================================================================
-//
-// Copyright (C) 1997-2008 Yves Renard
-//
-// This file is a part of GETFEM++
-//
-// Getfem++  is  free software;  you  can  redistribute  it  and/or modify it
-// under  the  terms  of the  GNU  Lesser General Public License as published
-// by  the  Free Software Foundation;  either version 2.1 of the License,  or
-// (at your option) any later version.
-// This program  is  distributed  in  the  hope  that it will be useful,  but
-// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-// or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
-// License for more details.
-// You  should  have received a copy of the GNU Lesser General Public License
-// along  with  this program;  if not, write to the Free Software Foundation,
-// Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
-//
-// As a special exception, you may use this file as part of a free software
-// library without restriction.  Specifically, if other files instantiate
-// templates or use macros or inline functions from this file, or you compile
-// this file and link it with other files to produce an executable, this
-// file does not by itself cause the resulting executable to be covered by
-// the GNU General Public License.  This exception does not however
-// invalidate any other reasons why the executable file might be covered by
-// the GNU General Public License.
-//
-//===========================================================================
+/* -*- c++ -*- (enables emacs c++ mode) */
+/*===========================================================================
+
+ Copyright (C) 2002-2020 Yves Renard
+
+ This file is a part of GetFEM
+
+ GetFEM  is  free software;  you  can  redistribute  it  and/or modify it
+ under  the  terms  of the  GNU  Lesser General Public License as published
+ by  the  Free Software Foundation;  either version 3 of the License,  or
+ (at your option) any later version along with the GCC Runtime Library
+ Exception either version 3.1 or (at your option) any later version.
+ This program  is  distributed  in  the  hope  that it will be useful,  but
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+ License and GCC Runtime Library Exception for more details.
+ You  should  have received a copy of the GNU Lesser General Public License
+ along  with  this program;  if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+
+ As a special exception, you  may use  this file  as it is a part of a free
+ software  library  without  restriction.  Specifically,  if   other  files
+ instantiate  templates  or  use macros or inline functions from this file,
+ or  you compile this  file  and  link  it  with other files  to produce an
+ executable, this file  does  not  by itself cause the resulting executable
+ to be covered  by the GNU Lesser General Public License.  This   exception
+ does not  however  invalidate  any  other  reasons why the executable file
+ might be covered by the GNU Lesser General Public License.
+
+===========================================================================*/
 
 // This file is a modified version of ilu.h from ITL.
 // See http://osl.iu.edu/research/itl/
 // Following the corresponding Copyright notice.
 //===========================================================================
 //
-// Copyright (c) 1997-2001, The Trustees of Indiana University.
-// All rights reserved.
+// Copyright (c) 1998-2020, University of Notre Dame. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are met:
 //
@@ -43,7 +43,7 @@
 //    * Redistributions in binary form must reproduce the above copyright
 //      notice, this list of conditions and the following disclaimer in the
 //      documentation and/or other materials provided with the distribution.
-//    * Neither the name of the University of California, Berkeley nor the
+//    * Neither the name of the University of Notre Dame nor the
 //      names of its contributors may be used to endorse or promote products
 //      derived from this software without specific prior written permission.
 //
@@ -142,7 +142,7 @@ namespace gmm {
       for (i = 0; i < n; ++i) {
 	typedef typename linalg_traits<M>::const_sub_row_type row_type;
 	row_type row = mat_const_row(A, i);
-	typename linalg_traits<row_type>::const_iterator
+	typename linalg_traits<typename org_type<row_type>::t>::const_iterator
 	  it = vect_const_begin(row), ite = vect_const_end(row);
 	
 	if (count) { U_val[U_loc] = T(0); U_ind[U_loc] = i; }
@@ -192,16 +192,16 @@ namespace gmm {
 	qn = j + 1;
 	rn = U_ptr[i];
 	
-	for (pn++; U_ind[pn] < i && pn < U_ptr[L_ind[j]+1]; pn++) {
-	  while (L_ind[qn] < U_ind[pn] && qn < L_ptr[i+1])
+	for (pn++; pn < U_ptr[L_ind[j]+1] && U_ind[pn] < i; pn++) {
+	  while (qn < L_ptr[i+1] && L_ind[qn] < U_ind[pn])
 	    qn++;
-	  if (U_ind[pn] == L_ind[qn] && qn < L_ptr[i+1])
+	  if (qn < L_ptr[i+1] && U_ind[pn] == L_ind[qn])
 	    L_val[qn] -= multiplier * U_val[pn];
 	}
 	for (; pn < U_ptr[L_ind[j]+1]; pn++) {
-	  while (U_ind[rn] < U_ind[pn] && rn < U_ptr[i+1])
+	  while (rn < U_ptr[i+1] && U_ind[rn] < U_ind[pn])
 	    rn++;
-	  if (U_ind[pn] == U_ind[rn] && rn < U_ptr[i+1])
+	  if (rn < U_ptr[i+1] && U_ind[pn] == U_ind[rn])
 	    U_val[rn] -= multiplier * U_val[pn];
 	}
       }
diff --git a/contrib/gmm/gmm_precond_ilut.h b/contrib/gmm/gmm_precond_ilut.h
index b0c304543e..04bbe7df62 100644
--- a/contrib/gmm/gmm_precond_ilut.h
+++ b/contrib/gmm/gmm_precond_ilut.h
@@ -1,32 +1,66 @@
-// -*- c++ -*- (enables emacs c++ mode)
+/* -*- c++ -*- (enables emacs c++ mode) */
+/*===========================================================================
+
+ Copyright (C) 2002-2020 Yves Renard
+
+ This file is a part of GetFEM
+
+ GetFEM  is  free software;  you  can  redistribute  it  and/or modify it
+ under  the  terms  of the  GNU  Lesser General Public License as published
+ by  the  Free Software Foundation;  either version 3 of the License,  or
+ (at your option) any later version along with the GCC Runtime Library
+ Exception either version 3.1 or (at your option) any later version.
+ This program  is  distributed  in  the  hope  that it will be useful,  but
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+ License and GCC Runtime Library Exception for more details.
+ You  should  have received a copy of the GNU Lesser General Public License
+ along  with  this program;  if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+
+ As a special exception, you  may use  this file  as it is a part of a free
+ software  library  without  restriction.  Specifically,  if   other  files
+ instantiate  templates  or  use macros or inline functions from this file,
+ or  you compile this  file  and  link  it  with other files  to produce an
+ executable, this file  does  not  by itself cause the resulting executable
+ to be covered  by the GNU Lesser General Public License.  This   exception
+ does not  however  invalidate  any  other  reasons why the executable file
+ might be covered by the GNU Lesser General Public License.
+
+===========================================================================*/
+
+// This file is a modified version of ilut.h from ITL.
+// See http://osl.iu.edu/research/itl/
+// Following the corresponding Copyright notice.
 //===========================================================================
 //
-// Copyright (C) 1997-2008 Yves Renard
+// Copyright (c) 1998-2020, University of Notre Dame. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
 //
-// This file is a part of GETFEM++
+//    * Redistributions of source code must retain the above copyright
+//      notice, this list of conditions and the following disclaimer.
+//    * Redistributions in binary form must reproduce the above copyright
+//      notice, this list of conditions and the following disclaimer in the
+//      documentation and/or other materials provided with the distribution.
+//    * Neither the name of the University of Notre Dame nor the
+//      names of its contributors may be used to endorse or promote products
+//      derived from this software without specific prior written permission.
 //
-// Getfem++  is  free software;  you  can  redistribute  it  and/or modify it
-// under  the  terms  of the  GNU  Lesser General Public License as published
-// by  the  Free Software Foundation;  either version 2.1 of the License,  or
-// (at your option) any later version.
-// This program  is  distributed  in  the  hope  that it will be useful,  but
-// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-// or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
-// License for more details.
-// You  should  have received a copy of the GNU Lesser General Public License
-// along  with  this program;  if not, write to the Free Software Foundation,
-// Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
-//
-// As a special exception, you may use this file as part of a free software
-// library without restriction.  Specifically, if other files instantiate
-// templates or use macros or inline functions from this file, or you compile
-// this file and link it with other files to produce an executable, this
-// file does not by itself cause the resulting executable to be covered by
-// the GNU General Public License.  This exception does not however
-// invalidate any other reasons why the executable file might be covered by
-// the GNU General Public License.
+// THIS SOFTWARE  IS  PROVIDED  BY  THE TRUSTEES  OF  INDIANA UNIVERSITY  AND
+// CONTRIBUTORS  ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,  INCLUDING,
+// BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND  FITNESS
+// FOR  A PARTICULAR PURPOSE ARE DISCLAIMED. IN  NO  EVENT SHALL THE TRUSTEES
+// OF INDIANA UNIVERSITY AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY,  OR CONSEQUENTIAL DAMAGES (INCLUDING,  BUT
+// NOT  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA,  OR PROFITS;  OR BUSINESS  INTERRUPTION)  HOWEVER  CAUSED AND ON ANY
+// THEORY  OF  LIABILITY,  WHETHER  IN  CONTRACT,  STRICT  LIABILITY, OR TORT
+// (INCLUDING  NEGLIGENCE  OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+// THIS  SOFTWARE,  EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 //
 //===========================================================================
+
 #ifndef GMM_PRECOND_ILUT_H
 #define GMM_PRECOND_ILUT_H
 
@@ -83,7 +117,9 @@ namespace gmm {
     void do_ilut(const Matrix&, col_major);
 
   public:
-    void build_with(const Matrix& A) {
+    void build_with(const Matrix& A, int k_ = -1, double eps_ = double(-1)) {
+      if (k_ >= 0) K = k_;
+      if (eps_ >= double(0)) eps = eps_;
       invert = false;
       gmm::resize(L, mat_nrows(A), mat_ncols(A));
       gmm::resize(U, mat_nrows(A), mat_ncols(A));
@@ -119,16 +155,16 @@ namespace gmm {
       gmm::copy(mat_const_row(A, i), w);
       double norm_row = gmm::vect_norm2(w);
 
-      typename _wsvector::iterator wkold = w.begin();
-      bool itfirst = true;
+      typename _wsvector::iterator wkold = w.end();
       for (typename _wsvector::iterator wk = w.begin();
 	   wk != w.end() && wk->first < i; ) {
 	size_type k = wk->first;
 	tmp = (wk->second) * indiag[k];
-	if (gmm::abs(tmp) < eps * norm_row) w.erase(k); 
+	if (gmm::abs(tmp) < eps * norm_row) w.erase(k);
 	else { wk->second += tmp; gmm::add(scaled(mat_row(U, k), -tmp), w); }
-	if (itfirst) wk = w.begin(); else wk = ++wkold;
-	if (wk != w.end() && wk->first == k) { ++wk; itfirst = false; }
+	if (wkold == w.end()) wk = w.begin(); else { wk = wkold; ++wk; }
+	if (wk != w.end() && wk->first == k)
+	  { if (wkold == w.end()) wkold = w.begin(); else ++wkold; ++wk; }
       }
       tmp = w[i];
 
diff --git a/contrib/gmm/gmm_precond_ilutp.h b/contrib/gmm/gmm_precond_ilutp.h
index 68bce2e7c4..785bf35f30 100644
--- a/contrib/gmm/gmm_precond_ilutp.h
+++ b/contrib/gmm/gmm_precond_ilutp.h
@@ -1,32 +1,33 @@
-// -*- c++ -*- (enables emacs c++ mode)
-//===========================================================================
-//
-// Copyright (C) 2004-2008 Yves Renard
-//
-// This file is a part of GETFEM++
-//
-// Getfem++  is  free software;  you  can  redistribute  it  and/or modify it
-// under  the  terms  of the  GNU  Lesser General Public License as published
-// by  the  Free Software Foundation;  either version 2.1 of the License,  or
-// (at your option) any later version.
-// This program  is  distributed  in  the  hope  that it will be useful,  but
-// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-// or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
-// License for more details.
-// You  should  have received a copy of the GNU Lesser General Public License
-// along  with  this program;  if not, write to the Free Software Foundation,
-// Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
-//
-// As a special exception, you may use this file as part of a free software
-// library without restriction.  Specifically, if other files instantiate
-// templates or use macros or inline functions from this file, or you compile
-// this file and link it with other files to produce an executable, this
-// file does not by itself cause the resulting executable to be covered by
-// the GNU General Public License.  This exception does not however
-// invalidate any other reasons why the executable file might be covered by
-// the GNU General Public License.
-//
-//===========================================================================
+/* -*- c++ -*- (enables emacs c++ mode) */
+/*===========================================================================
+
+ Copyright (C) 2004-2020 Yves Renard
+
+ This file is a part of GetFEM
+
+ GetFEM  is  free software;  you  can  redistribute  it  and/or modify it
+ under  the  terms  of the  GNU  Lesser General Public License as published
+ by  the  Free Software Foundation;  either version 3 of the License,  or
+ (at your option) any later version along with the GCC Runtime Library
+ Exception either version 3.1 or (at your option) any later version.
+ This program  is  distributed  in  the  hope  that it will be useful,  but
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+ License and GCC Runtime Library Exception for more details.
+ You  should  have received a copy of the GNU Lesser General Public License
+ along  with  this program;  if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+
+ As a special exception, you  may use  this file  as it is a part of a free
+ software  library  without  restriction.  Specifically,  if   other  files
+ instantiate  templates  or  use macros or inline functions from this file,
+ or  you compile this  file  and  link  it  with other files  to produce an
+ executable, this file  does  not  by itself cause the resulting executable
+ to be covered  by the GNU Lesser General Public License.  This   exception
+ does not  however  invalidate  any  other  reasons why the executable file
+ might be covered by the GNU Lesser General Public License.
+
+===========================================================================*/
 
 /**@file gmm_precond_ilutp.h
    @author  Yves Renard <Yves.Renard@insa-lyon.fr>
@@ -75,7 +76,9 @@ namespace gmm {
     void do_ilutp(const Matrix&, col_major);
 
   public:
-    void build_with(const Matrix& A) {
+    void build_with(const Matrix& A, int k_ = -1, double eps_ = double(-1)) {
+      if (k_ >= 0) K = k_;
+      if (eps_ >= double(0)) eps = eps_;
       invert = false;
       gmm::resize(L, mat_nrows(A), mat_ncols(A));
       gmm::resize(U, mat_nrows(A), mat_ncols(A));
@@ -120,16 +123,16 @@ namespace gmm {
       copy(sub_vector(mat_const_row(A, i), indperm), w);
       double norm_row = gmm::vect_norm2(mat_const_row(A, i)); 
 
-      typename _wsvector::iterator wkold = w.begin();
-      bool itfirst = true;
+      typename _wsvector::iterator wkold = w.end();
       for (typename _wsvector::iterator wk = w.begin();
 	   wk != w.end() && wk->first < i; )  {
 	size_type k = wk->first;
 	tmp = (wk->second) * indiag[k];
 	if (gmm::abs(tmp) < eps * norm_row) w.erase(k); 
 	else { wk->second += tmp; gmm::add(scaled(mat_row(U, k), -tmp), w); }
-	if (itfirst) wk = w.begin(); else wk = ++wkold;
-	if (wk != w.end() && wk->first == k) { ++wk; itfirst = false; }
+	if (wkold == w.end()) wk = w.begin(); else { wk = wkold; ++wk; }
+	if (wk != w.end() && wk->first == k)
+	  { if (wkold == w.end()) wkold = w.begin(); else ++wkold; ++wk; }
       }
 
       gmm::clean(w, eps * norm_row);
diff --git a/contrib/gmm/gmm_precond_mr_approx_inverse.h b/contrib/gmm/gmm_precond_mr_approx_inverse.h
index cb54822cf6..91a749dad2 100644
--- a/contrib/gmm/gmm_precond_mr_approx_inverse.h
+++ b/contrib/gmm/gmm_precond_mr_approx_inverse.h
@@ -1,40 +1,41 @@
-// -*- c++ -*- (enables emacs c++ mode)
-//===========================================================================
-//
-// Copyright (C) 1997-2008 Yves Renard
-//
-// This file is a part of GETFEM++
-//
-// Getfem++  is  free software;  you  can  redistribute  it  and/or modify it
-// under  the  terms  of the  GNU  Lesser General Public License as published
-// by  the  Free Software Foundation;  either version 2.1 of the License,  or
-// (at your option) any later version.
-// This program  is  distributed  in  the  hope  that it will be useful,  but
-// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-// or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
-// License for more details.
-// You  should  have received a copy of the GNU Lesser General Public License
-// along  with  this program;  if not, write to the Free Software Foundation,
-// Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
-//
-// As a special exception, you may use this file as part of a free software
-// library without restriction.  Specifically, if other files instantiate
-// templates or use macros or inline functions from this file, or you compile
-// this file and link it with other files to produce an executable, this
-// file does not by itself cause the resulting executable to be covered by
-// the GNU General Public License.  This exception does not however
-// invalidate any other reasons why the executable file might be covered by
-// the GNU General Public License.
-//
-//===========================================================================
+/* -*- c++ -*- (enables emacs c++ mode) */
+/*===========================================================================
+
+ Copyright (C) 2002-2020 Yves Renard
+
+ This file is a part of GetFEM
+
+ GetFEM  is  free software;  you  can  redistribute  it  and/or modify it
+ under  the  terms  of the  GNU  Lesser General Public License as published
+ by  the  Free Software Foundation;  either version 3 of the License,  or
+ (at your option) any later version along with the GCC Runtime Library
+ Exception either version 3.1 or (at your option) any later version.
+ This program  is  distributed  in  the  hope  that it will be useful,  but
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+ License and GCC Runtime Library Exception for more details.
+ You  should  have received a copy of the GNU Lesser General Public License
+ along  with  this program;  if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+
+ As a special exception, you  may use  this file  as it is a part of a free
+ software  library  without  restriction.  Specifically,  if   other  files
+ instantiate  templates  or  use macros or inline functions from this file,
+ or  you compile this  file  and  link  it  with other files  to produce an
+ executable, this file  does  not  by itself cause the resulting executable
+ to be covered  by the GNU Lesser General Public License.  This   exception
+ does not  however  invalidate  any  other  reasons why the executable file
+ might be covered by the GNU Lesser General Public License.
+
+===========================================================================*/
+
 
 // This file is a modified version of approximate_inverse.h from ITL.
 // See http://osl.iu.edu/research/itl/
 // Following the corresponding Copyright notice.
 //===========================================================================
 //
-// Copyright (c) 1997-2001, The Trustees of Indiana University.
-// All rights reserved.
+// Copyright (c) 1998-2020, University of Notre Dame. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are met:
 //
@@ -43,7 +44,7 @@
 //    * Redistributions in binary form must reproduce the above copyright
 //      notice, this list of conditions and the following disclaimer in the
 //      documentation and/or other materials provided with the distribution.
-//    * Neither the name of the University of California, Berkeley nor the
+//    * Neither the name of the University of Notre Dame nor the
 //      names of its contributors may be used to endorse or promote products
 //      derived from this software without specific prior written permission.
 //
diff --git a/contrib/gmm/gmm_range_basis.h b/contrib/gmm/gmm_range_basis.h
new file mode 100644
index 0000000000..7d7eeb589c
--- /dev/null
+++ b/contrib/gmm/gmm_range_basis.h
@@ -0,0 +1,499 @@
+/* -*- c++ -*- (enables emacs c++ mode) */
+/*===========================================================================
+
+ Copyright (C) 2009-2020 Yves Renard
+
+ This file is a part of GetFEM
+
+ GetFEM  is  free software;  you  can  redistribute  it  and/or modify it
+ under  the  terms  of the  GNU  Lesser General Public License as published
+ by  the  Free Software Foundation;  either version 3 of the License,  or
+ (at your option) any later version along with the GCC Runtime Library
+ Exception either version 3.1 or (at your option) any later version.
+ This program  is  distributed  in  the  hope  that it will be useful,  but
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+ License and GCC Runtime Library Exception for more details.
+ You  should  have received a copy of the GNU Lesser General Public License
+ along  with  this program;  if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+
+ As a special exception, you  may use  this file  as it is a part of a free
+ software  library  without  restriction.  Specifically,  if   other  files
+ instantiate  templates  or  use macros or inline functions from this file,
+ or  you compile this  file  and  link  it  with other files  to produce an
+ executable, this file  does  not  by itself cause the resulting executable
+ to be covered  by the GNU Lesser General Public License.  This   exception
+ does not  however  invalidate  any  other  reasons why the executable file
+ might be covered by the GNU Lesser General Public License.
+
+===========================================================================*/
+
+/**@file gmm_range_basis.h
+   @author  Yves Renard <Yves.Renard@insa-lyon.fr>
+   @date March 10, 2009.
+   @brief Extract a basis of the range of a (large sparse) matrix from the
+          columns of this matrix.
+*/
+#ifndef GMM_RANGE_BASIS_H
+#define GMM_RANGE_BASIS_H
+#include "gmm_dense_qr.h"
+#include "gmm_dense_lu.h"
+
+#include "gmm_kernel.h"
+#include "gmm_iter.h"
+#include <set>
+#include <list>
+
+
+namespace gmm {
+
+
+  template <typename T, typename VECT, typename MAT1>
+  void tridiag_qr_algorithm
+  (std::vector<typename number_traits<T>::magnitude_type> diag,
+   std::vector<T> sdiag, const VECT &eigval_, const MAT1 &eigvect_,
+   bool compvect, tol_type_for_qr tol = default_tol_for_qr) {
+    VECT &eigval = const_cast<VECT &>(eigval_);
+    MAT1 &eigvect = const_cast<MAT1 &>(eigvect_);
+    typedef typename number_traits<T>::magnitude_type R;
+
+    if (compvect) gmm::copy(identity_matrix(), eigvect);
+
+    size_type n = diag.size(), q = 0, p, ite = 0;
+    if (n == 0) return;
+    if (n == 1) { eigval[0] = gmm::real(diag[0]); return; }
+
+    symmetric_qr_stop_criterion(diag, sdiag, p, q, tol);
+
+    while (q < n) {
+      sub_interval SUBI(p, n-p-q), SUBJ(0, mat_ncols(eigvect)), SUBK(p, n-p-q);
+      if (!compvect) SUBK = sub_interval(0,0);
+
+      symmetric_Wilkinson_qr_step(sub_vector(diag, SUBI),
+                                  sub_vector(sdiag, SUBI),
+                                  sub_matrix(eigvect, SUBJ, SUBK), compvect);
+
+      symmetric_qr_stop_criterion(diag, sdiag, p, q, tol*R(3));
+      ++ite;
+      GMM_ASSERT1(ite < n*100, "QR algorithm failed.");
+    }
+
+    gmm::copy(diag, eigval);
+  }
+
+  // Range basis with a restarted Lanczos method
+  template <typename Mat>
+  void range_basis_eff_Lanczos(const Mat &BB, std::set<size_type> &columns,
+                       double EPS=1E-12) {
+    typedef std::set<size_type> TAB;
+    typedef typename linalg_traits<Mat>::value_type T;
+    typedef typename number_traits<T>::magnitude_type R;
+
+    size_type nc_r = columns.size(), k;
+    col_matrix< rsvector<T> > B(mat_nrows(BB), mat_ncols(BB));
+
+    k = 0;
+    for (TAB::iterator it = columns.begin(); it!=columns.end(); ++it, ++k){
+      gmm::copy(scaled(mat_col(BB, *it), T(1)/vect_norm2(mat_col(BB, *it))),
+                mat_col(B, *it));
+    }
+    std::vector<T> w(mat_nrows(B));
+    size_type restart = 120;
+    std::vector<T> sdiag(restart);
+    std::vector<R> eigval(restart), diag(restart);
+    dense_matrix<T> eigvect(restart, restart);
+
+    R rho = R(-1), rho2;
+    while (nc_r) {
+
+      std::vector<T> v(nc_r), v0(nc_r), wl(nc_r);
+      dense_matrix<T> lv(nc_r, restart);
+
+      if (rho < R(0)) { // Estimate of the spectral radius of B^* B
+        gmm::fill_random(v);
+        for (size_type i = 0; i < 100; ++i) {
+          gmm::scale(v, T(1)/vect_norm2(v));
+          gmm::copy(v, v0);
+          k = 0; gmm::clear(w);
+          for (TAB::iterator it=columns.begin(); it!=columns.end(); ++it, ++k)
+            add(scaled(mat_col(B, *it), v[k]), w);
+          k = 0;
+          for (TAB::iterator it=columns.begin(); it!=columns.end(); ++it, ++k)
+            v[k] = vect_hp(w, mat_col(B, *it));
+          rho = gmm::abs(vect_hp(v, v0) / vect_hp(v0, v0));
+        }
+        rho *= R(2);
+      }
+
+      // Computing vectors of the null space of de B^* B with restarted Lanczos
+      rho2 = 0;
+      gmm::fill_random(v);
+      size_type iter = 0;
+      for(;;++iter) {
+        R rho_old = rho2;
+        R beta = R(0), alpha;
+        gmm::scale(v, T(1)/vect_norm2(v));
+        size_type eff_restart = restart;
+    if (sdiag.size() != restart) {
+      sdiag.resize(restart); eigval.resize(restart); diag.resize(restart); gmm::resize(eigvect, restart, restart);
+      gmm::resize(lv, nc_r, restart);
+    }
+
+        for (size_type i = 0; i < restart; ++i) { // Lanczos iterations
+          gmm::copy(v, mat_col(lv, i));
+          gmm::clear(w);
+          k = 0;
+          for (TAB::iterator it=columns.begin(); it!=columns.end(); ++it, ++k)
+            add(scaled(mat_col(B, *it), v[k]), w);
+
+          k = 0;
+          for (TAB::iterator it=columns.begin(); it!=columns.end(); ++it, ++k)
+            wl[k] = v[k]*rho - vect_hp(w, mat_col(B, *it)) - beta*v0[k];
+          alpha = gmm::real(vect_hp(wl, v));
+          diag[i] = alpha;
+          gmm::add(gmm::scaled(v, -alpha), wl);
+          sdiag[i] = beta = vect_norm2(wl);
+          gmm::copy(v, v0);
+      if (beta < EPS) { eff_restart = i+1; break; }
+      gmm::copy(gmm::scaled(wl, T(1) / beta), v);
+    }
+    if (eff_restart != restart) {
+      sdiag.resize(eff_restart); eigval.resize(eff_restart); diag.resize(eff_restart);
+      gmm::resize(eigvect, eff_restart, eff_restart); gmm::resize(lv, nc_r, eff_restart);
+    }
+        tridiag_qr_algorithm(diag, sdiag, eigval, eigvect, true);
+
+        size_type num = size_type(-1);
+        rho2 = R(0);
+        for (size_type j = 0; j < eff_restart; ++j)
+          { R nvp=gmm::abs(eigval[j]); if (nvp > rho2) { rho2=nvp; num=j; }}
+
+        GMM_ASSERT1(num != size_type(-1), "Internal error");
+
+        gmm::mult(lv, mat_col(eigvect, num), v);
+
+        if (gmm::abs(rho2-rho_old) < rho_old*R(EPS)) break;
+        // if (gmm::abs(rho-rho2) < rho*R(gmm::sqrt(EPS))) break;
+        if (gmm::abs(rho-rho2) < rho*R(EPS)*R(100)) break;
+      }
+
+      if (gmm::abs(rho-rho2) < rho*R(EPS*10.)) {
+        size_type j_max = size_type(-1), j = 0;
+        R val_max = R(0);
+        for (TAB::iterator it=columns.begin(); it!=columns.end(); ++it, ++j)
+          if (gmm::abs(v[j]) > val_max)
+            { val_max = gmm::abs(v[j]); j_max = *it; }
+        columns.erase(j_max); nc_r = columns.size();
+      }
+      else break;
+    }
+  }
+
+  // Range basis with LU decomposition. Not stable from a numerical viewpoint.
+  // Complex version not verified
+  template <typename Mat>
+  void range_basis_eff_lu(const Mat &B, std::set<size_type> &columns,
+                          std::vector<bool> &c_ortho, double EPS) {
+
+    typedef std::set<size_type> TAB;
+    typedef typename linalg_traits<Mat>::value_type T;
+    typedef typename number_traits<T>::magnitude_type R;
+
+    size_type nc_r = 0, nc_o = 0, nc = mat_ncols(B), nr = mat_nrows(B), i, j;
+
+    for (TAB::iterator it=columns.begin(); it!=columns.end(); ++it)
+      if (!(c_ortho[*it])) ++nc_r; else nc_o++;
+
+    if (nc_r > 0) {
+
+      gmm::row_matrix< gmm::rsvector<T> > Hr(nc, nc_r), Ho(nc, nc_o);
+      gmm::row_matrix< gmm::rsvector<T> > BBr(nr, nc_r), BBo(nr, nc_o);
+
+      i = j = 0;
+      for (TAB::iterator it=columns.begin(); it!=columns.end(); ++it)
+        if (!(c_ortho[*it]))
+          { Hr(*it, i) = T(1)/ vect_norminf(mat_col(B, *it)); ++i; }
+        else
+          { Ho(*it, j) = T(1)/ vect_norm2(mat_col(B, *it)); ++j; }
+
+      gmm::mult(B, Hr, BBr);
+      gmm::mult(B, Ho, BBo);
+      gmm::dense_matrix<T> M(nc_r, nc_r), BBB(nc_r, nc_o), MM(nc_r, nc_r);
+      gmm::mult(gmm::conjugated(BBr), BBr, M);
+      gmm::mult(gmm::conjugated(BBr), BBo, BBB);
+      gmm::mult(BBB, gmm::conjugated(BBB), MM);
+      gmm::add(gmm::scaled(MM, T(-1)), M);
+
+      std::vector<int> ipvt(nc_r);
+      gmm::lu_factor(M, ipvt);
+
+      R emax = R(0);
+      for (i = 0; i < nc_r; ++i) emax = std::max(emax, gmm::abs(M(i,i)));
+
+      i = 0;
+      std::set<size_type> c = columns;
+      for (TAB::iterator it = c.begin(); it != c.end(); ++it)
+        if (!(c_ortho[*it])) {
+          if (gmm::abs(M(i,i)) <= R(EPS)*emax) columns.erase(*it);
+          ++i;
+        }
+    }
+  }
+
+
+  // Range basis with Gram-Schmidt orthogonalization (sparse version)
+  // The sparse version is better when the sparsity is high and less efficient
+  // than the dense version for high degree elements (P3, P4 ...)
+  // Complex version not verified
+  template <typename Mat>
+  void range_basis_eff_Gram_Schmidt_sparse(const Mat &BB,
+                                           std::set<size_type> &columns,
+                                           std::vector<bool> &c_ortho,
+                                           double EPS) {
+
+    typedef std::set<size_type> TAB;
+    typedef typename linalg_traits<Mat>::value_type T;
+    typedef typename number_traits<T>::magnitude_type R;
+
+    size_type nc = mat_ncols(BB), nr = mat_nrows(BB);
+    std::set<size_type> c = columns, rc = columns;
+
+    gmm::col_matrix< rsvector<T> > B(nr, nc);
+    for (std::set<size_type>::iterator it = columns.begin();
+         it != columns.end(); ++it) {
+      gmm::copy(mat_col(BB, *it), mat_col(B, *it));
+      gmm::scale(mat_col(B, *it), T(1)/vect_norm2(mat_col(B, *it)));
+    }
+
+    for (std::set<size_type>::iterator it = c.begin(); it != c.end(); ++it)
+      if (c_ortho[*it]) {
+        for (std::set<size_type>::iterator it2 = rc.begin();
+             it2 != rc.end(); ++it2)
+          if (!(c_ortho[*it2])) {
+            T r = -vect_hp(mat_col(B, *it2), mat_col(B, *it));
+            if (r != T(0)) add(scaled(mat_col(B, *it), r), mat_col(B, *it2));
+          }
+        rc.erase(*it);
+      }
+
+    while (rc.size()) {
+      R nmax = R(0); size_type cmax = size_type(-1);
+      for (std::set<size_type>::iterator it=rc.begin(); it != rc.end();) {
+        TAB::iterator itnext = it; ++itnext;
+        R n = vect_norm2(mat_col(B, *it));
+        if (nmax < n) { nmax = n; cmax = *it; }
+        if (n < R(EPS)) { columns.erase(*it); rc.erase(*it); }
+        it = itnext;
+      }
+
+      if (nmax < R(EPS)) break;
+
+      gmm::scale(mat_col(B, cmax), T(1)/vect_norm2(mat_col(B, cmax)));
+      rc.erase(cmax);
+      for (std::set<size_type>::iterator it=rc.begin(); it!=rc.end(); ++it) {
+        T r = -vect_hp(mat_col(B, *it), mat_col(B, cmax));
+        if (r != T(0)) add(scaled(mat_col(B, cmax), r), mat_col(B, *it));
+      }
+    }
+    for (std::set<size_type>::iterator it=rc.begin(); it!=rc.end(); ++it)
+      columns.erase(*it);
+  }
+
+
+  // Range basis with Gram-Schmidt orthogonalization (dense version)
+  template <typename Mat>
+  void range_basis_eff_Gram_Schmidt_dense(const Mat &B,
+                                          std::set<size_type> &columns,
+                                          std::vector<bool> &c_ortho,
+                                          double EPS) {
+
+    typedef std::set<size_type> TAB;
+    typedef typename linalg_traits<Mat>::value_type T;
+    typedef typename number_traits<T>::magnitude_type R;
+
+    size_type nc_r = columns.size(), nc = mat_ncols(B), nr = mat_nrows(B), i;
+    std::set<size_type> rc;
+
+    row_matrix< gmm::rsvector<T> > H(nc, nc_r), BB(nr, nc_r);
+    std::vector<T> v(nc_r);
+    std::vector<size_type> ind(nc_r);
+
+    i = 0;
+    for (TAB::iterator it = columns.begin(); it != columns.end(); ++it, ++i)
+      H(*it, i) = T(1) / vect_norm2(mat_col(B, *it));
+
+    mult(B, H, BB);
+    dense_matrix<T> M(nc_r, nc_r);
+    mult(gmm::conjugated(BB), BB, M);
+
+    i = 0;
+    for (TAB::iterator it = columns.begin(); it != columns.end(); ++it, ++i)
+      if (c_ortho[*it]) {
+        gmm::copy(mat_row(M, i), v);
+        rank_one_update(M, scaled(v, T(-1)), v);
+        M(i, i) = T(1);
+      }
+      else { rc.insert(i); ind[i] = *it; }
+
+    while (rc.size() > 0) {
+
+      // Next pivot
+      R nmax = R(0); size_type imax = size_type(-1);
+      for (TAB::iterator it = rc.begin(); it != rc.end();) {
+        TAB::iterator itnext = it; ++itnext;
+        R a = gmm::abs(M(*it, *it));
+        if (a > nmax) { nmax = a; imax = *it; }
+        if (a < R(EPS)) { columns.erase(ind[*it]); rc.erase(*it); }
+        it = itnext;
+      }
+
+      if (nmax < R(EPS)) break;
+
+      // Normalization
+      gmm::scale(mat_row(M, imax), T(1) / sqrt(nmax));
+      gmm::scale(mat_col(M, imax), T(1) / sqrt(nmax));
+
+      // orthogonalization
+      copy(mat_row(M, imax), v);
+      rank_one_update(M, scaled(v, T(-1)), v);
+      M(imax, imax) = T(1);
+
+      rc.erase(imax);
+    }
+    for (std::set<size_type>::iterator it=rc.begin(); it!=rc.end(); ++it)
+      columns.erase(ind[*it]);
+  }
+
+  template <typename L> size_type nnz_eps(const L& l, double eps) {
+    typename linalg_traits<L>::const_iterator it = vect_const_begin(l),
+      ite = vect_const_end(l);
+    size_type res(0);
+    for (; it != ite; ++it) if (gmm::abs(*it) >= eps) ++res;
+    return res;
+  }
+
+  template <typename L>
+  bool reserve__rb(const L& l, std::vector<bool> &b, double eps) {
+    typename linalg_traits<L>::const_iterator it = vect_const_begin(l),
+      ite = vect_const_end(l);
+    bool ok = true;
+    for (; it != ite; ++it)
+      if (gmm::abs(*it) >= eps && b[it.index()]) ok = false;
+    if (ok) {
+      for (it = vect_const_begin(l); it != ite; ++it)
+        if (gmm::abs(*it) >= eps) b[it.index()] = true;
+    }
+    return ok;
+  }
+
+  template <typename Mat>
+  void range_basis(const Mat &B, std::set<size_type> &columns,
+                       double EPS, col_major, bool skip_init=false) {
+
+    typedef typename linalg_traits<Mat>::value_type T;
+    typedef typename number_traits<T>::magnitude_type R;
+
+    size_type nc = mat_ncols(B), nr = mat_nrows(B);
+
+    std::vector<R> norms(nc);
+    std::vector<bool> c_ortho(nc), booked(nr);
+    std::vector< std::set<size_type> > nnzs(mat_nrows(B));
+
+    if (!skip_init) {
+
+      R norm_max = R(0);
+      for (size_type i = 0; i < nc; ++i) {
+        norms[i] = vect_norminf(mat_col(B, i));
+        norm_max = std::max(norm_max, norms[i]);
+      }
+
+      columns.clear();
+      for (size_type i = 0; i < nc; ++i)
+        if (norms[i] > norm_max*R(EPS)) {
+          columns.insert(i);
+          nnzs[nnz_eps(mat_col(B, i), R(EPS) * norms[i])].insert(i);
+        }
+
+      for (size_type i = 1; i < nr; ++i)
+        for (std::set<size_type>::iterator it = nnzs[i].begin();
+             it != nnzs[i].end(); ++it)
+          if (reserve__rb(mat_col(B, *it), booked, R(EPS) * norms[*it]))
+            c_ortho[*it] = true;
+    }
+
+    size_type sizesm[7] = {125, 200, 350, 550, 800, 1100, 1500}, actsize;
+    for (int k = 0; k < 7; ++k) {
+      size_type nc_r = columns.size();
+      std::set<size_type> c1, cres;
+      actsize = sizesm[k];
+      for (std::set<size_type>::iterator it = columns.begin();
+           it != columns.end(); ++it) {
+        c1.insert(*it);
+        if (c1.size() >= actsize) {
+          range_basis_eff_Gram_Schmidt_dense(B, c1, c_ortho, EPS);
+          for (std::set<size_type>::iterator it2=c1.begin(); it2 != c1.end();
+               ++it2) cres.insert(*it2);
+          c1.clear();
+        }
+      }
+      if (c1.size() > 1)
+        range_basis_eff_Gram_Schmidt_dense(B, c1, c_ortho, EPS);
+      for (std::set<size_type>::iterator it = c1.begin(); it != c1.end(); ++it)
+        cres.insert(*it);
+      columns = cres;
+      if (nc_r <= actsize) return;
+      if (columns.size() == nc_r) break;
+      if (sizesm[k] >= 350 && columns.size() > (nc_r*19)/20) break;
+    }
+    if (columns.size() > std::max(size_type(10), actsize))
+      range_basis_eff_Lanczos(B, columns, EPS);
+    else
+      range_basis_eff_Gram_Schmidt_dense(B, columns, c_ortho, EPS);
+  }
+
+
+  template <typename Mat>
+  void range_basis(const Mat &B, std::set<size_type> &columns,
+                   double EPS, row_major) {
+    typedef typename  linalg_traits<Mat>::value_type T;
+    gmm::col_matrix< rsvector<T> > BB(mat_nrows(B), mat_ncols(B));
+    GMM_WARNING3("A copy of a row matrix is done into a column matrix "
+                 "for range basis algorithm.");
+    gmm::copy(B, BB);
+    range_basis(BB, columns, EPS);
+  }
+
+  /** Range Basis :
+    Extract a basis of the range of a (large sparse) matrix selecting some
+    column vectors of this matrix. This is in particular useful to select
+    an independent set of linear constraints.
+
+    The algorithm is optimized for two cases :
+       - when the (non trivial) kernel is small. An iterativ algorithm
+         based on Lanczos method is applied
+       - when the (non trivial) kernel is large and most of the dependencies
+         can be detected locally. A block Gram-Schmidt is applied first then
+         a restarted Lanczos method when the remaining kernel is greatly
+         smaller.
+    The restarted Lanczos method could be improved or replaced by a block
+    Lanczos method, a block Wiedelann method (in order to be parallelized for
+    instance) or simply could compute more than one vector of the null
+    space at each iteration.
+    The LU decomposition has been tested for local elimination but gives bad
+    results : the algorithm is unstable and do not permit to give the right
+    number of vector at the end of the process. Moreover, the number of final
+    vectors depends greatly on the number of vectors in a block of the local
+    analysis.
+  */
+  template <typename Mat>
+  void range_basis(const Mat &B, std::set<size_type> &columns,
+                   double EPS=1E-12) {
+    range_basis(B, columns, EPS,
+                typename principal_orientation_type
+                <typename linalg_traits<Mat>::sub_orientation>::potype());
+}
+
+}
+
+#endif
diff --git a/contrib/gmm/gmm_real_part.h b/contrib/gmm/gmm_real_part.h
index b023986558..0ea6d4dd38 100644
--- a/contrib/gmm/gmm_real_part.h
+++ b/contrib/gmm/gmm_real_part.h
@@ -1,32 +1,33 @@
-// -*- c++ -*- (enables emacs c++ mode)
-//===========================================================================
-//
-// Copyright (C) 2003-2008 Yves Renard
-//
-// This file is a part of GETFEM++
-//
-// Getfem++  is  free software;  you  can  redistribute  it  and/or modify it
-// under  the  terms  of the  GNU  Lesser General Public License as published
-// by  the  Free Software Foundation;  either version 2.1 of the License,  or
-// (at your option) any later version.
-// This program  is  distributed  in  the  hope  that it will be useful,  but
-// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-// or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
-// License for more details.
-// You  should  have received a copy of the GNU Lesser General Public License
-// along  with  this program;  if not, write to the Free Software Foundation,
-// Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
-//
-// As a special exception, you may use this file as part of a free software
-// library without restriction.  Specifically, if other files instantiate
-// templates or use macros or inline functions from this file, or you compile
-// this file and link it with other files to produce an executable, this
-// file does not by itself cause the resulting executable to be covered by
-// the GNU General Public License.  This exception does not however
-// invalidate any other reasons why the executable file might be covered by
-// the GNU General Public License.
-//
-//===========================================================================
+/* -*- c++ -*- (enables emacs c++ mode) */
+/*===========================================================================
+
+ Copyright (C) 2003-2020 Yves Renard
+
+ This file is a part of GetFEM
+
+ GetFEM  is  free software;  you  can  redistribute  it  and/or modify it
+ under  the  terms  of the  GNU  Lesser General Public License as published
+ by  the  Free Software Foundation;  either version 3 of the License,  or
+ (at your option) any later version along with the GCC Runtime Library
+ Exception either version 3.1 or (at your option) any later version.
+ This program  is  distributed  in  the  hope  that it will be useful,  but
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+ License and GCC Runtime Library Exception for more details.
+ You  should  have received a copy of the GNU Lesser General Public License
+ along  with  this program;  if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+
+ As a special exception, you  may use  this file  as it is a part of a free
+ software  library  without  restriction.  Specifically,  if   other  files
+ instantiate  templates  or  use macros or inline functions from this file,
+ or  you compile this  file  and  link  it  with other files  to produce an
+ executable, this file  does  not  by itself cause the resulting executable
+ to be covered  by the GNU Lesser General Public License.  This   exception
+ does not  however  invalidate  any  other  reasons why the executable file
+ might be covered by the GNU Lesser General Public License.
+
+===========================================================================*/
 
 /**@file gmm_real_part.h
    @author  Yves Renard <Yves.Renard@insa-lyon.fr>
@@ -38,6 +39,7 @@
 
 #include "gmm_def.h"
 #include "gmm_vector.h"
+#include <functional>
 
 namespace gmm {
 
@@ -136,8 +138,10 @@ namespace gmm {
     
     part_vector_iterator(void) {}
     explicit part_vector_iterator(const IT &i) : it(i) {}
-    part_vector_iterator(const part_vector_iterator<MIT, MIT, PART> &i) : it(i.it) {}
-    
+    part_vector_iterator(const part_vector_iterator<MIT, MIT, PART> &i)
+      : it(i.it) {}
+    part_vector_iterator &operator =
+    (const part_vector_iterator<MIT, MIT, PART> &i) { it = i.it; return *this; }
 
     size_type index(void) const { return it.index(); }
     part_vector_iterator operator ++(int)
@@ -236,7 +240,163 @@ namespace gmm {
     typedef typename linalg_traits<VECT>::V_reference ref_t;
     set_to_end(it.it, o, typename linalg_traits<VECT>::pV(), ref_t());
   }
+
+  template <typename PT, typename PART> std::ostream &operator <<
+    (std::ostream &o, const part_vector<PT, PART>& m)
+  { gmm::write(o,m); return o; }
+
+
+  /* ********************************************************************* */
+  /*	Reference to the real or imaginary part of (complex) matrices      */
+  /* ********************************************************************* */
+
+
+  template <typename PT, typename PART> struct  part_row_ref {
+    
+    typedef part_row_ref<PT, PART> this_type;
+    typedef typename std::iterator_traits<PT>::value_type M;
+    typedef M * CPT;
+    typedef typename std::iterator_traits<PT>::reference ref_M;
+    typedef typename select_ref<typename linalg_traits<this_type>
+            ::const_row_iterator, typename linalg_traits<this_type>
+            ::row_iterator, PT>::ref_type iterator;
+    typedef typename linalg_traits<this_type>::value_type value_type;
+    typedef typename linalg_traits<this_type>::reference reference;
+    typedef typename linalg_traits<this_type>::porigin_type porigin_type;
+
+    iterator begin_, end_;
+    porigin_type origin;
+    size_type nr, nc;
+
+    part_row_ref(ref_M m)
+      : begin_(mat_row_begin(m)), end_(mat_row_end(m)),
+	origin(linalg_origin(m)), nr(mat_nrows(m)), nc(mat_ncols(m)) {}
+
+    part_row_ref(const part_row_ref<CPT, PART> &cr) :
+      begin_(cr.begin_),end_(cr.end_), origin(cr.origin),nr(cr.nr),nc(cr.nc) {}
+
+    reference operator()(size_type i, size_type j) const {
+      return reference(ref_or_value_type<reference>::r(
+					 linalg_traits<M>::access(begin_+i, j),
+					 PART(), value_type()));
+    }
+  };
   
+  template<typename PT, typename PART> std::ostream &operator <<
+    (std::ostream &o, const part_row_ref<PT, PART>& m)
+  { gmm::write(o,m); return o; }
+
+  template <typename PT, typename PART> struct  part_col_ref {
+    
+    typedef part_col_ref<PT, PART> this_type;
+    typedef typename std::iterator_traits<PT>::value_type M;
+    typedef M * CPT;
+    typedef typename std::iterator_traits<PT>::reference ref_M;
+    typedef typename select_ref<typename linalg_traits<this_type>
+            ::const_col_iterator, typename linalg_traits<this_type>
+            ::col_iterator, PT>::ref_type iterator;
+    typedef typename linalg_traits<this_type>::value_type value_type;
+    typedef typename linalg_traits<this_type>::reference reference;
+    typedef typename linalg_traits<this_type>::porigin_type porigin_type;
+
+    iterator begin_, end_;
+    porigin_type origin;
+    size_type nr, nc;
+
+    part_col_ref(ref_M m)
+      : begin_(mat_col_begin(m)), end_(mat_col_end(m)),
+	origin(linalg_origin(m)), nr(mat_nrows(m)), nc(mat_ncols(m)) {}
+
+    part_col_ref(const part_col_ref<CPT, PART> &cr) :
+      begin_(cr.begin_),end_(cr.end_), origin(cr.origin),nr(cr.nr),nc(cr.nc) {}
+
+    reference operator()(size_type i, size_type j) const {
+      return reference(ref_or_value_type<reference>::r(
+					 linalg_traits<M>::access(begin_+j, i),
+					 PART(), value_type()));
+    }
+  };
+   
+
+  
+  template<typename PT, typename PART> std::ostream &operator <<
+    (std::ostream &o, const part_col_ref<PT, PART>& m)
+  { gmm::write(o,m); return o; }
+
+  
+
+
+
+
+template <typename TYPE, typename PART, typename PT>
+  struct part_return_ {
+    typedef abstract_null_type return_type;
+  };
+  template <typename PT, typename PART>
+  struct part_return_<row_major, PART, PT> {
+    typedef typename std::iterator_traits<PT>::value_type L;
+    typedef typename select_return<part_row_ref<const L *, PART>,
+		     part_row_ref< L *, PART>, PT>::return_type return_type;
+  };
+  template <typename PT, typename PART>
+  struct part_return_<col_major, PART, PT> {
+    typedef typename std::iterator_traits<PT>::value_type L;
+    typedef typename select_return<part_col_ref<const L *, PART>,
+		     part_col_ref<L *, PART>, PT>::return_type return_type;
+  };
+
+  template <typename PT, typename PART, typename LT> struct part_return__{
+    typedef abstract_null_type return_type;
+  };
+
+  template <typename PT, typename PART>
+  struct part_return__<PT, PART, abstract_matrix> {
+    typedef typename std::iterator_traits<PT>::value_type L;
+    typedef typename part_return_<typename principal_orientation_type<
+      typename linalg_traits<L>::sub_orientation>::potype, PART,
+      PT>::return_type return_type;
+  };
+
+  template <typename PT, typename PART>
+  struct part_return__<PT, PART, abstract_vector> {
+    typedef typename std::iterator_traits<PT>::value_type L;
+    typedef typename select_return<part_vector<const L *, PART>,
+      part_vector<L *, PART>, PT>::return_type return_type;
+  };
+
+  template <typename PT, typename PART> struct part_return {
+    typedef typename std::iterator_traits<PT>::value_type L;
+    typedef typename part_return__<PT, PART,
+      typename linalg_traits<L>::linalg_type>::return_type return_type;
+  };
+
+  template <typename L> inline 
+  typename part_return<const L *, linalg_real_part>::return_type
+  real_part(const L &l) {
+    return typename part_return<const L *, linalg_real_part>::return_type
+      (linalg_cast(const_cast<L &>(l)));
+  }
+
+  template <typename L> inline 
+  typename part_return<L *, linalg_real_part>::return_type
+  real_part(L &l) {
+    return typename part_return<L *, linalg_real_part>::return_type(linalg_cast(l));
+  }
+
+  template <typename L> inline 
+  typename part_return<const L *, linalg_imag_part>::return_type
+  imag_part(const L &l) {
+    return typename part_return<const L *, linalg_imag_part>::return_type
+      (linalg_cast(const_cast<L &>(l)));
+  }
+
+  template <typename L> inline 
+  typename part_return<L *, linalg_imag_part>::return_type
+  imag_part(L &l) {
+    return typename part_return<L *, linalg_imag_part>::return_type(linalg_cast(l));
+  }
+
+
   template <typename PT, typename PART>
   struct linalg_traits<part_vector<PT, PART> > {
     typedef part_vector<PT, PART> this_type;
@@ -322,47 +482,6 @@ namespace gmm {
     { return reference(linalg_traits<V>::access(o, it.it, ite.it,i)); }
   };
 
-  template <typename PT, typename PART> std::ostream &operator <<
-    (std::ostream &o, const part_vector<PT, PART>& m)
-  { gmm::write(o,m); return o; }
-
-
-  /* ********************************************************************* */
-  /*	Reference to the real or imaginary part of (complex) matrices      */
-  /* ********************************************************************* */
-
-
-  template <typename PT, typename PART> struct  part_row_ref {
-    
-    typedef part_row_ref<PT, PART> this_type;
-    typedef typename std::iterator_traits<PT>::value_type M;
-    typedef M * CPT;
-    typedef typename std::iterator_traits<PT>::reference ref_M;
-    typedef typename select_ref<typename linalg_traits<this_type>
-            ::const_row_iterator, typename linalg_traits<this_type>
-            ::row_iterator, PT>::ref_type iterator;
-    typedef typename linalg_traits<this_type>::value_type value_type;
-    typedef typename linalg_traits<this_type>::reference reference;
-    typedef typename linalg_traits<this_type>::porigin_type porigin_type;
-
-    iterator begin_, end_;
-    porigin_type origin;
-    size_type nr, nc;
-
-    part_row_ref(ref_M m)
-      : begin_(mat_row_begin(m)), end_(mat_row_end(m)),
-	origin(linalg_origin(m)), nr(mat_nrows(m)), nc(mat_ncols(m)) {}
-
-    part_row_ref(const part_row_ref<CPT, PART> &cr) :
-      begin_(cr.begin_),end_(cr.end_), origin(cr.origin),nr(cr.nr),nc(cr.nc) {}
-
-    reference operator()(size_type i, size_type j) const {
-      return reference(ref_or_value_type<reference>::r(
-					 linalg_traits<M>::access(begin_+j, i),
-					 PART(), value_type()));
-    }
-  };
-
   template <typename PT, typename PART>
   struct linalg_traits<part_row_ref<PT, PART> > {
     typedef part_row_ref<PT, PART> this_type;
@@ -379,9 +498,9 @@ namespace gmm {
     typedef abstract_null_type const_sub_col_type;
     typedef abstract_null_type col_iterator;
     typedef abstract_null_type const_col_iterator;
-    typedef typename linalg_traits<M>::const_sub_row_type
+    typedef typename org_type<typename linalg_traits<M>::const_sub_row_type>::t
             pre_const_sub_row_type;
-    typedef typename linalg_traits<M>::sub_row_type pre_sub_row_type;
+    typedef typename org_type<typename linalg_traits<M>::sub_row_type>::t pre_sub_row_type;
     typedef part_vector<const pre_const_sub_row_type *, PART>
             const_sub_row_type;
     typedef typename select_ref<abstract_null_type,
@@ -417,47 +536,6 @@ namespace gmm {
 					 PART(), value_type()));
     }
   };
-   
-  template <typename PT, typename PART> 
-  void linalg_traits<part_row_ref<PT, PART> >::do_clear(this_type &v) { 
-    row_iterator it = mat_row_begin(v), ite = mat_row_end(v);
-    for (; it != ite; ++it) clear(row(it));
-  }
-  
-  template<typename PT, typename PART> std::ostream &operator <<
-    (std::ostream &o, const part_row_ref<PT, PART>& m)
-  { gmm::write(o,m); return o; }
-
-  template <typename PT, typename PART> struct  part_col_ref {
-    
-    typedef part_col_ref<PT, PART> this_type;
-    typedef typename std::iterator_traits<PT>::value_type M;
-    typedef M * CPT;
-    typedef typename std::iterator_traits<PT>::reference ref_M;
-    typedef typename select_ref<typename linalg_traits<this_type>
-            ::const_col_iterator, typename linalg_traits<this_type>
-            ::col_iterator, PT>::ref_type iterator;
-    typedef typename linalg_traits<this_type>::value_type value_type;
-    typedef typename linalg_traits<this_type>::reference reference;
-    typedef typename linalg_traits<this_type>::porigin_type porigin_type;
-
-    iterator begin_, end_;
-    porigin_type origin;
-    size_type nr, nc;
-
-    part_col_ref(ref_M m)
-      : begin_(mat_col_begin(m)), end_(mat_col_end(m)),
-	origin(linalg_origin(m)), nr(mat_nrows(m)), nc(mat_ncols(m)) {}
-
-    part_col_ref(const part_col_ref<CPT, PART> &cr) :
-      begin_(cr.begin_),end_(cr.end_), origin(cr.origin),nr(cr.nr),nc(cr.nc) {}
-
-    reference operator()(size_type i, size_type j) const {
-      return reference(ref_or_value_type<reference>::r(
-					 linalg_traits<M>::access(begin_+j, i),
-					 PART(), value_type()));
-    }
-  };
 
   template <typename PT, typename PART>
   struct linalg_traits<part_col_ref<PT, PART> > {
@@ -475,9 +553,9 @@ namespace gmm {
     typedef abstract_null_type const_sub_row_type;
     typedef abstract_null_type row_iterator;
     typedef abstract_null_type const_row_iterator;
-    typedef typename linalg_traits<M>::const_sub_col_type
+    typedef typename org_type<typename linalg_traits<M>::const_sub_col_type>::t
             pre_const_sub_col_type;
-    typedef typename linalg_traits<M>::sub_col_type pre_sub_col_type;
+    typedef typename org_type<typename linalg_traits<M>::sub_col_type>::t pre_sub_col_type;
     typedef part_vector<const pre_const_sub_col_type *, PART>
             const_sub_col_type;
     typedef typename select_ref<abstract_null_type,
@@ -513,92 +591,18 @@ namespace gmm {
 					 PART(), value_type()));
     }
   };
-   
+
   template <typename PT, typename PART> 
   void linalg_traits<part_col_ref<PT, PART> >::do_clear(this_type &v) { 
     col_iterator it = mat_col_begin(v), ite = mat_col_end(v);
     for (; it != ite; ++it) clear(col(it));
   }
   
-  template<typename PT, typename PART> std::ostream &operator <<
-    (std::ostream &o, const part_col_ref<PT, PART>& m)
-  { gmm::write(o,m); return o; }
-
-  
-
-
-
-
-template <typename TYPE, typename PART, typename PT>
-  struct part_return_ {
-    typedef abstract_null_type return_type;
-  };
-  template <typename PT, typename PART>
-  struct part_return_<row_major, PART, PT> {
-    typedef typename std::iterator_traits<PT>::value_type L;
-    typedef typename select_return<part_row_ref<const L *, PART>,
-		     part_row_ref< L *, PART>, PT>::return_type return_type;
-  };
-  template <typename PT, typename PART>
-  struct part_return_<col_major, PART, PT> {
-    typedef typename std::iterator_traits<PT>::value_type L;
-    typedef typename select_return<part_col_ref<const L *, PART>,
-		     part_col_ref<L *, PART>, PT>::return_type return_type;
-  };
-
-  template <typename PT, typename PART, typename LT> struct part_return__{
-    typedef abstract_null_type return_type;
-  };
-
-  template <typename PT, typename PART>
-  struct part_return__<PT, PART, abstract_matrix> {
-    typedef typename std::iterator_traits<PT>::value_type L;
-    typedef typename part_return_<typename principal_orientation_type<
-      typename linalg_traits<L>::sub_orientation>::potype, PART,
-      PT>::return_type return_type;
-  };
-
-  template <typename PT, typename PART>
-  struct part_return__<PT, PART, abstract_vector> {
-    typedef typename std::iterator_traits<PT>::value_type L;
-    typedef typename select_return<part_vector<const L *, PART>,
-      part_vector<L *, PART>, PT>::return_type return_type;
-  };
-
-  template <typename PT, typename PART> struct part_return {
-    typedef typename std::iterator_traits<PT>::value_type L;
-    typedef typename part_return__<PT, PART,
-      typename linalg_traits<L>::linalg_type>::return_type return_type;
-  };
-
-  template <typename L> inline 
-  typename part_return<const L *, linalg_real_part>::return_type
-  real_part(const L &l) {
-    return typename part_return<const L *, linalg_real_part>::return_type
-      (linalg_cast(const_cast<L &>(l)));
-  }
-
-  template <typename L> inline 
-  typename part_return<L *, linalg_real_part>::return_type
-  real_part(L &l) {
-    return typename part_return<L *, linalg_real_part>::return_type(linalg_cast(l));
-  }
-
-  template <typename L> inline 
-  typename part_return<const L *, linalg_imag_part>::return_type
-  imag_part(const L &l) {
-    return typename part_return<const L *, linalg_imag_part>::return_type
-      (linalg_cast(const_cast<L &>(l)));
-  }
-
-  template <typename L> inline 
-  typename part_return<L *, linalg_imag_part>::return_type
-  imag_part(L &l) {
-    return typename part_return<L *, linalg_imag_part>::return_type(linalg_cast(l));
+  template <typename PT, typename PART> 
+  void linalg_traits<part_row_ref<PT, PART> >::do_clear(this_type &v) { 
+    row_iterator it = mat_row_begin(v), ite = mat_row_end(v);
+    for (; it != ite; ++it) clear(row(it));
   }
-
-
-
 }
 
 #endif //  GMM_REAL_PART_H
diff --git a/contrib/gmm/gmm_ref.h b/contrib/gmm/gmm_ref.h
index 0f6c7454f6..b41fbdd509 100644
--- a/contrib/gmm/gmm_ref.h
+++ b/contrib/gmm/gmm_ref.h
@@ -1,32 +1,33 @@
-// -*- c++ -*- (enables emacs c++ mode)
-//===========================================================================
-//
-// Copyright (C) 2000-2008 Yves Renard
-//
-// This file is a part of GETFEM++
-//
-// Getfem++  is  free software;  you  can  redistribute  it  and/or modify it
-// under  the  terms  of the  GNU  Lesser General Public License as published
-// by  the  Free Software Foundation;  either version 2.1 of the License,  or
-// (at your option) any later version.
-// This program  is  distributed  in  the  hope  that it will be useful,  but
-// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-// or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
-// License for more details.
-// You  should  have received a copy of the GNU Lesser General Public License
-// along  with  this program;  if not, write to the Free Software Foundation,
-// Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
-//
-// As a special exception, you may use this file as part of a free software
-// library without restriction.  Specifically, if other files instantiate
-// templates or use macros or inline functions from this file, or you compile
-// this file and link it with other files to produce an executable, this
-// file does not by itself cause the resulting executable to be covered by
-// the GNU General Public License.  This exception does not however
-// invalidate any other reasons why the executable file might be covered by
-// the GNU General Public License.
-//
-//===========================================================================
+/* -*- c++ -*- (enables emacs c++ mode) */
+/*===========================================================================
+
+ Copyright (C) 2000-2020 Yves Renard
+
+ This file is a part of GetFEM
+
+ GetFEM  is  free software;  you  can  redistribute  it  and/or modify it
+ under  the  terms  of the  GNU  Lesser General Public License as published
+ by  the  Free Software Foundation;  either version 3 of the License,  or
+ (at your option) any later version along with the GCC Runtime Library
+ Exception either version 3.1 or (at your option) any later version.
+ This program  is  distributed  in  the  hope  that it will be useful,  but
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+ License and GCC Runtime Library Exception for more details.
+ You  should  have received a copy of the GNU Lesser General Public License
+ along  with  this program;  if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+
+ As a special exception, you  may use  this file  as it is a part of a free
+ software  library  without  restriction.  Specifically,  if   other  files
+ instantiate  templates  or  use macros or inline functions from this file,
+ or  you compile this  file  and  link  it  with other files  to produce an
+ executable, this file  does  not  by itself cause the resulting executable
+ to be covered  by the GNU Lesser General Public License.  This   exception
+ does not  however  invalidate  any  other  reasons why the executable file
+ might be covered by the GNU Lesser General Public License.
+
+===========================================================================*/
 
 
 #ifndef GMM_REF_H__
@@ -255,7 +256,7 @@ namespace gmm {
 	
       reference operator *() const
       { return *(piter + *iter_index); }
-      reference operator [](int ii) const
+      reference operator [](size_type ii) const
       { return *(piter + *(iter_index+ii)); }
       
       bool operator ==(const iterator &i) const
@@ -376,7 +377,7 @@ namespace gmm {
     { return (N ? (it - ii.it) / N : 0) + i - ii.i; }
 
     reference operator *() const { return *(it + i*N); }
-    reference operator [](int ii) const { return *(it + (i+ii)*N); }
+    reference operator [](size_type ii) const { return *(it + (i+ii)*N); }
 
     bool operator ==(const iterator &ii) const
     { return (*this - ii) == difference_type(0); }
diff --git a/contrib/gmm/gmm_scaled.h b/contrib/gmm/gmm_scaled.h
index 281ef59d8f..0d7d563cf2 100644
--- a/contrib/gmm/gmm_scaled.h
+++ b/contrib/gmm/gmm_scaled.h
@@ -1,32 +1,33 @@
-// -*- c++ -*- (enables emacs c++ mode)
-//===========================================================================
-//
-// Copyright (C) 2002-2008 Yves Renard
-//
-// This file is a part of GETFEM++
-//
-// Getfem++  is  free software;  you  can  redistribute  it  and/or modify it
-// under  the  terms  of the  GNU  Lesser General Public License as published
-// by  the  Free Software Foundation;  either version 2.1 of the License,  or
-// (at your option) any later version.
-// This program  is  distributed  in  the  hope  that it will be useful,  but
-// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-// or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
-// License for more details.
-// You  should  have received a copy of the GNU Lesser General Public License
-// along  with  this program;  if not, write to the Free Software Foundation,
-// Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
-//
-// As a special exception, you may use this file as part of a free software
-// library without restriction.  Specifically, if other files instantiate
-// templates or use macros or inline functions from this file, or you compile
-// this file and link it with other files to produce an executable, this
-// file does not by itself cause the resulting executable to be covered by
-// the GNU General Public License.  This exception does not however
-// invalidate any other reasons why the executable file might be covered by
-// the GNU General Public License.
-//
-//===========================================================================
+/* -*- c++ -*- (enables emacs c++ mode) */
+/*===========================================================================
+
+ Copyright (C) 2002-2020 Yves Renard
+
+ This file is a part of GetFEM
+
+ GetFEM  is  free software;  you  can  redistribute  it  and/or modify it
+ under  the  terms  of the  GNU  Lesser General Public License as published
+ by  the  Free Software Foundation;  either version 3 of the License,  or
+ (at your option) any later version along with the GCC Runtime Library
+ Exception either version 3.1 or (at your option) any later version.
+ This program  is  distributed  in  the  hope  that it will be useful,  but
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+ License and GCC Runtime Library Exception for more details.
+ You  should  have received a copy of the GNU Lesser General Public License
+ along  with  this program;  if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+
+ As a special exception, you  may use  this file  as it is a part of a free
+ software  library  without  restriction.  Specifically,  if   other  files
+ instantiate  templates  or  use macros or inline functions from this file,
+ or  you compile this  file  and  link  it  with other files  to produce an
+ executable, this file  does  not  by itself cause the resulting executable
+ to be covered  by the GNU Lesser General Public License.  This   exception
+ does not  however  invalidate  any  other  reasons why the executable file
+ might be covered by the GNU Lesser General Public License.
+
+===========================================================================*/
 
 /**@file gmm_scaled.h
    @author  Yves Renard <Yves.Renard@insa-lyon.fr>
@@ -78,7 +79,7 @@ namespace gmm {
     inline difference_type operator -(const scaled_const_iterator &i) const
       { return difference_type(it - i.it); }
     
-    inline value_type operator  *() const { return (*it) * r; }
+    inline value_type operator  *() const { return (*it) * value_type(r); }
     inline value_type operator [](size_type ii) const { return it[ii] * r; }
     
     inline bool operator ==(const scaled_const_iterator &i) const
@@ -106,32 +107,9 @@ namespace gmm {
 	origin(linalg_origin(v)), size_(vect_size(v)), r(rr) {}
 
     reference operator[](size_type i) const
-    { return r * linalg_traits<V>::access(origin, begin_, end_, i); }
+    { return value_type(r) * linalg_traits<V>::access(origin, begin_, end_, i); }
   };
 
-  template <typename V, typename S> struct linalg_traits<scaled_vector_const_ref<V,S> > {
-    typedef scaled_vector_const_ref<V,S> this_type;
-    typedef linalg_const is_reference;
-    typedef abstract_vector linalg_type;
-    typedef typename strongest_numeric_type<S, typename linalg_traits<V>::value_type>::T value_type;
-    typedef typename linalg_traits<V>::origin_type origin_type;
-    typedef value_type reference;
-    typedef abstract_null_type iterator;
-    typedef scaled_const_iterator<typename linalg_traits<V>::const_iterator, S>
-      const_iterator;
-    typedef typename linalg_traits<V>::storage_type storage_type;
-    typedef typename linalg_traits<V>::index_sorted index_sorted;
-    static size_type size(const this_type &v) { return v.size_; }
-    static const_iterator begin(const this_type &v)
-    { return const_iterator(v.begin_, v.r); }
-    static const_iterator end(const this_type &v)
-    { return const_iterator(v.end_, v.r); }
-    static const origin_type* origin(const this_type &v) { return v.origin; }
-    static value_type access(const origin_type *o, const const_iterator &it,
-			     const const_iterator &ite, size_type i)
-    { return it.r * (linalg_traits<V>::access(o, it.it, ite.it, i)); }
-
-  };
 
    template<typename V, typename S> std::ostream &operator <<
      (std::ostream &o, const scaled_vector_const_ref<V,S>& m)
@@ -196,39 +174,6 @@ namespace gmm {
     { return r * linalg_traits<M>::access(begin_+i, j); }
   };
 
-  template <typename M, typename S> struct linalg_traits<scaled_row_matrix_const_ref<M,S> > {
-    typedef scaled_row_matrix_const_ref<M,S> this_type;
-    typedef linalg_const is_reference;
-    typedef abstract_matrix linalg_type;
-    typedef typename linalg_traits<M>::origin_type origin_type;
-    typedef typename strongest_numeric_type<S, typename linalg_traits<M>::value_type>::T value_type;
-    typedef value_type reference;
-    typedef typename linalg_traits<M>::storage_type storage_type;
-    typedef typename linalg_traits<M>::const_sub_row_type vector_type;
-    typedef scaled_vector_const_ref<vector_type,S> sub_row_type;
-    typedef scaled_vector_const_ref<vector_type,S> const_sub_row_type;
-    typedef scaled_row_const_iterator<M,S> row_iterator;
-    typedef scaled_row_const_iterator<M,S> const_row_iterator;
-    typedef abstract_null_type const_sub_col_type;
-    typedef abstract_null_type sub_col_type;
-    typedef abstract_null_type const_col_iterator;
-    typedef abstract_null_type col_iterator;
-    typedef row_major sub_orientation;
-    typedef typename linalg_traits<M>::index_sorted index_sorted;
-    static size_type nrows(const this_type &m)
-    { return m.nr; }
-    static size_type ncols(const this_type &m)
-    { return m.nc; }
-    static const_sub_row_type row(const const_row_iterator &it)
-    { return scaled(linalg_traits<M>::row(it.it), it.r); }
-    static const_row_iterator row_begin(const this_type &m)
-    { return const_row_iterator(m.begin_, m.r); }
-    static const_row_iterator row_end(const this_type &m)
-    { return const_row_iterator(m.end_, m.r); }
-    static const origin_type* origin(const this_type &m) { return m.origin; }
-    static value_type access(const const_row_iterator &it, size_type i)
-    { return it.r * (linalg_traits<M>::access(it.it, i)); }
-  };
 
   template<typename M, typename S> std::ostream &operator <<
     (std::ostream &o, const scaled_row_matrix_const_ref<M,S>& m)
@@ -290,39 +235,7 @@ namespace gmm {
     { return r * linalg_traits<M>::access(begin_+j, i); }
   };
 
-  template <typename M, typename S> struct linalg_traits<scaled_col_matrix_const_ref<M,S> > {
-    typedef scaled_col_matrix_const_ref<M,S> this_type;
-    typedef linalg_const is_reference;
-    typedef abstract_matrix linalg_type;
-    typedef typename strongest_numeric_type<S, typename linalg_traits<M>::value_type>::T value_type;
-    typedef typename linalg_traits<M>::origin_type origin_type;
-    typedef value_type reference;
-    typedef typename linalg_traits<M>::storage_type storage_type;
-    typedef typename linalg_traits<M>::const_sub_col_type vector_type;
-    typedef abstract_null_type sub_col_type;
-    typedef scaled_vector_const_ref<vector_type,S> const_sub_col_type;
-    typedef abstract_null_type  col_iterator;
-    typedef scaled_col_const_iterator<M,S> const_col_iterator;
-    typedef abstract_null_type const_sub_row_type;
-    typedef abstract_null_type sub_row_type;
-    typedef abstract_null_type const_row_iterator;
-    typedef abstract_null_type row_iterator;
-    typedef col_major sub_orientation;
-    typedef typename linalg_traits<M>::index_sorted index_sorted;
-    static size_type ncols(const this_type &m)
-    { return m.nc; }
-    static size_type nrows(const this_type &m)
-    { return m.nr; }
-    static const_sub_col_type col(const const_col_iterator &it)
-    { return scaled(linalg_traits<M>::col(it.it), it.r); }
-    static const_col_iterator col_begin(const this_type &m)
-    { return const_col_iterator(m.begin_, m.r); }
-    static const_col_iterator col_end(const this_type &m)
-    { return const_col_iterator(m.end_, m.r); }
-    static const origin_type* origin(const this_type &m) { return m.origin; }
-    static value_type access(const const_col_iterator &it, size_type i)
-    { return it.r * (linalg_traits<M>::access(it.it, i)); }
-  };
+
 
   template<typename M, typename S> std::ostream &operator <<
     (std::ostream &o, const scaled_col_matrix_const_ref<M,S>& m)
@@ -383,7 +296,7 @@ namespace gmm {
     return scaled_col_matrix_const_ref<M,S>(m, x);
   }
 
-  
+
   /* ******************************************************************** */
   /*	matrix or vector scale                                	          */
   /* ******************************************************************** */
@@ -422,6 +335,100 @@ namespace gmm {
     for ( ; it != ite; ++it) scale(linalg_traits<L>::col(it), a);
   }
 
+  template <typename V, typename S> struct linalg_traits<scaled_vector_const_ref<V,S> > {
+    typedef scaled_vector_const_ref<V,S> this_type;
+    typedef linalg_const is_reference;
+    typedef abstract_vector linalg_type;
+    typedef typename strongest_numeric_type<S, typename linalg_traits<V>::value_type>::T value_type;
+    typedef typename linalg_traits<V>::origin_type origin_type;
+    typedef value_type reference;
+    typedef abstract_null_type iterator;
+    typedef scaled_const_iterator<typename linalg_traits<V>::const_iterator, S>
+      const_iterator;
+    typedef typename linalg_traits<V>::storage_type storage_type;
+    typedef typename linalg_traits<V>::index_sorted index_sorted;
+    static size_type size(const this_type &v) { return v.size_; }
+    static const_iterator begin(const this_type &v)
+    { return const_iterator(v.begin_, v.r); }
+    static const_iterator end(const this_type &v)
+    { return const_iterator(v.end_, v.r); }
+    static const origin_type* origin(const this_type &v) { return v.origin; }
+    static value_type access(const origin_type *o, const const_iterator &it,
+			     const const_iterator &ite, size_type i)
+    { return it.r * (linalg_traits<V>::access(o, it.it, ite.it, i)); }
+
+  };
+
+
+  template <typename M, typename S> struct linalg_traits<scaled_row_matrix_const_ref<M,S> > {
+    typedef scaled_row_matrix_const_ref<M,S> this_type;
+    typedef linalg_const is_reference;
+    typedef abstract_matrix linalg_type;
+    typedef typename linalg_traits<M>::origin_type origin_type;
+    typedef typename strongest_numeric_type<S, typename linalg_traits<M>::value_type>::T value_type;
+    typedef value_type reference;
+    typedef typename linalg_traits<M>::storage_type storage_type;
+    typedef typename org_type<typename linalg_traits<M>::const_sub_row_type>::t vector_type;
+    typedef scaled_vector_const_ref<vector_type,S> sub_row_type;
+    typedef scaled_vector_const_ref<vector_type,S> const_sub_row_type;
+    typedef scaled_row_const_iterator<M,S> row_iterator;
+    typedef scaled_row_const_iterator<M,S> const_row_iterator;
+    typedef abstract_null_type const_sub_col_type;
+    typedef abstract_null_type sub_col_type;
+    typedef abstract_null_type const_col_iterator;
+    typedef abstract_null_type col_iterator;
+    typedef row_major sub_orientation;
+    typedef typename linalg_traits<M>::index_sorted index_sorted;
+    static size_type nrows(const this_type &m)
+    { return m.nr; }
+    static size_type ncols(const this_type &m)
+    { return m.nc; }
+    static const_sub_row_type row(const const_row_iterator &it)
+    { return scaled(linalg_traits<M>::row(it.it), it.r); }
+    static const_row_iterator row_begin(const this_type &m)
+    { return const_row_iterator(m.begin_, m.r); }
+    static const_row_iterator row_end(const this_type &m)
+    { return const_row_iterator(m.end_, m.r); }
+    static const origin_type* origin(const this_type &m) { return m.origin; }
+    static value_type access(const const_row_iterator &it, size_type i)
+    { return it.r * (linalg_traits<M>::access(it.it, i)); }
+  };
+
+  template <typename M, typename S> struct linalg_traits<scaled_col_matrix_const_ref<M,S> > {
+    typedef scaled_col_matrix_const_ref<M,S> this_type;
+    typedef linalg_const is_reference;
+    typedef abstract_matrix linalg_type;
+    typedef typename strongest_numeric_type<S, typename linalg_traits<M>::value_type>::T value_type;
+    typedef typename linalg_traits<M>::origin_type origin_type;
+    typedef value_type reference;
+    typedef typename linalg_traits<M>::storage_type storage_type;
+    typedef typename org_type<typename linalg_traits<M>::const_sub_col_type>::t vector_type;
+    typedef abstract_null_type sub_col_type;
+    typedef scaled_vector_const_ref<vector_type,S> const_sub_col_type;
+    typedef abstract_null_type  col_iterator;
+    typedef scaled_col_const_iterator<M,S> const_col_iterator;
+    typedef abstract_null_type const_sub_row_type;
+    typedef abstract_null_type sub_row_type;
+    typedef abstract_null_type const_row_iterator;
+    typedef abstract_null_type row_iterator;
+    typedef col_major sub_orientation;
+    typedef typename linalg_traits<M>::index_sorted index_sorted;
+    static size_type ncols(const this_type &m)
+    { return m.nc; }
+    static size_type nrows(const this_type &m)
+    { return m.nr; }
+    static const_sub_col_type col(const const_col_iterator &it)
+    { return scaled(linalg_traits<M>::col(it.it), it.r); }
+    static const_col_iterator col_begin(const this_type &m)
+    { return const_col_iterator(m.begin_, m.r); }
+    static const_col_iterator col_end(const this_type &m)
+    { return const_col_iterator(m.end_, m.r); }
+    static const origin_type* origin(const this_type &m) { return m.origin; }
+    static value_type access(const const_col_iterator &it, size_type i)
+    { return it.r * (linalg_traits<M>::access(it.it, i)); }
+  };
+
+
 }
 
 #endif //  GMM_SCALED_H__
diff --git a/contrib/gmm/gmm_solver_Newton.h b/contrib/gmm/gmm_solver_Newton.h
deleted file mode 100644
index 34c95ddaf7..0000000000
--- a/contrib/gmm/gmm_solver_Newton.h
+++ /dev/null
@@ -1,137 +0,0 @@
-// -*- c++ -*- (enables emacs c++ mode)
-//===========================================================================
-//
-// Copyright (C) 2006-2008 Yves Renard
-//
-// This file is a part of GETFEM++
-//
-// Getfem++  is  free software;  you  can  redistribute  it  and/or modify it
-// under  the  terms  of the  GNU  Lesser General Public License as published
-// by  the  Free Software Foundation;  either version 2.1 of the License,  or
-// (at your option) any later version.
-// This program  is  distributed  in  the  hope  that it will be useful,  but
-// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-// or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
-// License for more details.
-// You  should  have received a copy of the GNU Lesser General Public License
-// along  with  this program;  if not, write to the Free Software Foundation,
-// Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
-//
-// As a special exception, you may use this file as part of a free software
-// library without restriction.  Specifically, if other files instantiate
-// templates or use macros or inline functions from this file, or you compile
-// this file and link it with other files to produce an executable, this
-// file does not by itself cause the resulting executable to be covered by
-// the GNU General Public License.  This exception does not however
-// invalidate any other reasons why the executable file might be covered by
-// the GNU General Public License.
-//
-//===========================================================================
-
-/**@file gmm_solver_Newton.h
-   @author  Yves Renard <Yves.Renard@insa-lyon.fr>
-   @author  Michel Fournie <fournie@mip.ups-tlse.fr>
-   @date January 24, 2006.
-*/
-#ifndef GMM_SOLVERS_NEWTON_H__
-#define GMM_SOLVERS_NEWTON_H__ 
-
-namespace gmm {
-
-#include "gmm_kernel.h"
-
-  /* ***************************************************************** */
-  /*     Line search definition                                        */
-  /* ***************************************************************** */
-
-  struct abstract_newton_line_search {
-    double conv_alpha, conv_r;
-    size_t it, itmax, glob_it;
-    virtual void init_search(double r, size_t git) = 0;
-    virtual double next_try(void) = 0;
-    virtual bool is_converged(double) = 0;
-    virtual double converged_value(void) { return conv_alpha; };
-    virtual double converged_residual(void) { return conv_r; };
-    virtual ~abstract_newton_line_search() {}
-  };
-
-
-  struct simplest_newton_line_search : public abstract_newton_line_search {
-    double alpha, alpha_mult, first_res, alpha_max_ratio, alpha_min;
-    virtual void init_search(double r, size_t git) {
-      glob_it = git;
-      conv_alpha = alpha = double(1); conv_r = first_res = r; it = 0;
-    }
-    virtual double next_try(void)
-    { conv_alpha = alpha; alpha *= alpha_mult; ++it; return conv_alpha; }
-    virtual bool is_converged(double r) {
-      conv_r = r;
-      return ((it <= 1 && r < first_res)
-	      || (r <= first_res * alpha_max_ratio)
-	      || (conv_alpha <= alpha_min)
-	      || it >= itmax);
-    }
-    simplest_newton_line_search
-    (size_t imax = size_t(-1), double a_max_ratio = 6.0/5.0,
-     double a_min = 1.0/1000.0, double a_mult = 3.0/5.0)
-      : alpha_mult(a_mult), alpha_max_ratio(a_max_ratio), alpha_min(a_min)
-      { itmax = imax; }
-  };
-
-  struct default_newton_line_search : public abstract_newton_line_search {
-    double alpha, alpha_mult, first_res, alpha_max_ratio;
-    double alpha_min, prev_res, alpha_max_augment;
-    virtual void init_search(double r, size_t git) {
-      glob_it = git;
-      conv_alpha = alpha = double(1);
-      prev_res = conv_r = first_res = r; it = 0;
-    }
-    virtual double next_try(void)
-    { conv_alpha = alpha; alpha *= alpha_mult; ++it; return conv_alpha; }
-    virtual bool is_converged(double r) {
-      if (glob_it == 0 || (r < first_res / double(2))
-	  || (conv_alpha <= alpha_min && r < first_res * alpha_max_augment)
-	  || it >= itmax)
-	{ conv_r = r; return true; }
-      if (it > 1 && r > prev_res && prev_res < alpha_max_ratio * first_res)
-	return true;
-      prev_res = conv_r = r;
-      return false;
-    }
-    default_newton_line_search
-    (size_t imax = size_t(-1),
-     double a_max_ratio = 5.0/3.0,
-     double a_min = 1.0/1000.0, double a_mult = 3.0/5.0, double a_augm = 2.0)
-      : alpha_mult(a_mult), alpha_max_ratio(a_max_ratio),
-	alpha_min(a_min), alpha_max_augment(a_augm) { itmax = imax; }
-  };
-
-
-  struct systematic_newton_line_search : public abstract_newton_line_search {
-    double alpha, alpha_mult, first_res;
-    double alpha_min, prev_res;
-    bool first;
-    virtual void init_search(double r, size_t git) {
-      glob_it = git;
-      conv_alpha = alpha = double(1);
-      prev_res = conv_r = first_res = r; it = 0; first = true;
-    }
-    virtual double next_try(void)
-    { double a = alpha; alpha *= alpha_mult; ++it; return a; }
-    virtual bool is_converged(double r) {
-      // cout << "a = " << alpha / alpha_mult << " r = " << r << endl;
-      if (r < conv_r || first)
-	{ conv_r = r; conv_alpha = alpha / alpha_mult; first = false; }
-      if ((alpha <= alpha_min*alpha_mult) || it >= itmax) return true;
-      return false;
-    }
-    systematic_newton_line_search
-    (size_t imax = size_t(-1),
-     double a_min = 1.0/10000.0, double a_mult = 3.0/5.0)
-      : alpha_mult(a_mult), alpha_min(a_min)  { itmax = imax; }
-  };
-
-}
-
-
-#endif
diff --git a/contrib/gmm/gmm_solver_Schwarz_additive.h b/contrib/gmm/gmm_solver_Schwarz_additive.h
index 7f4c958134..5585e027c2 100644
--- a/contrib/gmm/gmm_solver_Schwarz_additive.h
+++ b/contrib/gmm/gmm_solver_Schwarz_additive.h
@@ -1,32 +1,33 @@
-// -*- c++ -*- (enables emacs c++ mode)
-//===========================================================================
-//
-// Copyright (C) 2002-2008 Yves Renard
-//
-// This file is a part of GETFEM++
-//
-// Getfem++  is  free software;  you  can  redistribute  it  and/or modify it
-// under  the  terms  of the  GNU  Lesser General Public License as published
-// by  the  Free Software Foundation;  either version 2.1 of the License,  or
-// (at your option) any later version.
-// This program  is  distributed  in  the  hope  that it will be useful,  but
-// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-// or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
-// License for more details.
-// You  should  have received a copy of the GNU Lesser General Public License
-// along  with  this program;  if not, write to the Free Software Foundation,
-// Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
-//
-// As a special exception, you may use this file as part of a free software
-// library without restriction.  Specifically, if other files instantiate
-// templates or use macros or inline functions from this file, or you compile
-// this file and link it with other files to produce an executable, this
-// file does not by itself cause the resulting executable to be covered by
-// the GNU General Public License.  This exception does not however
-// invalidate any other reasons why the executable file might be covered by
-// the GNU General Public License.
-//
-//===========================================================================
+/* -*- c++ -*- (enables emacs c++ mode) */
+/*===========================================================================
+
+ Copyright (C) 2002-2020 Yves Renard
+
+ This file is a part of GetFEM
+
+ GetFEM  is  free software;  you  can  redistribute  it  and/or modify it
+ under  the  terms  of the  GNU  Lesser General Public License as published
+ by  the  Free Software Foundation;  either version 3 of the License,  or
+ (at your option) any later version along with the GCC Runtime Library
+ Exception either version 3.1 or (at your option) any later version.
+ This program  is  distributed  in  the  hope  that it will be useful,  but
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+ License and GCC Runtime Library Exception for more details.
+ You  should  have received a copy of the GNU Lesser General Public License
+ along  with  this program;  if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+
+ As a special exception, you  may use  this file  as it is a part of a free
+ software  library  without  restriction.  Specifically,  if   other  files
+ instantiate  templates  or  use macros or inline functions from this file,
+ or  you compile this  file  and  link  it  with other files  to produce an
+ executable, this file  does  not  by itself cause the resulting executable
+ to be covered  by the GNU Lesser General Public License.  This   exception
+ does not  however  invalidate  any  other  reasons why the executable file
+ might be covered by the GNU Lesser General Public License.
+
+===========================================================================*/
 
 /**@file gmm_solver_Schwarz_additive.h
    @author  Yves Renard <Yves.Renard@insa-lyon.fr>
@@ -43,7 +44,6 @@
 #include "gmm_solver_gmres.h"
 #include "gmm_solver_bicgstab.h"
 #include "gmm_solver_qmr.h"
-#include "gmm_solver_Newton.h"
 
 namespace gmm {
       
@@ -212,23 +212,22 @@ namespace gmm {
 #ifdef GMM_USES_MPI
      }
       if (nproc != size - 1) {
-	MPI_Sendrecv(Acsr.jc, sizeA+1, MPI_INT, next, tag2,
-		     Acsrtemp.jc, sizeA+1,MPI_INT,previous,tag2,
-		     MPI_COMM_WORLD,&status);
-	if (Acsrtemp.jc[sizeA] > size_type(sizepr)) {
-	  sizepr = Acsrtemp.jc[sizeA];
-	  delete[] Acsrtemp.pr; delete[] Acsrtemp.ir;
-	  Acsrtemp.pr = new value_type[sizepr];
-	  Acsrtemp.ir = new unsigned int[sizepr];
-	}
-	MPI_Sendrecv(Acsr.ir, Acsr.jc[sizeA], MPI_INT, next, tag1,
-		     Acsrtemp.ir, Acsrtemp.jc[sizeA],MPI_INT,previous,tag1,
-		     MPI_COMM_WORLD,&status);
-	
-	MPI_Sendrecv(Acsr.pr, Acsr.jc[sizeA], mpi_type(value_type()), next, tag3, 
-		     Acsrtemp.pr, Acsrtemp.jc[sizeA],mpi_type(value_type()),previous,tag3,
-		     MPI_COMM_WORLD,&status);
-	gmm::copy(Acsrtemp, Acsr);
+        MPI_Sendrecv(&(Acsr.jc[0]), sizeA+1, MPI_INT, next, tag2,
+                     &(Acsrtemp.jc[0]), sizeA+1, MPI_INT, previous, tag2,
+                     MPI_COMM_WORLD, &status);
+        if (Acsrtemp.jc[sizeA] > size_type(sizepr)) {
+          sizepr = Acsrtemp.jc[sizeA];
+          gmm::resize(Acsrtemp.pr, sizepr);
+          gmm::resize(Acsrtemp.ir, sizepr);
+        }
+        MPI_Sendrecv(&(Acsr.ir[0]), Acsr.jc[sizeA], MPI_INT, next, tag1,
+                     &(Acsrtemp.ir[0]), Acsrtemp.jc[sizeA], MPI_INT, previous, tag1,
+                     MPI_COMM_WORLD, &status);
+        
+        MPI_Sendrecv(&(Acsr.pr[0]), Acsr.jc[sizeA], mpi_type(value_type()), next, tag3, 
+                     &(Acsrtemp.pr[0]), Acsrtemp.jc[sizeA], mpi_type(value_type()), previous, tag3,
+                     MPI_COMM_WORLD, &status);
+        gmm::copy(Acsrtemp, Acsr);
       }
     }
       t_final=MPI_Wtime();
@@ -595,7 +594,69 @@ namespace gmm {
   void mult(const AS_exact_gradient<Matrixt, MatrixBi> &M,
 	    const Vector2 &p, const Vector3 &p2, const Vector4 &q)
   { mult(M, p, const_cast<Vector4 &>(q)); add(p2, q); }
-  
+
+  struct S_default_newton_line_search {
+    
+    double conv_alpha, conv_r;
+    size_t it, itmax, glob_it;
+
+    double alpha, alpha_old, alpha_mult, first_res, alpha_max_ratio;
+    double alpha_min_ratio, alpha_min;
+    size_type count, count_pat;
+    bool max_ratio_reached;
+    double alpha_max_ratio_reached, r_max_ratio_reached;
+    size_type it_max_ratio_reached;
+
+    
+    double converged_value(void) { return conv_alpha; };
+    double converged_residual(void) { return conv_r; };
+
+    virtual void init_search(double r, size_t git, double = 0.0) {
+      alpha_min_ratio = 0.9;
+      alpha_min = 1e-10;
+      alpha_max_ratio = 10.0;
+      alpha_mult = 0.25;
+      itmax = size_type(-1);
+      glob_it = git; if (git <= 1) count_pat = 0;
+      conv_alpha = alpha = alpha_old = 1.;
+      conv_r = first_res = r; it = 0;
+      count = 0;
+      max_ratio_reached = false;
+    }
+    virtual double next_try(void) {
+      alpha_old = alpha;
+      if (alpha >= 0.4) alpha *= 0.5; else alpha *= alpha_mult; ++it;
+      return alpha_old;
+    }
+    virtual bool is_converged(double r, double = 0.0) {
+      // cout << "r = " << r << " alpha = " << alpha / alpha_mult << " count_pat = " << count_pat << endl;
+      if (!max_ratio_reached && r < first_res * alpha_max_ratio) {
+	alpha_max_ratio_reached = alpha_old; r_max_ratio_reached = r;
+	it_max_ratio_reached = it; max_ratio_reached = true; 
+      }
+      if (max_ratio_reached && r < r_max_ratio_reached * 0.5
+	  && r > first_res * 1.1 && it <= it_max_ratio_reached+1) {
+	alpha_max_ratio_reached = alpha_old; r_max_ratio_reached = r;
+	it_max_ratio_reached = it;
+      }
+      if (count == 0 || r < conv_r)
+	{ conv_r = r; conv_alpha = alpha_old; count = 1; }
+      if (conv_r < first_res) ++count;
+
+      if (r < first_res *  alpha_min_ratio)
+	{ count_pat = 0; return true; }      
+      if (count >= 5 || (alpha < alpha_min && max_ratio_reached)) {
+	if (conv_r < first_res * 0.99) count_pat = 0;
+	if (/*gmm::random() * 50. < -log(conv_alpha)-4.0 ||*/ count_pat >= 3)
+	  { conv_r=r_max_ratio_reached; conv_alpha=alpha_max_ratio_reached; }
+	if (conv_r >= first_res * 0.9999) count_pat++;
+	return true;
+      }
+      return false;
+    }
+    S_default_newton_line_search(void) { count_pat = 0; }
+  };
+
 
   
   template <typename Matrixt, typename MatrixBi, typename Vector,
@@ -611,10 +672,8 @@ namespace gmm {
     
     double residual = iter.get_resmax();
 
-    default_newton_line_search internal_ls;
-    default_newton_line_search external_ls(size_t(-1), 5.0/3, 1.0/1000, 3.0/5);
-
-    // systematic_newton_line_search external_ls(size_t(-1), 1.0/10000.0, 3.0/100.0);
+    S_default_newton_line_search internal_ls;
+    S_default_newton_line_search external_ls;
 
     typename chgt_precond::APrecond PP = chgt_precond::transform(P);
     iter.set_rhsnorm(mtype(1));
diff --git a/contrib/gmm/gmm_solver_bfgs.h b/contrib/gmm/gmm_solver_bfgs.h
index 297b802143..d92abbca0f 100644
--- a/contrib/gmm/gmm_solver_bfgs.h
+++ b/contrib/gmm/gmm_solver_bfgs.h
@@ -1,32 +1,33 @@
-// -*- c++ -*- (enables emacs c++ mode)
-//===========================================================================
-//
-// Copyright (C) 2004-2008 Yves Renard
-//
-// This file is a part of GETFEM++
-//
-// Getfem++  is  free software;  you  can  redistribute  it  and/or modify it
-// under  the  terms  of the  GNU  Lesser General Public License as published
-// by  the  Free Software Foundation;  either version 2.1 of the License,  or
-// (at your option) any later version.
-// This program  is  distributed  in  the  hope  that it will be useful,  but
-// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-// or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
-// License for more details.
-// You  should  have received a copy of the GNU Lesser General Public License
-// along  with  this program;  if not, write to the Free Software Foundation,
-// Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
-//
-// As a special exception, you may use this file as part of a free software
-// library without restriction.  Specifically, if other files instantiate
-// templates or use macros or inline functions from this file, or you compile
-// this file and link it with other files to produce an executable, this
-// file does not by itself cause the resulting executable to be covered by
-// the GNU General Public License.  This exception does not however
-// invalidate any other reasons why the executable file might be covered by
-// the GNU General Public License.
-//
-//===========================================================================
+/* -*- c++ -*- (enables emacs c++ mode) */
+/*===========================================================================
+
+ Copyright (C) 2004-2020 Yves Renard
+
+ This file is a part of GetFEM
+
+ GetFEM  is  free software;  you  can  redistribute  it  and/or modify it
+ under  the  terms  of the  GNU  Lesser General Public License as published
+ by  the  Free Software Foundation;  either version 3 of the License,  or
+ (at your option) any later version along with the GCC Runtime Library
+ Exception either version 3.1 or (at your option) any later version.
+ This program  is  distributed  in  the  hope  that it will be useful,  but
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+ License and GCC Runtime Library Exception for more details.
+ You  should  have received a copy of the GNU Lesser General Public License
+ along  with  this program;  if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+
+ As a special exception, you  may use  this file  as it is a part of a free
+ software  library  without  restriction.  Specifically,  if   other  files
+ instantiate  templates  or  use macros or inline functions from this file,
+ or  you compile this  file  and  link  it  with other files  to produce an
+ executable, this file  does  not  by itself cause the resulting executable
+ to be covered  by the GNU Lesser General Public License.  This   exception
+ does not  however  invalidate  any  other  reasons why the executable file
+ might be covered by the GNU Lesser General Public License.
+
+===========================================================================*/
 
 /**@file gmm_solver_bfgs.h 
    @author  Yves Renard <Yves.Renard@insa-lyon.fr>
@@ -92,6 +93,8 @@ namespace gmm {
     
     template<typename VECT1, typename VECT2>
     void update(const VECT1 &deltak, const VECT2 &gammak) {
+      T vsp = vect_sp(deltak, gammak);
+      if (vsp == T(0)) return;
       size_type N = vect_size(deltak), k = delta.size();
       VECTOR Y(N);
       hmult(gammak, Y);
@@ -100,7 +103,7 @@ namespace gmm {
       resize(delta[k], N); resize(gamma[k], N); resize(zeta[k], N); 
       gmm::copy(deltak, delta[k]);
       gmm::copy(gammak, gamma[k]);
-      rho[k] = R(1) / vect_sp(deltak, gammak);
+      rho[k] = R(1) / vsp;
       if (version == 0)
 	add(delta[k], scaled(Y, -1), zeta[k]);
       else
@@ -113,9 +116,9 @@ namespace gmm {
 
 
   template <typename FUNCTION, typename DERIVATIVE, typename VECTOR> 
-  void bfgs(FUNCTION f, DERIVATIVE grad, VECTOR &x,
+  void bfgs(const FUNCTION &f, const DERIVATIVE &grad, VECTOR &x,
 	    int restart, iteration& iter, int version = 0,
-	    float lambda_init=0.001, float print_norm=1.0) {
+	    double lambda_init=0.001, double print_norm=1.0) {
 
     typedef typename linalg_traits<VECTOR>::value_type T;
     typedef typename number_traits<T>::magnitude_type R;
@@ -173,7 +176,7 @@ namespace gmm {
       ++iter;
       if (!grad_computed) grad(y, r2);
       gmm::add(scaled(r2, -1), r);
-      if (iter.get_iteration() % restart == 0 || blocked) { 
+      if ((iter.get_iteration() % restart) == 0 || blocked) { 
 	if (iter.get_noisy() >= 1) cout << "Restart\n";
 	invhessian.restart();
 	if (++nb_restart > 10) {
@@ -194,7 +197,7 @@ namespace gmm {
 
 
   template <typename FUNCTION, typename DERIVATIVE, typename VECTOR> 
-  inline void dfp(FUNCTION f, DERIVATIVE grad, VECTOR &x,
+  inline void dfp(const FUNCTION &f, const DERIVATIVE &grad, VECTOR &x,
 	    int restart, iteration& iter, int version = 1) {
     bfgs(f, grad, x, restart, iter, version);
 
diff --git a/contrib/gmm/gmm_solver_bicgstab.h b/contrib/gmm/gmm_solver_bicgstab.h
index 0fa6ab86e8..7581847a43 100644
--- a/contrib/gmm/gmm_solver_bicgstab.h
+++ b/contrib/gmm/gmm_solver_bicgstab.h
@@ -1,40 +1,40 @@
-// -*- c++ -*- (enables emacs c++ mode)
-//===========================================================================
-//
-// Copyright (C) 2002-2008 Yves Renard
-//
-// This file is a part of GETFEM++
-//
-// Getfem++  is  free software;  you  can  redistribute  it  and/or modify it
-// under  the  terms  of the  GNU  Lesser General Public License as published
-// by  the  Free Software Foundation;  either version 2.1 of the License,  or
-// (at your option) any later version.
-// This program  is  distributed  in  the  hope  that it will be useful,  but
-// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-// or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
-// License for more details.
-// You  should  have received a copy of the GNU Lesser General Public License
-// along  with  this program;  if not, write to the Free Software Foundation,
-// Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
-//
-// As a special exception, you may use this file as part of a free software
-// library without restriction.  Specifically, if other files instantiate
-// templates or use macros or inline functions from this file, or you compile
-// this file and link it with other files to produce an executable, this
-// file does not by itself cause the resulting executable to be covered by
-// the GNU General Public License.  This exception does not however
-// invalidate any other reasons why the executable file might be covered by
-// the GNU General Public License.
-//
-//===========================================================================
+/* -*- c++ -*- (enables emacs c++ mode) */
+/*===========================================================================
+
+ Copyright (C) 2002-2020 Yves Renard
+
+ This file is a part of GetFEM
+
+ GetFEM  is  free software;  you  can  redistribute  it  and/or modify it
+ under  the  terms  of the  GNU  Lesser General Public License as published
+ by  the  Free Software Foundation;  either version 3 of the License,  or
+ (at your option) any later version along with the GCC Runtime Library
+ Exception either version 3.1 or (at your option) any later version.
+ This program  is  distributed  in  the  hope  that it will be useful,  but
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+ License and GCC Runtime Library Exception for more details.
+ You  should  have received a copy of the GNU Lesser General Public License
+ along  with  this program;  if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+
+ As a special exception, you  may use  this file  as it is a part of a free
+ software  library  without  restriction.  Specifically,  if   other  files
+ instantiate  templates  or  use macros or inline functions from this file,
+ or  you compile this  file  and  link  it  with other files  to produce an
+ executable, this file  does  not  by itself cause the resulting executable
+ to be covered  by the GNU Lesser General Public License.  This   exception
+ does not  however  invalidate  any  other  reasons why the executable file
+ might be covered by the GNU Lesser General Public License.
+
+===========================================================================*/
 
 // This file is a modified version of bicgstab.h from ITL.
 // See http://osl.iu.edu/research/itl/
 // Following the corresponding Copyright notice.
 //===========================================================================
 //
-// Copyright (c) 1997-2001, The Trustees of Indiana University.
-// All rights reserved.
+// Copyright (c) 1998-2020, University of Notre Dame. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are met:
 //
@@ -43,7 +43,7 @@
 //    * Redistributions in binary form must reproduce the above copyright
 //      notice, this list of conditions and the following disclaimer in the
 //      documentation and/or other materials provided with the distribution.
-//    * Neither the name of the University of California, Berkeley nor the
+//    * Neither the name of the University of Notre Dame nor the
 //      names of its contributors may be used to endorse or promote products
 //      derived from this software without specific prior written permission.
 //
diff --git a/contrib/gmm/gmm_solver_cg.h b/contrib/gmm/gmm_solver_cg.h
index a6d29aeb1f..c81a6e9ea4 100644
--- a/contrib/gmm/gmm_solver_cg.h
+++ b/contrib/gmm/gmm_solver_cg.h
@@ -1,40 +1,40 @@
-// -*- c++ -*- (enables emacs c++ mode)
-//===========================================================================
-//
-// Copyright (C) 2002-2008 Yves Renard
-//
-// This file is a part of GETFEM++
-//
-// Getfem++  is  free software;  you  can  redistribute  it  and/or modify it
-// under  the  terms  of the  GNU  Lesser General Public License as published
-// by  the  Free Software Foundation;  either version 2.1 of the License,  or
-// (at your option) any later version.
-// This program  is  distributed  in  the  hope  that it will be useful,  but
-// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-// or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
-// License for more details.
-// You  should  have received a copy of the GNU Lesser General Public License
-// along  with  this program;  if not, write to the Free Software Foundation,
-// Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
-//
-// As a special exception, you may use this file as part of a free software
-// library without restriction.  Specifically, if other files instantiate
-// templates or use macros or inline functions from this file, or you compile
-// this file and link it with other files to produce an executable, this
-// file does not by itself cause the resulting executable to be covered by
-// the GNU General Public License.  This exception does not however
-// invalidate any other reasons why the executable file might be covered by
-// the GNU General Public License.
-//
-//===========================================================================
+/* -*- c++ -*- (enables emacs c++ mode) */
+/*===========================================================================
+
+ Copyright (C) 2002-2020 Yves Renard
+
+ This file is a part of GetFEM
+
+ GetFEM  is  free software;  you  can  redistribute  it  and/or modify it
+ under  the  terms  of the  GNU  Lesser General Public License as published
+ by  the  Free Software Foundation;  either version 3 of the License,  or
+ (at your option) any later version along with the GCC Runtime Library
+ Exception either version 3.1 or (at your option) any later version.
+ This program  is  distributed  in  the  hope  that it will be useful,  but
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+ License and GCC Runtime Library Exception for more details.
+ You  should  have received a copy of the GNU Lesser General Public License
+ along  with  this program;  if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+
+ As a special exception, you  may use  this file  as it is a part of a free
+ software  library  without  restriction.  Specifically,  if   other  files
+ instantiate  templates  or  use macros or inline functions from this file,
+ or  you compile this  file  and  link  it  with other files  to produce an
+ executable, this file  does  not  by itself cause the resulting executable
+ to be covered  by the GNU Lesser General Public License.  This   exception
+ does not  however  invalidate  any  other  reasons why the executable file
+ might be covered by the GNU Lesser General Public License.
+
+===========================================================================*/
 
 // This file is a modified version of cg.h from ITL.
 // See http://osl.iu.edu/research/itl/
 // Following the corresponding Copyright notice.
 //===========================================================================
 //
-// Copyright (c) 1997-2001, The Trustees of Indiana University.
-// All rights reserved.
+// Copyright (c) 1998-2020, University of Notre Dame. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are met:
 //
@@ -43,7 +43,7 @@
 //    * Redistributions in binary form must reproduce the above copyright
 //      notice, this list of conditions and the following disclaimer in the
 //      documentation and/or other materials provided with the distribution.
-//    * Neither the name of the University of California, Berkeley nor the
+//    * Neither the name of the University of Notre Dame nor the
 //      names of its contributors may be used to endorse or promote products
 //      derived from this software without specific prior written permission.
 //
@@ -102,10 +102,6 @@ namespace gmm {
       rho = vect_hp(PS, z, r);
       copy(z, p);
 
-// #ifdef GMM_USES_MPI
-//       double t_ref, t_prec = MPI_Wtime(), t_tot = 0;
-//       static double tmult_tot = 0.0;
-// #endif
       while (!iter.finished_vect(r)) {
 
 	if (!iter.first()) { 
@@ -113,24 +109,13 @@ namespace gmm {
 	  rho = vect_hp(PS, z, r);
 	  add(z, scaled(p, rho / rho_1), p);
 	}
-// #ifdef GMM_USES_MPI
-// t_ref = MPI_Wtime();
-//     cout << "mult CG " << endl;
-// #endif	
 	mult(A, p, q);
-// #ifdef GMM_USES_MPI
-//     tmult_tot += MPI_Wtime()-t_ref;
-//     cout << "tmult_tot CG = " << tmult_tot << endl;
-// #endif
+
 	a = rho / vect_hp(PS, q, p);	
 	add(scaled(p, a), x);
 	add(scaled(q, -a), r);
 	rho_1 = rho;
 
-// #ifdef GMM_USES_MPI
-// 	t_tot = MPI_Wtime() - t_prec;
-// 	cout << "temps CG : " << t_tot << endl; 
-// #endif
 	++iter;
       }
     }
@@ -155,34 +140,17 @@ namespace gmm {
       rho = vect_hp(PS, r, r);
       copy(r, p);
 
-// #ifdef GMM_USES_MPI
-//       double t_ref, t_prec = MPI_Wtime(), t_tot = 0;
-//       static double tmult_tot = 0.0;
-// #endif
       while (!iter.finished_vect(r)) {
 
 	if (!iter.first()) { 
 	  rho = vect_hp(PS, r, r);
 	  add(r, scaled(p, rho / rho_1), p);
-	}
-// #ifdef GMM_USES_MPI
-// t_ref = MPI_Wtime();
-//     cout << "mult CG " << endl;
-// #endif	
+	}	
 	mult(A, p, q);
-// #ifdef GMM_USES_MPI
-//     tmult_tot += MPI_Wtime()-t_ref;
-//     cout << "tmult_tot CG = " << tmult_tot << endl;
-// #endif
 	a = rho / vect_hp(PS, q, p);	
 	add(scaled(p, a), x);
 	add(scaled(q, -a), r);
 	rho_1 = rho;
-
-// #ifdef GMM_USES_MPI
-// 	t_tot = MPI_Wtime() - t_prec;
-// 	cout << "temps CG : " << t_tot << endl; 
-// #endif
 	++iter;
       }
     }
@@ -205,7 +173,7 @@ namespace gmm {
   void cg(const Matrix& A, const Vector1& x, const Vector2& b,
 	 const Precond &P, iteration &iter)
   { cg(A, x , b , identity_matrix(), P , iter); }
-  
+
 }
 
 
diff --git a/contrib/gmm/gmm_solver_constrained_cg.h b/contrib/gmm/gmm_solver_constrained_cg.h
index c7442c8c0d..c599bc9412 100644
--- a/contrib/gmm/gmm_solver_constrained_cg.h
+++ b/contrib/gmm/gmm_solver_constrained_cg.h
@@ -1,32 +1,33 @@
-// -*- c++ -*- (enables emacs c++ mode)
-//===========================================================================
-//
-// Copyright (C) 2002-2008 Yves Renard
-//
-// This file is a part of GETFEM++
-//
-// Getfem++  is  free software;  you  can  redistribute  it  and/or modify it
-// under  the  terms  of the  GNU  Lesser General Public License as published
-// by  the  Free Software Foundation;  either version 2.1 of the License,  or
-// (at your option) any later version.
-// This program  is  distributed  in  the  hope  that it will be useful,  but
-// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-// or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
-// License for more details.
-// You  should  have received a copy of the GNU Lesser General Public License
-// along  with  this program;  if not, write to the Free Software Foundation,
-// Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
-//
-// As a special exception, you may use this file as part of a free software
-// library without restriction.  Specifically, if other files instantiate
-// templates or use macros or inline functions from this file, or you compile
-// this file and link it with other files to produce an executable, this
-// file does not by itself cause the resulting executable to be covered by
-// the GNU General Public License.  This exception does not however
-// invalidate any other reasons why the executable file might be covered by
-// the GNU General Public License.
-//
-//===========================================================================
+/* -*- c++ -*- (enables emacs c++ mode) */
+/*===========================================================================
+
+ Copyright (C) 2002-2020 Yves Renard
+
+ This file is a part of GetFEM
+
+ GetFEM  is  free software;  you  can  redistribute  it  and/or modify it
+ under  the  terms  of the  GNU  Lesser General Public License as published
+ by  the  Free Software Foundation;  either version 3 of the License,  or
+ (at your option) any later version along with the GCC Runtime Library
+ Exception either version 3.1 or (at your option) any later version.
+ This program  is  distributed  in  the  hope  that it will be useful,  but
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+ License and GCC Runtime Library Exception for more details.
+ You  should  have received a copy of the GNU Lesser General Public License
+ along  with  this program;  if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+
+ As a special exception, you  may use  this file  as it is a part of a free
+ software  library  without  restriction.  Specifically,  if   other  files
+ instantiate  templates  or  use macros or inline functions from this file,
+ or  you compile this  file  and  link  it  with other files  to produce an
+ executable, this file  does  not  by itself cause the resulting executable
+ to be covered  by the GNU Lesser General Public License.  This   exception
+ does not  however  invalidate  any  other  reasons why the executable file
+ might be covered by the GNU Lesser General Public License.
+
+===========================================================================*/
 
 /**@file gmm_solver_constrained_cg.h
    @author  Yves Renard <Yves.Renard@insa-lyon.fr>
@@ -53,7 +54,6 @@ namespace gmm {
     // optimisable : copie de la ligne, precalcul de C * trans(C).
     
     typedef VectorX TmpVec;
-    typedef size_t size_type;
     typedef typename linalg_traits<VectorX>::value_type value_type;
     
     size_type nr = mat_nrows(C), nc = mat_ncols(C);
@@ -101,7 +101,6 @@ namespace gmm {
     typedef typename temporary_vector<CMatrix>::vector_type TmpCVec;
     typedef row_matrix<TmpCVec> TmpCmat;
     
-    typedef size_t size_type;
     typedef typename linalg_traits<VectorX>::value_type value_type;
     value_type rho = 1.0, rho_1, lambda, gamma;
     TmpVec p(vect_size(x)), q(vect_size(x)), q2(vect_size(x)),
@@ -146,7 +145,7 @@ namespace gmm {
       add(z, scaled(p, gamma), p); // ...
       
       ++iter;
-      // one dimensionnal optimization
+      // one dimensional optimization
       mult(A, p, q);
       lambda = rho / vect_sp(PS, q, p);
       for (size_type i = 0; i < mat_nrows(C); ++i)
diff --git a/contrib/gmm/gmm_solver_gmres.h b/contrib/gmm/gmm_solver_gmres.h
index fde56e41c2..96f81158ad 100644
--- a/contrib/gmm/gmm_solver_gmres.h
+++ b/contrib/gmm/gmm_solver_gmres.h
@@ -1,40 +1,40 @@
-// -*- c++ -*- (enables emacs c++ mode)
-//===========================================================================
-//
-// Copyright (C) 1997-2008 Yves Renard
-//
-// This file is a part of GETFEM++
-//
-// Getfem++  is  free software;  you  can  redistribute  it  and/or modify it
-// under  the  terms  of the  GNU  Lesser General Public License as published
-// by  the  Free Software Foundation;  either version 2.1 of the License,  or
-// (at your option) any later version.
-// This program  is  distributed  in  the  hope  that it will be useful,  but
-// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-// or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
-// License for more details.
-// You  should  have received a copy of the GNU Lesser General Public License
-// along  with  this program;  if not, write to the Free Software Foundation,
-// Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
-//
-// As a special exception, you may use this file as part of a free software
-// library without restriction.  Specifically, if other files instantiate
-// templates or use macros or inline functions from this file, or you compile
-// this file and link it with other files to produce an executable, this
-// file does not by itself cause the resulting executable to be covered by
-// the GNU General Public License.  This exception does not however
-// invalidate any other reasons why the executable file might be covered by
-// the GNU General Public License.
-//
-//===========================================================================
+/* -*- c++ -*- (enables emacs c++ mode) */
+/*===========================================================================
+
+ Copyright (C) 2002-2020 Yves Renard
+
+ This file is a part of GetFEM
+
+ GetFEM  is  free software;  you  can  redistribute  it  and/or modify it
+ under  the  terms  of the  GNU  Lesser General Public License as published
+ by  the  Free Software Foundation;  either version 3 of the License,  or
+ (at your option) any later version along with the GCC Runtime Library
+ Exception either version 3.1 or (at your option) any later version.
+ This program  is  distributed  in  the  hope  that it will be useful,  but
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+ License and GCC Runtime Library Exception for more details.
+ You  should  have received a copy of the GNU Lesser General Public License
+ along  with  this program;  if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+
+ As a special exception, you  may use  this file  as it is a part of a free
+ software  library  without  restriction.  Specifically,  if   other  files
+ instantiate  templates  or  use macros or inline functions from this file,
+ or  you compile this  file  and  link  it  with other files  to produce an
+ executable, this file  does  not  by itself cause the resulting executable
+ to be covered  by the GNU Lesser General Public License.  This   exception
+ does not  however  invalidate  any  other  reasons why the executable file
+ might be covered by the GNU Lesser General Public License.
+
+===========================================================================*/
 
 // This file is a modified version of gmres.h from ITL.
 // See http://osl.iu.edu/research/itl/
 // Following the corresponding Copyright notice.
 //===========================================================================
 //
-// Copyright (c) 1997-2001, The Trustees of Indiana University.
-// All rights reserved.
+// Copyright (c) 1998-2020, University of Notre Dame. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are met:
 //
@@ -43,7 +43,7 @@
 //    * Redistributions in binary form must reproduce the above copyright
 //      notice, this list of conditions and the following disclaimer in the
 //      documentation and/or other materials provided with the distribution.
-//    * Neither the name of the University of California, Berkeley nor the
+//    * Neither the name of the University of Notre Dame nor the
 //      names of its contributors may be used to endorse or promote products
 //      derived from this software without specific prior written permission.
 //
@@ -106,7 +106,7 @@ t_ref = MPI_Wtime();
     outer.set_rhsnorm(gmm::vect_norm2(r));
     if (outer.get_rhsnorm() == 0.0) { clear(x); return; }
     
-    mult(A, scaled(x, -1), b, w);
+    mult(A, scaled(x, T(-1)), b, w);
     mult(M, w, r);
     R beta = gmm::vect_norm2(r), beta_old = beta;
     int blocked = 0;
@@ -143,7 +143,7 @@ t_ref = MPI_Wtime();
 
       upper_tri_solve(H, s, i, false);
       combine(KS, s, x, i);
-      mult(A, gmm::scaled(x, -1), b, w);
+      mult(A, gmm::scaled(x, T(-1)), b, w);
       mult(M, w, r);
       beta_old = std::min(beta, beta_old); beta = gmm::vect_norm2(r);
       if (int(inner.get_iteration()) < restart -1 || beta_old <= beta)
diff --git a/contrib/gmm/gmm_solver_idgmres.h b/contrib/gmm/gmm_solver_idgmres.h
index 2a472ce8db..d6cc0460ac 100644
--- a/contrib/gmm/gmm_solver_idgmres.h
+++ b/contrib/gmm/gmm_solver_idgmres.h
@@ -1,32 +1,33 @@
-// -*- c++ -*- (enables emacs c++ mode)
-//===========================================================================
-//
-// Copyright (C) 2003-2008 Yves Renard
-//
-// This file is a part of GETFEM++
-//
-// Getfem++  is  free software;  you  can  redistribute  it  and/or modify it
-// under  the  terms  of the  GNU  Lesser General Public License as published
-// by  the  Free Software Foundation;  either version 2.1 of the License,  or
-// (at your option) any later version.
-// This program  is  distributed  in  the  hope  that it will be useful,  but
-// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-// or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
-// License for more details.
-// You  should  have received a copy of the GNU Lesser General Public License
-// along  with  this program;  if not, write to the Free Software Foundation,
-// Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
-//
-// As a special exception, you may use this file as part of a free software
-// library without restriction.  Specifically, if other files instantiate
-// templates or use macros or inline functions from this file, or you compile
-// this file and link it with other files to produce an executable, this
-// file does not by itself cause the resulting executable to be covered by
-// the GNU General Public License.  This exception does not however
-// invalidate any other reasons why the executable file might be covered by
-// the GNU General Public License.
-//
-//===========================================================================
+/* -*- c++ -*- (enables emacs c++ mode) */
+/*===========================================================================
+
+ Copyright (C) 2003-2020 Yves Renard, Caroline Lecalvez
+
+ This file is a part of GetFEM
+
+ GetFEM  is  free software;  you  can  redistribute  it  and/or modify it
+ under  the  terms  of the  GNU  Lesser General Public License as published
+ by  the  Free Software Foundation;  either version 3 of the License,  or
+ (at your option) any later version along with the GCC Runtime Library
+ Exception either version 3.1 or (at your option) any later version.
+ This program  is  distributed  in  the  hope  that it will be useful,  but
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+ License and GCC Runtime Library Exception for more details.
+ You  should  have received a copy of the GNU Lesser General Public License
+ along  with  this program;  if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+
+ As a special exception, you  may use  this file  as it is a part of a free
+ software  library  without  restriction.  Specifically,  if   other  files
+ instantiate  templates  or  use macros or inline functions from this file,
+ or  you compile this  file  and  link  it  with other files  to produce an
+ executable, this file  does  not  by itself cause the resulting executable
+ to be covered  by the GNU Lesser General Public License.  This   exception
+ does not  however  invalidate  any  other  reasons why the executable file
+ might be covered by the GNU Lesser General Public License.
+
+===========================================================================*/
 
 /**@file gmm_solver_idgmres.h
    @author  Caroline Lecalvez <Caroline.Lecalvez@gmm.insa-tlse.fr>
diff --git a/contrib/gmm/gmm_solver_qmr.h b/contrib/gmm/gmm_solver_qmr.h
index 48be120368..9ff0ddce5e 100644
--- a/contrib/gmm/gmm_solver_qmr.h
+++ b/contrib/gmm/gmm_solver_qmr.h
@@ -1,39 +1,40 @@
-// -*- c++ -*- (enables emacs c++ mode)
-//===========================================================================
-//
-// Copyright (C) 1997-2008 Yves Renard
-//
-// This file is a part of GETFEM++
-//
-// Getfem++  is  free software;  you  can  redistribute  it  and/or modify it
-// under  the  terms  of the  GNU  Lesser General Public License as published
-// by  the  Free Software Foundation;  either version 2.1 of the License,  or
-// (at your option) any later version.
-// This program  is  distributed  in  the  hope  that it will be useful,  but
-// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-// or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
-// License for more details.
-// You  should  have received a copy of the GNU Lesser General Public License
-// along  with  this program;  if not, write to the Free Software Foundation,
-// Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
-//
-// As a special exception, you may use this file as part of a free software
-// library without restriction.  Specifically, if other files instantiate
-// templates or use macros or inline functions from this file, or you compile
-// this file and link it with other files to produce an executable, this
-// file does not by itself cause the resulting executable to be covered by
-// the GNU General Public License.  This exception does not however
-// invalidate any other reasons why the executable file might be covered by
-// the GNU General Public License.
-//
-//===========================================================================
+/* -*- c++ -*- (enables emacs c++ mode) */
+/*===========================================================================
+
+ Copyright (C) 2002-2020 Yves Renard
+
+ This file is a part of GetFEM
+
+ GetFEM  is  free software;  you  can  redistribute  it  and/or modify it
+ under  the  terms  of the  GNU  Lesser General Public License as published
+ by  the  Free Software Foundation;  either version 3 of the License,  or
+ (at your option) any later version along with the GCC Runtime Library
+ Exception either version 3.1 or (at your option) any later version.
+ This program  is  distributed  in  the  hope  that it will be useful,  but
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+ License and GCC Runtime Library Exception for more details.
+ You  should  have received a copy of the GNU Lesser General Public License
+ along  with  this program;  if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+
+ As a special exception, you  may use  this file  as it is a part of a free
+ software  library  without  restriction.  Specifically,  if   other  files
+ instantiate  templates  or  use macros or inline functions from this file,
+ or  you compile this  file  and  link  it  with other files  to produce an
+ executable, this file  does  not  by itself cause the resulting executable
+ to be covered  by the GNU Lesser General Public License.  This   exception
+ does not  however  invalidate  any  other  reasons why the executable file
+ might be covered by the GNU Lesser General Public License.
+
+===========================================================================*/
 
 // This file is a modified version of qmr.h from ITL.
 // See http://osl.iu.edu/research/itl/
 // Following the corresponding Copyright notice.
 //===========================================================================
 //
-// Copyright (c) 1997-2001, The Trustees of Indiana University.
+// Copyright (c) 1997-2020, The Trustees of Indiana University.
 // All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are met:
@@ -43,7 +44,7 @@
 //    * Redistributions in binary form must reproduce the above copyright
 //      notice, this list of conditions and the following disclaimer in the
 //      documentation and/or other materials provided with the distribution.
-//    * Neither the name of the University of California, Berkeley nor the
+//    * Neither the name of the University of Notre Dame nor the
 //      names of its contributors may be used to endorse or promote products
 //      derived from this software without specific prior written permission.
 //
@@ -120,7 +121,7 @@ namespace gmm {
   
     while (! iter.finished_vect(r)) {
     
-      if (rho == R(0) || xi == R(0)){
+      if (rho == R(0) || xi == R(0)) {
 	if (iter.get_maxiter() == size_type(-1)) 
 	  { GMM_ASSERT1(false, "QMR failed to converge"); }
 	else { GMM_WARNING1("QMR failed to converge"); return; }
@@ -132,7 +133,7 @@ namespace gmm {
       gmm::scale(z, T(R(1)/xi));
 
       delta = gmm::vect_sp(z, y);
-      if (delta == T(0)){
+      if (delta == T(0)) {
 	if (iter.get_maxiter() == size_type(-1)) 
 	  { GMM_ASSERT1(false, "QMR failed to converge"); }
 	else { GMM_WARNING1("QMR failed to converge"); return; }
@@ -151,13 +152,13 @@ namespace gmm {
       gmm::mult(A, p, p_tld);
 
       ep = gmm::vect_sp(q, p_tld);
-      if (ep == T(0)){
+      if (ep == T(0)) {
 	if (iter.get_maxiter() == size_type(-1)) 
 	  { GMM_ASSERT1(false, "QMR failed to converge"); }
 	else { GMM_WARNING1("QMR failed to converge"); return; }
       }
       beta = ep / delta;
-      if (beta == T(0)){
+      if (beta == T(0)) {
 	if (iter.get_maxiter() == size_type(-1)) 
 	  { GMM_ASSERT1(false, "QMR failed to converge"); }
 	else { GMM_WARNING1("QMR failed to converge"); return; }
@@ -180,7 +181,7 @@ namespace gmm {
       theta = rho / (gamma_1 * beta);
       gamma = T(1) / gmm::sqrt(T(1) + gmm::sqr(theta));
 
-      if (gamma == T(0)){
+      if (gamma == T(0)) {
 	if (iter.get_maxiter() == size_type(-1)) 
 	  { GMM_ASSERT1(false, "QMR failed to converge"); }
 	else { GMM_WARNING1("QMR failed to converge"); return; }
diff --git a/contrib/gmm/gmm_std.h b/contrib/gmm/gmm_std.h
index 82aa9f84ba..d3a5320a01 100644
--- a/contrib/gmm/gmm_std.h
+++ b/contrib/gmm/gmm_std.h
@@ -1,38 +1,39 @@
-// -*- c++ -*- (enables emacs c++ mode)
-//===========================================================================
-//
-// Copyright (C) 1995-2008 Yves Renard
-//
-// This file is a part of GETFEM++
-//
-// Getfem++  is  free software;  you  can  redistribute  it  and/or modify it
-// under  the  terms  of the  GNU  Lesser General Public License as published
-// by  the  Free Software Foundation;  either version 2.1 of the License,  or
-// (at your option) any later version.
-// This program  is  distributed  in  the  hope  that it will be useful,  but
-// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-// or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
-// License for more details.
-// You  should  have received a copy of the GNU Lesser General Public License
-// along  with  this program;  if not, write to the Free Software Foundation,
-// Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
-//
-// As a special exception, you may use this file as part of a free software
-// library without restriction.  Specifically, if other files instantiate
-// templates or use macros or inline functions from this file, or you compile
-// this file and link it with other files to produce an executable, this
-// file does not by itself cause the resulting executable to be covered by
-// the GNU General Public License.  This exception does not however
-// invalidate any other reasons why the executable file might be covered by
-// the GNU General Public License.
-//
-//===========================================================================
+/* -*- c++ -*- (enables emacs c++ mode) */
+/*===========================================================================
+
+ Copyright (C) 2002-2020 Yves Renard
+
+ This file is a part of GetFEM
+
+ GetFEM  is  free software;  you  can  redistribute  it  and/or modify it
+ under  the  terms  of the  GNU  Lesser General Public License as published
+ by  the  Free Software Foundation;  either version 3 of the License,  or
+ (at your option) any later version along with the GCC Runtime Library
+ Exception either version 3.1 or (at your option) any later version.
+ This program  is  distributed  in  the  hope  that it will be useful,  but
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+ License and GCC Runtime Library Exception for more details.
+ You  should  have received a copy of the GNU Lesser General Public License
+ along  with  this program;  if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+
+ As a special exception, you  may use  this file  as it is a part of a free
+ software  library  without  restriction.  Specifically,  if   other  files
+ instantiate  templates  or  use macros or inline functions from this file,
+ or  you compile this  file  and  link  it  with other files  to produce an
+ executable, this file  does  not  by itself cause the resulting executable
+ to be covered  by the GNU Lesser General Public License.  This   exception
+ does not  however  invalidate  any  other  reasons why the executable file
+ might be covered by the GNU Lesser General Public License.
+
+===========================================================================*/
 
 /**@file gmm_std.h
-   @author  Yves Renard <Yves.Renard@insa-lyon.fr>,
-   @author  Julien Pommier <Julien.Pommier@insa-toulouse.fr>
-   @date June 01, 1995.
-   @brief basic setup for gmm (includes, typedefs etc.)
+@author  Yves Renard <Yves.Renard@insa-lyon.fr>,
+@author  Julien Pommier <Julien.Pommier@insa-toulouse.fr>
+@date June 01, 1995.
+@brief basic setup for gmm (includes, typedefs etc.)
 */
 #ifndef GMM_STD_H__
 #define GMM_STD_H__
@@ -55,8 +56,8 @@
 # define SECURE_NONCHAR_FSCANF fscanf_s
 # define SECURE_STRNCPY(a, la, b, lb) strncpy_s(a, la, b, lb)
 # define SECURE_FOPEN(F, filename, mode) (*(F) = 0,  fopen_s(F, filename, mode))
-# define SECURE_SPRINTF1(S, l, st, p1) sprintf_s(S, l, st, p1) 
-# define SECURE_SPRINTF2(S, l, st, p1, p2) sprintf_s(S, l, st, p1, p2) 
+# define SECURE_SPRINTF1(S, l, st, p1) sprintf_s(S, l, st, p1)
+# define SECURE_SPRINTF2(S, l, st, p1, p2) sprintf_s(S, l, st, p1, p2)
 # define SECURE_SPRINTF4(S, l, st, p1, p2, p3, p4) sprintf_s(S, l, st, p1, p2, p3, p4)
 # define SECURE_STRDUP(s) _strdup(s)
 # ifndef _SCL_SECURE_NO_DEPRECATE
@@ -69,41 +70,33 @@
 # define SECURE_FOPEN(F, filename, mode) ((*(F)) = fopen(filename, mode))
 # define SECURE_SPRINTF1(S, l, st, p1) sprintf(S, st, p1)
 # define SECURE_SPRINTF2(S, l, st, p1, p2) sprintf(S, st, p1, p2)
-# define SECURE_SPRINTF4(S, l, st, p1, p2, p3, p4) sprintf(S, st, p1, p2, p3, p4) 
+# define SECURE_SPRINTF4(S, l, st, p1, p2, p3, p4) sprintf(S, st, p1, p2, p3, p4)
 # define SECURE_STRDUP(s) strdup(s)
 #endif
 
-
-#if !defined(GMM_USES_MPI) && GETFEM_PARA_LEVEL > 0
-# define GMM_USES_MPI
-#endif
+inline void GMM_NOPERATION_(int) { }
+#define GMM_NOPERATION(a) { GMM_NOPERATION_(abs(&(a) != &(a))); }
 
 /* ********************************************************************** */
 /*	Compilers detection.						  */
 /* ********************************************************************** */
 
-/* for sun CC 5.0 ...
-#if defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x500
-# include <stdcomp.h>
-# undef _RWSTD_NO_CLASS_PARTIAL_SPEC
-# undef _RWSTD_NO_NAMESPACE
-#endif 
-*/
 /* for VISUAL C++ ...
-   #if defined(_MSC_VER) //  && !defined(__MWERKS__)
-   #define _GETFEM_MSVCPP_ _MSC_VER
-   #endif
+#if defined(_MSC_VER) //  && !defined(__MWERKS__)
+#define _GETFEM_MSVCPP_ _MSC_VER
+#endif
 */
 
 #if defined(__GNUC__)
-#  if (__GNUC__ < 3)
-#    error : PLEASE UPDATE g++ TO AT LEAST 3.0 VERSION
+#  if (__GNUC__ < 4)
+#    error : PLEASE UPDATE g++ TO AT LEAST 4.8 VERSION
 #  endif
 #endif
 
 /* ********************************************************************** */
 /*	C++ Standard Headers.						  */
 /* ********************************************************************** */
+#include <clocale>
 #include <cstdlib>
 #include <cstddef>
 #include <cmath>
@@ -112,7 +105,7 @@
 #include <cassert>
 #include <climits>
 #include <iostream>
-//#include <ios> 
+//#include <ios>
 #include <fstream>
 #include <ctime>
 #include <exception>
@@ -127,17 +120,88 @@
 #include <limits>
 #include <sstream>
 #include <numeric>
+#include <memory>
+#include <array>
+#include <locale.h>
+
+//#include <gmm/gmm_arch_config.h>
+
+namespace std {
+#if defined(__GNUC__) && (__cplusplus <= 201103L)
+  template<typename _Tp>
+    struct _MakeUniq
+    { typedef unique_ptr<_Tp> __single_object; };
+  template<typename _Tp>
+    struct _MakeUniq<_Tp[]>
+    { typedef unique_ptr<_Tp[]> __array; };
+  template<typename _Tp, size_t _Bound>
+    struct _MakeUniq<_Tp[_Bound]>
+    { struct __invalid_type { }; };
+  /// std::make_unique for single objects
+  template<typename _Tp, typename... _Args>
+    inline typename _MakeUniq<_Tp>::__single_object
+    make_unique(_Args&&... __args)
+    { return unique_ptr<_Tp>(new _Tp(std::forward<_Args>(__args)...)); }
+  /// std::make_unique for arrays of unknown bound
+  template<typename _Tp>
+    inline typename _MakeUniq<_Tp>::__array
+    make_unique(size_t __num)
+    { return unique_ptr<_Tp>(new typename remove_extent<_Tp>::type[__num]()); }
+  /// Disable std::make_unique for arrays of known bound
+  template<typename _Tp, typename... _Args>
+    inline typename _MakeUniq<_Tp>::__invalid_type
+    make_unique(_Args&&...) = delete;
+#endif
+
 
+  // Should simply be replaced by std::shared_ptr<T[]> when it will be supported
+  // by the STL
+  template <typename T> class shared_array_ptr : shared_ptr<T> {
+  public:
+    shared_array_ptr() {}
+    shared_array_ptr(T *q) : std::shared_ptr<T>(q, default_delete<T[]>()) {}
+    template <typename Y> shared_array_ptr(const std::shared_ptr<Y> &p, T *q)
+      : std::shared_ptr<T>(p, q) {}
+    T *get() const { return shared_ptr<T>::get(); }
+    T& operator*() const { return shared_ptr<T>::operator*(); }
+    T* operator->() const { return shared_ptr<T>::operator->(); }
+  };
 
-using std::endl; using std::cout; using std::cerr;
-using std::ends; using std::cin;
+  template <typename T> shared_array_ptr<T> make_shared_array(size_t num)
+  { return shared_array_ptr<T>(new T[num]); }
+}
 
 namespace gmm {
 
+  using std::endl; using std::cout; using std::cerr;
+        using std::ends; using std::cin; using std::isnan;
+
+  class standard_locale {
+    std::string cloc;
+    std::locale cinloc;
+
+  public :
+    inline standard_locale(void)
+      : cloc(setlocale(LC_NUMERIC, 0)), cinloc(cin.getloc())
+    { setlocale(LC_NUMERIC,"C"); cin.imbue(std::locale("C")); }
+    inline ~standard_locale()
+    { setlocale(LC_NUMERIC, cloc.c_str()); cin.imbue(cinloc); }
+  };
+
+  class stream_standard_locale {
+    std::locale cloc;
+    std::ios &io;
+
+  public :
+    inline stream_standard_locale(std::ios &i)
+      : cloc(i.getloc()), io(i) { io.imbue(std::locale("C")); }
+    inline ~stream_standard_locale() { io.imbue(cloc); }
+  };
+
   /* ******************************************************************* */
   /*       Clock functions.                                              */
   /* ******************************************************************* */
-  
+
 # if  defined(HAVE_SYS_TIMES)
   inline double uclock_sec(void) {
     static double ttclk = 0.;
@@ -148,16 +212,16 @@ namespace gmm {
   inline double uclock_sec(void)
   { return double(clock())/double(CLOCKS_PER_SEC); }
 # endif
-  
+
   /* ******************************************************************** */
   /*	Fixed size integer types.                     			  */
   /* ******************************************************************** */
-  // Remark : the test program dynamic_array tests the lenght of
+  // Remark : the test program dynamic_array tests the length of
   //          resulting integers
 
   template <size_t s> struct fixed_size_integer_generator {
     typedef void int_base_type;
-    typedef void uint_base_type;  
+    typedef void uint_base_type;
   };
 
   template <> struct fixed_size_integer_generator<sizeof(char)> {
@@ -167,36 +231,36 @@ namespace gmm {
 
   template <> struct fixed_size_integer_generator<sizeof(short int)
     - ((sizeof(short int) == sizeof(char)) ? 78 : 0)> {
-    typedef signed short int int_base_type;
-    typedef unsigned short int uint_base_type;
-  };
+  typedef signed short int int_base_type;
+  typedef unsigned short int uint_base_type;
+};
 
-  template <> struct fixed_size_integer_generator<sizeof(int)
-    - ((sizeof(int) == sizeof(short int)) ? 59 : 0)> {
+template <> struct fixed_size_integer_generator<sizeof(int)
+  - ((sizeof(int) == sizeof(short int)) ? 59 : 0)> {
     typedef signed int int_base_type;
     typedef unsigned int uint_base_type;
   };
- 
-  template <> struct fixed_size_integer_generator<sizeof(long)
-    - ((sizeof(int) == sizeof(long)) ? 93 : 0)> {
+
+template <> struct fixed_size_integer_generator<sizeof(long)
+  - ((sizeof(int) == sizeof(long)) ? 93 : 0)> {
     typedef signed long int_base_type;
     typedef unsigned long uint_base_type;
   };
 
-  template <> struct fixed_size_integer_generator<sizeof(long long)
-    - ((sizeof(long long) == sizeof(long)) ? 99 : 0)> {
+template <> struct fixed_size_integer_generator<sizeof(long long)
+  - ((sizeof(long long) == sizeof(long)) ? 99 : 0)> {
     typedef signed long long int_base_type;
     typedef unsigned long long uint_base_type;
   };
- 
-  typedef fixed_size_integer_generator<1>::int_base_type int8_type;
-  typedef fixed_size_integer_generator<1>::uint_base_type uint8_type;
-  typedef fixed_size_integer_generator<2>::int_base_type int16_type;
-  typedef fixed_size_integer_generator<2>::uint_base_type uint16_type;
-  typedef fixed_size_integer_generator<4>::int_base_type int32_type;
-  typedef fixed_size_integer_generator<4>::uint_base_type uint32_type;
-  typedef fixed_size_integer_generator<8>::int_base_type int64_type;
-  typedef fixed_size_integer_generator<8>::uint_base_type uint64_type;
+
+typedef fixed_size_integer_generator<1>::int_base_type int8_type;
+typedef fixed_size_integer_generator<1>::uint_base_type uint8_type;
+typedef fixed_size_integer_generator<2>::int_base_type int16_type;
+typedef fixed_size_integer_generator<2>::uint_base_type uint16_type;
+typedef fixed_size_integer_generator<4>::int_base_type int32_type;
+typedef fixed_size_integer_generator<4>::uint_base_type uint32_type;
+typedef fixed_size_integer_generator<8>::int_base_type int64_type;
+typedef fixed_size_integer_generator<8>::uint_base_type uint64_type;
 
 // #if INT_MAX == 32767
 //   typedef signed int    int16_type;
@@ -235,23 +299,54 @@ namespace gmm {
 // #endif
 
 #if defined(__GNUC__) && !defined(__ICC)
-/* 
-   g++ can issue a warning at each usage of a function declared with this special attribute 
+/*
+   g++ can issue a warning at each usage of a function declared with this special attribute
    (also works with typedefs and variable declarations)
 */
-//# define IS_DEPRECATED __attribute__ ((__deprecated__))
-// annoying : just including .h files e.g. gmm_precond_ildlt.h generates lots of useless warnings with new 4.6+ gcc.
-# define IS_DEPRECATED
+# define IS_DEPRECATED __attribute__ ((__deprecated__))
 /*
-   the specified function is inlined at any optimization level 
+  the specified function is inlined at any optimization level
 */
 # define ALWAYS_INLINE __attribute__((always_inline))
 #else
 # define IS_DEPRECATED
 # define ALWAYS_INLINE
 #endif
-  
+
 }
 
-#endif /* GMM_STD_H__ */
+  /* ******************************************************************** */
+  /*	Import/export classes and interfaces from a shared library          */
+  /* ******************************************************************** */
 
+#if defined(EXPORTED_TO_SHARED_LIB)
+#  if defined(_MSC_VER) || defined(__INTEL_COMPILER)
+#     define APIDECL __declspec(dllexport)
+#  elif defined(__GNUC__)
+#     define __attribute__((visibility("default")))
+#  else
+#     define APIDECL
+#  endif
+#   if defined(IMPORTED_FROM_SHARED_LIB)
+#	  error INTENTIONAL COMPILCATION ERROR, DLL IMPORT AND EXPORT ARE INCOMPITABLE
+#   endif
+#endif
+
+#if defined(IMPORTED_FROM_SHARED_LIB)
+#  if defined(_MSC_VER) || defined(__INTEL_COMPILER)
+#     define APIDECL __declspec(dllimport)
+#  else
+#     define APIDECL
+#  endif
+#   if defined(EXPORTED_TO_SHARED_LIB)
+#	  error INTENTIONAL COMPILCATION ERROR, DLL IMPORT AND EXPORT ARE INCOMPITABLE
+#   endif
+#endif
+
+#ifndef EXPORTED_TO_SHARED_LIB
+#  ifndef IMPORTED_FROM_SHARED_LIB
+#    define APIDECL  //empty, used during static linking
+#  endif
+#endif
+
+#endif /* GMM_STD_H__ */
diff --git a/contrib/gmm/gmm_sub_index.h b/contrib/gmm/gmm_sub_index.h
index 387c70701f..28c95e0dea 100644
--- a/contrib/gmm/gmm_sub_index.h
+++ b/contrib/gmm/gmm_sub_index.h
@@ -1,32 +1,33 @@
-// -*- c++ -*- (enables emacs c++ mode)
-//===========================================================================
-//
-// Copyright (C) 2002-2008 Yves Renard
-//
-// This file is a part of GETFEM++
-//
-// Getfem++  is  free software;  you  can  redistribute  it  and/or modify it
-// under  the  terms  of the  GNU  Lesser General Public License as published
-// by  the  Free Software Foundation;  either version 2.1 of the License,  or
-// (at your option) any later version.
-// This program  is  distributed  in  the  hope  that it will be useful,  but
-// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-// or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
-// License for more details.
-// You  should  have received a copy of the GNU Lesser General Public License
-// along  with  this program;  if not, write to the Free Software Foundation,
-// Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
-//
-// As a special exception, you may use this file as part of a free software
-// library without restriction.  Specifically, if other files instantiate
-// templates or use macros or inline functions from this file, or you compile
-// this file and link it with other files to produce an executable, this
-// file does not by itself cause the resulting executable to be covered by
-// the GNU General Public License.  This exception does not however
-// invalidate any other reasons why the executable file might be covered by
-// the GNU General Public License.
-//
-//===========================================================================
+/* -*- c++ -*- (enables emacs c++ mode) */
+/*===========================================================================
+
+ Copyright (C) 2002-2020 Yves Renard
+
+ This file is a part of GetFEM
+
+ GetFEM  is  free software;  you  can  redistribute  it  and/or modify it
+ under  the  terms  of the  GNU  Lesser General Public License as published
+ by  the  Free Software Foundation;  either version 3 of the License,  or
+ (at your option) any later version along with the GCC Runtime Library
+ Exception either version 3.1 or (at your option) any later version.
+ This program  is  distributed  in  the  hope  that it will be useful,  but
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+ License and GCC Runtime Library Exception for more details.
+ You  should  have received a copy of the GNU Lesser General Public License
+ along  with  this program;  if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+
+ As a special exception, you  may use  this file  as it is a part of a free
+ software  library  without  restriction.  Specifically,  if   other  files
+ instantiate  templates  or  use macros or inline functions from this file,
+ or  you compile this  file  and  link  it  with other files  to produce an
+ executable, this file  does  not  by itself cause the resulting executable
+ to be covered  by the GNU Lesser General Public License.  This   exception
+ does not  however  invalidate  any  other  reasons why the executable file
+ might be covered by the GNU Lesser General Public License.
+
+===========================================================================*/
 
 /**@file gmm_sub_index.h
    @author  Yves Renard <Yves.Renard@insa-lyon.fr>
@@ -105,38 +106,41 @@ namespace gmm {
 	{ first_ = std::min(first_, *it); last_ = std::max(last_, *it); }
     }
 
-    // inline void test_rind(void) const
-    //  { if (!rind) rind = index_generator::create_rindex(ind); }
+    inline void test_rind(void) const
+    { if (!rind) rind = index_generator::create_rindex(ind); }
     size_type size(void) const { return ind->size(); }
     size_type first(void) const { return first_; }
     size_type last(void) const { return last_; }
     size_type index(size_type i) const { return (*ind)[i]; }
     size_type rindex(size_type i) const {
-      // test_rind();
+      test_rind();
       if (i < rind->size()) return (*rind)[i]; else return size_type(-1);
     }
    
     const_iterator  begin(void) const { return  ind->begin(); }
     const_iterator    end(void) const { return  ind->end();   }
-    const_iterator rbegin(void) const {/*test_rind();*/ return rind->begin(); }
-    const_iterator   rend(void) const {/*test_rind();*/ return rind->end();   }
+    const_iterator rbegin(void) const { test_rind(); return rind->begin(); }
+    const_iterator   rend(void) const { test_rind(); return rind->end();   }
 
     sub_index() : ind(0), rind(0) {}
     template <typename IT> sub_index(IT it, IT ite)
       : ind(index_generator::create_index(it, ite)),
-	rind(index_generator::create_rindex(ind)) { comp_extr(); }
+	rind(0) { comp_extr(); }
     template <typename CONT> sub_index(const CONT &c)
       : ind(index_generator::create_index(c.begin(), c.end())),
-	rind(index_generator::create_rindex(ind))
-        { comp_extr(); }
-    ~sub_index()
-      { index_generator::unattach(rind); index_generator::unattach(ind); }
+	rind(0) { comp_extr(); }
+    ~sub_index() {
+      index_generator::unattach(rind);
+      index_generator::unattach(ind);
+    }
     sub_index(const sub_index &si) : first_(si.first_), last_(si.last_),
 				     ind(si.ind), rind(si.rind)
-      { index_generator::attach(rind); index_generator::attach(ind); }
+    { index_generator::attach(rind); index_generator::attach(ind); }
     sub_index &operator =(const sub_index &si) {
-      index_generator::unattach(rind); index_generator::unattach(ind);
-      ind = si.ind; rind = si.rind; index_generator::attach(rind);
+      index_generator::unattach(rind);
+      index_generator::unattach(ind);
+      ind = si.ind; rind = si.rind;
+      index_generator::attach(rind);
       index_generator::attach(ind);
       first_ = si.first_; last_ = si.last_;
       return *this;
@@ -144,12 +148,15 @@ namespace gmm {
   };
 
   struct unsorted_sub_index : public sub_index {
+    typedef basic_index base_type;
+    typedef base_type::const_iterator const_iterator;
+    
     template <typename IT> unsorted_sub_index(IT it, IT ite)
       : sub_index(it, ite) {}
     template <typename CONT> unsorted_sub_index(const CONT &c)
       : sub_index(c) {}
     unsorted_sub_index() {}
-    unsorted_sub_index(const unsorted_sub_index &si) : sub_index(si) {}
+    unsorted_sub_index(const unsorted_sub_index &si) : sub_index((const sub_index &)(si)) { }
     unsorted_sub_index &operator =(const unsorted_sub_index &si)
     { sub_index::operator =(si); return *this; }
     void swap(size_type i, size_type j) {
diff --git a/contrib/gmm/gmm_sub_matrix.h b/contrib/gmm/gmm_sub_matrix.h
index efc36bcf69..998a766234 100644
--- a/contrib/gmm/gmm_sub_matrix.h
+++ b/contrib/gmm/gmm_sub_matrix.h
@@ -1,32 +1,33 @@
-// -*- c++ -*- (enables emacs c++ mode)
-//===========================================================================
-//
-// Copyright (C) 2002-2008 Yves Renard
-//
-// This file is a part of GETFEM++
-//
-// Getfem++  is  free software;  you  can  redistribute  it  and/or modify it
-// under  the  terms  of the  GNU  Lesser General Public License as published
-// by  the  Free Software Foundation;  either version 2.1 of the License,  or
-// (at your option) any later version.
-// This program  is  distributed  in  the  hope  that it will be useful,  but
-// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-// or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
-// License for more details.
-// You  should  have received a copy of the GNU Lesser General Public License
-// along  with  this program;  if not, write to the Free Software Foundation,
-// Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
-//
-// As a special exception, you may use this file as part of a free software
-// library without restriction.  Specifically, if other files instantiate
-// templates or use macros or inline functions from this file, or you compile
-// this file and link it with other files to produce an executable, this
-// file does not by itself cause the resulting executable to be covered by
-// the GNU General Public License.  This exception does not however
-// invalidate any other reasons why the executable file might be covered by
-// the GNU General Public License.
-//
-//===========================================================================
+/* -*- c++ -*- (enables emacs c++ mode) */
+/*===========================================================================
+
+ Copyright (C) 2002-2020 Yves Renard
+
+ This file is a part of GetFEM
+
+ GetFEM  is  free software;  you  can  redistribute  it  and/or modify it
+ under  the  terms  of the  GNU  Lesser General Public License as published
+ by  the  Free Software Foundation;  either version 3 of the License,  or
+ (at your option) any later version along with the GCC Runtime Library
+ Exception either version 3.1 or (at your option) any later version.
+ This program  is  distributed  in  the  hope  that it will be useful,  but
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+ License and GCC Runtime Library Exception for more details.
+ You  should  have received a copy of the GNU Lesser General Public License
+ along  with  this program;  if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+
+ As a special exception, you  may use  this file  as it is a part of a free
+ software  library  without  restriction.  Specifically,  if   other  files
+ instantiate  templates  or  use macros or inline functions from this file,
+ or  you compile this  file  and  link  it  with other files  to produce an
+ executable, this file  does  not  by itself cause the resulting executable
+ to be covered  by the GNU Lesser General Public License.  This   exception
+ does not  however  invalidate  any  other  reasons why the executable file
+ might be covered by the GNU Lesser General Public License.
+
+===========================================================================*/
 
 /**@file gmm_sub_matrix.h
    @author Yves Renard <Yves.Renard@insa-lyon.fr>
@@ -142,11 +143,11 @@ namespace gmm {
     typedef abstract_null_type col_iterator;
     typedef abstract_null_type const_sub_col_type;
     typedef abstract_null_type const_col_iterator;
-    typedef typename sub_vector_type<const typename
-            linalg_traits<M>::const_sub_row_type *, SUBI2>::vector_type
+    typedef typename sub_vector_type<const typename org_type<typename
+	    linalg_traits<M>::const_sub_row_type>::t *, SUBI2>::vector_type
             const_sub_row_type;
     typedef typename select_ref<abstract_null_type, 
-            typename sub_vector_type<typename linalg_traits<M>::sub_row_type *,
+	    typename sub_vector_type<typename org_type<typename linalg_traits<M>::sub_row_type>::t *,
 	    SUBI2>::vector_type, PT>::ref_type sub_row_type;
     typedef gen_sub_row_matrix_iterator<typename const_pointer<PT>::pointer,
 	    SUBI1, SUBI2> const_row_iterator;
@@ -289,12 +290,8 @@ namespace gmm {
     typedef abstract_null_type row_iterator;
     typedef abstract_null_type const_sub_row_type;
     typedef abstract_null_type const_row_iterator;
-    typedef typename sub_vector_type<const typename
-            linalg_traits<M>::const_sub_col_type *, SUBI1>::vector_type
-            const_sub_col_type;
-    typedef typename select_ref<abstract_null_type, 
-            typename sub_vector_type<typename linalg_traits<M>::sub_col_type *,
-	    SUBI1>::vector_type, PT>::ref_type sub_col_type;
+    typedef typename sub_vector_type<const typename org_type<typename linalg_traits<M>::const_sub_col_type>::t *, SUBI1>::vector_type const_sub_col_type;
+    typedef typename select_ref<abstract_null_type, typename sub_vector_type<typename org_type<typename linalg_traits<M>::sub_col_type>::t *, SUBI1>::vector_type, PT>::ref_type sub_col_type;
     typedef gen_sub_col_matrix_iterator<typename const_pointer<PT>::pointer,
 	    SUBI1, SUBI2> const_col_iterator;
     typedef typename select_ref<abstract_null_type, 
diff --git a/contrib/gmm/gmm_sub_vector.h b/contrib/gmm/gmm_sub_vector.h
index 4f3292db5a..2ca8df8dfb 100644
--- a/contrib/gmm/gmm_sub_vector.h
+++ b/contrib/gmm/gmm_sub_vector.h
@@ -1,32 +1,33 @@
-// -*- c++ -*- (enables emacs c++ mode)
-//===========================================================================
-//
-// Copyright (C) 2002-2008 Yves Renard
-//
-// This file is a part of GETFEM++
-//
-// Getfem++  is  free software;  you  can  redistribute  it  and/or modify it
-// under  the  terms  of the  GNU  Lesser General Public License as published
-// by  the  Free Software Foundation;  either version 2.1 of the License,  or
-// (at your option) any later version.
-// This program  is  distributed  in  the  hope  that it will be useful,  but
-// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-// or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
-// License for more details.
-// You  should  have received a copy of the GNU Lesser General Public License
-// along  with  this program;  if not, write to the Free Software Foundation,
-// Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
-//
-// As a special exception, you may use this file as part of a free software
-// library without restriction.  Specifically, if other files instantiate
-// templates or use macros or inline functions from this file, or you compile
-// this file and link it with other files to produce an executable, this
-// file does not by itself cause the resulting executable to be covered by
-// the GNU General Public License.  This exception does not however
-// invalidate any other reasons why the executable file might be covered by
-// the GNU General Public License.
-//
-//===========================================================================
+/* -*- c++ -*- (enables emacs c++ mode) */
+/*===========================================================================
+
+ Copyright (C) 2002-2020 Yves Renard
+
+ This file is a part of GetFEM
+
+ GetFEM  is  free software;  you  can  redistribute  it  and/or modify it
+ under  the  terms  of the  GNU  Lesser General Public License as published
+ by  the  Free Software Foundation;  either version 3 of the License,  or
+ (at your option) any later version along with the GCC Runtime Library
+ Exception either version 3.1 or (at your option) any later version.
+ This program  is  distributed  in  the  hope  that it will be useful,  but
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+ License and GCC Runtime Library Exception for more details.
+ You  should  have received a copy of the GNU Lesser General Public License
+ along  with  this program;  if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+
+ As a special exception, you  may use  this file  as it is a part of a free
+ software  library  without  restriction.  Specifically,  if   other  files
+ instantiate  templates  or  use macros or inline functions from this file,
+ or  you compile this  file  and  link  it  with other files  to produce an
+ executable, this file  does  not  by itself cause the resulting executable
+ to be covered  by the GNU Lesser General Public License.  This   exception
+ does not  however  invalidate  any  other  reasons why the executable file
+ might be covered by the GNU Lesser General Public License.
+
+===========================================================================*/
 
 /**@file gmm_sub_vector.h
    @author  Yves Renard <Yves.Renard@insa-lyon.fr>
@@ -78,8 +79,13 @@ namespace gmm {
     sparse_sub_vector_iterator(void) {}
     sparse_sub_vector_iterator(const IT &it, const IT &ite, const SUBI &s)
       : itb(it), itbe(ite), si(s) { forward(); }
-    sparse_sub_vector_iterator(const sparse_sub_vector_iterator<MIT, MIT,
-	 SUBI> &it) : itb(it.itb), itbe(it.itbe), si(it.si) {}
+    sparse_sub_vector_iterator
+    (const sparse_sub_vector_iterator<MIT, MIT, SUBI> &it)
+      : itb(it.itb), itbe(it.itbe), si(it.si) {}
+    sparse_sub_vector_iterator &operator =
+    (const sparse_sub_vector_iterator<MIT, MIT, SUBI> &it)
+    { itb = it.itb; itbe = it.itbe;  si = it.si; return *this; }
+
   };
 
   template <typename IT, typename MIT, typename SUBI>
@@ -533,7 +539,8 @@ namespace gmm {
     typename sub_vector_type<const V *, SUBI>::vector_type,
     typename sub_vector_type<V *, SUBI>::vector_type, const V *>::return_type
   sub_vector(const V &v, const SUBI &si) {
-    GMM_ASSERT2(si.last() <= vect_size(v), "sub vector too large");
+    GMM_ASSERT2(si.last() <= vect_size(v),
+                "sub vector too large, " << si.last() << " > " << vect_size(v));
     return typename select_return<
       typename sub_vector_type<const V *, SUBI>::vector_type,
       typename sub_vector_type<V *, SUBI>::vector_type, const V *>::return_type
@@ -545,7 +552,8 @@ namespace gmm {
     typename sub_vector_type<const V *, SUBI>::vector_type,
     typename sub_vector_type<V *, SUBI>::vector_type, V *>::return_type
   sub_vector(V &v, const SUBI &si) {
-    GMM_ASSERT2(si.last() <= vect_size(v), "sub vector too large");
+    GMM_ASSERT2(si.last() <= vect_size(v),
+                "sub vector too large, " << si.last() << " > " << vect_size(v));
     return  typename select_return<
       typename sub_vector_type<const V *, SUBI>::vector_type,
       typename sub_vector_type<V *, SUBI>::vector_type, V *>::return_type
diff --git a/contrib/gmm/gmm_superlu_interface.h b/contrib/gmm/gmm_superlu_interface.h
index eb32435b86..2a7a2a4a52 100644
--- a/contrib/gmm/gmm_superlu_interface.h
+++ b/contrib/gmm/gmm_superlu_interface.h
@@ -1,32 +1,33 @@
-// -*- c++ -*- (enables emacs c++ mode)
-//===========================================================================
-//
-// Copyright (C) 2003-2008 Yves Renard
-//
-// This file is a part of GETFEM++
-//
-// Getfem++  is  free software;  you  can  redistribute  it  and/or modify it
-// under  the  terms  of the  GNU  Lesser General Public License as published
-// by  the  Free Software Foundation;  either version 2.1 of the License,  or
-// (at your option) any later version.
-// This program  is  distributed  in  the  hope  that it will be useful,  but
-// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-// or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
-// License for more details.
-// You  should  have received a copy of the GNU Lesser General Public License
-// along  with  this program;  if not, write to the Free Software Foundation,
-// Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
-//
-// As a special exception, you may use this file as part of a free software
-// library without restriction.  Specifically, if other files instantiate
-// templates or use macros or inline functions from this file, or you compile
-// this file and link it with other files to produce an executable, this
-// file does not by itself cause the resulting executable to be covered by
-// the GNU General Public License.  This exception does not however
-// invalidate any other reasons why the executable file might be covered by
-// the GNU General Public License.
-//
-//===========================================================================
+/* -*- c++ -*- (enables emacs c++ mode) */
+/*===========================================================================
+
+ Copyright (C) 2003-2020 Yves Renard
+
+ This file is a part of GetFEM
+
+ GetFEM  is  free software;  you  can  redistribute  it  and/or modify it
+ under  the  terms  of the  GNU  Lesser General Public License as published
+ by  the  Free Software Foundation;  either version 3 of the License,  or
+ (at your option) any later version along with the GCC Runtime Library
+ Exception either version 3.1 or (at your option) any later version.
+ This program  is  distributed  in  the  hope  that it will be useful,  but
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+ License and GCC Runtime Library Exception for more details.
+ You  should  have received a copy of the GNU Lesser General Public License
+ along  with  this program;  if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+
+ As a special exception, you  may use  this file  as it is a part of a free
+ software  library  without  restriction.  Specifically,  if   other  files
+ instantiate  templates  or  use macros or inline functions from this file,
+ or  you compile this  file  and  link  it  with other files  to produce an
+ executable, this file  does  not  by itself cause the resulting executable
+ to be covered  by the GNU Lesser General Public License.  This   exception
+ does not  however  invalidate  any  other  reasons why the executable file
+ might be covered by the GNU Lesser General Public License.
+
+===========================================================================*/
 
 /**@file gmm_superlu_interface.h
    @author  Yves Renard <Yves.Renard@insa-lyon.fr>
@@ -50,21 +51,21 @@ typedef int int_t;
 # undef FALSE
 #endif
 
-#include "SRC/slu_Cnames.h"
-#include "SRC/supermatrix.h"
-#include "SRC/slu_util.h"
+#include "superlu/slu_Cnames.h"
+#include "superlu/supermatrix.h"
+#include "superlu/slu_util.h"
 
 namespace SuperLU_S {
-#include "SRC/slu_sdefs.h"
+#include "superlu/slu_sdefs.h"
 }
 namespace SuperLU_D {
-#include "SRC/slu_ddefs.h"
+#include "superlu/slu_ddefs.h"
 }
 namespace SuperLU_C {
-#include "SRC/slu_cdefs.h"
+#include "superlu/slu_cdefs.h"
 }
 namespace SuperLU_Z {
-#include "SRC/slu_zdefs.h" 
+#include "superlu/slu_zdefs.h" 
 }
 
 
@@ -157,7 +158,7 @@ namespace gmm {
   /* ********************************************************************* */
 
   template <typename MAT, typename VECTX, typename VECTB>
-  void SuperLU_solve(const MAT &A, const VECTX &X_, const VECTB &B,
+  int SuperLU_solve(const MAT &A, const VECTX &X_, const VECTB &B,
 		     double& rcond_, int permc_spec = 3) {
     VECTX &X = const_cast<VECTX &>(X_);
     /*
@@ -195,8 +196,8 @@ namespace gmm {
     StatInit(&stat);
 
     SuperMatrix SA, SL, SU, SB, SX; // SuperLU format.
-    Create_CompCol_Matrix(&SA, m, n, nz, csc_A.pr,
-			  (int *)(csc_A.ir), (int *)(csc_A.jc));
+    Create_CompCol_Matrix(&SA, m, n, nz, (double *)(&(csc_A.pr[0])),
+			  (int *)(&(csc_A.ir[0])), (int *)(&(csc_A.jc[0])));
     Create_Dense_Matrix(&SB, m, nrhs, &rhs[0], m);
     Create_Dense_Matrix(&SX, m, nrhs, &sol[0], m);
     memset(&SL,0,sizeof SL);
@@ -231,8 +232,10 @@ namespace gmm {
     Destroy_SuperNode_Matrix(&SL);
     Destroy_CompCol_Matrix(&SU);
     StatFree(&stat);
-    GMM_ASSERT1(info == 0, "SuperLU solve failed: info=" << info);
+    GMM_ASSERT1(info >= 0, "SuperLU solve failed: info =" << info);
+    if (info > 0) GMM_WARNING1("SuperLU solve failed: info =" << info);
     gmm::copy(sol, X);
+    return info;
   }
 
   template <class T> class SuperLU_factor {
@@ -314,9 +317,10 @@ namespace gmm {
       case 3 : options.ColPerm = COLAMD; break;
       }
       StatInit(&stat);
-      
-      Create_CompCol_Matrix(&SA, m, n, nz, csc_A.pr,
-			    (int *)(csc_A.ir), (int *)(csc_A.jc));
+
+      Create_CompCol_Matrix(&SA, m, n, nz, (double *)(&(csc_A.pr[0])),
+			    (int *)(&(csc_A.ir[0])), (int *)(&(csc_A.jc[0])));
+
       Create_Dense_Matrix(&SB, m, 0, &rhs[0], m);
       Create_Dense_Matrix(&SX, m, 0, &sol[0], m);
       memset(&SL,0,sizeof SL);
diff --git a/contrib/gmm/gmm_transposed.h b/contrib/gmm/gmm_transposed.h
index b5da665970..77cf460e8c 100644
--- a/contrib/gmm/gmm_transposed.h
+++ b/contrib/gmm/gmm_transposed.h
@@ -1,32 +1,33 @@
-// -*- c++ -*- (enables emacs c++ mode)
-//===========================================================================
-//
-// Copyright (C) 2002-2008 Yves Renard
-//
-// This file is a part of GETFEM++
-//
-// Getfem++  is  free software;  you  can  redistribute  it  and/or modify it
-// under  the  terms  of the  GNU  Lesser General Public License as published
-// by  the  Free Software Foundation;  either version 2.1 of the License,  or
-// (at your option) any later version.
-// This program  is  distributed  in  the  hope  that it will be useful,  but
-// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-// or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
-// License for more details.
-// You  should  have received a copy of the GNU Lesser General Public License
-// along  with  this program;  if not, write to the Free Software Foundation,
-// Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
-//
-// As a special exception, you may use this file as part of a free software
-// library without restriction.  Specifically, if other files instantiate
-// templates or use macros or inline functions from this file, or you compile
-// this file and link it with other files to produce an executable, this
-// file does not by itself cause the resulting executable to be covered by
-// the GNU General Public License.  This exception does not however
-// invalidate any other reasons why the executable file might be covered by
-// the GNU General Public License.
-//
-//===========================================================================
+/* -*- c++ -*- (enables emacs c++ mode) */
+/*===========================================================================
+
+ Copyright (C) 2002-2020 Yves Renard
+
+ This file is a part of GetFEM
+
+ GetFEM  is  free software;  you  can  redistribute  it  and/or modify it
+ under  the  terms  of the  GNU  Lesser General Public License as published
+ by  the  Free Software Foundation;  either version 3 of the License,  or
+ (at your option) any later version along with the GCC Runtime Library
+ Exception either version 3.1 or (at your option) any later version.
+ This program  is  distributed  in  the  hope  that it will be useful,  but
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+ License and GCC Runtime Library Exception for more details.
+ You  should  have received a copy of the GNU Lesser General Public License
+ along  with  this program;  if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+
+ As a special exception, you  may use  this file  as it is a part of a free
+ software  library  without  restriction.  Specifically,  if   other  files
+ instantiate  templates  or  use macros or inline functions from this file,
+ or  you compile this  file  and  link  it  with other files  to produce an
+ executable, this file  does  not  by itself cause the resulting executable
+ to be covered  by the GNU Lesser General Public License.  This   exception
+ does not  however  invalidate  any  other  reasons why the executable file
+ might be covered by the GNU Lesser General Public License.
+
+===========================================================================*/
 
 /**@file gmm_transposed.h
    @author  Yves Renard <Yves.Renard@insa-lyon.fr>
@@ -89,7 +90,7 @@ namespace gmm {
     typedef abstract_null_type const_row_iterator;
     typedef typename linalg_traits<M>::const_sub_row_type const_sub_col_type;
     typedef typename select_ref<abstract_null_type, typename
-            linalg_traits<M>::sub_row_type, PT>::ref_type sub_col_type;
+	    linalg_traits<M>::sub_row_type, PT>::ref_type sub_col_type;
     typedef typename linalg_traits<M>::const_row_iterator const_col_iterator;
     typedef typename select_ref<abstract_null_type, typename
             linalg_traits<M>::row_iterator, PT>::ref_type col_iterator;
@@ -170,7 +171,7 @@ namespace gmm {
     typedef abstract_null_type const_col_iterator;
     typedef typename linalg_traits<M>::const_sub_col_type const_sub_row_type;
     typedef typename select_ref<abstract_null_type, typename
-            linalg_traits<M>::sub_col_type, PT>::ref_type sub_row_type;
+	    linalg_traits<M>::sub_col_type, PT>::ref_type sub_row_type;
     typedef typename linalg_traits<M>::const_col_iterator const_row_iterator;
     typedef typename select_ref<abstract_null_type, typename
             linalg_traits<M>::col_iterator, PT>::ref_type row_iterator;
diff --git a/contrib/gmm/gmm_tri_solve.h b/contrib/gmm/gmm_tri_solve.h
index 2f7acf2582..ad2590f170 100644
--- a/contrib/gmm/gmm_tri_solve.h
+++ b/contrib/gmm/gmm_tri_solve.h
@@ -1,32 +1,33 @@
-// -*- c++ -*- (enables emacs c++ mode)
-//===========================================================================
-//
-// Copyright (C) 2002-2008 Yves Renard
-//
-// This file is a part of GETFEM++
-//
-// Getfem++  is  free software;  you  can  redistribute  it  and/or modify it
-// under  the  terms  of the  GNU  Lesser General Public License as published
-// by  the  Free Software Foundation;  either version 2.1 of the License,  or
-// (at your option) any later version.
-// This program  is  distributed  in  the  hope  that it will be useful,  but
-// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-// or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
-// License for more details.
-// You  should  have received a copy of the GNU Lesser General Public License
-// along  with  this program;  if not, write to the Free Software Foundation,
-// Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
-//
-// As a special exception, you may use this file as part of a free software
-// library without restriction.  Specifically, if other files instantiate
-// templates or use macros or inline functions from this file, or you compile
-// this file and link it with other files to produce an executable, this
-// file does not by itself cause the resulting executable to be covered by
-// the GNU General Public License.  This exception does not however
-// invalidate any other reasons why the executable file might be covered by
-// the GNU General Public License.
-//
-//===========================================================================
+/* -*- c++ -*- (enables emacs c++ mode) */
+/*===========================================================================
+
+ Copyright (C) 2002-2020 Yves Renard
+
+ This file is a part of GetFEM
+
+ GetFEM  is  free software;  you  can  redistribute  it  and/or modify it
+ under  the  terms  of the  GNU  Lesser General Public License as published
+ by  the  Free Software Foundation;  either version 3 of the License,  or
+ (at your option) any later version along with the GCC Runtime Library
+ Exception either version 3.1 or (at your option) any later version.
+ This program  is  distributed  in  the  hope  that it will be useful,  but
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+ License and GCC Runtime Library Exception for more details.
+ You  should  have received a copy of the GNU Lesser General Public License
+ along  with  this program;  if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+
+ As a special exception, you  may use  this file  as it is a part of a free
+ software  library  without  restriction.  Specifically,  if   other  files
+ instantiate  templates  or  use macros or inline functions from this file,
+ or  you compile this  file  and  link  it  with other files  to produce an
+ executable, this file  does  not  by itself cause the resulting executable
+ to be covered  by the GNU Lesser General Public License.  This   exception
+ does not  however  invalidate  any  other  reasons why the executable file
+ might be covered by the GNU Lesser General Public License.
+
+===========================================================================*/
 
 /**@file gmm_tri_solve.h
    @author Yves Renard
@@ -43,12 +44,12 @@ namespace gmm {
 
   template <typename TriMatrix, typename VecX>
   void upper_tri_solve__(const TriMatrix& T, VecX& x, size_t k,
-				col_major, abstract_sparse, bool is_unit) {
+			 col_major, abstract_sparse, bool is_unit) {
     typename linalg_traits<TriMatrix>::value_type x_j;
     for (int j = int(k) - 1; j >= 0; --j) {
       typedef typename linalg_traits<TriMatrix>::const_sub_col_type COL;
       COL c = mat_const_col(T, j);
-      typename linalg_traits<COL>::const_iterator 
+      typename linalg_traits<typename org_type<COL>::t>::const_iterator 
 	it = vect_const_begin(c), ite = vect_const_end(c);
       if (!is_unit) x[j] /= c[j];
       for (x_j = x[j]; it != ite ; ++it)
@@ -58,12 +59,12 @@ namespace gmm {
 
   template <typename TriMatrix, typename VecX>
   void upper_tri_solve__(const TriMatrix& T, VecX& x, size_t k,
-				col_major, abstract_dense, bool is_unit) {
+			 col_major, abstract_dense, bool is_unit) {
     typename linalg_traits<TriMatrix>::value_type x_j;
     for (int j = int(k) - 1; j >= 0; --j) {
       typedef typename linalg_traits<TriMatrix>::const_sub_col_type COL;
       COL c = mat_const_col(T, j);
-      typename linalg_traits<COL>::const_iterator
+      typename linalg_traits<typename org_type<COL>::t>::const_iterator
 	it = vect_const_begin(c), ite = it + j;
       typename linalg_traits<VecX>::iterator itx = vect_begin(x);
       if (!is_unit) x[j] /= c[j];
@@ -73,14 +74,14 @@ namespace gmm {
 
   template <typename TriMatrix, typename VecX>
   void lower_tri_solve__(const TriMatrix& T, VecX& x, size_t k,
-				col_major, abstract_sparse, bool is_unit) {
+			 col_major, abstract_sparse, bool is_unit) {
     typename linalg_traits<TriMatrix>::value_type x_j;
     // cout << "(lower col)The Tri Matrix = " << T << endl;
     // cout << "k = " << endl;
     for (int j = 0; j < int(k); ++j) {
       typedef typename linalg_traits<TriMatrix>::const_sub_col_type COL;
       COL c = mat_const_col(T, j);
-      typename linalg_traits<COL>::const_iterator 
+      typename linalg_traits<typename org_type<COL>::t>::const_iterator 
 	it = vect_const_begin(c), ite = vect_const_end(c);
       if (!is_unit) x[j] /= c[j];
       for (x_j = x[j]; it != ite ; ++it)
@@ -90,12 +91,12 @@ namespace gmm {
   
   template <typename TriMatrix, typename VecX>
   void lower_tri_solve__(const TriMatrix& T, VecX& x, size_t k,
-				col_major, abstract_dense, bool is_unit) {
+			 col_major, abstract_dense, bool is_unit) {
     typename linalg_traits<TriMatrix>::value_type x_j;
     for (int j = 0; j < int(k); ++j) {
       typedef typename linalg_traits<TriMatrix>::const_sub_col_type COL;
       COL c = mat_const_col(T, j);
-      typename linalg_traits<COL>::const_iterator 
+      typename linalg_traits<typename org_type<COL>::t>::const_iterator 
 	it = vect_const_begin(c) + (j+1), ite = vect_const_begin(c) + k;
       typename linalg_traits<VecX>::iterator itx = vect_begin(x) + (j+1);
       if (!is_unit) x[j] /= c[j];
@@ -106,7 +107,7 @@ namespace gmm {
 
   template <typename TriMatrix, typename VecX>
   void upper_tri_solve__(const TriMatrix& T, VecX& x, size_t k,
-				row_major, abstract_sparse, bool is_unit) {
+			 row_major, abstract_sparse, bool is_unit) {
     typedef typename linalg_traits<TriMatrix>::const_sub_row_type ROW;
     typename linalg_traits<TriMatrix>::value_type t;
     typename linalg_traits<TriMatrix>::const_row_iterator
@@ -114,7 +115,7 @@ namespace gmm {
     for (int i = int(k) - 1; i >= 0; --i) {
       --itr;
       ROW c = linalg_traits<TriMatrix>::row(itr);
-      typename linalg_traits<ROW>::const_iterator 
+      typename linalg_traits<typename org_type<ROW>::t>::const_iterator 
 	it = vect_const_begin(c), ite = vect_const_end(c);
       for (t = x[i]; it != ite; ++it)
 	if (int(it.index()) > i && it.index() < k) t -= (*it) * x[it.index()];
@@ -124,13 +125,13 @@ namespace gmm {
 
   template <typename TriMatrix, typename VecX>
   void upper_tri_solve__(const TriMatrix& T, VecX& x, size_t k,
-				row_major, abstract_dense, bool is_unit) {
+			 row_major, abstract_dense, bool is_unit) {
     typename linalg_traits<TriMatrix>::value_type t;
    
     for (int i = int(k) - 1; i >= 0; --i) {
       typedef typename linalg_traits<TriMatrix>::const_sub_row_type ROW;
       ROW c = mat_const_row(T, i);
-      typename linalg_traits<ROW>::const_iterator 
+      typename linalg_traits<typename org_type<ROW>::t>::const_iterator 
 	it = vect_const_begin(c) + (i + 1), ite = vect_const_begin(c) + k;
       typename linalg_traits<VecX>::iterator itx = vect_begin(x) + (i+1);
       
@@ -141,13 +142,13 @@ namespace gmm {
 
   template <typename TriMatrix, typename VecX>
   void lower_tri_solve__(const TriMatrix& T, VecX& x, size_t k,
-				row_major, abstract_sparse, bool is_unit) {
+			 row_major, abstract_sparse, bool is_unit) {
     typename linalg_traits<TriMatrix>::value_type t;
    
     for (int i = 0; i < int(k); ++i) {
       typedef typename linalg_traits<TriMatrix>::const_sub_row_type ROW;
       ROW c = mat_const_row(T, i);
-      typename linalg_traits<ROW>::const_iterator 
+      typename linalg_traits<typename org_type<ROW>::t>::const_iterator 
 	it = vect_const_begin(c), ite = vect_const_end(c);
 
       for (t = x[i]; it != ite; ++it)
@@ -158,13 +159,13 @@ namespace gmm {
 
   template <typename TriMatrix, typename VecX>
   void lower_tri_solve__(const TriMatrix& T, VecX& x, size_t k,
-				row_major, abstract_dense, bool is_unit) {
+			 row_major, abstract_dense, bool is_unit) {
     typename linalg_traits<TriMatrix>::value_type t;
    
     for (int i = 0; i < int(k); ++i) {
       typedef typename linalg_traits<TriMatrix>::const_sub_row_type ROW;
       ROW c = mat_const_row(T, i);
-      typename linalg_traits<ROW>::const_iterator 
+      typename linalg_traits<typename org_type<ROW>::t>::const_iterator 
 	it = vect_const_begin(c), ite = it + i;
       typename linalg_traits<VecX>::iterator itx = vect_begin(x);
 
diff --git a/contrib/gmm/gmm_vector.h b/contrib/gmm/gmm_vector.h
index f114a32aab..2e4919bf73 100644
--- a/contrib/gmm/gmm_vector.h
+++ b/contrib/gmm/gmm_vector.h
@@ -1,32 +1,33 @@
-// -*- c++ -*- (enables emacs c++ mode)
-//===========================================================================
-//
-// Copyright (C) 2002-2008 Yves Renard
-//
-// This file is a part of GETFEM++
-//
-// Getfem++  is  free software;  you  can  redistribute  it  and/or modify it
-// under  the  terms  of the  GNU  Lesser General Public License as published
-// by  the  Free Software Foundation;  either version 2.1 of the License,  or
-// (at your option) any later version.
-// This program  is  distributed  in  the  hope  that it will be useful,  but
-// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-// or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
-// License for more details.
-// You  should  have received a copy of the GNU Lesser General Public License
-// along  with  this program;  if not, write to the Free Software Foundation,
-// Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
-//
-// As a special exception, you may use this file as part of a free software
-// library without restriction.  Specifically, if other files instantiate
-// templates or use macros or inline functions from this file, or you compile
-// this file and link it with other files to produce an executable, this
-// file does not by itself cause the resulting executable to be covered by
-// the GNU General Public License.  This exception does not however
-// invalidate any other reasons why the executable file might be covered by
-// the GNU General Public License.
-//
-//===========================================================================
+/* -*- c++ -*- (enables emacs c++ mode) */
+/*===========================================================================
+
+ Copyright (C) 2002-2020 Yves Renard
+
+ This file is a part of GetFEM
+
+ GetFEM  is  free software;  you  can  redistribute  it  and/or modify it
+ under  the  terms  of the  GNU  Lesser General Public License as published
+ by  the  Free Software Foundation;  either version 3 of the License,  or
+ (at your option) any later version along with the GCC Runtime Library
+ Exception either version 3.1 or (at your option) any later version.
+ This program  is  distributed  in  the  hope  that it will be useful,  but
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+ License and GCC Runtime Library Exception for more details.
+ You  should  have received a copy of the GNU Lesser General Public License
+ along  with  this program;  if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+
+ As a special exception, you  may use  this file  as it is a part of a free
+ software  library  without  restriction.  Specifically,  if   other  files
+ instantiate  templates  or  use macros or inline functions from this file,
+ or  you compile this  file  and  link  it  with other files  to produce an
+ executable, this file  does  not  by itself cause the resulting executable
+ to be covered  by the GNU Lesser General Public License.  This   exception
+ does not  however  invalidate  any  other  reasons why the executable file
+ might be covered by the GNU Lesser General Public License.
+
+===========================================================================*/
 /**@file gmm_vector.h
    @author  Yves Renard <Yves.Renard@insa-lyon.fr>
    @date October 13, 2002.
@@ -52,70 +53,144 @@ namespace gmm {
 
     V *pm;
     size_type l;
-    
+
     public :
 
     operator T() const { return pm->r(l); }
     ref_elt_vector(V *p, size_type ll) : pm(p), l(ll) {}
-    inline ref_elt_vector &operator =(T v)
-      { (*pm).w(l,v); return *this; }
     inline bool operator ==(T v) const { return ((*pm).r(l) == v); }
     inline bool operator !=(T v) const { return ((*pm).r(l) != v); }
+    inline bool operator ==(std::complex<T> v) const
+    { return ((*pm).r(l) == v); }
+    inline bool operator !=(std::complex<T> v) const
+    { return ((*pm).r(l) != v); }
     inline ref_elt_vector &operator +=(T v)
-      { (*pm).w(l,(*pm).r(l) + v); return *this; }
+    { (*pm).wa(l, v); return *this; }
     inline ref_elt_vector &operator -=(T v)
-      { (*pm).w(l,(*pm).r(l) - v); return *this; }
+    { (*pm).wa(l, -v); return *this; }
     inline ref_elt_vector &operator /=(T v)
-      { (*pm).w(l,(*pm).r(l) / v); return *this; }
+    { (*pm).w(l,(*pm).r(l) / v); return *this; }
     inline ref_elt_vector &operator *=(T v)
-      { (*pm).w(l,(*pm).r(l) * v); return *this; }
+    { (*pm).w(l,(*pm).r(l) * v); return *this; }
     inline ref_elt_vector &operator =(const ref_elt_vector &re)
-      { *this = T(re); return *this; }
-    T operator +()    { return  T(*this);   } // necessary for unknow reason
-    T operator -()    { return -T(*this);   } // necessary for unknow reason
-    T operator +(T v) { return T(*this)+ v; } // necessary for unknow reason
-    T operator -(T v) { return T(*this)- v; } // necessary for unknow reason
-    T operator *(T v) { return T(*this)* v; } // necessary for unknow reason
-    T operator /(T v) { return T(*this)/ v; } // necessary for unknow reason
-  };  
-  
-  
+    { *this = T(re); return *this; }
+    inline ref_elt_vector &operator =(T v)
+    { (*pm).w(l,v); return *this; }
+    T operator +()    { return  T(*this);   }
+    T operator -()    { return -T(*this);   }
+    T operator +(T v) { return T(*this)+ v; }
+    T operator -(T v) { return T(*this)- v; }
+    T operator *(T v) { return T(*this)* v; }
+    T operator /(T v) { return T(*this)/ v; }
+    std::complex<T> operator +(std::complex<T> v) { return T(*this)+ v; }
+    std::complex<T> operator -(std::complex<T> v) { return T(*this)- v; }
+    std::complex<T> operator *(std::complex<T> v) { return T(*this)* v; }
+    std::complex<T> operator /(std::complex<T> v) { return T(*this)/ v; }
+  };
+
+  template<typename T, typename V> class ref_elt_vector<std::complex<T>,V> {
+
+    V *pm;
+    size_type l;
+
+    public :
+
+    operator std::complex<T>() const { return pm->r(l); }
+    ref_elt_vector(V *p, size_type ll) : pm(p), l(ll) {}
+    ref_elt_vector(const ref_elt_vector &re) : pm(re.pm), l(re.l) {}
+    inline bool operator ==(std::complex<T> v) const
+    { return ((*pm).r(l) == v); }
+    inline bool operator !=(std::complex<T> v) const
+    { return ((*pm).r(l) != v); }
+    inline bool operator ==(T v) const { return ((*pm).r(l) == v); }
+    inline bool operator !=(T v) const { return ((*pm).r(l) != v); }
+    inline ref_elt_vector &operator +=(std::complex<T> v)
+    { (*pm).w(l,(*pm).r(l) + v); return *this; }
+    inline ref_elt_vector &operator -=(std::complex<T> v)
+    { (*pm).w(l,(*pm).r(l) - v); return *this; }
+    inline ref_elt_vector &operator /=(std::complex<T> v)
+    { (*pm).w(l,(*pm).r(l) / v); return *this; }
+    inline ref_elt_vector &operator *=(std::complex<T> v)
+    { (*pm).w(l,(*pm).r(l) * v); return *this; }
+    inline ref_elt_vector &operator =(const ref_elt_vector &re)
+    { *this = std::complex<T>(re); return *this; }
+    inline ref_elt_vector &operator =(std::complex<T> v)
+    { (*pm).w(l,v); return *this; }
+    inline ref_elt_vector &operator =(T v)
+    { (*pm).w(l,std::complex<T>(v)); return *this; }
+    inline ref_elt_vector &operator +=(T v)
+    { (*pm).w(l,(*pm).r(l) + v); return *this; }
+    inline ref_elt_vector &operator -=(T v)
+    { (*pm).w(l,(*pm).r(l) - v); return *this; }
+    inline ref_elt_vector &operator /=(T v)
+    { (*pm).w(l,(*pm).r(l) / v); return *this; }
+    inline ref_elt_vector &operator *=(T v)
+    { (*pm).w(l,(*pm).r(l) * v); return *this; }
+    std::complex<T> operator +()    { return  std::complex<T>(*this);   }
+    std::complex<T> operator -()    { return -std::complex<T>(*this);   }
+    std::complex<T> operator +(T v) { return std::complex<T>(*this)+ v; }
+    std::complex<T> operator -(T v) { return std::complex<T>(*this)- v; }
+    std::complex<T> operator *(T v) { return std::complex<T>(*this)* v; }
+    std::complex<T> operator /(T v) { return std::complex<T>(*this)/ v; }
+    std::complex<T> operator +(std::complex<T> v)
+    { return std::complex<T>(*this)+ v; }
+    std::complex<T> operator -(std::complex<T> v)
+    { return std::complex<T>(*this)- v; }
+    std::complex<T> operator *(std::complex<T> v)
+    { return std::complex<T>(*this)* v; }
+    std::complex<T> operator /(std::complex<T> v)
+    { return std::complex<T>(*this)/ v; }
+  };
+
+
   template<typename T, typename V> inline
   bool operator ==(T v, const ref_elt_vector<T, V> &re) { return (v==T(re)); }
   template<typename T, typename V> inline
   bool operator !=(T v, const ref_elt_vector<T, V> &re) { return (v!=T(re)); }
   template<typename T, typename V> inline
-  T &operator +=(T &v, const ref_elt_vector<T, V> &re) 
+  T &operator +=(T &v, const ref_elt_vector<T, V> &re)
   { v += T(re); return v; }
   template<typename T, typename V> inline
   T &operator -=(T &v, const ref_elt_vector<T, V> &re)
   { v -= T(re); return v; }
   template<typename T, typename V> inline
-  T &operator *=(T &v, const ref_elt_vector<T, V> &re) 
+  T &operator *=(T &v, const ref_elt_vector<T, V> &re)
   { v *= T(re); return v; }
   template<typename T, typename V> inline
   T &operator /=(T &v, const ref_elt_vector<T, V> &re)
   { v /= T(re); return v; }
   template<typename T, typename V> inline
-  T operator +(const ref_elt_vector<T, V> &re) { return T(re); }
+  T operator +(T v, const ref_elt_vector<T, V> &re) { return v+ T(re); }
+  template<typename T, typename V> inline
+  T operator -(T v, const ref_elt_vector<T, V> &re) { return v- T(re); }
   template<typename T, typename V> inline
-  T operator -(const ref_elt_vector<T, V> &re) { return -T(re); }
+  T operator *(T v, const ref_elt_vector<T, V> &re) { return v* T(re); }
   template<typename T, typename V> inline
-  T operator +(const ref_elt_vector<T, V> &re, T v) { return T(re)+ v; }
+  T operator /(T v, const ref_elt_vector<T, V> &re) { return v/ T(re); }
   template<typename T, typename V> inline
-  T operator +(T v, const ref_elt_vector<T, V> &re) { return v+ T(re); }
+  std::complex<T> operator +(std::complex<T> v, const ref_elt_vector<T, V> &re)
+  { return v+ T(re); }
   template<typename T, typename V> inline
-  T operator -(const ref_elt_vector<T, V> &re, T v) { return T(re)- v; }
+  std::complex<T> operator -(std::complex<T> v, const ref_elt_vector<T, V> &re)
+  { return v- T(re); }
   template<typename T, typename V> inline
-  T operator -(T v, const ref_elt_vector<T, V> &re) { return v- T(re); }
-  template<typename T, typename V>  inline
-  T operator *(const ref_elt_vector<T, V> &re, T v) { return T(re)* v; }
+  std::complex<T> operator *(std::complex<T> v, const ref_elt_vector<T, V> &re)
+  { return v* T(re); }
   template<typename T, typename V> inline
-  T operator *(T v, const ref_elt_vector<T, V> &re) { return v* T(re); }
+  std::complex<T> operator /(std::complex<T> v, const ref_elt_vector<T, V> &re)
+  { return v/ T(re); }
   template<typename T, typename V> inline
-  T operator /(const ref_elt_vector<T, V> &re, T v) { return T(re)/ v; }
+  std::complex<T> operator +(T v, const ref_elt_vector<std::complex<T>, V> &re)
+  { return v+ std::complex<T>(re); }
   template<typename T, typename V> inline
-  T operator /(T v, const ref_elt_vector<T, V> &re) { return v/ T(re); }
+  std::complex<T> operator -(T v, const ref_elt_vector<std::complex<T>, V> &re)
+  { return v- std::complex<T>(re); }
+  template<typename T, typename V> inline
+  std::complex<T> operator *(T v, const ref_elt_vector<std::complex<T>, V> &re)
+  { return v* std::complex<T>(re); }
+  template<typename T, typename V> inline
+  std::complex<T> operator /(T v, const ref_elt_vector<std::complex<T>, V> &re)
+  { return v/ std::complex<T>(re); }
   template<typename T, typename V> inline
   typename number_traits<T>::magnitude_type
   abs(const ref_elt_vector<T, V> &re) { return gmm::abs(T(re)); }
@@ -135,14 +210,477 @@ namespace gmm {
   typename number_traits<T>::magnitude_type
   imag(const ref_elt_vector<T, V> &re) { return gmm::imag(T(re)); }
 
-  
+  /*************************************************************************/
+  /*                                                                       */
+  /* Class dsvector: sparse vector optimized for random write operations   */
+  /* with constant complexity for read and write operations.               */
+  /* Based on distribution sort principle.                                 */
+  /* Cheap for densely populated vectors.                                  */
+  /*                                                                       */
+  /*************************************************************************/
+
+  template<typename T> class dsvector;
+
+  template<typename T> struct dsvector_iterator {
+    size_type i;    // Current index.
+    T* p;           // Pointer to the current position.
+    dsvector<T> *v; // Pointer to the vector.
+
+    typedef T                   value_type;
+    typedef value_type*         pointer;
+    typedef const value_type*   const_pointer;
+    typedef value_type&         reference;
+    // typedef size_t              size_type;
+    typedef ptrdiff_t           difference_type;
+    typedef std::bidirectional_iterator_tag iterator_category;
+    typedef dsvector_iterator<T> iterator;
+
+    reference operator *() const { return *p; }
+    pointer operator->() const { return &(operator*()); }
+
+    iterator &operator ++() {
+      for (size_type k = (i & 15); k < 15; ++k)
+        { ++p; ++i; if (*p != T(0)) return *this; }
+      v->next_pos(*(const_cast<const_pointer *>(&(p))), i);
+      return *this;
+    }
+    iterator operator ++(int) { iterator tmp = *this; ++(*this); return tmp; }
+    iterator &operator --() {
+      for (size_type k = (i & 15); k > 0; --k)
+        { --p; --i; if (*p != T(0)) return *this; }
+      v->previous_pos(p, i);
+      return *this;
+    }
+    iterator operator --(int) { iterator tmp = *this; --(*this); return tmp; }
+
+    bool operator ==(const iterator &it) const
+    { return (i == it.i && p == it.p && v == it.v); }
+    bool operator !=(const iterator &it) const
+    { return !(it == *this); }
+
+    size_type index() const { return i; }
+
+    dsvector_iterator() : i(size_type(-1)), p(0), v(0) {}
+    dsvector_iterator(dsvector<T> &w) : i(size_type(-1)), p(0), v(&w) {};
+  };
+
+
+  template<typename T> struct dsvector_const_iterator {
+    size_type i;          // Current index.
+    const T* p;           // Pointer to the current position.
+    const dsvector<T> *v; // Pointer to the vector.
+
+    typedef T                   value_type;
+    typedef const value_type*   pointer;
+    typedef const value_type&   reference;
+    // typedef size_t           size_type;
+    typedef ptrdiff_t           difference_type;
+    typedef std::bidirectional_iterator_tag iterator_category;
+    typedef dsvector_const_iterator<T> iterator;
+
+    reference operator *() const { return *p; }
+    pointer operator->() const { return &(operator*()); }
+    iterator &operator ++() {
+      for (size_type k = (i & 15); k < 15; ++k)
+        { ++p; ++i; if (*p != T(0)) return *this; }
+      v->next_pos(p, i);
+      return *this;
+    }
+    iterator operator ++(int) { iterator tmp = *this; ++(*this); return tmp; }
+    iterator &operator --() {
+      for (size_type k = (i & 15); k > 0; --k)
+        { --p; --i; if (*p != T(0)) return *this; }
+      v->previous_pos(p, i);
+      return *this;
+    }
+    iterator operator --(int) { iterator tmp = *this; --(*this); return tmp; }
+
+    bool operator ==(const iterator &it) const
+    { return (i == it.i && p == it.p && v == it.v); }
+    bool operator !=(const iterator &it) const
+    { return !(it == *this); }
+
+    size_type index() const { return i; }
+
+    dsvector_const_iterator() : i(size_type(-1)), p(0) {}
+    dsvector_const_iterator(const dsvector_iterator<T> &it)
+      : i(it.i), p(it.p), v(it.v) {}
+    dsvector_const_iterator(const dsvector<T> &w)
+      : i(size_type(-1)), p(0), v(&w) {};
+  };
+
+
+  /**
+     Sparse vector built on distribution sort principle.
+     Read and write access have a constant complexity depending only on the
+     vector size.
+  */
+  template<typename T> class dsvector {
+
+    typedef dsvector_iterator<T>       iterator;
+    typedef dsvector_const_iterator<T> const_iterator;
+    typedef dsvector<T>                this_type;
+    typedef T *                        pointer;
+    typedef const T *                  const_pointer;
+    typedef void *                     void_pointer;
+    typedef const void *               const_void_pointer;
+
+  protected:
+    size_type    n;         // Potential vector size
+    size_type    depth;     // Number of row of pointer arrays
+    size_type    mask;      // Mask for the first pointer array
+    size_type    shift;     // Shift for the first pointer array
+    void_pointer root_ptr;  // Root pointer
+
+    const T *read_access(size_type i) const {
+      GMM_ASSERT1(i < n, "index out of range");
+      size_type my_mask = mask, my_shift = shift;
+      void_pointer p = root_ptr;
+      if (!p) return 0;
+      for (size_type k = 0; k < depth; ++k) {
+        p = ((void **)(p))[(i & my_mask) >> my_shift];
+        if (!p) return 0;
+        my_mask = (my_mask >> 4);
+        my_shift -= 4;
+      }
+      GMM_ASSERT1(my_shift == 0, "internal error");
+      GMM_ASSERT1(my_mask == 15, "internal error");
+      return &(((const T *)(p))[i & 15]);
+    }
+
+    T *write_access(size_type i) {
+      GMM_ASSERT1(i < n, "index " << i << " out of range (size " << n << ")");
+      size_type my_mask = mask, my_shift = shift;
+      if (!root_ptr) {
+        if (depth) {
+          root_ptr = new void_pointer[16];
+          std::memset(root_ptr, 0, 16*sizeof(void_pointer));
+        } else {
+          root_ptr = new T[16];
+          for (size_type l = 0; l < 16; ++l) ((T *)(root_ptr))[l] = T(0);
+        }
+      }
+
+      void_pointer p = root_ptr;
+      for (size_type k = 0; k < depth; ++k) {
+        size_type j = (i & my_mask) >> my_shift;
+        void_pointer q = ((void_pointer *)(p))[j];
+        if (!q) {
+          if (k+1 != depth) {
+            q = new void_pointer[16];
+            std::memset(q, 0, 16*sizeof(void_pointer));
+          } else {
+            q = new T[16];
+            for (size_type l = 0; l < 16; ++l) ((T *)(q))[l] = T(0);
+          }
+          ((void_pointer *)(p))[j] = q;
+        }
+        p = q;
+        my_mask = (my_mask >> 4);
+        my_shift -= 4;
+      }
+      GMM_ASSERT1(my_shift == 0, "internal error");
+      GMM_ASSERT1(my_mask == 15, "internal error " << my_mask);
+      return &(((T *)(p))[i & 15]);
+    }
+
+    void init(size_type n_) {
+      n = n_; depth = 0; shift = 0; mask = 1; if (n_) --n_;
+      while (n_) { n_ /= 16; ++depth; shift += 4; mask *= 16; }
+      mask--; if (shift) shift -= 4; if (depth) --depth;
+      root_ptr = 0;
+    }
+
+    void rec_del(void_pointer p, size_type my_depth) {
+      if (my_depth) {
+        for (size_type k = 0; k < 16; ++k)
+          if (((void_pointer *)(p))[k])
+            rec_del(((void_pointer *)(p))[k], my_depth-1);
+        delete[] ((void_pointer *)(p));
+      } else {
+        delete[] ((T *)(p));
+      }
+    }
+
+    void rec_clean(void_pointer p, size_type my_depth, double eps) {
+      if (my_depth) {
+        for (size_type k = 0; k < 16; ++k)
+          if (((void_pointer *)(p))[k])
+            rec_clean(((void_pointer *)(p))[k], my_depth-1, eps);
+      } else {
+        for (size_type k = 0; k < 16; ++k)
+          if (gmm::abs(((T *)(p))[k]) <= eps) ((T *)(p))[k] = T(0);
+      }
+    }
+
+    void rec_clean_i(void_pointer p, size_type my_depth, size_type my_mask,
+                     size_type i, size_type base) {
+      if (my_depth) {
+        my_mask = (my_mask >> 4);
+        for (size_type k = 0; k < 16; ++k)
+          if (((void_pointer *)(p))[k] && (base + (k+1)*(mask+1)) >= i)
+            rec_clean_i(((void_pointer *)(p))[k], my_depth-1, my_mask,
+                        i, base + k*(my_mask+1));
+      } else {
+        for (size_type k = 0; k < 16; ++k)
+          if (base+k > i) ((T *)(p))[k] = T(0);
+      }
+    }
+
+
+    size_type rec_nnz(void_pointer p, size_type my_depth) const {
+      size_type nn = 0;
+      if (my_depth) {
+        for (size_type k = 0; k < 16; ++k)
+          if (((void_pointer *)(p))[k])
+            nn += rec_nnz(((void_pointer *)(p))[k], my_depth-1);
+      } else {
+        for (size_type k = 0; k < 16; ++k)
+          if (((const T *)(p))[k] != T(0)) nn++;
+      }
+      return nn;
+    }
+
+    void copy_rec(void_pointer &p, const_void_pointer q, size_type my_depth) {
+      if (my_depth) {
+        p = new void_pointer[16];
+        std::memset(p, 0, 16*sizeof(void_pointer));
+        for (size_type l = 0; l < 16; ++l)
+          if (((const const_void_pointer *)(q))[l])
+            copy_rec(((void_pointer *)(p))[l],
+                     ((const const_void_pointer *)(q))[l], my_depth-1);
+      } else {
+        p = new T[16];
+        for (size_type l = 0; l < 16; ++l) ((T *)(p))[l] = ((const T *)(q))[l];
+      }
+    }
+
+    void copy(const dsvector<T> &v) {
+      if (root_ptr) rec_del(root_ptr, depth);
+      root_ptr = 0;
+      mask = v.mask; depth = v.depth; n = v.n; shift = v.shift;
+      if (v.root_ptr) copy_rec(root_ptr, v.root_ptr, depth);
+    }
+
+    void next_pos_rec(void_pointer p, size_type my_depth, size_type my_mask,
+                      const_pointer &pp, size_type &i, size_type base) const {
+      size_type ii = i;
+      if (my_depth) {
+        my_mask = (my_mask >> 4);
+        for (size_type k = 0; k < 16; ++k)
+          if (((void_pointer *)(p))[k] && (base + (k+1)*(my_mask+1)) >= i) {
+            next_pos_rec(((void_pointer *)(p))[k], my_depth-1, my_mask,
+                         pp, i, base + k*(my_mask+1));
+            if (i != size_type(-1)) return; else i = ii;
+        }
+        i = size_type(-1); pp = 0;
+      } else {
+        for (size_type k = 0; k < 16; ++k)
+          if (base+k > i && ((const_pointer)(p))[k] != T(0))
+            { i = base+k; pp = &(((const_pointer)(p))[k]); return; }
+        i = size_type(-1); pp = 0;
+      }
+    }
+
+    void previous_pos_rec(void_pointer p, size_type my_depth, size_type my_mask,
+                          const_pointer &pp, size_type &i,
+                          size_type base) const {
+      size_type ii = i;
+      if (my_depth) {
+        my_mask = (my_mask >> 4);
+        for (size_type k = 15; k != size_type(-1); --k)
+          if (((void_pointer *)(p))[k] && ((base + k*(my_mask+1)) < i)) {
+            previous_pos_rec(((void_pointer *)(p))[k], my_depth-1,
+                             my_mask, pp, i, base + k*(my_mask+1));
+            if (i != size_type(-1)) return; else i = ii;
+        }
+        i = size_type(-1); pp = 0;
+      } else {
+        for (size_type k = 15; k != size_type(-1); --k)
+          if (base+k < i && ((const_pointer)(p))[k] != T(0))
+            { i = base+k; pp = &(((const_pointer)(p))[k]); return; }
+        i = size_type(-1); pp = 0;
+      }
+    }
+
+
+  public:
+    void clean(double eps) { if (root_ptr) rec_clean(root_ptr, depth); }
+    void resize(size_type n_) {
+      if (n_ != n) {
+        n = n_;
+        if (n_ < n) { // Depth unchanged (a choice)
+          if (root_ptr) rec_clean_i(root_ptr, depth, mask, n_, 0);
+        } else {
+          // may change the depth (add some levels)
+          size_type my_depth = 0, my_shift = 0, my_mask = 1; if (n_) --n_;
+          while (n_) { n_ /= 16; ++my_depth; my_shift += 4; my_mask *= 16; }
+          my_mask--; if (my_shift) my_shift -= 4; if (my_depth) --my_depth;
+          if (my_depth > depth || depth == 0) {
+            if (root_ptr) {
+              for (size_type k = depth; k < my_depth; ++k) {
+                void_pointer *q = new void_pointer [16];
+                std::memset(q, 0, 16*sizeof(void_pointer));
+                q[0] = root_ptr; root_ptr = q;
+              }
+            }
+            mask = my_mask; depth = my_depth; shift = my_shift;
+          }
+        }
+      }
+    }
+
+    void clear() { if (root_ptr) rec_del(root_ptr, depth); root_ptr = 0; }
+
+    void next_pos(const_pointer &pp, size_type &i) const {
+      if (!root_ptr || i >= n) { pp = 0, i = size_type(-1); return; }
+      next_pos_rec(root_ptr, depth, mask, pp, i, 0);
+    }
+
+    void previous_pos(const_pointer &pp, size_type &i) const {
+      if (!root_ptr) { pp = 0, i = size_type(-1); return; }
+      if (i == size_type(-1)) { i = n; }
+      previous_pos_rec(root_ptr, depth, mask, pp, i, 0);
+    }
+
+    iterator begin() {
+      iterator it(*this);
+      if (n && root_ptr) {
+        it.i = 0; it.p = const_cast<T *>(read_access(0));
+        if (!(it.p) || *(it.p) == T(0))
+          next_pos(*(const_cast<const_pointer *>(&(it.p))), it.i);
+      }
+      return it;
+    }
+
+    iterator end() { return iterator(*this); }
+
+    const_iterator begin() const {
+      const_iterator it(*this);
+      if (n && root_ptr) {
+        it.i = 0; it.p = read_access(0);
+        if (!(it.p) || *(it.p) == T(0)) next_pos(it.p, it.i);
+      }
+      return it;
+    }
+
+    const_iterator end() const { return const_iterator(*this); }
+
+    inline ref_elt_vector<T, dsvector<T> > operator [](size_type c)
+    { return ref_elt_vector<T, dsvector<T> >(this, c); }
+
+    inline void w(size_type c, const T &e) {
+      if (e == T(0)) { if (read_access(c)) *(write_access(c)) = e; }
+      else *(write_access(c)) = e;
+    }
+
+    inline void wa(size_type c, const T &e)
+    { if (e != T(0)) { *(write_access(c)) += e; } }
+
+    inline T r(size_type c) const
+    { const T *p = read_access(c); if (p) return *p; else return T(0); }
+
+    inline T operator [](size_type c) const { return r(c); }
+
+    size_type nnz() const
+    { if (root_ptr) return rec_nnz(root_ptr, depth); else return 0; }
+    size_type size() const { return n; }
+
+    void swap(dsvector<T> &v) {
+      std::swap(n, v.n); std::swap(root_ptr, v.root_ptr);
+      std::swap(depth, v.depth); std::swap(shift, v.shift);
+      std::swap(mask, v.mask);
+    }
+
+    /* Constructors */
+    dsvector(const dsvector<T> &v) { init(0); copy(v); }
+    dsvector<T> &operator =(const dsvector<T> &v) { copy(v); return *this; }
+    explicit dsvector(size_type l){ init(l); }
+    dsvector() { init(0); }
+    ~dsvector() { if (root_ptr) rec_del(root_ptr, depth); root_ptr = 0; }
+  };
+
+  template <typename T> struct linalg_traits<dsvector<T>> {
+    typedef dsvector<T> this_type;
+    typedef this_type origin_type;
+    typedef linalg_false is_reference;
+    typedef abstract_vector linalg_type;
+    typedef T value_type;
+    typedef ref_elt_vector<T, dsvector<T> > reference;
+    typedef dsvector_iterator<T>  iterator;
+    typedef dsvector_const_iterator<T> const_iterator;
+    typedef abstract_sparse storage_type;
+    typedef linalg_true index_sorted;
+    static size_type size(const this_type &v) { return v.size(); }
+    static iterator begin(this_type &v) { return v.begin(); }
+    static const_iterator begin(const this_type &v) { return v.begin(); }
+    static iterator end(this_type &v) { return v.end(); }
+    static const_iterator end(const this_type &v) { return v.end(); }
+    static origin_type* origin(this_type &v) { return &v; }
+    static const origin_type* origin(const this_type &v) { return &v; }
+    static void clear(origin_type* o, const iterator &, const iterator &)
+    { o->clear(); }
+    static void do_clear(this_type &v) { v.clear(); }
+    static value_type access(const origin_type *o, const const_iterator &,
+                             const const_iterator &, size_type i)
+    { return (*o)[i]; }
+    static reference access(origin_type *o, const iterator &, const iterator &,
+                            size_type i)
+    { return (*o)[i]; }
+    static void resize(this_type &v, size_type n) { v.resize(n); }
+  };
+
+  template<typename T> std::ostream &operator <<
+  (std::ostream &o, const dsvector<T>& v) { gmm::write(o,v); return o; }
+
+  /******* Optimized operations for dsvector<T> ****************************/
+
+  template <typename T> inline void copy(const dsvector<T> &v1,
+                                         dsvector<T> &v2) {
+    GMM_ASSERT2(v1.size() == v2.size(), "dimensions mismatch");
+    v2 = v1;
+  }
+  template <typename T> inline void copy(const dsvector<T> &v1,
+                                         const dsvector<T> &v2) {
+    GMM_ASSERT2(v1.size() == v2.size(), "dimensions mismatch");
+    v2 = const_cast<dsvector<T> &>(v1);
+  }
+ template <typename T> inline
+  void copy(const dsvector<T> &v1, const simple_vector_ref<dsvector<T> *> &v2){
+    simple_vector_ref<dsvector<T> *>
+      *svr = const_cast<simple_vector_ref<dsvector<T> *> *>(&v2);
+    dsvector<T>
+      *pv = const_cast<dsvector<T> *>((v2.origin));
+    GMM_ASSERT2(vect_size(v1) == vect_size(v2), "dimensions mismatch");
+    *pv = v1; svr->begin_ = vect_begin(*pv); svr->end_ = vect_end(*pv);
+  }
+  template <typename T> inline
+  void copy(const simple_vector_ref<const dsvector<T> *> &v1,
+            dsvector<T> &v2)
+  { copy(*(v1.origin), v2); }
+  template <typename T> inline
+  void copy(const simple_vector_ref<dsvector<T> *> &v1, dsvector<T> &v2)
+  { copy(*(v1.origin), v2); }
+  template <typename T> inline
+  void copy(const simple_vector_ref<dsvector<T> *> &v1,
+            const simple_vector_ref<dsvector<T> *> &v2)
+  { copy(*(v1.origin), v2); }
+  template <typename T> inline
+  void copy(const simple_vector_ref<const dsvector<T> *> &v1,
+            const simple_vector_ref<dsvector<T> *> &v2)
+  { copy(*(v1.origin), v2); }
+
+  template <typename T>
+  inline size_type nnz(const dsvector<T>& l) { return l.nnz(); }
 
   /*************************************************************************/
   /*                                                                       */
-  /* Class wsvector: sparse vector optimized for random write operations.  */
+  /* Class wsvector: sparse vector optimized for random write operations,  */
+  /* with log(n) complexity for read and write operations.                 */
+  /* Based on std::map                                                     */
   /*                                                                       */
   /*************************************************************************/
-  
+
   template<typename T> struct wsvector_iterator
     : public std::map<size_type, T>::iterator {
     typedef typename std::map<size_type, T>::iterator base_it_type;
@@ -152,12 +690,12 @@ namespace gmm {
     // typedef size_t              size_type;
     typedef ptrdiff_t           difference_type;
     typedef std::bidirectional_iterator_tag iterator_category;
-    
+
     reference operator *() const { return (base_it_type::operator*()).second; }
     pointer operator->() const { return &(operator*()); }
-    size_type index(void) const { return (base_it_type::operator*()).first; }
+    size_type index() const { return (base_it_type::operator*()).first; }
 
-    wsvector_iterator(void) {}
+    wsvector_iterator() {}
     wsvector_iterator(const base_it_type &it) : base_it_type(it) {}
   };
 
@@ -170,14 +708,14 @@ namespace gmm {
     // typedef size_t              size_type;
     typedef ptrdiff_t           difference_type;
     typedef std::bidirectional_iterator_tag iterator_category;
-    
+
     reference operator *() const { return (base_it_type::operator*()).second; }
     pointer operator->() const { return &(operator*()); }
-    size_type index(void) const { return (base_it_type::operator*()).first; }
+    size_type index() const { return (base_it_type::operator*()).first; }
 
-    wsvector_const_iterator(void) {}
+    wsvector_const_iterator() {}
     wsvector_const_iterator(const wsvector_iterator<T> &it)
-      : base_it_type(it) {}
+      : base_it_type(typename std::map<size_type, T>::iterator(it)) {}
     wsvector_const_iterator(const base_it_type &it) : base_it_type(it) {}
   };
 
@@ -188,7 +726,7 @@ namespace gmm {
   */
   template<typename T> class wsvector : public std::map<size_type, T> {
   public:
-    
+
     typedef typename std::map<int, T>::size_type size_type;
     typedef std::map<size_type, T> base_type;
     typedef typename base_type::iterator iterator;
@@ -196,20 +734,29 @@ namespace gmm {
 
   protected:
     size_type nbl;
-    
+
   public:
     void clean(double eps);
     void resize(size_type);
-    
+
     inline ref_elt_vector<T, wsvector<T> > operator [](size_type c)
     { return ref_elt_vector<T, wsvector<T> >(this, c); }
 
     inline void w(size_type c, const T &e) {
       GMM_ASSERT2(c < nbl, "out of range");
-      if (e == T(0)) { base_type::erase(c); }
+      if (e == T(0)) { this->erase(c); }
       else base_type::operator [](c) = e;
     }
 
+    inline void wa(size_type c, const T &e) {
+      GMM_ASSERT2(c < nbl, "out of range");
+      if (e != T(0)) {
+        iterator it = this->lower_bound(c);
+        if (it != this->end() && it->first == c) it->second += e;
+        else base_type::operator [](c) = e;
+      }
+    }
+
     inline T r(size_type c) const {
       GMM_ASSERT2(c < nbl, "out of range");
       const_iterator it = this->lower_bound(c);
@@ -218,31 +765,31 @@ namespace gmm {
     }
 
     inline T operator [](size_type c) const { return r(c); }
-    
-    size_type nb_stored(void) const { return base_type::size(); }
-    size_type size(void) const { return nbl; }
+
+    size_type nb_stored() const { return base_type::size(); }
+    size_type size() const { return nbl; }
 
     void swap(wsvector<T> &v)
     { std::swap(nbl, v.nbl); std::map<size_type, T>::swap(v); }
-				       
 
-    /* Constructeurs */
+
+    /* Constructors */
     void init(size_type l) { nbl = l; this->clear(); }
     explicit wsvector(size_type l){ init(l); }
-    wsvector(void) { init(0); }
+    wsvector() { init(0); }
   };
 
   template<typename T>  void wsvector<T>::clean(double eps) {
     iterator it = this->begin(), itf = it, ite = this->end();
     while (it != ite) {
-      ++itf; if (gmm::abs(it->second) <= eps) erase(it); it = itf;
+      ++itf; if (gmm::abs(it->second) <= eps) this->erase(it); it = itf;
     }
   }
 
   template<typename T>  void wsvector<T>::resize(size_type n) {
     if (n < nbl) {
       iterator it = this->begin(), itf = it, ite = this->end();
-      while (it != ite) { ++itf; if (it->first >= n) erase(it); it = itf; }
+      while (it != ite) { ++itf; if (it->first >= n) this->erase(it); it=itf; }
     }
     nbl = n;
   }
@@ -269,10 +816,10 @@ namespace gmm {
     { o->clear(); }
     static void do_clear(this_type &v) { v.clear(); }
     static value_type access(const origin_type *o, const const_iterator &,
-			     const const_iterator &, size_type i)
+                             const const_iterator &, size_type i)
     { return (*o)[i]; }
     static reference access(origin_type *o, const iterator &, const iterator &,
-			    size_type i)
+                            size_type i)
     { return (*o)[i]; }
     static void resize(this_type &v, size_type n) { v.resize(n); }
   };
@@ -283,7 +830,7 @@ namespace gmm {
   /******* Optimized BLAS for wsvector<T> **********************************/
 
   template <typename T> inline void copy(const wsvector<T> &v1,
-					 wsvector<T> &v2) {
+                                         wsvector<T> &v2) {
     GMM_ASSERT2(vect_size(v1) == vect_size(v2), "dimensions mismatch");
     v2 = v1;
   }
@@ -298,7 +845,7 @@ namespace gmm {
   }
   template <typename T> inline
   void copy(const simple_vector_ref<const wsvector<T> *> &v1,
-	    wsvector<T> &v2)
+            wsvector<T> &v2)
   { copy(*(v1.origin), v2); }
   template <typename T> inline
   void copy(const simple_vector_ref<wsvector<T> *> &v1, wsvector<T> &v2)
@@ -307,9 +854,9 @@ namespace gmm {
   template <typename T> inline void clean(wsvector<T> &v, double eps) {
     typedef typename number_traits<T>::magnitude_type R;
     typename wsvector<T>::iterator it = v.begin(), ite = v.end(), itc;
-    while (it != ite) 
+    while (it != ite)
       if (gmm::abs((*it).second) <= R(eps))
-	{ itc=it; ++it; v.erase(itc); } else ++it; 
+        { itc=it; ++it; v.erase(itc); } else ++it;
   }
 
   template <typename T>
@@ -333,9 +880,9 @@ namespace gmm {
 
   template<typename T> struct elt_rsvector_ {
     size_type c; T e;
-    /* e is initialized by default to avoid some false warnings of valgrind..
+    /* e is initialized by default to avoid some false warnings of valgrind.
        (from http://valgrind.org/docs/manual/mc-manual.html:
-      
+
        When memory is read into the CPU's floating point registers, the
        relevant V bits are read from memory and they are immediately
        checked. If any are invalid, an uninitialised value error is
@@ -344,7 +891,7 @@ namespace gmm {
        does not have to track the validity status of the floating-point
        registers.
     */
-    elt_rsvector_(void) : e(0) {}
+    elt_rsvector_() : e(0) {}
     elt_rsvector_(size_type cc) : c(cc), e(0) {}
     elt_rsvector_(size_type cc, const T &ee) : c(cc), e(ee) {}
     bool operator < (const elt_rsvector_ &a) const { return c < a.c; }
@@ -375,8 +922,8 @@ namespace gmm {
     bool operator ==(const iterator &i) const { return it == i.it; }
     bool operator !=(const iterator &i) const { return !(i == *this); }
 
-    size_type index(void) const { return it->c; }
-    rsvector_iterator(void) {}
+    size_type index() const { return it->c; }
+    rsvector_iterator() {}
     rsvector_iterator(const IT &i) : it(i) {}
   };
 
@@ -394,7 +941,7 @@ namespace gmm {
 
     reference operator *() const { return it->e; }
     pointer operator->() const { return &(operator*()); }
-    size_type index(void) const { return it->c; }
+    size_type index() const { return it->c; }
 
     iterator &operator ++() { ++it; return *this; }
     iterator operator ++(int) { iterator tmp = *this; ++(*this); return tmp; }
@@ -404,18 +951,18 @@ namespace gmm {
     bool operator ==(const iterator &i) const { return it == i.it; }
     bool operator !=(const iterator &i) const { return !(i == *this); }
 
-    rsvector_const_iterator(void) {}
+    rsvector_const_iterator() {}
     rsvector_const_iterator(const rsvector_iterator<T> &i) : it(i.it) {}
     rsvector_const_iterator(const IT &i) : it(i) {}
   };
 
   /**
      sparse vector built upon std::vector. Read access is fast,
-     but insertion is O(n) 
+     but insertion is O(n)
   */
   template<typename T> class rsvector : public std::vector<elt_rsvector_<T> > {
   public:
-    
+
     typedef std::vector<elt_rsvector_<T> > base_type_;
     typedef typename base_type_::iterator iterator;
     typedef typename base_type_::const_iterator const_iterator;
@@ -423,32 +970,33 @@ namespace gmm {
     typedef T value_type;
 
   protected:
-    size_type nbl;    	/* size of the vector.	          	  */
-    
+    size_type nbl;    // size of the vector
+
   public:
 
     void sup(size_type j);
     void base_resize(size_type n) { base_type_::resize(n); }
     void resize(size_type);
-    
+
     ref_elt_vector<T, rsvector<T> > operator [](size_type c)
     { return ref_elt_vector<T, rsvector<T> >(this, c); }
 
     void w(size_type c, const T &e);
+    void wa(size_type c, const T &e);
     T r(size_type c) const;
     void swap_indices(size_type i, size_type j);
 
     inline T operator [](size_type c) const { return r(c); }
-    
-    size_type nb_stored(void) const { return base_type_::size(); }
-    size_type size(void) const { return nbl; }
-    void clear(void) { base_type_::resize(0); }
+
+    size_type nb_stored() const { return base_type_::size(); }
+    size_type size() const { return nbl; }
+    void clear() { base_type_::resize(0); }
     void swap(rsvector<T> &v)
     { std::swap(nbl, v.nbl); std::vector<elt_rsvector_<T> >::swap(v); }
 
     /* Constructeurs */
     explicit rsvector(size_type l) : nbl(l) { }
-    rsvector(void) : nbl(0) { }
+    rsvector() : nbl(0) { }
   };
 
   template <typename T>
@@ -465,18 +1013,18 @@ namespace gmm {
 
       switch (situation) {
       case 1 : a = *iti; a.c = j; it = iti; ++it; ite = this->end();
-	       for (; it != ite && it->c <= j; ++it, ++iti) *iti = *it;
-	       *iti = a;
-	       break;
+               for (; it != ite && it->c <= j; ++it, ++iti) *iti = *it;
+               *iti = a;
+               break;
       case 2 : a = *itj; a.c = i; it = itj; ite = this->begin();
-	if (it != ite) {
-	  --it;
-	  while (it->c >= i) { *itj = *it;  --itj; if (it==ite) break; --it; }
-	}
-	*itj = a;
-	break;
+        if (it != ite) {
+          --it;
+          while (it->c >= i) { *itj = *it;  --itj; if (it==ite) break; --it; }
+        }
+        *itj = a;
+        break;
       case 3 : std::swap(iti->e, itj->e);
-	       break;
+               break;
       }
     }
   }
@@ -486,8 +1034,8 @@ namespace gmm {
       elt_rsvector_<T> ev(j);
       iterator it = std::lower_bound(this->begin(), this->end(), ev);
       if (it != this->end() && it->c == j) {
-	for (iterator ite = this->end() - 1; it != ite; ++it) *it = *(it+1);
-	base_type_::resize(nb_stored()-1);
+        for (iterator ite = this->end() - 1; it != ite; ++it) *it = *(it+1);
+        base_resize(nb_stored()-1);
       }
     }
   }
@@ -495,7 +1043,7 @@ namespace gmm {
   template<typename T>  void rsvector<T>::resize(size_type n) {
     if (n < nbl) {
       for (size_type i = 0; i < nb_stored(); ++i)
-	if (base_type_::operator[](i).c >= n) { base_resize(i); break; }
+        if (base_type_::operator[](i).c >= n) { base_resize(i); break; }
     }
     nbl = n;
   }
@@ -506,27 +1054,58 @@ namespace gmm {
     else {
       elt_rsvector_<T> ev(c, e);
       if (nb_stored() == 0) {
-	base_type_::resize(1,ev);
+        base_type_::push_back(ev);
       }
       else {
-	iterator it = std::lower_bound(this->begin(), this->end(), ev);
-	if (it != this->end() && it->c == c) it->e = e;
-	else {
-	  size_type ind = it - this->begin();
-	  base_type_::resize(nb_stored()+1, ev);
-	  if (ind != nb_stored() - 1) {
-	    it = this->begin() + ind;
-	    for (iterator ite = this->end() - 1; ite != it; --ite)
-	      *ite = *(ite-1);
-	    *it = ev;
-	  }
-	}
+        iterator it = std::lower_bound(this->begin(), this->end(), ev);
+        if (it != this->end() && it->c == c) it->e = e;
+        else {
+          size_type ind = it - this->begin(), nb = this->nb_stored();
+          if (nb - ind > 1100)
+            GMM_WARNING2("Inefficient addition of element in rsvector with "
+                         << this->nb_stored() - ind << " non-zero entries");
+          base_type_::push_back(ev);
+          if (ind != nb) {
+            it = this->begin() + ind;
+            iterator ite = this->end(); --ite; iterator itee = ite;
+            for (; ite != it; --ite) { --itee; *ite = *itee; }
+            *it = ev;
+          }
+        }
       }
     }
   }
-  
-  template <typename T> T rsvector<T>::r(size_type c) const {
+
+  template <typename T> void rsvector<T>::wa(size_type c, const T &e) {
     GMM_ASSERT2(c < nbl, "out of range");
+    if (e != T(0)) {
+      elt_rsvector_<T> ev(c, e);
+      if (nb_stored() == 0) {
+        base_type_::push_back(ev);
+      }
+      else {
+        iterator it = std::lower_bound(this->begin(), this->end(), ev);
+        if (it != this->end() && it->c == c) it->e += e;
+        else {
+          size_type ind = it - this->begin(), nb = this->nb_stored();
+          if (nb - ind > 1100)
+            GMM_WARNING2("Inefficient addition of element in rsvector with "
+                         << this->nb_stored() - ind << " non-zero entries");
+          base_type_::push_back(ev);
+          if (ind != nb) {
+            it = this->begin() + ind;
+            iterator ite = this->end(); --ite; iterator itee = ite;
+            for (; ite != it; --ite) { --itee; *ite = *itee; }
+            *it = ev;
+          }
+        }
+      }
+    }
+  }
+
+  template <typename T> T rsvector<T>::r(size_type c) const {
+    GMM_ASSERT2(c < nbl, "out of range. Index " << c
+                << " for a length of " << nbl);
     if (nb_stored() != 0) {
       elt_rsvector_<T> ev(c);
       const_iterator it = std::lower_bound(this->begin(), this->end(), ev);
@@ -559,10 +1138,10 @@ namespace gmm {
     { o->clear(); }
     static void do_clear(this_type &v) { v.clear(); }
     static value_type access(const origin_type *o, const const_iterator &,
-			     const const_iterator &, size_type i)
+                             const const_iterator &, size_type i)
     { return (*o)[i]; }
     static reference access(origin_type *o, const iterator &, const iterator &,
-			    size_type i)
+                            size_type i)
     { return (*o)[i]; }
     static void resize(this_type &v, size_type n) { v.resize(n); }
   };
@@ -573,7 +1152,7 @@ namespace gmm {
   /******* Optimized operations for rsvector<T> ****************************/
 
   template <typename T> inline void copy(const rsvector<T> &v1,
- 					 rsvector<T> &v2) {
+                                          rsvector<T> &v2) {
     GMM_ASSERT2(vect_size(v1) == vect_size(v2), "dimensions mismatch");
     v2 = v1;
   }
@@ -588,39 +1167,39 @@ namespace gmm {
   }
   template <typename T> inline
   void copy(const simple_vector_ref<const rsvector<T> *> &v1,
-	    rsvector<T> &v2)
+            rsvector<T> &v2)
   { copy(*(v1.origin), v2); }
   template <typename T> inline
   void copy(const simple_vector_ref<rsvector<T> *> &v1, rsvector<T> &v2)
   { copy(*(v1.origin), v2); }
 
   template <typename V, typename T> inline void add(const V &v1,
-						    rsvector<T> &v2) {
+                                                    rsvector<T> &v2) {
     if ((const void *)(&v1) != (const void *)(&v2)) {
       GMM_ASSERT2(vect_size(v1) == vect_size(v2), "dimensions mismatch");
-	add_rsvector(v1, v2, typename linalg_traits<V>::storage_type());
+        add_rsvector(v1, v2, typename linalg_traits<V>::storage_type());
     }
   }
 
-  template <typename V, typename T> 
+  template <typename V, typename T>
   inline void add_rsvector(const V &v1, rsvector<T> &v2, abstract_dense)
   { add(v1, v2, abstract_dense(), abstract_sparse()); }
 
-  template <typename V, typename T> 
+  template <typename V, typename T>
   inline void add_rsvector(const V &v1, rsvector<T> &v2, abstract_skyline)
   { add(v1, v2, abstract_skyline(), abstract_sparse()); }
 
-  template <typename V, typename T> 
+  template <typename V, typename T>
   void add_rsvector(const V &v1, rsvector<T> &v2, abstract_sparse) {
     add_rsvector(v1, v2, typename linalg_traits<V>::index_sorted());
   }
 
-  template <typename V, typename T> 
+  template <typename V, typename T>
   void add_rsvector(const V &v1, rsvector<T> &v2, linalg_false) {
     add(v1, v2, abstract_sparse(), abstract_sparse());
   }
 
-  template <typename V, typename T> 
+  template <typename V, typename T>
   void add_rsvector(const V &v1, rsvector<T> &v2, linalg_true) {
     typename linalg_traits<V>::const_iterator it1 = vect_const_begin(v1),
       ite1 = vect_const_end(v1);
@@ -634,31 +1213,49 @@ namespace gmm {
 
     v2.base_resize(nbc);
     it3 = v2.begin() + old_nbc;
-    it2 = v2.end(); ite2 = v2.begin();
-    it1 = vect_end(v1); ite1 = vect_const_begin(v1);
-    while (it1 != ite1 && it3 != ite2) {
-      --it3; --it1; --it2;
-      if (it3->c > it1.index()) { *it2 = *it3; ++it1; }
-      else if (it3->c == it1.index()) { *it2=*it3; it2->e+=*it1; }
-      else { it2->c = it1.index(); it2->e = *it1; ++it3; }
-    }
-    while (it1 != ite1) { --it1; --it2; it2->c = it1.index(); it2->e = *it1; }
+    it2 = v2.end();
+    ite2 = v2.begin();
+    it1 = vect_end(v1);
+    ite1 = vect_const_begin(v1);
+    while (it1 != ite1 && it2 != ite2 && it3 != ite2){
+      --it3;
+      --it1;
+      --it2;
+      if (it3->c > it1.index()) {
+        *it2 = *it3;
+        ++it1;
+      }
+      else if (it3->c == it1.index()) {
+        *it2=*it3;
+        it2->e+=*it1;
+      }
+      else {
+        it2->c = it1.index();
+        it2->e = *it1; ++it3;
+      }
+    }
+    while (it1 != ite1 && it2 != ite2) {
+      --it1;
+      --it2;
+      it2->c = it1.index();
+      it2->e = *it1;
+    }
   }
 
   template <typename V, typename T> void copy(const V &v1, rsvector<T> &v2) {
     if ((const void *)(&v1) != (const void *)(&v2)) {
       GMM_ASSERT2(vect_size(v1) == vect_size(v2), "dimensions mismatch");
       if (same_origin(v1, v2))
-	GMM_WARNING2("a conflict is possible in vector copy\n");
+        GMM_WARNING2("a conflict is possible in vector copy\n");
       copy_rsvector(v1, v2, typename linalg_traits<V>::storage_type());
     }
   }
 
-  template <typename V, typename T> 
+  template <typename V, typename T>
   void copy_rsvector(const V &v1, rsvector<T> &v2, abstract_dense)
   { copy_vect(v1, v2, abstract_dense(), abstract_sparse()); }
 
-  template <typename V, typename T> 
+  template <typename V, typename T>
   void copy_rsvector(const V &v1, rsvector<T> &v2, abstract_skyline)
   { copy_vect(v1, v2, abstract_skyline(), abstract_sparse()); }
 
@@ -666,7 +1263,7 @@ namespace gmm {
   void copy_rsvector(const V &v1, rsvector<T> &v2, abstract_sparse) {
     copy_rsvector(v1, v2, typename linalg_traits<V>::index_sorted());
   }
-  
+
   template <typename V, typename T2>
   void copy_rsvector(const V &v1, rsvector<T2> &v2, linalg_true) {
     typedef typename linalg_traits<V>::value_type T1;
@@ -693,7 +1290,7 @@ namespace gmm {
     v2.base_resize(nn);
     std::sort(v2.begin(), v2.end());
   }
-  
+
   template <typename T> inline void clean(rsvector<T> &v, double eps) {
     typedef typename number_traits<T>::magnitude_type R;
     typename rsvector<T>::iterator it = v.begin(), ite = v.end();
@@ -702,7 +1299,7 @@ namespace gmm {
       typename rsvector<T>::iterator itc = it;
       size_type erased = 1;
       for (++it; it != ite; ++it)
-	{ *itc = *it; if (gmm::abs((*it).e) <= R(eps)) ++erased; else ++itc; }
+        { *itc = *it; if (gmm::abs((*it).e) <= R(eps)) ++erased; else ++itc; }
       v.base_resize(v.nb_stored() - erased);
     }
   }
@@ -716,7 +1313,7 @@ namespace gmm {
     clean(*pv, eps);
     svr->begin_ = vect_begin(*pv); svr->end_ = vect_end(*pv);
   }
-  
+
   template <typename T>
   inline size_type nnz(const rsvector<T>& l) { return l.nb_stored(); }
 
@@ -738,8 +1335,8 @@ namespace gmm {
 
     base_iterator it;
     size_type shift;
-    
-   
+
+
     iterator &operator ++()
     { ++it; ++shift; return *this; }
     iterator &operator --()
@@ -758,21 +1355,21 @@ namespace gmm {
     { iterator tmp = *this; return (tmp -= i); }
     difference_type operator -(const iterator &i) const
     { return it - i.it; }
-	
+
     reference operator *() const
     { return *it; }
     reference operator [](int ii)
     { return *(it + ii); }
-    
+
     bool operator ==(const iterator &i) const
     { return it == i.it; }
     bool operator !=(const iterator &i) const
     { return !(i == *this); }
     bool operator < (const iterator &i) const
     { return it < i.it; }
-    size_type index(void) const { return shift; }
+    size_type index() const { return shift; }
 
-    slvector_iterator(void) {}
+    slvector_iterator() {}
     slvector_iterator(const base_iterator &iter, size_type s)
       : it(iter), shift(s) {}
   };
@@ -789,8 +1386,8 @@ namespace gmm {
 
     base_iterator it;
     size_type shift;
-    
-   
+
+
     iterator &operator ++()
     { ++it; ++shift; return *this; }
     iterator &operator --()
@@ -809,21 +1406,21 @@ namespace gmm {
     { iterator tmp = *this; return (tmp -= i); }
     difference_type operator -(const iterator &i) const
     { return it - i.it; }
-	
+
     value_type operator *() const
     { return *it; }
     value_type operator [](int ii)
     { return *(it + ii); }
-    
+
     bool operator ==(const iterator &i) const
     { return it == i.it; }
     bool operator !=(const iterator &i) const
     { return !(i == *this); }
     bool operator < (const iterator &i) const
     { return it < i.it; }
-    size_type index(void) const { return shift; }
+    size_type index() const { return shift; }
 
-    slvector_const_iterator(void) {}
+    slvector_const_iterator() {}
     slvector_const_iterator(const slvector_iterator<T>& iter)
       : it(iter.it), shift(iter.shift) {}
     slvector_const_iterator(const base_iterator &iter, size_type s)
@@ -834,7 +1431,7 @@ namespace gmm {
   /** skyline vector.
    */
   template <typename T> class slvector {
-    
+
   public :
     typedef slvector_iterator<T> iterators;
     typedef slvector_const_iterator<T> const_iterators;
@@ -849,20 +1446,21 @@ namespace gmm {
 
   public :
 
-    size_type size(void) const { return size_; }
-    size_type first(void) const { return shift; }
-    size_type last(void) const { return shift + data.size(); }
+    size_type size() const { return size_; }
+    size_type first() const { return shift; }
+    size_type last() const { return shift + data.size(); }
     ref_elt_vector<T, slvector<T> > operator [](size_type c)
     { return ref_elt_vector<T, slvector<T> >(this, c); }
 
-    typename std::vector<T>::iterator data_begin(void) { return data.begin(); }
-    typename std::vector<T>::iterator data_end(void) { return data.end(); }
-    typename std::vector<T>::const_iterator data_begin(void) const
+    typename std::vector<T>::iterator data_begin() { return data.begin(); }
+    typename std::vector<T>::iterator data_end() { return data.end(); }
+    typename std::vector<T>::const_iterator data_begin() const
       { return data.begin(); }
-    typename std::vector<T>::const_iterator data_end(void) const
+    typename std::vector<T>::const_iterator data_end() const
       { return data.end(); }
 
     void w(size_type c, const T &e);
+    void wa(size_type c, const T &e);
     T r(size_type c) const {
       GMM_ASSERT2(c < size_, "out of range");
       if (c < shift || c >= shift + data.size()) return T(0);
@@ -871,7 +1469,7 @@ namespace gmm {
 
     inline T operator [](size_type c) const { return r(c); }
     void resize(size_type);
-    void clear(void) { data.resize(0); shift = 0; }
+    void clear() { data.resize(0); shift = 0; }
     void swap(slvector<T> &v) {
       std::swap(data, v.data);
       std::swap(shift, v.shift);
@@ -879,7 +1477,7 @@ namespace gmm {
     }
 
 
-    slvector(void) : data(0), shift(0), size_(0) {}
+    slvector() : data(0), shift(0), size_(0) {}
     explicit slvector(size_type l) : data(0), shift(0), size_(l) {}
     slvector(size_type l, size_type d, size_type s)
       : data(d), shift(s), size_(l) {}
@@ -898,7 +1496,7 @@ namespace gmm {
     size_type s = data.size();
     if (!s) { data.resize(1); shift = c; }
     else if (c < shift) {
-      data.resize(s + shift - c); 
+      data.resize(s + shift - c);
       typename std::vector<T>::iterator it = data.begin(),it2=data.end()-1;
       typename std::vector<T>::iterator it3 = it2 - shift + c;
       for (; it3 >= it; --it3, --it2) *it2 = *it3;
@@ -906,12 +1504,36 @@ namespace gmm {
       shift = c;
     }
     else if (c >= shift + s) {
-      data.resize(c - shift + 1);
-      std::fill(data.begin() + s, data.end(), T(0));
+      data.resize(c - shift + 1, T(0));
+      // std::fill(data.begin() + s, data.end(), T(0));
     }
     data[c - shift] = e;
   }
-  
+
+  template<typename T>  void slvector<T>::wa(size_type c, const T &e) {
+    GMM_ASSERT2(c < size_, "out of range");
+    size_type s = data.size();
+    if (!s) { data.resize(1, e); shift = c; return; }
+    else if (c < shift) {
+      data.resize(s + shift - c);
+      typename std::vector<T>::iterator it = data.begin(),it2=data.end()-1;
+      typename std::vector<T>::iterator it3 = it2 - shift + c;
+      for (; it3 >= it; --it3, --it2) *it2 = *it3;
+      std::fill(it, it + shift - c, T(0));
+      shift = c;
+      data[c - shift] = e;
+      return;
+    }
+    else if (c >= shift + s) {
+      data.resize(c - shift + 1, T(0));
+      data[c - shift] = e;
+      return;
+      // std::fill(data.begin() + s, data.end(), T(0));
+    }
+    data[c - shift] += e;
+  }
+
+
   template <typename T> struct linalg_traits<slvector<T> > {
     typedef slvector<T> this_type;
     typedef this_type origin_type;
@@ -938,10 +1560,10 @@ namespace gmm {
     { o->clear(); }
     static void do_clear(this_type &v) { v.clear(); }
     static value_type access(const origin_type *o, const const_iterator &,
-			     const const_iterator &, size_type i)
+                             const const_iterator &, size_type i)
     { return (*o)[i]; }
     static reference access(origin_type *o, const iterator &, const iterator &,
-			    size_type i)
+                            size_type i)
     { return (*o)[i]; }
     static void resize(this_type &v, size_type n) { v.resize(n); }
   };
diff --git a/contrib/gmm/gmm_vector_to_matrix.h b/contrib/gmm/gmm_vector_to_matrix.h
index 50036fc639..95b0bea1f2 100644
--- a/contrib/gmm/gmm_vector_to_matrix.h
+++ b/contrib/gmm/gmm_vector_to_matrix.h
@@ -1,32 +1,33 @@
-// -*- c++ -*- (enables emacs c++ mode)
-//===========================================================================
-//
-// Copyright (C) 2003-2008 Yves Renard
-//
-// This file is a part of GETFEM++
-//
-// Getfem++  is  free software;  you  can  redistribute  it  and/or modify it
-// under  the  terms  of the  GNU  Lesser General Public License as published
-// by  the  Free Software Foundation;  either version 2.1 of the License,  or
-// (at your option) any later version.
-// This program  is  distributed  in  the  hope  that it will be useful,  but
-// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-// or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
-// License for more details.
-// You  should  have received a copy of the GNU Lesser General Public License
-// along  with  this program;  if not, write to the Free Software Foundation,
-// Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
-//
-// As a special exception, you may use this file as part of a free software
-// library without restriction.  Specifically, if other files instantiate
-// templates or use macros or inline functions from this file, or you compile
-// this file and link it with other files to produce an executable, this
-// file does not by itself cause the resulting executable to be covered by
-// the GNU General Public License.  This exception does not however
-// invalidate any other reasons why the executable file might be covered by
-// the GNU General Public License.
-//
-//===========================================================================
+/* -*- c++ -*- (enables emacs c++ mode) */
+/*===========================================================================
+
+ Copyright (C) 2003-2020 Yves Renard
+
+ This file is a part of GetFEM
+
+ GetFEM  is  free software;  you  can  redistribute  it  and/or modify it
+ under  the  terms  of the  GNU  Lesser General Public License as published
+ by  the  Free Software Foundation;  either version 3 of the License,  or
+ (at your option) any later version along with the GCC Runtime Library
+ Exception either version 3.1 or (at your option) any later version.
+ This program  is  distributed  in  the  hope  that it will be useful,  but
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+ License and GCC Runtime Library Exception for more details.
+ You  should  have received a copy of the GNU Lesser General Public License
+ along  with  this program;  if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+
+ As a special exception, you  may use  this file  as it is a part of a free
+ software  library  without  restriction.  Specifically,  if   other  files
+ instantiate  templates  or  use macros or inline functions from this file,
+ or  you compile this  file  and  link  it  with other files  to produce an
+ executable, this file  does  not  by itself cause the resulting executable
+ to be covered  by the GNU Lesser General Public License.  This   exception
+ does not  however  invalidate  any  other  reasons why the executable file
+ might be covered by the GNU Lesser General Public License.
+
+===========================================================================*/
 
 /**@file gmm_vector_to_matrix.h
    @author  Yves Renard <Yves.Renard@insa-lyon.fr>
diff --git a/src/solver/linearSystemCSR.cpp b/src/solver/linearSystemCSR.cpp
index 486a8433ca..14dbadf2d5 100644
--- a/src/solver/linearSystemCSR.cpp
+++ b/src/solver/linearSystemCSR.cpp
@@ -437,7 +437,7 @@ void linearSystemCSR<std::complex<double> >::getMatrix(INDEX_TYPE *&jptr,
 #if defined(HAVE_GMM)
 
 #undef BB // can be defined by FlGui.h, and clashes with gmm arg name
-#include <gmm.h>
+#include "gmm.h"
 
 template <> int linearSystemCSRGmm<double>::systemSolve()
 {
diff --git a/src/solver/linearSystemGmm.h b/src/solver/linearSystemGmm.h
index a2a3496f12..98358bbd80 100644
--- a/src/solver/linearSystemGmm.h
+++ b/src/solver/linearSystemGmm.h
@@ -14,7 +14,7 @@
 #if defined(HAVE_GMM)
 
 #undef BB // can be defined by FlGui.h, and clashes with gmm arg name
-#include <gmm.h>
+#include "gmm.h"
 
 // Consider using linearSystemCSRGmm instead: assembly is much faster
 template <class scalar> class linearSystemGmm : public linearSystem<scalar> {
-- 
GitLab

