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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -84,7 +84,7 @@ public:
return std::make_unique<ResidFunction>(*this); return std::make_unique<ResidFunction>(*this);
} }
void eval(const Vector &point, const ParameterSignal &sig, Vector &out) override; 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|. */ /* This is a |ResidFunction| wrapped with |GaussConverterFunction|. */
@ -104,7 +104,7 @@ public:
return std::make_unique<GResidFunction>(*this); return std::make_unique<GResidFunction>(*this);
} }
void void
setYU(const Vector &ys, const Vector &xx) setYU(const ConstVector &ys, const ConstVector &xx)
{ {
((ResidFunction *) func)->setYU(ys, 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)))); TwoDMatrix gs_y(*(gs<unfold>().get(Symmetry(1, 0, 0, 0))));
GeneralSylvester sylv(der.getSym()[0], ny, ypart.nys(), GeneralSylvester sylv(der.getSym()[0], ny, ypart.nys(),
ypart.nstat+ypart.npred, ypart.nstat+ypart.npred,
matA.getData().base(), matB.getData().base(), matA.getData(), matB.getData(),
gs_y.getData().base(), der.getData().base()); gs_y.getData(), der.getData());
sylv.solve(); sylv.solve();
} }
else if (ypart.nys() > 0 && ypart.nyss() == 0) else if (ypart.nys() > 0 && ypart.nyss() == 0)

View File

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

View File

