/* Software SPAMS v2.1 - Copyright 2009-2011 Julien Mairal 
 *
 * This file is part of SPAMS.
 *
 * SPAMS is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * SPAMS 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with SPAMS.  If not, see <http://www.gnu.org/licenses/>.
 */

/* \file
 *                toolbox Linalg 
 *
 *                by Julien Mairal
 *                julien.mairal@inria.fr
 *
 *                File linalg.h
 * \brief Contains Matrix, Vector classes */

#ifndef LINALG_H
#define LINALG_H

#include "misc.h"
//#ifdef USE_BLAS_LIB
#include "cblas_alt_template.h"
//#else
//#include "cblas_template.h"   // this is obsolete
//#endif
#include <fstream>
#ifdef WINDOWS
#include <string>
#else
#include <cstring>
#endif
#include <list>
#include <vector>

#include "utils.h"
#include "list.h"
typedef List<int> list_int;
typedef ListIterator<int> const_iterator_int;

#undef max
#undef min

/// Dense Matrix class
template<typename T> class Matrix;
/// Sparse Matrix class
template<typename T> class SpMatrix;
/// Dense Vector class
template<typename T> class Vector;
/// Sparse Vector class
template<typename T> class SpVector;



typedef std::list< INTM > group;
typedef std::list< group > list_groups;
typedef std::vector< group > vector_groups;

template <typename T> 
static inline bool isZero(const T lambda) {
   return static_cast<double>(abs<T>(lambda)) < 1e-99;
}

template <typename T> 
static inline bool isEqual(const T lambda1, const T lambda2) {
   return static_cast<double>(abs<T>(lambda1-lambda2)) < 1e-99;
}


template <typename T>
static inline T softThrs(const T x, const T lambda) {
   if (x > lambda) {
      return x-lambda;
   } else if (x < -lambda) {
      return x+lambda;
   } else {
      return 0;
   }
};

template <typename T>
static inline T hardThrs(const T x, const T lambda) {
   return (x > lambda || x < -lambda) ? x : 0;
};

template <typename T>
static inline T alt_log(const T x);
template <> inline double alt_log<double>(const double x) { return log(x); };
template <> inline float alt_log<float>(const float x) { return logf(x); };

template <typename T>
static inline T xlogx(const T x) {
   if (x < -1e-20) {
      return INFINITY;
   } else if (x < 1e-20) {
      return 0;
   } else {
      return x*alt_log<T>(x);
   }
}

template <typename T>
static inline T logexp(const T x) {
   if (x < -30) {
      return 0;
   } else if (x < 30) {
      return alt_log<T>( T(1.0) + exp_alt<T>( x ) );
   } else {
      return x;
   }
}

/// Data class, abstract class, useful in the class image.
template <typename T> class Data {
   public:
      virtual void getData(Vector<T>& data, const INTM i) const = 0;
      virtual void getGroup(Matrix<T>& data, const vector_groups& groups,
            const INTM i) const = 0;
      virtual inline T operator[](const INTM index) const = 0;
      virtual INTM n() const = 0;
      virtual INTM m() const = 0;
      virtual INTM V() const = 0;
      virtual void norm_2sq_cols(Vector<T>& norms) const { };
      virtual ~Data() { };
};

/// Abstract matrix class
template <typename T> class AbstractMatrixB {
   public:
      virtual INTM n() const = 0;
      virtual INTM m() const = 0;

      /// b <- alpha A'x + beta b
      virtual void multTrans(const Vector<T>& x, Vector<T>& b,
            const T alpha = 1.0, const T beta = 0.0) const = 0;

      /// perform b = alpha*A*x + beta*b, when x is sparse
      virtual void mult(const SpVector<T>& x, Vector<T>& b, 
            const T alpha = 1.0, const T beta = 0.0) const = 0;

      virtual void mult(const Vector<T>& x, Vector<T>& b, 
            const T alpha = 1.0, const T beta = 0.0) const = 0;

      /// perform C = a*A*B + b*C, possibly transposing A or B.
      virtual void mult(const Matrix<T>& B, Matrix<T>& C, 
            const bool transA = false, const bool transB = false,
            const T a = 1.0, const T b = 0.0) const = 0;

      virtual void mult(const SpMatrix<T>& B, Matrix<T>& C, 
            const bool transA = false, const bool transB = false,
            const T a = 1.0, const T b = 0.0) const = 0;

      /// perform C = a*B*A + b*C, possibly transposing A or B.
      virtual void multSwitch(const Matrix<T>& B, Matrix<T>& C, 
            const bool transA = false, const bool transB = false,
            const T a = 1.0, const T b = 0.0) const = 0;

      /// XtX = A'*A
      virtual void XtX(Matrix<T>& XtX) const = 0;

      virtual void copyRow(const INTM i, Vector<T>& x) const = 0;

      virtual void copyTo(Matrix<T>& copy) const = 0;
      virtual T dot(const Matrix<T>& x) const = 0;

      virtual void print(const string& name) const = 0;

      void ridgeCG(const Vector<T>& b, Vector<T>& x, const T lambda, const T tol, const int itermax) const;
      void ridgeCG(const Vector<T>& b, const Vector<T>& delta, Vector<T>& x, const T lambda, const T tol, const int itermax) const;
      void ridgeCG(const Matrix<T>& b, Matrix<T>& x, const T lambda, const T tol, const int itermax, const int numThreads = -1) const; 
      void ridgeCG(const Matrix<T>& b, const Matrix<T>& delta, Matrix<T>& x, const T lambda, const T tol, const int itermax, const int numThreads = -1) const; 

      virtual ~AbstractMatrixB() { };
};

/// Abstract matrix class
template <typename T> class AbstractMatrix {
   public:
      virtual INTM n() const = 0;
      virtual INTM m() const = 0;
      /// copy X(:,i) INTMo Xi
      virtual void copyCol(const INTM i, Vector<T>& Xi) const = 0;
      /// compute X(:,i)<- X(:,i)+a*col;
      virtual void add_rawCol(const INTM i, T* col, const T a) const = 0;
      /// copy X(:,i) INTMo Xi
      virtual void extract_rawCol(const INTM i,T* Xi) const = 0;
      /// extract diagonal
      virtual void diag(Vector<T>& diag) const = 0;
      //// extract X(index1,index2)
      virtual inline T operator()(const INTM index1, const INTM index2) const = 0;
      virtual ~AbstractMatrix() { };
};

/// Class Matrix
template<typename T> class Matrix : public Data<T>, public AbstractMatrix<T>, public AbstractMatrixB<T> {
   friend class SpMatrix<T>;
   public:

   /// Constructor with existing data X of an m x n matrix
   Matrix(T* X, INTM m, INTM n);
   /// Constructor for a new m x n matrix
   Matrix(INTM m, INTM n);
   /// Empty constructor
   Matrix();

   /// Destructor
   virtual ~Matrix();

   /// Accessors
   /// Number of rows
   inline INTM m() const { return _m; };
   /// Number of columns
   inline INTM n() const { return _n; };
   /// Return a modifiable reference to X(i,j)
   inline T& operator()(const INTM i, const INTM j);
   /// Return the value X(i,j)
   inline T operator()(const INTM i, const INTM j) const;
   /// Return a modifiable reference to X(i) (1D indexing)
   inline T& operator[](const INTM index) { return _X[index]; };
   /// Return the value X(i) (1D indexing)
   inline T operator[](const INTM index) const { return _X[index]; };
   /// Copy the column i into x
   inline void copyCol(const INTM i, Vector<T>& x) const;
   /// Copy the column i into x
   inline void copyRow(const INTM i, Vector<T>& x) const;
   /// Copy the column i into x
   inline void extract_rawCol(const INTM i, T* x) const;
   /// Copy the column i into x
   virtual void add_rawCol(const INTM i, T* DtXi, const T a) const;
   /// Copy the column i into x
   inline void getData(Vector<T>& data, const INTM i) const;
   /// extract the group i
   virtual void getGroup(Matrix<T>& data, const vector_groups& groups,
         const INTM i) const;
   /// Reference the column i into the vector x
   inline void refCol(INTM i, Vector<T>& x) const;
   /// Reference the column i to i+n into the Matrix mat
   inline void refSubMat(INTM i, INTM n, Matrix<T>& mat) const;
   /// extract a sub-matrix of a symmetric matrix
   inline void subMatrixSym(const Vector<INTM>& indices, 
         Matrix<T>& subMatrix) const;
   /// reference a modifiable reference to the data, DANGEROUS
   inline T* rawX() const { return _X; };
   /// return a non-modifiable reference to the data
   inline const T* X() const { return _X; };
   /// make a copy of the matrix mat in the current matrix
   inline void copy(const Matrix<T>& mat);
   /// make a copy of the matrix mat in the current matrix
   inline void copyTo(Matrix<T>& mat) const { mat.copy(*this); };
   /// make a copy of the matrix mat in the current matrix
   inline void copyRef(const Matrix<T>& mat);

   /// Debugging function
   /// Print the matrix to std::cout
   inline void print(const string& name) const;


   /// Modifiers
   /// clean a dictionary matrix
   inline void clean();
   /// Resize the matrix
   inline void resize(INTM m, INTM n, const bool set_zeros = true);
   /// Change the data in the matrix
   inline void setData(T* X, INTM m, INTM n);
   /// modify _m
   inline void setm(const INTM m) { _m = m; }; //DANGEROUS
   /// modify _n
   inline void setn(const INTM n) { _n = n; }; //DANGEROUS
   /// Set all the values to zero
   inline void setZeros();
   /// Set all the values to a scalar
   inline void set(const T a);
   /// Clear the matrix
   inline void clear();
   /// Put white Gaussian noise in the matrix 
   inline void setAleat();
   /// set the matrix to the identity;
   inline void eye();
   /// Normalize all columns to unit l2 norm
   inline void normalize();
   /// Normalize all columns which l2 norm is greater than one.
   inline void normalize2();
   /// center the columns of the matrix
   inline void center();
   /// center the columns of the matrix
   inline void center_rows();
   /// center the columns of the matrix and keep the center values
   inline void center(Vector<T>& centers);
   /// scale the matrix by the a
   inline void scal(const T a);
   /// make the matrix symmetric by copying the upper-right part
   /// into the lower-left part
   inline void fillSymmetric();
   inline void fillSymmetric2();
   /// change artificially the size of the matrix, DANGEROUS
   inline void fakeSize(const INTM m, const INTM n) { _n = n; _m=m;};
   /// whiten
   inline void whiten(const INTM V);
   /// whiten
   inline void whiten(Vector<T>& mean, const bool pattern = false);
   /// whiten
   inline void whiten(Vector<T>& mean, const Vector<T>& mask);
   /// whiten
   inline void unwhiten(Vector<T>& mean, const bool pattern = false);
   /// whiten
   inline void sum_cols(Vector<T>& sum) const;

   /// Analysis functions
   /// Check wether the columns of the matrix are normalized or not
   inline bool isNormalized() const;
   /// return the 1D-index of the value of greatest magnitude
   inline INTM fmax() const;
   /// return the 1D-index of the value of greatest magnitude
   inline T fmaxval() const;
   /// return the 1D-index of the value of lowest magnitude
   inline INTM fmin() const;

   // Algebric operations
   /// Transpose the current matrix and put the result in the matrix
   /// trans
   inline void transpose(Matrix<T>& trans);
   /// A <- -A
   inline void neg();
   /// add one to the diagonal
   inline void incrDiag();
   inline void addDiag(const Vector<T>& diag);
   inline void addDiag(const T diag);
   inline void addToCols(const Vector<T>& diag);
   inline void addVecToCols(const Vector<T>& diag, const T a = 1.0);
   /// perform a rank one approximation uv' using the power method
   /// u0 is an initial guess for u (can be empty).
   inline void svdRankOne(const Vector<T>& u0,
         Vector<T>& u, Vector<T>& v) const;
   inline void singularValues(Vector<T>& u) const;
   inline void svd(Matrix<T>& U, Vector<T>& S, Matrix<T>&V) const;

   /// find the eigenvector corresponding to the largest eigenvalue
   /// when the current matrix is symmetric. u0 is the initial guess.
   /// using two iterations of the power method
   inline void eigLargestSymApprox(const Vector<T>& u0,
         Vector<T>& u) const;
   /// find the eigenvector corresponding to the eivenvalue with the 
   /// largest magnitude when the current matrix is symmetric,
   /// using the power method. It 
   /// returns the eigenvalue. u0 is an initial guess for the 
   /// eigenvector.
   inline T eigLargestMagnSym(const Vector<T>& u0, 
         Vector<T>& u) const;
   /// returns the value of the eigenvalue with the largest magnitude
   /// using the power iteration.
   inline T eigLargestMagnSym() const;
   /// inverse the matrix when it is symmetric
   inline void invSym();
   /// perform b = alpha*A'x + beta*b
   inline void multTrans(const Vector<T>& x, Vector<T>& b,
         const T alpha = 1.0, const T beta = 0.0) const;
   /// perform b = alpha*A'x + beta*b
   inline void multTrans(const Vector<T>& x, Vector<T>& b,
         const Vector<bool>& active) const;
   /// perform b = A'x, when x is sparse
   inline void multTrans(const SpVector<T>& x, Vector<T>& b, const T alpha =1.0, const T beta = 0.0) const;
   /// perform b = alpha*A*x+beta*b
   inline void mult(const Vector<T>& x, Vector<T>& b, 
         const T alpha = 1.0, const T beta = 0.0) const;
   /// perform b = alpha*A*x + beta*b, when x is sparse
   inline void mult(const SpVector<T>& x, Vector<T>& b, 
         const T alpha = 1.0, const T beta = 0.0) const;
   /// perform C = a*A*B + b*C, possibly transposing A or B.
   inline void mult(const Matrix<T>& B, Matrix<T>& C, 
         const bool transA = false, const bool transB = false,
         const T a = 1.0, const T b = 0.0) const;
   /// perform C = a*B*A + b*C, possibly transposing A or B.
   inline void multSwitch(const Matrix<T>& B, Matrix<T>& C, 
         const bool transA = false, const bool transB = false,
         const T a = 1.0, const T b = 0.0) const;
   /// perform C = A*B, when B is sparse
   inline void mult(const SpMatrix<T>& B, Matrix<T>& C, const bool transA = false,
         const bool transB = false, const T a = 1.0,
         const T b = 0.0) const;
   /// mult by a diagonal matrix on the left
   inline void multDiagLeft(const Vector<T>& diag);
   /// mult by a diagonal matrix on the right
   inline void multDiagRight(const Vector<T>& diag);
   /// C = A .* B, elementwise multiplication
   inline void mult_elementWise(const Matrix<T>& B, Matrix<T>& C) const;
   inline void div_elementWise(const Matrix<T>& B, Matrix<T>& C) const;
   /// XtX = A'*A
   inline void XtX(Matrix<T>& XtX) const;
   /// XXt = A*A'
   inline void XXt(Matrix<T>& XXt) const;
   /// XXt = A*A' where A is an upper triangular matrix
   inline void upperTriXXt(Matrix<T>& XXt, 
         const INTM L) const;
   /// extract the diagonal
   inline void diag(Vector<T>& d) const;
   /// set the diagonal
   inline void setDiag(const Vector<T>& d);
   /// set the diagonal
   inline void setDiag(const T val);
   /// each element of the matrix is replaced by its exponential
   inline void exp();
   /// each element of the matrix is replaced by its square root
   inline void Sqrt();
   inline void Invsqrt();
   /// return vec1'*A*vec2, where vec2 is sparse
   inline T quad(const Vector<T>& vec1, const SpVector<T>& vec2) const;
   /// return vec1'*A*vec2, where vec2 is sparse
   inline void quad_mult(const Vector<T>& vec1, const SpVector<T>& vec2,
         Vector<T>& y, const T a = 1.0, const T b = 0.0) const;
   /// return vec'*A*vec when vec is sparse
   inline T quad(const SpVector<T>& vec) const;
   /// add alpha*mat to the current matrix
   inline void add(const Matrix<T>& mat, const T alpha = 1.0);
   /// add alpha to the current matrix
   inline void add(const T alpha);
   /// add alpha*mat to the current matrix
   inline T dot(const Matrix<T>& mat) const;
   /// substract the matrix mat to the current matrix
   inline void sub(const Matrix<T>& mat);
   /// inverse the elements of the matrix
   inline void inv_elem();
   /// inverse the elements of the matrix
   inline void inv() { this->inv_elem(); };
   /// return the trace of the matrix
   inline T trace() const;
   /// compute the sum of the magnitude of the matrix values
   inline T asum() const;
   /// return ||A||_F
   inline T normF() const;
   /// whiten
   inline T mean() const;
   /// return ||A||_F^2
   inline T normFsq() const;
   /// return ||A||_F^2
   inline T nrm2sq() const { return this->normFsq(); };
   /// return ||At||_{inf,2} (max of l2 norm of the columns)
   inline T norm_inf_2_col() const;
   /// return ||At||_{1,2} (max of l2 norm of the columns)
   inline T norm_1_2_col() const;
   /// returns the l2 norms of the columns
   inline void norm_2_cols(Vector<T>& norms) const;
   /// returns the l2 norms of the columns
   inline void norm_2_rows(Vector<T>& norms) const;
   /// returns the linf norms of the columns
   inline void norm_inf_cols(Vector<T>& norms) const;
   /// returns the linf norms of the columns
   inline void norm_inf_rows(Vector<T>& norms) const;
   /// returns the linf norms of the columns
   inline void norm_l1_rows(Vector<T>& norms) const;
   /// returns the l2 norms ^2 of the columns
   inline void norm_2sq_cols(Vector<T>& norms) const;
   /// returns the l2 norms of the columns
   inline void norm_2sq_rows(Vector<T>& norms) const;
   inline void thrsmax(const T nu);
   inline void thrsmin(const T nu);
   inline void thrsabsmin(const T nu);
   /// perform soft-thresholding of the matrix, with the threshold nu
   inline void softThrshold(const T nu);
   inline void hardThrshold(const T nu);
   /// perform soft-thresholding of the matrix, with the threshold nu
   inline void thrsPos();
   /// perform A <- A + alpha*vec1*vec2'
   inline void rank1Update(const Vector<T>& vec1, const Vector<T>& vec2,
         const T alpha = 1.0);
   /// perform A <- A + alpha*vec1*vec2', when vec1 is sparse
   inline void rank1Update(const SpVector<T>& vec1, const Vector<T>& vec2,
         const T alpha = 1.0);
   /// perform A <- A + alpha*vec1*vec2', when vec2 is sparse
   inline void rank1Update(const Vector<T>& vec1, const SpVector<T>& vec2,
         const T alpha = 1.0);
   inline void rank1Update_mult(const Vector<T>& vec1, const Vector<T>& vec1b,
         const SpVector<T>& vec2,
         const T alpha = 1.0);
   /// perform A <- A + alpha*vec*vec', when vec2 is sparse
   inline void rank1Update(const SpVector<T>& vec,
         const T alpha = 1.0);
   /// perform A <- A + alpha*vec*vec', when vec2 is sparse
   inline void rank1Update(const SpVector<T>& vec, const SpVector<T>& vec2,
         const T alpha = 1.0);
   /// Compute the mean of the columns
   inline void meanCol(Vector<T>& mean) const;
   /// Compute the mean of the rows
   inline void meanRow(Vector<T>& mean) const;
   /// fill the matrix with the row given
   inline void fillRow(const Vector<T>& row);
   /// fill the matrix with the row given
   inline void extractRow(const INTM i, Vector<T>& row) const;
   inline void setRow(const INTM i, const Vector<T>& row);
   inline void addRow(const INTM i, const Vector<T>& row, const T a=1.0);
   /// compute x, such that b = Ax, WARNING this function needs to be u
   /// updated
   inline void conjugateGradient(const Vector<T>& b, Vector<T>& x,
         const T tol = 1e-4, const int = 4) const;
   /// compute x, such that b = Ax, WARNING this function needs to be u
   /// updated, the temporary vectors are given.
   inline void drop(char* fileName) const;
   /// compute a Nadaraya Watson estimator
   inline void NadarayaWatson(const Vector<INTM>& ind, const T sigma);
   /// performs soft-thresholding of the vector
   inline void blockThrshold(const T nu, const INTM sizeGroup);
   /// performs sparse projections of the columns 
   inline void sparseProject(Matrix<T>& out, const T thrs,   const int mode = 1, const T lambda1 = 0,
         const T lambda2 = 0, const T lambda3 = 0, const bool pos = false, const int numThreads=-1);
   inline void transformFilter();

   /// Conversion
   /// make a sparse copy of the current matrix
   inline void toSparse(SpMatrix<T>& matrix) const;
   /// make a sparse copy of the current matrix
   inline void toSparseTrans(SpMatrix<T>& matrixTrans);
   /// make a reference of the matrix to a vector vec 
   inline void toVect(Vector<T>& vec) const;
   /// Accessor
   inline INTM V() const { return 1;};
   /// merge two dictionaries
   inline void merge(const Matrix<T>& B, Matrix<T>& C) const;
   /// extract the rows of a matrix corresponding to a binary mask
   inline void copyMask(Matrix<T>& out, Vector<bool>& mask) const;

   typedef Vector<T> col;
   static const bool is_sparse = false;

   protected:
   /// Forbid lazy copies
   explicit Matrix(const Matrix<T>& matrix);
   /// Forbid lazy copies
   Matrix<T>& operator=(const Matrix<T>& matrix);

   /// is the data allocation external or not
   bool _externAlloc;
   /// pointer to the data
   T* _X;
   /// number of rows
   INTM _m;
   /// number of columns
   INTM _n;

};

