Dynare++ sylvester equation solver: various simplifications and improvements
In particular, the test binary now errors out in case of test failure.time-shift
parent
d15c998804
commit
3ce051d819
|
@ -5,12 +5,11 @@
|
|||
#include "BlockDiagonal.hh"
|
||||
|
||||
#include <iostream>
|
||||
#include <cstring>
|
||||
#include <utility>
|
||||
|
||||
BlockDiagonal::BlockDiagonal(ConstVector d, int d_size)
|
||||
: QuasiTriangular(std::move(d), d_size),
|
||||
row_len(new int[d_size]), col_len(new int[d_size])
|
||||
row_len(d_size), col_len(d_size)
|
||||
{
|
||||
for (int i = 0; i < d_size; i++)
|
||||
{
|
||||
|
@ -21,7 +20,7 @@ BlockDiagonal::BlockDiagonal(ConstVector d, int d_size)
|
|||
|
||||
BlockDiagonal::BlockDiagonal(const QuasiTriangular &t)
|
||||
: QuasiTriangular(t),
|
||||
row_len(new int[t.numRows()]), col_len(new int[t.numRows()])
|
||||
row_len(t.numRows()), col_len(t.numRows())
|
||||
{
|
||||
for (int i = 0; i < t.numRows(); i++)
|
||||
{
|
||||
|
@ -32,18 +31,8 @@ BlockDiagonal::BlockDiagonal(const QuasiTriangular &t)
|
|||
|
||||
BlockDiagonal::BlockDiagonal(int p, const BlockDiagonal &b)
|
||||
: QuasiTriangular(p, b),
|
||||
row_len(new int[b.numRows()]), col_len(new int[b.numRows()])
|
||||
row_len(b.row_len), col_len(b.col_len)
|
||||
{
|
||||
memcpy(row_len, b.row_len, b.numRows()*sizeof(int));
|
||||
memcpy(col_len, b.col_len, b.numRows()*sizeof(int));
|
||||
}
|
||||
|
||||
BlockDiagonal::BlockDiagonal(const BlockDiagonal &b)
|
||||
: QuasiTriangular(b),
|
||||
row_len(new int[b.numRows()]), col_len(new int[b.numRows()])
|
||||
{
|
||||
memcpy(row_len, b.row_len, b.numRows()*sizeof(int));
|
||||
memcpy(col_len, b.col_len, b.numRows()*sizeof(int));
|
||||
}
|
||||
|
||||
/* put zeroes to right upper submatrix whose first column is defined
|
||||
|
@ -135,9 +124,7 @@ BlockDiagonal::getNumZeros() const
|
|||
{
|
||||
int sum = 0;
|
||||
for (int i = 0; i < diagonal.getSize(); i++)
|
||||
{
|
||||
sum += diagonal.getSize() - row_len[i];
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
|
|
|
@ -6,28 +6,25 @@
|
|||
#define BLOCK_DIAGONAL_H
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "QuasiTriangular.hh"
|
||||
|
||||
class BlockDiagonal : public QuasiTriangular
|
||||
{
|
||||
int *const row_len;
|
||||
int *const col_len;
|
||||
std::vector<int> row_len, col_len;
|
||||
public:
|
||||
BlockDiagonal(ConstVector d, int d_size);
|
||||
BlockDiagonal(int p, const BlockDiagonal &b);
|
||||
BlockDiagonal(const BlockDiagonal &b);
|
||||
BlockDiagonal(const BlockDiagonal &b) = default;
|
||||
BlockDiagonal(const QuasiTriangular &t);
|
||||
BlockDiagonal &
|
||||
operator=(const QuasiTriangular &t)
|
||||
BlockDiagonal &operator=(const QuasiTriangular &t)
|
||||
{
|
||||
GeneralMatrix::operator=(t); return *this;
|
||||
}
|
||||
BlockDiagonal &operator=(const BlockDiagonal &b);
|
||||
~BlockDiagonal() override
|
||||
{
|
||||
delete [] row_len; delete [] col_len;
|
||||
GeneralMatrix::operator=(t);
|
||||
return *this;
|
||||
}
|
||||
BlockDiagonal &operator=(const BlockDiagonal &b) = default;
|
||||
~BlockDiagonal() override = default;
|
||||
void setZeroBlockEdge(diag_iter edge);
|
||||
int getNumZeros() const;
|
||||
int getNumBlocks() const;
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
|
@ -28,7 +27,7 @@ GeneralMatrix::GeneralMatrix(const ConstGeneralMatrix &m)
|
|||
copy(m);
|
||||
}
|
||||
|
||||
GeneralMatrix::GeneralMatrix(const GeneralMatrix &m, const char *dummy)
|
||||
GeneralMatrix::GeneralMatrix(const GeneralMatrix &m, const std::string &dummy)
|
||||
: data(m.rows*m.cols), rows(m.cols), cols(m.rows), ld(m.cols)
|
||||
{
|
||||
for (int i = 0; i < m.rows; i++)
|
||||
|
@ -36,7 +35,7 @@ GeneralMatrix::GeneralMatrix(const GeneralMatrix &m, const char *dummy)
|
|||
get(j, i) = m.get(i, j);
|
||||
}
|
||||
|
||||
GeneralMatrix::GeneralMatrix(const ConstGeneralMatrix &m, const char *dummy)
|
||||
GeneralMatrix::GeneralMatrix(const ConstGeneralMatrix &m, const std::string &dummy)
|
||||
: data(m.rows*m.cols), rows(m.cols), cols(m.rows), ld(m.cols)
|
||||
{
|
||||
for (int i = 0; i < m.rows; i++)
|
||||
|
@ -61,20 +60,20 @@ GeneralMatrix::GeneralMatrix(const ConstGeneralMatrix &a, const ConstGeneralMatr
|
|||
gemm("N", a, "N", b, 1.0, 0.0);
|
||||
}
|
||||
|
||||
GeneralMatrix::GeneralMatrix(const ConstGeneralMatrix &a, const ConstGeneralMatrix &b, const char *dum)
|
||||
GeneralMatrix::GeneralMatrix(const ConstGeneralMatrix &a, const ConstGeneralMatrix &b, const std::string &dum)
|
||||
: data(a.rows*b.rows), rows(a.rows), cols(b.rows), ld(a.rows)
|
||||
{
|
||||
gemm("N", a, "T", b, 1.0, 0.0);
|
||||
}
|
||||
|
||||
GeneralMatrix::GeneralMatrix(const ConstGeneralMatrix &a, const char *dum, const ConstGeneralMatrix &b)
|
||||
GeneralMatrix::GeneralMatrix(const ConstGeneralMatrix &a, const std::string &dum, const ConstGeneralMatrix &b)
|
||||
: data(a.cols*b.cols), rows(a.cols), cols(b.cols), ld(a.cols)
|
||||
{
|
||||
gemm("T", a, "N", b, 1.0, 0.0);
|
||||
}
|
||||
|
||||
GeneralMatrix::GeneralMatrix(const ConstGeneralMatrix &a, const char *dum1,
|
||||
const ConstGeneralMatrix &b, const char *dum2)
|
||||
GeneralMatrix::GeneralMatrix(const ConstGeneralMatrix &a, const std::string &dum1,
|
||||
const ConstGeneralMatrix &b, const std::string &dum2)
|
||||
: data(a.cols*b.rows), rows(a.cols), cols(b.rows), ld(a.cols)
|
||||
{
|
||||
gemm("T", a, "T", b, 1.0, 0.0);
|
||||
|
@ -140,21 +139,21 @@ GeneralMatrix::multAndAdd(const ConstGeneralMatrix &a, const ConstGeneralMatrix
|
|||
|
||||
void
|
||||
GeneralMatrix::multAndAdd(const ConstGeneralMatrix &a, const ConstGeneralMatrix &b,
|
||||
const char *dum, double mult)
|
||||
const std::string &dum, double mult)
|
||||
{
|
||||
gemm("N", a, "T", b, mult, 1.0);
|
||||
}
|
||||
|
||||
void
|
||||
GeneralMatrix::multAndAdd(const ConstGeneralMatrix &a, const char *dum,
|
||||
GeneralMatrix::multAndAdd(const ConstGeneralMatrix &a, const std::string &dum,
|
||||
const ConstGeneralMatrix &b, double mult)
|
||||
{
|
||||
gemm("T", a, "N", b, mult, 1.0);
|
||||
}
|
||||
|
||||
void
|
||||
GeneralMatrix::multAndAdd(const ConstGeneralMatrix &a, const char *dum1,
|
||||
const ConstGeneralMatrix &b, const char *dum2, double mult)
|
||||
GeneralMatrix::multAndAdd(const ConstGeneralMatrix &a, const std::string &dum1,
|
||||
const ConstGeneralMatrix &b, const std::string &dum2, double mult)
|
||||
{
|
||||
gemm("T", a, "T", b, mult, 1.0);
|
||||
}
|
||||
|
@ -269,7 +268,7 @@ GeneralMatrix::add(double a, const ConstGeneralMatrix &m)
|
|||
}
|
||||
|
||||
void
|
||||
GeneralMatrix::add(double a, const ConstGeneralMatrix &m, const char *dum)
|
||||
GeneralMatrix::add(double a, const ConstGeneralMatrix &m, const std::string &dum)
|
||||
{
|
||||
if (m.numRows() != cols || m.numCols() != rows)
|
||||
throw SYLV_MES_EXCEPTION("Matrix has different size in GeneralMatrix::add.");
|
||||
|
@ -288,20 +287,20 @@ GeneralMatrix::copy(const ConstGeneralMatrix &m, int ioff, int joff)
|
|||
}
|
||||
|
||||
void
|
||||
GeneralMatrix::gemm(const char *transa, const ConstGeneralMatrix &a,
|
||||
const char *transb, const ConstGeneralMatrix &b,
|
||||
GeneralMatrix::gemm(const std::string &transa, const ConstGeneralMatrix &a,
|
||||
const std::string &transb, const ConstGeneralMatrix &b,
|
||||
double alpha, double beta)
|
||||
{
|
||||
int opa_rows = a.numRows();
|
||||
int opa_cols = a.numCols();
|
||||
if (!strcmp(transa, "T"))
|
||||
if (transa == "T")
|
||||
{
|
||||
opa_rows = a.numCols();
|
||||
opa_cols = a.numRows();
|
||||
}
|
||||
int opb_rows = b.numRows();
|
||||
int opb_cols = b.numCols();
|
||||
if (!strcmp(transb, "T"))
|
||||
if (transb == "T")
|
||||
{
|
||||
opb_rows = b.numCols();
|
||||
opb_cols = b.numRows();
|
||||
|
@ -322,7 +321,7 @@ GeneralMatrix::gemm(const char *transa, const ConstGeneralMatrix &a,
|
|||
blas_int ldc = ld;
|
||||
if (lda > 0 && ldb > 0 && ldc > 0)
|
||||
{
|
||||
dgemm(transa, transb, &m, &n, &k, &alpha, a.data.base(), &lda,
|
||||
dgemm(transa.c_str(), transb.c_str(), &m, &n, &k, &alpha, a.data.base(), &lda,
|
||||
b.data.base(), &ldb, &beta, data.base(), &ldc);
|
||||
}
|
||||
else if (numRows()*numCols() > 0)
|
||||
|
@ -335,7 +334,7 @@ GeneralMatrix::gemm(const char *transa, const ConstGeneralMatrix &a,
|
|||
}
|
||||
|
||||
void
|
||||
GeneralMatrix::gemm_partial_left(const char *trans, const ConstGeneralMatrix &m,
|
||||
GeneralMatrix::gemm_partial_left(const std::string &trans, const ConstGeneralMatrix &m,
|
||||
double alpha, double beta)
|
||||
{
|
||||
int icol;
|
||||
|
@ -354,7 +353,7 @@ GeneralMatrix::gemm_partial_left(const char *trans, const ConstGeneralMatrix &m,
|
|||
}
|
||||
|
||||
void
|
||||
GeneralMatrix::gemm_partial_right(const char *trans, const ConstGeneralMatrix &m,
|
||||
GeneralMatrix::gemm_partial_right(const std::string &trans, const ConstGeneralMatrix &m,
|
||||
double alpha, double beta)
|
||||
{
|
||||
int irow;
|
||||
|
@ -469,7 +468,7 @@ ConstGeneralMatrix::multVecTrans(double a, Vector &x, double b,
|
|||
|
||||
/* m = inv(this)*m */
|
||||
void
|
||||
ConstGeneralMatrix::multInvLeft(const char *trans, int mrows, int mcols, int mld, double *d) const
|
||||
ConstGeneralMatrix::multInvLeft(const std::string &trans, int mrows, int mcols, int mld, double *d) const
|
||||
{
|
||||
if (rows != cols)
|
||||
throw SYLV_MES_EXCEPTION("The matrix is not square for inversion.");
|
||||
|
@ -483,7 +482,7 @@ ConstGeneralMatrix::multInvLeft(const char *trans, int mrows, int mcols, int mld
|
|||
lapack_int info;
|
||||
lapack_int rows2 = rows, mcols2 = mcols, mld2 = mld, lda = inv.ld;
|
||||
dgetrf(&rows2, &rows2, inv.getData().base(), &lda, ipiv.data(), &info);
|
||||
dgetrs(trans, &rows2, &mcols2, inv.base(), &lda, ipiv.data(), d,
|
||||
dgetrs(trans.c_str(), &rows2, &mcols2, inv.base(), &lda, ipiv.data(), d,
|
||||
&mld2, &info);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include <string>
|
||||
|
||||
class GeneralMatrix;
|
||||
|
||||
|
@ -120,7 +121,7 @@ public:
|
|||
|
||||
virtual void print() const;
|
||||
protected:
|
||||
void multInvLeft(const char *trans, int mrows, int mcols, int mld, double *d) const;
|
||||
void multInvLeft(const std::string &trans, int mrows, int mcols, int mld, double *d) const;
|
||||
};
|
||||
|
||||
class GeneralMatrix
|
||||
|
@ -152,19 +153,19 @@ public:
|
|||
explicit GeneralMatrix(const ConstGeneralMatrix &m);
|
||||
|
||||
GeneralMatrix(GeneralMatrix &&m) = default;
|
||||
GeneralMatrix(const GeneralMatrix &m, const char *dummy); // transpose
|
||||
GeneralMatrix(const ConstGeneralMatrix &m, const char *dummy); // transpose
|
||||
GeneralMatrix(const GeneralMatrix &m, const std::string &dummy); // transpose
|
||||
GeneralMatrix(const ConstGeneralMatrix &m, const std::string &dummy); // transpose
|
||||
GeneralMatrix(const GeneralMatrix &m, int i, int j, int nrows, int ncols);
|
||||
GeneralMatrix(GeneralMatrix &m, int i, int j, int nrows, int ncols);
|
||||
/* this = a*b */
|
||||
GeneralMatrix(const ConstGeneralMatrix &a, const ConstGeneralMatrix &b);
|
||||
/* this = a*b' */
|
||||
GeneralMatrix(const ConstGeneralMatrix &a, const ConstGeneralMatrix &b, const char *dum);
|
||||
GeneralMatrix(const ConstGeneralMatrix &a, const ConstGeneralMatrix &b, const std::string &dum);
|
||||
/* this = a'*b */
|
||||
GeneralMatrix(const ConstGeneralMatrix &a, const char *dum, const ConstGeneralMatrix &b);
|
||||
GeneralMatrix(const ConstGeneralMatrix &a, const std::string &dum, const ConstGeneralMatrix &b);
|
||||
/* this = a'*b */
|
||||
GeneralMatrix(const ConstGeneralMatrix &a, const char *dum1,
|
||||
const ConstGeneralMatrix &b, const char *dum2);
|
||||
GeneralMatrix(const ConstGeneralMatrix &a, const std::string &dum1,
|
||||
const ConstGeneralMatrix &b, const std::string &dum2);
|
||||
|
||||
virtual ~GeneralMatrix() = default;
|
||||
GeneralMatrix &operator=(const GeneralMatrix &m) = default;
|
||||
|
@ -260,30 +261,30 @@ public:
|
|||
|
||||
/* this = this + scalar*a*b' */
|
||||
void multAndAdd(const ConstGeneralMatrix &a, const ConstGeneralMatrix &b,
|
||||
const char *dum, double mult = 1.0);
|
||||
const std::string &dum, double mult = 1.0);
|
||||
void
|
||||
multAndAdd(const GeneralMatrix &a, const GeneralMatrix &b,
|
||||
const char *dum, double mult = 1.0)
|
||||
const std::string &dum, double mult = 1.0)
|
||||
{
|
||||
multAndAdd(ConstGeneralMatrix(a), ConstGeneralMatrix(b), dum, mult);
|
||||
}
|
||||
|
||||
/* this = this + scalar*a'*b */
|
||||
void multAndAdd(const ConstGeneralMatrix &a, const char *dum, const ConstGeneralMatrix &b,
|
||||
void multAndAdd(const ConstGeneralMatrix &a, const std::string &dum, const ConstGeneralMatrix &b,
|
||||
double mult = 1.0);
|
||||
void
|
||||
multAndAdd(const GeneralMatrix &a, const char *dum, const GeneralMatrix &b,
|
||||
multAndAdd(const GeneralMatrix &a, const std::string &dum, const GeneralMatrix &b,
|
||||
double mult = 1.0)
|
||||
{
|
||||
multAndAdd(ConstGeneralMatrix(a), dum, ConstGeneralMatrix(b), mult);
|
||||
}
|
||||
|
||||
/* this = this + scalar*a'*b' */
|
||||
void multAndAdd(const ConstGeneralMatrix &a, const char *dum1,
|
||||
const ConstGeneralMatrix &b, const char *dum2, double mult = 1.0);
|
||||
void multAndAdd(const ConstGeneralMatrix &a, const std::string &dum1,
|
||||
const ConstGeneralMatrix &b, const std::string &dum2, double mult = 1.0);
|
||||
void
|
||||
multAndAdd(const GeneralMatrix &a, const char *dum1,
|
||||
const GeneralMatrix &b, const char *dum2, double mult = 1.0)
|
||||
multAndAdd(const GeneralMatrix &a, const std::string &dum1,
|
||||
const GeneralMatrix &b, const std::string &dum2, double mult = 1.0)
|
||||
{
|
||||
multAndAdd(ConstGeneralMatrix(a), dum1, ConstGeneralMatrix(b), dum2, mult);
|
||||
}
|
||||
|
@ -394,9 +395,9 @@ public:
|
|||
}
|
||||
|
||||
/* this = this + scalar*m' */
|
||||
void add(double a, const ConstGeneralMatrix &m, const char *dum);
|
||||
void add(double a, const ConstGeneralMatrix &m, const std::string &dum);
|
||||
void
|
||||
add(double a, const GeneralMatrix &m, const char *dum)
|
||||
add(double a, const GeneralMatrix &m, const std::string &dum)
|
||||
{
|
||||
add(a, ConstGeneralMatrix(m), dum);
|
||||
}
|
||||
|
@ -426,12 +427,12 @@ private:
|
|||
copy(ConstGeneralMatrix(m), ioff, joff);
|
||||
}
|
||||
|
||||
void gemm(const char *transa, const ConstGeneralMatrix &a,
|
||||
const char *transb, const ConstGeneralMatrix &b,
|
||||
void gemm(const std::string &transa, const ConstGeneralMatrix &a,
|
||||
const std::string &transb, const ConstGeneralMatrix &b,
|
||||
double alpha, double beta);
|
||||
void
|
||||
gemm(const char *transa, const GeneralMatrix &a,
|
||||
const char *transb, const GeneralMatrix &b,
|
||||
gemm(const std::string &transa, const GeneralMatrix &a,
|
||||
const std::string &transb, const GeneralMatrix &b,
|
||||
double alpha, double beta)
|
||||
{
|
||||
gemm(transa, ConstGeneralMatrix(a), transb, ConstGeneralMatrix(b),
|
||||
|
@ -439,20 +440,20 @@ private:
|
|||
}
|
||||
|
||||
/* this = this * op(m) (without whole copy of this) */
|
||||
void gemm_partial_right(const char *trans, const ConstGeneralMatrix &m,
|
||||
void gemm_partial_right(const std::string &trans, const ConstGeneralMatrix &m,
|
||||
double alpha, double beta);
|
||||
void
|
||||
gemm_partial_right(const char *trans, const GeneralMatrix &m,
|
||||
gemm_partial_right(const std::string &trans, const GeneralMatrix &m,
|
||||
double alpha, double beta)
|
||||
{
|
||||
gemm_partial_right(trans, ConstGeneralMatrix(m), alpha, beta);
|
||||
}
|
||||
|
||||
/* this = op(m) *this (without whole copy of this) */
|
||||
void gemm_partial_left(const char *trans, const ConstGeneralMatrix &m,
|
||||
void gemm_partial_left(const std::string &trans, const ConstGeneralMatrix &m,
|
||||
double alpha, double beta);
|
||||
void
|
||||
gemm_partial_left(const char *trans, const GeneralMatrix &m,
|
||||
gemm_partial_left(const std::string &trans, const GeneralMatrix &m,
|
||||
double alpha, double beta)
|
||||
{
|
||||
gemm_partial_left(trans, ConstGeneralMatrix(m), alpha, beta);
|
||||
|
|
|
@ -71,7 +71,7 @@ GeneralSylvester::init()
|
|||
cdecomp = std::make_unique<SimilarityDecomp>(c.getData(), c.numRows(), *(pars.bs_norm));
|
||||
cdecomp->check(pars, c);
|
||||
cdecomp->infoToPars(pars);
|
||||
if (*(pars.method) == SylvParams::recurse)
|
||||
if (*(pars.method) == SylvParams::solve_method::recurse)
|
||||
sylv = std::make_unique<TriangularSylvester>(*bdecomp, *cdecomp);
|
||||
else
|
||||
sylv = std::make_unique<IterativeSylvester>(*bdecomp, *cdecomp);
|
||||
|
|
|
@ -27,9 +27,7 @@ KronUtils::multAtLevel(int level, const QuasiTriangular &t,
|
|||
t.multVec(x, b);
|
||||
}
|
||||
else // 0 < level == depth
|
||||
{
|
||||
t.multKron(x);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -55,9 +53,7 @@ KronUtils::multAtLevelTrans(int level, const QuasiTriangular &t,
|
|||
t.multVecTrans(x, b);
|
||||
}
|
||||
else // 0 < level == depth
|
||||
{
|
||||
t.multKronTrans(x);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -37,18 +37,17 @@ KronVector::KronVector(KronVector &v, int i)
|
|||
}
|
||||
|
||||
KronVector::KronVector(const ConstKronVector &v)
|
||||
: Vector(v.length()), m(v.getM()), n(v.getN()), depth(v.getDepth())
|
||||
: Vector(v), m(v.m), n(v.n), depth(v.depth)
|
||||
{
|
||||
Vector::operator=(v);
|
||||
}
|
||||
|
||||
KronVector &
|
||||
KronVector::operator=(const ConstKronVector &v)
|
||||
{
|
||||
Vector::operator=(v);
|
||||
m = v.getM();
|
||||
n = v.getN();
|
||||
depth = v.getDepth();
|
||||
m = v.m;
|
||||
n = v.n;
|
||||
depth = v.depth;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -62,13 +61,7 @@ KronVector::operator=(const Vector &v)
|
|||
}
|
||||
|
||||
ConstKronVector::ConstKronVector(const KronVector &v)
|
||||
: ConstVector(v), m(v.getM()), n(v.getN()), depth(v.getDepth())
|
||||
{
|
||||
}
|
||||
|
||||
ConstKronVector::ConstKronVector(const ConstKronVector &v)
|
||||
: ConstVector(power(v.getM(), v.getDepth())*v.getN()), m(v.getM()), n(v.getN()),
|
||||
depth(v.getDepth())
|
||||
: ConstVector(v), m(v.m), n(v.n), depth(v.depth)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -11,18 +11,22 @@ class ConstKronVector;
|
|||
|
||||
class KronVector : public Vector
|
||||
{
|
||||
friend class ConstKronVector;
|
||||
protected:
|
||||
int m{0};
|
||||
int n{0};
|
||||
int depth{0};
|
||||
public:
|
||||
KronVector() = default;
|
||||
KronVector(const KronVector &v) = default;
|
||||
KronVector(KronVector &&v) = default;
|
||||
KronVector(int mm, int nn, int dp); // new instance
|
||||
KronVector(Vector &v, int mm, int nn, int dp); // conversion
|
||||
KronVector(KronVector &, int i); // picks i-th subvector
|
||||
// We don't want implict conversion from ConstKronVector, since it's expensive
|
||||
explicit KronVector(const ConstKronVector &v); // new instance and copy
|
||||
KronVector &operator=(const KronVector &v) = default;
|
||||
KronVector &operator=(KronVector &&v) = default;
|
||||
KronVector &operator=(const ConstKronVector &v);
|
||||
KronVector &operator=(const Vector &v);
|
||||
int
|
||||
|
@ -44,6 +48,7 @@ public:
|
|||
|
||||
class ConstKronVector : public ConstVector
|
||||
{
|
||||
friend class KronVector;
|
||||
protected:
|
||||
int m;
|
||||
int n;
|
||||
|
@ -51,11 +56,14 @@ protected:
|
|||
public:
|
||||
// Implicit conversion from KronVector is ok, since it's cheap
|
||||
ConstKronVector(const KronVector &v);
|
||||
ConstKronVector(const ConstKronVector &v);
|
||||
ConstKronVector(const ConstKronVector &v) = default;
|
||||
ConstKronVector(ConstKronVector &&v) = default;
|
||||
ConstKronVector(const Vector &v, int mm, int nn, int dp);
|
||||
ConstKronVector(ConstVector v, int mm, int nn, int dp);
|
||||
ConstKronVector(const KronVector &v, int i);
|
||||
ConstKronVector(const ConstKronVector &v, int i);
|
||||
ConstKronVector &operator=(const ConstKronVector &v) = delete;
|
||||
ConstKronVector &operator=(ConstKronVector &&v) = delete;
|
||||
int
|
||||
getM() const
|
||||
{
|
||||
|
|
|
@ -12,8 +12,6 @@
|
|||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
double
|
||||
DiagonalBlock::getDeterminant() const
|
||||
{
|
||||
|
@ -30,9 +28,9 @@ double
|
|||
DiagonalBlock::getSize() const
|
||||
{
|
||||
if (real)
|
||||
return abs(*alpha);
|
||||
return std::abs(*alpha);
|
||||
else
|
||||
return sqrt(getDeterminant());
|
||||
return std::sqrt(getDeterminant());
|
||||
}
|
||||
|
||||
// this function makes Diagonal inconsistent, it should only be used
|
||||
|
@ -119,28 +117,18 @@ Diagonal::Diagonal(double *data, const Diagonal &d)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
Diagonal::copy(const Diagonal &d)
|
||||
{
|
||||
num_all = d.num_all;
|
||||
num_real = d.num_real;
|
||||
blocks = d.blocks;
|
||||
}
|
||||
|
||||
int
|
||||
Diagonal::getNumComplex(const double *data, int d_size)
|
||||
{
|
||||
int num_complex = 0;
|
||||
int in = 1;
|
||||
for (int i = 0; i < d_size-1; i++, in = in + d_size + 1)
|
||||
{
|
||||
if (!isZero(data[in]))
|
||||
{
|
||||
num_complex++;
|
||||
if (in < d_size - 2 && !isZero(data[in + d_size +1]))
|
||||
throw SYLV_MES_EXCEPTION("Matrix is not quasi-triangular");
|
||||
}
|
||||
}
|
||||
return num_complex;
|
||||
}
|
||||
|
||||
|
@ -174,7 +162,7 @@ Diagonal::getEigenValues(Vector &eig) const
|
|||
int d_size = getSize();
|
||||
if (eig.length() != 2*d_size)
|
||||
{
|
||||
ostringstream mes;
|
||||
std::ostringstream mes;
|
||||
mes << "Wrong length of vector for eigenvalues len=" << eig.length()
|
||||
<< ", should be=" << 2*d_size << '.' << std::endl;
|
||||
throw SYLV_MES_EXCEPTION(mes.str());
|
||||
|
@ -187,7 +175,7 @@ Diagonal::getEigenValues(Vector &eig) const
|
|||
eig[2*ind+1] = 0.0;
|
||||
else
|
||||
{
|
||||
double beta = sqrt(b.getSBeta());
|
||||
double beta = std::sqrt(b.getSBeta());
|
||||
eig[2*ind+1] = beta;
|
||||
eig[2*ind+2] = eig[2*ind];
|
||||
eig[2*ind+3] = -beta;
|
||||
|
@ -204,28 +192,28 @@ Diagonal::swapLogically(diag_iter it)
|
|||
diag_iter itp = it;
|
||||
++itp;
|
||||
|
||||
if ((*it).isReal() && !(*itp).isReal())
|
||||
if (it->isReal() && !itp->isReal())
|
||||
{
|
||||
// first is real, second is complex
|
||||
double *d1 = (*it).alpha.a1;
|
||||
double *d2 = (*itp).alpha.a1;
|
||||
double *d3 = (*itp).alpha.a2;
|
||||
double *d1 = it->alpha.a1;
|
||||
double *d2 = itp->alpha.a1;
|
||||
double *d3 = itp->alpha.a2;
|
||||
// swap
|
||||
DiagonalBlock new_it((*it).jbar, d1, d2);
|
||||
DiagonalBlock new_it(it->jbar, d1, d2);
|
||||
*it = new_it;
|
||||
DiagonalBlock new_itp((*itp).jbar+1, d3);
|
||||
DiagonalBlock new_itp(itp->jbar+1, d3);
|
||||
*itp = new_itp;
|
||||
}
|
||||
else if (!(*it).isReal() && (*itp).isReal())
|
||||
else if (!it->isReal() && itp->isReal())
|
||||
{
|
||||
// first is complex, second is real
|
||||
double *d1 = (*it).alpha.a1;
|
||||
double *d2 = (*it).alpha.a2;
|
||||
double *d3 = (*itp).alpha.a1;
|
||||
double *d1 = it->alpha.a1;
|
||||
double *d2 = it->alpha.a2;
|
||||
double *d3 = itp->alpha.a1;
|
||||
// swap
|
||||
DiagonalBlock new_it((*it).jbar, d1);
|
||||
DiagonalBlock new_it(it->jbar, d1);
|
||||
*it = new_it;
|
||||
DiagonalBlock new_itp((*itp).jbar-1, d2, d3);
|
||||
DiagonalBlock new_itp(itp->jbar-1, d2, d3);
|
||||
*itp = new_itp;
|
||||
}
|
||||
}
|
||||
|
@ -233,17 +221,17 @@ Diagonal::swapLogically(diag_iter it)
|
|||
void
|
||||
Diagonal::checkConsistency(diag_iter it)
|
||||
{
|
||||
if (!(*it).isReal() && isZero((*it).getBeta2()))
|
||||
if (!it->isReal() && isZero(it->getBeta2()))
|
||||
{
|
||||
(*it).getBeta2() = 0.0; // put exact zero
|
||||
int jbar = (*it).getIndex();
|
||||
double *d2 = (*it).alpha.a2;
|
||||
(*it).alpha.a2 = (*it).alpha.a1;
|
||||
(*it).real = true;
|
||||
(*it).beta1 = nullptr;
|
||||
(*it).beta2 = nullptr;
|
||||
it->getBeta2() = 0.0; // put exact zero
|
||||
int jbar = it->getIndex();
|
||||
double *d2 = it->alpha.a2;
|
||||
it->alpha.a2 = it->alpha.a1;
|
||||
it->real = true;
|
||||
it->beta1 = nullptr;
|
||||
it->beta2 = nullptr;
|
||||
DiagonalBlock b(jbar+1, d2);
|
||||
blocks.insert((++it).iter(), b);
|
||||
blocks.insert(++it, b);
|
||||
num_real += 2;
|
||||
num_all++;
|
||||
}
|
||||
|
@ -257,7 +245,7 @@ Diagonal::getAverageSize(diag_iter start, diag_iter end)
|
|||
for (diag_iter run = start; run != end; ++run)
|
||||
{
|
||||
num++;
|
||||
res += (*run).getSize();
|
||||
res += run->getSize();
|
||||
}
|
||||
if (num > 0)
|
||||
res = res/num;
|
||||
|
@ -271,7 +259,7 @@ Diagonal::findClosestBlock(diag_iter start, diag_iter end, double a)
|
|||
double minim = 1.0e100;
|
||||
for (diag_iter run = start; run != end; ++run)
|
||||
{
|
||||
double dist = abs(a - (*run).getSize());
|
||||
double dist = std::abs(a - run->getSize());
|
||||
if (dist < minim)
|
||||
{
|
||||
minim = dist;
|
||||
|
@ -288,7 +276,7 @@ Diagonal::findNextLargerBlock(diag_iter start, diag_iter end, double a)
|
|||
double minim = 1.0e100;
|
||||
for (diag_iter run = start; run != end; ++run)
|
||||
{
|
||||
double dist = (*run).getSize() - a;
|
||||
double dist = run->getSize() - a;
|
||||
if ((0 <= dist) && (dist < minim))
|
||||
{
|
||||
minim = dist;
|
||||
|
@ -318,7 +306,7 @@ Diagonal::print() const
|
|||
bool
|
||||
Diagonal::isZero(double p)
|
||||
{
|
||||
return (abs(p) < EPS);
|
||||
return (std::abs(p) < EPS);
|
||||
}
|
||||
|
||||
QuasiTriangular::const_col_iter
|
||||
|
@ -453,21 +441,15 @@ QuasiTriangular::QuasiTriangular(const SchurDecompZero &decomp)
|
|||
zv.zeros();
|
||||
// fill right upper part with decomp.getRU()
|
||||
for (int i = 0; i < decomp.getRU().numRows(); i++)
|
||||
{
|
||||
for (int j = 0; j < decomp.getRU().numCols(); j++)
|
||||
{
|
||||
getData()[(j+decomp.getZeroCols())*decomp.getDim()+i] = decomp.getRU().get(i, j);
|
||||
}
|
||||
}
|
||||
|
||||
// fill right lower part with decomp.getT()
|
||||
for (int i = 0; i < decomp.getT().numRows(); i++)
|
||||
{
|
||||
for (int j = 0; j < decomp.getT().numCols(); j++)
|
||||
{
|
||||
getData()[(j+decomp.getZeroCols())*decomp.getDim()+decomp.getZeroCols()+i]
|
||||
= decomp.getT().get(i, j);
|
||||
}
|
||||
}
|
||||
|
||||
// construct diagonal
|
||||
diagonal = Diagonal{getData().base(), decomp.getDim()};
|
||||
}
|
||||
|
@ -487,27 +469,23 @@ QuasiTriangular::setMatrixViaIter(double r, const QuasiTriangular &t)
|
|||
const_diag_iter dir = t.diag_begin();
|
||||
for (; dil != diag_end(); ++dil, ++dir)
|
||||
{
|
||||
(*dil).getAlpha() = rr*(*(*dir).getAlpha());
|
||||
if (!(*dil).isReal())
|
||||
dil->getAlpha() = rr*(*dir->getAlpha());
|
||||
if (!dil->isReal())
|
||||
{
|
||||
(*dil).getBeta1() = rr*(*dir).getBeta1();
|
||||
(*dil).getBeta2() = rr*(*dir).getBeta2();
|
||||
dil->getBeta1() = rr*dir->getBeta1();
|
||||
dil->getBeta2() = rr*dir->getBeta2();
|
||||
}
|
||||
col_iter cil = col_begin(*dil);
|
||||
const_col_iter cir = t.col_begin(*dir);
|
||||
for (; cil != col_end(*dil); ++cil, ++cir)
|
||||
{
|
||||
if ((*dil).isReal())
|
||||
{
|
||||
if (dil->isReal())
|
||||
*cil = rr*(*cir);
|
||||
}
|
||||
else
|
||||
{
|
||||
cil.a() = rr*cir.a();
|
||||
cil.b() = rr*cir.b();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -524,36 +502,30 @@ QuasiTriangular::addMatrixViaIter(double r, const QuasiTriangular &t)
|
|||
const_diag_iter dir = t.diag_begin();
|
||||
for (; dil != diag_end(); ++dil, ++dir)
|
||||
{
|
||||
(*dil).getAlpha() = (*(*dil).getAlpha()) + rr*(*(*dir).getAlpha());
|
||||
if (!(*dil).isReal())
|
||||
dil->getAlpha() = (*dil->getAlpha()) + rr*(*dir->getAlpha());
|
||||
if (!dil->isReal())
|
||||
{
|
||||
(*dil).getBeta1() += rr*(*dir).getBeta1();
|
||||
(*dil).getBeta2() += rr*(*dir).getBeta2();
|
||||
dil->getBeta1() += rr*dir->getBeta1();
|
||||
dil->getBeta2() += rr*dir->getBeta2();
|
||||
}
|
||||
col_iter cil = col_begin(*dil);
|
||||
const_col_iter cir = t.col_begin(*dir);
|
||||
for (; cil != col_end(*dil); ++cil, ++cir)
|
||||
{
|
||||
if ((*dil).isReal())
|
||||
{
|
||||
if (dil->isReal())
|
||||
*cil += rr*(*cir);
|
||||
}
|
||||
else
|
||||
{
|
||||
cil.a() += rr*cir.a();
|
||||
cil.b() += rr*cir.b();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
QuasiTriangular::addUnit()
|
||||
{
|
||||
for (diag_iter di = diag_begin(); di != diag_end(); ++di)
|
||||
{
|
||||
(*di).getAlpha() = *((*di).getAlpha()) + 1.0;
|
||||
}
|
||||
di->getAlpha() = *(di->getAlpha()) + 1.0;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -577,15 +549,13 @@ QuasiTriangular::solvePre(Vector &x, double &eig_min)
|
|||
for (diag_iter di = diag_begin(); di != diag_end(); ++di)
|
||||
{
|
||||
double eig_size;
|
||||
if (!(*di).isReal())
|
||||
if (!di->isReal())
|
||||
{
|
||||
eig_size = (*di).getDeterminant();
|
||||
eliminateLeft((*di).getIndex()+1, (*di).getIndex(), x);
|
||||
eig_size = di->getDeterminant();
|
||||
eliminateLeft(di->getIndex()+1, di->getIndex(), x);
|
||||
}
|
||||
else
|
||||
{
|
||||
eig_size = *(*di).getAlpha()*(*(*di).getAlpha());
|
||||
}
|
||||
eig_size = *di->getAlpha()*(*di->getAlpha());
|
||||
if (eig_size < eig_min)
|
||||
eig_min = eig_size;
|
||||
}
|
||||
|
@ -603,15 +573,13 @@ QuasiTriangular::solvePreTrans(Vector &x, double &eig_min)
|
|||
for (diag_iter di = diag_begin(); di != diag_end(); ++di)
|
||||
{
|
||||
double eig_size;
|
||||
if (!(*di).isReal())
|
||||
if (!di->isReal())
|
||||
{
|
||||
eig_size = (*di).getDeterminant();
|
||||
eliminateRight((*di).getIndex()+1, (*di).getIndex(), x);
|
||||
eig_size = di->getDeterminant();
|
||||
eliminateRight(di->getIndex()+1, di->getIndex(), x);
|
||||
}
|
||||
else
|
||||
{
|
||||
eig_size = *(*di).getAlpha()*(*(*di).getAlpha());
|
||||
}
|
||||
eig_size = *di->getAlpha()*(*di->getAlpha());
|
||||
if (eig_size < eig_min)
|
||||
eig_min = eig_size;
|
||||
}
|
||||
|
@ -632,12 +600,10 @@ QuasiTriangular::multVec(Vector &x, const ConstVector &b) const
|
|||
blas_int incx = x.skip();
|
||||
dtrmv("U", "N", "N", &nn, getData().base(), &lda, x.base(), &incx);
|
||||
for (const_diag_iter di = diag_begin(); di != diag_end(); ++di)
|
||||
if (!di->isReal())
|
||||
{
|
||||
if (!(*di).isReal())
|
||||
{
|
||||
int jbar = (*di).getIndex();
|
||||
x[jbar+1] += (*di).getBeta2()*(b[jbar]);
|
||||
}
|
||||
int jbar = di->getIndex();
|
||||
x[jbar+1] += di->getBeta2()*(b[jbar]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -650,12 +616,10 @@ QuasiTriangular::multVecTrans(Vector &x, const ConstVector &b) const
|
|||
blas_int incx = x.skip();
|
||||
dtrmv("U", "T", "N", &nn, getData().base(), &lda, x.base(), &incx);
|
||||
for (const_diag_iter di = diag_begin(); di != diag_end(); ++di)
|
||||
if (!di->isReal())
|
||||
{
|
||||
if (!(*di).isReal())
|
||||
{
|
||||
int jbar = (*di).getIndex();
|
||||
x[jbar] += (*di).getBeta2()*b[jbar+1];
|
||||
}
|
||||
int jbar = di->getIndex();
|
||||
x[jbar] += di->getBeta2()*b[jbar+1];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,8 +12,6 @@
|
|||
#include <list>
|
||||
#include <memory>
|
||||
|
||||
using namespace std;
|
||||
|
||||
class DiagonalBlock;
|
||||
class Diagonal;
|
||||
class DiagPair
|
||||
|
@ -23,19 +21,17 @@ private:
|
|||
double *a2;
|
||||
public:
|
||||
DiagPair() = default;
|
||||
DiagPair(double *aa1, double *aa2)
|
||||
DiagPair(double *aa1, double *aa2) : a1{aa1}, a2{aa2}
|
||||
{
|
||||
a1 = aa1; a2 = aa2;
|
||||
}
|
||||
DiagPair(const DiagPair &p)
|
||||
{
|
||||
a1 = p.a1; a2 = p.a2;
|
||||
}
|
||||
DiagPair(const DiagPair &p) = default;
|
||||
DiagPair &operator=(const DiagPair &p) = default;
|
||||
DiagPair &
|
||||
operator=(double v)
|
||||
{
|
||||
*a1 = v; *a2 = v; return *this;
|
||||
*a1 = v;
|
||||
*a2 = v;
|
||||
return *this;
|
||||
}
|
||||
const double &
|
||||
operator*() const
|
||||
|
@ -48,6 +44,9 @@ public:
|
|||
friend class DiagonalBlock;
|
||||
};
|
||||
|
||||
// Stores a diagonal block: either a scalar, or a 2x2 block
|
||||
/* alpha points to the diagonal element(s); beta1 and beta2 point to the
|
||||
off-diagonal elements of the 2x2 block */
|
||||
class DiagonalBlock
|
||||
{
|
||||
private:
|
||||
|
@ -57,54 +56,25 @@ private:
|
|||
double *beta1;
|
||||
double *beta2;
|
||||
|
||||
void
|
||||
copy(const DiagonalBlock &b)
|
||||
{
|
||||
jbar = b.jbar;
|
||||
real = b.real;
|
||||
alpha = b.alpha;
|
||||
beta1 = b.beta1;
|
||||
beta2 = b.beta2;
|
||||
}
|
||||
|
||||
public:
|
||||
DiagonalBlock() = default;
|
||||
DiagonalBlock(int jb, bool r, double *a1, double *a2,
|
||||
double *b1, double *b2)
|
||||
: alpha(a1, a2)
|
||||
: jbar{jb}, real{r}, alpha{a1, a2}, beta1{b1}, beta2{b2}
|
||||
{
|
||||
jbar = jb;
|
||||
real = r;
|
||||
beta1 = b1;
|
||||
beta2 = b2;
|
||||
}
|
||||
// construct complex block
|
||||
DiagonalBlock(int jb, double *a1, double *a2)
|
||||
: alpha(a1, a2)
|
||||
: jbar{jb}, real{false}, alpha{a1, a2}, beta1{a2-1}, beta2{a1+1}
|
||||
{
|
||||
jbar = jb;
|
||||
real = false;
|
||||
beta1 = a2 - 1;
|
||||
beta2 = a1 + 1;
|
||||
}
|
||||
// construct real block
|
||||
DiagonalBlock(int jb, double *a1)
|
||||
: alpha(a1, a1)
|
||||
: jbar{jb}, real{true}, alpha{a1, a1}, beta1{nullptr}, beta2{nullptr}
|
||||
{
|
||||
jbar = jb;
|
||||
real = true;
|
||||
beta1 = nullptr;
|
||||
beta2 = nullptr;
|
||||
}
|
||||
DiagonalBlock(const DiagonalBlock &b)
|
||||
{
|
||||
copy(b);
|
||||
}
|
||||
DiagonalBlock &
|
||||
operator=(const DiagonalBlock &b)
|
||||
{
|
||||
copy(b); return *this;
|
||||
}
|
||||
DiagonalBlock(const DiagonalBlock &b) = default;
|
||||
DiagonalBlock &operator=(const DiagonalBlock &b) = default;
|
||||
int
|
||||
getIndex() const
|
||||
{
|
||||
|
@ -144,76 +114,21 @@ public:
|
|||
friend class Diagonal;
|
||||
};
|
||||
|
||||
template <class _Tdiag, class _Tblock, class _Titer>
|
||||
struct _diag_iter
|
||||
{
|
||||
using _Self = _diag_iter<_Tdiag, _Tblock, _Titer>;
|
||||
_Tdiag diag;
|
||||
_Titer it;
|
||||
public:
|
||||
_diag_iter(_Tdiag d, _Titer iter) : diag(d), it(iter)
|
||||
{
|
||||
}
|
||||
_Tblock
|
||||
operator*() const
|
||||
{
|
||||
return *it;
|
||||
}
|
||||
_Self &
|
||||
operator++()
|
||||
{
|
||||
++it; return *this;
|
||||
}
|
||||
_Self &
|
||||
operator--()
|
||||
{
|
||||
--it; return *this;
|
||||
}
|
||||
bool
|
||||
operator==(const _Self &x) const
|
||||
{
|
||||
return x.it == it;
|
||||
}
|
||||
bool
|
||||
operator!=(const _Self &x) const
|
||||
{
|
||||
return x.it != it;
|
||||
}
|
||||
_Self &
|
||||
operator=(const _Self &x)
|
||||
{
|
||||
it = x.it; return *this;
|
||||
}
|
||||
_Titer
|
||||
iter() const
|
||||
{
|
||||
return it;
|
||||
}
|
||||
};
|
||||
|
||||
class Diagonal
|
||||
{
|
||||
public:
|
||||
using const_diag_iter = _diag_iter<const Diagonal &, const DiagonalBlock &, list<DiagonalBlock>::const_iterator>;
|
||||
using diag_iter = _diag_iter<Diagonal &, DiagonalBlock &, list<DiagonalBlock>::iterator>;
|
||||
using const_diag_iter = std::list<DiagonalBlock>::const_iterator;
|
||||
using diag_iter = std::list<DiagonalBlock>::iterator;
|
||||
private:
|
||||
int num_all{0};
|
||||
list<DiagonalBlock> blocks;
|
||||
std::list<DiagonalBlock> blocks;
|
||||
int num_real{0};
|
||||
void copy(const Diagonal &);
|
||||
public:
|
||||
Diagonal() = default;
|
||||
Diagonal(double *data, int d_size);
|
||||
Diagonal(double *data, const Diagonal &d);
|
||||
Diagonal(const Diagonal &d)
|
||||
{
|
||||
copy(d);
|
||||
}
|
||||
Diagonal &
|
||||
operator=(const Diagonal &d)
|
||||
{
|
||||
copy(d); return *this;
|
||||
}
|
||||
Diagonal(const Diagonal &d) = default;
|
||||
Diagonal &operator=(const Diagonal &d) = default;
|
||||
virtual ~Diagonal() = default;
|
||||
|
||||
int
|
||||
|
@ -247,22 +162,22 @@ public:
|
|||
diag_iter
|
||||
begin()
|
||||
{
|
||||
return diag_iter(*this, blocks.begin());
|
||||
return blocks.begin();
|
||||
}
|
||||
const_diag_iter
|
||||
begin() const
|
||||
{
|
||||
return const_diag_iter(*this, blocks.begin());
|
||||
return blocks.begin();
|
||||
}
|
||||
diag_iter
|
||||
end()
|
||||
{
|
||||
return diag_iter(*this, blocks.end());
|
||||
return blocks.end();
|
||||
}
|
||||
const_diag_iter
|
||||
end() const
|
||||
{
|
||||
return const_diag_iter(*this, blocks.end());
|
||||
return blocks.end();
|
||||
}
|
||||
|
||||
/* redefine pointers as data start at p */
|
||||
|
@ -283,14 +198,11 @@ struct _matrix_iter
|
|||
public:
|
||||
_matrix_iter(_TPtr base, int ds, bool r)
|
||||
{
|
||||
ptr = base; d_size = ds; real = r;
|
||||
ptr = base;
|
||||
d_size = ds;
|
||||
real = r;
|
||||
}
|
||||
virtual ~_matrix_iter() = default;
|
||||
_Self &
|
||||
operator=(const _Self &it)
|
||||
{
|
||||
ptr = it.ptr; d_size = it.d_size; real = it.real; return *this;
|
||||
}
|
||||
bool
|
||||
operator==(const _Self &it) const
|
||||
{
|
||||
|
@ -328,20 +240,18 @@ public:
|
|||
_Self &
|
||||
operator++() override
|
||||
{
|
||||
_Tparent::ptr++; row++; return *this;
|
||||
_Tparent::ptr++;
|
||||
row++;
|
||||
return *this;
|
||||
}
|
||||
_TRef
|
||||
b() const
|
||||
{
|
||||
if (_Tparent::real)
|
||||
{
|
||||
return *(_Tparent::ptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
return *(_Tparent::ptr+_Tparent::d_size);
|
||||
}
|
||||
}
|
||||
int
|
||||
getRow() const
|
||||
{
|
||||
|
@ -363,20 +273,18 @@ public:
|
|||
_Self &
|
||||
operator++() override
|
||||
{
|
||||
_Tparent::ptr += _Tparent::d_size; col++; return *this;
|
||||
_Tparent::ptr += _Tparent::d_size;
|
||||
col++;
|
||||
return *this;
|
||||
}
|
||||
virtual _TRef
|
||||
b() const
|
||||
{
|
||||
if (_Tparent::real)
|
||||
{
|
||||
return *(_Tparent::ptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
return *(_Tparent::ptr+1);
|
||||
}
|
||||
}
|
||||
int
|
||||
getCol() const
|
||||
{
|
||||
|
@ -387,6 +295,12 @@ public:
|
|||
class SchurDecomp;
|
||||
class SchurDecompZero;
|
||||
|
||||
/* Represents an upper quasi-triangular matrix.
|
||||
All the elements are stored in the SqSylvMatrix super-class.
|
||||
Additionally, a list of the diagonal blocks (1x1 or 2x2), is stored in the
|
||||
"diagonal" member, in order to optimize some operations (where the matrix is
|
||||
seen as an upper-triangular matrix, plus sub-diagonal elements of the 2x2
|
||||
diagonal blocks) */
|
||||
class QuasiTriangular : public SqSylvMatrix
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -19,9 +19,7 @@ SchurDecompEig::bubbleEigen(diag_iter from, diag_iter to)
|
|||
{
|
||||
diag_iter runm = run;
|
||||
if (!tryToSwap(run, runm) && runm == to)
|
||||
{
|
||||
++to;
|
||||
}
|
||||
else
|
||||
{
|
||||
// bubble all eigenvalues from runm(incl.) to run(excl.),
|
||||
|
|
|
@ -120,10 +120,8 @@ SimilarityDecomp::diagonalize(double norm)
|
|||
++end;
|
||||
}
|
||||
else
|
||||
{
|
||||
bringGuiltyBlock(start, end); // moves with end
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
#include <dynblas.h>
|
||||
#include <dynlapack.h>
|
||||
|
||||
#include <cstring>
|
||||
#include <cmath>
|
||||
#include <vector>
|
||||
|
||||
|
@ -102,9 +101,7 @@ SylvMatrix::eliminateLeft(int row, int col, Vector &x)
|
|||
get(row, col) = 0.0;
|
||||
double mult = e/d;
|
||||
for (int i = col + 1; i < numCols(); i++)
|
||||
{
|
||||
get(row, i) = get(row, i) - mult*get(col, i);
|
||||
}
|
||||
x[row] = x[row] - mult*x[col];
|
||||
}
|
||||
else if (std::abs(e) > std::abs(d))
|
||||
|
@ -137,9 +134,7 @@ SylvMatrix::eliminateRight(int row, int col, Vector &x)
|
|||
get(row, col) = 0.0;
|
||||
double mult = e/d;
|
||||
for (int i = 0; i < row; i++)
|
||||
{
|
||||
get(i, col) = get(i, col) - mult*get(i, row);
|
||||
}
|
||||
x[col] = x[col] - mult*x[row];
|
||||
}
|
||||
else if (std::abs(e) > std::abs(d))
|
||||
|
|
|
@ -39,6 +39,10 @@ public:
|
|||
: GeneralMatrix(a, b)
|
||||
{
|
||||
}
|
||||
SylvMatrix(const SylvMatrix &m) = default;
|
||||
SylvMatrix(SylvMatrix &&m) = default;
|
||||
SylvMatrix &operator=(const SylvMatrix &m) = default;
|
||||
SylvMatrix &operator=(SylvMatrix &&m) = default;
|
||||
|
||||
/* this = |I 0|* this
|
||||
|0 m| */
|
||||
|
@ -70,6 +74,7 @@ public:
|
|||
{
|
||||
}
|
||||
SqSylvMatrix(const SqSylvMatrix &m) = default;
|
||||
SqSylvMatrix(SqSylvMatrix &&m) = default;
|
||||
SqSylvMatrix(const GeneralMatrix &m, int i, int j, int nrows)
|
||||
: SylvMatrix(m, i, j, nrows, nrows)
|
||||
{
|
||||
|
@ -79,12 +84,8 @@ public:
|
|||
{
|
||||
}
|
||||
SqSylvMatrix(const GeneralMatrix &a, const GeneralMatrix &b);
|
||||
SqSylvMatrix &
|
||||
operator=(const SqSylvMatrix &m)
|
||||
{
|
||||
GeneralMatrix::operator=(m);
|
||||
return *this;
|
||||
}
|
||||
SqSylvMatrix &operator=(const SqSylvMatrix &m) = default;
|
||||
SqSylvMatrix &operator=(SqSylvMatrix &&m) = default;
|
||||
/* x = (this \otimes this..\otimes this)*d */
|
||||
void multVecKron(KronVector &x, const ConstKronVector &d) const;
|
||||
/* x = (this' \otimes this'..\otimes this')*d */
|
||||
|
|
|
@ -29,7 +29,7 @@ SylvParams::print(std::ostream &fdesc, const std::string &prefix) const
|
|||
f_largest.print(fdesc, prefix, "largest block in F ");
|
||||
f_zeros.print(fdesc, prefix, "num zeros in F ");
|
||||
f_offdiag.print(fdesc, prefix, "num offdiag in F ");
|
||||
if (*method == iter)
|
||||
if (*method == solve_method::iter)
|
||||
{
|
||||
converged.print(fdesc, prefix, "converged ");
|
||||
convergence_tol.print(fdesc, prefix, "convergence tol. ");
|
||||
|
@ -52,57 +52,57 @@ void
|
|||
SylvParams::setArrayNames(int &num, const char **names) const
|
||||
{
|
||||
num = 0;
|
||||
if (method.getStatus() != undef)
|
||||
if (method.getStatus() != status::undef)
|
||||
names[num++] = "method";
|
||||
if (convergence_tol.getStatus() != undef)
|
||||
if (convergence_tol.getStatus() != status::undef)
|
||||
names[num++] = "convergence_tol";
|
||||
if (max_num_iter.getStatus() != undef)
|
||||
if (max_num_iter.getStatus() != status::undef)
|
||||
names[num++] = "max_num_iter";
|
||||
if (bs_norm.getStatus() != undef)
|
||||
if (bs_norm.getStatus() != status::undef)
|
||||
names[num++] = "bs_norm";
|
||||
if (converged.getStatus() != undef)
|
||||
if (converged.getStatus() != status::undef)
|
||||
names[num++] = "converged";
|
||||
if (iter_last_norm.getStatus() != undef)
|
||||
if (iter_last_norm.getStatus() != status::undef)
|
||||
names[num++] = "iter_last_norm";
|
||||
if (num_iter.getStatus() != undef)
|
||||
if (num_iter.getStatus() != status::undef)
|
||||
names[num++] = "num_iter";
|
||||
if (f_err1.getStatus() != undef)
|
||||
if (f_err1.getStatus() != status::undef)
|
||||
names[num++] = "f_err1";
|
||||
if (f_errI.getStatus() != undef)
|
||||
if (f_errI.getStatus() != status::undef)
|
||||
names[num++] = "f_errI";
|
||||
if (viv_err1.getStatus() != undef)
|
||||
if (viv_err1.getStatus() != status::undef)
|
||||
names[num++] = "viv_err1";
|
||||
if (viv_errI.getStatus() != undef)
|
||||
if (viv_errI.getStatus() != status::undef)
|
||||
names[num++] = "viv_errI";
|
||||
if (ivv_err1.getStatus() != undef)
|
||||
if (ivv_err1.getStatus() != status::undef)
|
||||
names[num++] = "ivv_err1";
|
||||
if (ivv_errI.getStatus() != undef)
|
||||
if (ivv_errI.getStatus() != status::undef)
|
||||
names[num++] = "ivv_errI";
|
||||
if (f_blocks.getStatus() != undef)
|
||||
if (f_blocks.getStatus() != status::undef)
|
||||
names[num++] = "f_blocks";
|
||||
if (f_largest.getStatus() != undef)
|
||||
if (f_largest.getStatus() != status::undef)
|
||||
names[num++] = "f_largest";
|
||||
if (f_zeros.getStatus() != undef)
|
||||
if (f_zeros.getStatus() != status::undef)
|
||||
names[num++] = "f_zeros";
|
||||
if (f_offdiag.getStatus() != undef)
|
||||
if (f_offdiag.getStatus() != status::undef)
|
||||
names[num++] = "f_offdiag";
|
||||
if (rcondA1.getStatus() != undef)
|
||||
if (rcondA1.getStatus() != status::undef)
|
||||
names[num++] = "rcondA1";
|
||||
if (rcondAI.getStatus() != undef)
|
||||
if (rcondAI.getStatus() != status::undef)
|
||||
names[num++] = "rcondAI";
|
||||
if (eig_min.getStatus() != undef)
|
||||
if (eig_min.getStatus() != status::undef)
|
||||
names[num++] = "eig_min";
|
||||
if (mat_err1.getStatus() != undef)
|
||||
if (mat_err1.getStatus() != status::undef)
|
||||
names[num++] = "mat_err1";
|
||||
if (mat_errI.getStatus() != undef)
|
||||
if (mat_errI.getStatus() != status::undef)
|
||||
names[num++] = "mat_errI";
|
||||
if (mat_errF.getStatus() != undef)
|
||||
if (mat_errF.getStatus() != status::undef)
|
||||
names[num++] = "mat_errF";
|
||||
if (vec_err1.getStatus() != undef)
|
||||
if (vec_err1.getStatus() != status::undef)
|
||||
names[num++] = "vec_err1";
|
||||
if (vec_errI.getStatus() != undef)
|
||||
if (vec_errI.getStatus() != status::undef)
|
||||
names[num++] = "vec_errI";
|
||||
if (cpu_time.getStatus() != undef)
|
||||
if (cpu_time.getStatus() != status::undef)
|
||||
names[num++] = "cpu_time";
|
||||
}
|
||||
|
||||
|
@ -133,7 +133,7 @@ SylvParams::BoolParamItem::createMatlabArray() const
|
|||
mxArray *
|
||||
SylvParams::MethodParamItem::createMatlabArray() const
|
||||
{
|
||||
if (value == iter)
|
||||
if (value == solve_method::iter)
|
||||
return mxCreateString("iterative");
|
||||
else
|
||||
return mxCreateString("recursive");
|
||||
|
@ -149,57 +149,57 @@ SylvParams::createStructArray() const
|
|||
mxArray *const res = mxCreateStructArray(2, dims, num, names);
|
||||
|
||||
int i = 0;
|
||||
if (method.getStatus() != undef)
|
||||
if (method.getStatus() != status::undef)
|
||||
mxSetFieldByNumber(res, 0, i++, method.createMatlabArray());
|
||||
if (convergence_tol.getStatus() != undef)
|
||||
if (convergence_tol.getStatus() != status::undef)
|
||||
mxSetFieldByNumber(res, 0, i++, convergence_tol.createMatlabArray());
|
||||
if (max_num_iter.getStatus() != undef)
|
||||
if (max_num_iter.getStatus() != status::undef)
|
||||
mxSetFieldByNumber(res, 0, i++, max_num_iter.createMatlabArray());
|
||||
if (bs_norm.getStatus() != undef)
|
||||
if (bs_norm.getStatus() != status::undef)
|
||||
mxSetFieldByNumber(res, 0, i++, bs_norm.createMatlabArray());
|
||||
if (converged.getStatus() != undef)
|
||||
if (converged.getStatus() != status::undef)
|
||||
mxSetFieldByNumber(res, 0, i++, converged.createMatlabArray());
|
||||
if (iter_last_norm.getStatus() != undef)
|
||||
if (iter_last_norm.getStatus() != status::undef)
|
||||
mxSetFieldByNumber(res, 0, i++, iter_last_norm.createMatlabArray());
|
||||
if (num_iter.getStatus() != undef)
|
||||
if (num_iter.getStatus() != status::undef)
|
||||
mxSetFieldByNumber(res, 0, i++, num_iter.createMatlabArray());
|
||||
if (f_err1.getStatus() != undef)
|
||||
if (f_err1.getStatus() != status::undef)
|
||||
mxSetFieldByNumber(res, 0, i++, f_err1.createMatlabArray());
|
||||
if (f_errI.getStatus() != undef)
|
||||
if (f_errI.getStatus() != status::undef)
|
||||
mxSetFieldByNumber(res, 0, i++, f_errI.createMatlabArray());
|
||||
if (viv_err1.getStatus() != undef)
|
||||
if (viv_err1.getStatus() != status::undef)
|
||||
mxSetFieldByNumber(res, 0, i++, viv_err1.createMatlabArray());
|
||||
if (viv_errI.getStatus() != undef)
|
||||
if (viv_errI.getStatus() != status::undef)
|
||||
mxSetFieldByNumber(res, 0, i++, viv_errI.createMatlabArray());
|
||||
if (ivv_err1.getStatus() != undef)
|
||||
if (ivv_err1.getStatus() != status::undef)
|
||||
mxSetFieldByNumber(res, 0, i++, ivv_err1.createMatlabArray());
|
||||
if (ivv_errI.getStatus() != undef)
|
||||
if (ivv_errI.getStatus() != status::undef)
|
||||
mxSetFieldByNumber(res, 0, i++, ivv_errI.createMatlabArray());
|
||||
if (f_blocks.getStatus() != undef)
|
||||
if (f_blocks.getStatus() != status::undef)
|
||||
mxSetFieldByNumber(res, 0, i++, f_blocks.createMatlabArray());
|
||||
if (f_largest.getStatus() != undef)
|
||||
if (f_largest.getStatus() != status::undef)
|
||||
mxSetFieldByNumber(res, 0, i++, f_largest.createMatlabArray());
|
||||
if (f_zeros.getStatus() != undef)
|
||||
if (f_zeros.getStatus() != status::undef)
|
||||
mxSetFieldByNumber(res, 0, i++, f_zeros.createMatlabArray());
|
||||
if (f_offdiag.getStatus() != undef)
|
||||
if (f_offdiag.getStatus() != status::undef)
|
||||
mxSetFieldByNumber(res, 0, i++, f_offdiag.createMatlabArray());
|
||||
if (rcondA1.getStatus() != undef)
|
||||
if (rcondA1.getStatus() != status::undef)
|
||||
mxSetFieldByNumber(res, 0, i++, rcondA1.createMatlabArray());
|
||||
if (rcondAI.getStatus() != undef)
|
||||
if (rcondAI.getStatus() != status::undef)
|
||||
mxSetFieldByNumber(res, 0, i++, rcondAI.createMatlabArray());
|
||||
if (eig_min.getStatus() != undef)
|
||||
if (eig_min.getStatus() != status::undef)
|
||||
mxSetFieldByNumber(res, 0, i++, eig_min.createMatlabArray());
|
||||
if (mat_err1.getStatus() != undef)
|
||||
if (mat_err1.getStatus() != status::undef)
|
||||
mxSetFieldByNumber(res, 0, i++, mat_err1.createMatlabArray());
|
||||
if (mat_errI.getStatus() != undef)
|
||||
if (mat_errI.getStatus() != status::undef)
|
||||
mxSetFieldByNumber(res, 0, i++, mat_errI.createMatlabArray());
|
||||
if (mat_errF.getStatus() != undef)
|
||||
if (mat_errF.getStatus() != status::undef)
|
||||
mxSetFieldByNumber(res, 0, i++, mat_errF.createMatlabArray());
|
||||
if (vec_err1.getStatus() != undef)
|
||||
if (vec_err1.getStatus() != status::undef)
|
||||
mxSetFieldByNumber(res, 0, i++, vec_err1.createMatlabArray());
|
||||
if (vec_errI.getStatus() != undef)
|
||||
if (vec_errI.getStatus() != status::undef)
|
||||
mxSetFieldByNumber(res, 0, i++, vec_errI.createMatlabArray());
|
||||
if (cpu_time.getStatus() != undef)
|
||||
if (cpu_time.getStatus() != status::undef)
|
||||
mxSetFieldByNumber(res, 0, i++, cpu_time.createMatlabArray());
|
||||
|
||||
return res;
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
# include <dynmex.h>
|
||||
#endif
|
||||
|
||||
typedef enum {def, changed, undef} status;
|
||||
enum class status {def, changed, undef};
|
||||
|
||||
template <class _Type>
|
||||
struct ParamItem
|
||||
|
@ -24,25 +24,21 @@ protected:
|
|||
public:
|
||||
ParamItem()
|
||||
{
|
||||
s = undef;
|
||||
s = status::undef;
|
||||
}
|
||||
ParamItem(_Type val)
|
||||
{
|
||||
value = val; s = def;
|
||||
}
|
||||
ParamItem(const _Self &item)
|
||||
{
|
||||
value = item.value; s = item.s;
|
||||
}
|
||||
_Self &
|
||||
operator=(const _Self &item)
|
||||
{
|
||||
value = item.value; s = item.s; return *this;
|
||||
value = val;
|
||||
s = status::def;
|
||||
}
|
||||
ParamItem(const _Self &item) = default;
|
||||
_Self &operator=(const _Self &item) = default;
|
||||
_Self &
|
||||
operator=(const _Type &val)
|
||||
{
|
||||
value = val; s = changed; return *this;
|
||||
value = val;
|
||||
s = status::changed;
|
||||
return *this;
|
||||
}
|
||||
_Type
|
||||
operator*() const
|
||||
|
@ -57,10 +53,10 @@ public:
|
|||
void
|
||||
print(std::ostream &out, const std::string &prefix, const std::string &str) const
|
||||
{
|
||||
if (s == undef)
|
||||
if (s == status::undef)
|
||||
return;
|
||||
out << prefix << str << "= " << value;
|
||||
if (s == def)
|
||||
if (s == status::def)
|
||||
out << " <default>";
|
||||
out << std::endl;
|
||||
}
|
||||
|
@ -69,7 +65,7 @@ public:
|
|||
class SylvParams
|
||||
{
|
||||
public:
|
||||
using solve_method = enum {iter, recurse};
|
||||
enum class solve_method {iter, recurse};
|
||||
|
||||
protected:
|
||||
class DoubleParamItem : public ParamItem<double>
|
||||
|
@ -184,7 +180,7 @@ public:
|
|||
DoubleParamItem cpu_time; // time of the job in CPU seconds
|
||||
|
||||
SylvParams(bool wc = false)
|
||||
: method(recurse), convergence_tol(1.e-30), max_num_iter(15),
|
||||
: method(solve_method::recurse), convergence_tol(1.e-30), max_num_iter(15),
|
||||
bs_norm(1.3), want_check(wc)
|
||||
{
|
||||
}
|
||||
|
@ -206,10 +202,10 @@ operator<<(std::ostream &out, SylvParams::solve_method m)
|
|||
{
|
||||
switch (m)
|
||||
{
|
||||
case SylvParams::iter:
|
||||
case SylvParams::solve_method::iter:
|
||||
out << "iterative";
|
||||
break;
|
||||
case SylvParams::recurse:
|
||||
case SylvParams::solve_method::recurse:
|
||||
out << "recurse (a.k.a. triangular)";
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -19,9 +19,6 @@ SymSchurDecomp::SymSchurDecomp(const ConstGeneralMatrix &mata)
|
|||
throw SYLV_MES_EXCEPTION("Matrix is not square in SymSchurDecomp constructor");
|
||||
|
||||
// prepare for dsyevr
|
||||
const char *jobz = "V";
|
||||
const char *range = "A";
|
||||
const char *uplo = "U";
|
||||
lapack_int n = mata.numRows();
|
||||
GeneralMatrix tmpa(mata);
|
||||
double *a = tmpa.base();
|
||||
|
@ -45,7 +42,7 @@ SymSchurDecomp::SymSchurDecomp(const ConstGeneralMatrix &mata)
|
|||
lapack_int info;
|
||||
|
||||
// query for lwork and liwork
|
||||
dsyevr(jobz, range, uplo, &n, a, &lda, vl, vu, il, iu, &abstol,
|
||||
dsyevr("V", "A", "U", &n, a, &lda, vl, vu, il, iu, &abstol,
|
||||
&m, w, z, &ldz, isuppz.data(), &tmpwork, &lwork, &tmpiwork, &liwork, &info);
|
||||
lwork = (int) tmpwork;
|
||||
liwork = tmpiwork;
|
||||
|
@ -54,7 +51,7 @@ SymSchurDecomp::SymSchurDecomp(const ConstGeneralMatrix &mata)
|
|||
std::vector<lapack_int> iwork(liwork);
|
||||
|
||||
// do the calculation
|
||||
dsyevr(jobz, range, uplo, &n, a, &lda, vl, vu, il, iu, &abstol,
|
||||
dsyevr("V", "A", "U", &n, a, &lda, vl, vu, il, iu, &abstol,
|
||||
&m, w, z, &ldz, isuppz.data(), work.data(), &lwork, iwork.data(), &liwork, &info);
|
||||
|
||||
if (info < 0)
|
||||
|
|
|
@ -48,7 +48,7 @@ TriangularSylvester::solve(SylvParams &pars, KronVector &d) const
|
|||
{
|
||||
double eig_min = 1e30;
|
||||
solvi(1., d, eig_min);
|
||||
pars.eig_min = sqrt(eig_min);
|
||||
pars.eig_min = std::sqrt(eig_min);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -122,7 +122,7 @@ TriangularSylvester::solviRealAndEliminate(double r, const_diag_iter di,
|
|||
double f = *((*di).getAlpha());
|
||||
KronVector dj(d, jbar);
|
||||
// solve system
|
||||
if (abs(r*f) > diag_zero)
|
||||
if (std::abs(r*f) > diag_zero)
|
||||
solvi(r*f, dj, eig_min);
|
||||
// calculate y
|
||||
KronVector y((const KronVector &)dj);
|
||||
|
@ -277,8 +277,8 @@ TriangularSylvester::solviipComplex(double alpha, double betas, double gamma,
|
|||
KronVector d2tmp(d2);
|
||||
quaEval(alpha, betas, gamma, delta1, delta2,
|
||||
d1, d2, d1tmp, d2tmp);
|
||||
double delta = sqrt(delta1*delta2);
|
||||
double beta = sqrt(betas);
|
||||
double delta = std::sqrt(delta1*delta2);
|
||||
double beta = std::sqrt(betas);
|
||||
double a1 = alpha*gamma - beta*delta;
|
||||
double b1 = alpha*delta + gamma*beta;
|
||||
double a2 = alpha*gamma + beta*delta;
|
||||
|
|
|
@ -14,8 +14,6 @@
|
|||
#include <iostream>
|
||||
#include <iomanip>
|
||||
|
||||
using namespace std;
|
||||
|
||||
ZeroPad zero_pad;
|
||||
|
||||
Vector::Vector(const Vector &v)
|
||||
|
@ -25,9 +23,9 @@ Vector::Vector(const Vector &v)
|
|||
}
|
||||
|
||||
Vector::Vector(const ConstVector &v)
|
||||
: len(v.length()), data{new double[len], [](double *arr) { delete[] arr; }}
|
||||
: len(v.len), data{new double[len], [](double *arr) { delete[] arr; }}
|
||||
{
|
||||
copy(v.base(), v.skip());
|
||||
copy(v.base(), v.s);
|
||||
}
|
||||
|
||||
Vector &
|
||||
|
@ -38,17 +36,13 @@ Vector::operator=(const Vector &v)
|
|||
|
||||
if (v.len != len)
|
||||
throw SYLV_MES_EXCEPTION("Attempt to assign vectors with different lengths.");
|
||||
/*
|
||||
|
||||
if (s == v.s
|
||||
&& (data <= v.data && v.data < data+len*s
|
||||
|| v.data <= data && data < v.data+v.len*v.s)
|
||||
&& (data-v.data) % s == 0)
|
||||
{
|
||||
std::cout << "this destroy=" << destroy << ", v destroy=" << v.destroy
|
||||
<< ", data-v.data=" << (unsigned long) (data-v.data)
|
||||
<< ", len=" << len << std::endl;
|
||||
&& (base() <= v.base() && v.base() < base()+len*s
|
||||
|| v.base() <= base() && base() < v.base()+v.len*v.s)
|
||||
&& (base()-v.base()) % s == 0)
|
||||
throw SYLV_MES_EXCEPTION("Attempt to assign overlapping vectors.");
|
||||
} */
|
||||
|
||||
copy(v.base(), v.s);
|
||||
return *this;
|
||||
}
|
||||
|
@ -65,16 +59,15 @@ Vector::operator=(Vector &&v)
|
|||
Vector &
|
||||
Vector::operator=(const ConstVector &v)
|
||||
{
|
||||
if (v.length() != len)
|
||||
if (v.len != len)
|
||||
throw SYLV_MES_EXCEPTION("Attempt to assign vectors with different lengths.");
|
||||
/*
|
||||
if (v.skip() == 1 && skip() == 1 && (
|
||||
(base() < v.base() + v.length() && base() >= v.base())
|
||||
|| (base() + length() < v.base() + v.length()
|
||||
&& base() + length() > v.base())))
|
||||
if (s == v.s
|
||||
&& (base() <= v.base() && v.base() < base()+len*s
|
||||
|| v.base() <= base() && base() < v.base()+v.len*v.s)
|
||||
&& (base()-v.base()) % s == 0)
|
||||
throw SYLV_MES_EXCEPTION("Attempt to assign overlapping vectors.");
|
||||
*/
|
||||
copy(v.base(), v.skip());
|
||||
|
||||
copy(v.base(), v.s);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -210,7 +203,7 @@ void
|
|||
Vector::add(double r, const ConstVector &v)
|
||||
{
|
||||
blas_int n = len;
|
||||
blas_int incx = v.skip();
|
||||
blas_int incx = v.s;
|
||||
blas_int incy = s;
|
||||
daxpy(&n, &r, v.base(), &incx, base(), &incy);
|
||||
}
|
||||
|
@ -225,7 +218,7 @@ void
|
|||
Vector::addComplex(const std::complex<double> &z, const ConstVector &v)
|
||||
{
|
||||
blas_int n = len/2;
|
||||
blas_int incx = v.skip();
|
||||
blas_int incx = v.s;
|
||||
blas_int incy = s;
|
||||
zaxpy(&n, reinterpret_cast<const double(&)[2]>(z), v.base(), &incx, base(), &incy);
|
||||
}
|
||||
|
@ -374,8 +367,8 @@ ConstVector::getMax() const
|
|||
{
|
||||
double r = 0;
|
||||
for (int i = 0; i < len; i++)
|
||||
if (abs(operator[](i)) > r)
|
||||
r = abs(operator[](i));
|
||||
if (std::abs(operator[](i)) > r)
|
||||
r = std::abs(operator[](i));
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -384,7 +377,7 @@ ConstVector::getNorm1() const
|
|||
{
|
||||
double norm = 0.0;
|
||||
for (int i = 0; i < len; i++)
|
||||
norm += abs(operator[](i));
|
||||
norm += std::abs(operator[](i));
|
||||
return norm;
|
||||
}
|
||||
|
||||
|
@ -403,7 +396,7 @@ bool
|
|||
ConstVector::isFinite() const
|
||||
{
|
||||
int i = 0;
|
||||
while (i < len && isfinite(operator[](i)))
|
||||
while (i < len && std::isfinite(operator[](i)))
|
||||
i++;
|
||||
return i == len;
|
||||
}
|
||||
|
|
|
@ -140,6 +140,7 @@ class ConstGeneralMatrix;
|
|||
|
||||
class ConstVector
|
||||
{
|
||||
friend class Vector;
|
||||
protected:
|
||||
int len;
|
||||
int off{0}; // offset to double* pointer
|
||||
|
|
|
@ -4,70 +4,52 @@
|
|||
|
||||
#include "MMMatrix.hh"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
#include <iomanip>
|
||||
|
||||
MMMatrixIn::MMMatrixIn(const char *fname)
|
||||
MMMatrixIn::MMMatrixIn(const std::string &fname)
|
||||
{
|
||||
FILE *fd;
|
||||
if (nullptr == (fd = fopen(fname, "r")))
|
||||
throw MMException(string("Cannot open file ")+fname+" for reading\n");
|
||||
std::ifstream fd{fname};
|
||||
if (fd.fail())
|
||||
throw MMException("Cannot open file "+fname+" for reading\n");
|
||||
|
||||
char buffer[1000];
|
||||
// jump over initial comments
|
||||
while (fgets(buffer, 1000, fd) && strncmp(buffer, "%%", 2))
|
||||
{
|
||||
}
|
||||
while (fd.peek() == '%')
|
||||
fd.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
|
||||
|
||||
// read in number of rows and cols
|
||||
if (!fgets(buffer, 1000, fd))
|
||||
throw MMException(string("Cannot read rows and cols while reading ")+fname+"\n");
|
||||
if (2 != sscanf(buffer, "%d %d", &rows, &cols))
|
||||
fd >> rows >> cols;
|
||||
if (fd.fail())
|
||||
throw MMException("Couldn't parse rows and cols\n");
|
||||
// read in data
|
||||
data = std::shared_ptr<double>(static_cast<double *>(operator new[](rows*cols*sizeof(double))), [](double *arr) { operator delete[](static_cast<void *>(arr)); });
|
||||
int len = rows*cols;
|
||||
int i = 0;
|
||||
while (fgets(buffer, 1000, fd) && i < len)
|
||||
while (!fd.eof() && i < len)
|
||||
{
|
||||
if (1 != sscanf(buffer, "%lf", const_cast<double *>(data.get())+i))
|
||||
throw MMException(string("Couldn't parse float number ")+buffer+"\n");
|
||||
fd >> data.get()[i];
|
||||
if (fd.fail())
|
||||
throw MMException("Couldn't parse float number\n");
|
||||
i++;
|
||||
}
|
||||
if (i < len)
|
||||
{
|
||||
char mes[1000];
|
||||
sprintf(mes, "Couldn't read all %d lines, read %d so far\n", len, i);
|
||||
throw MMException(mes);
|
||||
}
|
||||
fclose(fd);
|
||||
throw MMException("Couldn't read all " + std::to_string(len) + " elements, read "
|
||||
+ std::to_string(i) + " so far\n");
|
||||
fd.close();
|
||||
}
|
||||
|
||||
void
|
||||
MMMatrixOut::write(const char *fname, int rows, int cols, const double *data)
|
||||
MMMatrixOut::write(const std::string &fname, const GeneralMatrix &m)
|
||||
{
|
||||
FILE *fd;
|
||||
if (nullptr == (fd = fopen(fname, "w")))
|
||||
throw MMException(string("Cannot open file ")+fname+" for writing\n");
|
||||
std::ofstream fd{fname, std::ios::out | std::ios::trunc};
|
||||
if (fd.fail())
|
||||
throw MMException("Cannot open file "+fname+" for writing\n");
|
||||
|
||||
if (0 > fprintf(fd, "%%%%MatrixMarket matrix array real general\n"))
|
||||
throw MMException(string("Output error when writing file ")+fname);
|
||||
if (0 > fprintf(fd, "%d %d\n", rows, cols))
|
||||
throw MMException(string("Output error when writing file ")+fname);
|
||||
int running = 0;
|
||||
for (int i = 0; i < cols; i++)
|
||||
{
|
||||
for (int j = 0; j < rows; j++)
|
||||
{
|
||||
if (0 > fprintf(fd, "%40.35g\n", data[running]))
|
||||
throw MMException(string("Output error when writing file ")+fname);
|
||||
running++;
|
||||
}
|
||||
}
|
||||
fclose(fd);
|
||||
}
|
||||
|
||||
void
|
||||
MMMatrixOut::write(const char *fname, const GeneralMatrix &m)
|
||||
{
|
||||
write(fname, m.numRows(), m.numCols(), m.base());
|
||||
fd << "%%%%MatrixMarket matrix array real general" << std::endl
|
||||
<< m.numRows() << ' ' << m.numCols() << std::endl
|
||||
<< std::setprecision(35);
|
||||
for (int i = 0; i < m.numCols(); i++)
|
||||
for (int j = 0; j < m.numRows(); j++)
|
||||
fd << std::setw(40) << m.get(i, j);
|
||||
fd.close();
|
||||
}
|
||||
|
|
|
@ -12,22 +12,17 @@
|
|||
#include <utility>
|
||||
#include <memory>
|
||||
|
||||
using namespace std;
|
||||
|
||||
class MMException : public MallocAllocator
|
||||
{
|
||||
string message;
|
||||
std::string message;
|
||||
public:
|
||||
MMException(string mes) : message(std::move(mes))
|
||||
MMException(std::string mes) : message(std::move(mes))
|
||||
{
|
||||
}
|
||||
MMException(const char *mes) : message(mes)
|
||||
{
|
||||
}
|
||||
const char *
|
||||
std::string
|
||||
getMessage() const
|
||||
{
|
||||
return message.data();
|
||||
return message;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -37,7 +32,7 @@ class MMMatrixIn : public MallocAllocator
|
|||
int rows;
|
||||
int cols;
|
||||
public:
|
||||
MMMatrixIn(const char *fname);
|
||||
MMMatrixIn(const std::string &fname);
|
||||
~MMMatrixIn() = default;
|
||||
Vector
|
||||
getData() const
|
||||
|
@ -64,8 +59,7 @@ public:
|
|||
class MMMatrixOut : public MallocAllocator
|
||||
{
|
||||
public:
|
||||
static void write(const char *fname, int rows, int cols, const double *data);
|
||||
static void write(const char *fname, const GeneralMatrix &m);
|
||||
static void write(const std::string &fname, const GeneralMatrix &m);
|
||||
};
|
||||
|
||||
#endif /* MM_MATRIX_H */
|
||||
|
|
|
@ -18,76 +18,65 @@
|
|||
|
||||
#include "MMMatrix.hh"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <ctime>
|
||||
|
||||
#include <cmath>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <memory>
|
||||
|
||||
class TestRunnable : public MallocAllocator
|
||||
{
|
||||
char name[100];
|
||||
static double eps_norm;
|
||||
public:
|
||||
TestRunnable(const char *n)
|
||||
const std::string name;
|
||||
static constexpr double eps_norm = 1.0e-10;
|
||||
TestRunnable(std::string n) : name(std::move(n))
|
||||
{
|
||||
strncpy(name, n, 100);
|
||||
}
|
||||
virtual ~TestRunnable() = default;
|
||||
bool test() const;
|
||||
virtual bool run() const = 0;
|
||||
const char *
|
||||
getName() const
|
||||
{
|
||||
return name;
|
||||
}
|
||||
protected:
|
||||
// declaration of auxiliary static methods
|
||||
static bool quasi_solve(bool trans, const char *mname, const char *vname);
|
||||
static bool mult_kron(bool trans, const char *mname, const char *vname,
|
||||
const char *cname, int m, int n, int depth);
|
||||
static bool level_kron(bool trans, const char *mname, const char *vname,
|
||||
const char *cname, int level, int m, int n, int depth);
|
||||
static bool kron_power(const char *m1name, const char *m2name, const char *vname,
|
||||
const char *cname, int m, int n, int depth);
|
||||
static bool lin_eval(const char *m1name, const char *m2name, const char *vname,
|
||||
const char *cname, int m, int n, int depth,
|
||||
static bool quasi_solve(bool trans, const std::string &mname, const std::string &vname);
|
||||
static bool mult_kron(bool trans, const std::string &mname, const std::string &vname,
|
||||
const std::string &cname, int m, int n, int depth);
|
||||
static bool level_kron(bool trans, const std::string &mname, const std::string &vname,
|
||||
const std::string &cname, int level, int m, int n, int depth);
|
||||
static bool kron_power(const std::string &m1name, const std::string &m2name, const std::string &vname,
|
||||
const std::string &cname, int m, int n, int depth);
|
||||
static bool lin_eval(const std::string &m1name, const std::string &m2name, const std::string &vname,
|
||||
const std::string &cname, int m, int n, int depth,
|
||||
double alpha, double beta1, double beta2);
|
||||
static bool qua_eval(const char *m1name, const char *m2name, const char *vname,
|
||||
const char *cname, int m, int n, int depth,
|
||||
static bool qua_eval(const std::string &m1name, const std::string &m2name, const std::string &vname,
|
||||
const std::string &cname, int m, int n, int depth,
|
||||
double alpha, double betas, double gamma,
|
||||
double delta1, double delta2);
|
||||
static bool tri_sylv(const char *m1name, const char *m2name, const char *vname,
|
||||
static bool tri_sylv(const std::string &m1name, const std::string &m2name, const std::string &vname,
|
||||
int m, int n, int depth);
|
||||
static bool gen_sylv(const char *aname, const char *bname, const char *cname,
|
||||
const char *dname, int m, int n, int order);
|
||||
static bool eig_bubble(const char *aname, int from, int to);
|
||||
static bool block_diag(const char *aname, double log10norm = 3.0);
|
||||
static bool iter_sylv(const char *m1name, const char *m2name, const char *vname,
|
||||
static bool gen_sylv(const std::string &aname, const std::string &bname, const std::string &cname,
|
||||
const std::string &dname, int m, int n, int order);
|
||||
static bool eig_bubble(const std::string &aname, int from, int to);
|
||||
static bool block_diag(const std::string &aname, double log10norm = 3.0);
|
||||
static bool iter_sylv(const std::string &m1name, const std::string &m2name, const std::string &vname,
|
||||
int m, int n, int depth);
|
||||
};
|
||||
|
||||
double TestRunnable::eps_norm = 1.0e-10;
|
||||
|
||||
bool
|
||||
TestRunnable::test() const
|
||||
{
|
||||
printf("Running test <%s>\n", name);
|
||||
std::cout << "Running test <" << name << '>' << std::endl;
|
||||
clock_t start = clock();
|
||||
bool passed = run();
|
||||
clock_t end = clock();
|
||||
printf("CPU time %8.4g (CPU seconds)..................",
|
||||
((double) (end-start))/CLOCKS_PER_SEC);
|
||||
std::cout << "CPU time " << ((double) (end-start))/CLOCKS_PER_SEC << " (CPU seconds)..................";
|
||||
if (passed)
|
||||
{
|
||||
printf("passed\n\n");
|
||||
return passed;
|
||||
}
|
||||
std::cout << "passed";
|
||||
else
|
||||
{
|
||||
printf("FAILED\n\n");
|
||||
std::cout << "FAILED";
|
||||
std::cout << std::endl << std::endl;
|
||||
return passed;
|
||||
}
|
||||
}
|
||||
|
||||
/**********************************************************/
|
||||
|
@ -95,27 +84,27 @@ TestRunnable::test() const
|
|||
/**********************************************************/
|
||||
|
||||
bool
|
||||
TestRunnable::quasi_solve(bool trans, const char *mname, const char *vname)
|
||||
TestRunnable::quasi_solve(bool trans, const std::string &mname, const std::string &vname)
|
||||
{
|
||||
MMMatrixIn mmt(mname);
|
||||
MMMatrixIn mmv(vname);
|
||||
|
||||
SylvMemoryDriver memdriver(1, mmt.row(), mmt.row(), 1);
|
||||
QuasiTriangular *t;
|
||||
QuasiTriangular *tsave;
|
||||
std::unique_ptr<QuasiTriangular> t;
|
||||
std::unique_ptr<QuasiTriangular> tsave;
|
||||
if (mmt.row() == mmt.col())
|
||||
{
|
||||
t = new QuasiTriangular(mmt.getData(), mmt.row());
|
||||
tsave = new QuasiTriangular(*t);
|
||||
t = std::make_unique<QuasiTriangular>(mmt.getData(), mmt.row());
|
||||
tsave = std::make_unique<QuasiTriangular>(*t);
|
||||
}
|
||||
else if (mmt.row() > mmt.col())
|
||||
{
|
||||
t = new QuasiTriangularZero(mmt.row()-mmt.col(), mmt.getData(), mmt.col());
|
||||
tsave = new QuasiTriangularZero((const QuasiTriangularZero &) *t);
|
||||
t = std::make_unique<QuasiTriangularZero>(mmt.row()-mmt.col(), mmt.getData(), mmt.col());
|
||||
tsave = std::make_unique<QuasiTriangularZero>((const QuasiTriangularZero &) *t);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf(" Wrong quasi triangular dimensions, rows must be >= cols.\n");
|
||||
std::cout << " Wrong quasi triangular dimensions, rows must be >= cols.\n";
|
||||
return false;
|
||||
}
|
||||
ConstVector v{mmv.getData()};
|
||||
|
@ -125,24 +114,22 @@ TestRunnable::quasi_solve(bool trans, const char *mname, const char *vname)
|
|||
t->solveTrans(x, v, eig_min);
|
||||
else
|
||||
t->solve(x, v, eig_min);
|
||||
printf("eig_min = %8.4g\n", eig_min);
|
||||
std::cout << "eig_min = " << eig_min << std::endl;
|
||||
Vector xx(v.length());
|
||||
if (trans)
|
||||
tsave->multVecTrans(xx, ConstVector(x));
|
||||
else
|
||||
tsave->multVec(xx, ConstVector(x));
|
||||
delete tsave;
|
||||
delete t;
|
||||
xx.add(-1.0, v);
|
||||
xx.add(1.0, x);
|
||||
double norm = xx.getNorm();
|
||||
printf("\terror norm = %8.4g\n", norm);
|
||||
std::cout << "\terror norm = " << norm << std::endl;
|
||||
return (norm < eps_norm);
|
||||
}
|
||||
|
||||
bool
|
||||
TestRunnable::mult_kron(bool trans, const char *mname, const char *vname,
|
||||
const char *cname, int m, int n, int depth)
|
||||
TestRunnable::mult_kron(bool trans, const std::string &mname, const std::string &vname,
|
||||
const std::string &cname, int m, int n, int depth)
|
||||
{
|
||||
MMMatrixIn mmt(mname);
|
||||
MMMatrixIn mmv(vname);
|
||||
|
@ -153,7 +140,10 @@ TestRunnable::mult_kron(bool trans, const char *mname, const char *vname,
|
|||
|| mmv.row() != length
|
||||
|| mmc.row() != length)
|
||||
{
|
||||
printf(" Incompatible sizes for krom mult action, len=%d, matrow=%d, m=%d, vrow=%d, crow=%d \n", length, mmt.row(), m, mmv.row(), mmc.row());
|
||||
std::cout << " Incompatible sizes for kron mult action, len=" << length
|
||||
<< ", matrow=" << mmt.row() << ", m=" << m
|
||||
<< ", vrow=" << mmv.row() << ", crow=" << mmc.row()
|
||||
<< std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -169,13 +159,13 @@ TestRunnable::mult_kron(bool trans, const char *mname, const char *vname,
|
|||
t.multKron(v);
|
||||
c.add(-1.0, v);
|
||||
double norm = c.getNorm();
|
||||
printf("\terror norm = %8.4g\n", norm);
|
||||
std::cout << "\terror norm = " << norm << std::endl;
|
||||
return (norm < eps_norm);
|
||||
}
|
||||
|
||||
bool
|
||||
TestRunnable::level_kron(bool trans, const char *mname, const char *vname,
|
||||
const char *cname, int level, int m, int n, int depth)
|
||||
TestRunnable::level_kron(bool trans, const std::string &mname, const std::string &vname,
|
||||
const std::string &cname, int level, int m, int n, int depth)
|
||||
{
|
||||
MMMatrixIn mmt(mname);
|
||||
MMMatrixIn mmv(vname);
|
||||
|
@ -187,7 +177,10 @@ TestRunnable::level_kron(bool trans, const char *mname, const char *vname,
|
|||
|| mmv.row() != length
|
||||
|| mmc.row() != length)
|
||||
{
|
||||
printf(" Incompatible sizes for krom mult action, len=%d, matrow=%d, m=%d, n=%d, vrow=%d, crow=%d \n", length, mmt.row(), m, n, mmv.row(), mmc.row());
|
||||
std::cout << " Incompatible sizes for kron mult action, len=" << length
|
||||
<< ", matrow=" << mmt.row() << ", m=" << m << ", n=" << n
|
||||
<< ", vrow=" << mmv.row() << ", crow=" << mmc.row()
|
||||
<< std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -204,13 +197,13 @@ TestRunnable::level_kron(bool trans, const char *mname, const char *vname,
|
|||
KronUtils::multAtLevel(level, t, x);
|
||||
x.add(-1, c);
|
||||
double norm = x.getNorm();
|
||||
printf("\terror norm = %8.4g\n", norm);
|
||||
std::cout << "\terror norm = " << norm << std::endl;
|
||||
return (norm < eps_norm);
|
||||
}
|
||||
|
||||
bool
|
||||
TestRunnable::kron_power(const char *m1name, const char *m2name, const char *vname,
|
||||
const char *cname, int m, int n, int depth)
|
||||
TestRunnable::kron_power(const std::string &m1name, const std::string &m2name, const std::string &vname,
|
||||
const std::string &cname, int m, int n, int depth)
|
||||
{
|
||||
MMMatrixIn mmt1(m1name);
|
||||
MMMatrixIn mmt2(m2name);
|
||||
|
@ -223,7 +216,11 @@ TestRunnable::kron_power(const char *m1name, const char *m2name, const char *vna
|
|||
|| mmv.row() != length
|
||||
|| mmc.row() != length)
|
||||
{
|
||||
printf(" Incompatible sizes for krom power mult action, len=%d, row1=%d, row2=%d, m=%d, n=%d, vrow=%d, crow=%d \n", length, mmt1.row(), mmt2.row(), m, n, mmv.row(), mmc.row());
|
||||
std::cout << " Incompatible sizes for kron power mult action, len=" << length
|
||||
<< ", row1=" << mmt1.row() << ", row2=" << mmt2.row()
|
||||
<< ", m=" << m << ", n=" << n
|
||||
<< ", vrow=" << mmv.row() << ", crow=" << mmc.row()
|
||||
<< std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -240,13 +237,13 @@ TestRunnable::kron_power(const char *m1name, const char *m2name, const char *vna
|
|||
memdriver.setStackMode(false);
|
||||
x.add(-1, c);
|
||||
double norm = x.getNorm();
|
||||
printf("\terror norm = %8.4g\n", norm);
|
||||
std::cout << "\terror norm = " << norm << std::endl;
|
||||
return (norm < eps_norm);
|
||||
}
|
||||
|
||||
bool
|
||||
TestRunnable::lin_eval(const char *m1name, const char *m2name, const char *vname,
|
||||
const char *cname, int m, int n, int depth,
|
||||
TestRunnable::lin_eval(const std::string &m1name, const std::string &m2name, const std::string &vname,
|
||||
const std::string &cname, int m, int n, int depth,
|
||||
double alpha, double beta1, double beta2)
|
||||
{
|
||||
MMMatrixIn mmt1(m1name);
|
||||
|
@ -260,7 +257,11 @@ TestRunnable::lin_eval(const char *m1name, const char *m2name, const char *vname
|
|||
|| mmv.row() != 2*length
|
||||
|| mmc.row() != 2*length)
|
||||
{
|
||||
printf(" Incompatible sizes for lin eval action, len=%d, row1=%d, row2=%d, m=%d, n=%d, vrow=%d, crow=%d \n", length, mmt1.row(), mmt2.row(), m, n, mmv.row(), mmc.row());
|
||||
std::cout << " Incompatible sizes for lin eval action, len=" << length
|
||||
<< ", row1=" << mmt1.row() << ", row2=" << mmt2.row()
|
||||
<< ", m=" << m << ", n=" << n
|
||||
<< ", vrow=" << mmv.row() << ", crow=" << mmc.row()
|
||||
<< std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -285,13 +286,13 @@ TestRunnable::lin_eval(const char *m1name, const char *m2name, const char *vname
|
|||
x2.add(-1, c2);
|
||||
double norm1 = x1.getNorm();
|
||||
double norm2 = x2.getNorm();
|
||||
printf("\terror norm1 = %8.4g\n\terror norm2 = %8.4g\n", norm1, norm2);
|
||||
std::cout << "\terror norm1 = " << norm1 << "\n\terror norm2 = " << norm2 << '\n';
|
||||
return (norm1*norm1+norm2*norm2 < eps_norm*eps_norm);
|
||||
}
|
||||
|
||||
bool
|
||||
TestRunnable::qua_eval(const char *m1name, const char *m2name, const char *vname,
|
||||
const char *cname, int m, int n, int depth,
|
||||
TestRunnable::qua_eval(const std::string &m1name, const std::string &m2name, const std::string &vname,
|
||||
const std::string &cname, int m, int n, int depth,
|
||||
double alpha, double betas, double gamma,
|
||||
double delta1, double delta2)
|
||||
{
|
||||
|
@ -306,7 +307,11 @@ TestRunnable::qua_eval(const char *m1name, const char *m2name, const char *vname
|
|||
|| mmv.row() != 2*length
|
||||
|| mmc.row() != 2*length)
|
||||
{
|
||||
printf(" Incompatible sizes for qua eval action, len=%d, row1=%d, row2=%d, m=%d, n=%d, vrow=%d, crow=%d \n", length, mmt1.row(), mmt2.row(), m, n, mmv.row(), mmc.row());
|
||||
std::cout << " Incompatible sizes for qua eval action, len=" << length
|
||||
<< ", row1=" << mmt1.row() << ", row2=" << mmt2.row()
|
||||
<< ", m=" << m << ", n=" << n
|
||||
<< ", vrow=" << mmv.row() << ", crow=" << mmc.row()
|
||||
<< std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -331,12 +336,12 @@ TestRunnable::qua_eval(const char *m1name, const char *m2name, const char *vname
|
|||
x2.add(-1, c2);
|
||||
double norm1 = x1.getNorm();
|
||||
double norm2 = x2.getNorm();
|
||||
printf("\terror norm1 = %8.4g\n\terror norm2 = %8.4g\n", norm1, norm2);
|
||||
std::cout << "\terror norm1 = " << norm1 << "\n\terror norm2 = " << norm2 << std::endl;
|
||||
return (norm1*norm1+norm2*norm2 < 100*eps_norm*eps_norm); // relax norm
|
||||
}
|
||||
|
||||
bool
|
||||
TestRunnable::tri_sylv(const char *m1name, const char *m2name, const char *vname,
|
||||
TestRunnable::tri_sylv(const std::string &m1name, const std::string &m2name, const std::string &vname,
|
||||
int m, int n, int depth)
|
||||
{
|
||||
MMMatrixIn mmt1(m1name);
|
||||
|
@ -348,7 +353,11 @@ TestRunnable::tri_sylv(const char *m1name, const char *m2name, const char *vname
|
|||
|| mmt2.row() != n
|
||||
|| mmv.row() != length)
|
||||
{
|
||||
printf(" Incompatible sizes for triangular sylvester action, len=%d, row1=%d, row2=%d, m=%d, n=%d, vrow=%d\n", length, mmt1.row(), mmt2.row(), m, n, mmv.row());
|
||||
std::cout << " Incompatible sizes for triangular sylvester action, len=" << length
|
||||
<< ", row1=" << mmt1.row() << ", row2=" << mmt2.row()
|
||||
<< ", m=" << m << ", n=" << n
|
||||
<< ", vrow=" << mmv.row()
|
||||
<< std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -369,17 +378,17 @@ TestRunnable::tri_sylv(const char *m1name, const char *m2name, const char *vname
|
|||
dcheck.add(-1.0, v);
|
||||
double norm = dcheck.getNorm();
|
||||
double xnorm = v.getNorm();
|
||||
printf("\trel. error norm = %8.4g\n", norm/xnorm);
|
||||
std::cout << "\trel. error norm = " << norm/xnorm << std::endl;
|
||||
double max = dcheck.getMax();
|
||||
double xmax = v.getMax();
|
||||
printf("\trel. error max = %8.4g\n", max/xmax);
|
||||
std::cout << "\trel. error max = " << max/xmax << std::endl;
|
||||
memdriver.setStackMode(false);
|
||||
return (norm < xnorm*eps_norm);
|
||||
}
|
||||
|
||||
bool
|
||||
TestRunnable::gen_sylv(const char *aname, const char *bname, const char *cname,
|
||||
const char *dname, int m, int n, int order)
|
||||
TestRunnable::gen_sylv(const std::string &aname, const std::string &bname, const std::string &cname,
|
||||
const std::string &dname, int m, int n, int order)
|
||||
{
|
||||
MMMatrixIn mma(aname);
|
||||
MMMatrixIn mmb(bname);
|
||||
|
@ -391,7 +400,7 @@ TestRunnable::gen_sylv(const char *aname, const char *bname, const char *cname,
|
|||
|| n != mmb.row() || n < mmb.col()
|
||||
|| n != mmd.row() || power(m, order) != mmd.col())
|
||||
{
|
||||
printf(" Incompatible sizes for gen_sylv.\n");
|
||||
std::cout << " Incompatible sizes for gen_sylv.\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -410,13 +419,13 @@ TestRunnable::gen_sylv(const char *aname, const char *bname, const char *cname,
|
|||
}
|
||||
|
||||
bool
|
||||
TestRunnable::eig_bubble(const char *aname, int from, int to)
|
||||
TestRunnable::eig_bubble(const std::string &aname, int from, int to)
|
||||
{
|
||||
MMMatrixIn mma(aname);
|
||||
|
||||
if (mma.row() != mma.col())
|
||||
{
|
||||
printf(" Matrix is not square\n");
|
||||
std::cout << " Matrix is not square\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -438,21 +447,21 @@ TestRunnable::eig_bubble(const char *aname, int from, int to)
|
|||
double normInf = check.getNormInf();
|
||||
double onorm1 = orig.getNorm1();
|
||||
double onormInf = orig.getNormInf();
|
||||
printf("\tabs. error1 = %8.4g\n", norm1);
|
||||
printf("\tabs. errorI = %8.4g\n", normInf);
|
||||
printf("\trel. error1 = %8.4g\n", norm1/onorm1);
|
||||
printf("\trel. errorI = %8.4g\n", normInf/onormInf);
|
||||
std:: cout << "\tabs. error1 = " << norm1 << std::endl
|
||||
<< "\tabs. errorI = " << normInf << std::endl
|
||||
<< "\trel. error1 = " << norm1/onorm1 << std::endl
|
||||
<< "\trel. errorI = " << normInf/onormInf << std::endl;
|
||||
return (norm1 < eps_norm*onorm1 && normInf < eps_norm*onormInf);
|
||||
}
|
||||
|
||||
bool
|
||||
TestRunnable::block_diag(const char *aname, double log10norm)
|
||||
TestRunnable::block_diag(const std::string &aname, double log10norm)
|
||||
{
|
||||
MMMatrixIn mma(aname);
|
||||
|
||||
if (mma.row() != mma.col())
|
||||
{
|
||||
printf(" Matrix is not square\n");
|
||||
std::cout << " Matrix is not square\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -468,25 +477,25 @@ TestRunnable::block_diag(const char *aname, double log10norm)
|
|||
double normInf = check.getNormInf();
|
||||
double onorm1 = orig.getNorm1();
|
||||
double onormInf = orig.getNormInf();
|
||||
printf("\terror Q*B*invQ:\n");
|
||||
printf("\tabs. error1 = %8.4g\n", norm1);
|
||||
printf("\tabs. errorI = %8.4g\n", normInf);
|
||||
printf("\trel. error1 = %8.4g\n", norm1/onorm1);
|
||||
printf("\trel. errorI = %8.4g\n", normInf/onormInf);
|
||||
std::cout << "\terror Q*B*invQ:" << std::endl
|
||||
<< "\tabs. error1 = " << norm1 << std::endl
|
||||
<< "\tabs. errorI = " << normInf << std::endl
|
||||
<< "\trel. error1 = " << norm1/onorm1 << std::endl
|
||||
<< "\trel. errorI = " << normInf/onormInf << std::endl;
|
||||
SqSylvMatrix check2(dec.getQ(), dec.getInvQ());
|
||||
SqSylvMatrix in(n);
|
||||
in.setUnit();
|
||||
check2.add(-1, in);
|
||||
double nor1 = check2.getNorm1();
|
||||
double norInf = check2.getNormInf();
|
||||
printf("\terror Q*invQ:\n");
|
||||
printf("\tabs. error1 = %8.4g\n", nor1);
|
||||
printf("\tabs. errorI = %8.4g\n", norInf);
|
||||
std::cout << "\terror Q*invQ:" << std::endl
|
||||
<< "\tabs. error1 = " << nor1 << std::endl
|
||||
<< "\tabs. errorI = " << norInf << std::endl;
|
||||
return (norm1 < eps_norm*pow(10, log10norm)*onorm1);
|
||||
}
|
||||
|
||||
bool
|
||||
TestRunnable::iter_sylv(const char *m1name, const char *m2name, const char *vname,
|
||||
TestRunnable::iter_sylv(const std::string &m1name, const std::string &m2name, const std::string &vname,
|
||||
int m, int n, int depth)
|
||||
{
|
||||
MMMatrixIn mmt1(m1name);
|
||||
|
@ -498,7 +507,11 @@ TestRunnable::iter_sylv(const char *m1name, const char *m2name, const char *vnam
|
|||
|| mmt2.row() != n
|
||||
|| mmv.row() != length)
|
||||
{
|
||||
printf(" Incompatible sizes for triangular sylvester iteration, len=%d, row1=%d, row2=%d, m=%d, n=%d, vrow=%d\n", length, mmt1.row(), mmt2.row(), m, n, mmv.row());
|
||||
std::cout << " Incompatible sizes for triangular sylvester iteration, len=" << length
|
||||
<< ", row1=" << mmt1.row() << ", row2=" << mmt2.row()
|
||||
<< ", m=" << m << ", n=" << n
|
||||
<< ", vrow=" << mmv.row()
|
||||
<< std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -511,7 +524,7 @@ TestRunnable::iter_sylv(const char *m1name, const char *m2name, const char *vnam
|
|||
ConstKronVector v(vraw, m, n, depth);
|
||||
KronVector d(v); // copy of v
|
||||
SylvParams pars;
|
||||
pars.method = SylvParams::iter;
|
||||
pars.method = SylvParams::solve_method::iter;
|
||||
is.solve(pars, d);
|
||||
pars.print("\t");
|
||||
KronVector dcheck((const KronVector &)d);
|
||||
|
@ -520,10 +533,10 @@ TestRunnable::iter_sylv(const char *m1name, const char *m2name, const char *vnam
|
|||
dcheck.add(-1.0, v);
|
||||
double cnorm = dcheck.getNorm();
|
||||
double xnorm = v.getNorm();
|
||||
printf("\trel. error norm = %8.4g\n", cnorm/xnorm);
|
||||
std::cout << "\trel. error norm = " << cnorm/xnorm << std::endl;
|
||||
double max = dcheck.getMax();
|
||||
double xmax = v.getMax();
|
||||
printf("\trel. error max = %8.4g\n", max/xmax);
|
||||
std::cout << "\trel. error max = " << max/xmax << std::endl;
|
||||
memdriver.setStackMode(false);
|
||||
return (cnorm < xnorm*eps_norm);
|
||||
}
|
||||
|
@ -1149,79 +1162,76 @@ BlockDiagBigTest::run() const
|
|||
int
|
||||
main()
|
||||
{
|
||||
TestRunnable *all_tests[50];
|
||||
std::vector<std::unique_ptr<TestRunnable>> all_tests;
|
||||
// fill in vector of all tests
|
||||
int num_tests = 0;
|
||||
all_tests[num_tests++] = new PureTriangTest();
|
||||
all_tests[num_tests++] = new PureTriangTransTest();
|
||||
all_tests[num_tests++] = new PureTrLargeTest();
|
||||
all_tests[num_tests++] = new PureTrLargeTransTest();
|
||||
all_tests[num_tests++] = new QuasiTriangTest();
|
||||
all_tests[num_tests++] = new QuasiTriangTransTest();
|
||||
all_tests[num_tests++] = new QuasiTrLargeTest();
|
||||
all_tests[num_tests++] = new QuasiTrLargeTransTest();
|
||||
all_tests[num_tests++] = new QuasiZeroSmallTest();
|
||||
all_tests[num_tests++] = new MultKronSmallTest();
|
||||
all_tests[num_tests++] = new MultKronTest();
|
||||
all_tests[num_tests++] = new MultKronSmallTransTest();
|
||||
all_tests[num_tests++] = new MultKronTransTest();
|
||||
all_tests[num_tests++] = new LevelKronTest();
|
||||
all_tests[num_tests++] = new LevelKronTransTest();
|
||||
all_tests[num_tests++] = new LevelZeroKronTest();
|
||||
all_tests[num_tests++] = new LevelZeroKronTransTest();
|
||||
all_tests[num_tests++] = new KronPowerTest();
|
||||
all_tests[num_tests++] = new SmallLinEvalTest();
|
||||
all_tests[num_tests++] = new LinEvalTest();
|
||||
all_tests[num_tests++] = new SmallQuaEvalTest();
|
||||
all_tests[num_tests++] = new QuaEvalTest();
|
||||
all_tests[num_tests++] = new EigBubFrankTest();
|
||||
all_tests[num_tests++] = new EigBubSplitTest();
|
||||
all_tests[num_tests++] = new EigBubSameTest();
|
||||
all_tests[num_tests++] = new BlockDiagSmallTest();
|
||||
all_tests[num_tests++] = new BlockDiagFrankTest();
|
||||
all_tests[num_tests++] = new BlockDiagIllCondTest();
|
||||
all_tests[num_tests++] = new BlockDiagBigTest();
|
||||
all_tests[num_tests++] = new TriSylvSmallRealTest();
|
||||
all_tests[num_tests++] = new TriSylvSmallComplexTest();
|
||||
all_tests[num_tests++] = new TriSylvTest();
|
||||
all_tests[num_tests++] = new TriSylvBigTest();
|
||||
all_tests[num_tests++] = new TriSylvLargeTest();
|
||||
all_tests[num_tests++] = new IterSylvTest();
|
||||
all_tests[num_tests++] = new IterSylvLargeTest();
|
||||
all_tests[num_tests++] = new GenSylvSmallTest();
|
||||
all_tests[num_tests++] = new GenSylvTest();
|
||||
all_tests[num_tests++] = new GenSylvSingTest();
|
||||
all_tests[num_tests++] = new GenSylvLargeTest();
|
||||
all_tests.push_back(std::make_unique<PureTriangTest>());
|
||||
all_tests.push_back(std::make_unique<PureTriangTransTest>());
|
||||
all_tests.push_back(std::make_unique<PureTrLargeTest>());
|
||||
all_tests.push_back(std::make_unique<PureTrLargeTransTest>());
|
||||
all_tests.push_back(std::make_unique<QuasiTriangTest>());
|
||||
all_tests.push_back(std::make_unique<QuasiTriangTransTest>());
|
||||
all_tests.push_back(std::make_unique<QuasiTrLargeTest>());
|
||||
all_tests.push_back(std::make_unique<QuasiTrLargeTransTest>());
|
||||
all_tests.push_back(std::make_unique<QuasiZeroSmallTest>());
|
||||
all_tests.push_back(std::make_unique<MultKronSmallTest>());
|
||||
all_tests.push_back(std::make_unique<MultKronTest>());
|
||||
all_tests.push_back(std::make_unique<MultKronSmallTransTest>());
|
||||
all_tests.push_back(std::make_unique<MultKronTransTest>());
|
||||
all_tests.push_back(std::make_unique<LevelKronTest>());
|
||||
all_tests.push_back(std::make_unique<LevelKronTransTest>());
|
||||
all_tests.push_back(std::make_unique<LevelZeroKronTest>());
|
||||
all_tests.push_back(std::make_unique<LevelZeroKronTransTest>());
|
||||
all_tests.push_back(std::make_unique<KronPowerTest>());
|
||||
all_tests.push_back(std::make_unique<SmallLinEvalTest>());
|
||||
all_tests.push_back(std::make_unique<LinEvalTest>());
|
||||
all_tests.push_back(std::make_unique<SmallQuaEvalTest>());
|
||||
all_tests.push_back(std::make_unique<QuaEvalTest>());
|
||||
all_tests.push_back(std::make_unique<EigBubFrankTest>());
|
||||
all_tests.push_back(std::make_unique<EigBubSplitTest>());
|
||||
all_tests.push_back(std::make_unique<EigBubSameTest>());
|
||||
all_tests.push_back(std::make_unique<BlockDiagSmallTest>());
|
||||
all_tests.push_back(std::make_unique<BlockDiagFrankTest>());
|
||||
all_tests.push_back(std::make_unique<BlockDiagIllCondTest>());
|
||||
all_tests.push_back(std::make_unique<BlockDiagBigTest>());
|
||||
all_tests.push_back(std::make_unique<TriSylvSmallRealTest>());
|
||||
all_tests.push_back(std::make_unique<TriSylvSmallComplexTest>());
|
||||
all_tests.push_back(std::make_unique<TriSylvTest>());
|
||||
all_tests.push_back(std::make_unique<TriSylvBigTest>());
|
||||
all_tests.push_back(std::make_unique<TriSylvLargeTest>());
|
||||
all_tests.push_back(std::make_unique<IterSylvTest>());
|
||||
all_tests.push_back(std::make_unique<IterSylvLargeTest>());
|
||||
all_tests.push_back(std::make_unique<GenSylvSmallTest>());
|
||||
all_tests.push_back(std::make_unique<GenSylvTest>());
|
||||
all_tests.push_back(std::make_unique<GenSylvSingTest>());
|
||||
all_tests.push_back(std::make_unique<GenSylvLargeTest>());
|
||||
|
||||
// launch the tests
|
||||
std::cout << std::setprecision(4);
|
||||
int success = 0;
|
||||
for (int i = 0; i < num_tests; i++)
|
||||
for (const auto &test : all_tests)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (all_tests[i]->test())
|
||||
if (test->test())
|
||||
success++;
|
||||
}
|
||||
catch (const MMException &e)
|
||||
{
|
||||
printf("Caugth MM exception in <%s>:\n%s", all_tests[i]->getName(),
|
||||
e.getMessage());
|
||||
std::cout << "Caught MM exception in <" << test->name << ">:\n" << e.getMessage();
|
||||
}
|
||||
catch (SylvException &e)
|
||||
{
|
||||
printf("Caught Sylv exception in %s:\n", all_tests[i]->getName());
|
||||
std::cout << "Caught Sylv exception in " << test->name << ":\n";
|
||||
e.printMessage();
|
||||
}
|
||||
}
|
||||
|
||||
printf("There were %d tests that failed out of %d tests run.\n",
|
||||
num_tests - success, num_tests);
|
||||
int nfailed = all_tests.size() - success;
|
||||
std::cout << "There were " << nfailed << " tests that failed out of "
|
||||
<< all_tests.size() << " tests run." << std::endl;
|
||||
|
||||
// destroy
|
||||
for (int i = 0; i < num_tests; i++)
|
||||
{
|
||||
delete all_tests[i];
|
||||
}
|
||||
|
||||
return 0;
|
||||
if (nfailed)
|
||||
return EXIT_FAILURE;
|
||||
else
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue