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
time-shift
Sébastien Villemot 2019-01-22 16:07:44 +01:00
parent 49c06f5c7f
commit c711d34d1d
No known key found for this signature in database
GPG Key ID: 2CECE9350ECEBE4A
53 changed files with 456 additions and 412 deletions

View File

@ -100,7 +100,7 @@ extern "C" {
DYN_MEX_FUNC_ERR_MSG_TXT(buf);
}
ft.zeros();
ConstTwoDMatrix gk_mat(ft.nrows(), ft.ncols(), mxGetPr(gk));
ConstTwoDMatrix gk_mat(ft.nrows(), ft.ncols(), ConstVector{gk});
ft.add(1.0, gk_mat);
auto *ut = new UFSTensor(ft);
pol.insert(ut);
@ -108,17 +108,16 @@ extern "C" {
// form the decision rule
UnfoldDecisionRule
dr(pol, PartitionY(nstat, npred, nboth, nforw),
nexog, ConstVector(mxGetPr(ysteady), ny));
nexog, ConstVector{ysteady});
// form the shock realization
TwoDMatrix shocks_mat(nexog, nper, (const double *)mxGetPr(shocks));
TwoDMatrix vcov_mat(nexog, nexog, (const double *)mxGetPr(vcov));
TwoDMatrix shocks_mat(nexog, nper, ConstVector{shocks});
TwoDMatrix vcov_mat(nexog, nexog, ConstVector{vcov});
GenShockRealization sr(vcov_mat, shocks_mat, seed);
// simulate and copy the results
Vector ystart_vec((const double *)mxGetPr(ystart), ny);
TwoDMatrix *res_mat
= dr.simulate(DecisionRule::horner, nper,
ystart_vec, sr);
TwoDMatrix res_tmp_mat(ny, nper, mxGetPr(res));
ConstVector{ystart}, sr);
TwoDMatrix res_tmp_mat{ny, nper, Vector{res}};
res_tmp_mat = (const TwoDMatrix &) (*res_mat);
delete res_mat;
plhs[1] = res;

View File

@ -144,7 +144,7 @@ Approximation::walkStochSteady()
to |ss|. */
model.solveDeterministicSteady();
approxAtSteady();
Vector steady0(ss, 0);
Vector steady0{ss.getCol(0)};
steady0 = (const Vector &) model.getSteady();
double sigma_so_far = 0.0;
@ -172,7 +172,7 @@ Approximation::walkStochSteady()
rec << " Not converged!!" << endrec;
KORD_RAISE_X("Fix point calculation not converged", KORD_FP_NOT_CONV);
}
Vector steadyi(ss, i);
Vector steadyi{ss.getCol(i)};
steadyi = (const Vector &) model.getSteady();
// calculate |hh| as expectations of the last $g^{**}$
@ -378,7 +378,7 @@ Approximation::calcYCov() const
TwoDMatrix *X = new TwoDMatrix(guSigma, guTrans);
GeneralSylvester gs(1, model.numeq(), model.numeq(), 0,
A.base(), B.base(), C.base(), X->base());
A.getData(), B.getData(), C.getData(), X->getData());
gs.solve();
return X;

View File

