Page MenuHomec4science

linalg.h
No OneTemporary

File Metadata

Created
Thu, May 15, 03:35

linalg.h

/* 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>
#ifdef NEW_MATLAB
typedef ptrdiff_t INTT;
#else
typedef int INTT;
#endif
#include <utils.h>
#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< int > 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 int i) const = 0;
virtual void getGroup(Matrix<T>& data, const vector_groups& groups,
const int i) const = 0;
virtual inline T operator[](const int index) const = 0;
virtual int n() const = 0;
virtual int m() const = 0;
virtual int V() const = 0;
virtual void norm_2sq_cols(Vector<T>& norms) const { };
virtual ~Data() { };
};
/// Abstract matrix class
template <typename T> class AbstractMatrixB {
public:
virtual int n() const = 0;
virtual int 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 int 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;
virtual ~AbstractMatrixB() { };
};
/// Abstract matrix class
template <typename T> class AbstractMatrix {
public:
virtual int n() const = 0;
virtual int m() const = 0;
/// copy X(:,i) into Xi
virtual void copyCol(const int i, Vector<T>& Xi) const = 0;
/// compute X(:,i)<- X(:,i)+a*col;
virtual void add_rawCol(const int i, T* col, const T a) const = 0;
/// copy X(:,i) into Xi
virtual void extract_rawCol(const int i,T* Xi) const = 0;
/// extract diagonal
virtual void diag(Vector<T>& diag) const = 0;
//// extract X(index1,index2)
virtual inline T operator()(const int index1, const int 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, int m, int n);
/// Constructor for a new m x n matrix
Matrix(int m, int n);
/// Empty constructor
Matrix();
/// Destructor
virtual ~Matrix();
/// Accessors
/// Number of rows
inline int m() const { return _m; };
/// Number of columns
inline int n() const { return _n; };
/// Return a modifiable reference to X(i,j)
inline T& operator()(const int i, const int j);
/// Return the value X(i,j)
inline T operator()(const int i, const int j) const;
/// Return a modifiable reference to X(i) (1D indexing)
inline T& operator[](const int index) { return _X[index]; };
/// Return the value X(i) (1D indexing)
inline T operator[](const int index) const { return _X[index]; };
/// Copy the column i into x
inline void copyCol(const int i, Vector<T>& x) const;
/// Copy the column i into x
inline void copyRow(const int i, Vector<T>& x) const;
/// Copy the column i into x
inline void extract_rawCol(const int i, T* x) const;
/// Copy the column i into x
virtual void add_rawCol(const int i, T* DtXi, const T a) const;
/// Copy the column i into x
inline void getData(Vector<T>& data, const int i) const;
/// extract the group i
virtual void getGroup(Matrix<T>& data, const vector_groups& groups,
const int i) const;
/// Reference the column i into the vector x
inline void refCol(int i, Vector<T>& x) const;
/// Reference the column i to i+n into the Matrix mat
inline void refSubMat(int i, int n, Matrix<T>& mat) const;
/// extract a sub-matrix of a symmetric matrix
inline void subMatrixSym(const Vector<int>& 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(int m, int n);
/// Change the data in the matrix
inline void setData(T* X, int m, int n);
/// modify _m
inline void setm(const int m) { _m = m; }; //DANGEROUS
/// modify _n
inline void setn(const int 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 int m, const int n) { _n = n; _m=m;};
/// whiten
inline void whiten(const int 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 int 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 int 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 int 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 int i, Vector<T>& row) const;
inline void setRow(const int i, const Vector<T>& row);
inline void addRow(const int 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<int>& ind, const T sigma);
/// performs soft-thresholding of the vector
inline void blockThrshold(const T nu, const int 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 int 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;
protected:
/// Forbid lazy copies
explicit Matrix<T>(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
int _m;
/// number of columns
int _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(int n);
/// Constructor with existing data
Vector(T* X, int n);
/// Copy constructor
explicit Vector<T>(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 int max() const;
/// returns the index of the minimum value
inline int 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 int fmax() const;
/// returns the index of the value with smallest magnitude
inline int 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 int index);
/// returns X[index]
inline T operator[](const int index) const;
/// make a copy of x
inline void copy(const Vector<T>& x);
/// returns the size of the vector
inline int 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 int n) { _n = n; };
/// generate logarithmically spaced values
inline void logspace(const int n, const T a, const T b);
inline int nnz() const;
/// Modifiers
/// Set all values to zero
inline void setZeros();
/// resize the vector
inline void resize(const int n);
/// change the data of the vector
inline void setPointer(T* X, const int n);
inline void setData(T* X, const int n) { this->setPointer(X,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 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 int 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 <- 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 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 int 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 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<int>& key, const bool mode) const;
/// sort the vector
inline void sort2(Vector<int>& 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
int _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, int* r, int* pB, int* pE, int m, int n, int nzmax);
/// Constructor, new m x n matrix, with at most nzmax non-zeros values
SpMatrix(int m, int n, int nzmax);
/// Empty constructor
SpMatrix();
/// Destructor
~SpMatrix();
/// Accessors
/// reference the column i into vec
inline void refCol(int i, SpVector<T>& vec) const;
/// returns pB[i]
inline int pB(const int i) const { return _pB[i]; };
/// returns r[i]
inline int r(const int i) const { return _r[i]; };
/// returns v[i]
inline T v(const int i) const { return _v[i]; };
/// returns the maximum number of non-zero elements
inline int nzmax() const { return _nzmax; };
/// returns the number of rows
inline int n() const { return _n; };
/// returns the number of columns
inline int m() const { return _m; };
/// returns the number of columns
inline int V() const { return 1; };
/// returns X[index]
inline T operator[](const int index) const;
void getData(Vector<T>& data, const int index) const;
void getGroup(Matrix<T>& data, const vector_groups& groups,
const int 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 int* pB() const { return _pB; };
/// Direct access to _pE
inline int* pE() const { return _pE; };
/// Direct access to _r
inline int* r() const { return _r; };
/// Direct access to _v
inline T* v() const { return _v; };
/// number of nonzeros elements
inline int 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 int m, const int n, const int 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<int>& 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<int>& 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 int 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<int>& r,
const int K);
/// use the data from v, r for _v, _r
inline void convert2(const Matrix<T>&v, const Vector<int>& r,
const int 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);
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
int* _r;
/// indices of the beginning of columns
int* _pB;
/// indices of the end of columns
int* _pE;
/// number of rows
int _m;
/// number of columns
int _n;
/// number of non-zero values
int _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, int* r, int L, int nzmax);
/// Constructor, allocates nzmax slots
SpVector(int 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<int>& indices) const;
/// creates a reference on the vector val
inline void refVal(Vector<T>& val) const;
/// access table r
inline int r(const int i) const { return _r[i]; };
/// access table r
inline T v(const int i) const { return _v[i]; };
inline T* rawX() const { return _v; };
///
inline int L() const { return _L; };
///
inline void setL(const int L) { _L=L; };
/// a <- a.^2
inline void sqr();
/// dot product
inline T dot(const SpVector<T>& vec) const;
/// Modifiers
/// clears the vector
inline void clear();
/// resizes the vector
inline void resize(const int nzmax);
/// resize the vector as a sparse matrix
void inline toSpMatrix(SpMatrix<T>& out,
const int m, const int 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
int* _r;
/// length
int _L;
/// maximum number of nonzeros elements
int _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 int i, Vector<T>& DtXi) const;
/// compute DtX(:,i)
inline void extract_rawCol(const int i,T* DtXi) const;
/// compute DtX(:,i)
virtual void add_rawCol(const int 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 int n() const { return _n;};
/// returns the number of rows
inline int m() const { return _m;};
/// returns the value of an index
inline T operator()(const int index1, const int index2) const;
/// returns the value of an index
inline T operator[](const int 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;
int _n;
int _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, int m, int n) :
_externAlloc(true), _X(X), _m(m), _n(n) { };
/// Constructor for a new m x n matrix
template <typename T> Matrix<T>::Matrix(int m, int 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 int i, const int j) {
return _X[j*_m+i];
};
/// Return the value X(i,j)
template <typename T> inline T Matrix<T>::operator()(const int i, const int 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 (int i = 0; i<_m; ++i) {
for (int 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 into x
template <typename T> inline void Matrix<T>::copyCol(const int 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 into x
template <typename T> inline void Matrix<T>::copyRow(const int 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 into x
template <typename T> inline void Matrix<T>::extract_rawCol(const int i, T* x) const {
assert(i >= 0 && i<_n);
cblas_copy<T>(_m,_X+i*_m,1,x,1);
};
/// Copy the column i into x
template <typename T> inline void Matrix<T>::add_rawCol(const int 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 into x
template <typename T> inline void Matrix<T>::getData(Vector<T>& x, const int i) const {
this->copyCol(i,x);
};
template <typename T> inline void Matrix<T>::getGroup(Matrix<T>& data,
const vector_groups& groups, const int i) const {
const group& gr = groups[i];
const int N = gr.size();
data.resize(_m,N);
int 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(int 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 into the Matrix mat
template <typename T> inline void Matrix<T>::refSubMat(int i, int 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 (int 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 (int i = 0; i<_n; ++i) {
for (int 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 int 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 int 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<int>& indices, Matrix<T>& subMatrix) const {
int L = indices.n();
subMatrix.resize(L,L);
T* out = subMatrix._X;
int* rawInd = indices.rawX();
for (int i = 0; i<L; ++i)
for (int 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(int m, int n) {
if (_n==n && _m==m) return;
clear();
_n=n;
_m=m;
_externAlloc=false;
#pragma omp critical
{
_X=new T[_n*_m];
}
setZeros();
};
/// Change the data in the matrix
template <typename T> inline void Matrix<T>::setData(T* X, int m, int 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 (int 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 (int 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 (int 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 (int 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); /// multi with 1/l2-norm
} else {
// for (int 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 (int 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 (int 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 (int i = 0; i<_n; ++i)
for (int j = 0; j<_m; ++j)
mean_rows[j] += _X[i*_m+j];
mean_rows.scal(T(1.0)/_n);
for (int i = 0; i<_n; ++i)
for (int 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 (int 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
/// into the lower-left part
template <typename T> inline void Matrix<T>::fillSymmetric() {
for (int i = 0; i<_n; ++i) {
for (int j =0; j<i; ++j) {
_X[j*_m+i]=_X[i*_m+j];
}
}
};
template <typename T> inline void Matrix<T>::fillSymmetric2() {
for (int i = 0; i<_n; ++i) {
for (int j =0; j<i; ++j) {
_X[i*_m+j]=_X[j*_m+i];
}
}
};
template <typename T> inline void Matrix<T>::whiten(const int V) {
const int sizePatch=_m/V;
for (int i = 0; i<_n; ++i) {
for (int j = 0; j<V; ++j) {
T mean = 0;
for (int k = 0; k<sizePatch; ++k) {
mean+=_X[i*_m+sizePatch*j+k];
}
mean /= sizePatch;
for (int 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 int n =static_cast<int>(sqrt(static_cast<T>(_m)));
int count[4];
for (int i = 0; i<4; ++i) count[i]=0;
for (int i = 0; i<_n; ++i) {
int offsetx=0;
for (int j = 0; j<n; ++j) {
offsetx= (offsetx+1) % 2;
int offsety=0;
for (int k = 0; k<n; ++k) {
offsety= (offsety+1) % 2;
mean[2*offsetx+offsety]+=_X[i*_m+j*n+k];
count[2*offsetx+offsety]++;
}
}
}
for (int i = 0; i<4; ++i)
mean[i] /= count[i];
for (int i = 0; i<_n; ++i) {
int offsetx=0;
for (int j = 0; j<n; ++j) {
offsetx= (offsetx+1) % 2;
int offsety=0;
for (int k = 0; k<n; ++k) {
offsety= (offsety+1) % 2;
_X[i*_m+j*n+k]-=mean[2*offsetx+offsety];
}
}
}
} else {
const int V = mean.n();
const int sizePatch=_m/V;
for (int i = 0; i<_n; ++i) {
for (int j = 0; j<V; ++j) {
for (int k = 0; k<sizePatch; ++k) {
mean[j]+=_X[i*_m+sizePatch*j+k];
}
}
}
mean.scal(T(1.0)/(_n*sizePatch));
for (int i = 0; i<_n; ++i) {
for (int j = 0; j<V; ++j) {
for (int 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 int V = mean.n();
const int sizePatch=_m/V;
mean.setZeros();
for (int i = 0; i<_n; ++i) {
for (int j = 0; j<V; ++j) {
for (int k = 0; k<sizePatch; ++k) {
mean[j]+=_X[i*_m+sizePatch*j+k];
}
}
}
for (int i = 0; i<V; ++i)
mean[i] /= _n*cblas_asum(sizePatch,mask._X+i*sizePatch,1);
for (int i = 0; i<_n; ++i) {
for (int j = 0; j<V; ++j) {
for (int 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 int n =static_cast<int>(sqrt(static_cast<T>(_m)));
for (int i = 0; i<_n; ++i) {
int offsetx=0;
for (int j = 0; j<n; ++j) {
offsetx= (offsetx+1) % 2;
int offsety=0;
for (int k = 0; k<n; ++k) {
offsety= (offsety+1) % 2;
_X[i*_m+j*n+k]+=mean[2*offsetx+offsety];
}
}
}
} else {
const int V = mean.n();
const int sizePatch=_m/V;
for (int i = 0; i<_n; ++i) {
for (int j = 0; j<V; ++j) {
for (int 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 (int i = 0; i<_n; ++i)
for (int j = 0; j<_m; ++j)
out[j*_n+i] = _X[i*_m+j];
};
/// A <- -A
template <typename T> inline void Matrix<T>::neg() {
for (int i = 0; i<_n*_m; ++i) _X[i]=-_X[i];
};
template <typename T> inline void Matrix<T>::incrDiag() {
for (int 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 (int 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 (int 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 (int 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 (int 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, *vv;
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 int 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 (int 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 (int 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() {
// int lwork=2*_n;
// T* work;
//#ifdef USE_BLAS_LIB
// INTT* ipiv;
//#else
// int* ipiv;
//#endif
//#pragma omp critical
// {
// work= new T[lwork];
//#ifdef USE_BLAS_LIB
/// ipiv= new INTT[lwork];
//#else
// ipiv= new int[lwork];
//#endif
// }
// sytrf<T>(upper,_n,_X,_n,ipiv,work,lwork);
// sytri<T>(upper,_n,_X,_n,ipiv,work);
// sytrf<T>(upper,_n,_X,_n);
sytri<T>(upper,_n,_X,_n);
this->fillSymmetric();
// delete[](work);
// delete[](ipiv);
};
/// 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 (int i = 0; i<_n; ++i) {
refCol(i,col);
b._X[i] = alpha*col.dot(x);
}
} else {
for (int 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 (int 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 (int i = 0; i<x._L; ++i) {
cblas_axpy<T>(_m,x._v[i],_X+x._r[i]*_m,1,b._X,1);
}
} else {
for (int 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;
int 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 (int 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 (int 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 (int 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 (int 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 (int i = 0; i< _n; ++i) {
for (int 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 (int i = 0; i< _n; ++i) {
for (int 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 int L) const {
XXt.resize(L,L);
for (int 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 {
int size_diag=MIN(_n,_m);
dv.resize(size_diag);
T* const d = dv.rawX();
for (int 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) {
int size_diag=MIN(_n,_m);
T* const d = dv.rawX();
for (int 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) {
int size_diag=MIN(_n,_m);
for (int 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();
int L = vec._L;
int* r = vec._r;
T* v = vec._v;
for (int i = 0; i<L; ++i)
for (int 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 int size_y= y.n();
const int nn = _n/size_y;
//y.resize(size_y);
//y.setZeros();
Matrix<T> tmp;
for (int 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();
int L = vec._L;
int* r = vec._r;
T* v = vec._v;
Vector<T> col;
for (int 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 (int 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();
int m = MIN(_n,_m);
for (int 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 (int 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 (int 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 (int i = 0; i<_n; ++i)
for (int j = 0; j<_m; ++j)
norms[j] += _X[i*_m+j]*_X[i*_m+j];
for (int 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 (int i = 0; i<_n; ++i)
for (int 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 (int 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 (int 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 (int i = 0; i<_n; ++i)
for (int 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 (int i = 0; i<_n; ++i)
for (int 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 (int 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 (int 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 (int i = 0; i<_n; ++i) {
T val = row[i];
for (int 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 int j,
Vector<T>& row) const {
row.resize(_n);
for (int 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 int j,
const Vector<T>& row) {
for (int 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 int j,
const Vector<T>& row, const T a) {
if (a==1.0) {
for (int i = 0; i<_n; ++i) {
_X[i*_m+j]+=row[i];
}
} else {
for (int 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 int sizeGroup) {
for (int i = 0; i<_n; ++i) {
int j;
for (j = 0; j<_m-sizeGroup+1; j+=sizeGroup) {
T nrm=0;
for (int k = 0; k<sizeGroup; ++k)
nrm += _X[i*_m +j+k]*_X[i*_m +j+k];
nrm=sqrt(nrm);
if (nrm < nu) {
for (int k = 0; k<sizeGroup; ++k)
_X[i*_m +j+k]=0;
} else {
T scal = (nrm-nu)/nrm;
for (int 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) {
int* r = vec1._r;
T* v = vec1._v;
T* X2 = vec2._X;
assert(vec2._n == _n);
if (alpha == 1.0) {
for (int i = 0; i<_n; ++i) {
for (int j = 0; j<vec1._L; ++j) {
_X[i*_m+r[j]] += v[j]*X2[i];
}
}
} else {
for (int i = 0; i<_n; ++i) {
for (int 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 int nn = vec1b.n();
const int size_A = _n/nn;
Matrix<T> tmp;
for (int 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) {
int* r = vec1._r;
T* v = vec1._v;
T* v2 = vec2._v;
int* r2 = vec2._r;
if (alpha == 1.0) {
for (int i = 0; i<vec2._L; ++i) {
for (int j = 0; j<vec1._L; ++j) {
_X[r2[i]*_m+r[j]] += v[j]*v2[i];
}
}
} else {
for (int i = 0; i<vec2._L; ++i) {
for (int 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) {
int* r = vec2._r;
T* v = vec2._v;
Vector<T> Xi;
for (int 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) {
int* r = vec1._r;
T* v = vec1._v;
if (alpha == 1.0) {
for (int i = 0; i<vec1._L; ++i) {
for (int j = 0; j<vec1._L; ++j) {
_X[r[i]*_m+r[j]] += v[j]*v[i];
}
}
} else {
for (int i = 0; i<vec1._L; ++i) {
for (int 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 (int i = 0; i<_n; ++i) {
for (int 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<int>& ind, const T sigma) {
if (ind.n() != _n) return;
init_omp(MAX_THREADS);
const int Ngroups=ind.maxval();
int i;
#pragma omp parallel for private(i)
for (i = 1; i<=Ngroups; ++i) {
Vector<int> indicesGroup(_n);
int count = 0;
for (int j = 0; j<_n; ++j)
if (ind[j] == i) indicesGroup[count++]=j;
Matrix<T> Xm(_m,count);
Vector<T> col, col2;
for (int 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 (int 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();
int count=0;
int* pB;
#pragma omp critical
{
pB=new int[_n+1];
}
int* pE=pB+1;
for (int i = 0; i<_n*_m; ++i)
if (_X[i] != 0) ++count;
int* r;
T* v;
#pragma omp critical
{
r=new int[count];
v=new T[count];
}
count=0;
for (int i = 0; i<_n; ++i) {
pB[i]=count;
for (int 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();
int count=0;
int* pB;
#pragma omp critical
{
pB=new int[_m+1];
}
int* pE=pB+1;
for (int i = 0; i<_n*_m; ++i)
if (_X[i] != 0) ++count;
int* r;
T* v;
#pragma omp critical
{
r=new int[count];
v=new T[count];
}
count=0;
for (int i = 0; i<_m; ++i) {
pB[i]=count;
for (int 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 int K =_n;
Matrix<T> G;
this->mult(B,G,true,false);
std::list<int> list;
for (int 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 (int i = 0; i<K; ++i) {
Vector<T> d, d2;
C.refCol(i,d);
this->refCol(i,d2);
d.copy(d2);
}
int count=0;
for (std::list<int>::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(int n) :
_externAlloc(false), _n(n) {
#pragma omp critical
{
_X=new T[_n];
}
};
/// Constructor with existing data
template <typename T> Vector<T>::Vector(T* X, int 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,_n);
for (int 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,_n);
for (int 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,_n);
for (int 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,_n);
for (int i = 0; i<_n; ++i) {
printf("%d ",_X[i] ? 1 : 0);
}
printf("\n");
};
/// returns the index of the largest value
template <typename T> inline int Vector<T>::max() const {
int imax=0;
T max=_X[0];
for (int 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 int Vector<T>::min() const {
int imin=0;
T min=_X[0];
for (int 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 int 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 (int i = 1; i<_n; ++i)
_X[i]=_X[i-1]+step;
for (int i = 0; i<_n; ++i)
_X[i]=pow(T(10.0),_X[i]);
}
template <typename T>
inline int Vector<T>::nnz() const {
int sum=0;
for (int i = 0; i<_n; ++i)
if (_X[i] != T()) ++sum;
return sum;
};
/// generate logarithmically spaced values
template <>
inline void Vector<int>::logspace(const int n, const int a, const int b) {
Vector<double> tmp(n);
tmp.logspace(n,double(a),double(b));
this->resize(n);
_X[0]=a;
_X[n-1]=b;
for (int i = 1; i<_n-1; ++i) {
int candidate=static_cast<int>(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 int Vector<T>::fmax() const {
return cblas_iamax<T>(_n,_X,1);
};
/// returns the index of the value with smallest magnitude
template <typename T> inline int 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 int i) {
assert(i>=0 && i<_n);
return _X[i];
};
/// returns X[index]
template <typename T> inline T Vector<T>::operator[] (const int 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 int 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 int 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 (int 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 (int i = 0; i<_n; ++i) {
if (_X[i] > nu) {
_X[i] -= nu;
} else if (_X[i] < -nu) {
_X[i] += nu;
} else {
_X[i] = T();
}
}
};
/// performs soft-thresholding of the vector
template <typename T> inline void Vector<T>::hardThrshold(const T nu) {
for (int 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 (int 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 (int 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 (int 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 (int 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 (int i = 0; i<_n; ++i) {
if (_X[i] < 0) _X[i]=0;
}
};
template <>
inline bool Vector<bool>::alltrue() const {
for (int i = 0; i<_n; ++i) {
if (!_X[i]) return false;
}
return true;
};
template <>
inline bool Vector<bool>::allfalse() const {
for (int 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 (int 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 T* v = x._v;
const int* r = x._r;
for (int i = 0; i<x._L; ++i) {
sum += _X[r[i]]*v[i];
}
return sum;
};
/// 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);
};
/// A <- A + a*x
template <typename T> inline void Vector<T>::add(const SpVector<T>& x,
const T a) {
if (a == 1.0) {
for (int i = 0; i<x._L; ++i)
_X[x._r[i]]+=x._v[i];
} else {
for (int 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 (int 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 (int 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>::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 int n =static_cast<int>(sqrt(static_cast<T>(_n)));
int count[4];
for (int i = 0; i<4; ++i) count[i]=0;
int offsetx=0;
for (int j = 0; j<n; ++j) {
offsetx= (offsetx+1) % 2;
int offsety=0;
for (int k = 0; k<n; ++k) {
offsety= (offsety+1) % 2;
meanv[2*offsetx+offsety]+=_X[j*n+k];
count[2*offsetx+offsety]++;
}
}
for (int i = 0; i<4; ++i)
meanv[i] /= count[i];
offsetx=0;
for (int j = 0; j<n; ++j) {
offsetx= (offsetx+1) % 2;
int offsety=0;
for (int k = 0; k<n; ++k) {
offsety= (offsety+1) % 2;
_X[j*n+k]-=meanv[2*offsetx+offsety];
}
}
} else {
const int V = meanv.n();
const int sizePatch=_n/V;
for (int j = 0; j<V; ++j) {
T mean = 0;
for (int k = 0; k<sizePatch; ++k) {
mean+=_X[sizePatch*j+k];
}
mean /= sizePatch;
for (int 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 int V = meanv.n();
const int sizePatch=_n/V;
for (int j = 0; j<V; ++j) {
T mean = 0;
for (int k = 0; k<sizePatch; ++k) {
mean+=_X[sizePatch*j+k];
}
mean /= cblas_asum(sizePatch,mask._X+j*sizePatch,1);
for (int 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 int V) {
const int sizePatch=_n/V;
for (int j = 0; j<V; ++j) {
T mean = 0;
for (int k = 0; k<sizePatch; ++k) {
mean+=_X[sizePatch*j+k];
}
mean /= sizePatch;
for (int 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();
// Y.print("Y");
// this->print("X");
// stop();
for (int 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 int n =static_cast<int>(sqrt(static_cast<T>(_n)));
int offsetx=0;
for (int j = 0; j<n; ++j) {
offsetx= (offsetx+1) % 2;
int offsety=0;
for (int k = 0; k<n; ++k) {
offsety= (offsety+1) % 2;
_X[j*n+k]+=meanv[2*offsetx+offsety];
}
}
} else {
const int V = meanv.n();
const int sizePatch=_n/V;
for (int j = 0; j<V; ++j) {
T mean = meanv[j];
for (int 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 (int 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 (int 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 logarithm
template <typename T> inline void Vector<T>::log() {
for (int 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 (int 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] ) );
}
}
};
/// 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 {
int count=0;
for (int 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 (int 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 (int i = 0; i<_n; ++i) sum +=_X[i];
return sum;
};
/// puts in signs, the sign of each point in the vector
template <typename T> inline void Vector<T>::sign(Vector<T>& signs) const {
T* prSign=signs.rawX();
for (int 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;
int sizeU = _n;
T sum = T();
int sum_card = 0;
while (sizeU > 0) {
// put the pivot in prU[0]
swap(prU[0],prU[sizeU/2]);
T pivot = prU[0];
int sizeG=1;
T sumG=pivot;
for (int 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<int> keys(_n);
for (int i = 0; i<_n; ++i) keys[i]=i;
out.sort2(keys,false);
T sum1=0;
T sum2=0;
T lambda=0;
for (int 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 (int 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 (int 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) {
int n_seuils=0;
for (int 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) {
int n_seuils=0;
for (int 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;
int sizeU = _n;
T sum = 0;
int sum_card = 0;
while (sizeU > 0) {
// put the pivot in prU[0]
swap(prU[0],prU[sizeU/2]);
T pivot = prU[0];
int sizeG=1;
T sumG=pivot+0.5*gamma*pivot*pivot;
for (int 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 int 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<int> ind(K+1);
Vector<bool> signs(K);
ind.set(K);
int* 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 (int 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;
int currentInd=this->fmax();
T currentLambda=abs<T>(pr_DtR[currentInd]);
bool newAtom = true;
/// Solve the Lasso using simplified LARS
for (int i = 1; i<K; ++i) {
/// exit if constraints 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) {
int j;
for (j = 1; j<i; ++j)
if (pr_ind[j] > currentInd) break;
for (int 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 (int 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 (int k = 1; k<pr_ind[1]; ++k)
pr_Du[k]=pr_Du[0];
for (int j = 1; j<=i; ++j) {
pr_Du[pr_ind[j]]=pr_Du[pr_ind[j]-1]+pr_u[j];
for (int 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 (int j = K-2; j>=0; --j)
pr_DDu[j] += pr_DDu[j+1];
/// Check constraints
T max_step1 = INFINITY;
if (penalty) {
max_step1 = currentLambda-lambda2;
}
/// Check changes of sign
T max_step2 = INFINITY;
int step_out = -1;
for (int 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 (int 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 (int 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 (int 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 (int k = step_out; k<=i; ++k)
pr_ind[k]=pr_ind[k+1];
pr_ind[i]=K;
for (int 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 int K = alpha.n();
T total_alpha =alpha.sum();
/// Modification of beta
for (int i = K-2; i>=0; --i)
pr_beta[i]+=pr_beta[i+1];
for (int 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 (int 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<int>& key, const bool mode) {
quick_sort(key.rawX(),_X,0,_n-1,mode);
};
template <typename T>
inline void Vector<T>::sort2(Vector<T>& out, Vector<int>& key, const bool mode) const {
out.copy(*this);
out.sort2(key,mode);
}
template <typename T>
inline void Vector<T>::applyBayerPattern(const int offset) {
int sizePatch=_n/3;
int n = static_cast<int>(sqrt(static_cast<T>(sizePatch)));
if (offset == 0) {
// R
for (int i = 0; i<n; ++i) {
const int step = (i % 2) ? 1 : 2;
const int off = (i % 2) ? 0 : 1;
for (int j = off; j<n; j+=step) {
_X[i*n+j]=0;
}
}
// G
for (int i = 0; i<n; ++i) {
const int step = 2;
const int off = (i % 2) ? 1 : 0;
for (int j = off; j<n; j+=step) {
_X[sizePatch+i*n+j]=0;
}
}
// B
for (int i = 0; i<n; ++i) {
const int step = (i % 2) ? 2 : 1;
const int off = 0;
for (int j = off; j<n; j+=step) {
_X[2*sizePatch+i*n+j]=0;
}
}
} else if (offset == 1) {
// R
for (int i = 0; i<n; ++i) {
const int step = (i % 2) ? 2 : 1;
const int off = (i % 2) ? 1 : 0;
for (int j = off; j<n; j+=step) {
_X[i*n+j]=0;
}
}
// G
for (int i = 0; i<n; ++i) {
const int step = 2;
const int off = (i % 2) ? 0 : 1;
for (int j = off; j<n; j+=step) {
_X[sizePatch+i*n+j]=0;
}
}
// B
for (int i = 0; i<n; ++i) {
const int step = (i % 2) ? 1 : 2;
const int off = 0;
for (int j = off; j<n; j+=step) {
_X[2*sizePatch+i*n+j]=0;
}
}
} else if (offset == 2) {
// R
for (int i = 0; i<n; ++i) {
const int step = (i % 2) ? 1 : 2;
const int off = 0;
for (int j = off; j<n; j+=step) {
_X[i*n+j]=0;
}
}
// G
for (int i = 0; i<n; ++i) {
const int step = 2;
const int off = (i % 2) ? 0 : 1;
for (int j = off; j<n; j+=step) {
_X[sizePatch+i*n+j]=0;
}
}
// B
for (int i = 0; i<n; ++i) {
const int step = (i % 2) ? 2 : 1;
const int off = (i % 2) ? 1 : 0;
for (int j = off; j<n; j+=step) {
_X[2*sizePatch+i*n+j]=0;
}
}
} else if (offset == 3) {
// R
for (int i = 0; i<n; ++i) {
const int step = (i % 2) ? 2 : 1;
const int off = 0;
for (int j = off; j<n; j+=step) {
_X[i*n+j]=0;
}
}
// G
for (int i = 0; i<n; ++i) {
const int step = 2;
const int off = (i % 2) ? 1 : 0;
for (int j = off; j<n; j+=step) {
_X[sizePatch+i*n+j]=0;
}
}
// B
for (int i = 0; i<n; ++i) {
const int step = (i % 2) ? 1 : 2;
const int off = (i % 2) ? 0 : 1;
for (int 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 {
int L=0;
T* v = vec._v;
int* r = vec._r;
for (int 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);
int pointer=0;
for (int 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);
int count=0;
for (int i = 0; i<mask.n(); ++i)
if (mask[i])
++count;
out.setm(count);
for (int i = 0; i<_n; ++i) {
int pointer=0;
for (int 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, int* r, int* pB, int* pE,
int m, int n, int 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(int m, int n, int nzmax) :
_externAlloc(false), _m(m), _n(n), _nzmax(nzmax) {
#pragma omp critical
{
_v=new T[nzmax];
_r=new int[nzmax];
_pB=new int[_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(int));
memcpy(_pB,mat._pB,(_n+1)*sizeof(int));
}
/// Destructor
template <typename T> SpMatrix<T>::~SpMatrix() {
clear();
};
/// reference the column i into vec
template <typename T> inline void SpMatrix<T>::refCol(int 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 (int i = 0; i<_n; ++i) {
for (int j = _pB[i]; j<_pE[i]; ++j) {
cerr << "(" <<_r[j] << "," << i << ") = " << _v[j] << endl;
}
}
};
template<typename T>
inline T SpMatrix<T>::operator[](const int index) const {
const int num_col=(index/_m);
const int num_row=index -num_col*_m;
T val = 0;
for (int 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 int index) const {
data.resize(_m);
data.setZeros();
for (int i = _pB[index]; i< _pB[index+1]; ++i)
data[_r[i]]=_v[i];
};
template<typename T>
void SpMatrix<T>::getGroup(Matrix<T>& data, const vector_groups& groups, const int i) const {
const group& gr = groups[i];
const int N = gr.size();
data.resize(_m,N);
int 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 int m,
const int n, const int 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 int[nzmax];
_pB = new int[_n+1];
}
_pE = _pB+1;
for (int 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 (int i = 0; i<_n; ++i) {
T sum=T();
for (int 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 (int 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 (int i = 0; i<_n; ++i) {
T sca=alpha* prX[i];
for (int 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 (int i = 0; i<x.L(); ++i) {
int ind=x.r(i);
T val = alpha * x.v(i);
for (int 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 (int 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 (int 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 (int 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 (int 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 (int 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 (int 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 (int 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 (int 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 (int i = 0; i<_n; ++i)
for (int 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 int ind, Vector<T>& x) const {
x.resize(_n);
x.setZeros();
for (int i = 0; i<_n; ++i) {
for (int 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 (int i = 0; i<_n; ++i)
for (int j = _pB[i]; j<_pE[i]; ++j)
_v[j] += pr_vec[_r[j]];
} else {
for (int i = 0; i<_n; ++i)
for (int 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 (int i = 0; i<_n; ++i)
for (int j = _pB[i]; j<_pE[i]; ++j)
_v[j] += pr_vec[_r[j]]*weights[j-_pB[i]];
} else {
for (int i = 0; i<_n; ++i)
for (int 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 (int 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 {
int i,j,k;
int K=_m;
int 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 (int 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<int>& indices) const {
int i,j,k;
int K=_m;
int 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) {
int 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 {
int i,j,k;
int K=_m;
int 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 {
int j,i;
int n=X._m;
int K=_m;
int 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<int>& indices) const {
int j,i;
int n=X._m;
int K=_m;
int 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) {
int 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 {
int j,l,i;
int n=X._m;
int K=_m;
int M=_n;
int Mx = X._n;
int 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) {
int 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 (int i=0; i<_n; ++i) {
for (int 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 (int i=0; i<_n; ++i) {
for (int 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<int>& rM, const int K) {
const int M = rM.n();
const int L = rM.m();
const int* r = rM.X();
const T* v = vM.X();
int count=0;
for (int i = 0; i<M*L; ++i) if (r[i] != -1) ++count;
resize(K,M,count);
count=0;
for (int i = 0; i<M; ++i) {
_pB[i]=count;
for (int 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 (int 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<int>& rv, const int K) {
const int M = vM.n();
const int L = vM.m();
int* r = rv.rawX();
const T* v = vM.X();
int LL=0;
for (int i = 0; i<L; ++i) if (r[i] != -1) ++LL;
this->resize(K,M,LL*M);
int count=0;
for (int i = 0; i<M; ++i) {
_pB[i]=count;
for (int j = 0; j<LL; ++j) {
_v[count]=v[i*L+j];
_r[count++]=r[j];
}
_pE[i]=count;
}
for (int 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 (int 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 (int 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 (int 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, int* r, int L, int nzmax) :
_externAlloc(true), _v(v), _r(r), _L(L), _nzmax(nzmax) { };
/// Constructor, allocates nzmax slots
template <typename T> SpVector<T>::SpVector(int nzmax) :
_externAlloc(false), _L(0), _nzmax(nzmax) {
#pragma omp critical
{
_v = new T[nzmax];
_r = new int[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 (int 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<int>& 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 T SpVector<T>::dot(const SpVector<T>& vec) const {
T sum=T();
int countI = 0;
int countJ = 0;
while (countI < _L && countJ < vec._L) {
const int rI = _r[countI];
const int rJ = vec._r[countJ];
if (rI > rJ) {
++countJ;
} else if (rJ > rI) {
++countI;
} else {
sum+=_v[countI]*vec._v[countJ];
++countI;
++countJ;
}
}
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 int nzmax) {
if (_nzmax != nzmax) {
clear();
_nzmax=nzmax;
_L=0;
_externAlloc=false;
#pragma omp critical
{
_v=new T[nzmax];
_r=new int[nzmax];
}
}
};
template <typename T> void inline SpVector<T>::toSpMatrix(
SpMatrix<T>& out, const int m, const int n) const {
out.resize(m,n,_L);
cblas_copy<T>(_L,_v,1,out._v,1);
int current_col=0;
T* out_v=out._v;
int* out_r=out._r;
int* out_pB=out._pB;
out_pB[0]=current_col;
for (int i = 0; i<_L; ++i) {
int 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 (int 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 int 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 int 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 int 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 int index) const {
if (_high_memory) {
return (*_DtX)[index];
} else {
const int index2=index/this->_m;
const int 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 int index1,
const int 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 (int 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<int>& indI, Vector<int>& indJ);
void inline convertIndicesI(Vector<int>& ind) const;
void inline convertIndicesJ(Vector<int>& ind) const;
int inline n() const { return _indicesJ.n(); };
int inline m() const { return _indicesI.n(); };
void inline extract_rawCol(const int i, T* pr) const;
/// compute DtX(:,i)
inline void copyCol(const int i, Vector<T>& DtXi) const;
/// compute DtX(:,i)
inline void add_rawCol(const int i, T* DtXi, const T a) const;
/// compute DtX(:,i)
inline void diag(Vector<T>& diag) const;
inline T operator()(const int index1, const int index2) const;
private:
Vector<int> _indicesI;
Vector<int> _indicesJ;
AbstractMatrix<T>* _matrix;
};
template <typename T>
SubMatrix<T>::SubMatrix(AbstractMatrix<T>& G, Vector<int>& indI, Vector<int>& indJ) {
_matrix = &G;
_indicesI.copy(indI);
_indicesJ.copy(indJ);
};
template <typename T> void inline SubMatrix<T>::convertIndicesI(
Vector<int>& ind) const {
int* pr_ind = ind.rawX();
for (int 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<int>& ind) const {
int* pr_ind = ind.rawX();
for (int 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 int i, T* pr) const {
int* pr_ind=_indicesI.rawX();
int* pr_ind2=_indicesJ.rawX();
for (int j = 0; j<_indicesI.n(); ++j) {
pr[j]=(*_matrix)(pr_ind[j],pr_ind2[i]);
}
};
template <typename T> inline void SubMatrix<T>::copyCol(const int i,
Vector<T>& DtXi) const {
this->extract_rawCol(i,DtXi.rawX());
};
template <typename T> void inline SubMatrix<T>::add_rawCol(const int i, T* pr,
const T a) const {
int* pr_ind=_indicesI.rawX();
int* pr_ind2=_indicesJ.rawX();
for (int 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();
int* pr_ind=_indicesI.rawX();
for (int j = 0; j<_indicesI.n(); ++j) {
pr[j]=(*_matrix)(pr_ind[j],pr_ind[j]);
}
};
template <typename T> inline T SubMatrix<T>::operator()(const int index1,
const int 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();
};
int n() const { return _n; };
int 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 int 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; };
int _m;
int _n;
int _shifts;
bool _centered;
Vector<T> _means;
const AbstractMatrixB<T>* _inputmatrix;
};
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 int 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 int nn=_inputmatrix->n();
const int 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 int nn=_inputmatrix->n();
const int 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 int ind, Vector<T>& x) const {
Vector<T> sub_vec;
const int 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();
};
int n() const { return _n; };
int 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 int 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:
int _m;
int _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 int mm = _inputmatrix->m();
Vector<T> tmp(mm);
for (int 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 int mm = _inputmatrix->m();
Vector<T> tmp(mm);
_inputmatrix->mult(x,tmp,alpha);
for (int 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 int mm = _inputmatrix->m();
Vector<T> tmp(mm);
_inputmatrix->mult(x,tmp,alpha);
for (int 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 int ind, Vector<T>& x) const {
const int indd2= static_cast<int>(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);
};
#endif

Event Timeline