/// Class for dense vector
template<typename T> class Vector {
   friend class SpMatrix<T>;
   friend class Matrix<T>;
   friend class SpVector<T>;
   public:
   /// Empty constructor
   Vector();
   /// Constructor. Create a new vector of size n
   Vector(INTM n);
   /// Constructor with existing data
   Vector(T* X, INTM n);
   /// Copy constructor
   explicit Vector(const Vector<T>& vec);

   /// Destructor
   virtual ~Vector();

   /// Accessors
   /// Print the vector to std::cout
   inline void print(const char* name) const;
   /// returns the index of the largest value
   inline INTM max() const;
   /// returns the index of the minimum value
   inline INTM min() const;
   /// returns the maximum value
   inline T maxval() const;
   /// returns the minimum value
   inline T minval() const;
   /// returns the index of the value with largest magnitude
   inline INTM fmax() const;
   /// returns the index of the value with smallest magnitude
   inline INTM fmin() const;
   /// returns the maximum magnitude
   inline T fmaxval() const;
   /// returns the minimum magnitude
   inline T fminval() const;
   /// returns a reference to X[index]
   inline T& operator[](const INTM index);
   /// returns X[index]
   inline T operator[](const INTM index) const;
   /// make a copy of x
   inline void copy(const Vector<T>& x);
   /// returns the size of the vector
   inline INTM n() const { return _n; };
   /// returns a modifiable reference of the data, DANGEROUS
   inline T* rawX() const { return _X; };
   /// change artificially the size of the vector, DANGEROUS
   inline void fakeSize(const INTM n) { _n = n; };
   /// generate logarithmically spaced values
   inline void logspace(const INTM n, const T a, const T b);
   inline INTM nnz() const;

   /// Modifiers
   /// Set all values to zero
   inline void setZeros();
   /// resize the vector
   inline void resize(const INTM n);
   /// change the data of the vector
   inline void setPointer(T* X, const INTM n);
   inline void setData(T* X, const INTM n) { this->setPointer(X,n); };
   inline void refSubVec(INTM i, INTM n, Vector<T>& mat) const { mat.setData(_X+i,n); };

   /// put a random permutation of size n (for integral vectors)
   inline void randperm(int n);  
   /// put random values in the vector (White Gaussian Noise)
   inline void setAleat();
   /// clear the vector
   inline void clear();
   /// performs soft-thresholding of the vector
   inline void softThrshold(const T nu);
   inline void softThrsholdScal(Vector<T>& out, const T nu, const T s);
   inline void hardThrshold(const T nu);
   /// performs soft-thresholding of the vector
   inline void thrsmax(const T nu);
   inline void thrsmin(const T nu);
   inline void thrsabsmin(const T nu);
   /// performs soft-thresholding of the vector
   inline void thrshold(const T nu);
   /// performs soft-thresholding of the vector
   inline void thrsPos();
   /// set each value of the vector to val
   inline void set(const T val);
   inline void setn(const INTM n) { _n = n; }; //DANGEROUS
   inline bool alltrue() const;
   inline bool allfalse() const;

   /// Algebric operations
   /// returns ||A||_2
   inline T nrm2() const;
   /// returns ||A||_2^2
   inline T nrm2sq() const;
   /// returns  A'x
   inline T dot(const Vector<T>& x) const;
   /// returns A'x, when x is sparse
   inline T dot(const SpVector<T>& x) const;
   /// A <- A + a*x
   inline void add(const Vector<T>& x, const T a = 1.0);
   /// A <- A + a*x
   inline void add(const SpVector<T>& x, const T a = 1.0);
   /// adds a to each value in the vector
   inline void add(const T a);
   /// A <- b*A + a*x
   inline void add_scal(const Vector<T>& x, const T a = 1.0, const T b = 0);
   /// A <- A - x
   inline void sub(const Vector<T>& x);
   /// A <- A + a*x
   inline void sub(const SpVector<T>& x);
   /// A <- A ./ x
   inline void div(const Vector<T>& x);
   /// A <- x ./ y
   inline void div(const Vector<T>& x, const Vector<T>& y);
   /// A <- x .^ 2
   inline void sqr(const Vector<T>& x);
   /// A <- 1 ./ sqrt(x) 
   inline void sqr();
   /// A <- 1 ./ sqrt(A) 
   inline void Sqrt(const Vector<T>& x);
   /// A <- 1 ./ sqrt(x) 
   inline void Sqrt();
   /// A <- 1 ./ sqrt(x) 
   inline void Invsqrt(const Vector<T>& x);
   /// A <- 1 ./ sqrt(A) 
   inline void Invsqrt();
   /// A <- 1./x
   inline void inv(const Vector<T>& x);
   /// A <- 1./A
   inline void inv();
   /// A <- x .* y
   inline void mult(const Vector<T>& x, const Vector<T>& y);
   inline void mult_elementWise(const Vector<T>& B, Vector<T>& C) const { C.mult(*this,B); };
   /// normalize the vector
   inline void normalize();
   /// normalize the vector
   inline void normalize2();
   /// whiten
   inline void whiten(Vector<T>& mean, const bool pattern = false);
   /// whiten
   inline void whiten(Vector<T>& mean, const
         Vector<T>& mask);
   /// whiten
   inline void whiten(const INTM V);
   /// whiten
   inline T mean();
   /// whiten
   inline T std();
   /// compute the Kuhlback-Leiber divergence
   inline T KL(const Vector<T>& X);
   /// whiten
   inline void unwhiten(Vector<T>& mean, const bool pattern = false);
   /// scale the vector by a
   inline void scal(const T a);
   /// A <- -A
   inline void neg();
   /// replace each value by its exponential
   inline void exp();
   /// replace each value by its logarithm
   inline void log();
   /// replace each value by its absolute value
   inline void abs_vec();
   /// replace each value by its exponential
   inline void logexp();
   /// replace each value by its exponential
   inline T softmax(const int y);
   /// computes the sum of the magnitudes of the vector
   inline T asum() const;
   inline T lzero() const;
   /// compute the sum of the differences
   inline T afused() const;
   /// returns the sum of the vector
   inline T sum() const;
   /// puts in signs, the sign of each point in the vector
   inline void sign(Vector<T>& signs) const;
   /// projects the vector onto the l1 ball of radius thrs,
   /// returns true if the returned vector is null
   inline void l1project(Vector<T>& out, const T thrs, const bool simplex = false) const;
   inline void l1project_weighted(Vector<T>& out, const Vector<T>& weights, const T thrs, const bool residual = false) const;
   inline void l1l2projectb(Vector<T>& out, const T thrs, const T gamma, const bool pos = false,
         const int mode = 1);
   inline void sparseProject(Vector<T>& out, const T thrs,   const int mode = 1, const T lambda1 = 0,
         const T lambda2 = 0, const T lambda3 = 0, const bool pos = false);
   inline void project_sft(const Vector<int>& labels, const int clas);
   inline void project_sft_binary(const Vector<T>& labels);
   /// projects the vector onto the l1 ball of radius thrs,
   /// projects the vector onto the l1 ball of radius thrs,
   /// returns true if the returned vector is null
   inline void l1l2project(Vector<T>& out, const T thrs, const T gamma, const bool pos = false) const;
   inline void fusedProject(Vector<T>& out, const T lambda1, const T lambda2, const int itermax);
   inline void fusedProjectHomotopy(Vector<T>& out, const T lambda1,const T lambda2,const T lambda3 = 0,
         const bool penalty = true);
   /// projects the vector onto the l1 ball of radius thrs,
   /// sort the vector
   inline void sort(Vector<T>& out, const bool mode) const;
   /// sort the vector
   inline void sort(const bool mode);
   //// sort the vector
   inline void sort2(Vector<T>& out, Vector<INTM>& key, const bool mode) const;
   /// sort the vector
   inline void sort2(Vector<INTM>& key, const bool mode);
   /// sort the vector
   inline void applyBayerPattern(const int offset);


   /// Conversion
   /// make a sparse copy 
   inline void toSparse(SpVector<T>& vec) const;
   /// extract the rows of a matrix corresponding to a binary mask
   inline void copyMask(Vector<T>& out, Vector<bool>& mask) const;



   private:
   /// = operator, 
   Vector<T>& operator=(const Vector<T>& vec);

   /// if the data has been externally allocated
   bool _externAlloc;
   /// data
   T* _X;
   /// size of the vector
   INTM _n;
};


/// Sparse Matrix class, CSC format
template<typename T> class SpMatrix : public Data<T>, public AbstractMatrixB<T> {
   friend class Matrix<T>;
   friend class SpVector<T>;
   public:
   /// Constructor, CSC format, existing data
   SpMatrix(T* v, INTM* r, INTM* pB, INTM* pE, INTM m, INTM n, INTM nzmax);
   /// Constructor, new m x n matrix, with at most nzmax non-zeros values
   SpMatrix(INTM m, INTM n, INTM nzmax);
   /// Empty constructor
   SpMatrix();

   /// Destructor
   ~SpMatrix();

   /// Accessors
   /// reference the column i INTMo vec
   inline void refCol(INTM i, SpVector<T>& vec) const;
   /// returns pB[i]
   inline INTM pB(const INTM i) const { return _pB[i]; };
   /// returns r[i]
   inline INTM r(const INTM i) const { return _r[i]; };
   /// returns v[i]
   inline T v(const INTM i) const { return _v[i]; };
   /// returns the maximum number of non-zero elements
   inline INTM nzmax() const { return _nzmax; };
   /// returns the number of rows
   inline INTM n() const { return _n; };
   /// returns the number of columns
   inline INTM m() const { return _m; };
   /// returns the number of columns
   inline INTM V() const { return 1; };
   /// returns X[index]
   inline T operator[](const INTM index) const;
   void getData(Vector<T>& data, const INTM index) const;
   void setData(T* v, INTM* r, INTM* pB, INTM* pE, INTM m, INTM n, INTM nzmax);

   void getGroup(Matrix<T>& data, const vector_groups& groups,
         const INTM i) const ;
   /// print the sparse matrix
   inline void print(const string& name) const;
   /// compute the sum of the matrix elements
   inline T asum() const;
   /// compute the sum of the matrix elements
   inline T normFsq() const;
   /// Direct access to _pB
   inline INTM* pB() const { return _pB; };
   /// Direct access to _pE
   inline INTM* pE() const { return _pE; };
   /// Direct access to _r
   inline INTM* r() const { return _r; };
   /// Direct access to _v
   inline T* v() const { return _v; };
   /// number of nonzeros elements
   inline INTM nnz() const { return _pB[_n]; };
   inline void add_direct(const SpMatrix<T>& mat, const T a);
   inline void copy_direct(const SpMatrix<T>& mat);
   inline T dot_direct(const SpMatrix<T>& mat) const;

   /// Modifiers
   /// clear the matrix
   inline void clear();
   /// resize the matrix
   inline void resize(const INTM m, const INTM n, const INTM nzmax);
   /// scale the matrix by a
   inline void scal(const T a) const;

   /// Algebraic operations
   /// aat <- A*A'
   inline void AAt(Matrix<T>& aat) const;
   /// aat <- A(:,indices)*A(:,indices)'
   inline void AAt(Matrix<T>& aat, const Vector<INTM>& indices) const;
   /// aat <- sum_i w_i A(:,i)*A(:,i)'
   inline void wAAt(const Vector<T>& w, Matrix<T>& aat) const;
   /// XAt <- X*A'
   inline void XAt(const Matrix<T>& X, Matrix<T>& XAt) const;
   /// XAt <- X(:,indices)*A(:,indices)'
   inline void XAt(const Matrix<T>& X, Matrix<T>& XAt, 
         const Vector<INTM>& indices) const;
   /// XAt <- sum_i w_i X(:,i)*A(:,i)'
   inline void wXAt( const Vector<T>& w, const Matrix<T>& X, 
         Matrix<T>& XAt, const int numthreads=-1) const;
   inline void XtX(Matrix<T>& XtX) const;

   /// y <- A'*x
   inline void multTrans(const Vector<T>& x, Vector<T>& y,
         const T alpha = 1.0, const T beta = 0.0) const;
   inline void multTrans(const SpVector<T>& x, Vector<T>& y,
         const T alpha = 1.0, const T beta = 0.0) const;
   /// perform b = alpha*A*x + beta*b, when x is sparse
   inline void mult(const SpVector<T>& x, Vector<T>& b, 
         const T alpha = 1.0, const T beta = 0.0) const;
   /// perform b = alpha*A*x + beta*b, when x is sparse
   inline void mult(const Vector<T>& x, Vector<T>& b, 
         const T alpha = 1.0, const T beta = 0.0) const;
   /// perform C = a*A*B + b*C, possibly transposing A or B.
   inline void mult(const Matrix<T>& B, Matrix<T>& C, 
         const bool transA = false, const bool transB = false,
         const T a = 1.0, const T b = 0.0) const;
   /// perform C = a*B*A + b*C, possibly transposing A or B.
   inline void multSwitch(const Matrix<T>& B, Matrix<T>& C, 
         const bool transA = false, const bool transB = false,
         const T a = 1.0, const T b = 0.0) const;
   /// perform C = a*B*A + b*C, possibly transposing A or B.
   inline void mult(const SpMatrix<T>& B, Matrix<T>& C, const bool transA = false,
         const bool transB = false, const T a = 1.0,
         const T b = 0.0) const;
   /// make a copy of the matrix mat in the current matrix
   inline void copyTo(Matrix<T>& mat) const { this->toFull(mat); };
   /// dot product;
   inline T dot(const Matrix<T>& x) const;
   inline void copyRow(const INTM i, Vector<T>& x) const;
   inline void sum_cols(Vector<T>& sum) const;
   inline void copy(const SpMatrix<T>& mat);

   /// Conversions
   /// copy the sparse matrix into a dense matrix
   inline void toFull(Matrix<T>& matrix) const;
   /// copy the sparse matrix into a dense transposed matrix
   inline void toFullTrans(Matrix<T>& matrix) const;

   /// use the data from v, r for _v, _r
   inline void convert(const Matrix<T>&v, const Matrix<INTM>& r,
         const INTM K);
   /// use the data from v, r for _v, _r
   inline void convert2(const Matrix<T>&v, const Vector<INTM>& r,
         const INTM K);
   /// returns the l2 norms ^2 of the columns
   inline void norm_2sq_cols(Vector<T>& norms) const;
   /// returns the l0 norms of the columns
   inline void norm_0_cols(Vector<T>& norms) const;
   /// returns the l1 norms of the columns
   inline void norm_1_cols(Vector<T>& norms) const;
   inline void addVecToCols(const Vector<T>& diag, const T a = 1.0);
   inline void addVecToColsWeighted(const Vector<T>& diag, const T* weights, const T a = 1.0);

   typedef SpVector<T> col;
   static const bool is_sparse = true;

   private:
   /// forbid copy constructor
   explicit SpMatrix(const SpMatrix<T>& matrix);
   SpMatrix<T>& operator=(const SpMatrix<T>& matrix);

   /// if the data has been externally allocated
   bool _externAlloc;
   /// data
   T* _v;
   /// row indices 
   INTM* _r;
   /// indices of the beginning of columns
   INTM* _pB;
   /// indices of the end of columns
   INTM* _pE;
   /// number of rows
   INTM _m;
   /// number of columns
   INTM _n;
   /// number of non-zero values
   INTM _nzmax;
};

/// Sparse vector class
template <typename T> class SpVector {
   friend class Matrix<T>;
   friend class SpMatrix<T>;
   friend class Vector<T>;
   public:
   /// Constructor, of the sparse vector of size L.
   SpVector(T* v, INTM* r, INTM L, INTM nzmax);
   /// Constructor, allocates nzmax slots
   SpVector(INTM nzmax);
   /// Empty constructor
   SpVector();

   /// Destructor
   ~SpVector();

   /// Accessors
   /// returns the length of the vector
   inline T nzmax() const { return _nzmax; };
   /// returns the length of the vector
   inline T length() const { return _L; };
   /// computes the sum of the magnitude of the elements
   inline T asum() const;
   /// computes the l2 norm ^2 of the vector
   inline T nrm2sq() const;
   /// computes the l2 norm  of the vector
   inline T nrm2() const;
   /// computes the linf norm  of the vector
   inline T fmaxval() const;
   /// print the vector to std::cerr
   inline void print(const string& name) const;
   /// create a reference on the vector r
   inline void refIndices(Vector<INTM>& indices) const;
   /// creates a reference on the vector val
   inline void refVal(Vector<T>& val) const;
   /// access table r
   inline INTM r(const INTM i) const { return _r[i]; };
   /// access table r
   inline T v(const INTM i) const { return _v[i]; };
   inline T* rawX() const { return _v; };
   inline INTM* rawR() const { return _r; };

   /// 
   inline INTM L() const { return _L; };
   /// 
   inline void setL(const INTM L) { _L=L; };
   /// a <- a.^2
   inline void sqr();
   /// dot product
   inline T dot(const SpVector<T>& vec) const;
   /// dot product
   inline T dot(const Vector<T>& vec) const;
   /// dot product
   inline void scal(const T a);

   /// Modifiers
   /// clears the vector
   inline void clear();
   /// resizes the vector
   inline void resize(const INTM nzmax);

   /// resize the vector as a sparse matrix
   void inline toSpMatrix(SpMatrix<T>& out,
         const INTM m, const INTM n) const;
  /// resize the vector as a sparse matrix
   void inline toFull(Vector<T>& out) const;


   private:
   /// forbids lazy copies
   explicit SpVector(const SpVector<T>& vector);
   SpVector<T>& operator=(const SpVector<T>& vector);

   /// external allocation 
   bool _externAlloc;
   /// data
   T* _v;
   /// indices
   INTM* _r;
   /// length
   INTM _L;
   /// maximum number of nonzeros elements
   INTM _nzmax;
};


/// Class representing the product of two matrices
template<typename T> class ProdMatrix : public AbstractMatrix<T> {
   public:
      ProdMatrix();
      /// Constructor. Matrix D'*D is represented
      ProdMatrix(const Matrix<T>& D, const bool high_memory = true);
      /// Constructor. Matrix D'*X is represented
      ProdMatrix(const Matrix<T>& D, const Matrix<T>& X, const bool high_memory = true);
      /// Constructor, D'*X is represented, with optional transpositions
      /*ProdMatrix(const SpMatrix<T>& D, const Matrix<T>& X,
        const bool transD = false, const bool transX = false);*/

      /// Destructor
      ~ProdMatrix() { delete(_DtX);} ;

      /// set_matrices
      inline void setMatrices(const Matrix<T>& D, const bool high_memory=true);
      inline void setMatrices(const Matrix<T>& D, 
            const Matrix<T>& X, const bool high_memory=true);
      /// compute DtX(:,i)
      inline void copyCol(const INTM i, Vector<T>& DtXi) const;
      /// compute DtX(:,i)
      inline void extract_rawCol(const INTM i,T* DtXi) const;
      /// compute DtX(:,i)
      virtual void add_rawCol(const INTM i, T* DtXi, const T a) const;
      /// add something to the diagonal
      void inline addDiag(const T diag);
      /// add something to the diagonal
      void inline diag(Vector<T>& diag) const;
      /// returns the number of columns
      inline INTM n() const { return _n;};
      /// returns the number of rows
      inline INTM m() const { return _m;};
      /// returns the value of an index
      inline T operator()(const INTM index1, const INTM index2) const;
      /// returns the value of an index
      inline T operator[](const INTM index) const;

   private:
      /// Depending on the mode, DtX is a matrix, or two matrices
      Matrix<T>* _DtX;
      const Matrix<T>* _X;
      const Matrix<T>* _D;
      bool _high_memory;
      INTM _n;
      INTM _m;
      T _addDiag;
};


/* ************************************
 * Implementation of the class Matrix 
 * ************************************/

/// Constructor with existing data X of an m x n matrix
template <typename T> Matrix<T>::Matrix(T* X, INTM m, INTM n) :
   _externAlloc(true), _X(X), _m(m), _n(n) {  };


/// Constructor for a new m x n matrix
template <typename T> Matrix<T>::Matrix(INTM m, INTM n) :
   _externAlloc(false), _m(m), _n(n)  {
#pragma omp critical
      {
         _X= new T[_n*_m];
      }
   };

/// Empty constructor
template <typename T> Matrix<T>::Matrix() :
   _externAlloc(false), _X(NULL), _m(0), _n(0) { };

/// Destructor
template <typename T> Matrix<T>::~Matrix() {
   clear();
};

/// Return a modifiable reference to X(i,j)
template <typename T> inline T& Matrix<T>::operator()(const INTM i, const INTM j) {
   return _X[j*_m+i];
};

/// Return the value X(i,j)
template <typename T> inline T Matrix<T>::operator()(const INTM i, const INTM j) const {
   return _X[j*_m+i];
};

/// Print the matrix to std::cout
template <typename T> inline void Matrix<T>::print(const string& name) const {
   // std::cerr << name << std::endl;
   // std::cerr << _m << " x " << _n << std::endl;
   for (INTM i = 0; i<_m; ++i) {
      for (INTM j = 0; j<_n; ++j) {
         // printf("%10.5g ",static_cast<double>(_X[j*_m+i]));
         //         std::cerr << _X[j*_m+i] << " ";
      }
      // printf("\n ");
      //std::cerr << std::endl;
   }
   // printf("\n ");
};

/// Copy the column i INTMo x
template <typename T> inline void Matrix<T>::copyCol(const INTM i, Vector<T>& x) const {
   // assert(i >= 0 && i<_n);
   x.resize(_m);
   cblas_copy<T>(_m,_X+i*_m,1,x._X,1);
};

/// Copy the column i INTMo x
template <typename T> inline void Matrix<T>::copyRow(const INTM i, Vector<T>& x) const {
   // assert(i >= 0 && i<_m);
   x.resize(_n);
   cblas_copy<T>(_n,_X+i,_m,x._X,1);
};


/// Copy the column i INTMo x
template <typename T> inline void Matrix<T>::extract_rawCol(const INTM i, T* x) const {
   // assert(i >= 0 && i<_n);
   cblas_copy<T>(_m,_X+i*_m,1,x,1);
};

/// Copy the column i INTMo x
template <typename T> inline void Matrix<T>::add_rawCol(const INTM i, T* x, const T a) const {
   // assert(i >= 0 && i<_n);
   cblas_axpy<T>(_m,a,_X+i*_m,1,x,1);
};

/// Copy the column i INTMo x
template <typename T> inline void Matrix<T>::getData(Vector<T>& x, const INTM i) const {
   this->copyCol(i,x);
};

template <typename T> inline void Matrix<T>::getGroup(Matrix<T>& data, 
      const vector_groups& groups, const INTM i) const {
   const group& gr = groups[i];
   const INTM N = gr.size();
   data.resize(_m,N);
   INTM count=0;
   for (group::const_iterator it = gr.begin(); it != gr.end(); ++it) {
      cblas_copy<T>(_m,_X+(*it)*_m,1,data._X+count*_m,1);
      ++count;
   }
};


/// Reference the column i into the vector x
template <typename T> inline void Matrix<T>::refCol(INTM i, Vector<T>& x) const {
   // assert(i >= 0 && i<_n);
   x.clear();
   x._X=_X+i*_m;
   x._n=_m;
   x._externAlloc=true; 
};

/// Reference the column i to i+n INTMo the Matrix mat
template <typename T> inline void Matrix<T>::refSubMat(INTM i, INTM n, Matrix<T>& mat) const {
   mat.setData(_X+i*_m,_m,n);
}

/// Check wether the columns of the matrix are normalized or not
template <typename T> inline bool Matrix<T>::isNormalized() const {
   for (INTM i = 0; i<_n; ++i) {
      T norm=cblas_nrm2<T>(_m,_X+_m*i,1);
      if (fabs(norm - 1.0) > 1e-6) return false;
   }
   return true;
};

/// clean a dictionary matrix
template <typename T>
inline void Matrix<T>::clean() {
   this->normalize();
   Matrix<T> G;
   this->XtX(G);
   T* prG = G._X;
   /// remove the diagonal
   for (INTM i = 0; i<_n; ++i) {
      for (INTM j = i+1; j<_n; ++j) {
         if (prG[i*_n+j] > 0.99) {
            // remove nasty column j and put random values inside
            Vector<T> col;
            this->refCol(j,col);
            col.setAleat();
            col.normalize();
         }
      }
   }
};

/// return the 1D-index of the value of greatest magnitude
template <typename T> inline INTM Matrix<T>::fmax() const {
   return cblas_iamax<T>(_n*_m,_X,1);
};

/// return the value of greatest magnitude
template <typename T> inline T Matrix<T>::fmaxval() const {
   return _X[cblas_iamax<T>(_n*_m,_X,1)];
};


/// return the 1D-index of the value of lowest magnitude
template <typename T> inline INTM Matrix<T>::fmin() const {
   return cblas_iamin<T>(_n*_m,_X,1);
};

/// extract a sub-matrix of a symmetric matrix
template <typename T> inline void Matrix<T>::subMatrixSym(
      const Vector<INTM>& indices, Matrix<T>& subMatrix) const {
   INTM L = indices.n();
   subMatrix.resize(L,L);
   T* out = subMatrix._X;
   INTM* rawInd = indices.rawX();
   for (INTM i = 0; i<L; ++i)
      for (INTM j = 0; j<=i; ++j)
         out[i*L+j]=_X[rawInd[i]*_n+rawInd[j]];
   subMatrix.fillSymmetric();
};

/// Resize the matrix
template <typename T> inline void Matrix<T>::resize(INTM m, INTM n, const bool set_zeros) {
   if (_n==n && _m==m) return;
   clear();
   _n=n;
   _m=m;
   _externAlloc=false;
#pragma omp critical
   {
      _X=new T[_n*_m];
   }
   if (set_zeros)
      setZeros();
};

/// Change the data in the matrix
template <typename T> inline void Matrix<T>::setData(T* X, INTM m, INTM n) {
   clear();
   _X=X;
   _m=m;
   _n=n;
   _externAlloc=true;
};

/// Set all the values to zero
template <typename T> inline void Matrix<T>::setZeros() {
   memset(_X,0,_n*_m*sizeof(T));
};

/// Set all the values to a scalar
template <typename T> inline void Matrix<T>::set(const T a) {
   for (INTM i = 0; i<_n*_m; ++i) _X[i]=a;
};

/// Clear the matrix
template <typename T> inline void Matrix<T>::clear() {
   if (!_externAlloc) delete[](_X);
   _n=0;
   _m=0;
   _X=NULL;
   _externAlloc=true;
};

/// Put white Gaussian noise in the matrix 
template <typename T> inline void Matrix<T>::setAleat() {
   for (INTM i = 0; i<_n*_m; ++i) _X[i]=normalDistrib<T>();
};

/// set the matrix to the identity
template <typename T> inline void Matrix<T>::eye() {
   this->setZeros();
   for (INTM i = 0; i<MIN(_n,_m); ++i) _X[i*_m+i] = T(1.0);
};

/// Normalize all columns to unit l2 norm
template <typename T> inline void Matrix<T>::normalize() {
   //T constant = 1.0/sqrt(_m);
   for (INTM i = 0; i<_n; ++i) {
      T norm=cblas_nrm2<T>(_m,_X+_m*i,1);
      if (norm > 1e-10) {
         T invNorm=1.0/norm;
         cblas_scal<T>(_m,invNorm,_X+_m*i,1);
      }  else {
         // for (INTM j = 0; j<_m; ++j) _X[_m*i+j]=constant;
         Vector<T> d;
         this->refCol(i,d);
         d.setAleat();
         d.normalize();
      } 
   }
};

/// Normalize all columns which l2 norm is greater than one.
template <typename T> inline void Matrix<T>::normalize2() {
   for (INTM i = 0; i<_n; ++i) {
      T norm=cblas_nrm2<T>(_m,_X+_m*i,1);
      if (norm > 1.0) {
         T invNorm=1.0/norm;
         cblas_scal<T>(_m,invNorm,_X+_m*i,1);
      } 
   }
};