@ -181,7 +181,7 @@ SimResultsStats::writeMat(mat_t *fd, const char *lname) const
{
char tmp[100];
sprintf(tmp, "%s_mean", lname);
ConstTwoDMatrix m(num_y, 1, mean.base());
ConstTwoDMatrix m(num_y, 1, mean);
m.writeMat(fd, tmp);
sprintf(tmp, "%s_vcov", lname);
ConstTwoDMatrix(vcov).writeMat(fd, tmp);
@ -198,7 +198,7 @@ SimResultsStats::calcMean()
{
for (int j = 0; j < num_per; j++)
{
ConstVector col(*i, j);
ConstVector col{i->getCol(j)};
mean.add(mult, col);
}
}
@ -273,10 +273,10 @@ SimResultsDynamicStats::calcMean()
double mult = 1.0/data.size();
for (int j = 0; j < num_per; j++)
{
Vector meanj(mean, j);
Vector meanj{mean.getCol(j)};
for (auto & i : data)
{
ConstVector col(*i, j);
ConstVector col{i->getCol(j)};
meanj.add(mult, col);
}
}
@ -292,11 +292,11 @@ SimResultsDynamicStats::calcVariance()
double mult = 1.0/(data.size()-1);
for (int j = 0; j < num_per; j++)
{
ConstVector meanj(mean, j);
Vector varj(variance, j);
ConstVector meanj{mean.getCol(j)};
Vector varj{variance.getCol(j)};
for (auto & i : data)
{
Vector col(ConstVector((*i), j));
Vector col{i->getCol(j)};
col.add(-1.0, meanj);
for (int k = 0; k < col.length(); k++)
col[k] = col[k]*col[k];
@ -426,7 +426,7 @@ RTSimResultsStats::writeMat(mat_t *fd, const char *lname)
{
char tmp[100];
sprintf(tmp, "%s_rt_mean", lname);
ConstTwoDMatrix m(nc.getDim(), 1, mean.base());
ConstTwoDMatrix m(nc.getDim(), 1, mean);
m.writeMat(fd, tmp);
sprintf(tmp, "%s_rt_vcov", lname);
ConstTwoDMatrix(vcov).writeMat(fd, tmp);
@ -500,7 +500,7 @@ SimulationIRFWorker::operator()()
= new ExplicitShockRealization(res.control.getShocks(idata));
esr->addToShock(ishock, 0, imp);
const TwoDMatrix &data = res.control.getData(idata);
ConstVector st(data, res.control.getNumBurn());
Vector st{data.getCol(res.control.getNumBurn())};
TwoDMatrix *m = dr.simulate(em, np, st, *esr);
m->add(-1.0, res.control.getData(idata));
{
@ -604,7 +604,7 @@ ExplicitShockRealization::ExplicitShockRealization(ShockRealization &sr,
{
for (int j = 0; j < num_per; j++)
{
Vector jcol(shocks, j);
Vector jcol{shocks.getCol(j)};
sr.get(j, jcol);
}
}
@ -615,7 +615,7 @@ ExplicitShockRealization::get(int n, Vector &out)
KORD_RAISE_IF(out.length() != numShocks(),
"Wrong length of out vector in ExplicitShockRealization::get");
int i = n % shocks.ncols();
ConstVector icol(shocks, i);
ConstVector icol{shocks.getCol(i)};
out = icol;
}

View File

@ -57,7 +57,7 @@ public:
enum emethod { horner, trad };
virtual ~DecisionRule()
= default;
virtual TwoDMatrix *simulate(emethod em, int np, const Vector &ystart,
virtual TwoDMatrix *simulate(emethod em, int np, const ConstVector &ystart,
ShockRealization &sr) const = 0;
virtual void eval(emethod em, Vector &out, const ConstVector &v) const = 0;
virtual void evaluate(emethod em, Vector &out, const ConstVector &ys,
@ -103,18 +103,18 @@ protected:
const int nu;
public:
DecisionRuleImpl(const _Tparent &pol, const PartitionY &yp, int nuu,
const Vector &ys)
const ConstVector &ys)
: ctraits<t>::Tpol(pol), ysteady(ys), ypart(yp), nu(nuu)
{
}
DecisionRuleImpl(_Tparent &pol, const PartitionY &yp, int nuu,
const Vector &ys)
const ConstVector &ys)
: ctraits<t>::Tpol(0, yp.ny(), pol), ysteady(ys), ypart(yp),
nu(nuu)
{
}
DecisionRuleImpl(const _Tg &g, const PartitionY &yp, int nuu,
const Vector &ys, double sigma)
const ConstVector &ys, double sigma)
: ctraits<t>::Tpol(yp.ny(), yp.nys()+nuu), ysteady(ys), ypart(yp), nu(nuu)
{
fillTensors(g, sigma);
@ -130,7 +130,7 @@ public:
{
return ysteady;
}
TwoDMatrix *simulate(emethod em, int np, const Vector &ystart,
TwoDMatrix *simulate(emethod em, int np, const ConstVector &ystart,
ShockRealization &sr) const override;
void evaluate(emethod em, Vector &out, const ConstVector &ys,
const ConstVector &u) const override;
@ -280,7 +280,7 @@ DecisionRuleImpl<t>::centralize(const DecisionRuleImpl &dr)
template <int t>
TwoDMatrix *
DecisionRuleImpl<t>::simulate(emethod em, int np, const Vector &ystart,
DecisionRuleImpl<t>::simulate(emethod em, int np, const ConstVector &ystart,
ShockRealization &sr) const
{
KORD_RAISE_IF(ysteady.length() != ystart.length(),
@ -303,7 +303,7 @@ DecisionRuleImpl<t>::simulate(emethod em, int np, const Vector &ystart,
dy = ystart_pred;
dy.add(-1.0, ysteady_pred);
sr.get(0, u);
Vector out(*res, 0);
Vector out{res->getCol(0)};
eval(em, out, dyu);
// perform all other steps of simulations
@ -312,11 +312,11 @@ DecisionRuleImpl<t>::simulate(emethod em, int np, const Vector &ystart,
int i = 1;
while (i < np)
{
ConstVector ym(*res, i-1);
ConstVector ym{res->getCol(i-1)};
ConstVector dym(ym, ypart.nstat, ypart.nys());
dy = dym;
sr.get(i, u);
Vector out(*res, i);
Vector out{res->getCol(i)};
eval(em, out, dyu);
if (!out.isFinite())
{
@ -335,7 +335,7 @@ DecisionRuleImpl<t>::simulate(emethod em, int np, const Vector &ystart,
and leave the padded columns to zero. */
for (int j = 0; j < i; j++)
{
Vector col(*res, j);
Vector col{res->getCol(j)};
col.add(1.0, ysteady);
}
@ -415,17 +415,17 @@ class FoldDecisionRule : public DecisionRuleImpl<KOrder::fold>
friend class UnfoldDecisionRule;
public:
FoldDecisionRule(const ctraits<KOrder::fold>::Tpol &pol, const PartitionY &yp, int nuu,
const Vector &ys)
const ConstVector &ys)
: DecisionRuleImpl<KOrder::fold>(pol, yp, nuu, ys)
{
}
FoldDecisionRule(ctraits<KOrder::fold>::Tpol &pol, const PartitionY &yp, int nuu,
const Vector &ys)
const ConstVector &ys)
: DecisionRuleImpl<KOrder::fold>(pol, yp, nuu, ys)
{
}
FoldDecisionRule(const ctraits<KOrder::fold>::Tg &g, const PartitionY &yp, int nuu,
const Vector &ys, double sigma)
const ConstVector &ys, double sigma)
: DecisionRuleImpl<KOrder::fold>(g, yp, nuu, ys, sigma)
{
}
@ -445,17 +445,17 @@ class UnfoldDecisionRule : public DecisionRuleImpl<KOrder::unfold>
friend class FoldDecisionRule;
public:
UnfoldDecisionRule(const ctraits<KOrder::unfold>::Tpol &pol, const PartitionY &yp, int nuu,
const Vector &ys)
const ConstVector &ys)
: DecisionRuleImpl<KOrder::unfold>(pol, yp, nuu, ys)
{
}
UnfoldDecisionRule(ctraits<KOrder::unfold>::Tpol &pol, const PartitionY &yp, int nuu,
const Vector &ys)
const ConstVector &ys)
: DecisionRuleImpl<KOrder::unfold>(pol, yp, nuu, ys)
{
}
UnfoldDecisionRule(const ctraits<KOrder::unfold>::Tg &g, const PartitionY &yp, int nuu,
const Vector &ys, double sigma)
const ConstVector &ys, double sigma)
: DecisionRuleImpl<KOrder::unfold>(g, yp, nuu, ys, sigma)
{
}

View File

@ -107,9 +107,9 @@ public:
virtual Vector&getSteady() = 0;
virtual void solveDeterministicSteady() = 0;
virtual void evaluateSystem(Vector &out, const Vector &yy, const Vector &xx) = 0;
virtual void evaluateSystem(Vector &out, const Vector &yym, const Vector &yy,
const Vector &yyp, const Vector &xx) = 0;
virtual void evaluateSystem(Vector &out, const ConstVector &yy, const Vector &xx) = 0;
virtual void evaluateSystem(Vector &out, const ConstVector &yym, const ConstVector &yy,
const ConstVector &yyp, const Vector &xx) = 0;
virtual void calcDerivativesAtSteady() = 0;
};

View File

@ -52,7 +52,7 @@ ResidFunction::~ResidFunction()
|hss|. */
void
ResidFunction::setYU(const Vector &ys, const Vector &xx)
ResidFunction::setYU(const ConstVector &ys, const ConstVector &xx)
{
// delete |y| and |u| dependent data
/* NB: code shared with the destructor */
@ -195,9 +195,9 @@ GlobalChecker::check(int max_evals, const ConstTwoDMatrix &y,
ConstTwoDMatrix ysmat(y, first_row, 0, model.npred()+model.nboth(), y.ncols());
for (int j = 0; j < y.ncols(); j++)
{
ConstVector yj(ysmat, j);
ConstVector xj(x, j);
Vector outj(out, j);
ConstVector yj{ysmat.getCol(j)};
ConstVector xj{x.getCol(j)};
Vector outj{out.getCol(j)};
check(*quad, lev, yj, xj, outj);
}
@ -221,7 +221,7 @@ GlobalChecker::checkAlongShocksAndSave(mat_t *fd, const char *prefix,
TwoDMatrix y_mat(model.numeq(), 2*m *model.nexog()+1);
for (int j = 0; j < 2*m*model.nexog()+1; j++)
{
Vector yj(y_mat, j);
Vector yj{y_mat.getCol(j)};
yj = (const Vector &) model.getSteady();
}
@ -246,7 +246,7 @@ GlobalChecker::checkAlongShocksAndSave(mat_t *fd, const char *prefix,
TwoDMatrix res(model.nexog(), 2*m+1);
JournalRecord rec(journal);
rec << "Shock value error" << endrec;
ConstVector err0(errors, 0);
ConstVector err0{errors.getCol(0)};
char shock[9];
char erbuf[17];
for (int ishock = 0; ishock < model.nexog(); ishock++)
@ -256,14 +256,14 @@ GlobalChecker::checkAlongShocksAndSave(mat_t *fd, const char *prefix,
for (int j = 0; j < 2*m+1; j++)
{
int jj;
Vector error(err_out, j);
Vector error{err_out.getCol(j)};
if (j != m)
{
if (j < m)
jj = 1 + 2*m*ishock+j;
else
jj = 1 + 2*m*ishock+j-1;
ConstVector coljj(errors, jj);
ConstVector coljj{errors.getCol(jj)};
error = coljj;
}
else
@ -347,7 +347,7 @@ GlobalChecker::checkOnEllipseAndSave(mat_t *fd, const char *prefix,
qmcpit end = qmc.end(m);
for (qmcpit run = beg; run != end; ++run, icol++)
{
Vector ycol(ymat, icol);
Vector ycol{ymat.getCol(icol)};
Vector x(run.point());
x.mult(2*M_PI);
ycol[0] = 1;
@ -372,7 +372,7 @@ GlobalChecker::checkOnEllipseAndSave(mat_t *fd, const char *prefix,
model.npred()+model.nboth());
for (int icol = 0; icol < ymat.ncols(); icol++)
{
Vector ycol(ymat, icol);
Vector ycol{ymat.getCol(icol)};
ycol.add(1.0, ys);
}

View File

@ -84,7 +84,7 @@ public:
return std::make_unique<ResidFunction>(*this);
}
void eval(const Vector &point, const ParameterSignal &sig, Vector &out) override;
void setYU(const Vector &ys, const Vector &xx);
void setYU(const ConstVector &ys, const ConstVector &xx);
};
/* This is a |ResidFunction| wrapped with |GaussConverterFunction|. */
@ -104,7 +104,7 @@ public:
return std::make_unique<GResidFunction>(*this);
}
void
setYU(const Vector &ys, const Vector &xx)
setYU(const ConstVector &ys, const ConstVector &xx)
{
((ResidFunction *) func)->setYU(ys, xx);
}

View File

@ -307,8 +307,8 @@ KOrder::sylvesterSolve<KOrder::unfold>(ctraits<unfold>::Ttensor &der) const
TwoDMatrix gs_y(*(gs<unfold>().get(Symmetry(1, 0, 0, 0))));
GeneralSylvester sylv(der.getSym()[0], ny, ypart.nys(),
ypart.nstat+ypart.npred,
matA.getData().base(), matB.getData().base(),
gs_y.getData().base(), der.getData().base());
matA.getData(), matB.getData(),
gs_y.getData(), der.getData());
sylv.solve();
}
else if (ypart.nys() > 0 && ypart.nyss() == 0)

View File

@ -18,12 +18,12 @@ NormalConj::NormalConj(const ConstTwoDMatrix &ydata)
{
mu.zeros();
for (int i = 0; i < ydata.numCols(); i++)
mu.add(1.0/ydata.numCols(), ConstVector(ydata, i));
mu.add(1.0/ydata.numCols(), ydata.getCol(i));
lambda.zeros();
for (int i = 0; i < ydata.numCols(); i++)
{
Vector diff(ConstVector(ydata, i));
Vector diff{ydata.getCol(i)};
diff.add(-1, mu);
lambda.addOuter(diff);
}

View File

@ -13,6 +13,13 @@ struct Rand
static bool discrete(double prob); // answers true with given probability
};
TwoDMatrix
make_matrix(int rows, int cols, const double *p)
{
return TwoDMatrix{rows, cols,
ConstVector{std::shared_ptr<const double>{p, [](const double *arr) {}}, rows*cols}};
}
void
Rand::init(int n1, int n2, int n3, int n4, int n5)
{
@ -345,9 +352,9 @@ public:
bool
run() const override
{
TwoDMatrix gy(8, 4, gy_data);
TwoDMatrix gu(8, 3, gu_data);
TwoDMatrix v(3, 3, vdata);
TwoDMatrix gy{make_matrix(8, 4, gy_data)};
TwoDMatrix gu{make_matrix(8, 3, gu_data)};
TwoDMatrix v{make_matrix(3, 3, vdata)};
double err = korder_unfold_fold(4, 3, 2, 3, 1, 2,
gy, gu, v);
@ -368,9 +375,9 @@ public:
bool
run() const override
{
TwoDMatrix gy(30, 20, gy_data2);
TwoDMatrix gu(30, 10, gu_data2);
TwoDMatrix v(10, 10, vdata2);
TwoDMatrix gy{make_matrix(30, 20, gy_data2)};
TwoDMatrix gu{make_matrix(30, 10, gu_data2)};
TwoDMatrix v{make_matrix(10, 10, vdata2)};
v.mult(0.001);
gu.mult(.01);
double err = korder_unfold_fold(4, 4, 5, 12, 8, 5,
@ -392,9 +399,9 @@ public:
bool
run() const override
{
TwoDMatrix gy(30, 20, gy_data2);
TwoDMatrix gu(30, 10, gu_data2);
TwoDMatrix v(10, 10, vdata2);
TwoDMatrix gy{make_matrix(30, 20, gy_data2)};
TwoDMatrix gu{make_matrix(30, 10, gu_data2)};
TwoDMatrix v{make_matrix(10, 10, vdata2)};
v.mult(0.001);
gu.mult(.01);
double err = korder_unfold_fold(4, 3, 5, 12, 8, 5,

View File

@ -199,7 +199,7 @@ Dynare::solveDeterministicSteady(Vector &steady)
// evaluate system at given y_t=y_{t+1}=y_{t-1}, and given shocks x_t
void
Dynare::evaluateSystem(Vector &out, const Vector &yy, const Vector &xx)
Dynare::evaluateSystem(Vector &out, const ConstVector &yy, const Vector &xx)
{
ConstVector yym(yy, nstat(), nys());
ConstVector yyp(yy, nstat()+npred(), nyss());
@ -210,8 +210,8 @@ Dynare::evaluateSystem(Vector &out, const Vector &yy, const Vector &xx)
// exogenous x_t, all three vectors yym, yy, and yyp have the
// respective lengths of y^*_{t-1}, y_t, y^{**}_{t+1}
void
Dynare::evaluateSystem(Vector &out, const Vector &yym, const Vector &yy,
const Vector &yyp, const Vector &xx)
Dynare::evaluateSystem(Vector &out, const ConstVector &yym, const ConstVector &yy,
const ConstVector &yyp, const Vector &xx)
{
ogdyn::DynareAtomValues dav(model->getAtoms(), model->getParams(), yym, yy, yyp, xx);
DynareEvalLoader del(model->getAtoms(), out);

View File

@ -228,9 +228,9 @@ public:
{
solveDeterministicSteady(*ysteady);
}
void evaluateSystem(Vector &out, const Vector &yy, const Vector &xx) override;
void evaluateSystem(Vector &out, const Vector &yym, const Vector &yy,
const Vector &yyp, const Vector &xx) override;
void evaluateSystem(Vector &out, const ConstVector &yy, const Vector &xx) override;
void evaluateSystem(Vector &out, const ConstVector &yym, const ConstVector &yy,
const ConstVector &yyp, const Vector &xx) override;
void calcDerivatives(const Vector &yy, const Vector &xx);
void calcDerivativesAtSteady() override;

View File

@ -112,7 +112,7 @@ namespace ogdyn
{
}
DynareAtomValues(const ogp::FineAtoms &a, const Vector &pvals, const ConstVector &ym,
const Vector &y, const ConstVector &yp, const Vector &x)
const ConstVector &y, const ConstVector &yp, const Vector &x)
: atoms(a), paramvals(pvals), yym(ym), yy(y), yyp(yp), xx(x)
{
}

View File

@ -142,7 +142,7 @@ main(int argc, char **argv)
if (params.num_condper > 0 && params.num_condsim > 0)
{
SimResultsDynamicStats rescond(dynare.numeq(), params.num_condper, 0);
ConstVector det_ss(app.getSS(), 0);
Vector det_ss{app.getSS().getCol(0)};
rescond.simulate(params.num_condsim, app.getFoldDecisionRule(), det_ss, dynare.getVcov(), journal);
rescond.writeMat(matfd, params.prefix);
}

View File

@ -6,9 +6,10 @@
#include <iostream>
#include <cstring>
#include <utility>
BlockDiagonal::BlockDiagonal(const double *d, int d_size)
: QuasiTriangular(d, d_size),
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])
{
for (int i = 0; i < d_size; i++)

View File

@ -14,7 +14,7 @@ class BlockDiagonal : public QuasiTriangular
int *const row_len;
int *const col_len;
public:
BlockDiagonal(const double *d, int d_size);
BlockDiagonal(ConstVector d, int d_size);
BlockDiagonal(int p, const BlockDiagonal &b);
BlockDiagonal(const BlockDiagonal &b);
BlockDiagonal(const QuasiTriangular &t);

View File

@ -16,8 +16,6 @@
#include <limits>
#include <vector>
int GeneralMatrix::md_length = 32;
GeneralMatrix::GeneralMatrix(const GeneralMatrix &m)
: data(m.rows*m.cols), rows(m.rows), cols(m.cols), ld(m.rows)
{
@ -53,35 +51,59 @@ GeneralMatrix::GeneralMatrix(const GeneralMatrix &m, int i, int j, int nrows, in
}
GeneralMatrix::GeneralMatrix(GeneralMatrix &m, int i, int j, int nrows, int ncols)
: data(m.base()+m.ld*j+i, m.ld*(ncols-1)+nrows), rows(nrows), cols(ncols), ld(m.ld)
: data(m.data, m.ld*j+i, m.ld*(ncols-1)+nrows), rows(nrows), cols(ncols), ld(m.ld)
{
}
GeneralMatrix::GeneralMatrix(const GeneralMatrix &a, const GeneralMatrix &b)
GeneralMatrix::GeneralMatrix(const ConstGeneralMatrix &a, const ConstGeneralMatrix &b)
: data(a.rows*b.cols), rows(a.rows), cols(b.cols), ld(a.rows)
{
gemm("N", a, "N", b, 1.0, 0.0);
}
GeneralMatrix::GeneralMatrix(const GeneralMatrix &a, const GeneralMatrix &b, const char *dum)
GeneralMatrix::GeneralMatrix(const ConstGeneralMatrix &a, const ConstGeneralMatrix &b, const char *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 GeneralMatrix &a, const char *dum, const GeneralMatrix &b)
GeneralMatrix::GeneralMatrix(const ConstGeneralMatrix &a, const char *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 GeneralMatrix &a, const char *dum1,
const GeneralMatrix &b, const char *dum2)
GeneralMatrix::GeneralMatrix(const ConstGeneralMatrix &a, const char *dum1,
const ConstGeneralMatrix &b, const char *dum2)
: data(a.cols*b.rows), rows(a.cols), cols(b.rows), ld(a.cols)
{
gemm("T", a, "T", b, 1.0, 0.0);
}
Vector
GeneralMatrix::getRow(int row)
{
return Vector{data, row, ld, cols};
}
Vector
GeneralMatrix::getCol(int col)
{
return Vector{data, ld*col, rows};
}
ConstVector
GeneralMatrix::getRow(int row) const
{
return ConstVector{data, row, ld, cols};
}
ConstVector
GeneralMatrix::getCol(int col) const
{
return ConstVector{data, ld*col, rows};
}
void
GeneralMatrix::place(const ConstGeneralMatrix &m, int i, int j)
{
@ -357,14 +379,25 @@ ConstGeneralMatrix::ConstGeneralMatrix(const GeneralMatrix &m)
{
}
ConstVector
ConstGeneralMatrix::getRow(int row) const
{
return ConstVector{data, row, ld, cols};
}
ConstVector
ConstGeneralMatrix::getCol(int col) const
{
return ConstVector{data, ld*col, rows};
}
double
ConstGeneralMatrix::getNormInf() const
{
double norm = 0.0;
for (int i = 0; i < numRows(); i++)
{
ConstVector rowi(data.base()+i, ld, cols);
double normi = rowi.getNorm1();
double normi = getRow(i).getNorm1();
if (norm < normi)
norm = normi;
}
@ -377,8 +410,7 @@ ConstGeneralMatrix::getNorm1() const
double norm = 0.0;
for (int j = 0; j < numCols(); j++)
{
ConstVector colj(data.base()+ld *j, 1, rows);
double normj = colj.getNorm1();
double normj = getCol(j).getNorm1();
if (norm < normj)
norm = normj;
}
@ -581,12 +613,12 @@ SVDDecomp::solve(const GeneralMatrix &B, GeneralMatrix &X) const
GeneralMatrix Bprime(UTB, m-minmn, 0, minmn-nz, B.numCols());
// solve sigma
for (int i = 0; i < minmn-nz; i++)
Vector(i, Bprime).mult(1.0/sigma[i]);
Bprime.getRow(i).mult(1.0/sigma[i]);
// solve VT
X.zeros();
//- copy Bprime to right place of X
for (int i = 0; i < minmn-nz; i++)
Vector(n-minmn+i, X) = ConstVector(i, Bprime);
X.getRow(n-minmn+i) = Bprime.getRow(i);
//- multiply with VT
X.multLeftTrans(VT);
}

View File

@ -8,6 +8,8 @@
#include "Vector.hh"
#include <algorithm>
#include <memory>
#include <utility>
class GeneralMatrix;
@ -20,10 +22,11 @@ protected:
int cols;
int ld;
public:
ConstGeneralMatrix(const double *d, int m, int n)
: data(d, m*n), rows(m), cols(n), ld(m)
ConstGeneralMatrix(ConstVector d, int m, int n)
: data(std::move(d)), rows(m), cols(n), ld(m)
{
}
// Implicit conversion from ConstGeneralMatrix is ok, since it's cheap
ConstGeneralMatrix(const GeneralMatrix &m);
ConstGeneralMatrix(const GeneralMatrix &m, int i, int j, int nrows, int ncols);
ConstGeneralMatrix(const ConstGeneralMatrix &m, int i, int j, int nrows, int ncols);
@ -59,6 +62,8 @@ public:
{
return data;
}
ConstVector getRow(int row) const;
ConstVector getCol(int col) const;
double getNormInf() const;
double getNorm1() const;
@ -121,29 +126,30 @@ public:
: data(m*n), rows(m), cols(n), ld(m)
{
}
GeneralMatrix(const double *d, int m, int n)
: data(d, m*n), rows(m), cols(n), ld(m)
GeneralMatrix(const ConstVector &d, int m, int n)
: data(d), rows(m), cols(n), ld(m)
{
}
GeneralMatrix(double *d, int m, int n)
: data(d, m*n), rows(m), cols(n), ld(m)
GeneralMatrix(Vector &d, int m, int n)
: data(d), rows(m), cols(n), ld(m)
{
}
GeneralMatrix(const GeneralMatrix &m);
GeneralMatrix(const ConstGeneralMatrix &m);
// We don't want implict conversion from ConstGeneralMatrix, since it's expensive
explicit GeneralMatrix(const ConstGeneralMatrix &m);
GeneralMatrix(const GeneralMatrix &m, const char *dummy); // transpose
GeneralMatrix(const ConstGeneralMatrix &m, const char *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 GeneralMatrix &a, const GeneralMatrix &b);
GeneralMatrix(const ConstGeneralMatrix &a, const ConstGeneralMatrix &b);
/* this = a*b' */
GeneralMatrix(const GeneralMatrix &a, const GeneralMatrix &b, const char *dum);
GeneralMatrix(const ConstGeneralMatrix &a, const ConstGeneralMatrix &b, const char *dum);
/* this = a'*b */
GeneralMatrix(const GeneralMatrix &a, const char *dum, const GeneralMatrix &b);
GeneralMatrix(const ConstGeneralMatrix &a, const char *dum, const ConstGeneralMatrix &b);
/* this = a'*b */
GeneralMatrix(const GeneralMatrix &a, const char *dum1,
const GeneralMatrix &b, const char *dum2);
GeneralMatrix(const ConstGeneralMatrix &a, const char *dum1,
const ConstGeneralMatrix &b, const char *dum2);
virtual ~GeneralMatrix() = default;
GeneralMatrix &operator=(const GeneralMatrix &m) = default;
@ -193,6 +199,10 @@ public:
{
return data;
}
Vector getRow(int row);
Vector getCol(int col);
ConstVector getRow(int row) const;
ConstVector getCol(int col) const;
double
getNormInf() const
@ -432,7 +442,7 @@ private:
}
/* number of rows/columns for copy used in gemm_partial_* */
static int md_length;
static constexpr int md_length = 23;
};
class SVDDecomp
@ -473,8 +483,8 @@ public:
void
solve(const Vector &b, Vector &x) const
{
GeneralMatrix xmat(x.base(), x.length(), 1);
solve(GeneralMatrix(b.base(), b.length(), 1), xmat);
GeneralMatrix xmat(x, x.length(), 1);
solve(GeneralMatrix(b, b.length(), 1), xmat);
}
private:
void construct(const GeneralMatrix &A);

View File

@ -11,8 +11,8 @@
#include <ctime>
GeneralSylvester::GeneralSylvester(int ord, int n, int m, int zero_cols,
const double *da, const double *db,
const double *dc, const double *dd,
const ConstVector &da, const ConstVector &db,
const ConstVector &dc, const ConstVector &dd,
const SylvParams &ps)
: pars(ps),
mem_driver(pars, 1, m, n, ord), order(ord), a(da, n),
@ -23,8 +23,8 @@ GeneralSylvester::GeneralSylvester(int ord, int n, int m, int zero_cols,
}
GeneralSylvester::GeneralSylvester(int ord, int n, int m, int zero_cols,
const double *da, const double *db,
const double *dc, double *dd,
const ConstVector &da, const ConstVector &db,
const ConstVector &dc, Vector &dd,
const SylvParams &ps)
: pars(ps),
mem_driver(pars, 0, m, n, ord), order(ord), a(da, n),
@ -35,8 +35,8 @@ GeneralSylvester::GeneralSylvester(int ord, int n, int m, int zero_cols,
}
GeneralSylvester::GeneralSylvester(int ord, int n, int m, int zero_cols,
const double *da, const double *db,
const double *dc, const double *dd,
const ConstVector &da, const ConstVector &db,
const ConstVector &dc, const ConstVector &dd,
bool alloc_for_check)
: pars(alloc_for_check),
mem_driver(pars, 1, m, n, ord), order(ord), a(da, n),
@ -47,8 +47,8 @@ GeneralSylvester::GeneralSylvester(int ord, int n, int m, int zero_cols,
}
GeneralSylvester::GeneralSylvester(int ord, int n, int m, int zero_cols,
const double *da, const double *db,
const double *dc, double *dd,
const ConstVector &da, const ConstVector &db,
const ConstVector &dc, Vector &dd,
bool alloc_for_check)
: pars(alloc_for_check),
mem_driver(pars, 0, m, n, ord), order(ord), a(da, n),
@ -68,7 +68,7 @@ GeneralSylvester::init()
pars.rcondA1 = rcond1;
pars.rcondAI = rcondinf;
bdecomp = std::make_unique<SchurDecompZero>(ainvb);
cdecomp = std::make_unique<SimilarityDecomp>(c.getData().base(), c.numRows(), *(pars.bs_norm));
cdecomp = std::make_unique<SimilarityDecomp>(c.getData(), c.numRows(), *(pars.bs_norm));
cdecomp->check(pars, c);
cdecomp->infoToPars(pars);
if (*(pars.method) == SylvParams::recurse)
@ -105,7 +105,7 @@ GeneralSylvester::solve()
}
void
GeneralSylvester::check(const double *ds)
GeneralSylvester::check(const ConstVector &ds)
{
if (!solved)
throw SYLV_MES_EXCEPTION("Cannot run check on system, which is not solved yet.");
@ -117,8 +117,7 @@ GeneralSylvester::check(const double *ds)
dcheck.multLeft(b.numRows()-b.numCols(), b, d);
dcheck.multRightKron(c, order);
dcheck.multAndAdd(a, d);
ConstVector dv(ds, d.numRows()*d.numCols());
dcheck.getData().add(-1.0, dv);
dcheck.getData().add(-1.0, ds);
// calculate relative norms
pars.mat_err1 = dcheck.getNorm1()/d.getNorm1();
pars.mat_errI = dcheck.getNormInf()/d.getNormInf();

View File

@ -28,21 +28,21 @@ class GeneralSylvester
public:
/* construct with my copy of d*/
GeneralSylvester(int ord, int n, int m, int zero_cols,
const double *da, const double *db,
const double *dc, const double *dd,
const ConstVector &da, const ConstVector &db,
const ConstVector &dc, const ConstVector &dd,
const SylvParams &ps);
GeneralSylvester(int ord, int n, int m, int zero_cols,
const double *da, const double *db,
const double *dc, const double *dd,
const ConstVector &da, const ConstVector &db,
const ConstVector &dc, const ConstVector &dd,
bool alloc_for_check = false);
/* construct with provided storage for d */
GeneralSylvester(int ord, int n, int m, int zero_cols,
const double *da, const double *db,
const double *dc, double *dd,
const ConstVector &da, const ConstVector &db,
const ConstVector &dc, Vector &dd,
bool alloc_for_check = false);
GeneralSylvester(int ord, int n, int m, int zero_cols,
const double *da, const double *db,
const double *dc, double *dd,
const ConstVector &da, const ConstVector &db,
const ConstVector &dc, Vector &dd,
const SylvParams &ps);
virtual ~GeneralSylvester() = default;
int
@ -71,7 +71,7 @@ public:
return pars;
}
void solve();
void check(const double *ds);
void check(const ConstVector &ds);
private:
void init();
};

View File

@ -18,7 +18,7 @@ KronUtils::multAtLevel(int level, const QuasiTriangular &t,
}
else if (0 == level && 0 < x.getDepth())
{
GeneralMatrix tmp(x.base(), x.getN(), power(x.getM(), x.getDepth()));
GeneralMatrix tmp(x, x.getN(), power(x.getM(), x.getDepth()));
t.multLeftOther(tmp);
}
else if (0 == level && 0 == x.getDepth())
@ -46,7 +46,7 @@ KronUtils::multAtLevelTrans(int level, const QuasiTriangular &t,
}
else if (0 == level && 0 < x.getDepth())
{
GeneralMatrix tmp(x.base(), x.getN(), power(x.getM(), x.getDepth()));
GeneralMatrix tmp(x, x.getN(), power(x.getM(), x.getDepth()));
t.multLeftOtherTrans(tmp);
}
else if (level == 0 && 0 == x.getDepth())

View File

@ -5,6 +5,8 @@
#include "KronVector.hh"
#include "SylvException.hh"
#include <utility>
int
power(int m, int depth)
{
@ -77,8 +79,8 @@ ConstKronVector::ConstKronVector(const Vector &v, int mm, int nn, int dp)
throw SYLV_MES_EXCEPTION("Bad conversion KronVector from Vector.");
}
ConstKronVector::ConstKronVector(const ConstVector &v, int mm, int nn, int dp)
: ConstVector(v), m(mm), n(nn), depth(dp)
ConstKronVector::ConstKronVector(ConstVector v, int mm, int nn, int dp)
: ConstVector(std::move(v)), m(mm), n(nn), depth(dp)
{
if (length() != power(m, depth)*n)
throw SYLV_MES_EXCEPTION("Bad conversion KronVector from Vector.");

View File

@ -16,13 +16,12 @@ protected:
int n{0};
int depth{0};
public:
KronVector() : Vector((double *) nullptr, 0)
{
}
KronVector() = 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
KronVector(const ConstKronVector &v); // new instance and copy
// 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=(const ConstKronVector &v);
KronVector &operator=(const Vector &v);
@ -50,10 +49,11 @@ protected:
int n;
int depth;
public:
// Implicit conversion from KronVector is ok, since it's cheap
ConstKronVector(const KronVector &v);
ConstKronVector(const ConstKronVector &v);
ConstKronVector(const Vector &v, int mm, int nn, int dp);
ConstKronVector(const ConstVector &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);
int

View File

@ -420,7 +420,7 @@ QuasiTriangular::QuasiTriangular(const QuasiTriangular &t)
{
}
QuasiTriangular::QuasiTriangular(const double *d, int d_size)
QuasiTriangular::QuasiTriangular(const ConstVector &d, int d_size)
: SqSylvMatrix(d, d_size), diagonal(getData().base(), d_size)
{
}
@ -679,8 +679,8 @@ void
QuasiTriangular::multaKron(KronVector &x, const ConstKronVector &b) const
{
int id = b.getN()*power(b.getM(), b.getDepth()-1);
ConstGeneralMatrix b_resh(b.base(), id, b.getM());
GeneralMatrix x_resh(x.base(), id, b.getM());
ConstGeneralMatrix b_resh(b, id, b.getM());
GeneralMatrix x_resh(x, id, b.getM());
x_resh.multAndAdd(b_resh, ConstGeneralMatrix(*this), "trans");
}
@ -689,8 +689,8 @@ void
QuasiTriangular::multaKronTrans(KronVector &x, const ConstKronVector &b) const
{
int id = b.getN()*power(b.getM(), b.getDepth()-1);
ConstGeneralMatrix b_resh(b.base(), id, b.getM());
GeneralMatrix x_resh(x.base(), id, b.getM());
ConstGeneralMatrix b_resh(b, id, b.getM());
GeneralMatrix x_resh(x, id, b.getM());
x_resh.multAndAdd(b_resh, ConstGeneralMatrix(*this));
}

View File

@ -399,7 +399,7 @@ public:
protected:
Diagonal diagonal;
public:
QuasiTriangular(const double *d, int d_size);
QuasiTriangular(const ConstVector &d, int d_size);
QuasiTriangular(double r, const QuasiTriangular &t);
QuasiTriangular(double r, const QuasiTriangular &t,
double rr, const QuasiTriangular &tt);

View File

@ -8,14 +8,15 @@
#include "SylvException.hh"
#include <iostream>
#include <utility>
QuasiTriangularZero::QuasiTriangularZero(int num_zeros, const double *d,
QuasiTriangularZero::QuasiTriangularZero(int num_zeros, const ConstVector &d,
int d_size)
: QuasiTriangular(SqSylvMatrix(GeneralMatrix(d, num_zeros+d_size, d_size),
num_zeros, 0, d_size).getData().base(),
num_zeros, 0, d_size).getData(),
d_size),
nz(num_zeros),
ru(GeneralMatrix(d, num_zeros+d_size, d_size), 0, 0, num_zeros, d_size)
ru(GeneralMatrix(std::move(d), num_zeros+d_size, d_size), 0, 0, num_zeros, d_size)
{
}
@ -49,7 +50,7 @@ QuasiTriangularZero::QuasiTriangularZero(int p, const QuasiTriangularZero &t)
}
QuasiTriangularZero::QuasiTriangularZero(const SchurDecompZero &decomp)
: QuasiTriangular(decomp.getT().getData().base(),
: QuasiTriangular(decomp.getT().getData(),
decomp.getT().numRows()),
nz(decomp.getZeroCols()),
ru(decomp.getRU())

View File

@ -15,7 +15,7 @@ class QuasiTriangularZero : public QuasiTriangular
int nz; // number of zero columns
GeneralMatrix ru; // data in right upper part (nz,d_size)
public:
QuasiTriangularZero(int num_zeros, const double *d, int d_size);
QuasiTriangularZero(int num_zeros, const ConstVector &d, int d_size);
QuasiTriangularZero(double r, const QuasiTriangularZero &t);
QuasiTriangularZero(double r, const QuasiTriangularZero &t,
double rr, const QuasiTriangularZero &tt);

View File

@ -21,7 +21,7 @@ SchurDecomp::SchurDecomp(const SqSylvMatrix &m)
dgees("V", "N", nullptr, &rows, auxt.base(), &rows, &sdim,
wr.data(), wi.data(), q.base(), &rows,
work.data(), &lwork, nullptr, &info);
t_storage = std::make_unique<QuasiTriangular>(auxt.base(), rows);
t_storage = std::make_unique<QuasiTriangular>(auxt.getData(), rows);
t = t_storage.get();
}

View File

@ -11,7 +11,7 @@
#include <cmath>
SimilarityDecomp::SimilarityDecomp(const double *d, int d_size, double log10norm)
SimilarityDecomp::SimilarityDecomp(const ConstVector &d, int d_size, double log10norm)
{
SchurDecomp sd(SqSylvMatrix(d, d_size));
q = std::make_unique<SqSylvMatrix>(sd.getQ());

View File

@ -18,7 +18,7 @@ class SimilarityDecomp
std::unique_ptr<SqSylvMatrix> invq;
using diag_iter = BlockDiagonal::diag_iter;
public:
SimilarityDecomp(const double *d, int d_size, double log10norm = 3.0);
SimilarityDecomp(const ConstVector &d, int d_size, double log10norm = 3.0);
virtual ~SimilarityDecomp() = default;
const SqSylvMatrix &
getQ() const

View File

@ -69,7 +69,7 @@ SylvMatrix::multRightKron(const SqSylvMatrix &m, int order)
KronVector auxrow(m.numRows(), m.numRows(), order-1);
for (int i = 0; i < rows; i++)
{
Vector rowi(data.base()+i, rows, cols);
Vector rowi{getRow(i)};
KronVector rowikron(rowi, m.numRows(), m.numRows(), order-1);
auxrow = rowi; // copy data
m.multVecKronTrans(rowikron, auxrow);
@ -85,7 +85,7 @@ SylvMatrix::multRightKronTrans(const SqSylvMatrix &m, int order)
KronVector auxrow(m.numRows(), m.numRows(), order-1);
for (int i = 0; i < rows; i++)
{
Vector rowi(data.base()+i, rows, cols);
Vector rowi{getRow(i)};
KronVector rowikron(rowi, m.numRows(), m.numRows(), order-1);
auxrow = rowi; // copy data
m.multVecKron(rowikron, auxrow);
@ -169,7 +169,7 @@ SqSylvMatrix::SqSylvMatrix(const GeneralMatrix &a, const GeneralMatrix &b)
}
void
SqSylvMatrix::multVecKron(KronVector &x, const KronVector &d) const
SqSylvMatrix::multVecKron(KronVector &x, const ConstKronVector &d) const
{
x.zeros();
if (d.getDepth() == 0)
@ -196,7 +196,7 @@ SqSylvMatrix::multVecKron(KronVector &x, const KronVector &d) const
}
void
SqSylvMatrix::multVecKronTrans(KronVector &x, const KronVector &d) const
SqSylvMatrix::multVecKronTrans(KronVector &x, const ConstKronVector &d) const
{
x.zeros();
if (d.getDepth() == 0)

View File

@ -17,11 +17,11 @@ public:
: GeneralMatrix(m, n)
{
}
SylvMatrix(const double *d, int m, int n)
SylvMatrix(const ConstVector &d, int m, int n)
: GeneralMatrix(d, m, n)
{
}
SylvMatrix(double *d, int m, int n)
SylvMatrix(Vector &d, int m, int n)
: GeneralMatrix(d, m, n)
{
}
@ -68,10 +68,10 @@ public:
SqSylvMatrix(int m) : SylvMatrix(m, m)
{
}
SqSylvMatrix(const double *d, int m) : SylvMatrix(d, m, m)
SqSylvMatrix(const ConstVector &d, int m) : SylvMatrix(d, m, m)
{
}
SqSylvMatrix(double *d, int m) : SylvMatrix(d, m, m)
SqSylvMatrix(Vector &d, int m) : SylvMatrix(d, m, m)
{
}
SqSylvMatrix(const SqSylvMatrix &m) = default;
@ -91,9 +91,9 @@ public:
return *this;
}
/* x = (this \otimes this..\otimes this)*d */
void multVecKron(KronVector &x, const KronVector &d) const;
void multVecKron(KronVector &x, const ConstKronVector &d) const;
/* x = (this' \otimes this'..\otimes this')*d */
void multVecKronTrans(KronVector &x, const KronVector &d) const;
void multVecKronTrans(KronVector &x, const ConstKronVector &d) const;
/* a = inv(this)*a, b=inv(this)*b */
void multInvLeft2(GeneralMatrix &a, GeneralMatrix &b,
double &rcond1, double &rcondinf) const;

View File

@ -76,7 +76,7 @@ SymSchurDecomp::getFactor(GeneralMatrix &f) const
f = q;
for (int i = 0; i < f.numCols(); i++)
{
Vector fi(f, i);
Vector fi{f.getCol(i)};
fi.mult(std::sqrt(lambda[i]));
}
}

View File

@ -390,7 +390,7 @@ TriangularSylvester::multEigVector(KronVector &eig, const Vector &feig,
{
KronVector eigi(eig, i);
eigi.zeros();
eigi.add(&feig[2*i], aux);
eigi.addComplex({ feig[2*i], feig[2*i+1] }, aux);
}
}
}

View File

@ -19,13 +19,13 @@ using namespace std;
ZeroPad zero_pad;
Vector::Vector(const Vector &v)
: len(v.length()), data(new double[len]), destroy(true)
: len(v.len), data{new double[len], [](double *arr) { delete[] arr; }}
{
copy(v.base(), v.skip());
copy(v.base(), v.s);
}
Vector::Vector(const ConstVector &v)
: len(v.length()), data(new double[len]), destroy(true)
: len(v.length()), data{new double[len], [](double *arr) { delete[] arr; }}
{
copy(v.base(), v.skip());
}
@ -36,9 +36,9 @@ Vector::operator=(const Vector &v)
if (this == &v)
return *this;
if (v.length() != length())
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)
@ -48,23 +48,32 @@ Vector::operator=(const Vector &v)
<< ", data-v.data=" << (unsigned long) (data-v.data)
<< ", len=" << len << std::endl;
throw SYLV_MES_EXCEPTION("Attempt to assign overlapping vectors.");
}
copy(v.base(), v.skip());
} */
copy(v.base(), v.s);
return *this;
}
Vector &
Vector::operator=(Vector &&v)
{
if (v.len != len)
throw SYLV_MES_EXCEPTION("Attempt to assign vectors with different lengths.");
copy(v.base(), v.s);
return *this;
}
Vector &
Vector::operator=(const ConstVector &v)
{
if (v.length() != length())
if (v.length() != 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())))
throw SYLV_MES_EXCEPTION("Attempt to assign overlapping vectors.");
*/
copy(v.base(), v.skip());
return *this;
}
@ -72,37 +81,48 @@ Vector::operator=(const ConstVector &v)
void
Vector::copy(const double *d, int inc)
{
blas_int n = length();
blas_int incy = skip();
blas_int n = len;
blas_int incy = s;
blas_int inc2 = inc;
dcopy(&n, d, &inc2, base(), &incy);
}
Vector::Vector(Vector &v, int off, int l)
: len(l), s(v.skip()), data(v.base()+off*v.skip())
Vector::Vector(Vector &v, int off_arg, int l)
: len(l), off{v.off+off_arg*v.s}, s(v.s), data{v.data}
{
if (off < 0 || off + length() > v.length())
if (off_arg < 0 || off_arg + len > v.len)
throw SYLV_MES_EXCEPTION("Subvector not contained in supvector.");
}
Vector::Vector(const Vector &v, int off, int l)
: len(l), data(new double[len]), destroy(true)
Vector::Vector(const Vector &v, int off_arg, int l)
: len(l), data{new double[len], [](double *arr) { delete[] arr; }}
{
if (off < 0 || off + length() > v.length())
if (off_arg < 0 || off_arg + len > v.len)
throw SYLV_MES_EXCEPTION("Subvector not contained in supvector.");
copy(v.base()+off*v.skip(), v.skip());
copy(v.base()+off_arg*v.s, v.s);
}
Vector::Vector(GeneralMatrix &m, int col)
: len(m.numRows()), data(&(m.get(0, col)))
Vector::Vector(Vector &v, int off_arg, int skip, int l)
: len(l), off{v.off+off_arg*v.s}, s(v.s*skip), data{v.data}
{
}
Vector::Vector(int row, GeneralMatrix &m)
: len(m.numCols()), s(m.getLD()), data(&(m.get(row, 0)))
Vector::Vector(const Vector &v, int off_arg, int skip, int l)
: len(l), data{new double[len], [](double *arr) { delete[] arr; }}
{
copy(v.base()+off_arg*v.s, v.s*skip);
}
#if defined(MATLAB_MEX_FILE) || defined(OCTAVE_MEX_FILE)
Vector::Vector(mxArray *p)
: len{static_cast<int>(mxGetNumberOfElements(p))},
data{std::shared_ptr<double>{mxGetPr(p), [](double *arr) { }}}
{
if (!mxIsDouble(p))
throw SYLV_MES_EXCEPTION("This is not a MATLAB array of doubles.");
}
#endif
bool
Vector::operator==(const Vector &y) const
{
@ -142,18 +162,18 @@ Vector::operator>=(const Vector &y) const
void
Vector::zeros()
{
if (skip() == 1)
if (s == 1)
{
double *p = base();
for (int i = 0; i < length()/ZeroPad::length;
for (int i = 0; i < len/ZeroPad::length;
i++, p += ZeroPad::length)
memcpy(p, zero_pad.getBase(), sizeof(double)*ZeroPad::length);
for (; p < base()+length(); p++)
for (; p < base()+len; p++)
*p = 0.0;
}
else
{
for (int i = 0; i < length(); i++)
for (int i = 0; i < len; i++)
operator[](i) = 0.0;
}
}
@ -161,23 +181,17 @@ Vector::zeros()
void
Vector::nans()
{
for (int i = 0; i < length(); i++)
for (int i = 0; i < len; i++)
operator[](i) = std::numeric_limits<double>::quiet_NaN();
}
void
Vector::infs()
{
for (int i = 0; i < length(); i++)
for (int i = 0; i < len; i++)
operator[](i) = std::numeric_limits<double>::infinity();
}
Vector::~Vector()
{
if (destroy)
delete[] data;
}
void
Vector::rotatePair(double alpha, double beta1, double beta2, int i)
{
@ -195,32 +209,32 @@ Vector::add(double r, const Vector &v)
void
Vector::add(double r, const ConstVector &v)
{
blas_int n = length();
blas_int n = len;
blas_int incx = v.skip();
blas_int incy = skip();
blas_int incy = s;
daxpy(&n, &r, v.base(), &incx, base(), &incy);
}
void
Vector::add(const double *z, const Vector &v)
Vector::addComplex(const std::complex<double> &z, const Vector &v)
{
add(z, ConstVector(v));
addComplex(z, ConstVector(v));
}
void
Vector::add(const double *z, const ConstVector &v)
Vector::addComplex(const std::complex<double> &z, const ConstVector &v)
{
blas_int n = length()/2;
blas_int n = len/2;
blas_int incx = v.skip();
blas_int incy = skip();
zaxpy(&n, z, v.base(), &incx, base(), &incy);
blas_int incy = s;
zaxpy(&n, reinterpret_cast<const double(&)[2]>(z), v.base(), &incx, base(), &incy);
}
void
Vector::mult(double r)
{
blas_int n = length();
blas_int incx = skip();
blas_int n = len;
blas_int incx = s;
dscal(&n, &r, base(), &incx);
}
@ -283,71 +297,74 @@ Vector::print() const
{
auto ff = std::cout.flags();
std::cout << std::setprecision(4);
for (int i = 0; i < length(); i++)
for (int i = 0; i < len; i++)
std::cout << i << '\t' << std::setw(8) << operator[](i) << std::endl;
std::cout.flags(ff);
}
ConstVector::ConstVector(const Vector &v, int off, int l)
: BaseConstVector(l, v.skip(), v.base() + v.skip()*off)
ConstVector::ConstVector(const Vector &v)
: len{v.len}, off{v.off}, s{v.s}, data{v.data}
{
if (off < 0 || off + length() > v.length())
}
ConstVector::ConstVector(const ConstVector &v, int off_arg, int l)
: len{l}, off{v.off+off_arg*v.s}, s{v.s}, data{v.data}
{
if (off_arg < 0 || off_arg + len > v.len)
throw SYLV_MES_EXCEPTION("Subvector not contained in supvector.");
}
ConstVector::ConstVector(const ConstVector &v, int off, int l)
: BaseConstVector(l, v.skip(), v.base() + v.skip()*off)
{
if (off < 0 || off + length() > v.length())
throw SYLV_MES_EXCEPTION("Subvector not contained in supvector.");
}
ConstVector::ConstVector(const double *d, int skip, int l)
: BaseConstVector(l, skip, d)
ConstVector::ConstVector(const ConstVector &v, int off_arg, int skip, int l)
: len(l), off{v.off+off_arg*v.s}, s{v.s*skip}, data{v.data}
{
}
ConstVector::ConstVector(const ConstGeneralMatrix &m, int col)
: BaseConstVector(m.numRows(), 1, &(m.get(0, col)))
ConstVector::ConstVector(std::shared_ptr<const double> d, int skip, int l)
: len{l}, s{skip}, data{std::move(d)}
{
}
ConstVector::ConstVector(int row, const ConstGeneralMatrix &m)
: BaseConstVector(m.numCols(), m.getLD(), &(m.get(row, 0)))
#if defined(MATLAB_MEX_FILE) || defined(OCTAVE_MEX_FILE)
ConstVector::ConstVector(const mxArray *p)
: len{static_cast<int>(mxGetNumberOfElements(p))},
data{std::shared_ptr<const double>{mxGetPr(p), [](const double *arr) { }}}
{
if (!mxIsDouble(p))
throw SYLV_MES_EXCEPTION("This is not a MATLAB array of doubles.");
}
#endif
bool
ConstVector::operator==(const ConstVector &y) const
{
if (length() != y.length())
if (len != y.len)
return false;
if (length() == 0)
if (len == 0)
return true;
int i = 0;
while (i < length() && operator[](i) == y[i])
while (i < len && operator[](i) == y[i])
i++;
return i == length();
return i == len;
}
bool
ConstVector::operator<(const ConstVector &y) const
{
int i = std::min(length(), y.length());
int i = std::min(len, y.len);
int ii = 0;
while (ii < i && operator[](ii) == y[ii])
ii++;
if (ii < i)
return operator[](ii) < y[ii];
else
return length() < y.length();
return len < y.len;
}
double
ConstVector::getNorm() const
{
double s = 0;
for (int i = 0; i < length(); i++)
for (int i = 0; i < len; i++)
s += operator[](i)*operator[](i);
return sqrt(s);
}
@ -356,7 +373,7 @@ double
ConstVector::getMax() const
{
double r = 0;
for (int i = 0; i < length(); i++)
for (int i = 0; i < len; i++)
if (abs(operator[](i)) > r)
r = abs(operator[](i));
return r;
@ -366,7 +383,7 @@ double
ConstVector::getNorm1() const
{
double norm = 0.0;
for (int i = 0; i < length(); i++)
for (int i = 0; i < len; i++)
norm += abs(operator[](i));
return norm;
}
@ -374,11 +391,11 @@ ConstVector::getNorm1() const
double
ConstVector::dot(const ConstVector &y) const
{
if (length() != y.length())
if (len != y.len)
throw SYLV_MES_EXCEPTION("Vector has different length in ConstVector::dot.");
blas_int n = length();
blas_int incx = skip();
blas_int incy = y.skip();
blas_int n = len;
blas_int incx = s;
blas_int incy = y.s;
return ddot(&n, base(), &incx, y.base(), &incy);
}
@ -386,9 +403,9 @@ bool
ConstVector::isFinite() const
{
int i = 0;
while (i < length() && isfinite(operator[](i)))
while (i < len && isfinite(operator[](i)))
i++;
return i == length();
return i == len;
}
void
@ -396,7 +413,7 @@ ConstVector::print() const
{
auto ff = std::cout.flags();
std::cout << std::setprecision(4);
for (int i = 0; i < length(); i++)
for (int i = 0; i < len; i++)
std::cout << i << '\t' << std::setw(8) << operator[](i) << std::endl;
std::cout.flags(ff);
}

View File

@ -10,65 +10,67 @@
* members, and methods are thus duplicated */
#include <array>
#include <memory>
#include <complex>
#if defined(MATLAB_MEX_FILE) || defined(OCTAVE_MEX_FILE)
# include <dynmex.h>
#endif
class GeneralMatrix;
class ConstVector;
class Vector
{
friend class ConstVector;
protected:
int len{0};
int s{1};
double *data{nullptr};
bool destroy{false};
int off{0}; // offset to double* pointer
int s{1}; // stride (also called "skip" in some places)
std::shared_ptr<double> data;
public:
Vector() = default;
Vector(int l) : len(l), data(new double[l]), destroy(true)
{
}
Vector(Vector &v) : len(v.length()), s(v.skip()), data(v.base())
Vector(int l) : len{l}, data{new double[l], [](double *arr) { delete[] arr; }}
{
}
Vector(Vector &v) = default;
Vector(const Vector &v);
Vector(const ConstVector &v);
Vector(const double *d, int l)
: len(l), data(new double[len]), destroy(true)
{
copy(d, 1);
}
Vector(double *d, int l)
: len(l), data(d)
Vector(Vector &&v) = default;
// We don't want implict conversion from ConstVector, since it's expensive
explicit Vector(const ConstVector &v);
Vector(std::shared_ptr<double> d, int l)
: len(l), data{std::move(d)}
{
}
Vector(double *d, int skip, int l)
: len(l), s(skip), data(d)
{
}
Vector(Vector &v, int off, int l);
Vector(const Vector &v, int off, int l);
Vector(GeneralMatrix &m, int col);
Vector(int row, GeneralMatrix &m);
Vector(Vector &v, int off_arg, int l);
Vector(const Vector &v, int off_arg, int l);
Vector(Vector &v, int off_arg, int skip, int l);
Vector(const Vector &v, int off_arg, int skip, int l);
#if defined(MATLAB_MEX_FILE) || defined(OCTAVE_MEX_FILE)
explicit Vector(mxArray *p);
#endif
Vector &operator=(const Vector &v);
Vector &operator=(Vector &&v);
Vector &operator=(const ConstVector &v);
double &
operator[](int i)
{
return data[s*i];
return data.get()[off+s*i];
}
const double &
operator[](int i) const
{
return data[s*i];
return data.get()[off+s*i];
}
const double *
base() const
{
return data;
return data.get() + off;
}
double *
base()
{
return data;
return data.get() + off;
}
int
length() const
@ -90,20 +92,19 @@ public:
bool operator>(const Vector &y) const;
bool operator>=(const Vector &y) const;
virtual ~Vector();
virtual ~Vector() = default;
void zeros();
void nans();
void infs();
bool
toBeDestroyed() const
{
return destroy;
}
void rotatePair(double alpha, double beta1, double beta2, int i);
// Computes this += r*v
void add(double r, const Vector &v);
// Computes this += r*v
void add(double r, const ConstVector &v);
void add(const double *z, const Vector &v);
void add(const double *z, const ConstVector &v);
// Computes this += z*v (where this and v are intepreted as complex vectors)
void addComplex(const std::complex<double> &z, const Vector &v);
// Computes this += z*v (where this and v are intepreted as complex vectors)
void addComplex(const std::complex<double> &z, const ConstVector &v);
void mult(double r);
double getNorm() const;
double getMax() const;
@ -133,31 +134,43 @@ public:
}
private:
void copy(const double *d, int inc);
Vector &operator=(int); // must not be used (not implemented)
Vector &operator=(double); // must not be used (not implemented)
};
class BaseConstVector
class ConstGeneralMatrix;
class ConstVector
{
protected:
int len;
int s;
const double *data;
int off{0}; // offset to double* pointer
int s{1}; // stride (also called "skip" in some places)
std::shared_ptr<const double> data;
public:
BaseConstVector(int l, int si, const double *d) : len(l), s(si), data(d)
// Implicit conversion from Vector is ok, since it's cheap
ConstVector(const Vector &v);
ConstVector(const ConstVector &v) = default;
ConstVector(ConstVector &&v) = default;
ConstVector(std::shared_ptr<const double> d, int l) : len{l}, data{std::move(d)}
{
}
BaseConstVector(const BaseConstVector &v) = default;
BaseConstVector &operator=(const BaseConstVector &v) = default;
ConstVector(const ConstVector &v, int off_arg, int l);
ConstVector(const ConstVector &v, int off_arg, int skip, int l);
ConstVector(std::shared_ptr<const double> d, int skip, int l);
#if defined(MATLAB_MEX_FILE) || defined(OCTAVE_MEX_FILE)
explicit ConstVector(const mxArray *p);
#endif
virtual ~ConstVector() = default;
ConstVector &operator=(const ConstVector &v) = delete;
ConstVector &operator=(ConstVector &&v) = delete;
const double &
operator[](int i) const
{
return data[s*i];
return data.get()[off+s*i];
}
const double *
base() const
{
return data;
return data.get() + off;
}
int
length() const
@ -169,28 +182,6 @@ public:
{
return s;
}
};
class ConstGeneralMatrix;
class ConstVector : public BaseConstVector
{
public:
ConstVector(const Vector &v) : BaseConstVector(v.length(), v.skip(), v.base())
{
}
ConstVector(const ConstVector &v) = default;
ConstVector(const double *d, int l) : BaseConstVector(l, 1, d)
{
}
ConstVector(const Vector &v, int off, int l);
ConstVector(const ConstVector &v, int off, int l);
ConstVector(const double *d, int skip, int l);
ConstVector(const ConstGeneralMatrix &m, int col);
ConstVector(int row, const ConstGeneralMatrix &m);
virtual ~ConstVector() = default;
ConstVector &operator=(const ConstVector &v) = default;
/** Exact equality. */
bool operator==(const ConstVector &y) const;
bool

View File

@ -8,23 +8,23 @@
void
gen_sylv_solve(int order, int n, int m, int zero_cols,
const double *A, const double *B,
const double *C, double *X)
const ConstVector &A, const ConstVector &B,
const ConstVector &C, Vector &X)
{
GeneralSylvester s(order, n, m, zero_cols, A, B, C, X, false);
s.solve();
}
void
mxArray *
gen_sylv_solve_and_check(int order, int n, int m, int zero_cols,
const double *A, const double *B,
const double *C, const double *D,
double *X, mxArray * &p)
const ConstVector &A, const ConstVector &B,
const ConstVector &C, const ConstVector &D,
Vector &X)
{
GeneralSylvester s(order, n, m, zero_cols, A, B, C, X, true);
s.solve();
s.check(D);
p = s.getParams().createStructArray();
return s.getParams().createStructArray();
}
extern "C" {
@ -35,7 +35,7 @@ extern "C" {
if (nhrs != 5 || nlhs > 3 || nlhs < 2)
DYN_MEX_FUNC_ERR_MSG_TXT("Gensylv: Must have exactly 5 input args and either 2 or 3 output args.");
auto order = (int) mxGetScalar(prhs[0]);
auto order = static_cast<int>(mxGetScalar(prhs[0]));
const mxArray *const A = prhs[1];
const mxArray *const B = prhs[2];
const mxArray *const C = prhs[3];
@ -55,28 +55,24 @@ extern "C" {
DYN_MEX_FUNC_ERR_MSG_TXT("Matrix C must be square.");
if (Bdims[0] < Bdims[1])
DYN_MEX_FUNC_ERR_MSG_TXT("Matrix B must not have more columns than rows.");
if (Ddims[1] != (mwSize) power(Cdims[0], order))
if (Ddims[1] != static_cast<mwSize>(power(Cdims[0], order)))
DYN_MEX_FUNC_ERR_MSG_TXT("Matrix D has wrong number of columns.");
int n = Adims[0];
int m = Cdims[0];
int zero_cols = Bdims[0] - Bdims[1];
auto n = static_cast<int>(Adims[0]);
auto m = static_cast<int>(Cdims[0]);
auto zero_cols = static_cast<int>(Bdims[0] - Bdims[1]);
mxArray *X = mxCreateDoubleMatrix(Ddims[0], Ddims[1], mxREAL);
// copy D to X
Vector Xvec((double *)mxGetPr(X), power(m, order)*n);
ConstVector Dvec((double *)mxGetPr(D), power(m, order)*n);
ConstVector Avec{A}, Bvec{B}, Cvec{C}, Dvec{D};
Vector Xvec{X};
Xvec = Dvec;
// solve (or solve and check)
try
{
if (nlhs == 2)
gen_sylv_solve(order, n, m, zero_cols,
mxGetPr(A), mxGetPr(B), mxGetPr(C),
mxGetPr(X));
gen_sylv_solve(order, n, m, zero_cols, Avec, Bvec, Cvec, Xvec);
else if (nlhs == 3)
gen_sylv_solve_and_check(order, n, m, zero_cols,
mxGetPr(A), mxGetPr(B), mxGetPr(C),
mxGetPr(D), mxGetPr(X), plhs[2]);
plhs[2] = gen_sylv_solve_and_check(order, n, m, zero_cols, Avec, Bvec, Cvec, Dvec, Xvec);
}
catch (const SylvException &e)
{

View File

@ -24,12 +24,12 @@ MMMatrixIn::MMMatrixIn(const char *fname)
if (2 != sscanf(buffer, "%d %d", &rows, &cols))
throw MMException("Couldn't parse rows and cols\n");
// read in data
data = (double *) operator new[](rows*cols*sizeof(double));
data = std::shared_ptr<const 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)
{
if (1 != sscanf(buffer, "%lf", &data[i]))
if (1 != sscanf(buffer, "%lf", const_cast<double *>(data.get())+i))
throw MMException(string("Couldn't parse float number ")+buffer+"\n");
i++;
}
@ -42,11 +42,6 @@ MMMatrixIn::MMMatrixIn(const char *fname)
fclose(fd);
}
MMMatrixIn::~MMMatrixIn()
{
operator delete [](data);
}
void
MMMatrixOut::write(const char *fname, int rows, int cols, const double *data)
{

View File

@ -10,6 +10,7 @@
#include <string>
#include <utility>
#include <memory>
using namespace std;
@ -32,16 +33,16 @@ public:
class MMMatrixIn : public MallocAllocator
{
double *data;
std::shared_ptr<const double> data;
int rows;
int cols;
public:
MMMatrixIn(const char *fname);
~MMMatrixIn();
const double *
~MMMatrixIn() = default;
ConstVector
getData() const
{
return data;
return ConstVector{data, size()};
}
int
size() const

View File

@ -33,6 +33,7 @@ public:
{
strncpy(name, n, 100);
}
virtual ~TestRunnable() = default;
bool test() const;
virtual bool run() const = 0;
const char *
@ -117,7 +118,7 @@ TestRunnable::quasi_solve(bool trans, const char *mname, const char *vname)
printf(" Wrong quasi triangular dimensions, rows must be >= cols.\n");
return false;
}
ConstVector v(mmv.getData(), mmv.row());
ConstVector v{mmv.getData()};
Vector x(v.length());
double eig_min = 1.0e20;
if (trans)
@ -158,9 +159,9 @@ TestRunnable::mult_kron(bool trans, const char *mname, const char *vname,
SylvMemoryDriver memdriver(1, m, n, depth);
QuasiTriangular t(mmt.getData(), mmt.row());
Vector vraw(mmv.getData(), mmv.row());
Vector vraw{mmv.getData()};
KronVector v(vraw, m, n, depth);
Vector craw(mmc.getData(), mmc.row());
Vector craw{mmc.getData()};
KronVector c(craw, m, n, depth);
if (trans)
t.multKronTrans(v);
@ -192,9 +193,9 @@ TestRunnable::level_kron(bool trans, const char *mname, const char *vname,
SylvMemoryDriver memdriver(1, m, n, depth);
QuasiTriangular t(mmt.getData(), mmt.row());
Vector vraw(mmv.getData(), mmv.row());
Vector vraw{mmv.getData()};
ConstKronVector v(vraw, m, n, depth);
Vector craw(mmc.getData(), mmc.row());
Vector craw{mmc.getData()};
KronVector c(craw, m, n, depth);
KronVector x(v);
if (trans)
@ -229,9 +230,9 @@ TestRunnable::kron_power(const char *m1name, const char *m2name, const char *vna
SylvMemoryDriver memdriver(2, m, n, depth);
QuasiTriangular t1(mmt1.getData(), mmt1.row());
QuasiTriangular t2(mmt2.getData(), mmt2.row());
Vector vraw(mmv.getData(), mmv.row());
Vector vraw{mmv.getData()};
ConstKronVector v(vraw, m, n, depth);
Vector craw(mmc.getData(), mmc.row());
Vector craw{mmc.getData()};
KronVector c(craw, m, n, depth);
KronVector x(v);
memdriver.setStackMode(true);
@ -267,14 +268,14 @@ TestRunnable::lin_eval(const char *m1name, const char *m2name, const char *vname
QuasiTriangular t1(mmt1.getData(), mmt1.row());
QuasiTriangular t2(mmt2.getData(), mmt2.row());
TriangularSylvester ts(t2, t1);
Vector vraw1(mmv.getData(), length);
ConstVector vraw1{mmv.getData(), 0, length};
ConstKronVector v1(vraw1, m, n, depth);
Vector vraw2(mmv.getData()+length, length);
ConstVector vraw2{mmv.getData(), length, length};
ConstKronVector v2(vraw2, m, n, depth);
Vector craw1(mmc.getData(), length);
KronVector c1(craw1, m, n, depth);
Vector craw2(mmc.getData()+length, length);
KronVector c2(craw2, m, n, depth);
ConstVector craw1{mmc.getData(), 0, length};
ConstKronVector c1(craw1, m, n, depth);
ConstVector craw2{mmc.getData(), length, length};
ConstKronVector c2(craw2, m, n, depth);
KronVector x1(m, n, depth);
KronVector x2(m, n, depth);
memdriver.setStackMode(true);
@ -313,14 +314,14 @@ TestRunnable::qua_eval(const char *m1name, const char *m2name, const char *vname
QuasiTriangular t1(mmt1.getData(), mmt1.row());
QuasiTriangular t2(mmt2.getData(), mmt2.row());
TriangularSylvester ts(t2, t1);
Vector vraw1(mmv.getData(), length);
ConstVector vraw1{mmv.getData(), 0, length};
ConstKronVector v1(vraw1, m, n, depth);
Vector vraw2(mmv.getData()+length, length);
ConstVector vraw2{mmv.getData(), length, length};
ConstKronVector v2(vraw2, m, n, depth);
Vector craw1(mmc.getData(), length);
KronVector c1(craw1, m, n, depth);
Vector craw2(mmc.getData()+length, length);
KronVector c2(craw2, m, n, depth);
ConstVector craw1{mmc.getData(), 0, length};
ConstKronVector c1(craw1, m, n, depth);
ConstVector craw2{mmc.getData(), length, length};
ConstKronVector c2(craw2, m, n, depth);
KronVector x1(m, n, depth);
KronVector x2(m, n, depth);
memdriver.setStackMode(true);
@ -356,7 +357,7 @@ TestRunnable::tri_sylv(const char *m1name, const char *m2name, const char *vname
QuasiTriangular t1(mmt1.getData(), mmt1.row());
QuasiTriangular t2(mmt2.getData(), mmt2.row());
TriangularSylvester ts(t2, t1);
Vector vraw(mmv.getData(), length);
Vector vraw{mmv.getData()};
ConstKronVector v(vraw, m, n, depth);
KronVector d(v); // copy of v
SylvParams pars;
@ -458,7 +459,7 @@ TestRunnable::block_diag(const char *aname, double log10norm)
int n = mma.row();
SylvMemoryDriver memdriver(3, n, n, 2);
SqSylvMatrix orig(mma.getData(), n);
SimilarityDecomp dec(orig.base(), orig.numRows(), log10norm);
SimilarityDecomp dec(orig.getData(), orig.numRows(), log10norm);
dec.getB().printInfo();
SqSylvMatrix check(dec.getQ(), dec.getB());
check.multRight(dec.getInvQ());
@ -506,7 +507,7 @@ TestRunnable::iter_sylv(const char *m1name, const char *m2name, const char *vnam
QuasiTriangular t1(mmt1.getData(), mmt1.row());
QuasiTriangular t2(mmt2.getData(), mmt2.row());
IterativeSylvester is(t2, t1);
Vector vraw(mmv.getData(), length);
Vector vraw{mmv.getData()};
ConstKronVector v(vraw, m, n, depth);
KronVector d(v); // copy of v
SylvParams pars;

View File

@ -181,7 +181,7 @@ UFSTensor::UFSTensor(const UFSTensor &t, const ConstVector &x)
for (int i = 0; i < ncols(); i++)
{
ConstTwoDMatrix tpart(t, i *nvar(), nvar());
Vector outcol(*this, i);
Vector outcol{getCol(i)};
tpart.multaVec(outcol, x);
}
}

View File

@ -182,8 +182,8 @@ KronProdAI::mult(const ConstTwoDMatrix &in, TwoDMatrix &out) const
if (in.getLD() == in.nrows())
{
ConstTwoDMatrix in_resh(in.nrows()*id_cols, a.nrows(), in.getData().base());
TwoDMatrix out_resh(in.nrows()*id_cols, a.ncols(), out.getData().base());
ConstTwoDMatrix in_resh(in.nrows()*id_cols, a.nrows(), in.getData());
TwoDMatrix out_resh(in.nrows()*id_cols, a.ncols(), out.getData());
out_resh.mult(in_resh, a);
}
else
@ -293,7 +293,7 @@ KronProdAll::mult(const ConstTwoDMatrix &in, TwoDMatrix &out) const
}
else
{
last = new TwoDMatrix(in.nrows(), in.ncols(), in.getData().base());
last = new TwoDMatrix(in.nrows(), in.ncols(), in.getData());
}
// perform intermediate multiplications IAI
@ -352,7 +352,7 @@ KronProdAll::multRows(const IntSequence &irows) const
the |row| as ConstVector of this vector, which sheduled for
deallocation. */
if (matlist[j])
row = new ConstVector(irows[j], *(matlist[j]));
row = new ConstVector(matlist[j]->getRow(irows[j]));
else
{
auto *aux = new Vector(ncols(j));

View File

@ -390,7 +390,7 @@ FPSTensor::FPSTensor(const TensorDimens &td, const Equivalence &e, const Permuta
auto su = a.getMap().upper_bound(c);
for (auto srun = sl; srun != su; ++srun)
{
Vector out_row((*srun).second.first, *this);
Vector out_row{getRow((*srun).second.first)};
out_row.add((*srun).second.second, *row_prod);
}
delete row_prod;

View File

@ -68,10 +68,10 @@ USubTensor::addKronColumn(int i, const vector<const FGSTensor *> &ts,
IntSequence ind(pindex, lastdim, lastdim+t->dimen());
lastdim += t->dimen();
index in(t, ind);
tmpcols.emplace_back(*t, *in);
tmpcols.push_back(t->getCol(*in));
}
URSingleTensor kronmult(tmpcols);
Vector coli(*this, i);
Vector coli{getCol(i)};
coli.add(1.0, kronmult.getData());
}

View File

@ -216,7 +216,7 @@ FoldedStackContainer::multAndAddSparse3(const FSSparseTensor &t,
const EquivalenceSet &eset = ebundle.get(out.dimen());
for (Tensor::index run = out.begin(); run != out.end(); ++run)
{
Vector outcol(out, *run);
Vector outcol{out.getCol(*run)};
FRSingleTensor sumcol(t.nvar(), t.dimen());
sumcol.zeros();
for (const auto & it : eset)

View File

@ -249,7 +249,7 @@ public:
const _Ttype *t = getMatrix(i, s);
Tensor::index ind(t, coor);
Vector subres(*res, stack_offsets[i], stack_sizes[i]);
subres = ConstVector(ConstGeneralMatrix(*t), *ind);
subres = ConstGeneralMatrix(*t).getCol(*ind);
i++;
}
if (iu != -1)

View File

@ -64,17 +64,13 @@ TwoDMatrix::copyRow(int from, int to)
void
TwoDMatrix::copyRow(const ConstTwoDMatrix &m, int from, int to)
{
ConstVector fr_row(from, m);
Vector to_row(to, *this);
to_row = fr_row;
getRow(to) = m.getRow(from);
}
void
TwoDMatrix::addRow(double d, const ConstTwoDMatrix &m, int from, int to)
{
ConstVector fr_row(from, m);
Vector to_row(to, *this);
to_row.add(d, fr_row);
getRow(to).add(d, m.getRow(from));
}
void
@ -87,17 +83,13 @@ TwoDMatrix::copyColumn(int from, int to)
void
TwoDMatrix::copyColumn(const ConstTwoDMatrix &m, int from, int to)
{
ConstVector fr_col(m, from);
Vector to_col(*this, to);
to_col = fr_col;
getCol(to) = m.getCol(from);
}
void
TwoDMatrix::addColumn(double d, const ConstTwoDMatrix &m, int from, int to)
{
ConstVector fr_col(m, from);
Vector to_col(*this, to);
to_col.add(d, fr_col);
getCol(to).add(d, m.getCol(from));
}
void

View File

@ -19,6 +19,7 @@
#include <cstdio>
#include <matio.h>
#include <utility>
class TwoDMatrix;
@ -29,10 +30,11 @@ class TwoDMatrix;
class ConstTwoDMatrix : public ConstGeneralMatrix
{
public:
ConstTwoDMatrix(int m, int n, const double *d)
: ConstGeneralMatrix(d, m, n)
ConstTwoDMatrix(int m, int n, ConstVector d)
: ConstGeneralMatrix(std::move(d), m, n)
{
}
// Implicit conversion from TwoDMatrix is ok, since it's cheap
ConstTwoDMatrix(const TwoDMatrix &m);
ConstTwoDMatrix(const TwoDMatrix &m, int first_col, int num);
ConstTwoDMatrix(const ConstTwoDMatrix &m, int first_col, int num);
@ -71,11 +73,11 @@ public:
: GeneralMatrix(r, c)
{
}
TwoDMatrix(int r, int c, double *d)
TwoDMatrix(int r, int c, Vector &d)
: GeneralMatrix(d, r, c)
{
}
TwoDMatrix(int r, int c, const double *d)
TwoDMatrix(int r, int c, const ConstVector &d)
: GeneralMatrix(d, r, c)
{
}
@ -83,6 +85,11 @@ public:
: GeneralMatrix(m)
{
}
// We don't want implict conversion from ConstGeneralMatrix, since it's expensive
explicit TwoDMatrix(const ConstGeneralMatrix &m)
: GeneralMatrix(m)
{
}
TwoDMatrix(const GeneralMatrix &m, const char *dummy)
: GeneralMatrix(m, dummy)
{

View File

@ -124,7 +124,7 @@ Monom1Vector::deriv(int dim) const
= new FGSTensor(len, TensorDimens(Symmetry(dim), IntSequence(1, nx)));
for (Tensor::index it = res->begin(); it != res->end(); ++it)
{
Vector outcol(*res, *it);
Vector outcol{res->getCol(*it)};
deriv(it.getCoor(), outcol);
}
return res;
@ -214,7 +214,7 @@ Monom2Vector::deriv(const Symmetry &s) const
FGSTensor *t = new FGSTensor(len, TensorDimens(s, nvs));
for (Tensor::index it = t->begin(); it != t->end(); ++it)
{
Vector col(*t, *it);
Vector col{t->getCol(*it)};
deriv(s, it.getCoor(), col);
}
return t;
@ -392,7 +392,7 @@ Monom4Vector::deriv(const Symmetry &s) const
FGSTensor *res = new FGSTensor(len, TensorDimens(s, nvs));
for (Tensor::index run = res->begin(); run != res->end(); ++run)
{
Vector col(*res, *run);
Vector col{res->getCol(*run)};
deriv(s, run.getCoor(), col);
}
return res;

View File

@ -45,7 +45,7 @@ DynamicModelMFile::eval(const Vector &y, const Vector &x, const Vector &modParam
if (retVal != 0)
throw DynareException(__FILE__, __LINE__, "Trouble calling " + DynamicMFilename);
residual = Vector(mxGetPr(plhs[0]), residual.skip(), (int) mxGetM(plhs[0]));
residual = Vector{plhs[0]};
copyDoubleIntoTwoDMatData(mxGetPr(plhs[1]), g1, (int) mxGetM(plhs[1]), (int) mxGetN(plhs[1]));
if (g2 != nullptr)
unpackSparseMatrixAndCopyIntoTwoDMatData(plhs[2], g2);

View File

@ -89,15 +89,15 @@ KordpDynare::solveDeterministicSteady()
}
void
KordpDynare::evaluateSystem(Vector &out, const Vector &yy, const Vector &xx) noexcept(false)
KordpDynare::evaluateSystem(Vector &out, const ConstVector &yy, const Vector &xx) noexcept(false)
{
// This method is only called when checking the residuals at steady state (Approximation::check), so return zero residuals
out.zeros();
}
void
KordpDynare::evaluateSystem(Vector &out, const Vector &yym, const Vector &yy,
const Vector &yyp, const Vector &xx) noexcept(false)
KordpDynare::evaluateSystem(Vector &out, const ConstVector &yym, const ConstVector &yy,
const ConstVector &yyp, const Vector &xx) noexcept(false)
{
// This method is only called when checking the residuals at steady state (Approximation::check), so return zero residuals
out.zeros();

View File

@ -230,9 +230,9 @@ public:
}
void solveDeterministicSteady();
void evaluateSystem(Vector &out, const Vector &yy, const Vector &xx) noexcept(false);
void evaluateSystem(Vector &out, const Vector &yym, const Vector &yy,
const Vector &yyp, const Vector &xx) noexcept(false);
void evaluateSystem(Vector &out, const ConstVector &yy, const Vector &xx) noexcept(false);
void evaluateSystem(Vector &out, const ConstVector &yym, const ConstVector &yy,
const ConstVector &yyp, const Vector &xx) noexcept(false);
void calcDerivativesAtSteady();
unique_ptr<DynamicModelAC> dynamicModelFile;
DynamicModel *

View File

@ -111,23 +111,18 @@ extern "C" {
qz_criterium = (double) mxGetScalar(mxFldp);
mxFldp = mxGetField(M_, 0, "params");
double *dparams = mxGetPr(mxFldp);
int npar = (int) mxGetM(mxFldp);
Vector modParams(dparams, npar);
Vector modParams{mxFldp};
if (!modParams.isFinite())
DYN_MEX_FUNC_ERR_MSG_TXT("The parameters vector contains NaN or Inf");
mxFldp = mxGetField(M_, 0, "Sigma_e");
dparams = mxGetPr(mxFldp);
npar = (int) mxGetN(mxFldp);
TwoDMatrix vCov(npar, npar, dparams);
int npar = static_cast<int>(mxGetN(mxFldp));
TwoDMatrix vCov(npar, npar, Vector{mxFldp});
if (!vCov.isFinite())
DYN_MEX_FUNC_ERR_MSG_TXT("The covariance matrix of shocks contains NaN or Inf");
mxFldp = mxGetField(dr, 0, "ys"); // and not in order of dr.order_var
dparams = mxGetPr(mxFldp);
const int nSteady = (int) mxGetM(mxFldp);
Vector ySteady(dparams, nSteady);
Vector ySteady{mxFldp};
if (!ySteady.isFinite())
DYN_MEX_FUNC_ERR_MSG_TXT("The steady state vector contains NaN or Inf");
@ -152,7 +147,7 @@ extern "C" {
const int nPar = (int) mxGetScalar(mxFldp);
mxFldp = mxGetField(dr, 0, "order_var");
dparams = mxGetPr(mxFldp);
auto dparams = mxGetPr(mxFldp);
npar = (int) mxGetM(mxFldp);
if (npar != nEndo)
DYN_MEX_FUNC_ERR_MSG_TXT("Incorrect number of input var_order vars.");
@ -163,11 +158,10 @@ extern "C" {
// the lag, current and lead blocks of the jacobian respectively
mxFldp = mxGetField(M_, 0, "lead_lag_incidence");
dparams = mxGetPr(mxFldp);
npar = (int) mxGetN(mxFldp);
int nrows = (int) mxGetM(mxFldp);
TwoDMatrix llincidence(nrows, npar, dparams);
TwoDMatrix llincidence(nrows, npar, Vector{mxFldp});
if (npar != nEndo)
{
ostringstream strstrm;
@ -176,8 +170,7 @@ extern "C" {
}
//get NNZH =NNZD(2) = the total number of non-zero Hessian elements
mxFldp = mxGetField(M_, 0, "NNZDerivatives");
dparams = mxGetPr(mxFldp);
Vector NNZD(dparams, (int)mxGetM(mxFldp));
Vector NNZD{mxFldp};
if (NNZD[kOrder-1] == -1)
DYN_MEX_FUNC_ERR_MSG_TXT("The derivatives were not computed for the required order. Make sure that you used the right order option inside the stoch_simul command");
@ -207,19 +200,19 @@ extern "C" {
const mxArray *g1 = prhs[3];
int m = (int) mxGetM(g1);
int n = (int) mxGetN(g1);
g1m = new TwoDMatrix(m, n, mxGetPr(g1));
g1m = new TwoDMatrix(m, n, ConstVector{g1});
if (nrhs > 4)
{
const mxArray *g2 = prhs[4];
int m = (int) mxGetM(g2);
int n = (int) mxGetN(g2);
g2m = new TwoDMatrix(m, n, mxGetPr(g2));
g2m = new TwoDMatrix(m, n, ConstVector{g2});
if (nrhs > 5)
{
const mxArray *g3 = prhs[5];
int m = (int) mxGetM(g3);
int n = (int) mxGetN(g3);
g3m = new TwoDMatrix(m, n, mxGetPr(g3));
g3m = new TwoDMatrix(m, n, ConstVector{g3});
}
}
}