2019-06-19 14:34:30 +02:00
|
|
|
|
/*
|
|
|
|
|
* Copyright © 2004-2011 Ondra Kamenik
|
|
|
|
|
* Copyright © 2019 Dynare Team
|
|
|
|
|
*
|
|
|
|
|
* This file is part of Dynare.
|
|
|
|
|
*
|
|
|
|
|
* Dynare 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.
|
|
|
|
|
*
|
|
|
|
|
* Dynare 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
|
2021-06-09 17:33:48 +02:00
|
|
|
|
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
|
2019-06-19 14:34:30 +02:00
|
|
|
|
*/
|
2009-09-08 15:55:19 +02:00
|
|
|
|
|
|
|
|
|
#ifndef GENERAL_MATRIX_H
|
|
|
|
|
#define GENERAL_MATRIX_H
|
|
|
|
|
|
2019-01-08 17:12:05 +01:00
|
|
|
|
#include "Vector.hh"
|
2019-01-24 15:22:36 +01:00
|
|
|
|
#include "SylvException.hh"
|
2009-09-08 15:55:19 +02:00
|
|
|
|
|
2015-03-25 14:45:09 +01:00
|
|
|
|
#include <algorithm>
|
Dynare++ / sylvester equation solver: refactor Vector and ConstVector classes
- these classes now encapsulate a std::shared_ptr<{const, }double>, so that
they do not perform memory management, and several {Const,}Vector instances
can transparently share the same underlying data
- make converting constructor from ConstVector to Vector explicit, since that
entails memory allocation (but the reverse conversion is almost costless, so
keep it implicit); do the same for GeneralMatrix/ConstGeneralMatrix,
TwoDMatrix/ConstTwoDMatrix
- remove the constructors that were extracting a row/column from a matrix, and
replace them by getRow() and getCol() methods on {Const,}GeneralMatrix
- rename and change the API of the complex version Vector::add(), so that it is
explicit that it deals with complex numbers
- add constructors that take a MATLAB mxArray
2019-01-22 16:07:44 +01:00
|
|
|
|
#include <memory>
|
|
|
|
|
#include <utility>
|
2019-01-25 15:27:20 +01:00
|
|
|
|
#include <string>
|
2015-03-25 14:45:09 +01:00
|
|
|
|
|
2019-02-26 14:40:21 +01:00
|
|
|
|
template<class T>
|
|
|
|
|
class TransposedMatrix
|
|
|
|
|
{
|
|
|
|
|
friend class GeneralMatrix;
|
2019-02-26 16:54:34 +01:00
|
|
|
|
template<class T2>
|
|
|
|
|
friend GeneralMatrix operator*(const ConstGeneralMatrix &a, const TransposedMatrix<T2> &b);
|
|
|
|
|
template<class T2>
|
|
|
|
|
friend GeneralMatrix operator*(const TransposedMatrix<T2> &a, const ConstGeneralMatrix &b);
|
|
|
|
|
template<class T1, class T2>
|
|
|
|
|
friend GeneralMatrix operator*(const TransposedMatrix<T1> &a, const TransposedMatrix<T2> &b);
|
2019-02-26 14:40:21 +01:00
|
|
|
|
private:
|
|
|
|
|
T &orig;
|
|
|
|
|
public:
|
2019-12-20 14:36:20 +01:00
|
|
|
|
TransposedMatrix(T &orig_arg) : orig{orig_arg}
|
|
|
|
|
{
|
|
|
|
|
};
|
2019-02-26 14:40:21 +01:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Syntactic sugar for representing a transposed matrix
|
|
|
|
|
template<class T>
|
|
|
|
|
TransposedMatrix<T>
|
|
|
|
|
transpose(T &m)
|
|
|
|
|
{
|
|
|
|
|
return TransposedMatrix<T>(m);
|
|
|
|
|
}
|
|
|
|
|
|
2009-09-08 15:55:19 +02:00
|
|
|
|
class GeneralMatrix;
|
|
|
|
|
|
2017-05-16 16:30:27 +02:00
|
|
|
|
class ConstGeneralMatrix
|
|
|
|
|
{
|
|
|
|
|
friend class GeneralMatrix;
|
2019-02-26 16:54:34 +01:00
|
|
|
|
friend GeneralMatrix operator*(const ConstGeneralMatrix &a, const ConstGeneralMatrix &b);
|
|
|
|
|
template<class T>
|
|
|
|
|
friend GeneralMatrix operator*(const ConstGeneralMatrix &a, const TransposedMatrix<T> &b);
|
|
|
|
|
template<class T>
|
|
|
|
|
friend GeneralMatrix operator*(const TransposedMatrix<T> &a, const ConstGeneralMatrix &b);
|
|
|
|
|
template<class T1, class T2>
|
|
|
|
|
friend GeneralMatrix operator*(const TransposedMatrix<T1> &a, const TransposedMatrix<T2> &b);
|
2009-09-08 15:55:19 +02:00
|
|
|
|
protected:
|
2019-01-24 15:22:36 +01:00
|
|
|
|
ConstVector data; // Has unit-stride
|
2017-05-16 16:30:27 +02:00
|
|
|
|
int rows;
|
|
|
|
|
int cols;
|
|
|
|
|
int ld;
|
2009-09-08 15:55:19 +02:00
|
|
|
|
public:
|
Dynare++ / sylvester equation solver: refactor Vector and ConstVector classes
- these classes now encapsulate a std::shared_ptr<{const, }double>, so that
they do not perform memory management, and several {Const,}Vector instances
can transparently share the same underlying data
- make converting constructor from ConstVector to Vector explicit, since that
entails memory allocation (but the reverse conversion is almost costless, so
keep it implicit); do the same for GeneralMatrix/ConstGeneralMatrix,
TwoDMatrix/ConstTwoDMatrix
- remove the constructors that were extracting a row/column from a matrix, and
replace them by getRow() and getCol() methods on {Const,}GeneralMatrix
- rename and change the API of the complex version Vector::add(), so that it is
explicit that it deals with complex numbers
- add constructors that take a MATLAB mxArray
2019-01-22 16:07:44 +01:00
|
|
|
|
ConstGeneralMatrix(ConstVector d, int m, int n)
|
|
|
|
|
: data(std::move(d)), rows(m), cols(n), ld(m)
|
2017-05-16 16:30:27 +02:00
|
|
|
|
{
|
2019-01-24 15:22:36 +01:00
|
|
|
|
if (data.skip() > 1)
|
|
|
|
|
throw SYLV_MES_EXCEPTION("Vector must have unit-stride");
|
|
|
|
|
if (data.length() < m*n)
|
|
|
|
|
throw SYLV_MES_EXCEPTION("Vector is too small");
|
2017-05-16 16:30:27 +02:00
|
|
|
|
}
|
2019-01-24 15:22:36 +01:00
|
|
|
|
ConstGeneralMatrix(const ConstGeneralMatrix &m) = default;
|
|
|
|
|
ConstGeneralMatrix(ConstGeneralMatrix &&m) = default;
|
2019-02-26 12:43:04 +01:00
|
|
|
|
// Implicit conversion from GeneralMatrix is ok, since it's cheap
|
2017-05-16 16:30:27 +02:00
|
|
|
|
ConstGeneralMatrix(const GeneralMatrix &m);
|
2019-02-26 12:43:04 +01:00
|
|
|
|
// Create submatrix (with data sharing)
|
2017-05-16 16:30:27 +02:00
|
|
|
|
ConstGeneralMatrix(const GeneralMatrix &m, int i, int j, int nrows, int ncols);
|
2019-02-26 12:43:04 +01:00
|
|
|
|
// Create submatrix (with data sharing)
|
2017-05-16 16:30:27 +02:00
|
|
|
|
ConstGeneralMatrix(const ConstGeneralMatrix &m, int i, int j, int nrows, int ncols);
|
2019-04-10 18:03:25 +02:00
|
|
|
|
#if defined(MATLAB_MEX_FILE) || defined(OCTAVE_MEX_FILE)
|
|
|
|
|
explicit ConstGeneralMatrix(const mxArray *p)
|
|
|
|
|
: data(p), rows{static_cast<int>(mxGetM(p))}, cols{static_cast<int>(mxGetN(p))}, ld{rows}
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
#endif
|
2019-01-15 18:55:09 +01:00
|
|
|
|
virtual ~ConstGeneralMatrix() = default;
|
2017-05-16 16:30:27 +02:00
|
|
|
|
|
2019-01-24 15:22:36 +01:00
|
|
|
|
ConstGeneralMatrix &operator=(const ConstGeneralMatrix &v) = delete;
|
|
|
|
|
ConstGeneralMatrix &operator=(ConstGeneralMatrix &&v) = delete;
|
|
|
|
|
|
2017-05-16 16:30:27 +02:00
|
|
|
|
const double &
|
|
|
|
|
get(int i, int j) const
|
|
|
|
|
{
|
|
|
|
|
return data[j*ld+i];
|
|
|
|
|
}
|
|
|
|
|
int
|
2019-04-16 12:40:50 +02:00
|
|
|
|
nrows() const
|
2017-05-16 16:30:27 +02:00
|
|
|
|
{
|
|
|
|
|
return rows;
|
|
|
|
|
}
|
|
|
|
|
int
|
2019-04-16 12:40:50 +02:00
|
|
|
|
ncols() const
|
2017-05-16 16:30:27 +02:00
|
|
|
|
{
|
|
|
|
|
return cols;
|
|
|
|
|
}
|
|
|
|
|
int
|
|
|
|
|
getLD() const
|
|
|
|
|
{
|
|
|
|
|
return ld;
|
|
|
|
|
}
|
|
|
|
|
const double *
|
|
|
|
|
base() const
|
|
|
|
|
{
|
|
|
|
|
return data.base();
|
|
|
|
|
}
|
|
|
|
|
const ConstVector &
|
|
|
|
|
getData() const
|
|
|
|
|
{
|
|
|
|
|
return data;
|
|
|
|
|
}
|
Dynare++ / sylvester equation solver: refactor Vector and ConstVector classes
- these classes now encapsulate a std::shared_ptr<{const, }double>, so that
they do not perform memory management, and several {Const,}Vector instances
can transparently share the same underlying data
- make converting constructor from ConstVector to Vector explicit, since that
entails memory allocation (but the reverse conversion is almost costless, so
keep it implicit); do the same for GeneralMatrix/ConstGeneralMatrix,
TwoDMatrix/ConstTwoDMatrix
- remove the constructors that were extracting a row/column from a matrix, and
replace them by getRow() and getCol() methods on {Const,}GeneralMatrix
- rename and change the API of the complex version Vector::add(), so that it is
explicit that it deals with complex numbers
- add constructors that take a MATLAB mxArray
2019-01-22 16:07:44 +01:00
|
|
|
|
ConstVector getRow(int row) const;
|
|
|
|
|
ConstVector getCol(int col) const;
|
2017-05-16 16:30:27 +02:00
|
|
|
|
|
|
|
|
|
double getNormInf() const;
|
|
|
|
|
double getNorm1() const;
|
|
|
|
|
/* x = scalar(a)*x + scalar(b)*this*d */
|
|
|
|
|
void multVec(double a, Vector &x, double b, const ConstVector &d) const;
|
|
|
|
|
/* x = scalar(a)*x + scalar(b)*this'*d */
|
|
|
|
|
void multVecTrans(double a, Vector &x, double b, const ConstVector &d) const;
|
|
|
|
|
/* x = x + this*d */
|
|
|
|
|
void
|
|
|
|
|
multaVec(Vector &x, const ConstVector &d) const
|
|
|
|
|
{
|
|
|
|
|
multVec(1.0, x, 1.0, d);
|
|
|
|
|
}
|
|
|
|
|
/* x = x + this'*d */
|
|
|
|
|
void
|
|
|
|
|
multaVecTrans(Vector &x, const ConstVector &d) const
|
|
|
|
|
{
|
|
|
|
|
multVecTrans(1.0, x, 1.0, d);
|
|
|
|
|
}
|
|
|
|
|
/* x = x - this*d */
|
|
|
|
|
void
|
|
|
|
|
multsVec(Vector &x, const ConstVector &d) const
|
|
|
|
|
{
|
|
|
|
|
multVec(1.0, x, -1.0, d);
|
|
|
|
|
}
|
|
|
|
|
/* x = x - this'*d */
|
|
|
|
|
void
|
|
|
|
|
multsVecTrans(Vector &x, const ConstVector &d) const
|
|
|
|
|
{
|
|
|
|
|
multVecTrans(1.0, x, -1.0, d);
|
|
|
|
|
}
|
|
|
|
|
/* m = inv(this)*m */
|
|
|
|
|
void multInvLeft(GeneralMatrix &m) const;
|
|
|
|
|
/* m = inv(this')*m */
|
|
|
|
|
void multInvLeftTrans(GeneralMatrix &m) const;
|
|
|
|
|
/* d = inv(this)*d */
|
|
|
|
|
void multInvLeft(Vector &d) const;
|
|
|
|
|
/* d = inv(this')*d */
|
|
|
|
|
void multInvLeftTrans(Vector &d) const;
|
|
|
|
|
|
|
|
|
|
bool isFinite() const;
|
|
|
|
|
/** Returns true of the matrix is exactly zero. */
|
|
|
|
|
bool isZero() const;
|
|
|
|
|
|
|
|
|
|
virtual void print() const;
|
2009-09-08 15:55:19 +02:00
|
|
|
|
protected:
|
2019-01-25 15:27:20 +01:00
|
|
|
|
void multInvLeft(const std::string &trans, int mrows, int mcols, int mld, double *d) const;
|
2009-09-08 15:55:19 +02:00
|
|
|
|
};
|
|
|
|
|
|
2017-05-16 16:30:27 +02:00
|
|
|
|
class GeneralMatrix
|
|
|
|
|
{
|
|
|
|
|
friend class ConstGeneralMatrix;
|
2019-02-26 16:54:34 +01:00
|
|
|
|
friend GeneralMatrix operator*(const ConstGeneralMatrix &a, const ConstGeneralMatrix &b);
|
|
|
|
|
template<class T>
|
|
|
|
|
friend GeneralMatrix operator*(const ConstGeneralMatrix &a, const TransposedMatrix<T> &b);
|
|
|
|
|
template<class T>
|
|
|
|
|
friend GeneralMatrix operator*(const TransposedMatrix<T> &a, const ConstGeneralMatrix &b);
|
|
|
|
|
template<class T1, class T2>
|
|
|
|
|
friend GeneralMatrix operator*(const TransposedMatrix<T1> &a, const TransposedMatrix<T2> &b);
|
2009-09-08 15:55:19 +02:00
|
|
|
|
protected:
|
2019-01-24 15:22:36 +01:00
|
|
|
|
Vector data; // Has unit-stride
|
2017-05-16 16:30:27 +02:00
|
|
|
|
int rows;
|
|
|
|
|
int cols;
|
|
|
|
|
int ld;
|
2009-09-08 15:55:19 +02:00
|
|
|
|
public:
|
2017-05-16 16:30:27 +02:00
|
|
|
|
GeneralMatrix(int m, int n)
|
|
|
|
|
: data(m*n), rows(m), cols(n), ld(m)
|
|
|
|
|
{
|
|
|
|
|
}
|
2019-01-24 15:22:36 +01:00
|
|
|
|
GeneralMatrix(Vector d, int m, int n)
|
|
|
|
|
: data(std::move(d)), rows(m), cols(n), ld(m)
|
2017-05-16 16:30:27 +02:00
|
|
|
|
{
|
2019-01-24 15:22:36 +01:00
|
|
|
|
if (data.skip() > 1)
|
|
|
|
|
throw SYLV_MES_EXCEPTION("Vector must have unit-stride");
|
|
|
|
|
if (data.length() < m*n)
|
|
|
|
|
throw SYLV_MES_EXCEPTION("Vector is too small");
|
2017-05-16 16:30:27 +02:00
|
|
|
|
}
|
2019-01-24 15:22:36 +01:00
|
|
|
|
|
|
|
|
|
/* The copies will have ld==rows, for memory efficiency (hence we do not use
|
|
|
|
|
the default copy constructor) */
|
2017-05-16 16:30:27 +02:00
|
|
|
|
GeneralMatrix(const GeneralMatrix &m);
|
Dynare++ / sylvester equation solver: refactor Vector and ConstVector classes
- these classes now encapsulate a std::shared_ptr<{const, }double>, so that
they do not perform memory management, and several {Const,}Vector instances
can transparently share the same underlying data
- make converting constructor from ConstVector to Vector explicit, since that
entails memory allocation (but the reverse conversion is almost costless, so
keep it implicit); do the same for GeneralMatrix/ConstGeneralMatrix,
TwoDMatrix/ConstTwoDMatrix
- remove the constructors that were extracting a row/column from a matrix, and
replace them by getRow() and getCol() methods on {Const,}GeneralMatrix
- rename and change the API of the complex version Vector::add(), so that it is
explicit that it deals with complex numbers
- add constructors that take a MATLAB mxArray
2019-01-22 16:07:44 +01:00
|
|
|
|
// We don't want implict conversion from ConstGeneralMatrix, since it's expensive
|
|
|
|
|
explicit GeneralMatrix(const ConstGeneralMatrix &m);
|
2019-01-24 15:22:36 +01:00
|
|
|
|
|
|
|
|
|
GeneralMatrix(GeneralMatrix &&m) = default;
|
2019-02-26 14:40:21 +01:00
|
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
|
explicit GeneralMatrix(const TransposedMatrix<T> &m)
|
|
|
|
|
: data(m.orig.rows*m.orig.cols), rows(m.orig.cols), cols(m.orig.rows), ld(rows)
|
|
|
|
|
{
|
|
|
|
|
for (int i = 0; i < rows; i++)
|
|
|
|
|
for (int j = 0; j < cols; j++)
|
|
|
|
|
get(i, j) = m.orig.get(j, i);
|
|
|
|
|
}
|
|
|
|
|
|
2019-02-26 12:43:04 +01:00
|
|
|
|
// Create submatrix (with data copy)
|
2017-05-16 16:30:27 +02:00
|
|
|
|
GeneralMatrix(const GeneralMatrix &m, int i, int j, int nrows, int ncols);
|
2019-02-26 12:43:04 +01:00
|
|
|
|
// Create submatrix (with data sharing)
|
2017-05-16 16:30:27 +02:00
|
|
|
|
GeneralMatrix(GeneralMatrix &m, int i, int j, int nrows, int ncols);
|
|
|
|
|
|
2019-04-10 18:03:25 +02:00
|
|
|
|
#if defined(MATLAB_MEX_FILE) || defined(OCTAVE_MEX_FILE)
|
|
|
|
|
explicit GeneralMatrix(mxArray *p)
|
|
|
|
|
: data(p), rows{static_cast<int>(mxGetM(p))}, cols{static_cast<int>(mxGetN(p))}, ld{rows}
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2019-01-16 17:52:16 +01:00
|
|
|
|
virtual ~GeneralMatrix() = default;
|
2019-01-15 18:55:09 +01:00
|
|
|
|
GeneralMatrix &operator=(const GeneralMatrix &m) = default;
|
2019-01-24 15:22:36 +01:00
|
|
|
|
GeneralMatrix &operator=(GeneralMatrix &&m) = default;
|
|
|
|
|
GeneralMatrix &operator=(const ConstGeneralMatrix &m);
|
2017-05-16 16:30:27 +02:00
|
|
|
|
|
|
|
|
|
const double &
|
|
|
|
|
get(int i, int j) const
|
|
|
|
|
{
|
|
|
|
|
return data[j*ld+i];
|
|
|
|
|
}
|
|
|
|
|
double &
|
|
|
|
|
get(int i, int j)
|
|
|
|
|
{
|
|
|
|
|
return data[j*ld+i];
|
|
|
|
|
}
|
|
|
|
|
int
|
2019-04-16 12:40:50 +02:00
|
|
|
|
nrows() const
|
2017-05-16 16:30:27 +02:00
|
|
|
|
{
|
|
|
|
|
return rows;
|
|
|
|
|
}
|
|
|
|
|
int
|
2019-04-16 12:40:50 +02:00
|
|
|
|
ncols() const
|
2017-05-16 16:30:27 +02:00
|
|
|
|
{
|
|
|
|
|
return cols;
|
|
|
|
|
}
|
|
|
|
|
int
|
|
|
|
|
getLD() const
|
|
|
|
|
{
|
|
|
|
|
return ld;
|
|
|
|
|
}
|
|
|
|
|
double *
|
|
|
|
|
base()
|
|
|
|
|
{
|
|
|
|
|
return data.base();
|
|
|
|
|
}
|
|
|
|
|
const double *
|
|
|
|
|
base() const
|
|
|
|
|
{
|
|
|
|
|
return data.base();
|
|
|
|
|
}
|
|
|
|
|
Vector &
|
|
|
|
|
getData()
|
|
|
|
|
{
|
|
|
|
|
return data;
|
|
|
|
|
}
|
2019-01-24 15:22:36 +01:00
|
|
|
|
ConstVector
|
2017-05-16 16:30:27 +02:00
|
|
|
|
getData() const
|
|
|
|
|
{
|
|
|
|
|
return data;
|
|
|
|
|
}
|
Dynare++ / sylvester equation solver: refactor Vector and ConstVector classes
- these classes now encapsulate a std::shared_ptr<{const, }double>, so that
they do not perform memory management, and several {Const,}Vector instances
can transparently share the same underlying data
- make converting constructor from ConstVector to Vector explicit, since that
entails memory allocation (but the reverse conversion is almost costless, so
keep it implicit); do the same for GeneralMatrix/ConstGeneralMatrix,
TwoDMatrix/ConstTwoDMatrix
- remove the constructors that were extracting a row/column from a matrix, and
replace them by getRow() and getCol() methods on {Const,}GeneralMatrix
- rename and change the API of the complex version Vector::add(), so that it is
explicit that it deals with complex numbers
- add constructors that take a MATLAB mxArray
2019-01-22 16:07:44 +01:00
|
|
|
|
Vector getRow(int row);
|
|
|
|
|
Vector getCol(int col);
|
|
|
|
|
ConstVector getRow(int row) const;
|
|
|
|
|
ConstVector getCol(int col) const;
|
2017-05-16 16:30:27 +02:00
|
|
|
|
|
|
|
|
|
double
|
|
|
|
|
getNormInf() const
|
|
|
|
|
{
|
|
|
|
|
return ConstGeneralMatrix(*this).getNormInf();
|
|
|
|
|
}
|
|
|
|
|
double
|
|
|
|
|
getNorm1() const
|
|
|
|
|
{
|
|
|
|
|
return ConstGeneralMatrix(*this).getNorm1();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* place matrix m to the position (i,j) */
|
|
|
|
|
void place(const ConstGeneralMatrix &m, int i, int j);
|
|
|
|
|
void
|
|
|
|
|
place(const GeneralMatrix &m, int i, int j)
|
|
|
|
|
{
|
|
|
|
|
place(ConstGeneralMatrix(m), i, j);
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-27 19:22:35 +01:00
|
|
|
|
// this = a·b
|
2017-05-16 16:30:27 +02:00
|
|
|
|
void mult(const ConstGeneralMatrix &a, const ConstGeneralMatrix &b);
|
|
|
|
|
void
|
|
|
|
|
mult(const GeneralMatrix &a, const GeneralMatrix &b)
|
|
|
|
|
{
|
|
|
|
|
mult(ConstGeneralMatrix(a), ConstGeneralMatrix(b));
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-27 19:22:35 +01:00
|
|
|
|
// this = this + scalar·a·b
|
2017-05-16 16:30:27 +02:00
|
|
|
|
void multAndAdd(const ConstGeneralMatrix &a, const ConstGeneralMatrix &b,
|
|
|
|
|
double mult = 1.0);
|
|
|
|
|
void
|
|
|
|
|
multAndAdd(const GeneralMatrix &a, const GeneralMatrix &b,
|
|
|
|
|
double mult = 1.0)
|
|
|
|
|
{
|
|
|
|
|
multAndAdd(ConstGeneralMatrix(a), ConstGeneralMatrix(b), mult);
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-27 19:22:35 +01:00
|
|
|
|
// this = this + scalar·a·bᵀ
|
2017-05-16 16:30:27 +02:00
|
|
|
|
void multAndAdd(const ConstGeneralMatrix &a, const ConstGeneralMatrix &b,
|
2019-01-25 15:27:20 +01:00
|
|
|
|
const std::string &dum, double mult = 1.0);
|
2017-05-16 16:30:27 +02:00
|
|
|
|
void
|
|
|
|
|
multAndAdd(const GeneralMatrix &a, const GeneralMatrix &b,
|
2019-01-25 15:27:20 +01:00
|
|
|
|
const std::string &dum, double mult = 1.0)
|
2017-05-16 16:30:27 +02:00
|
|
|
|
{
|
|
|
|
|
multAndAdd(ConstGeneralMatrix(a), ConstGeneralMatrix(b), dum, mult);
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-27 19:22:35 +01:00
|
|
|
|
// this = this + scalar·aᵀ·b
|
2019-01-25 15:27:20 +01:00
|
|
|
|
void multAndAdd(const ConstGeneralMatrix &a, const std::string &dum, const ConstGeneralMatrix &b,
|
2017-05-16 16:30:27 +02:00
|
|
|
|
double mult = 1.0);
|
|
|
|
|
void
|
2019-01-25 15:27:20 +01:00
|
|
|
|
multAndAdd(const GeneralMatrix &a, const std::string &dum, const GeneralMatrix &b,
|
2017-05-16 16:30:27 +02:00
|
|
|
|
double mult = 1.0)
|
|
|
|
|
{
|
|
|
|
|
multAndAdd(ConstGeneralMatrix(a), dum, ConstGeneralMatrix(b), mult);
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-27 19:22:35 +01:00
|
|
|
|
// this = this + scalar·aᵀ·bᵀ
|
2019-01-25 15:27:20 +01:00
|
|
|
|
void multAndAdd(const ConstGeneralMatrix &a, const std::string &dum1,
|
|
|
|
|
const ConstGeneralMatrix &b, const std::string &dum2, double mult = 1.0);
|
2017-05-16 16:30:27 +02:00
|
|
|
|
void
|
2019-01-25 15:27:20 +01:00
|
|
|
|
multAndAdd(const GeneralMatrix &a, const std::string &dum1,
|
|
|
|
|
const GeneralMatrix &b, const std::string &dum2, double mult = 1.0)
|
2017-05-16 16:30:27 +02:00
|
|
|
|
{
|
|
|
|
|
multAndAdd(ConstGeneralMatrix(a), dum1, ConstGeneralMatrix(b), dum2, mult);
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-27 19:22:35 +01:00
|
|
|
|
// this = this + scalar·a·aᵀ
|
2017-05-16 16:30:27 +02:00
|
|
|
|
void addOuter(const ConstVector &a, double mult = 1.0);
|
|
|
|
|
void
|
|
|
|
|
addOuter(const Vector &a, double mult = 1.0)
|
|
|
|
|
{
|
|
|
|
|
addOuter(ConstVector(a), mult);
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-27 19:22:35 +01:00
|
|
|
|
// this = this·m
|
2017-05-16 16:30:27 +02:00
|
|
|
|
void multRight(const ConstGeneralMatrix &m);
|
|
|
|
|
void
|
|
|
|
|
multRight(const GeneralMatrix &m)
|
|
|
|
|
{
|
|
|
|
|
multRight(ConstGeneralMatrix(m));
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-27 19:22:35 +01:00
|
|
|
|
// this = m·this
|
2017-05-16 16:30:27 +02:00
|
|
|
|
void multLeft(const ConstGeneralMatrix &m);
|
|
|
|
|
void
|
|
|
|
|
multLeft(const GeneralMatrix &m)
|
|
|
|
|
{
|
|
|
|
|
multLeft(ConstGeneralMatrix(m));
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-27 19:22:35 +01:00
|
|
|
|
// this = this·mᵀ
|
2017-05-16 16:30:27 +02:00
|
|
|
|
void multRightTrans(const ConstGeneralMatrix &m);
|
|
|
|
|
void
|
|
|
|
|
multRightTrans(const GeneralMatrix &m)
|
|
|
|
|
{
|
|
|
|
|
multRightTrans(ConstGeneralMatrix(m));
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-27 19:22:35 +01:00
|
|
|
|
// this = mᵀ·this
|
2017-05-16 16:30:27 +02:00
|
|
|
|
void multLeftTrans(const ConstGeneralMatrix &m);
|
|
|
|
|
void
|
|
|
|
|
multLeftTrans(const GeneralMatrix &m)
|
|
|
|
|
{
|
|
|
|
|
multLeftTrans(ConstGeneralMatrix(m));
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-27 19:22:35 +01:00
|
|
|
|
// x = scalar(a)·x + scalar(b)·this·d
|
2017-05-16 16:30:27 +02:00
|
|
|
|
void
|
|
|
|
|
multVec(double a, Vector &x, double b, const ConstVector &d) const
|
|
|
|
|
{
|
|
|
|
|
ConstGeneralMatrix(*this).multVec(a, x, b, d);
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-27 19:22:35 +01:00
|
|
|
|
// x = scalar(a)·x + scalar(b)·thisᵀ·d
|
2017-05-16 16:30:27 +02:00
|
|
|
|
void
|
|
|
|
|
multVecTrans(double a, Vector &x, double b, const ConstVector &d) const
|
|
|
|
|
{
|
|
|
|
|
ConstGeneralMatrix(*this).multVecTrans(a, x, b, d);
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-27 19:22:35 +01:00
|
|
|
|
// x = x + this·d
|
2017-05-16 16:30:27 +02:00
|
|
|
|
void
|
|
|
|
|
multaVec(Vector &x, const ConstVector &d) const
|
|
|
|
|
{
|
|
|
|
|
ConstGeneralMatrix(*this).multaVec(x, d);
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-27 19:22:35 +01:00
|
|
|
|
// x = x + thisᵀ·d */
|
2017-05-16 16:30:27 +02:00
|
|
|
|
void
|
|
|
|
|
multaVecTrans(Vector &x, const ConstVector &d) const
|
|
|
|
|
{
|
|
|
|
|
ConstGeneralMatrix(*this).multaVecTrans(x, d);
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-27 19:22:35 +01:00
|
|
|
|
// x = x - this·d
|
2017-05-16 16:30:27 +02:00
|
|
|
|
void
|
|
|
|
|
multsVec(Vector &x, const ConstVector &d) const
|
|
|
|
|
{
|
|
|
|
|
ConstGeneralMatrix(*this).multsVec(x, d);
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-27 19:22:35 +01:00
|
|
|
|
// x = x - thisᵀ·d
|
2017-05-16 16:30:27 +02:00
|
|
|
|
void
|
|
|
|
|
multsVecTrans(Vector &x, const ConstVector &d) const
|
|
|
|
|
{
|
|
|
|
|
ConstGeneralMatrix(*this).multsVecTrans(x, d);
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-27 19:22:35 +01:00
|
|
|
|
// this = zero
|
2017-05-16 16:30:27 +02:00
|
|
|
|
void zeros();
|
|
|
|
|
|
2019-03-27 19:22:35 +01:00
|
|
|
|
// this = unit (on main diagonal)
|
2017-05-16 16:30:27 +02:00
|
|
|
|
void unit();
|
|
|
|
|
|
2019-03-27 19:22:35 +01:00
|
|
|
|
// this = NaN
|
2017-05-16 16:30:27 +02:00
|
|
|
|
void nans();
|
|
|
|
|
|
2019-03-27 19:22:35 +01:00
|
|
|
|
// this = ∞
|
2017-05-16 16:30:27 +02:00
|
|
|
|
void infs();
|
|
|
|
|
|
2019-03-27 19:22:35 +01:00
|
|
|
|
// this = scalar·this
|
2017-05-16 16:30:27 +02:00
|
|
|
|
void mult(double a);
|
|
|
|
|
|
2019-03-27 19:22:35 +01:00
|
|
|
|
// this = this + scalar·m
|
2017-05-16 16:30:27 +02:00
|
|
|
|
void add(double a, const ConstGeneralMatrix &m);
|
|
|
|
|
void
|
|
|
|
|
add(double a, const GeneralMatrix &m)
|
|
|
|
|
{
|
|
|
|
|
add(a, ConstGeneralMatrix(m));
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-27 19:22:35 +01:00
|
|
|
|
// this = this + scalar·mᵀ
|
2019-01-25 15:27:20 +01:00
|
|
|
|
void add(double a, const ConstGeneralMatrix &m, const std::string &dum);
|
2017-05-16 16:30:27 +02:00
|
|
|
|
void
|
2019-01-25 15:27:20 +01:00
|
|
|
|
add(double a, const GeneralMatrix &m, const std::string &dum)
|
2017-05-16 16:30:27 +02:00
|
|
|
|
{
|
|
|
|
|
add(a, ConstGeneralMatrix(m), dum);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
isFinite() const
|
|
|
|
|
{
|
|
|
|
|
return (ConstGeneralMatrix(*this)).isFinite();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
isZero() const
|
|
|
|
|
{
|
|
|
|
|
return (ConstGeneralMatrix(*this)).isZero();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual void
|
|
|
|
|
print() const
|
|
|
|
|
{
|
|
|
|
|
ConstGeneralMatrix(*this).print();
|
|
|
|
|
}
|
2009-09-08 15:55:19 +02:00
|
|
|
|
private:
|
2017-05-16 16:30:27 +02:00
|
|
|
|
void copy(const ConstGeneralMatrix &m, int ioff = 0, int joff = 0);
|
|
|
|
|
void
|
|
|
|
|
copy(const GeneralMatrix &m, int ioff = 0, int joff = 0)
|
|
|
|
|
{
|
|
|
|
|
copy(ConstGeneralMatrix(m), ioff, joff);
|
|
|
|
|
}
|
|
|
|
|
|
2019-01-25 15:27:20 +01:00
|
|
|
|
void gemm(const std::string &transa, const ConstGeneralMatrix &a,
|
|
|
|
|
const std::string &transb, const ConstGeneralMatrix &b,
|
2017-05-16 16:30:27 +02:00
|
|
|
|
double alpha, double beta);
|
|
|
|
|
void
|
2019-01-25 15:27:20 +01:00
|
|
|
|
gemm(const std::string &transa, const GeneralMatrix &a,
|
|
|
|
|
const std::string &transb, const GeneralMatrix &b,
|
2017-05-16 16:30:27 +02:00
|
|
|
|
double alpha, double beta)
|
|
|
|
|
{
|
|
|
|
|
gemm(transa, ConstGeneralMatrix(a), transb, ConstGeneralMatrix(b),
|
|
|
|
|
alpha, beta);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* this = this * op(m) (without whole copy of this) */
|
2019-01-25 15:27:20 +01:00
|
|
|
|
void gemm_partial_right(const std::string &trans, const ConstGeneralMatrix &m,
|
2017-05-16 16:30:27 +02:00
|
|
|
|
double alpha, double beta);
|
|
|
|
|
void
|
2019-01-25 15:27:20 +01:00
|
|
|
|
gemm_partial_right(const std::string &trans, const GeneralMatrix &m,
|
2017-05-16 16:30:27 +02:00
|
|
|
|
double alpha, double beta)
|
|
|
|
|
{
|
|
|
|
|
gemm_partial_right(trans, ConstGeneralMatrix(m), alpha, beta);
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-27 19:22:35 +01:00
|
|
|
|
// this = op(m)·this (without whole copy of ‘this’)
|
2019-01-25 15:27:20 +01:00
|
|
|
|
void gemm_partial_left(const std::string &trans, const ConstGeneralMatrix &m,
|
2017-05-16 16:30:27 +02:00
|
|
|
|
double alpha, double beta);
|
|
|
|
|
void
|
2019-01-25 15:27:20 +01:00
|
|
|
|
gemm_partial_left(const std::string &trans, const GeneralMatrix &m,
|
2017-05-16 16:30:27 +02:00
|
|
|
|
double alpha, double beta)
|
|
|
|
|
{
|
|
|
|
|
gemm_partial_left(trans, ConstGeneralMatrix(m), alpha, beta);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* number of rows/columns for copy used in gemm_partial_* */
|
Dynare++ / sylvester equation solver: refactor Vector and ConstVector classes
- these classes now encapsulate a std::shared_ptr<{const, }double>, so that
they do not perform memory management, and several {Const,}Vector instances
can transparently share the same underlying data
- make converting constructor from ConstVector to Vector explicit, since that
entails memory allocation (but the reverse conversion is almost costless, so
keep it implicit); do the same for GeneralMatrix/ConstGeneralMatrix,
TwoDMatrix/ConstTwoDMatrix
- remove the constructors that were extracting a row/column from a matrix, and
replace them by getRow() and getCol() methods on {Const,}GeneralMatrix
- rename and change the API of the complex version Vector::add(), so that it is
explicit that it deals with complex numbers
- add constructors that take a MATLAB mxArray
2019-01-22 16:07:44 +01:00
|
|
|
|
static constexpr int md_length = 23;
|
2009-09-08 15:55:19 +02:00
|
|
|
|
};
|
|
|
|
|
|
2019-03-27 19:22:35 +01:00
|
|
|
|
// Computes a·b
|
2019-02-26 16:54:34 +01:00
|
|
|
|
inline GeneralMatrix
|
|
|
|
|
operator*(const ConstGeneralMatrix &a, const ConstGeneralMatrix &b)
|
|
|
|
|
{
|
|
|
|
|
GeneralMatrix m(a.rows, b.cols);
|
|
|
|
|
m.gemm("N", a, "N", b, 1.0, 0.0);
|
|
|
|
|
return m;
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-27 19:22:35 +01:00
|
|
|
|
// Computes a·bᵀ
|
2019-02-26 16:54:34 +01:00
|
|
|
|
template<class T>
|
|
|
|
|
GeneralMatrix
|
|
|
|
|
operator*(const ConstGeneralMatrix &a, const TransposedMatrix<T> &b)
|
|
|
|
|
{
|
|
|
|
|
GeneralMatrix m(a.rows, b.orig.rows);
|
|
|
|
|
m.gemm("N", a, "T", b.orig, 1.0, 0.0);
|
|
|
|
|
return m;
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-27 19:22:35 +01:00
|
|
|
|
// Computes aᵀ·b
|
2019-02-26 16:54:34 +01:00
|
|
|
|
template<class T>
|
|
|
|
|
GeneralMatrix
|
|
|
|
|
operator*(const TransposedMatrix<T> &a, const ConstGeneralMatrix &b)
|
|
|
|
|
{
|
|
|
|
|
GeneralMatrix m(a.orig.cols, b.cols);
|
|
|
|
|
m.gemm("T", a.orig, "N", b, 1.0, 0.0);
|
|
|
|
|
return m;
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-27 19:22:35 +01:00
|
|
|
|
// Computes aᵀ·bᵀ
|
2019-02-26 16:54:34 +01:00
|
|
|
|
template<class T1, class T2>
|
|
|
|
|
GeneralMatrix
|
|
|
|
|
operator*(const TransposedMatrix<T1> &a, const TransposedMatrix<T2> &b)
|
|
|
|
|
{
|
|
|
|
|
GeneralMatrix m(a.orig.cols, b.orig.rows);
|
|
|
|
|
m.gemm("T", a.orig, "T", b.orig, 1.0, 0.0);
|
|
|
|
|
return m;
|
|
|
|
|
}
|
|
|
|
|
|
2017-05-16 16:30:27 +02:00
|
|
|
|
class SVDDecomp
|
|
|
|
|
{
|
2015-03-25 14:45:09 +01:00
|
|
|
|
protected:
|
2019-03-27 19:22:35 +01:00
|
|
|
|
// Minimum of number of rows and columns of the decomposed matrix
|
2017-05-16 16:30:27 +02:00
|
|
|
|
const int minmn;
|
2019-03-27 19:22:35 +01:00
|
|
|
|
// Singular values
|
2017-05-16 16:30:27 +02:00
|
|
|
|
Vector sigma;
|
2019-03-27 19:22:35 +01:00
|
|
|
|
// Orthogonal matrix U
|
2017-05-16 16:30:27 +02:00
|
|
|
|
GeneralMatrix U;
|
2019-03-27 19:22:35 +01:00
|
|
|
|
// Orthogonal matrix Vᵀ
|
2017-05-16 16:30:27 +02:00
|
|
|
|
GeneralMatrix VT;
|
2019-03-27 19:22:35 +01:00
|
|
|
|
// Convered flag
|
2017-05-16 16:30:27 +02:00
|
|
|
|
bool conv;
|
2015-03-25 14:45:09 +01:00
|
|
|
|
public:
|
2017-05-16 16:30:27 +02:00
|
|
|
|
SVDDecomp(const GeneralMatrix &A)
|
2019-04-16 12:40:50 +02:00
|
|
|
|
: minmn(std::min<int>(A.nrows(), A.ncols())),
|
2017-05-16 16:30:27 +02:00
|
|
|
|
sigma(minmn),
|
2019-04-16 12:40:50 +02:00
|
|
|
|
U(A.nrows(), A.nrows()),
|
|
|
|
|
VT(A.ncols(), A.ncols()),
|
2017-05-16 16:30:27 +02:00
|
|
|
|
conv(false)
|
|
|
|
|
{
|
|
|
|
|
construct(A);
|
|
|
|
|
}
|
|
|
|
|
const GeneralMatrix &
|
|
|
|
|
getU() const
|
|
|
|
|
{
|
|
|
|
|
return U;
|
|
|
|
|
}
|
|
|
|
|
const GeneralMatrix &
|
|
|
|
|
getVT() const
|
|
|
|
|
{
|
|
|
|
|
return VT;
|
|
|
|
|
}
|
2019-01-24 15:22:36 +01:00
|
|
|
|
void solve(const ConstGeneralMatrix &B, GeneralMatrix &X) const;
|
2017-05-16 16:30:27 +02:00
|
|
|
|
void
|
2019-01-24 15:22:36 +01:00
|
|
|
|
solve(const ConstVector &b, Vector &x) const
|
2017-05-16 16:30:27 +02:00
|
|
|
|
{
|
Dynare++ / sylvester equation solver: refactor Vector and ConstVector classes
- these classes now encapsulate a std::shared_ptr<{const, }double>, so that
they do not perform memory management, and several {Const,}Vector instances
can transparently share the same underlying data
- make converting constructor from ConstVector to Vector explicit, since that
entails memory allocation (but the reverse conversion is almost costless, so
keep it implicit); do the same for GeneralMatrix/ConstGeneralMatrix,
TwoDMatrix/ConstTwoDMatrix
- remove the constructors that were extracting a row/column from a matrix, and
replace them by getRow() and getCol() methods on {Const,}GeneralMatrix
- rename and change the API of the complex version Vector::add(), so that it is
explicit that it deals with complex numbers
- add constructors that take a MATLAB mxArray
2019-01-22 16:07:44 +01:00
|
|
|
|
GeneralMatrix xmat(x, x.length(), 1);
|
2019-01-24 15:22:36 +01:00
|
|
|
|
solve(ConstGeneralMatrix(b, b.length(), 1), xmat);
|
2017-05-16 16:30:27 +02:00
|
|
|
|
}
|
2015-03-25 14:45:09 +01:00
|
|
|
|
private:
|
2017-05-16 16:30:27 +02:00
|
|
|
|
void construct(const GeneralMatrix &A);
|
2015-03-25 14:45:09 +01:00
|
|
|
|
};
|
2009-09-08 15:55:19 +02:00
|
|
|
|
|
|
|
|
|
#endif /* GENERAL_MATRIX_H */
|