/// center the matrix
template <typename T> inline void Matrix<T>::center() {
   for (INTM i = 0; i<_n; ++i) {
      Vector<T> col;
      this->refCol(i,col);
      T sum = col.sum();
      col.add(-sum/static_cast<T>(_m));
   }
};

/// center the matrix
template <typename T> inline void Matrix<T>::center_rows() {
   Vector<T> mean_rows(_m);
   mean_rows.setZeros();
   for (INTM i = 0; i<_n; ++i) 
      for (INTM j = 0; j<_m; ++j) 
         mean_rows[j] += _X[i*_m+j];
   mean_rows.scal(T(1.0)/_n);
   for (INTM i = 0; i<_n; ++i) 
      for (INTM j = 0; j<_m; ++j) 
         _X[i*_m+j] -= mean_rows[j];
};

/// center the matrix and keep the center values
template <typename T> inline void Matrix<T>::center(Vector<T>& centers) {
   centers.resize(_n);
   for (INTM i = 0; i<_n; ++i) {
      Vector<T> col;
      this->refCol(i,col);
      T sum = col.sum()/static_cast<T>(_m);
      centers[i]=sum;
      col.add(-sum);
   }
};

/// scale the matrix by the a
template <typename T> inline void Matrix<T>::scal(const T a) {
   cblas_scal<T>(_n*_m,a,_X,1);
};

/// make a copy of the matrix mat in the current matrix
template <typename T> inline void Matrix<T>::copy(const Matrix<T>& mat) {
   resize(mat._m,mat._n);
//   cblas_copy<T>(_m*_n,mat._X,1,_X,1);
   memcpy(_X,mat._X,_m*_n*sizeof(T));
};

/// make a copy of the matrix mat in the current matrix
template <typename T> inline void Matrix<T>::copyRef(const Matrix<T>& mat) {
   this->setData(mat.rawX(),mat.m(),mat.n());
};

/// make the matrix symmetric by copying the upper-right part
/// INTMo the lower-left part
template <typename T> inline void Matrix<T>::fillSymmetric() {
   for (INTM i = 0; i<_n; ++i) {
      for (INTM j =0; j<i; ++j) {
         _X[j*_m+i]=_X[i*_m+j];
      }
   }
};
template <typename T> inline void Matrix<T>::fillSymmetric2() {
   for (INTM i = 0; i<_n; ++i) {
      for (INTM j =0; j<i; ++j) {
         _X[i*_m+j]=_X[j*_m+i];
      }
   }
};


template <typename T> inline void Matrix<T>::whiten(const INTM V) {
   const INTM sizePatch=_m/V;
   for (INTM i = 0; i<_n; ++i) {
      for (INTM j = 0; j<V; ++j) {
         T mean = 0;
         for (INTM k = 0; k<sizePatch; ++k) {
            mean+=_X[i*_m+sizePatch*j+k];
         }
         mean /= sizePatch;
         for (INTM k = 0; k<sizePatch; ++k) {
            _X[i*_m+sizePatch*j+k]-=mean;
         }
      }
   }
};

template <typename T> inline void Matrix<T>::whiten(Vector<T>& mean, const bool pattern) {
   mean.setZeros();
   if (pattern) {
      const INTM n =static_cast<INTM>(sqrt(static_cast<T>(_m)));
      INTM count[4];
      for (INTM i = 0; i<4; ++i) count[i]=0;
      for (INTM i = 0; i<_n; ++i) {
         INTM offsetx=0;
         for (INTM j = 0; j<n; ++j) {
            offsetx= (offsetx+1) % 2;
            INTM offsety=0;
            for (INTM k = 0; k<n; ++k) {
               offsety= (offsety+1) % 2;
               mean[2*offsetx+offsety]+=_X[i*_m+j*n+k];
               count[2*offsetx+offsety]++;
            }
         }
      }
      for (INTM i = 0; i<4; ++i)
         mean[i] /= count[i];
      for (INTM i = 0; i<_n; ++i) {
         INTM offsetx=0;
         for (INTM j = 0; j<n; ++j) {
            offsetx= (offsetx+1) % 2;
            INTM offsety=0;
            for (INTM k = 0; k<n; ++k) {
               offsety= (offsety+1) % 2;
               _X[i*_m+j*n+k]-=mean[2*offsetx+offsety];
            }
         }
      }
   } else  {
      const INTM V = mean.n();
      const INTM sizePatch=_m/V;
      for (INTM i = 0; i<_n; ++i) {
         for (INTM j = 0; j<V; ++j) {
            for (INTM k = 0; k<sizePatch; ++k) {
               mean[j]+=_X[i*_m+sizePatch*j+k];
            }
         }
      }
      mean.scal(T(1.0)/(_n*sizePatch));
      for (INTM i = 0; i<_n; ++i) {
         for (INTM j = 0; j<V; ++j) {
            for (INTM k = 0; k<sizePatch; ++k) {
               _X[i*_m+sizePatch*j+k]-=mean[j];
            }
         }
      }
   }
};

template <typename T> inline void Matrix<T>::whiten(Vector<T>& mean, const
      Vector<T>& mask) {
   const INTM V = mean.n();
   const INTM sizePatch=_m/V;
   mean.setZeros();
   for (INTM i = 0; i<_n; ++i) {
      for (INTM j = 0; j<V; ++j) {
         for (INTM k = 0; k<sizePatch; ++k) {
            mean[j]+=_X[i*_m+sizePatch*j+k];
         }
      }
   }
   for (INTM i = 0; i<V; ++i)
      mean[i] /= _n*cblas_asum(sizePatch,mask._X+i*sizePatch,1);
   for (INTM i = 0; i<_n; ++i) {
      for (INTM j = 0; j<V; ++j) {
         for (INTM k = 0; k<sizePatch; ++k) {
            if (mask[sizePatch*j+k])
               _X[i*_m+sizePatch*j+k]-=mean[j];
         }
      }
   }
};


template <typename T> inline void Matrix<T>::unwhiten(Vector<T>& mean, const bool pattern) {
   if (pattern) {
      const INTM n =static_cast<INTM>(sqrt(static_cast<T>(_m)));
      for (INTM i = 0; i<_n; ++i) {
         INTM offsetx=0;
         for (INTM j = 0; j<n; ++j) {
            offsetx= (offsetx+1) % 2;
            INTM offsety=0;
            for (INTM k = 0; k<n; ++k) {
               offsety= (offsety+1) % 2;
               _X[i*_m+j*n+k]+=mean[2*offsetx+offsety];
            }
         }
      }
   } else {
      const INTM V = mean.n();
      const INTM sizePatch=_m/V;
      for (INTM i = 0; i<_n; ++i) {
         for (INTM j = 0; j<V; ++j) {
            for (INTM k = 0; k<sizePatch; ++k) {
               _X[i*_m+sizePatch*j+k]+=mean[j];
            }
         }
      }
   }
};

/// Transpose the current matrix and put the result in the matrix
/// trans
template <typename T> inline void Matrix<T>::transpose(Matrix<T>& trans) {
   trans.resize(_n,_m);
   T* out = trans._X;
   for (INTM i = 0; i<_n; ++i)
      for (INTM j = 0; j<_m; ++j)
         out[j*_n+i] = _X[i*_m+j];
};

/// A <- -A
template <typename T> inline void Matrix<T>::neg() {
   for (INTM i = 0; i<_n*_m; ++i) _X[i]=-_X[i];
};

template <typename T> inline void Matrix<T>::incrDiag() {
   for (INTM i = 0; i<MIN(_n,_m); ++i) ++_X[i*_m+i];
};

template <typename T> inline void Matrix<T>::addDiag(
      const Vector<T>& diag) {
   T* d= diag.rawX();
   for (INTM i = 0; i<MIN(_n,_m); ++i) _X[i*_m+i] += d[i];
};

template <typename T> inline void Matrix<T>::addDiag(
      const T diag) {
   for (INTM i = 0; i<MIN(_n,_m); ++i) _X[i*_m+i] += diag;
};

template <typename T> inline void Matrix<T>::addToCols(
      const Vector<T>& cent) {
   Vector<T> col;
   for (INTM i = 0; i<_n; ++i) {
      this->refCol(i,col);      
      col.add(cent[i]);
   }
};

template <typename T> inline void Matrix<T>::addVecToCols(
      const Vector<T>& vec, const T a) {
   Vector<T> col;
   for (INTM i = 0; i<_n; ++i) {
      this->refCol(i,col);      
      col.add(vec,a);
   }
};

/// perform a rank one approximation uv' using the power method
/// u0 is an initial guess for u (can be empty).
template <typename T> inline void Matrix<T>::svdRankOne(const Vector<T>& u0,
      Vector<T>& u, Vector<T>& v) const {
   int i;
   const int max_iter=MAX(_m,MAX(_n,200));
   const T eps=1e-10;
   u.resize(_m);
   v.resize(_n);
   T norm=u0.nrm2();
   Vector<T> up(u0);
   if (norm < EPSILON) up.setAleat();
   up.normalize();
   multTrans(up,v);
   for (i = 0; i<max_iter; ++i) {
      mult(v,u);
      norm=u.nrm2();
      u.scal(1.0/norm);
      multTrans(u,v);
      T theta=u.dot(up);
      if (i > 10 && (1 - fabs(theta)) < eps) break;
      up.copy(u);
   }
};

template <typename T> inline void Matrix<T>::singularValues(Vector<T>& u) const {
   u.resize(MIN(_m,_n));
   if (_m > 10*_n) {
      Matrix<T> XtX;
      this->XtX(XtX);
      syev<T>(no,lower,_n,XtX.rawX(),_n,u.rawX());
      u.thrsPos();
      u.Sqrt();
   } else if (_n > 10*_m) { 
      Matrix<T> XXt;
      this->XXt(XXt);
      syev<T>(no,lower,_m,XXt.rawX(),_m,u.rawX());
      u.thrsPos();
      u.Sqrt();
   } else {
      T* vu = NULL;
      T* vv = NULL;
      Matrix<T> copyX;
      copyX.copy(*this);
      gesvd<T>(no,no,_m,_n,copyX._X,_m,u.rawX(),vu,1,vv,1);
   }
};

template <typename T> inline void Matrix<T>::svd(Matrix<T>& U, Vector<T>& S, Matrix<T>&V) const {
   const INTM num_eig=MIN(_m,_n);
   S.resize(num_eig);
   U.resize(_m,num_eig);
   V.resize(num_eig,_n);
   if (_m > 10*_n) {
      Matrix<T> Vt(_n,_n);
      this->XtX(Vt);
      syev<T>(allV,lower,_n,Vt.rawX(),_n,S.rawX());
      S.thrsPos();
      S.Sqrt();
      this->mult(Vt,U);
      Vt.transpose(V);
      Vector<T> inveigs;
      inveigs.copy(S);
      for (INTM i = 0; i<num_eig; ++i) 
         if (S[i] > 1e-10) {
            inveigs[i]=T(1.0)/S[i];
         } else {
            inveigs[i]=T(1.0);
         }
      U.multDiagRight(inveigs);
   } else if (_n > 10*_m) {
      this->XXt(U);
      syev<T>(allV,lower,_m,U.rawX(),_m,S.rawX());
      S.thrsPos();
      S.Sqrt();
      U.mult(*this,V,true,false);
      Vector<T> inveigs;
      inveigs.copy(S);
      for (INTM i = 0; i<num_eig; ++i) 
         if (S[i] > 1e-10) {
            inveigs[i]=T(1.0)/S[i];
         } else {
            inveigs[i]=T(1.0);
         }
      V.multDiagLeft(inveigs);
   } else {
      Matrix<T> copyX;
      copyX.copy(*this);
      gesvd<T>(reduced,reduced,_m,_n,copyX._X,_m,S.rawX(),U.rawX(),_m,V.rawX(),num_eig);
   }
};

/// find the eigenvector corresponding to the largest eigenvalue
/// when the current matrix is symmetric. u0 is the initial guess.
/// using two iterations of the power method
template <typename T> inline void Matrix<T>::eigLargestSymApprox(
      const Vector<T>& u0, Vector<T>& u) const {
   int i,j;
   const int max_iter=100;
   const T eps=10e-6;
   u.copy(u0);
   T norm = u.nrm2();
   T theta;
   u.scal(1.0/norm);
   Vector<T> up(u);
   Vector<T> uor(u);
   T lambda=T();

   for (j = 0; j<2;++j) {
      up.copy(u);
      for (i = 0; i<max_iter; ++i) {
         mult(up,u);
         norm = u.nrm2();
         u.scal(1.0/norm);
         theta=u.dot(up);
         if ((1 - fabs(theta)) < eps) break;
         up.copy(u);
      }
      lambda+=theta*norm;
      if (isnan(lambda)) {
         // std::cerr << "eigLargestSymApprox failed" << std::endl;
         // exit(1);
      }
      if (j == 1 && lambda < eps) {
         u.copy(uor);
         break;
      }
      if (theta >= 0) break;
      u.copy(uor);
      for (i = 0; i<_m; ++i) _X[i*_m+i]-=lambda;
   }
};

/// find the eigenvector corresponding to the eivenvalue with the 
/// largest magnitude when the current matrix is symmetric,
/// using the power method. It 
/// returns the eigenvalue. u0 is an initial guess for the 
/// eigenvector.
template <typename T> inline T Matrix<T>::eigLargestMagnSym(
      const Vector<T>& u0, Vector<T>& u) const {
   const int max_iter=1000;
   const T eps=10e-6;
   u.copy(u0);
   T norm = u.nrm2();
   u.scal(1.0/norm);
   Vector<T> up(u);
   T lambda=T();

   for (int i = 0; i<max_iter; ++i) {
      mult(u,up);
      u.copy(up);
      norm=u.nrm2();
      if (norm > 0) u.scal(1.0/norm);
      if (norm == 0 || fabs(norm-lambda)/norm < eps) break;
      lambda=norm;
   }
   return norm;
};

/// returns the value of the eigenvalue with the largest magnitude
/// using the power iteration.
template <typename T> inline T Matrix<T>::eigLargestMagnSym() const {
   const int max_iter=1000;
   const T eps=10e-6;
   Vector<T> u(_m);
   u.setAleat();
   T norm = u.nrm2();
   u.scal(1.0/norm);
   Vector<T> up(u);
   T lambda=T();
   for (int i = 0; i<max_iter; ++i) {
      mult(u,up);
      u.copy(up);
      norm=u.nrm2();
      if (fabs(norm-lambda) < eps) break;
      lambda=norm;
      u.scal(1.0/norm);
   }
   return norm;
};

/// inverse the matrix when it is symmetric
template <typename T> inline void Matrix<T>::invSym() {
   sytri<T>(upper,_n,_X,_n);
   this->fillSymmetric();
};

/// perform b = alpha*A'x + beta*b
template <typename T> inline void Matrix<T>::multTrans(const Vector<T>& x, 
      Vector<T>& b, const T a, const T c) const {
   b.resize(_n);
   //   assert(x._n == _m && b._n == _n);
   cblas_gemv<T>(CblasColMajor,CblasTrans,_m,_n,a,_X,_m,x._X,1,c,b._X,1);
};

/// perform b = A'x, when x is sparse
template <typename T> inline void Matrix<T>::multTrans(const SpVector<T>& x, 
      Vector<T>& b, const T alpha, const T beta) const {
   b.resize(_n);
   Vector<T> col;
   if (beta) {
      for (INTM i = 0; i<_n; ++i) {
         refCol(i,col);
         b._X[i] = alpha && col.dot(x);
      }
   } else {

      for (INTM i = 0; i<_n; ++i) {
         refCol(i,col);
         b._X[i] = beta*b._X[i]+alpha*col.dot(x);
      }
   }
};

template <typename T> inline void Matrix<T>::multTrans(
      const Vector<T>& x, Vector<T>& b, const Vector<bool>& active) const {
   b.setZeros();
   Vector<T> col;
   bool* pr_active=active.rawX();
   for (INTM i = 0; i<_n; ++i) {
      if (pr_active[i]) {
         this->refCol(i,col);
         b._X[i]=col.dot(x);
      }
   }
};

/// perform b = alpha*A*x+beta*b
template <typename T> inline void Matrix<T>::mult(const Vector<T>& x, 
      Vector<T>& b, const T a, const T c) const {
   //  assert(x._n == _n && b._n == _m);
   b.resize(_m);
   cblas_gemv<T>(CblasColMajor,CblasNoTrans,_m,_n,a,_X,_m,x._X,1,c,b._X,1);
};

/// perform b = alpha*A*x + beta*b, when x is sparse
template <typename T> inline void Matrix<T>::mult(const SpVector<T>& x, 
      Vector<T>& b, const T a, const T a2) const {
   if (!a2) {
      b.setZeros();
   } else if (a2 != 1.0) {
      b.scal(a2);
   }
   if (a == 1.0) {
      for (INTM i = 0; i<x._L; ++i) {
         cblas_axpy<T>(_m,x._v[i],_X+x._r[i]*_m,1,b._X,1);
      }
   } else {
      for (INTM i = 0; i<x._L; ++i) {
         cblas_axpy<T>(_m,a&&x._v[i],_X+x._r[i]*_m,1,b._X,1);
      }
   }
};

/// perform C = a*A*B + b*C, possibly transposing A or B.
template <typename T> inline void Matrix<T>::mult(const Matrix<T>& B, 
      Matrix<T>& C, const bool transA, const bool transB,
      const T a, const T b) const {
   CBLAS_TRANSPOSE trA,trB;
   INTM m,k,n;
   if (transA) {
      trA = CblasTrans;
      m = _n;
      k = _m;
   } else {
      trA= CblasNoTrans;
      m = _m;
      k = _n;
   }
   if (transB) {
      trB = CblasTrans;
      n = B._m; 
      //  assert(B._n == k);
   } else {
      trB = CblasNoTrans;
      n = B._n; 
      // assert(B._m == k);
   }
   C.resize(m,n);
   cblas_gemm<T>(CblasColMajor,trA,trB,m,n,k,a,_X,_m,B._X,B._m,
         b,C._X,C._m);
};

/// perform C = a*B*A + b*C, possibly transposing A or B.
template <typename T>
inline void Matrix<T>::multSwitch(const Matrix<T>& B, Matrix<T>& C, 
      const bool transA, const bool transB,
      const T a, const T b) const {
   B.mult(*this,C,transB,transA,a,b);
};

/// perform C = A*B, when B is sparse
template <typename T>
inline void Matrix<T>::mult(const SpMatrix<T>& B, Matrix<T>& C,
      const bool transA, const bool transB,
      const T a, const T b) const {
   if (transA) {
      if (transB) {
         C.resize(_n,B.m());
         if (b) {
            C.scal(b);
         } else {
            C.setZeros();
         }
         Vector<T> rowC(B.m());
         Vector<T> colA;
         for (INTM i = 0; i<_n; ++i) {
            this->refCol(i,colA);
            B.mult(colA,rowC,a);
            C.addRow(i,rowC,a);
         }
      } else {
         C.resize(_n,B.n());
         if (b) {
            C.scal(b);
         } else {
            C.setZeros();
         }
         Vector<T> colC;
         SpVector<T> colB;
         for (INTM i = 0; i<B.n(); ++i) {
            C.refCol(i,colC);
            B.refCol(i,colB);
            this->multTrans(colB,colC,a,T(1.0));
         }
      }
   } else {
      if (transB) {
         C.resize(_m,B.m());
         if (b) {
            C.scal(b);
         } else {
            C.setZeros();
         }
         Vector<T> colA;
         SpVector<T> colB;
         for (INTM i = 0; i<_n; ++i) {
            this->refCol(i,colA);
            B.refCol(i,colB);
            C.rank1Update(colA,colB,a);
         }
      } else {
         C.resize(_m,B.n());
         if (b) {
            C.scal(b);
         } else {
            C.setZeros();
         }
         Vector<T> colC;
         SpVector<T> colB;
         for (INTM i = 0; i<B.n(); ++i) {
            C.refCol(i,colC);
            B.refCol(i,colB);
            this->mult(colB,colC,a,T(1.0));
         }
      }
   };
}


/// mult by a diagonal matrix on the left
template <typename T>
   inline void Matrix<T>::multDiagLeft(const Vector<T>& diag) {
      if (diag.n() != _m)
         return;
      T* d = diag.rawX();
      for (INTM i = 0; i< _n; ++i) {
         for (INTM j = 0; j<_m; ++j) {
            _X[i*_m+j] *= d[j];
         }
      }
   };

/// mult by a diagonal matrix on the right
template <typename T> inline void Matrix<T>::multDiagRight(
      const Vector<T>& diag) {
   if (diag.n() != _n)
      return;
   T* d = diag.rawX();
   for (INTM i = 0; i< _n; ++i) {
      for (INTM j = 0; j<_m; ++j) {
         _X[i*_m+j] *= d[i];
      }
   }
};

/// C = A .* B, elementwise multiplication
template <typename T> inline void Matrix<T>::mult_elementWise(
      const Matrix<T>& B, Matrix<T>& C) const {
   // assert(_n == B._n && _m == B._m);
   C.resize(_m,_n);
   vMul<T>(_n*_m,_X,B._X,C._X);
};

/// C = A .* B, elementwise multiplication
template <typename T> inline void Matrix<T>::div_elementWise(
      const Matrix<T>& B, Matrix<T>& C) const {
   // assert(_n == B._n && _m == B._m);
   C.resize(_m,_n);
   vDiv<T>(_n*_m,_X,B._X,C._X);
};


/// XtX = A'*A
template <typename T> inline void Matrix<T>::XtX(Matrix<T>& xtx) const {
   xtx.resize(_n,_n);
   cblas_syrk<T>(CblasColMajor,CblasUpper,CblasTrans,_n,_m,T(1.0),
         _X,_m,T(),xtx._X,_n);
   xtx.fillSymmetric();
};

/// XXt = A*At
template <typename T> inline void Matrix<T>::XXt(Matrix<T>& xxt) const {
   xxt.resize(_m,_m);
   cblas_syrk<T>(CblasColMajor,CblasUpper,CblasNoTrans,_m,_n,T(1.0),
         _X,_m,T(),xxt._X,_m);
   xxt.fillSymmetric();
};

/// XXt = A*A' where A is an upper triangular matrix
template <typename T> inline void Matrix<T>::upperTriXXt(Matrix<T>& XXt, const INTM L) const {
   XXt.resize(L,L);
   for (INTM i = 0; i<L; ++i) {
      cblas_syr<T>(CblasColMajor,CblasUpper,i+1,T(1.0),_X+i*_m,1,XXt._X,L);
   }
   XXt.fillSymmetric();
}


/// extract the diagonal
template <typename T> inline void Matrix<T>::diag(Vector<T>& dv) const {
   INTM size_diag=MIN(_n,_m);
   dv.resize(size_diag);
   T* const d = dv.rawX();
   for (INTM i = 0; i<size_diag; ++i)
      d[i]=_X[i*_m+i];
};

/// set the diagonal
template <typename T> inline void Matrix<T>::setDiag(const Vector<T>& dv) {
   INTM size_diag=MIN(_n,_m);
   T* const d = dv.rawX();
   for (INTM i = 0; i<size_diag; ++i)
      _X[i*_m+i]=d[i];
};

/// set the diagonal
template <typename T> inline void Matrix<T>::setDiag(const T val) {
   INTM size_diag=MIN(_n,_m);
   for (INTM i = 0; i<size_diag; ++i)
      _X[i*_m+i]=val;
};


/// each element of the matrix is replaced by its exponential
template <typename T> inline void Matrix<T>::exp() {
   vExp<T>(_n*_m,_X,_X);
};
template <typename T> inline void Matrix<T>::Sqrt() {
   vSqrt<T>(_n*_m,_X,_X);
};

template <typename T> inline void Matrix<T>::Invsqrt() {
   vInvSqrt<T>(_n*_m,_X,_X);
};
/// return vec1'*A*vec2, where vec2 is sparse
template <typename T> inline T Matrix<T>::quad(
      const SpVector<T>& vec) const {
   T sum = T();
   INTM L = vec._L;
   INTM* r = vec._r;
   T* v = vec._v;
   for (INTM i = 0; i<L; ++i)
      for (INTM j = 0; j<L; ++j)
         sum += _X[r[i]*_m+r[j]]*v[i]*v[j];
   return sum;
};

template <typename T> inline void Matrix<T>::quad_mult(const Vector<T>& vec1,
      const SpVector<T>& vec2, Vector<T>& y, const T a, const T b) const {
   const INTM size_y= y.n();
   const INTM nn = _n/size_y;
   //y.resize(size_y);
   //y.setZeros();
   Matrix<T> tmp;
   for (INTM i = 0; i<size_y; ++i) {
      tmp.setData(_X+(i*nn)*_m,_m,nn);
      y[i]=b*y[i]+a*tmp.quad(vec1,vec2);
   }
}