@ -13,6 +13,13 @@ struct Rand
static bool discrete(double prob); // answers true with given probability 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 void
Rand::init(int n1, int n2, int n3, int n4, int n5) Rand::init(int n1, int n2, int n3, int n4, int n5)
{ {
@ -345,9 +352,9 @@ public:
bool bool
run() const override run() const override
{ {
TwoDMatrix gy(8, 4, gy_data); TwoDMatrix gy{make_matrix(8, 4, gy_data)};
TwoDMatrix gu(8, 3, gu_data); TwoDMatrix gu{make_matrix(8, 3, gu_data)};
TwoDMatrix v(3, 3, vdata); TwoDMatrix v{make_matrix(3, 3, vdata)};
double err = korder_unfold_fold(4, 3, 2, 3, 1, 2, double err = korder_unfold_fold(4, 3, 2, 3, 1, 2,
gy, gu, v); gy, gu, v);
@ -368,9 +375,9 @@ public:
bool bool
run() const override run() const override
{ {
TwoDMatrix gy(30, 20, gy_data2); TwoDMatrix gy{make_matrix(30, 20, gy_data2)};
TwoDMatrix gu(30, 10, gu_data2); TwoDMatrix gu{make_matrix(30, 10, gu_data2)};
TwoDMatrix v(10, 10, vdata2); TwoDMatrix v{make_matrix(10, 10, vdata2)};
v.mult(0.001); v.mult(0.001);
gu.mult(.01); gu.mult(.01);
double err = korder_unfold_fold(4, 4, 5, 12, 8, 5, double err = korder_unfold_fold(4, 4, 5, 12, 8, 5,
@ -392,9 +399,9 @@ public:
bool bool
run() const override run() const override
{ {
TwoDMatrix gy(30, 20, gy_data2); TwoDMatrix gy{make_matrix(30, 20, gy_data2)};
TwoDMatrix gu(30, 10, gu_data2); TwoDMatrix gu{make_matrix(30, 10, gu_data2)};
TwoDMatrix v(10, 10, vdata2); TwoDMatrix v{make_matrix(10, 10, vdata2)};
v.mult(0.001); v.mult(0.001);
gu.mult(.01); gu.mult(.01);
double err = korder_unfold_fold(4, 3, 5, 12, 8, 5, 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 // evaluate system at given y_t=y_{t+1}=y_{t-1}, and given shocks x_t
void 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 yym(yy, nstat(), nys());
ConstVector yyp(yy, nstat()+npred(), nyss()); 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 // exogenous x_t, all three vectors yym, yy, and yyp have the
// respective lengths of y^*_{t-1}, y_t, y^{**}_{t+1} // respective lengths of y^*_{t-1}, y_t, y^{**}_{t+1}
void void
Dynare::evaluateSystem(Vector &out, const Vector &yym, const Vector &yy, Dynare::evaluateSystem(Vector &out, const ConstVector &yym, const ConstVector &yy,
const Vector &yyp, const Vector &xx) const ConstVector &yyp, const Vector &xx)
{ {
ogdyn::DynareAtomValues dav(model->getAtoms(), model->getParams(), yym, yy, yyp, xx); ogdyn::DynareAtomValues dav(model->getAtoms(), model->getParams(), yym, yy, yyp, xx);
DynareEvalLoader del(model->getAtoms(), out); DynareEvalLoader del(model->getAtoms(), out);

View File

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

View File

@ -112,7 +112,7 @@ namespace ogdyn
{ {
} }
DynareAtomValues(const ogp::FineAtoms &a, const Vector &pvals, const ConstVector &ym, 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) : 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) if (params.num_condper > 0 && params.num_condsim > 0)
{ {
SimResultsDynamicStats rescond(dynare.numeq(), params.num_condper, 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.simulate(params.num_condsim, app.getFoldDecisionRule(), det_ss, dynare.getVcov(), journal);
rescond.writeMat(matfd, params.prefix); rescond.writeMat(matfd, params.prefix);
} }

View File

@ -6,9 +6,10 @@
#include <iostream> #include <iostream>
#include <cstring> #include <cstring>
#include <utility>
BlockDiagonal::BlockDiagonal(const double *d, int d_size) BlockDiagonal::BlockDiagonal(ConstVector d, int d_size)
: QuasiTriangular(d, d_size), : QuasiTriangular(std::move(d), d_size),
row_len(new int[d_size]), col_len(new int[d_size]) row_len(new int[d_size]), col_len(new int[d_size])
{ {
for (int i = 0; i < d_size; i++) for (int i = 0; i < d_size; i++)

View File

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

View File

@ -16,8 +16,6 @@
#include <limits> #include <limits>
#include <vector> #include <vector>
int GeneralMatrix::md_length = 32;
GeneralMatrix::GeneralMatrix(const GeneralMatrix &m) GeneralMatrix::GeneralMatrix(const GeneralMatrix &m)
: data(m.rows*m.cols), rows(m.rows), cols(m.cols), ld(m.rows) : 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) 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) : data(a.rows*b.cols), rows(a.rows), cols(b.cols), ld(a.rows)
{ {
gemm("N", a, "N", b, 1.0, 0.0); 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) : data(a.rows*b.rows), rows(a.rows), cols(b.rows), ld(a.rows)
{ {
gemm("N", a, "T", b, 1.0, 0.0); 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) : data(a.cols*b.cols), rows(a.cols), cols(b.cols), ld(a.cols)
{ {
gemm("T", a, "N", b, 1.0, 0.0); gemm("T", a, "N", b, 1.0, 0.0);
} }
GeneralMatrix::GeneralMatrix(const GeneralMatrix &a, const char *dum1, GeneralMatrix::GeneralMatrix(const ConstGeneralMatrix &a, const char *dum1,
const GeneralMatrix &b, const char *dum2) const ConstGeneralMatrix &b, const char *dum2)
: data(a.cols*b.rows), rows(a.cols), cols(b.rows), ld(a.cols) : data(a.cols*b.rows), rows(a.cols), cols(b.rows), ld(a.cols)
{ {
gemm("T", a, "T", b, 1.0, 0.0); 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 void
GeneralMatrix::place(const ConstGeneralMatrix &m, int i, int j) 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 double
ConstGeneralMatrix::getNormInf() const ConstGeneralMatrix::getNormInf() const
{ {
double norm = 0.0; double norm = 0.0;
for (int i = 0; i < numRows(); i++) for (int i = 0; i < numRows(); i++)
{ {
ConstVector rowi(data.base()+i, ld, cols); double normi = getRow(i).getNorm1();
double normi = rowi.getNorm1();
if (norm < normi) if (norm < normi)
norm = normi; norm = normi;
} }
@ -377,8 +410,7 @@ ConstGeneralMatrix::getNorm1() const
double norm = 0.0; double norm = 0.0;
for (int j = 0; j < numCols(); j++) for (int j = 0; j < numCols(); j++)
{ {
ConstVector colj(data.base()+ld *j, 1, rows); double normj = getCol(j).getNorm1();
double normj = colj.getNorm1();
if (norm < normj) if (norm < normj)
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()); GeneralMatrix Bprime(UTB, m-minmn, 0, minmn-nz, B.numCols());
// solve sigma // solve sigma
for (int i = 0; i < minmn-nz; i++) 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 // solve VT
X.zeros(); X.zeros();
//- copy Bprime to right place of X //- copy Bprime to right place of X
for (int i = 0; i < minmn-nz; i++) 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 //- multiply with VT
X.multLeftTrans(VT); X.multLeftTrans(VT);
} }

View File

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

View File

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

View File

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

View File

@ -18,7 +18,7 @@ KronUtils::multAtLevel(int level, const QuasiTriangular &t,
} }
else if (0 == level && 0 < x.getDepth()) 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); t.multLeftOther(tmp);
} }
else if (0 == level && 0 == x.getDepth()) 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()) 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); t.multLeftOtherTrans(tmp);
} }
else if (level == 0 && 0 == x.getDepth()) else if (level == 0 && 0 == x.getDepth())

View File

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

View File

@ -16,13 +16,12 @@ protected:
int n{0}; int n{0};
int depth{0}; int depth{0};
public: public:
KronVector() : Vector((double *) nullptr, 0) KronVector() = default;
{
}
KronVector(int mm, int nn, int dp); // new instance KronVector(int mm, int nn, int dp); // new instance
KronVector(Vector &v, int mm, int nn, int dp); // conversion KronVector(Vector &v, int mm, int nn, int dp); // conversion
KronVector(KronVector &, int i); // picks i-th subvector 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 KronVector &v) = default;
KronVector &operator=(const ConstKronVector &v); KronVector &operator=(const ConstKronVector &v);
KronVector &operator=(const Vector &v); KronVector &operator=(const Vector &v);
@ -50,10 +49,11 @@ protected:
int n; int n;
int depth; int depth;
public: public:
// Implicit conversion from KronVector is ok, since it's cheap
ConstKronVector(const KronVector &v); ConstKronVector(const KronVector &v);
ConstKronVector(const ConstKronVector &v); ConstKronVector(const ConstKronVector &v);
ConstKronVector(const Vector &v, int mm, int nn, int dp); 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 KronVector &v, int i);
ConstKronVector(const ConstKronVector &v, int i); ConstKronVector(const ConstKronVector &v, int i);
int 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) : SqSylvMatrix(d, d_size), diagonal(getData().base(), d_size)
{ {
} }
@ -679,8 +679,8 @@ void
QuasiTriangular::multaKron(KronVector &x, const ConstKronVector &b) const QuasiTriangular::multaKron(KronVector &x, const ConstKronVector &b) const
{ {
int id = b.getN()*power(b.getM(), b.getDepth()-1); int id = b.getN()*power(b.getM(), b.getDepth()-1);
ConstGeneralMatrix b_resh(b.base(), id, b.getM()); ConstGeneralMatrix b_resh(b, id, b.getM());
GeneralMatrix x_resh(x.base(), id, b.getM()); GeneralMatrix x_resh(x, id, b.getM());
x_resh.multAndAdd(b_resh, ConstGeneralMatrix(*this), "trans"); x_resh.multAndAdd(b_resh, ConstGeneralMatrix(*this), "trans");
} }
@ -689,8 +689,8 @@ void
QuasiTriangular::multaKronTrans(KronVector &x, const ConstKronVector &b) const QuasiTriangular::multaKronTrans(KronVector &x, const ConstKronVector &b) const
{ {
int id = b.getN()*power(b.getM(), b.getDepth()-1); int id = b.getN()*power(b.getM(), b.getDepth()-1);
ConstGeneralMatrix b_resh(b.base(), id, b.getM()); ConstGeneralMatrix b_resh(b, id, b.getM());
GeneralMatrix x_resh(x.base(), id, b.getM()); GeneralMatrix x_resh(x, id, b.getM());
x_resh.multAndAdd(b_resh, ConstGeneralMatrix(*this)); x_resh.multAndAdd(b_resh, ConstGeneralMatrix(*this));
} }

View File

@ -399,7 +399,7 @@ public:
protected: protected:
Diagonal diagonal; Diagonal diagonal;
public: 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);
QuasiTriangular(double r, const QuasiTriangular &t, QuasiTriangular(double r, const QuasiTriangular &t,
double rr, const QuasiTriangular &tt); double rr, const QuasiTriangular &tt);

View File

@ -8,14 +8,15 @@
#include "SylvException.hh" #include "SylvException.hh"
#include <iostream> #include <iostream>
#include <utility>
QuasiTriangularZero::QuasiTriangularZero(int num_zeros, const double *d, QuasiTriangularZero::QuasiTriangularZero(int num_zeros, const ConstVector &d,
int d_size) int d_size)
: QuasiTriangular(SqSylvMatrix(GeneralMatrix(d, num_zeros+d_size, 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), d_size),
nz(num_zeros), 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) QuasiTriangularZero::QuasiTriangularZero(const SchurDecompZero &decomp)
: QuasiTriangular(decomp.getT().getData().base(), : QuasiTriangular(decomp.getT().getData(),
decomp.getT().numRows()), decomp.getT().numRows()),
nz(decomp.getZeroCols()), nz(decomp.getZeroCols()),
ru(decomp.getRU()) ru(decomp.getRU())

View File

@ -15,7 +15,7 @@ class QuasiTriangularZero : public QuasiTriangular
int nz; // number of zero columns int nz; // number of zero columns
GeneralMatrix ru; // data in right upper part (nz,d_size) GeneralMatrix ru; // data in right upper part (nz,d_size)
public: 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);
QuasiTriangularZero(double r, const QuasiTriangularZero &t, QuasiTriangularZero(double r, const QuasiTriangularZero &t,
double rr, const QuasiTriangularZero &tt); 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, dgees("V", "N", nullptr, &rows, auxt.base(), &rows, &sdim,
wr.data(), wi.data(), q.base(), &rows, wr.data(), wi.data(), q.base(), &rows,
work.data(), &lwork, nullptr, &info); 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(); t = t_storage.get();
} }

View File

@ -11,7 +11,7 @@
#include <cmath> #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)); SchurDecomp sd(SqSylvMatrix(d, d_size));
q = std::make_unique<SqSylvMatrix>(sd.getQ()); q = std::make_unique<SqSylvMatrix>(sd.getQ());

View File

@ -18,7 +18,7 @@ class SimilarityDecomp
std::unique_ptr<SqSylvMatrix> invq; std::unique_ptr<SqSylvMatrix> invq;
using diag_iter = BlockDiagonal::diag_iter; using diag_iter = BlockDiagonal::diag_iter;
public: 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; virtual ~SimilarityDecomp() = default;
const SqSylvMatrix & const SqSylvMatrix &
getQ() const getQ() const

View File

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

View File

@ -17,11 +17,11 @@ public:
: GeneralMatrix(m, n) : GeneralMatrix(m, n)
{ {
} }
SylvMatrix(const double *d, int m, int n) SylvMatrix(const ConstVector &d, int m, int n)
: GeneralMatrix(d, m, n) : GeneralMatrix(d, m, n)
{ {
} }
SylvMatrix(double *d, int m, int n) SylvMatrix(Vector &d, int m, int n)
: GeneralMatrix(d, m, n) : GeneralMatrix(d, m, n)
{ {
} }
@ -68,10 +68,10 @@ public:
SqSylvMatrix(int m) : SylvMatrix(m, m) 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; SqSylvMatrix(const SqSylvMatrix &m) = default;
@ -91,9 +91,9 @@ public:
return *this; return *this;
} }
/* x = (this \otimes this..\otimes this)*d */ /* 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 */ /* 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 */ /* a = inv(this)*a, b=inv(this)*b */
void multInvLeft2(GeneralMatrix &a, GeneralMatrix &b, void multInvLeft2(GeneralMatrix &a, GeneralMatrix &b,
double &rcond1, double &rcondinf) const; double &rcond1, double &rcondinf) const;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -182,8 +182,8 @@ KronProdAI::mult(const ConstTwoDMatrix &in, TwoDMatrix &out) const
if (in.getLD() == in.nrows()) if (in.getLD() == in.nrows())
{ {
ConstTwoDMatrix in_resh(in.nrows()*id_cols, a.nrows(), in.getData().base()); ConstTwoDMatrix in_resh(in.nrows()*id_cols, a.nrows(), in.getData());
TwoDMatrix out_resh(in.nrows()*id_cols, a.ncols(), out.getData().base()); TwoDMatrix out_resh(in.nrows()*id_cols, a.ncols(), out.getData());
out_resh.mult(in_resh, a); out_resh.mult(in_resh, a);
} }
else else
@ -293,7 +293,7 @@ KronProdAll::mult(const ConstTwoDMatrix &in, TwoDMatrix &out) const
} }
else else
{ {
last = new TwoDMatrix(in.nrows(), in.ncols(), in.getData().base()); last = new TwoDMatrix(in.nrows(), in.ncols(), in.getData());
} }
// perform intermediate multiplications IAI // perform intermediate multiplications IAI
@ -352,7 +352,7 @@ KronProdAll::multRows(const IntSequence &irows) const
the |row| as ConstVector of this vector, which sheduled for the |row| as ConstVector of this vector, which sheduled for
deallocation. */ deallocation. */
if (matlist[j]) if (matlist[j])
row = new ConstVector(irows[j], *(matlist[j])); row = new ConstVector(matlist[j]->getRow(irows[j]));
else else
{ {
auto *aux = new Vector(ncols(j)); 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); auto su = a.getMap().upper_bound(c);
for (auto srun = sl; srun != su; ++srun) 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); out_row.add((*srun).second.second, *row_prod);
} }
delete 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()); IntSequence ind(pindex, lastdim, lastdim+t->dimen());
lastdim += t->dimen(); lastdim += t->dimen();
index in(t, ind); index in(t, ind);
tmpcols.emplace_back(*t, *in); tmpcols.push_back(t->getCol(*in));
} }
URSingleTensor kronmult(tmpcols); URSingleTensor kronmult(tmpcols);
Vector coli(*this, i); Vector coli{getCol(i)};
coli.add(1.0, kronmult.getData()); coli.add(1.0, kronmult.getData());
} }

View File

@ -216,7 +216,7 @@ FoldedStackContainer::multAndAddSparse3(const FSSparseTensor &t,
const EquivalenceSet &eset = ebundle.get(out.dimen()); const EquivalenceSet &eset = ebundle.get(out.dimen());
for (Tensor::index run = out.begin(); run != out.end(); ++run) 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()); FRSingleTensor sumcol(t.nvar(), t.dimen());
sumcol.zeros(); sumcol.zeros();
for (const auto & it : eset) for (const auto & it : eset)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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