/// return vec'*A*vec when vec is sparse
template <typename T> inline T Matrix<T>::quad(
      const Vector<T>& vec1, const SpVector<T>& vec) const {
   T sum = T();
   INTM L = vec._L;
   INTM* r = vec._r;
   T* v = vec._v;
   Vector<T> col;
   for (INTM i = 0; i<L; ++i) {
      this->refCol(r[i],col);
      sum += v[i]*col.dot(vec1);
   }
   return sum;
};

/// add alpha*mat to the current matrix
template <typename T> inline void Matrix<T>::add(const Matrix<T>& mat, const T alpha) {
   // assert(mat._m == _m && mat._n == _n);
   cblas_axpy<T>(_n*_m,alpha,mat._X,1,_X,1);
};

/// add alpha*mat to the current matrix
template <typename T> inline T Matrix<T>::dot(const Matrix<T>& mat) const {
   // assert(mat._m == _m && mat._n == _n);
   return cblas_dot<T>(_n*_m,mat._X,1,_X,1);
};


/// add alpha to the current matrix
template <typename T> inline void Matrix<T>::add(const T alpha) {
   for (INTM i = 0; i<_n*_m; ++i) _X[i]+=alpha;
};

/// substract the matrix mat to the current matrix
template <typename T> inline void Matrix<T>::sub(const Matrix<T>& mat) {
   vSub<T>(_n*_m,_X,mat._X,_X);
};

/// compute the sum of the magnitude of the matrix values
template <typename T> inline T Matrix<T>::asum() const {
   return cblas_asum<T>(_n*_m,_X,1);
};

/// returns the trace of the matrix
template <typename T> inline T Matrix<T>::trace() const {
   T sum=T();
   INTM m = MIN(_n,_m);
   for (INTM i = 0; i<m; ++i) 
      sum += _X[i*_m+i];
   return sum;
};

/// return ||A||_F
template <typename T> inline T Matrix<T>::normF() const {
   return cblas_nrm2<T>(_n*_m,_X,1);
};

template <typename T> inline T Matrix<T>::mean() const {
   Vector<T> vec;
   this->toVect(vec);
   return vec.mean();
};

/// return ||A||_F^2
template <typename T> inline T Matrix<T>::normFsq() const {
   return cblas_dot<T>(_n*_m,_X,1,_X,1);
};

/// return ||At||_{inf,2}
template <typename T> inline T Matrix<T>::norm_inf_2_col() const {
   Vector<T> col;
   T max = -1.0;
   for (INTM i = 0; i<_n; ++i) {
      refCol(i,col);
      T norm_col = col.nrm2();
      if (norm_col > max) 
         max = norm_col;
   }
   return max;
};

/// return ||At||_{1,2}
template <typename T> inline T Matrix<T>::norm_1_2_col() const {
   Vector<T> col;
   T sum = 0.0;
   for (INTM i = 0; i<_n; ++i) {
      refCol(i,col);
      sum += col.nrm2();
   }
   return sum;
};

/// returns the l2 norms of the columns
template <typename T> inline void Matrix<T>::norm_2_rows(
      Vector<T>& norms) const {
   norms.resize(_m);
   norms.setZeros();
   for (INTM i = 0; i<_n; ++i) 
      for (INTM j = 0; j<_m; ++j) 
         norms[j] += _X[i*_m+j]*_X[i*_m+j];
   for (INTM j = 0; j<_m; ++j) 
      norms[j]=sqrt(norms[j]);
};

/// returns the l2 norms of the columns
template <typename T> inline void Matrix<T>::norm_2sq_rows(
      Vector<T>& norms) const {
   norms.resize(_m);
   norms.setZeros();
   for (INTM i = 0; i<_n; ++i) 
      for (INTM j = 0; j<_m; ++j) 
         norms[j] += _X[i*_m+j]*_X[i*_m+j];
};


/// returns the l2 norms of the columns
template <typename T> inline void Matrix<T>::norm_2_cols(
      Vector<T>& norms) const {
   norms.resize(_n);
   Vector<T> col;
   for (INTM i = 0; i<_n; ++i) {
      refCol(i,col);
      norms[i] = col.nrm2();
   }
};


/// returns the linf norms of the columns
template <typename T> inline void Matrix<T>::norm_inf_cols(Vector<T>& norms) const {
   norms.resize(_n);
   Vector<T> col;
   for (INTM i = 0; i<_n; ++i) {
      refCol(i,col);
      norms[i] = col.fmaxval();
   }
};

/// returns the linf norms of the columns
template <typename T> inline void Matrix<T>::norm_inf_rows(Vector<T>& norms) const {
   norms.resize(_m);
   norms.setZeros();
   for (INTM i = 0; i<_n; ++i) 
      for (INTM j = 0; j<_m; ++j) 
         norms[j] = MAX(abs<T>(_X[i*_m+j]),norms[j]);
};

/// returns the linf norms of the columns
template <typename T> inline void Matrix<T>::norm_l1_rows(Vector<T>& norms) const {
   norms.resize(_m);
   norms.setZeros();
   for (INTM i = 0; i<_n; ++i) 
      for (INTM j = 0; j<_m; ++j) 
         norms[j] += abs<T>(_X[i*_m+j]);
};



/// returns the l2 norms of the columns
template <typename T> inline void Matrix<T>::norm_2sq_cols(
      Vector<T>& norms) const {
   norms.resize(_n);
   Vector<T> col;
   for (INTM i = 0; i<_n; ++i) {
      refCol(i,col);
      norms[i] = col.nrm2sq();
   }
};

template <typename T> 
inline void Matrix<T>::sum_cols(Vector<T>& sum) const {
   sum.resize(_m);
   sum.setZeros();
   Vector<T> tmp;
   for (INTM i = 0; i<_n; ++i) {
      this->refCol(i,tmp);
      sum.add(tmp);
   }
};

/// Compute the mean of the columns
template <typename T> inline void Matrix<T>::meanCol(Vector<T>& mean) const {
   Vector<T> ones(_n);
   ones.set(T(1.0/_n));
   this->mult(ones,mean,1.0,0.0);
};

/// Compute the mean of the rows
template <typename T> inline void Matrix<T>::meanRow(Vector<T>& mean) const {
   Vector<T> ones(_m);
   ones.set(T(1.0/_m));
   this->multTrans(ones,mean,1.0,0.0);
};


/// fill the matrix with the row given
template <typename T> inline void Matrix<T>::fillRow(const Vector<T>& row) {
   for (INTM i = 0; i<_n; ++i) {
      T val = row[i];
      for (INTM j = 0; j<_m; ++j) {
         _X[i*_m+j]=val;
      }
   }
};

/// fill the matrix with the row given
template <typename T> inline void Matrix<T>::extractRow(const INTM j,
      Vector<T>& row) const {
   row.resize(_n);
   for (INTM i = 0; i<_n; ++i) {
      row[i]=_X[i*_m+j];
   }
};

/// fill the matrix with the row given
template <typename T> inline void Matrix<T>::setRow(const INTM j,
      const Vector<T>& row) {
   for (INTM i = 0; i<_n; ++i) {
      _X[i*_m+j]=row[i];
   }
};

/// fill the matrix with the row given
template <typename T> inline void Matrix<T>::addRow(const INTM j,
      const Vector<T>& row, const T a) {
   if (a==1.0) {
      for (INTM i = 0; i<_n; ++i) {
         _X[i*_m+j]+=row[i];
      }
   } else {
      for (INTM i = 0; i<_n; ++i) {
         _X[i*_m+j]+=a*row[i];
      }
   }
};


/// perform soft-thresholding of the matrix, with the threshold nu
template <typename T> inline void Matrix<T>::softThrshold(const T nu) {
   Vector<T> vec;
   toVect(vec);
   vec.softThrshold(nu);
};

/// perform soft-thresholding of the matrix, with the threshold nu
template <typename T> inline void Matrix<T>::hardThrshold(const T nu) {
   Vector<T> vec;
   toVect(vec);
   vec.hardThrshold(nu);
};


/// perform thresholding of the matrix, with the threshold nu
template <typename T> inline void Matrix<T>::thrsmax(const T nu) {
   Vector<T> vec;
   toVect(vec);
   vec.thrsmax(nu);
};

/// perform thresholding of the matrix, with the threshold nu
template <typename T> inline void Matrix<T>::thrsmin(const T nu) {
   Vector<T> vec;
   toVect(vec);
   vec.thrsmin(nu);
};


/// perform soft-thresholding of the matrix, with the threshold nu
template <typename T> inline void Matrix<T>::inv_elem() {
   Vector<T> vec;
   toVect(vec);
   vec.inv();
};

/// perform soft-thresholding of the matrix, with the threshold nu
template <typename T> inline void Matrix<T>::blockThrshold(const T nu,
      const INTM sizeGroup) {
   for (INTM i = 0; i<_n; ++i) {
      INTM j;
      for (j = 0; j<_m-sizeGroup+1; j+=sizeGroup) {
         T nrm=0;
         for (INTM k = 0; k<sizeGroup; ++k)
            nrm += _X[i*_m +j+k]*_X[i*_m +j+k];
         nrm=sqrt(nrm);
         if (nrm < nu) {
            for (INTM k = 0; k<sizeGroup; ++k)
               _X[i*_m +j+k]=0;
         } else {
            T scal = (nrm-nu)/nrm;
            for (INTM k = 0; k<sizeGroup; ++k)
               _X[i*_m +j+k]*=scal;
         }
      }
      j -= sizeGroup;
      for ( ; j<_m; ++j)
         _X[j]=softThrs<T>(_X[j],nu);
   }
}

template <typename T> inline void Matrix<T>::sparseProject(Matrix<T>& Y, 
      const T thrs,   const int mode, const T lambda1,
      const T lambda2, const T lambda3, const bool pos,
      const int numThreads) {

   int NUM_THREADS=init_omp(numThreads);
   Vector<T>* XXT= new Vector<T>[NUM_THREADS];
   for (int i = 0; i<NUM_THREADS; ++i) {
      XXT[i].resize(_m);
   }

   int i;
#pragma omp parallel for private(i) 
   for (i = 0; i< _n; ++i) {
#ifdef _OPENMP
      int numT=omp_get_thread_num();
#else
      int numT=0;
#endif
      Vector<T> Xi;
      this->refCol(i,Xi);
      Vector<T> Yi;
      Y.refCol(i,Yi);
      Vector<T>& XX = XXT[numT];
      XX.copy(Xi);
      XX.sparseProject(Yi,thrs,mode,lambda1,lambda2,lambda3,pos);
   }
   delete[](XXT);
};


/// perform soft-thresholding of the matrix, with the threshold nu
template <typename T> inline void Matrix<T>::thrsPos() {
   Vector<T> vec;
   toVect(vec);
   vec.thrsPos();
};


/// perform A <- A + alpha*vec1*vec2'
template <typename T> inline void Matrix<T>::rank1Update(
      const Vector<T>& vec1, const Vector<T>& vec2, const T alpha) {
   cblas_ger<T>(CblasColMajor,_m,_n,alpha,vec1._X,1,vec2._X,1,_X,_m);
};

/// perform A <- A + alpha*vec1*vec2', when vec1 is sparse
template <typename T> inline void Matrix<T>::rank1Update(
      const SpVector<T>& vec1, const Vector<T>& vec2, const T alpha) {
   INTM* r = vec1._r;
   T* v = vec1._v;
   T* X2 = vec2._X;
   // assert(vec2._n == _n);
   if (alpha == 1.0) {
      for (INTM i = 0; i<_n; ++i) {
         for (INTM j = 0; j<vec1._L; ++j) {
            _X[i*_m+r[j]] += v[j]*X2[i];
         }
      }
   } else {
      for (INTM i = 0; i<_n; ++i) {
         for (INTM j = 0; j<vec1._L; ++j) {
            _X[i*_m+r[j]] += alpha*v[j]*X2[i];
         }
      }
   }
};

template <typename T>
inline void Matrix<T>::rank1Update_mult(const Vector<T>& vec1, 
      const Vector<T>& vec1b,
      const SpVector<T>& vec2,
      const T alpha) {
   const INTM nn = vec1b.n();
   const INTM size_A = _n/nn;
   Matrix<T> tmp;
   for (INTM i = 0; i<nn; ++i) {
      tmp.setData(_X+i*size_A*_m,_m,size_A);
      tmp.rank1Update(vec1,vec2,alpha*vec1b[i]);
   }
};

/// perform A <- A + alpha*vec1*vec2', when vec1 is sparse
template <typename T> inline void Matrix<T>::rank1Update(
      const SpVector<T>& vec1, const SpVector<T>& vec2, const T alpha) {
   INTM* r = vec1._r;
   T* v = vec1._v;
   T* v2 = vec2._v;
   INTM* r2 = vec2._r;
   if (alpha == 1.0) {
      for (INTM i = 0; i<vec2._L; ++i) {
         for (INTM j = 0; j<vec1._L; ++j) {
            _X[r2[i]*_m+r[j]] += v[j]*v2[i];
         }
      }
   } else {
      for (INTM i = 0; i<vec2._L; ++i) {
         for (INTM j = 0; j<vec1._L; ++j) {
            _X[r[i]*_m+r[j]] += alpha*v[j]*v2[i];
         }
      }
   }
};


/// perform A <- A + alpha*vec1*vec2', when vec2 is sparse
template <typename T> inline void Matrix<T>::rank1Update(
      const Vector<T>& vec1, const SpVector<T>& vec2, const T alpha) {
   INTM* r = vec2._r;
   T* v = vec2._v;
   Vector<T> Xi;
   for (INTM i = 0; i<vec2._L; ++i) {
      this->refCol(r[i],Xi);
      Xi.add(vec1,v[i] && alpha);
   }
};

/// perform A <- A + alpha*vec1*vec1', when vec1 is sparse
template <typename T> inline void Matrix<T>::rank1Update(
      const SpVector<T>& vec1, const T alpha) {
   INTM* r = vec1._r;
   T* v = vec1._v;
   if (alpha == 1.0) {
      for (INTM i = 0; i<vec1._L; ++i) {
         for (INTM j = 0; j<vec1._L; ++j) {
            _X[r[i]*_m+r[j]] += v[j]*v[i];
         }
      }
   } else {
      for (INTM i = 0; i<vec1._L; ++i) {
         for (INTM j = 0; j<vec1._L; ++j) {
            _X[_m*r[i]+r[j]] += alpha*v[j]*v[i];
         }
      }
   }
};


/// compute x, such that b = Ax, 
template <typename T> inline void Matrix<T>::conjugateGradient(
      const Vector<T>& b, Vector<T>& x, const T tol, const int itermax) const {
   Vector<T> R,P,AP;
   R.copy(b);
   this->mult(x,R,T(-1.0),T(1.0));
   P.copy(R);
   int k = 0;
   T normR = R.nrm2sq();
   T alpha;
   while (normR > tol && k < itermax) {
      this->mult(P,AP);
      alpha = normR/P.dot(AP);
      x.add(P,alpha);
      R.add(AP,-alpha);
      T tmp = R.nrm2sq();
      P.scal(tmp/normR);
      normR = tmp;
      P.add(R,T(1.0));
      ++k;
   };
};

template <typename T> inline void Matrix<T>::drop(char* fileName) const {
   std::ofstream f;
   f.precision(12);
   f.flags(std::ios_base::scientific);
   f.open(fileName, ofstream::trunc);
   // std::cout << "Matrix written in " << fileName << std::endl;
   for (INTM i = 0; i<_n; ++i) {
      for (INTM j = 0; j<_m; ++j) 
         f << _X[i*_m+j] << " ";
      f << std::endl;
   }
   f.close();
};

/// compute a Nadaraya Watson estimator
template <typename T> inline void Matrix<T>::NadarayaWatson(
      const Vector<INTM>& ind, const T sigma) {
   if (ind.n() != _n) return;

   init_omp(MAX_THREADS);

   const INTM Ngroups=ind.maxval();
   INTM i;
#pragma omp parallel for private(i)
   for (i = 1; i<=Ngroups; ++i) {
      Vector<INTM> indicesGroup(_n);
      INTM count = 0;
      for (INTM j = 0; j<_n; ++j)
         if (ind[j] == i) indicesGroup[count++]=j;
      Matrix<T> Xm(_m,count);
      Vector<T> col, col2;
      for (INTM j= 0; j<count; ++j) {
         this->refCol(indicesGroup[j],col);
         Xm.refCol(j,col2);
         col2.copy(col);
      }
      Vector<T> norms;
      Xm.norm_2sq_cols(norms);
      Matrix<T> weights;
      Xm.XtX(weights);
      weights.scal(T(-2.0));
      Vector<T> ones(Xm.n());
      ones.set(T(1.0));
      weights.rank1Update(ones,norms);
      weights.rank1Update(norms,ones);
      weights.scal(-sigma);
      weights.exp();
      Vector<T> den;
      weights.mult(ones,den);
      den.inv();
      weights.multDiagRight(den);
      Matrix<T> num;
      Xm.mult(weights,num);
      for (INTM j= 0; j<count; ++j) {
         this->refCol(indicesGroup[j],col);
         num.refCol(j,col2);
         col.copy(col2);
      }
   }
};

/// make a sparse copy of the current matrix
template <typename T> inline void Matrix<T>::toSparse(SpMatrix<T>& out) const {
   out.clear();
   INTM count=0;
   INTM* pB;
#pragma omp critical
   {
      pB=new INTM[_n+1];
   }
   INTM* pE=pB+1;
   for (INTM i = 0; i<_n*_m; ++i) 
      if (_X[i] != 0) ++count;
   INTM* r;
   T* v;
#pragma omp critical
   {
      r=new INTM[count];
      v=new T[count];
   }
   count=0;
   for (INTM i = 0; i<_n; ++i) {
      pB[i]=count;
      for (INTM j = 0; j<_m; ++j) {
         if (_X[i*_m+j] != 0) {
            v[count]=_X[i*_m+j];
            r[count++]=j;
         }
      }
      pE[i]=count;
   }
   out._v=v;
   out._r=r;
   out._pB=pB;
   out._pE=pE;
   out._m=_m;
   out._n=_n;
   out._nzmax=count;
   out._externAlloc=false;
};

/// make a sparse copy of the current matrix
template <typename T> inline void Matrix<T>::toSparseTrans(
      SpMatrix<T>& out) {
   out.clear();
   INTM count=0;
   INTM* pB;
#pragma omp critical
   {
      pB=new INTM[_m+1];
   }
   INTM* pE=pB+1;
   for (INTM i = 0; i<_n*_m; ++i) 
      if (_X[i] != 0) ++count;
   INTM* r;
   T* v;
#pragma omp critical
   {
      r=new INTM[count];
      v=new T[count];
   }
   count=0;
   for (INTM i = 0; i<_m; ++i) {
      pB[i]=count;
      for (INTM j = 0; j<_n; ++j) {
         if (_X[i+j*_m] != 0) {
            v[count]=_X[j*_m+i];
            r[count++]=j;
         }
      }
      pE[i]=count;
   }
   out._v=v;
   out._r=r;
   out._pB=pB;
   out._pE=pE;
   out._m=_n;
   out._n=_m;
   out._nzmax=count;
   out._externAlloc=false;
};

/// make a reference of the matrix to a vector vec 
template <typename T> inline void Matrix<T>::toVect(
      Vector<T>& vec) const {
   vec.clear();
   vec._externAlloc=true;
   vec._n=_n*_m;
   vec._X=_X;
};

/// merge two dictionaries
template <typename T> inline void Matrix<T>::merge(const Matrix<T>& B,
      Matrix<T>& C) const {
   const INTM K =_n; 
   Matrix<T> G;
   this->mult(B,G,true,false);
   std::list<INTM> list;
   for (INTM i = 0; i<G.n(); ++i) {
      Vector<T> g;
      G.refCol(i,g);
      T fmax=g.fmaxval();
      if (fmax < 0.995) list.push_back(i);
   }
   C.resize(_m,K+list.size());

   for (INTM i = 0; i<K; ++i) {
      Vector<T> d, d2;
      C.refCol(i,d);
      this->refCol(i,d2);
      d.copy(d2);
   }
   INTM count=0;
   for (std::list<INTM>::const_iterator it = list.begin();
         it != list.end(); ++it) {
      Vector<T> d, d2;
      C.refCol(K+count,d);
      B.refCol(*it,d2);
      d.copy(d2);
      ++count;
   }
};

/* ***********************************
 * Implementation of the class Vector
 * ***********************************/


/// Empty constructor
template <typename T> Vector<T>::Vector() :
   _externAlloc(true), _X(NULL),  _n(0) {  };

/// Constructor. Create a new vector of size n
template <typename T> Vector<T>::Vector(INTM n) :
   _externAlloc(false), _n(n) {
#pragma omp critical
      {
         _X=new T[_n];
      }
   };

/// Constructor with existing data
template <typename T> Vector<T>::Vector(T* X, INTM n) :
   _externAlloc(true), _X(X),  _n(n) {  };

/// Copy constructor
template <typename T> Vector<T>::Vector(const Vector<T>& vec) :
   _externAlloc(false), _n(vec._n) {
#pragma omp critical
      {
         _X=new T[_n];
      }
      cblas_copy<T>(_n,vec._X,1,_X,1);
   };

/// Destructor
template <typename T> Vector<T>::~Vector() {
   clear();
};

/// Print the vector to std::cout
template <> inline void Vector<double>::print(const char* name) const {
   // printf("%s, %d\n",name,(int)_n);
   for (INTM i = 0; i<_n; ++i) {
      // printf("%g ",_X[i]);
   }
   // printf("\n");
};

/// Print the vector to std::cout
template <> inline void Vector<float>::print(const char* name) const {
   // printf("%s, %d\n",name,(int)_n);
   for (INTM i = 0; i<_n; ++i) {
      // printf("%g ",_X[i]);
   }
   // printf("\n");
};

/// Print the vector to std::cout
template <> inline void Vector<int>::print(const char* name) const {
   // printf("%s, %d\n",name,(int)_n);
   for (INTM i = 0; i<_n; ++i) {
      // printf("%d ",_X[i]);
   }
   // printf("\n");
};

/// Print the vector to std::cout
template <> inline void Vector<bool>::print(const char* name) const {
   // printf("%s, %d\n",name,(int)_n);
   for (INTM i = 0; i<_n; ++i) {
      // printf("%d ",_X[i] ? 1 : 0);
   }
   // printf("\n");
};

/// returns the index of the largest value
template <typename T> inline INTM Vector<T>::max() const {
   INTM imax=0;
   T max=_X[0];
   for (INTM j = 1; j<_n; ++j) {
      T cur = _X[j];
      if (cur > max) {
         imax=j;
         max = cur;
      }
   }
   return imax;
};

/// returns the index of the minimum value
template <typename T> inline INTM Vector<T>::min() const {
   INTM imin=0;
   T min=_X[0];
   for (INTM j = 1; j<_n; ++j) {
      T cur = _X[j];
      if (cur < min) {
         imin=j;
         min = cur;
      }
   }
   return imin;
};

/// returns the maximum value
template <typename T> inline T Vector<T>::maxval() const {
   return _X[this->max()];
};

/// returns the minimum value
template <typename T> inline T Vector<T>::minval() const {
   return _X[this->min()];
};

/// returns the maximum magnitude
template <typename T> inline T Vector<T>::fmaxval() const {
   return fabs(_X[this->fmax()]);
};

/// returns the minimum magnitude
template <typename T> inline T Vector<T>::fminval() const {
   return fabs(_X[this->fmin()]);
};

template <typename T>
inline void Vector<T>::logspace(const INTM n, const T a, const T b) {
   T first=log10(a);
   T last=log10(b);
   T step = (last-first)/(n-1);
   this->resize(n);
   _X[0]=first;
   for (INTM i = 1; i<_n; ++i)
      _X[i]=_X[i-1]+step;
   for (INTM i = 0; i<_n; ++i)
      _X[i]=pow(T(10.0),_X[i]);
}

template <typename T>
inline INTM Vector<T>::nnz() const {
   INTM sum=0;
   for (INTM i = 0; i<_n; ++i) 
      if (_X[i] != T()) ++sum;
   return sum;
};
/// generate logarithmically spaced values
template <>
inline void Vector<INTM>::logspace(const INTM n, const INTM a, const INTM b) {
   Vector<double> tmp(n);
   tmp.logspace(n,double(a),double(b));
   this->resize(n);
   _X[0]=a;
   _X[n-1]=b;
   for (INTM i = 1; i<_n-1; ++i) {
      INTM candidate=static_cast<INTM>(floor(static_cast<double>(tmp[i])));
      _X[i]= candidate > _X[i-1] ? candidate : _X[i-1]+1;
   }
}

/// returns the index of the value with largest magnitude
template <typename T> inline INTM Vector<T>::fmax() const {
   return cblas_iamax<T>(_n,_X,1);
};

/// returns the index of the value with smallest magnitude
template <typename T> inline INTM Vector<T>::fmin() const {
   return cblas_iamin<T>(_n,_X,1);
};

/// returns a reference to X[index]
template <typename T> inline T& Vector<T>::operator[] (const INTM i) {
   // assert(i>=0 && i<_n);
   return _X[i];
};

/// returns X[index]
template <typename T> inline T Vector<T>::operator[] (const INTM i) const {
   // assert(i>=0 && i<_n);
   return _X[i];
};

/// make a copy of x
template <typename T> inline void Vector<T>::copy(const Vector<T>& x) {
   this->resize(x.n());
   //cblas_copy<T>(_n,x._X,1,_X,1);
   memcpy(_X,x._X,_n*sizeof(T));
};

/// Set all values to zero
template <typename T> inline void Vector<T>::setZeros() {
   memset(_X,0,_n*sizeof(T));
};

/// resize the vector
template <typename T> inline void Vector<T>::resize(const INTM n) {
   if (_n == n) return;
   clear();
#pragma omp critical
   {
      _X=new T[n];
   }
   _n=n;
   _externAlloc=false;
   this->setZeros();
};

/// change the data of the vector
template <typename T> inline void Vector<T>::setPointer(T* X, const INTM n) {
   clear();
   _externAlloc=true;
   _X=X;
   _n=n;
};

/// put a random permutation of size n (for integral vectors)
template <> inline void Vector<int>::randperm(int n) {
   resize(n);
   Vector<int> table(n);
   for (int i = 0; i<n; ++i)
      table[i]=i;
   int size=n;
   for (int i = 0; i<n; ++i) {
      const int ind=random() % size;
      _X[i]=table[ind];
      table[ind]=table[size-1];
      --size;
   }
};

/// put random values in the vector (white Gaussian Noise)
template <typename T> inline void Vector<T>::setAleat() {
   for (INTM i = 0; i<_n; ++i) _X[i]=normalDistrib<T>();
};

/// clear the vector
template <typename T> inline void Vector<T>::clear() {
   if (!_externAlloc) delete[](_X);
   _n=0;
   _X=NULL;
   _externAlloc=true;
};

/// performs soft-thresholding of the vector
template <typename T> inline void Vector<T>::softThrshold(const T nu) {
   for (INTM i = 0; i<_n; ++i) {
      if (_X[i] > nu) {
         _X[i] -= nu;
      } else if (_X[i] < -nu) {
         _X[i] += nu;
      } else {
         _X[i] = 0;
      }
   }
};

/// performs soft-thresholding of the vector
template <typename T> inline void Vector<T>::softThrsholdScal(Vector<T>& out, const T nu, const T s) {
   T* Y = out.rawX();
   for (INTM i = 0; i<_n; ++i) {
      if (_X[i] > nu) {
         Y[i] = s*(_X[i]-nu);
      } else if (_X[i] < -nu) {
         Y[i] = s*(_X[i]+nu);
      } else {
         Y[i] = 0;
      }
   }
};

/// performs soft-thresholding of the vector
template <typename T> inline void Vector<T>::hardThrshold(const T nu) {
   for (INTM i = 0; i<_n; ++i) {
      if (!(_X[i] > nu || _X[i] < -nu)) {
         _X[i] = 0;
      }
   }
};


/// performs thresholding of the vector
template <typename T> inline void Vector<T>::thrsmax(const T nu) {
   for (INTM i = 0; i<_n; ++i) 
      _X[i]=MAX(_X[i],nu);
}

/// performs thresholding of the vector
template <typename T> inline void Vector<T>::thrsmin(const T nu) {
   for (INTM i = 0; i<_n; ++i) 
      _X[i]=MIN(_X[i],nu);
}

/// performs thresholding of the vector
template <typename T> inline void Vector<T>::thrsabsmin(const T nu) {
   for (INTM i = 0; i<_n; ++i) 
      _X[i]=MAX(MIN(_X[i],nu),-nu);
}

/// performs thresholding of the vector
template <typename T> inline void Vector<T>::thrshold(const T nu) {
   for (INTM i = 0; i<_n; ++i) 
      if (abs<T>(_X[i]) < nu) 
         _X[i]=0;
}
/// performs soft-thresholding of the vector
template <typename T> inline void Vector<T>::thrsPos() {
   for (INTM i = 0; i<_n; ++i) {
      if (_X[i] < 0) _X[i]=0;
   }
};

template <>
inline bool Vector<bool>::alltrue() const {
   for (INTM i = 0; i<_n; ++i) {
      if (!_X[i]) return false;
   }
   return true;
};

template <>
inline bool Vector<bool>::allfalse() const {
   for (INTM i = 0; i<_n; ++i) {
      if (_X[i]) return false;
   }
   return true;
};


/// set each value of the vector to val
template <typename T> inline void Vector<T>::set(const T val) {
   for (INTM i = 0; i<_n; ++i) _X[i]=val;
};

/// returns ||A||_2
template <typename T> inline T Vector<T>::nrm2() const {
   return cblas_nrm2<T>(_n,_X,1);
};

/// returns ||A||_2^2
template <typename T> inline T Vector<T>::nrm2sq() const {
   return cblas_dot<T>(_n,_X,1,_X,1);
};

/// returns  A'x
template <typename T> inline T Vector<T>::dot(const Vector<T>& x) const {
   // assert(_n == x._n);
   return cblas_dot<T>(_n,_X,1,x._X,1);
};

/// returns A'x, when x is sparse
template <typename T> inline T Vector<T>::dot(const SpVector<T>& x) const {
   T sum=0;
   const INTM* r = x.rawR();
   const T* v = x.rawX();
   for (INTT i = 0; i<x._L; ++i) {
      sum += _X[r[i]]*v[i];
   }
   return sum;
   //return cblas_doti<T>(x._L,x._v,x._r,_X);
};

/// A <- A + a*x
template <typename T> inline void Vector<T>::add(const Vector<T>& x, const T a) {
   // assert(_n == x._n);
   cblas_axpy<T>(_n,a,x._X,1,_X,1);
};

template <typename T> inline void Vector<T>::add_scal(const Vector<T>& x, const T a, const T b) {
   // assert(_n == x._n);
   cblas_axpby<T>(_n,a,x._X,1,b,_X,1);
};

/// A <- A + a*x
template <typename T> inline void Vector<T>::add(const SpVector<T>& x,
      const T a) {
   if (a == 1.0) {
      for (INTM i = 0; i<x._L; ++i)
         _X[x._r[i]]+=x._v[i];
   } else {
      for (INTM i = 0; i<x._L; ++i)
         _X[x._r[i]]+=a*x._v[i];
   }
};

/// adds a to each value in the vector
template <typename T> inline void Vector<T>::add(const T a) {
   for (INTM i = 0; i<_n; ++i) _X[i]+=a;
};

/// A <- A - x
template <typename T> inline void Vector<T>::sub(const Vector<T>& x) {
   // assert(_n == x._n);
   vSub<T>(_n,_X,x._X,_X);
};

/// A <- A + a*x
template <typename T> inline void Vector<T>::sub(const SpVector<T>& x) {
   for (INTM i = 0; i<x._L; ++i)
      _X[x._r[i]]-=x._v[i];
};

/// A <- A ./ x
template <typename T> inline void Vector<T>::div(const Vector<T>& x) {
   // assert(_n == x._n);
   vDiv<T>(_n,_X,x._X,_X);
};

/// A <- x ./ y
template <typename T> inline void Vector<T>::div(const Vector<T>& x, const Vector<T>& y) {
   // assert(_n == x._n);
   vDiv<T>(_n,x._X,y._X,_X);
};


/// A <- x .^ 2
template <typename T> inline void Vector<T>::sqr(const Vector<T>& x) {
   this->resize(x._n);
   vSqr<T>(_n,x._X,_X);
}

/// A <- x .^ 2
template <typename T> inline void Vector<T>::sqr() {
   vSqr<T>(_n,_X,_X);
}

/// A <- x .^ 2
template <typename T> inline void Vector<T>::Invsqrt(const Vector<T>& x) {
   this->resize(x._n);
   vInvSqrt<T>(_n,x._X,_X);
}
/// A <- x .^ 2
template <typename T> inline void Vector<T>::Sqrt(const Vector<T>& x) {
   this->resize(x._n);
   vSqrt<T>(_n,x._X,_X);
}
/// A <- x .^ 2
template <typename T> inline void Vector<T>::Invsqrt() {
   vInvSqrt<T>(_n,_X,_X);
}
/// A <- x .^ 2
template <typename T> inline void Vector<T>::Sqrt() {
   vSqrt<T>(_n,_X,_X);
}


/// A <- 1./x
template <typename T> inline void Vector<T>::inv(const Vector<T>& x) {
   this->resize(x.n());
   vInv<T>(_n,x._X,_X);
};

/// A <- 1./A
template <typename T> inline void Vector<T>::inv() {
   vInv<T>(_n,_X,_X);
};

/// A <- x .* y
template <typename T> inline void Vector<T>::mult(const Vector<T>& x,
      const Vector<T>& y) {
   this->resize(x.n());
   vMul<T>(_n,x._X,y._X,_X);
};
;

/// normalize the vector
template <typename T> inline void Vector<T>::normalize() {
   T norm=nrm2();
   if (norm > EPSILON) scal(1.0/norm);
};

/// normalize the vector
template <typename T> inline void Vector<T>::normalize2() {
   T norm=nrm2();
   if (norm > T(1.0)) scal(1.0/norm);
};

/// whiten
template <typename T> inline void Vector<T>::whiten(
      Vector<T>& meanv, const bool pattern) {
   if (pattern) {
      const INTM n =static_cast<INTM>(sqrt(static_cast<T>(_n)));
      INTM count[4];
      for (INTM i = 0; i<4; ++i) count[i]=0;
      INTM offsetx=0;
      for (INTM j = 0; j<n; ++j) {
         offsetx= (offsetx+1) % 2;
         INTM offsety=0;
         for (INTM k = 0; k<n; ++k) {
            offsety= (offsety+1) % 2;
            meanv[2*offsetx+offsety]+=_X[j*n+k];
            count[2*offsetx+offsety]++;
         }
      }
      for (INTM i = 0; i<4; ++i)
         meanv[i] /= count[i];
      offsetx=0;
      for (INTM j = 0; j<n; ++j) {
         offsetx= (offsetx+1) % 2;
         INTM offsety=0;
         for (INTM k = 0; k<n; ++k) {
            offsety= (offsety+1) % 2;
            _X[j*n+k]-=meanv[2*offsetx+offsety];
         }
      }
   } else {
      const INTM V = meanv.n();
      const INTM sizePatch=_n/V;
      for (INTM j = 0; j<V; ++j) {
         T mean = 0;
         for (INTM k = 0; k<sizePatch; ++k) {
            mean+=_X[sizePatch*j+k];
         }
         mean /= sizePatch;
         for (INTM k = 0; k<sizePatch; ++k) {
            _X[sizePatch*j+k]-=mean;
         }
         meanv[j]=mean;
      }
   }
};

/// whiten
template <typename T> inline void Vector<T>::whiten(
      Vector<T>& meanv, const Vector<T>& mask) {
   const INTM V = meanv.n();
   const INTM sizePatch=_n/V;
   for (INTM j = 0; j<V; ++j) {
      T mean = 0;
      for (INTM k = 0; k<sizePatch; ++k) {
         mean+=_X[sizePatch*j+k];
      }
      mean /= cblas_asum(sizePatch,mask._X+j*sizePatch,1);
      for (INTM k = 0; k<sizePatch; ++k) {
         if (mask[sizePatch*j+k])
            _X[sizePatch*j+k]-=mean;
      }
      meanv[j]=mean;
   }
};

/// whiten
template <typename T> inline void Vector<T>::whiten(const INTM V) {
   const INTM sizePatch=_n/V;
   for (INTM j = 0; j<V; ++j) {
      T mean = 0;
      for (INTM k = 0; k<sizePatch; ++k) {
         mean+=_X[sizePatch*j+k];
      }
      mean /= sizePatch;
      for (INTM k = 0; k<sizePatch; ++k) {
         _X[sizePatch*j+k]-=mean;
      }
   }
};

template <typename T> inline T Vector<T>::KL(const Vector<T>& Y) {
   T sum = 0;
   T* prY = Y.rawX();
   for (INTM i = 0; i<_n; ++i) {
      if (_X[i] > 1e-20) {
         if (prY[i] < 1e-60) {
            sum += 1e200;
         } else {
            sum += _X[i]*log_alt<T>(_X[i]/prY[i]);
         }
         //sum += _X[i]*log_alt<T>(_X[i]/(prY[i]+1e-100));
      }
   }
   sum += T(-1.0) + Y.sum();
   return sum;
};

/// unwhiten
template <typename T> inline void Vector<T>::unwhiten(
      Vector<T>& meanv, const bool pattern) {
   if (pattern) {
      const INTM n =static_cast<INTM>(sqrt(static_cast<T>(_n)));
      INTM offsetx=0;
      for (INTM j = 0; j<n; ++j) {
         offsetx= (offsetx+1) % 2;
         INTM offsety=0;
         for (INTM k = 0; k<n; ++k) {
            offsety= (offsety+1) % 2;
            _X[j*n+k]+=meanv[2*offsetx+offsety];
         }
      }
   } else  {
      const INTM V = meanv.n();
      const INTM sizePatch=_n/V;
      for (INTM j = 0; j<V; ++j) {
         T mean = meanv[j];
         for (INTM k = 0; k<sizePatch; ++k) {
            _X[sizePatch*j+k]+=mean;
         }
      }
   }
};


/// return the mean
template <typename T> inline T Vector<T>::mean() {
   return this->sum()/_n;
}

/// return the std
template <typename T> inline T Vector<T>::std() {
   T E = this->mean();
   T std=0;
   for (INTM i = 0; i<_n; ++i) {
      T tmp=_X[i]-E;
      std += tmp*tmp;
   }
   std /= _n;
   return sqr_alt<T>(std);
}

/// scale the vector by a
template <typename T> inline void Vector<T>::scal(const T a) {
   return cblas_scal<T>(_n,a,_X,1);
};

/// A <- -A
template <typename T> inline void Vector<T>::neg() {
   for (INTM i = 0; i<_n; ++i) _X[i]=-_X[i];
};

/// replace each value by its exponential
template <typename T> inline void Vector<T>::exp() {
   vExp<T>(_n,_X,_X);
};

/// replace each value by its absolute value
template <typename T> inline void Vector<T>::abs_vec() {
   vAbs<T>(_n,_X,_X);
};

/// replace each value by its logarithm
template <typename T> inline void Vector<T>::log() {
   for (INTM i=0; i<_n; ++i) _X[i]=alt_log<T>(_X[i]);
};

/// replace each value by its exponential
template <typename T> inline void Vector<T>::logexp() {
   for (INTM i = 0; i<_n; ++i) {
      if (_X[i] < -30) {
         _X[i]=0;
      } else if (_X[i] < 30) {
         _X[i]= alt_log<T>( T(1.0) + exp_alt<T>( _X[i] ) );
      }
   }
};

template <typename T>
static inline T logexp2(const T x) {
   return (x > 0) ? x + log_alt<T>(T(1.0)+ exp_alt<T>(-x)) :
      log( T(1.0) + exp_alt<T>( x ) );
}

/// replace each value by its exponential
template <typename T> inline T Vector<T>::softmax(const int y) {
   this->add(-_X[y]);
   _X[y]=-INFINITY;
   T max=this->maxval();
   if (max > 30) {
      return max;
   } else if (max < -30) {
      return 0;
   } else {
      _X[y]=T(0.0);
      this->exp();
      return alt_log<T>(this->sum());
   }
};

/// computes the sum of the magnitudes of the vector
template <typename T> inline T Vector<T>::asum() const {
   return cblas_asum<T>(_n,_X,1);
};

template <typename T> inline T Vector<T>::lzero() const {
   INTM count=0;
   for (INTM i = 0; i<_n; ++i) 
      if (_X[i] != 0) ++count;
   return count;
};


template <typename T> inline T Vector<T>::afused() const {
   T sum = 0;
   for (INTM i = 1; i<_n; ++i) {
      sum += abs<T>(_X[i]-_X[i-1]);
   }
   return sum;
}
/// returns the sum of the vector
template <typename T> inline T Vector<T>::sum() const {
   T sum=T();
   for (INTM i = 0; i<_n; ++i) sum +=_X[i]; 
   return sum;
};

/// puts in signs, the sign of each poINTM in the vector
template <typename T> inline void Vector<T>::sign(Vector<T>& signs) const {
   T* prSign=signs.rawX();
   for (INTM i = 0; i<_n; ++i) {
      if (_X[i] == 0) {
         prSign[i]=0.0; 
      } else {
         prSign[i] = _X[i] > 0 ? 1.0 : -1.0;
      }
   }
};

/// projects the vector onto the l1 ball of radius thrs,
/// returns true if the returned vector is null
template <typename T> inline void Vector<T>::l1project(Vector<T>& out,
      const T thrs, const bool simplex) const {
   out.copy(*this);
   if (simplex) {
      out.thrsPos();
   } else {
      vAbs<T>(_n,out._X,out._X);
   }
   T norm1 = out.sum();
   if (norm1 <= thrs) {
      if (!simplex) out.copy(*this);
      return;
   }
   T* prU = out._X;
   INTM sizeU = _n;

   T sum = T();
   INTM sum_card = 0;

   while (sizeU > 0) {
      // put the pivot in prU[0]
      swap(prU[0],prU[sizeU/2]);
      T pivot = prU[0];
      INTM sizeG=1;
      T sumG=pivot;

      for (INTM i = 1; i<sizeU; ++i) {
         if (prU[i] >= pivot) {
            sumG += prU[i];
            swap(prU[sizeG++],prU[i]);
         }
      }

      if (sum + sumG - pivot*(sum_card + sizeG) <= thrs) {
         sum_card += sizeG;
         sum += sumG;
         prU +=sizeG;
         sizeU -= sizeG;
      } else {
         ++prU;
         sizeU = sizeG-1;
      }
   }
   T lambda = (sum-thrs)/sum_card;
   out.copy(*this);
   if (simplex) {
      out.thrsPos();
   }
   out.softThrshold(lambda);
};

/// projects the vector onto the l1 ball of radius thrs,
/// returns true if the returned vector is null
template <typename T> inline void Vector<T>::l1project_weighted(Vector<T>& out, const Vector<T>& weights,
      const T thrs, const bool residual) const {
   out.copy(*this);
   if (thrs==0) {
      out.setZeros();
      return;
   }
   vAbs<T>(_n,out._X,out._X);
   out.div(weights);
   Vector<INTM> keys(_n);
   for (INTM i = 0; i<_n; ++i) keys[i]=i;
   out.sort2(keys,false);
   T sum1=0;
   T sum2=0;
   T lambda=0;
   for (INTM i = 0; i<_n; ++i) {
      const T lambda_old=lambda;
      const T fact=weights[keys[i]]*weights[keys[i]];
      lambda=out[i];
      sum2 += fact;
      sum1 += fact*lambda;
      if (sum1 - lambda*sum2 >= thrs) {
         sum2-=fact;
         sum1-=fact*lambda;
         lambda=lambda_old;
         break;
      }
   }
   lambda=MAX(0,(sum1-thrs)/sum2);

   if (residual) {
      for (INTM i = 0; i<_n; ++i) {
         out._X[i]=_X[i] > 0 ? MIN(_X[i],lambda*weights[i]) : MAX(_X[i],-lambda*weights[i]);
      }
   } else {
      for (INTM i = 0; i<_n; ++i) {
         out._X[i]=_X[i] > 0 ? MAX(0,_X[i]-lambda*weights[i]) : MIN(0,_X[i]+lambda*weights[i]);
      }
   }
};


template <typename T>
inline void Vector<T>::project_sft_binary(const Vector<T>& y) {
   T mean = this->mean();
   T thrs=mean;
   while (abs(mean) > EPSILON) {
      INTM n_seuils=0;
      for (INTM i = 0; i< _n; ++i) {
         _X[i] = _X[i]-thrs;
         const T val = y[i]*_X[i];
         if (val > 0) {
            ++n_seuils;
            _X[i]=0;
         } else if (val < -1.0) {
            ++n_seuils;
            _X[i] = -y[i];
         }
      }
      mean = this->mean();
      thrs= mean * _n/(_n-n_seuils);
   }
};

template <typename T>
inline void Vector<T>::project_sft(const Vector<int>& labels, const int clas) {
   T mean = this->mean();
   T thrs=mean;

   while (abs(mean) > EPSILON) {
      INTM n_seuils=0;
      for (INTM i = 0; i< _n; ++i) {
         _X[i] = _X[i]-thrs;
         if (labels[i]==clas) {
            if (_X[i] < -1.0) {
               _X[i]=-1.0;
               ++n_seuils;
            }
         } else {
            if (_X[i] < 0) {
               ++n_seuils;
               _X[i]=0;
            }
         }
      }
      mean = this->mean();
      thrs= mean * _n/(_n-n_seuils);
   }
};

template <typename T>
inline void Vector<T>::sparseProject(Vector<T>& out, const T thrs, const int mode, const T lambda1,
      const T lambda2, const T lambda3, const bool pos) {
   if (mode == 1) {
      /// min_u ||b-u||_2^2 / ||u||_1 <= thrs
      this->l1project(out,thrs,pos);
   } else if (mode == 2) {
      /// min_u ||b-u||_2^2 / ||u||_2^2 + lambda1||u||_1 <= thrs
      if (lambda1 > 1e-10) {
         this->scal(lambda1);
         this->l1l2project(out,thrs,2.0/(lambda1*lambda1),pos);
         this->scal(T(1.0/lambda1));
         out.scal(T(1.0/lambda1));
      } else {
         out.copy(*this);
         out.normalize2();
         out.scal(sqrt(thrs));
      }
   } else if (mode == 3) {
      /// min_u ||b-u||_2^2 / ||u||_1 + (lambda1/2) ||u||_2^2 <= thrs
      this->l1l2project(out,thrs,lambda1,pos);
   } else if (mode == 4) {
      /// min_u 0.5||b-u||_2^2  + lambda1||u||_1 / ||u||_2^2 <= thrs
      out.copy(*this);
      if (pos) 
         out.thrsPos();
      out.softThrshold(lambda1);
      T nrm=out.nrm2sq();
      if (nrm > thrs)
         out.scal(sqr_alt<T>(thrs/nrm));
   } else if (mode == 5) {
      /// min_u 0.5||b-u||_2^2  + lambda1||u||_1 +lambda2 Fused(u) / ||u||_2^2 <= thrs
      //      this->fusedProject(out,lambda1,lambda2,100);
      //      T nrm=out.nrm2sq();
      //      if (nrm > thrs)
      //         out.scal(sqr_alt<T>(thrs/nrm));
      //  } else if (mode == 6) {
      /// min_u 0.5||b-u||_2^2  + lambda1||u||_1 +lambda2 Fused(u) +0.5lambda_3 ||u||_2^2 
      this->fusedProjectHomotopy(out,lambda1,lambda2,lambda3,true);
} else if (mode==6) {
   /// min_u ||b-u||_2^2  /  lambda1||u||_1 +lambda2 Fused(u) + 0.5lambda3||u||_2^2 <= thrs
   this->fusedProjectHomotopy(out,lambda1/thrs,lambda2/thrs,lambda3/thrs,false);
} else {
   /// min_u ||b-u||_2^2 / (1-lambda1)*||u||_2^2 + lambda1||u||_1 <= thrs
   if (lambda1 < 1e-10) {
      out.copy(*this);
      if (pos) 
         out.thrsPos();
      out.normalize2();
      out.scal(sqrt(thrs));
   } else if (lambda1 > 0.999999) {
      this->l1project(out,thrs,pos);
   } else {
      this->sparseProject(out,thrs/(1.0-lambda1),2,lambda1/(1-lambda1),0,0,pos);
   }
}
};

/// returns true if the returned vector is null
template <typename T>
inline void Vector<T>::l1l2projectb(Vector<T>& out, const T thrs, const T gamma, const bool pos,
      const int mode) {
   if (mode == 1) {
      /// min_u ||b-u||_2^2 / ||u||_2^2 + gamma ||u||_1 <= thrs
      this->scal(gamma);
      this->l1l2project(out,thrs,2.0/(gamma*gamma),pos);
      this->scal(T(1.0/gamma));
      out.scal(T(1.0/gamma));
   } else if (mode == 2) {
      /// min_u ||b-u||_2^2 / ||u||_1 + (gamma/2) ||u||_2^2 <= thrs
      this->l1l2project(out,thrs,gamma,pos);
   } else if (mode == 3) {
      /// min_u 0.5||b-u||_2^2  + gamma||u||_1 / ||u||_2^2 <= thrs
      out.copy(*this);
      if (pos) 
         out.thrsPos();
      out.softThrshold(gamma);
      T nrm=out.nrm2();
      if (nrm > thrs)
         out.scal(thrs/nrm);
   }
}

/// returns true if the returned vector is null
/// min_u ||b-u||_2^2 / ||u||_1 + (gamma/2) ||u||_2^2 <= thrs
template <typename T>
   inline void Vector<T>::l1l2project(Vector<T>& out, const T thrs, const T gamma, const bool pos) const {
      if (gamma == 0) 
         return this->l1project(out,thrs,pos);
      out.copy(*this);
      if (pos) {
         out.thrsPos();
      } else {
         vAbs<T>(_n,out._X,out._X);
      }
      T norm = out.sum() + gamma*out.nrm2sq();
      if (norm <= thrs) {
         if (!pos) out.copy(*this);
         return;
      }

      /// BEGIN
      T* prU = out._X;
      INTM sizeU = _n;

      T sum = 0;
      INTM sum_card = 0;

      while (sizeU > 0) {
         // put the pivot in prU[0]
         swap(prU[0],prU[sizeU/2]);
         T pivot = prU[0];
         INTM sizeG=1;
         T sumG=pivot+0.5*gamma*pivot*pivot;

         for (INTM i = 1; i<sizeU; ++i) {
            if (prU[i] >= pivot) {
               sumG += prU[i]+0.5*gamma*prU[i]*prU[i];
               swap(prU[sizeG++],prU[i]);
            }
         }
         if (sum + sumG - pivot*(1+0.5*gamma*pivot)*(sum_card + sizeG) <
               thrs*(1+gamma*pivot)*(1+gamma*pivot)) {
            sum_card += sizeG;
            sum += sumG;
            prU +=sizeG;
            sizeU -= sizeG;
         } else {
            ++prU;
            sizeU = sizeG-1;
         }
      }
      T a = gamma*gamma*thrs+0.5*gamma*sum_card;
      T b = 2*gamma*thrs+sum_card;
      T c=thrs-sum;
      T delta = b*b-4*a*c;
      T lambda = (-b+sqrt(delta))/(2*a);

      out.copy(*this);
      if (pos) {
         out.thrsPos();
      }
      out.softThrshold(lambda);
      out.scal(T(1.0/(1+lambda*gamma)));
   };

template <typename T>
static inline T fusedHomotopyAux(const bool& sign1,
      const bool& sign2,
      const bool& sign3,
      const T& c1,
      const T& c2) {
   if (sign1) {
      if (sign2) {
         return sign3 ? 0 : c2;
      } else {
         return sign3 ? -c2-c1 : -c1;
      }
   } else {
      if (sign2) {
         return sign3 ? c1 : c1+c2;
      } else {
         return sign3 ? -c2 : 0;
      }
   }
};

template <typename T>
inline void Vector<T>::fusedProjectHomotopy(Vector<T>& alpha, 
      const T lambda1,const T lambda2,const T lambda3,
      const bool penalty) {
   T* pr_DtR=_X;
   const INTM K = _n;
   alpha.setZeros();
   Vector<T> u(K); // regularization path for gamma
   Vector<T> Du(K); // regularization path for alpha
   Vector<T> DDu(K); // regularization path for alpha
   Vector<T> gamma(K); // auxiliary variable
   Vector<T> c(K); // auxiliary variables
   Vector<T> scores(K); // auxiliary variables
   gamma.setZeros();
   T* pr_gamma = gamma.rawX();
   T* pr_u = u.rawX();
   T* pr_Du = Du.rawX();
   T* pr_DDu = DDu.rawX();
   T* pr_c = c.rawX();
   T* pr_scores = scores.rawX();
   Vector<INTM> ind(K+1);
   Vector<bool> signs(K);
   ind.set(K);
   INTM* pr_ind = ind.rawX();
   bool* pr_signs = signs.rawX();

   /// Computation of DtR
   T sumBeta = this->sum();

   /// first element is selected, gamma and alpha are updated
   pr_gamma[0]=sumBeta/K;
   /// update alpha
   alpha.set(pr_gamma[0]);
   /// update DtR
   this->sub(alpha);
   for (INTM j = K-2; j>=0; --j) 
      pr_DtR[j] += pr_DtR[j+1];

   pr_DtR[0]=0;
   pr_ind[0]=0;
   pr_signs[0] = pr_DtR[0] > 0;
   pr_c[0]=T(1.0)/K;
   INTM currentInd=this->fmax();
   T currentLambda=abs<T>(pr_DtR[currentInd]);
   bool newAtom = true;

   /// Solve the Lasso using simplified LARS
   for (INTM i = 1; i<K; ++i) {
      /// exit if constraINTMs are satisfied
      /// min_u ||b-u||_2^2  +  lambda1||u||_1 +lambda2 Fused(u) + 0.5lambda3||u||_2^2 
      if (penalty && currentLambda <= lambda2) break;
      if (!penalty) {
         /// min_u ||b-u||_2^2  /  lambda1||u||_1 +lambda2 Fused(u) + 0.5lambda3||u||_2^2 <= 1.0
         scores.copy(alpha);
         scores.softThrshold(lambda1*currentLambda/lambda2);
         scores.scal(T(1.0/(1.0+lambda3*currentLambda/lambda2)));
         if (lambda1*scores.asum()+lambda2*scores.afused()+0.5*
               lambda3*scores.nrm2sq() >= T(1.0)) break;
      }

      /// Update pr_ind and pr_c
      if (newAtom) {
         INTM j;
         for (j = 1; j<i; ++j) 
            if (pr_ind[j] > currentInd) break;
         for (INTM k = i; k>j; --k) {
            pr_ind[k]=pr_ind[k-1];
            pr_c[k]=pr_c[k-1];
            pr_signs[k]=pr_signs[k-1];
         }
         pr_ind[j]=currentInd;
         pr_signs[j]=pr_DtR[currentInd] > 0;
         pr_c[j-1]=T(1.0)/(pr_ind[j]-pr_ind[j-1]);
         pr_c[j]=T(1.0)/(pr_ind[j+1]-pr_ind[j]);
      }

      // Compute u
      pr_u[0]= pr_signs[1] ? -pr_c[0] : pr_c[0];
      if (i == 1) {
         pr_u[1]=pr_signs[1] ? pr_c[0]+pr_c[1] : -pr_c[0]-pr_c[1];
      } else {
         pr_u[1]=pr_signs[1] ? pr_c[0]+pr_c[1] : -pr_c[0]-pr_c[1];
         pr_u[1]+=pr_signs[2] ? -pr_c[1] : pr_c[1];
         for (INTM j = 2; j<i; ++j) {
            pr_u[j]=2*fusedHomotopyAux<T>(pr_signs[j-1],
                  pr_signs[j],pr_signs[j+1], pr_c[j-1],pr_c[j]);
         }
         pr_u[i] = pr_signs[i-1] ? -pr_c[i-1] : pr_c[i-1];
         pr_u[i] += pr_signs[i] ? pr_c[i-1]+pr_c[i] : -pr_c[i-1]-pr_c[i];
      } 

      // Compute Du 
      pr_Du[0]=pr_u[0];
      for (INTM k = 1; k<pr_ind[1]; ++k)
         pr_Du[k]=pr_Du[0];
      for (INTM j = 1; j<=i; ++j) {
         pr_Du[pr_ind[j]]=pr_Du[pr_ind[j]-1]+pr_u[j];
         for (INTM k = pr_ind[j]+1; k<pr_ind[j+1]; ++k)
            pr_Du[k]=pr_Du[pr_ind[j]];
      }

      /// Compute DDu 
      DDu.copy(Du);
      for (INTM j = K-2; j>=0; --j) 
         pr_DDu[j] += pr_DDu[j+1];

      /// Check constraINTMs
      T max_step1 = INFINITY;
      if (penalty) {
         max_step1 = currentLambda-lambda2;
      } 

      /// Check changes of sign
      T max_step2 = INFINITY;
      INTM step_out = -1;
      for (INTM j = 1; j<=i; ++j) {
         T ratio = -pr_gamma[pr_ind[j]]/pr_u[j];
         if (ratio > 0 && ratio <= max_step2) {
            max_step2=ratio;
            step_out=j;
         }
      }
      T max_step3 = INFINITY;
      /// Check new variables entering the active set
      for (INTM j = 1; j<K; ++j) {
         T sc1 = (currentLambda-pr_DtR[j])/(T(1.0)-pr_DDu[j]);
         T sc2 = (currentLambda+pr_DtR[j])/(T(1.0)+pr_DDu[j]);
         if (sc1 <= 1e-10) sc1=INFINITY;
         if (sc2 <= 1e-10) sc2=INFINITY;
         pr_scores[j]= MIN(sc1,sc2);
      }
      for (INTM j = 0; j<=i; ++j) {
         pr_scores[pr_ind[j]]=INFINITY;
      }
      currentInd = scores.fmin();
      max_step3 = pr_scores[currentInd];
      T step = MIN(max_step1,MIN(max_step3,max_step2));
      if (step == 0 || step == INFINITY) break; 

      /// Update gamma, alpha, DtR, currentLambda
      for (INTM j = 0; j<=i; ++j) {
         pr_gamma[pr_ind[j]]+=step*pr_u[j];
      }
      alpha.add(Du,step);
      this->add(DDu,-step);
      currentLambda -= step;
      if (step == max_step2) {
         /// Update signs,pr_ind, pr_c
         for (INTM k = step_out; k<=i; ++k) 
            pr_ind[k]=pr_ind[k+1];
         pr_ind[i]=K;
         for (INTM k = step_out; k<=i; ++k) 
            pr_signs[k]=pr_signs[k+1];
         pr_c[step_out-1]=T(1.0)/(pr_ind[step_out]-pr_ind[step_out-1]);
         pr_c[step_out]=T(1.0)/(pr_ind[step_out+1]-pr_ind[step_out]);
         i-=2;
         newAtom=false;
      } else {
         newAtom=true;
      }
   }

   if (penalty) {
      alpha.softThrshold(lambda1);
      alpha.scal(T(1.0/(1.0+lambda3)));
   } else {
      alpha.softThrshold(lambda1*currentLambda/lambda2);
      alpha.scal(T(1.0/(1.0+lambda3*currentLambda/lambda2)));
   }
};

template <typename T>
inline void Vector<T>::fusedProject(Vector<T>& alpha, const T lambda1, const T lambda2,
      const int itermax) {
   T* pr_alpha= alpha.rawX();
   T* pr_beta=_X;
   const INTM K = alpha.n();

   T total_alpha =alpha.sum();
   /// Modification of beta
   for (INTM i = K-2; i>=0; --i) 
      pr_beta[i]+=pr_beta[i+1];

   for (INTM i = 0; i<itermax; ++i) {
      T sum_alpha=0;
      T sum_diff = 0;
      /// Update first coordinate
      T gamma_old=pr_alpha[0];
      pr_alpha[0]=(K*gamma_old+pr_beta[0]-
            total_alpha)/K;
      T diff = pr_alpha[0]-gamma_old;
      sum_diff += diff;
      sum_alpha += pr_alpha[0];
      total_alpha +=K*diff;

      /// Update alpha_j
      for (INTM j = 1; j<K; ++j) {
         pr_alpha[j]+=sum_diff;
         T gamma_old=pr_alpha[j]-pr_alpha[j-1];
         T gamma_new=softThrs((K-j)*gamma_old+pr_beta[j]-
               (total_alpha-sum_alpha),lambda2)/(K-j);
         pr_alpha[j]=pr_alpha[j-1]+gamma_new;
         T diff = gamma_new-gamma_old;
         sum_diff += diff;
         sum_alpha+=pr_alpha[j];
         total_alpha +=(K-j)*diff;
      }
   }
   alpha.softThrshold(lambda1);

};

/// sort the vector
template <typename T>
inline void Vector<T>::sort(const bool mode) {
   if (mode) {
      lasrt<T>(incr,_n,_X);
   } else {
      lasrt<T>(decr,_n,_X);
   }
};


/// sort the vector
template <typename T>
inline void Vector<T>::sort(Vector<T>& out, const bool mode) const {
   out.copy(*this);
   out.sort(mode);
};

template <typename T>
inline void Vector<T>::sort2(Vector<INTM>& key, const bool mode) {
   quick_sort(key.rawX(),_X,(INTM)0,_n-1,mode);
};


template <typename T>
inline void Vector<T>::sort2(Vector<T>& out, Vector<INTM>& key, const bool mode) const {
   out.copy(*this);
   out.sort2(key,mode);
}

template <typename T>
inline void Vector<T>::applyBayerPattern(const int offset) {
   INTM sizePatch=_n/3;
   INTM n = static_cast<INTM>(sqrt(static_cast<T>(sizePatch)));
   if (offset == 0) {
      // R
      for (INTM i = 0; i<n; ++i) {
         const INTM step = (i % 2) ? 1 : 2;
         const INTM off = (i % 2) ? 0 : 1;
         for (INTM j = off; j<n; j+=step) {
            _X[i*n+j]=0;
         }
      }
      // G
      for (INTM i = 0; i<n; ++i) {
         const INTM step = 2;
         const INTM off = (i % 2) ? 1 : 0;
         for (INTM j = off; j<n; j+=step) {
            _X[sizePatch+i*n+j]=0;
         }
      }
      // B
      for (INTM i = 0; i<n; ++i) {
         const INTM step = (i % 2) ? 2 : 1;
         const INTM off = 0;
         for (INTM j = off; j<n; j+=step) {
            _X[2*sizePatch+i*n+j]=0;
         }
      }
   } else if (offset == 1) {
      // R
      for (INTM i = 0; i<n; ++i) {
         const INTM step = (i % 2) ? 2 : 1;
         const INTM off = (i % 2) ? 1 : 0;
         for (INTM j = off; j<n; j+=step) {
            _X[i*n+j]=0;
         }
      }
      // G
      for (INTM i = 0; i<n; ++i) {
         const INTM step = 2;
         const INTM off = (i % 2) ? 0 : 1;
         for (INTM j = off; j<n; j+=step) {
            _X[sizePatch+i*n+j]=0;
         }
      }
      // B
      for (INTM i = 0; i<n; ++i) {
         const INTM step = (i % 2) ? 1 : 2;
         const INTM off = 0;
         for (INTM j = off; j<n; j+=step) {
            _X[2*sizePatch+i*n+j]=0;
         }
      }
   } else if (offset == 2) {
      // R
      for (INTM i = 0; i<n; ++i) {
         const INTM step = (i % 2) ? 1 : 2;
         const INTM off = 0;
         for (INTM j = off; j<n; j+=step) {
            _X[i*n+j]=0;
         }
      }
      // G
      for (INTM i = 0; i<n; ++i) {
         const INTM step = 2;
         const INTM off = (i % 2) ? 0 : 1;
         for (INTM j = off; j<n; j+=step) {
            _X[sizePatch+i*n+j]=0;
         }
      }
      // B
      for (INTM i = 0; i<n; ++i) {
         const INTM step = (i % 2) ? 2 : 1;
         const INTM off = (i % 2) ? 1 : 0;
         for (INTM j = off; j<n; j+=step) {
            _X[2*sizePatch+i*n+j]=0;
         }
      }
   } else if (offset == 3) {
      // R
      for (INTM i = 0; i<n; ++i) {
         const INTM step = (i % 2) ? 2 : 1;
         const INTM off = 0;
         for (INTM j = off; j<n; j+=step) {
            _X[i*n+j]=0;
         }
      }
      // G
      for (INTM i = 0; i<n; ++i) {
         const INTM step = 2;
         const INTM off = (i % 2) ? 1 : 0;
         for (INTM j = off; j<n; j+=step) {
            _X[sizePatch+i*n+j]=0;
         }
      }
      // B
      for (INTM i = 0; i<n; ++i) {
         const INTM step = (i % 2) ? 1 : 2;
         const INTM off = (i % 2) ? 0 : 1;
         for (INTM j = off; j<n; j+=step) {
            _X[2*sizePatch+i*n+j]=0;
         }
      }
   }
};


/// make a sparse copy 
template <typename T> inline void Vector<T>::toSparse(
      SpVector<T>& vec) const {
   INTM L=0;
   T* v = vec._v;
   INTM* r = vec._r;
   for (INTM i = 0; i<_n; ++i) {
      if (_X[i] != T()) {
         v[L]=_X[i];
         r[L++]=i;
      }
   }
   vec._L=L;
};


template <typename T>
inline void Vector<T>::copyMask(Vector<T>& out, Vector<bool>& mask) const {
   out.resize(_n);
   INTM pointer=0;
   for (INTM i = 0; i<_n; ++i) {
      if (mask[i])
         out[pointer++]=_X[i];
   }
   out.setn(pointer);
};

template <typename T>
inline void Matrix<T>::copyMask(Matrix<T>& out, Vector<bool>& mask) const {
   out.resize(_m,_n);
   INTM count=0;
   for (INTM i = 0; i<mask.n(); ++i)
      if (mask[i])
         ++count;
   out.setm(count);
   for (INTM i = 0; i<_n; ++i) {
      INTM pointer=0;
      for (INTM j = 0; j<_m; ++j) {
         if (mask[j]) {
            out[i*count+pointer]=_X[i*_m+j];
            ++pointer;
         }
      }
   }
};



/* ****************************
 * Implementation of SpMatrix 
 * ****************************/


/// Constructor, CSC format, existing data
template <typename T> SpMatrix<T>::SpMatrix(T* v, INTM* r, INTM* pB, INTM* pE,
      INTM m, INTM n, INTM nzmax) :
   _externAlloc(true), _v(v), _r(r), _pB(pB), _pE(pE), _m(m), _n(n), _nzmax(nzmax)
{ };

/// Constructor, new m x n matrix, with at most nzmax non-zeros values
template <typename T> SpMatrix<T>::SpMatrix(INTM m, INTM n, INTM nzmax) :
   _externAlloc(false), _m(m), _n(n), _nzmax(nzmax) {
#pragma omp critical
      {
         _v=new T[nzmax];
         _r=new INTM[nzmax];
         _pB=new INTM[_n+1];
      }
      _pE=_pB+1;
   };

/// Empty constructor
template <typename T> SpMatrix<T>::SpMatrix() :
   _externAlloc(true), _v(NULL), _r(NULL), _pB(NULL), _pE(NULL),
   _m(0),_n(0),_nzmax(0) { };


template <typename T>
inline void SpMatrix<T>::copy(const SpMatrix<T>& mat) {
   this->resize(mat._m,mat._n,mat._nzmax);
   memcpy(_v,mat._v,_nzmax*sizeof(T));
   memcpy(_r,mat._r,_nzmax*sizeof(INTM));
   memcpy(_pB,mat._pB,(_n+1)*sizeof(INTM));
}


/// Destructor
template <typename T> SpMatrix<T>::~SpMatrix() {
   clear();
};

/// reference the column i INTMo vec
template <typename T> inline void SpMatrix<T>::refCol(INTM i, 
      SpVector<T>& vec) const {
   if (vec._nzmax > 0) vec.clear();
   vec._v=_v+_pB[i];
   vec._r=_r+_pB[i];
   vec._externAlloc=true;
   vec._L=_pE[i]-_pB[i];
   vec._nzmax=vec._L;
};

/// print the sparse matrix
template<typename T> inline void SpMatrix<T>::print(const string& name) const {
   // cerr << name << endl;
   // cerr << _m << " x " << _n << " , " << _nzmax << endl;
   for (INTM i = 0; i<_n; ++i) {
      for (INTM j = _pB[i]; j<_pE[i]; ++j) {
         // cerr << "(" <<_r[j] << "," << i << ") = " << _v[j] << endl;
      }
   }
};

template<typename T>
inline T SpMatrix<T>::operator[](const INTM index) const {
   const INTM num_col=(index/_m);
   const INTM num_row=index -num_col*_m;
   T val = 0;
   for (INTM j = _pB[num_col]; j<_pB[num_col+1]; ++j) {
      if (_r[j]==num_row) {
         val=_v[j];
         break;
      }
   }
   return val;
};
template<typename T>
void SpMatrix<T>::getData(Vector<T>& data, const INTM index) const {
   data.resize(_m);
   data.setZeros();
   for (INTM i = _pB[index]; i< _pB[index+1]; ++i) 
      data[_r[i]]=_v[i];
};

template <typename T>
void SpMatrix<T>::setData(T* v, INTM* r, INTM* pB, INTM* pE, INTM m, INTM n, INTM nzmax) {
   this->clear();
   _externAlloc =true;
    _v = v;
    _r=r;
    _pB=pB;
    _pE=pE;
    _m=m;
    _n=n;
    _nzmax=nzmax;
}

template<typename T>
void SpMatrix<T>::getGroup(Matrix<T>& data, const vector_groups& groups,  const INTM i) const {
   const group& gr = groups[i];
   const INTM N = gr.size();
   data.resize(_m,N);
   INTM count=0;
   Vector<T> col;
   for (group::const_iterator it = gr.begin(); it != gr.end(); ++it) {
      data.refCol(count,col);
      this->getData(col,*it);
      ++count;
   }
};

/// compute the sum of the matrix elements
template <typename T> inline T SpMatrix<T>::asum() const {
   return cblas_asum<T>(_pB[_n],_v,1);
};

/// compute the sum of the matrix elements
template <typename T> inline T SpMatrix<T>::normFsq() const {
   return cblas_dot<T>(_pB[_n],_v,1,_v,1);
};

template <typename T>
inline void SpMatrix<T>::add_direct(const SpMatrix<T>& mat, const T a) {
   Vector<T> v2(mat._v,mat._nzmax);
   Vector<T> v1(_v,_nzmax);
   v1.add(v2,a);
}

template <typename T>
inline void SpMatrix<T>::copy_direct(const SpMatrix<T>& mat) {
   Vector<T> v2(mat._v,_pB[_n]);
   Vector<T> v1(_v,_pB[_n]);
   v1.copy(v2);
}

template <typename T>
inline T SpMatrix<T>::dot_direct(const SpMatrix<T>& mat) const {
   Vector<T> v2(mat._v,_pB[_n]);
   Vector<T> v1(_v,_pB[_n]);
   return v1.dot(v2);
}

/// clear the matrix
template <typename T> inline void SpMatrix<T>::clear() {
   if (!_externAlloc) {
      delete[](_r);
      delete[](_v);
      delete[](_pB);
   }
   _n=0;
   _m=0;
   _nzmax=0;
   _v=NULL;
   _r=NULL;
   _pB=NULL;
   _pE=NULL;
   _externAlloc=true;
};

/// resize the matrix
template <typename T> inline void SpMatrix<T>::resize(const INTM m, 
      const INTM n, const INTM nzmax) {
   if (n == _n && m == _m && nzmax == _nzmax) return;
   this->clear();
   _n=n;
   _m=m;
   _nzmax=nzmax;
   _externAlloc=false;
#pragma omp critical
   {
      _v = new T[nzmax];
      _r = new INTM[nzmax];
      _pB = new INTM[_n+1];
   }
   _pE = _pB+1;
   for (INTM i = 0; i<=_n; ++i) _pB[i]=0;
};

/// resize the matrix
template <typename T> inline void SpMatrix<T>::scal(const T a) const {
   cblas_scal<T>(_pB[_n],a,_v,1);
};

/// y <- A'*x
template <typename T>
inline void SpMatrix<T>::multTrans(const Vector<T>& x, Vector<T>& y,
      const T alpha, const T beta) const {
   y.resize(_n);
   if (beta) {
      y.scal(beta);
   } else {
      y.setZeros();
   }
   const T* prX = x.rawX();
   for (INTM i = 0; i<_n; ++i) {
      T sum=T();
      for (INTM j = _pB[i]; j<_pE[i]; ++j) {
         sum+=_v[j]*prX[_r[j]];
      }
      y[i] += alpha*sum;
   }
};

/// perform b = alpha*A*x + beta*b, when x is sparse
template <typename T>
inline void SpMatrix<T>::multTrans(const SpVector<T>& x, Vector<T>& y, 
      const T alpha, const T beta) const {
   y.resize(_n);
   if (beta) {
      y.scal(beta);
   } else {
      y.setZeros();
   }
   T* prY = y.rawX();
   SpVector<T> col;
   for (INTM i = 0; i<_n; ++i) {
      this->refCol(i,col);
      prY[i] += alpha*x.dot(col);
   }
};


/// y <- A*x
template <typename T>
inline void SpMatrix<T>::mult(const Vector<T>& x, Vector<T>& y,
      const T alpha, const T beta) const {
   y.resize(_m);
   if (beta) {
      y.scal(beta);
   } else {
      y.setZeros();
   }
   const T* prX = x.rawX();
   for (INTM i = 0; i<_n; ++i) {
      T sca=alpha && prX[i];
      for (INTM j = _pB[i]; j<_pE[i]; ++j) {
         y[_r[j]] += sca*_v[j];
      }
   }
};


/// perform b = alpha*A*x + beta*b, when x is sparse
template <typename T>
inline void SpMatrix<T>::mult(const SpVector<T>& x, Vector<T>& y, 
      const T alpha, const T beta) const {
   y.resize(_m);
   if (beta) {
      y.scal(beta);
   } else {
      y.setZeros();
   }
   T* prY = y.rawX();
   for (INTM i = 0; i<x.L(); ++i) {
      INTM ind=x.r(i);
      T val = alpha && x.v(i);
      for (INTM j = _pB[ind]; j<_pE[ind]; ++j) {
         prY[_r[j]] += val *_v[j];
      }
   }
};

/// perform C = a*A*B + b*C, possibly transposing A or B.
template <typename T>
inline void SpMatrix<T>::mult(const Matrix<T>& B, Matrix<T>& C, 
      const bool transA, const bool transB,
      const T a, const T b) const {
   if (transA) {
      if (transB) {
         C.resize(_n,B.m());
         if (b) {
            C.scal(b);
         } else {
            C.setZeros();
         }
         SpVector<T> tmp;
         Vector<T> row(B.m());
         for (INTM i = 0; i<_n; ++i) {
            this->refCol(i,tmp);
            B.mult(tmp,row);
            C.addRow(i,row,a);
         }
      } else {
         C.resize(_n,B.n());
         if (b) {
            C.scal(b);
         } else {
            C.setZeros();
         }
         SpVector<T> tmp;
         Vector<T> row(B.n());
         for (INTM i = 0; i<_n; ++i) {
            this->refCol(i,tmp);
            B.multTrans(tmp,row);
            C.addRow(i,row,a);
         }
      }
   } else {
      if (transB) {
         C.resize(_m,B.m());
         if (b) {
            C.scal(b);
         } else {
            C.setZeros();
         }
         Vector<T> row(B.n());
         Vector<T> col;
         for (INTM i = 0; i<B.m(); ++i) {
            B.copyRow(i,row);
            C.refCol(i,col);
            this->mult(row,col,a,T(1.0));
         }
      } else {
         C.resize(_m,B.n());
         if (b) {
            C.scal(b);
         } else {
            C.setZeros();
         }
         Vector<T> colB;
         Vector<T> colC;
         for (INTM i = 0; i<B.n(); ++i) {
            B.refCol(i,colB);
            C.refCol(i,colC);
            this->mult(colB,colC,a,T(1.0));
         }
      }
   }
};

/// perform C = a*A*B + b*C, possibly transposing A or B.
template <typename T>
inline void SpMatrix<T>::mult(const SpMatrix<T>& B, Matrix<T>& C, 
      const bool transA, const bool transB,
      const T a, const T b) const {
   if (transA) {
      if (transB) {
         C.resize(_n,B.m());
         if (b) {
            C.scal(b);
         } else {
            C.setZeros();
         }
         SpVector<T> tmp;
         Vector<T> row(B.m());
         for (INTM i = 0; i<_n; ++i) {
            this->refCol(i,tmp);
            B.mult(tmp,row);
            C.addRow(i,row,a);
         }
      } else {
         C.resize(_n,B.n());
         if (b) {
            C.scal(b);
         } else {
            C.setZeros();
         }
         SpVector<T> tmp;
         Vector<T> row(B.n());
         for (INTM i = 0; i<_n; ++i) {
            this->refCol(i,tmp);
            B.multTrans(tmp,row);
            C.addRow(i,row,a);
         }
      }
   } else {
      if (transB) {
         C.resize(_m,B.m());
         if (b) {
            C.scal(b);
         } else {
            C.setZeros();
         }
         SpVector<T> colB;
         SpVector<T> colA;
         for (INTM i = 0; i<_n; ++i) {
            this->refCol(i,colA);
            B.refCol(i,colB);
            C.rank1Update(colA,colB,a);
         }
      } else {
         C.resize(_m,B.n());
         if (b) {
            C.scal(b);
         } else {
            C.setZeros();
         }
         SpVector<T> colB;
         Vector<T> colC;
         for (INTM i = 0; i<B.n(); ++i) {
            B.refCol(i,colB);
            C.refCol(i,colC);
            this->mult(colB,colC,a);
         }
      }
   }
};

/// perform C = a*B*A + b*C, possibly transposing A or B.
template <typename T>
inline void SpMatrix<T>::multSwitch(const Matrix<T>& B, Matrix<T>& C, 
      const bool transA, const bool transB,
      const T a, const T b) const {
   B.mult(*this,C,transB,transA,a,b);
};

template <typename T>
inline T SpMatrix<T>::dot(const Matrix<T>& x) const {
   T sum=0;
   for (INTM i = 0; i<_n; ++i)
      for (INTM j = _pB[i]; j<_pE[i]; ++j) {
         sum+=_v[j]*x(_r[j],j);
      }
   return sum;
};


template <typename T>
inline void SpMatrix<T>::copyRow(const INTM ind, Vector<T>& x) const {
   x.resize(_n);
   x.setZeros();
   for (INTM i = 0; i<_n; ++i) {
      for (INTM j = _pB[i]; j<_pE[i]; ++j) {
         if (_r[j]==ind) {
            x[i]=_v[j];
         } else if (_r[j] > ind) {
            break;
         }
      }
   }
};

template <typename T> 
inline void SpMatrix<T>::addVecToCols(
      const Vector<T>& vec, const T a) {
   const T* pr_vec = vec.rawX();
   if (isEqual(a,T(1.0))) {
      for (INTM i = 0; i<_n; ++i) 
         for (INTM j = _pB[i]; j<_pE[i]; ++j) 
            _v[j] += pr_vec[_r[j]];
   } else {
      for (INTM i = 0; i<_n; ++i) 
         for (INTM j = _pB[i]; j<_pE[i]; ++j) 
            _v[j] += a*pr_vec[_r[j]];
   }
};

template <typename T> 
inline void SpMatrix<T>::addVecToColsWeighted(
      const Vector<T>& vec, const T* weights, const T a) {
   const T* pr_vec = vec.rawX();
   if (isEqual(a,T(1.0))) {
      for (INTM i = 0; i<_n; ++i) 
         for (INTM j = _pB[i]; j<_pE[i]; ++j) 
            _v[j] += pr_vec[_r[j]]*weights[j-_pB[i]];
   } else {
      for (INTM i = 0; i<_n; ++i) 
         for (INTM j = _pB[i]; j<_pE[i]; ++j) 
            _v[j] += a*pr_vec[_r[j]]*weights[j-_pB[i]];
   }
};

template <typename T> 
inline void SpMatrix<T>::sum_cols(Vector<T>& sum) const {
   sum.resize(_m);
   sum.setZeros();
   SpVector<T> tmp;
   for (INTM i = 0; i<_n; ++i) {
      this->refCol(i,tmp);
      sum.add(tmp);
   }
};

/// aat <- A*A'
template <typename T> inline void SpMatrix<T>::AAt(Matrix<T>& aat) const {
   INTM i,j,k;
   INTM K=_m;
   INTM M=_n;

   /* compute alpha alpha^T */
   aat.resize(K,K);
   int NUM_THREADS=init_omp(MAX_THREADS);
   T* aatT=new T[NUM_THREADS*K*K];
   for (j = 0; j<NUM_THREADS*K*K; ++j) aatT[j]=T();

#pragma omp parallel for private(i,j,k)
   for (i = 0; i<M; ++i) {
#ifdef _OPENMP
      int numT=omp_get_thread_num();
#else
      int numT=0;
#endif
      T* write_area=aatT+numT*K*K;
      for (j = _pB[i]; j<_pE[i]; ++j) {
         for (k = _pB[i]; k<=j; ++k) {
            write_area[_r[j]*K+_r[k]]+=_v[j]*_v[k];
         }
      }
   }

   cblas_copy<T>(K*K,aatT,1,aat._X,1);
   for (i = 1; i<NUM_THREADS; ++i) 
      cblas_axpy<T>(K*K,1.0,aatT+K*K*i,1,aat._X,1);
   aat.fillSymmetric();
   delete[](aatT);
}

template <typename T>
inline void SpMatrix<T>::XtX(Matrix<T>& XtX) const {
   XtX.resize(_n,_n);
   XtX.setZeros();
   SpVector<T> col;
   Vector<T> col_out;
   for (INTM i = 0; i<_n; ++i) {
      this->refCol(i,col);
      XtX.refCol(i,col_out);
      this->multTrans(col,col_out);
   }
};


/// aat <- A(:,indices)*A(:,indices)'
template <typename T> inline void SpMatrix<T>::AAt(Matrix<T>& aat,
      const Vector<INTM>& indices) const {
   INTM i,j,k;
   INTM K=_m;
   INTM M=indices.n();

   /* compute alpha alpha^T */
   aat.resize(K,K);
   int NUM_THREADS=init_omp(MAX_THREADS);
   T* aatT=new T[NUM_THREADS*K*K];
   for (j = 0; j<NUM_THREADS*K*K; ++j) aatT[j]=T();

#pragma omp parallel for private(i,j,k)
   for (i = 0; i<M; ++i) {
      INTM ii = indices[i];
#ifdef _OPENMP
      int numT=omp_get_thread_num();
#else
      int numT=0;
#endif
      T* write_area=aatT+numT*K*K;
      for (j = _pB[ii]; j<_pE[ii]; ++j) {
         for (k = _pB[ii]; k<=j; ++k) {
            write_area[_r[j]*K+_r[k]]+=_v[j]*_v[k];
         }
      }
   }

   cblas_copy<T>(K*K,aatT,1,aat._X,1);
   for (i = 1; i<NUM_THREADS; ++i) 
      cblas_axpy<T>(K*K,1.0,aatT+K*K*i,1,aat._X,1);
   aat.fillSymmetric();
   delete[](aatT);
}

/// aat <- sum_i w_i A(:,i)*A(:,i)'
template <typename T> inline void SpMatrix<T>::wAAt(const Vector<T>& w,
      Matrix<T>& aat) const {
   INTM i,j,k;
   INTM K=_m;
   INTM M=_n;

   /* compute alpha alpha^T */
   aat.resize(K,K);
   int NUM_THREADS=init_omp(MAX_THREADS);
   T* aatT=new T[NUM_THREADS*K*K];
   for (j = 0; j<NUM_THREADS*K*K; ++j) aatT[j]=T();

#pragma omp parallel for private(i,j,k)
   for (i = 0; i<M; ++i) {
#ifdef _OPENMP
      int numT=omp_get_thread_num();
#else
      int numT=0;
#endif
      T* write_area=aatT+numT*K*K;
      for (j = _pB[i]; j<_pE[i]; ++j) {
         for (k = _pB[i]; k<=j; ++k) {
            write_area[_r[j]*K+_r[k]]+=w._X[i]*_v[j]*_v[k];
         }
      }
   }

   cblas_copy<T>(K*K,aatT,1,aat._X,1);
   for (i = 1; i<NUM_THREADS; ++i) 
      cblas_axpy<T>(K*K,1.0,aatT+K*K*i,1,aat._X,1);
   aat.fillSymmetric();
   delete[](aatT);
}

/// XAt <- X*A'
template <typename T> inline void SpMatrix<T>::XAt(const Matrix<T>& X,
      Matrix<T>& XAt) const {
   INTM j,i;
   INTM n=X._m;
   INTM K=_m;
   INTM M=_n;

   XAt.resize(n,K);
   /* compute X alpha^T */
   int NUM_THREADS=init_omp(MAX_THREADS);
   T* XatT=new T[NUM_THREADS*n*K];
   for (j = 0; j<NUM_THREADS*n*K; ++j) XatT[j]=T();

#pragma omp parallel for private(i,j)
   for (i = 0; i<M; ++i) {
#ifdef _OPENMP
      int numT=omp_get_thread_num();
#else
      int numT=0;
#endif
      T* write_area=XatT+numT*n*K;
      for (j = _pB[i]; j<_pE[i]; ++j) {
         cblas_axpy<T>(n,_v[j],X._X+i*n,1,write_area+_r[j]*n,1);
      }
   }

   cblas_copy<T>(n*K,XatT,1,XAt._X,1);
   for (i = 1; i<NUM_THREADS; ++i) 
      cblas_axpy<T>(n*K,1.0,XatT+n*K*i,1,XAt._X,1);
   delete[](XatT);
};

/// XAt <- X(:,indices)*A(:,indices)'
template <typename T> inline void SpMatrix<T>::XAt(const Matrix<T>& X,
      Matrix<T>& XAt, const Vector<INTM>& indices) const {
   INTM j,i;
   INTM n=X._m;
   INTM K=_m;
   INTM M=indices.n();

   XAt.resize(n,K);
   /* compute X alpha^T */
   int NUM_THREADS=init_omp(MAX_THREADS);
   T* XatT=new T[NUM_THREADS*n*K];
   for (j = 0; j<NUM_THREADS*n*K; ++j) XatT[j]=T();

#pragma omp parallel for private(i,j)
   for (i = 0; i<M; ++i) {
      INTM ii = indices[i];
#ifdef _OPENMP
      int numT=omp_get_thread_num();
#else
      int numT=0;
#endif
      T* write_area=XatT+numT*n*K;
      for (j = _pB[ii]; j<_pE[ii]; ++j) {
         cblas_axpy<T>(n,_v[j],X._X+i*n,1,write_area+_r[j]*n,1);
      }
   }

   cblas_copy<T>(n*K,XatT,1,XAt._X,1);
   for (i = 1; i<NUM_THREADS; ++i) 
      cblas_axpy<T>(n*K,1.0,XatT+n*K*i,1,XAt._X,1);
   delete[](XatT);
};

/// XAt <- sum_i w_i X(:,i)*A(:,i)'
template <typename T> inline void SpMatrix<T>::wXAt(const Vector<T>& w,
      const Matrix<T>& X, Matrix<T>& XAt, const int numThreads) const {
   INTM j,l,i;
   INTM n=X._m;
   INTM K=_m;
   INTM M=_n;
   INTM Mx = X._n;
   INTM numRepX= M/Mx;
   // assert(numRepX*Mx == M);
   XAt.resize(n,K);
   /* compute X alpha^T */
   int NUM_THREADS=init_omp(numThreads);
   T* XatT=new T[NUM_THREADS*n*K];
   for (j = 0; j<NUM_THREADS*n*K; ++j) XatT[j]=T();

#pragma omp parallel for private(i,j,l)
   for (i = 0; i<Mx; ++i) {
#ifdef _OPENMP
      int numT=omp_get_thread_num();
#else
      int numT=0;
#endif
      T * write_area=XatT+numT*n*K;
      for (l = 0; l<numRepX; ++l) {
         INTM ind=numRepX*i+l;
         if (w._X[ind] != 0)
            for (j = _pB[ind]; j<_pE[ind]; ++j) {
               cblas_axpy<T>(n,w._X[ind]*_v[j],X._X+i*n,1,write_area+_r[j]*n,1);
            }
      }
   }

   cblas_copy<T>(n*K,XatT,1,XAt._X,1);
   for (i = 1; i<NUM_THREADS; ++i) 
      cblas_axpy<T>(n*K,1.0,XatT+n*K*i,1,XAt._X,1);
   delete[](XatT);
};

/// copy the sparse matrix into a dense matrix
template<typename T> inline void SpMatrix<T>::toFull(Matrix<T>& matrix) const {
   matrix.resize(_m,_n);
   matrix.setZeros();
   T* out = matrix._X;
   for (INTM i=0; i<_n; ++i) {
      for (INTM j = _pB[i]; j<_pE[i]; ++j) {
         out[i*_m+_r[j]]=_v[j];
      }
   }
};

/// copy the sparse matrix into a full dense matrix
template <typename T> inline void SpMatrix<T>::toFullTrans(
      Matrix<T>& matrix) const {
   matrix.resize(_n,_m);
   matrix.setZeros();
   T* out = matrix._X;
   for (INTM i=0; i<_n; ++i) {
      for (INTM j = _pB[i]; j<_pE[i]; ++j) {
         out[i+_r[j]*_n]=_v[j];
      }
   }
};


/// use the data from v, r for _v, _r
template <typename T> inline void SpMatrix<T>::convert(const Matrix<T>&vM, 
      const Matrix<INTM>& rM, const INTM K) {
   const INTM M = rM.n();
   const INTM L = rM.m();
   const INTM* r = rM.X();
   const T* v = vM.X();
   INTM count=0;
   for (INTM i = 0; i<M*L; ++i) if (r[i] != -1) ++count;
   resize(K,M,count);
   count=0;
   for (INTM i = 0; i<M; ++i) {
      _pB[i]=count;
      for (INTM j = 0; j<L; ++j) {
         if (r[i*L+j] == -1) break;
         _v[count]=v[i*L+j];
         _r[count++]=r[i*L+j];
      }
      _pE[i]=count;
   }
   for (INTM i = 0; i<M; ++i) sort(_r,_v,_pB[i],_pE[i]-1);
};

/// use the data from v, r for _v, _r
template <typename T> inline void SpMatrix<T>::convert2(
      const Matrix<T>&vM, const Vector<INTM>& rv, const INTM K) {
   const INTM M = vM.n();
   const INTM L = vM.m();
   INTM* r = rv.rawX();
   const T* v = vM.X();
   INTM LL=0;
   for (INTM i = 0; i<L; ++i) if (r[i] != -1) ++LL;
   this->resize(K,M,LL*M);
   INTM count=0;
   for (INTM i = 0; i<M; ++i) {
      _pB[i]=count;
      for (INTM j = 0; j<LL; ++j) {
         _v[count]=v[i*L+j];
         _r[count++]=r[j];
      }
      _pE[i]=count;
   }
   for (INTM i = 0; i<M; ++i) sort(_r,_v,_pB[i],_pE[i]-1);
};

/// returns the l2 norms ^2 of the columns
template <typename T>
inline void SpMatrix<T>::norm_2sq_cols(Vector<T>& norms) const {
   norms.resize(_n);
   SpVector<T> col;
   for (INTM i = 0; i<_n; ++i) {
      this->refCol(i,col);
      norms[i] = col.nrm2sq();
   }
};

template <typename T>
inline void SpMatrix<T>::norm_0_cols(Vector<T>& norms) const {
   norms.resize(_n);
   SpVector<T> col;
   for (INTM i = 0; i<_n; ++i) {
      this->refCol(i,col);
      norms[i] = static_cast<T>(col.length());
   }
};

template <typename T>
inline void SpMatrix<T>::norm_1_cols(Vector<T>& norms) const {
   norms.resize(_n);
   SpVector<T> col;
   for (INTM i = 0; i<_n; ++i) {
      this->refCol(i,col);
      norms[i] =col.asum();
   }
};


/* ***************************
 * Implementation of SpVector 
 * ***************************/


/// Constructor, of the sparse vector of size L.
template <typename T> SpVector<T>::SpVector(T* v, INTM* r, INTM L, INTM nzmax) :
   _externAlloc(true), _v(v), _r(r), _L(L), _nzmax(nzmax)  { };

/// Constructor, allocates nzmax slots
template <typename T> SpVector<T>::SpVector(INTM nzmax) :
   _externAlloc(false), _L(0), _nzmax(nzmax) {
#pragma omp critical
      {
         _v = new T[nzmax];
         _r = new INTM[nzmax];
      }
   };

/// Empty constructor
template <typename T> SpVector<T>::SpVector() : _externAlloc(true), _v(NULL), _r(NULL), _L(0),
   _nzmax(0) { };


/// Destructor
template <typename T> SpVector<T>::~SpVector() { clear(); };


/// computes the sum of the magnitude of the elements
template <typename T> inline T SpVector<T>::asum() const {
   return cblas_asum<T>(_L,_v,1);
};

/// computes the l2 norm ^2 of the vector
template <typename T> inline T SpVector<T>::nrm2sq() const {
   return cblas_dot<T>(_L,_v,1,_v,1);
};

/// computes the l2 norm of the vector
template <typename T> inline T SpVector<T>::nrm2() const {
   return cblas_nrm2<T>(_L,_v,1);
};

/// computes the l2 norm of the vector
template <typename T> inline T SpVector<T>::fmaxval() const {
   Vector<T> tmp(_v,_L);
   return tmp.fmaxval();
};

/// print the vector to std::cerr
template <typename T> inline void SpVector<T>::print(const string& name) const {
   // std::cerr << name << std::endl;
   // std::cerr << _nzmax << std::endl;
   // for (INTM i = 0; i<_L; ++i)
      // cerr << "(" <<_r[i] << ", " <<  _v[i] << ")" << endl;
};

/// create a reference on the vector r
template <typename T> inline void SpVector<T>::refIndices(
      Vector<INTM>& indices) const {
   indices.setPointer(_r,_L);   
};

/// creates a reference on the vector val
template <typename T> inline void SpVector<T>::refVal(
      Vector<T>& val) const {
   val.setPointer(_v,_L);   
};

/// a <- a.^2
template <typename T> inline void SpVector<T>::sqr() {
   vSqr<T>(_L,_v,_v);
};

template <typename T>
inline void SpVector<T>::scal(const T a) {
   cblas_scal<T>(_L,a,_v,1);
};

template <typename T>
inline T SpVector<T>::dot(const SpVector<T>& vec) const {
   T sum=T();
   INTM countI = 0;
   INTM countJ = 0;
   while (countI < _L && countJ < vec._L) {
      const INTM rI = _r[countI];
      const INTM rJ = vec._r[countJ];
      if (rI > rJ) {
         ++countJ;
      } else if (rJ > rI) {
         ++countI;
      } else {
         sum+=_v[countI]*vec._v[countJ];
         ++countI;
         ++countJ;
      }
   }
   return sum;
};

template <typename T>
inline T SpVector<T>::dot(const Vector<T>& vec) const {
//   return cblas_doti<T>(_L,_v,_r,vec._X);
   T sum=T();
   INTM countI = 0;
   while (countI < _L) {
      sum+=_v[countI]*vec[_r[countI]];
      ++countI;
   }
   return sum;
};

/// clears the vector
template <typename T> inline void SpVector<T>::clear() {
   if (!_externAlloc) {
      delete[](_v);
      delete[](_r);
   }
   _v=NULL;
   _r=NULL;
   _L=0;
   _nzmax=0;
   _externAlloc=true;
};

/// resizes the vector
template <typename T> inline void SpVector<T>::resize(const INTM nzmax) {
   if (_nzmax != nzmax) {
      clear();
      _nzmax=nzmax;
      _L=0;
      _externAlloc=false;
#pragma omp critical
      {
         _v=new T[nzmax];
         _r=new INTM[nzmax];
      }
   }
};

template <typename T> void inline SpVector<T>::toSpMatrix(
      SpMatrix<T>& out, const INTM m, const INTM n) const {
   out.resize(m,n,_L);
   cblas_copy<T>(_L,_v,1,out._v,1);
   INTM current_col=0;
   INTM* out_r=out._r;
   INTM* out_pB=out._pB;
   out_pB[0]=current_col;
   for (INTM i = 0; i<_L; ++i) {
      INTM col=_r[i]/m;
      if (col > current_col) {
         out_pB[current_col+1]=i;
         current_col++;
         i--;
      } else {
         out_r[i]=_r[i]-col*m;
      }
   }
   for (current_col++ ; current_col < n+1; ++current_col) 
      out_pB[current_col]=_L;
};

template <typename T> void inline SpVector<T>::toFull(Vector<T>& out)
   const {
      out.setZeros();
      T* X = out.rawX();
      for (INTM i = 0; i<_L; ++i)
         X[_r[i]]=_v[i];
   };

/* ****************************
 * Implementaton of ProdMatrix
 * ****************************/

template <typename T> ProdMatrix<T>::ProdMatrix()  {
   _DtX= NULL; 
   _X=NULL; 
   _D=NULL; 
   _high_memory=true;
   _n=0;
   _m=0;
   _addDiag=0;
};

/// Constructor. Matrix D'*X is represented
template <typename T> ProdMatrix<T>::ProdMatrix(const Matrix<T>& D,
      const bool high_memory) {
   if (high_memory) _DtX = new Matrix<T>();
   this->setMatrices(D,high_memory);
};

/// Constructor. Matrix D'*X is represented
template <typename T> ProdMatrix<T>::ProdMatrix(const Matrix<T>& D, const Matrix<T>& X,
      const bool high_memory) {
   if (high_memory) _DtX = new Matrix<T>();
   this->setMatrices(D,X,high_memory);
};

template <typename T> inline void ProdMatrix<T>::setMatrices(const Matrix<T>& D, const Matrix<T>& X,
      const bool high_memory)  {
   _high_memory=high_memory;
   _m = D.n(); 
   _n = X.n();
   if (high_memory) {
      D.mult(X,*_DtX,true,false);
   } else {
      _X=&X;
      _D=&D;
      _DtX=NULL;
   }
   _addDiag=0;
};

template <typename T> inline void ProdMatrix<T>::setMatrices(
      const Matrix<T>& D, const bool high_memory) {
   _high_memory=high_memory;
   _m = D.n(); 
   _n = D.n();
   if (high_memory) {
      D.XtX(*_DtX);
   } else {
      _X=&D;
      _D=&D;
      _DtX=NULL;
   } 
   _addDiag=0;
};

/// compute DtX(:,i)
template <typename T> inline void ProdMatrix<T>::copyCol(const INTM i, Vector<T>& DtXi) const {
   if (_high_memory) {
      _DtX->copyCol(i,DtXi);
   } else {
      Vector<T> Xi;
      _X->refCol(i,Xi);
      _D->multTrans(Xi,DtXi);
      if (_addDiag && _m == _n) DtXi[i] += _addDiag;
   } 
};

/// compute DtX(:,i)
template <typename T> inline void ProdMatrix<T>::extract_rawCol(const INTM i,T* DtXi) const {
   if (_high_memory) {
      _DtX->extract_rawCol(i,DtXi);
   } else {
      Vector<T> Xi;
      Vector<T> vDtXi(DtXi,_m);
      _X->refCol(i,Xi);
      _D->multTrans(Xi,vDtXi);
      if (_addDiag && _m == _n) DtXi[i] += _addDiag;
   } 
};

template <typename T> inline void ProdMatrix<T>::add_rawCol(const INTM i,T* DtXi,
      const T a) const {
   if (_high_memory) {
      _DtX->add_rawCol(i,DtXi,a);
   } else {
      Vector<T> Xi;
      Vector<T> vDtXi(DtXi,_m);
      _X->refCol(i,Xi);
      _D->multTrans(Xi,vDtXi,a,T(1.0));
      if (_addDiag && _m == _n) DtXi[i] += a*_addDiag;
   } 
};

template <typename T> void inline ProdMatrix<T>::addDiag(const T diag) {
   if (_m == _n) {
      if (_high_memory) {
         _DtX->addDiag(diag);
      } else {
         _addDiag=diag;
      }
   }
};

template <typename T> inline T ProdMatrix<T>::operator[](const INTM index) const {
   if (_high_memory) {
      return (*_DtX)[index];
   } else {
      const INTM index2=index/this->_m;
      const INTM index1=index-this->_m*index2;
      Vector<T> col1, col2;
      _D->refCol(index1,col1);
      _X->refCol(index2,col2);
      return col1.dot(col2);
   }
};


template <typename T> inline T ProdMatrix<T>::operator()(const INTM index1,
      const INTM index2) const {
   if (_high_memory) {
      return (*_DtX)(index1,index2);
   } else {
      Vector<T> col1, col2;
      _D->refCol(index1,col1);
      _X->refCol(index2,col2);
      return col1.dot(col2);
   }
};

template <typename T> void inline ProdMatrix<T>::diag(Vector<T>& diag) const {
   if (_m == _n) {
      if (_high_memory) {
         _DtX->diag(diag);
      } else {
         Vector<T> col1, col2;
         for (INTM i = 0; i <_m; ++i) {
            _D->refCol(i,col1);
            _X->refCol(i,col2);
            diag[i] = col1.dot(col2);
         }
      }
   }
};

template <typename T> class SubMatrix : public AbstractMatrix<T> {

   public:
      SubMatrix(AbstractMatrix<T>& G, Vector<INTM>& indI, Vector<INTM>& indJ);

      void inline convertIndicesI(Vector<INTM>& ind) const;
      void inline convertIndicesJ(Vector<INTM>& ind) const;
      INTM inline n() const { return _indicesJ.n(); };
      INTM inline m() const { return _indicesI.n(); };
      void inline extract_rawCol(const INTM i, T* pr) const;
      /// compute DtX(:,i)
      inline void copyCol(const INTM i, Vector<T>& DtXi) const;
      /// compute DtX(:,i)
      inline void add_rawCol(const INTM i, T* DtXi, const T a) const;
      /// compute DtX(:,i)
      inline void diag(Vector<T>& diag) const;
      inline T operator()(const INTM index1, const INTM index2) const;

   private:
      Vector<INTM> _indicesI;
      Vector<INTM> _indicesJ;
      AbstractMatrix<T>* _matrix;
};

template <typename T> 
SubMatrix<T>::SubMatrix(AbstractMatrix<T>& G, Vector<INTM>& indI, Vector<INTM>& indJ) {
   _matrix = &G;
   _indicesI.copy(indI);
   _indicesJ.copy(indJ);
};

template <typename T> void inline SubMatrix<T>::convertIndicesI(
      Vector<INTM>& ind) const {
   INTM* pr_ind = ind.rawX();
   for (INTM i = 0; i<ind.n(); ++i) {
      if (pr_ind[i] == -1) break;
      pr_ind[i]=_indicesI[pr_ind[i]];
   }
};

template <typename T> void inline SubMatrix<T>::convertIndicesJ(
      Vector<INTM>& ind) const {
   INTM* pr_ind = ind.rawX();
   for (INTM i = 0; i<ind.n(); ++i) {
      if (pr_ind[i] == -1) break;
      pr_ind[i]=_indicesJ[pr_ind[i]];
   }
};

template <typename T> void inline SubMatrix<T>::extract_rawCol(const INTM i, T* pr) const {
   INTM* pr_ind=_indicesI.rawX();
   INTM* pr_ind2=_indicesJ.rawX();
   for (INTM j = 0; j<_indicesI.n(); ++j) {
      pr[j]=(*_matrix)(pr_ind[j],pr_ind2[i]);
   }
};

template <typename T> inline void SubMatrix<T>::copyCol(const INTM i, 
      Vector<T>& DtXi) const {
   this->extract_rawCol(i,DtXi.rawX());
};

template <typename T> void inline SubMatrix<T>::add_rawCol(const INTM i, T* pr,
      const T a) const {
   INTM* pr_ind=_indicesI.rawX();
   INTM* pr_ind2=_indicesJ.rawX();
   for (INTM j = 0; j<_indicesI.n(); ++j) {
      pr[j]+=a*(*_matrix)(pr_ind[j],pr_ind2[i]);
   }
};

template <typename T> void inline SubMatrix<T>::diag(Vector<T>& diag) const {
   T* pr = diag.rawX();
   INTM* pr_ind=_indicesI.rawX();
   for (INTM j = 0; j<_indicesI.n(); ++j) {
      pr[j]=(*_matrix)(pr_ind[j],pr_ind[j]);
   }
};

template <typename T> inline T SubMatrix<T>::operator()(const INTM index1, 
      const INTM index2) const {
   return (*_matrix)(_indicesI[index1],_indicesJ[index2]);
}

/// Matrix with shifts
template <typename T> class ShiftMatrix : public AbstractMatrixB<T> {
   public:
      ShiftMatrix(const AbstractMatrixB<T>& inputmatrix, const int shifts, const bool center = false) : _shifts(shifts), _inputmatrix(&inputmatrix), _centered(false) {
         _m=_inputmatrix->m()-shifts+1;
         _n=_inputmatrix->n()*shifts;
         if (center) this->center();
      };
      INTM n() const { return _n; };
      INTM m() const { return _m; };

      /// b <- alpha A'x + beta b
      void multTrans(const Vector<T>& x, Vector<T>& b,
            const T alpha = 1.0, const T beta = 0.0) const;

      /// perform b = alpha*A*x + beta*b, when x is sparse
      virtual void mult(const SpVector<T>& x, Vector<T>& b, 
            const T alpha = 1.0, const T beta = 0.0) const;

      virtual void mult(const Vector<T>& x, Vector<T>& b, 
            const T alpha = 1.0, const T beta = 0.0) const;

      /// perform C = a*A*B + b*C, possibly transposing A or B.
      virtual void mult(const Matrix<T>& B, Matrix<T>& C, 
            const bool transA = false, const bool transB = false,
            const T a = 1.0, const T b = 0.0) const;

      virtual void mult(const SpMatrix<T>& B, Matrix<T>& C, 
            const bool transA = false, const bool transB = false,
            const T a = 1.0, const T b = 0.0) const;

      /// perform C = a*B*A + b*C, possibly transposing A or B.
      virtual void multSwitch(const Matrix<T>& B, Matrix<T>& C, 
            const bool transA = false, const bool transB = false,
            const T a = 1.0, const T b = 0.0) const;

      /// XtX = A'*A
      virtual void XtX(Matrix<T>& XtX) const;

      virtual void copyRow(const INTM i, Vector<T>& x) const;

      virtual void copyTo(Matrix<T>& copy) const;
      virtual T dot(const Matrix<T>& x) const;

      virtual void print(const string& name) const;

      virtual ~ShiftMatrix() {  };

   private:
      void center() { 
         Vector<T> ones(_m);
         ones.set(T(1.0)/_m);
         this->multTrans(ones,_means);
         _centered=true;  };

      INTM _m;
      INTM _n;
      int _shifts;
      Vector<T> _means;
      const AbstractMatrixB<T>* _inputmatrix;
      bool _centered;
};

template <typename T> void ShiftMatrix<T>::multTrans(const
      Vector<T>& x, Vector<T>& b, const T alpha, const T beta) const {
   b.resize(_n);
   if (beta==0) b.setZeros();
   Vector<T> tmp(_inputmatrix->m());
   Vector<T> subvec;
   Vector<T> subvec2;
   const INTM nn=_inputmatrix->n();
   for (int i = 0; i<_shifts; ++i) {
      tmp.setZeros();
      subvec2.setData(tmp.rawX()+i,_m);
      subvec2.copy(x);
      subvec.setData(b.rawX()+i*nn,nn);
      _inputmatrix->multTrans(tmp,subvec,alpha,beta);
   }
   if (_centered) {
      b.add(_means,-alpha*x.sum());
   }
};


/// perform b = alpha*A*x + beta*b, when x is sparse
template <typename T> void ShiftMatrix<T>::mult(const
      SpVector<T>& x, Vector<T>& b, const T alpha, const T beta) const {
   b.resize(_m);
   if (beta==0) {
      b.setZeros();
   } else {
      b.scal(beta);
   }
   const INTM nn=_inputmatrix->n();
   const INTM mm=_inputmatrix->m();
   Vector<T> fullx(_n);
   x.toFull(fullx);
   SpVector<T> sptmp(nn);
   Vector<T> tmp;
   Vector<T> tmp2(mm);
   for (int i = 0; i<_shifts; ++i) {
      tmp.setData(fullx.rawX()+i*nn,nn);
      tmp.toSparse(sptmp);
      _inputmatrix->mult(sptmp,tmp2,alpha,0);
      tmp.setData(tmp2.rawX()+i,_m);
      b.add(tmp);
   }
   if (_centered) {
      b.add(-alpha*_means.dot(x));
   }
};

/// perform b = alpha*A*x + beta*b, when x is sparse
template <typename T> void ShiftMatrix<T>::mult(const
      Vector<T>& x, Vector<T>& b, const T alpha, const T beta) const {
   b.resize(_m);
   const INTM nn=_inputmatrix->n();
   const INTM mm=_inputmatrix->m();
   Vector<T> tmp;
   Vector<T> tmp2(mm);
   if (beta==0) {
      b.setZeros();
   } else {
      b.scal(beta);
   }
   for (int i = 0; i<_shifts; ++i) {
      tmp.setData(x.rawX()+i*nn,nn);
      _inputmatrix->mult(tmp,tmp2,alpha,0);
      tmp.setData(tmp2.rawX()+i,_m);
      b.add(tmp);
   }
   if (_centered) {
      b.add(-alpha*_means.dot(x));
   }
};

/// perform C = a*A*B + b*C, possibly transposing A or B.
template <typename T> void ShiftMatrix<T>::mult(const Matrix<T>&
      B, Matrix<T>& C, const bool transA, const bool transB, const T a, const T
      b) const {
   // cerr << "Shift Matrix is used in inadequate setting" << endl;
}

template <typename T> void ShiftMatrix<T>::mult(const SpMatrix<T>& B, Matrix<T>& C, 
      const bool transA, const bool transB, const T a, const T b) const {
   // cerr << "Shift Matrix is used in inadequate setting" << endl;
}

/// perform C = a*B*A + b*C, possibly transposing A or B.
template <typename T> void ShiftMatrix<T>::multSwitch(const
      Matrix<T>& B, Matrix<T>& C, const bool transA, const bool transB,
      const T a, const T b) const {
   // cerr << "Shift Matrix is used in inadequate setting" << endl;
}

template <typename T> void ShiftMatrix<T>::XtX(Matrix<T>& XtX) const {
   // cerr << "Shift Matrix is used in inadequate setting" << endl;
};

template <typename T> void ShiftMatrix<T>::copyRow(const INTM ind, Vector<T>& x) const {
   Vector<T> sub_vec;
   const INTM mm=_inputmatrix->m();
   for (int i = 0; i<_shifts; ++i) {
      sub_vec.setData(x.rawX()+i*mm,mm);
      _inputmatrix->copyRow(ind+i,sub_vec);
   }
   if (_centered) x.sub(_means);
};

template <typename T> void ShiftMatrix<T>::copyTo(Matrix<T>& x) const {
   // cerr << "Shift Matrix is used in inadequate setting" << endl;
};


template <typename T> T ShiftMatrix<T>::dot(const Matrix<T>& x) const {
   // cerr << "Shift Matrix is used in inadequate setting" << endl;
   return 0;
};

template <typename T> void ShiftMatrix<T>::print(const string& name) const {
   // cerr << name << endl;
   // cerr << "Shift Matrix: " << _shifts << " shifts" << endl;
   _inputmatrix->print(name);
};

/// Matrix with shifts
template <typename T> class DoubleRowMatrix : public AbstractMatrixB<T> {
   public:
      DoubleRowMatrix(const AbstractMatrixB<T>& inputmatrix) : _inputmatrix(&inputmatrix) { 
         _n=inputmatrix.n();
         _m=2*inputmatrix.m();
      };
      INTM n() const { return _n; };
      INTM m() const { return _m; };

      /// b <- alpha A'x + beta b
      void multTrans(const Vector<T>& x, Vector<T>& b,
            const T alpha = 1.0, const T beta = 0.0) const;

      /// perform b = alpha*A*x + beta*b, when x is sparse
      virtual void mult(const SpVector<T>& x, Vector<T>& b, 
            const T alpha = 1.0, const T beta = 0.0) const;

      virtual void mult(const Vector<T>& x, Vector<T>& b, 
            const T alpha = 1.0, const T beta = 0.0) const;

      /// perform C = a*A*B + b*C, possibly transposing A or B.
      virtual void mult(const Matrix<T>& B, Matrix<T>& C, 
            const bool transA = false, const bool transB = false,
            const T a = 1.0, const T b = 0.0) const;

      virtual void mult(const SpMatrix<T>& B, Matrix<T>& C, 
            const bool transA = false, const bool transB = false,
            const T a = 1.0, const T b = 0.0) const;

      /// perform C = a*B*A + b*C, possibly transposing A or B.
      virtual void multSwitch(const Matrix<T>& B, Matrix<T>& C, 
            const bool transA = false, const bool transB = false,
            const T a = 1.0, const T b = 0.0) const;

      /// XtX = A'*A
      virtual void XtX(Matrix<T>& XtX) const;

      virtual void copyRow(const INTM i, Vector<T>& x) const;

      virtual void copyTo(Matrix<T>& copy) const;
      virtual T dot(const Matrix<T>& x) const;

      virtual void print(const string& name) const;

      virtual ~DoubleRowMatrix() {  };

   private:
      INTM _m;
      INTM _n;
      const AbstractMatrixB<T>* _inputmatrix;
};


template <typename T> void DoubleRowMatrix<T>::multTrans(const
      Vector<T>& x, Vector<T>& b, const T alpha, const T beta) const {
   const INTM mm = _inputmatrix->m();
   Vector<T> tmp(mm);
   for (INTM i = 0; i<mm; ++i) 
      tmp[i]=x[2*i]+x[2*i+1];
   _inputmatrix->multTrans(tmp,b,alpha,beta);
};


/// perform b = alpha*A*x + beta*b, when x is sparse
template <typename T> void DoubleRowMatrix<T>::mult(const
      SpVector<T>& x, Vector<T>& b, const T alpha, const T beta) const {
   b.resize(_m);
   if (beta==0) {
      b.setZeros();
   } else {
      b.scal(beta);
   }
   const INTM mm = _inputmatrix->m();
   Vector<T> tmp(mm);
   _inputmatrix->mult(x,tmp,alpha);
   for (INTM i = 0; i<mm; ++i) {
      b[2*i]+=tmp[i];
      b[2*i+1]+=tmp[i];
   }
};

/// perform b = alpha*A*x + beta*b, when x is sparse
template <typename T> void DoubleRowMatrix<T>::mult(const
      Vector<T>& x, Vector<T>& b, const T alpha, const T beta) const {
   b.resize(_m);
   if (beta==0) {
      b.setZeros();
   } else {
      b.scal(beta);
   }
   const INTM mm = _inputmatrix->m();
   Vector<T> tmp(mm);
   _inputmatrix->mult(x,tmp,alpha);
   for (INTM i = 0; i<mm; ++i) {
      b[2*i]+=tmp[i];
      b[2*i+1]+=tmp[i];
   }
};

/// perform C = a*A*B + b*C, possibly transposing A or B.
template <typename T> void DoubleRowMatrix<T>::mult(const Matrix<T>&
      B, Matrix<T>& C, const bool transA, const bool transB, const T a, const T
      b) const {
   FLAG(5)
   // cerr << "Double Matrix is used in inadequate setting" << endl;
}

template <typename T> void DoubleRowMatrix<T>::mult(const SpMatrix<T>& B, Matrix<T>& C, 
      const bool transA, const bool transB, const T a, const T b) const {
   FLAG(4)
   // cerr << "Double Matrix is used in inadequate setting" << endl;
}

/// perform C = a*B*A + b*C, possibly transposing A or B.
template <typename T> void DoubleRowMatrix<T>::multSwitch(const
      Matrix<T>& B, Matrix<T>& C, const bool transA, const bool transB,
      const T a, const T b) const {
   FLAG(3)
   // cerr << "Double Matrix is used in inadequate setting" << endl;
}

template <typename T> void DoubleRowMatrix<T>::XtX(Matrix<T>& XtX) const {
   FLAG(2)
   // cerr << "Double Matrix is used in inadequate setting" << endl;
};

template <typename T> void DoubleRowMatrix<T>::copyRow(const INTM ind, Vector<T>& x) const {
   const INTM indd2= static_cast<INTM>(floor(static_cast<double>(ind)/2.0));
   _inputmatrix->copyRow(indd2,x);
};

template <typename T> void DoubleRowMatrix<T>::copyTo(Matrix<T>& x) const {
   FLAG(1)
   // cerr << "Double Matrix is used in inadequate setting" << endl;
};


template <typename T> T DoubleRowMatrix<T>::dot(const Matrix<T>& x) const {
   FLAG(0)
   // cerr << "Double Matrix is used in inadequate setting" << endl;
   return 0;
};

template <typename T> void DoubleRowMatrix<T>::print(const string& name) const {
   // cerr << name << endl;
   // cerr << "Double Row Matrix" << endl;
   _inputmatrix->print(name);
};

// solve (A'A+lambda I)x = A'b+delta
template <typename T> void AbstractMatrixB<T>::ridgeCG(const Vector<T>& b, const Vector<T>& delta,
      Vector<T>& x, const T lambda, const T tol, const int itermax) const {
   Vector<T> copyb;
   copyb.copy(b);
   List<int> missingvalues;
   for (int i = 0; i<b.n(); ++i) {
      if (isnan(b[i])) {
         copyb[i]=0;
         missingvalues.push_back(i);
      }
   }
   // (A'A+lambda I)x=A'b;
   Vector<T> R,P,AP,tmp;
   this->multTrans(copyb,R);
   R.add(delta);
   this->mult(x,tmp);
   for (ListIterator<int> it = missingvalues.begin();
         it != missingvalues.end(); ++it)
      tmp[*it]=0;
   this->multTrans(tmp,R,-T(1.0),T(1.0));
   R.add(x,-lambda);
   P.copy(R);
   int k = 0;
   T normR = R.nrm2sq();
   T alpha;
   while (normR > tol && k < itermax) {
      this->mult(P,tmp);
      for (ListIterator<int> it = missingvalues.begin();
            it != missingvalues.end(); ++it)
         tmp[*it]=0;
      this->multTrans(tmp,AP);
      AP.add(P,lambda);
      alpha = normR/P.dot(AP);
      x.add(P,alpha);
      R.add(AP,-alpha);
      T tmp = R.nrm2sq();
      P.scal(tmp/normR);
      normR = tmp;
      P.add(R,T(1.0));
      ++k;
   };
};



// solve (A'A+lambda I)x = A'b
template <typename T> void AbstractMatrixB<T>::ridgeCG(const Vector<T>& b,
      Vector<T>& x, const T lambda, const T tol, const int itermax) const {
   const int m = this->m();
   const int n = this->n();
   Vector<T> copyb;
   copyb.copy(b);
   List<int> missingvalues;
   for (int i = 0; i<b.n(); ++i) {
      if (isnan(b[i])) {
         copyb[i]=0;
         missingvalues.push_back(i);
      }
   }
   if (m > n) {
      // (A'A+lambda I)x=A'b;
      Vector<T> R,P,AP,tmp;
      this->multTrans(copyb,R);
      this->mult(x,tmp);
      for (ListIterator<int> it = missingvalues.begin();
            it != missingvalues.end(); ++it)
         tmp[*it]=0;
      this->multTrans(tmp,R,-T(1.0),T(1.0));
      R.add(x,-lambda);
      P.copy(R);
      int k = 0;
      T normR = R.nrm2sq();
      T alpha;
      while (normR > tol && k < itermax) {
         this->mult(P,tmp);
         for (ListIterator<int> it = missingvalues.begin();
               it != missingvalues.end(); ++it)
            tmp[*it]=0;
         this->multTrans(tmp,AP);
         AP.add(P,lambda);
         alpha = normR/P.dot(AP);
         x.add(P,alpha);
         R.add(AP,-alpha);
         T tmp = R.nrm2sq();
         P.scal(tmp/normR);
         normR = tmp;
         P.add(R,T(1.0));
         ++k;
      };
   } else {
      // (AA'+lambda I)delta=b;
      // x=A' delta;
      Vector<T> R,P,AP,tmp,delta;
      delta.resize(m);
      delta.setZeros();
      R.copy(copyb);
      this->multTrans(delta,tmp);
      this->mult(tmp,R,T(-1.0),T(1.0));
      R.add(delta,-lambda);
      P.copy(R);
      int k = 0;
      T normR = R.nrm2sq();
      T alpha;
      while (normR > tol && k < itermax) {
         this->multTrans(P,tmp);
         this->mult(tmp,AP);
         for (ListIterator<int> it = missingvalues.begin();
               it != missingvalues.end(); ++it)
            AP[*it]=0;
         AP.add(P,lambda);
         alpha = normR/P.dot(AP);
         delta.add(P,alpha);
         R.add(AP,-alpha);
         T tmp = R.nrm2sq();
         P.scal(tmp/normR);
         normR = tmp;
         P.add(R,T(1.0));
         ++k;
      }
      this->multTrans(delta,x);
   }
};

template <typename T> void AbstractMatrixB<T>::ridgeCG(const Matrix<T>& mb,
      Matrix<T>& mx, const T lambda, const T tol, const int itermax,const int numThreads) const {
   init_omp(numThreads);
   const int num_probs=mb.n();
   int i = 0;
#pragma omp parallel for private(i) 
   for (i =0; i<num_probs; ++i) {
      Vector<T> b;
      mb.refCol(i,b);
      Vector<T> x;
      mx.refCol(i,x);
      this->ridgeCG(b,x,lambda,tol,itermax);
   }
}


template <typename T> void AbstractMatrixB<T>::ridgeCG(const Matrix<T>& mb, const Matrix<T>& mdelta,
      Matrix<T>& mx, const T lambda, const T tol, const int itermax,const int numThreads) const {
   init_omp(numThreads);
   const int num_probs=mb.n();
   int i = 0;
#pragma omp parallel for private(i) 
   for (i =0; i<num_probs; ++i) {
      Vector<T> b;
      mb.refCol(i,b);
      Vector<T> delta;
      mdelta.refCol(i,delta);
      Vector<T> x;
      mx.refCol(i,x);
      this->ridgeCG(b,delta,x,lambda,tol,itermax);
   }
}



#endif
