Dynare++: refactor iterator over symmetries
Simplify the logic of iteration. Adapt the range-based for loop syntax.time-shift
parent
e9688560f6
commit
44d47ee560
|
@ -112,12 +112,11 @@ SmolyakQuadrature::SmolyakQuadrature(int d, int l, const OneDQuadrature &uq)
|
||||||
// todo: check |l>1|, |l>=d|
|
// todo: check |l>1|, |l>=d|
|
||||||
// todo: check |l>=uquad.miLevel()|, |l<=uquad.maxLevel()|
|
// todo: check |l>=uquad.miLevel()|, |l<=uquad.maxLevel()|
|
||||||
int cum = 0;
|
int cum = 0;
|
||||||
SymmetrySet ss(l-1, d+1);
|
for (auto &si : SymmetrySet(l-1, d+1))
|
||||||
for (symiterator si(ss); !si.isEnd(); ++si)
|
|
||||||
{
|
{
|
||||||
if ((*si)[d] <= d-1)
|
if (si[d] <= d-1)
|
||||||
{
|
{
|
||||||
IntSequence lev((const IntSequence &)*si, 0, d);
|
IntSequence lev((const IntSequence &) si, 0, d);
|
||||||
lev.add(1);
|
lev.add(1);
|
||||||
levels.push_back(lev);
|
levels.push_back(lev);
|
||||||
IntSequence levpts(d);
|
IntSequence levpts(d);
|
||||||
|
@ -171,12 +170,11 @@ int
|
||||||
SmolyakQuadrature::calcNumEvaluations(int lev) const
|
SmolyakQuadrature::calcNumEvaluations(int lev) const
|
||||||
{
|
{
|
||||||
int cum = 0;
|
int cum = 0;
|
||||||
SymmetrySet ss(lev-1, dim+1);
|
for (auto &si : SymmetrySet(lev-1, dim+1))
|
||||||
for (symiterator si(ss); !si.isEnd(); ++si)
|
|
||||||
{
|
{
|
||||||
if ((*si)[dim] <= dim-1)
|
if (si[dim] <= dim-1)
|
||||||
{
|
{
|
||||||
IntSequence lev((const IntSequence &)*si, 0, dim);
|
IntSequence lev((const IntSequence &) si, 0, dim);
|
||||||
lev.add(1);
|
lev.add(1);
|
||||||
IntSequence levpts(dim);
|
IntSequence levpts(dim);
|
||||||
for (int i = 0; i < dim; i++)
|
for (int i = 0; i < dim; i++)
|
||||||
|
|
|
@ -342,30 +342,27 @@ KOrder::switchToFolded()
|
||||||
|
|
||||||
int maxdim = g<unfold>().getMaxDim();
|
int maxdim = g<unfold>().getMaxDim();
|
||||||
for (int dim = 1; dim <= maxdim; dim++)
|
for (int dim = 1; dim <= maxdim; dim++)
|
||||||
{
|
for (auto &si : SymmetrySet(dim, 4))
|
||||||
SymmetrySet ss(dim, 4);
|
{
|
||||||
for (symiterator si(ss); !si.isEnd(); ++si)
|
if (si[2] == 0 && g<unfold>().check(si))
|
||||||
{
|
{
|
||||||
if ((*si)[2] == 0 && g<unfold>().check(*si))
|
auto *ft = new FGSTensor(*(g<unfold>().get(si)));
|
||||||
{
|
insertDerivative<fold>(ft);
|
||||||
auto *ft = new FGSTensor(*(g<unfold>().get(*si)));
|
if (dim > 1)
|
||||||
insertDerivative<fold>(ft);
|
{
|
||||||
if (dim > 1)
|
gss<unfold>().remove(si);
|
||||||
{
|
gs<unfold>().remove(si);
|
||||||
gss<unfold>().remove(*si);
|
g<unfold>().remove(si);
|
||||||
gs<unfold>().remove(*si);
|
}
|
||||||
g<unfold>().remove(*si);
|
}
|
||||||
}
|
if (G<unfold>().check(si))
|
||||||
}
|
{
|
||||||
if (G<unfold>().check(*si))
|
auto *ft = new FGSTensor(*(G<unfold>().get(si)));
|
||||||
{
|
G<fold>().insert(ft);
|
||||||
auto *ft = new FGSTensor(*(G<unfold>().get(*si)));
|
if (dim > 1)
|
||||||
G<fold>().insert(ft);
|
{
|
||||||
if (dim > 1)
|
G<fold>().remove(si);
|
||||||
{
|
}
|
||||||
G<fold>().remove(*si);
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -871,12 +871,11 @@ KOrder::check(int dim) const
|
||||||
}
|
}
|
||||||
|
|
||||||
// check for $F_{y^iu^ju'^k}+D_{ijk}+E_{ijk}=0$
|
// check for $F_{y^iu^ju'^k}+D_{ijk}+E_{ijk}=0$
|
||||||
SymmetrySet ss(dim, 3);
|
for (auto &si : SymmetrySet(dim, 3))
|
||||||
for (symiterator si(ss); !si.isEnd(); ++si)
|
|
||||||
{
|
{
|
||||||
int i = (*si)[0];
|
int i = si[0];
|
||||||
int j = (*si)[1];
|
int j = si[1];
|
||||||
int k = (*si)[2];
|
int k = si[2];
|
||||||
if (i+j > 0 && k > 0)
|
if (i+j > 0 && k > 0)
|
||||||
{
|
{
|
||||||
Symmetry sym{i, j, 0, k};
|
Symmetry sym{i, j, 0, k};
|
||||||
|
|
|
@ -516,18 +516,17 @@ KOrderStoch::performStep(int order)
|
||||||
int maxd = g<t>().getMaxDim();
|
int maxd = g<t>().getMaxDim();
|
||||||
KORD_RAISE_IF(order-1 != maxd && (order != 1 || maxd != -1),
|
KORD_RAISE_IF(order-1 != maxd && (order != 1 || maxd != -1),
|
||||||
"Wrong order for KOrderStoch::performStep");
|
"Wrong order for KOrderStoch::performStep");
|
||||||
SymmetrySet ss(order, 4);
|
for (auto &si : SymmetrySet(order, 4))
|
||||||
for (symiterator si(ss); !si.isEnd(); ++si)
|
|
||||||
{
|
{
|
||||||
if ((*si)[2] == 0)
|
if (si[2] == 0)
|
||||||
{
|
{
|
||||||
JournalRecordPair pa(journal);
|
JournalRecordPair pa(journal);
|
||||||
pa << "Recovering symmetry " << *si << endrec;
|
pa << "Recovering symmetry " << si << endrec;
|
||||||
|
|
||||||
_Ttensor *G_sym = faaDiBrunoG<t>(*si);
|
_Ttensor *G_sym = faaDiBrunoG<t>(si);
|
||||||
G<t>().insert(G_sym);
|
G<t>().insert(G_sym);
|
||||||
|
|
||||||
_Ttensor *g_sym = faaDiBrunoZ<t>(*si);
|
_Ttensor *g_sym = faaDiBrunoZ<t>(si);
|
||||||
g_sym->mult(-1.0);
|
g_sym->mult(-1.0);
|
||||||
matA.multInv(*g_sym);
|
matA.multInv(*g_sym);
|
||||||
g<t>().insert(g_sym);
|
g<t>().insert(g_sym);
|
||||||
|
|
|
@ -42,10 +42,10 @@ FoldedStackContainer::multAndAdd(int dim, const FGSContainer &c, FGSTensor &out)
|
||||||
"Wrong symmetry length of container for FoldedStackContainer::multAndAdd");
|
"Wrong symmetry length of container for FoldedStackContainer::multAndAdd");
|
||||||
|
|
||||||
sthread::detach_thread_group gr;
|
sthread::detach_thread_group gr;
|
||||||
SymmetrySet ss(dim, c.num());
|
|
||||||
for (symiterator si(ss); !si.isEnd(); ++si)
|
for (auto &si : SymmetrySet(dim, c.num()))
|
||||||
if (c.check(*si))
|
if (c.check(si))
|
||||||
gr.insert(std::make_unique<WorkerFoldMAADense>(*this, *si, c, out));
|
gr.insert(std::make_unique<WorkerFoldMAADense>(*this, si, c, out));
|
||||||
|
|
||||||
gr.run();
|
gr.run();
|
||||||
}
|
}
|
||||||
|
@ -395,10 +395,9 @@ UnfoldedStackContainer::multAndAdd(int dim, const UGSContainer &c,
|
||||||
"Wrong symmetry length of container for UnfoldedStackContainer::multAndAdd");
|
"Wrong symmetry length of container for UnfoldedStackContainer::multAndAdd");
|
||||||
|
|
||||||
sthread::detach_thread_group gr;
|
sthread::detach_thread_group gr;
|
||||||
SymmetrySet ss(dim, c.num());
|
for (auto &si : SymmetrySet(dim, c.num()))
|
||||||
for (symiterator si(ss); !si.isEnd(); ++si)
|
if (c.check(si))
|
||||||
if (c.check(*si))
|
gr.insert(std::make_unique<WorkerUnfoldMAADense>(*this, si, c, out));
|
||||||
gr.insert(std::make_unique<WorkerUnfoldMAADense>(*this, *si, c, out));
|
|
||||||
|
|
||||||
gr.run();
|
gr.run();
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,53 +51,42 @@ Symmetry::isFull() const
|
||||||
return count <= 1;
|
return count <= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Here we construct the beginning of the |symiterator|. The first
|
/* Construct a symiterator of given dimension, starting from the given
|
||||||
symmetry index is 0. If length is 2, the second index is the
|
symmetry. */
|
||||||
dimension, otherwise we create the subordinal symmetry set and its
|
|
||||||
beginning as subordinal |symiterator|. */
|
|
||||||
|
|
||||||
symiterator::symiterator(SymmetrySet &ss)
|
symiterator::symiterator(int dim_arg, Symmetry run_arg)
|
||||||
: s(ss), end_flag(false)
|
: dim{dim_arg}, run(std::move(run_arg))
|
||||||
{
|
{
|
||||||
s.sym()[0] = 0;
|
|
||||||
if (s.size() == 2)
|
|
||||||
s.sym()[1] = s.dimen();
|
|
||||||
else
|
|
||||||
{
|
|
||||||
subs = std::make_unique<SymmetrySet>(s, s.dimen());
|
|
||||||
subit = std::make_unique<symiterator>(*subs);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Here we move to the next symmetry. We do so only, if we are not at
|
/* Here we move to the next symmetry. We do so only, if we are not at
|
||||||
the end. If length is 2, we increase lower index and decrease upper
|
the end. If length is 2, we increase lower index and decrease upper
|
||||||
index, otherwise we increase the subordinal symmetry. If we got to the
|
index, otherwise we increase the subordinal symmetry. If we got to the
|
||||||
end, we recreate the subordinal symmetry set and set the subordinal
|
end, we recreate the subordinal symmetry set and set the subordinal
|
||||||
iterator to the beginning. At the end we test, if we are not at the
|
iterator to the beginning. */
|
||||||
end. This is recognized if the lowest index exceeded the dimension. */
|
|
||||||
|
|
||||||
symiterator &
|
symiterator &
|
||||||
symiterator::operator++()
|
symiterator::operator++()
|
||||||
{
|
{
|
||||||
if (!end_flag)
|
if (run[0] == dim)
|
||||||
|
run[0]++; // Jump to the past-the-end iterator
|
||||||
|
else if (run.size() == 2)
|
||||||
{
|
{
|
||||||
if (s.size() == 2)
|
run[0]++;
|
||||||
|
run[1]--;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
symiterator subit{dim-run[0], Symmetry(run, run.size()-1)};
|
||||||
|
++subit;
|
||||||
|
if (run[1] == dim-run[0]+1)
|
||||||
{
|
{
|
||||||
s.sym()[0]++;
|
run[0]++;
|
||||||
s.sym()[1]--;
|
run[1] = 0;
|
||||||
|
/* subit is equal to the past-the-end iterator, so the range
|
||||||
|
2..(size()-1) is already set to 0 */
|
||||||
|
run[run.size()-1] = dim-run[0];
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
++(*subit);
|
|
||||||
if (subit->isEnd())
|
|
||||||
{
|
|
||||||
s.sym()[0]++;
|
|
||||||
subs = std::make_unique<SymmetrySet>(s, s.dimen()-s.sym()[0]);
|
|
||||||
subit = std::make_unique<symiterator>(*subs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (s.sym()[0] == s.dimen()+1)
|
|
||||||
end_flag = true;
|
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
|
@ -105,95 +105,77 @@ public:
|
||||||
bool isFull() const;
|
bool isFull() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* The class |SymmetrySet| defines a set of symmetries of the given
|
/* This is an iterator that iterates over all symmetries of given length and
|
||||||
length having given dimension. It does not store all the symmetries,
|
dimension (see the SymmetrySet class for details).
|
||||||
rather it provides a storage for one symmetry, which is changed as an
|
|
||||||
adjoint iterator moves.
|
|
||||||
|
|
||||||
The iterator class is |symiterator|. It is implemented
|
The beginning iterator is (0, …, 0, dim).
|
||||||
recursively. The iterator object, when created, creates subordinal
|
Increasing it gives (0, … , 1, dim-1)
|
||||||
iterator, which iterates over a symmetry set whose length is one less,
|
The just-before-end iterator is (dim, 0, …, 0)
|
||||||
and dimension is the former dimension. When the subordinal iterator
|
The past-the-end iterator is (dim+1, 0, …, 0)
|
||||||
goes to its end, the superordinal iterator increases left most index in
|
|
||||||
the symmetry, resets the subordinal symmetry set with different
|
|
||||||
dimension, and iterates through the subordinal symmetry set until its
|
|
||||||
end, and so on. That's why we provide also |SymmetrySet| constructor
|
|
||||||
for construction of a subordinal symmetry set.
|
|
||||||
|
|
||||||
The typical usage of the abstractions for |SymmetrySet| and
|
The constructor creates the iterator which starts from the given symmetry
|
||||||
|symiterator| is as follows:
|
|
||||||
|
|
||||||
\kern0.3cm
|
|
||||||
\centerline{|for (symiterator si(SymmetrySet(6, 4)); !si.isEnd(); ++si) {body}|}
|
|
||||||
\kern0.3cm
|
|
||||||
|
|
||||||
\noindent It goes through all symmetries of size 4 having dimension
|
|
||||||
6. One can use |*si| as the symmetry in the body. */
|
|
||||||
|
|
||||||
class SymmetrySet
|
|
||||||
{
|
|
||||||
Symmetry run;
|
|
||||||
int dim;
|
|
||||||
public:
|
|
||||||
SymmetrySet(int d, int length)
|
|
||||||
: run(length), dim(d)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
SymmetrySet(SymmetrySet &s, int d)
|
|
||||||
: run(s.run, s.size()-1), dim(d)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
int
|
|
||||||
dimen() const
|
|
||||||
{
|
|
||||||
return dim;
|
|
||||||
}
|
|
||||||
const Symmetry &
|
|
||||||
sym() const
|
|
||||||
{
|
|
||||||
return run;
|
|
||||||
}
|
|
||||||
Symmetry &
|
|
||||||
sym()
|
|
||||||
{
|
|
||||||
return run;
|
|
||||||
}
|
|
||||||
int
|
|
||||||
size() const
|
|
||||||
{
|
|
||||||
return run.size();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/* The logic of |symiterator| was described in |@<|SymmetrySet| class
|
|
||||||
declaration@>|. Here we only comment that: the class has a reference
|
|
||||||
to the |SymmetrySet| only to know dimension and for access of its
|
|
||||||
symmetry storage. Further we have pointers to subordinal |symiterator|
|
|
||||||
and its |SymmetrySet|. These are pointers, since the recursion ends at
|
|
||||||
length equal to 2, in which case these pointers are uninitialized.
|
|
||||||
|
|
||||||
The constructor creates the iterator which initializes to the first
|
|
||||||
symmetry (beginning). */
|
symmetry (beginning). */
|
||||||
|
|
||||||
class symiterator
|
class symiterator
|
||||||
{
|
{
|
||||||
SymmetrySet &s;
|
const int dim;
|
||||||
std::unique_ptr<symiterator> subit;
|
Symmetry run;
|
||||||
std::unique_ptr<SymmetrySet> subs;
|
|
||||||
bool end_flag;
|
|
||||||
public:
|
public:
|
||||||
symiterator(SymmetrySet &ss);
|
symiterator(int dim_arg, Symmetry run_arg);
|
||||||
~symiterator() = default;
|
~symiterator() = default;
|
||||||
symiterator &operator++();
|
symiterator &operator++();
|
||||||
bool
|
|
||||||
isEnd() const
|
|
||||||
{
|
|
||||||
return end_flag;
|
|
||||||
}
|
|
||||||
const Symmetry &
|
const Symmetry &
|
||||||
operator*() const
|
operator*() const
|
||||||
{
|
{
|
||||||
return s.sym();
|
return run;
|
||||||
|
}
|
||||||
|
bool
|
||||||
|
operator=(const symiterator &it)
|
||||||
|
{
|
||||||
|
return dim == it.dim && run == it.run;
|
||||||
|
}
|
||||||
|
bool
|
||||||
|
operator!=(const symiterator &it)
|
||||||
|
{
|
||||||
|
return !operator=(it);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* The class |SymmetrySet| defines a set of symmetries of the given length
|
||||||
|
having given dimension (i.e. it represents all the lists of integers of
|
||||||
|
length "len" and of sum equal to "dim"). It does not store all the
|
||||||
|
symmetries, it is just a convenience class for iteration.
|
||||||
|
|
||||||
|
The typical usage of the abstractions for |SymmetrySet| and
|
||||||
|
|symiterator| is as follows:
|
||||||
|
|
||||||
|
for (auto &si : SymmetrySet(6, 4))
|
||||||
|
|
||||||
|
It goes through all symmetries of lenght 4 having dimension 6. One can use
|
||||||
|
"si" as the symmetry in the body. */
|
||||||
|
|
||||||
|
class SymmetrySet
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
const int len;
|
||||||
|
const int dim;
|
||||||
|
SymmetrySet(int dim_arg, int len_arg)
|
||||||
|
: len(len_arg), dim(dim_arg)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
symiterator
|
||||||
|
begin() const
|
||||||
|
{
|
||||||
|
Symmetry run(len);
|
||||||
|
run[len-1] = dim;
|
||||||
|
return { dim, run };
|
||||||
|
}
|
||||||
|
symiterator
|
||||||
|
end() const
|
||||||
|
{
|
||||||
|
Symmetry run(len);
|
||||||
|
run[0] = dim+1;
|
||||||
|
return { dim, run };
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -471,13 +471,12 @@ SparseDerivGenerator::SparseDerivGenerator(
|
||||||
|
|
||||||
for (int dim = 1; dim <= maxdimen; dim++)
|
for (int dim = 1; dim <= maxdimen; dim++)
|
||||||
{
|
{
|
||||||
SymmetrySet ss(dim, 4);
|
for (auto &si : SymmetrySet(dim, 4))
|
||||||
for (symiterator si(ss); !si.isEnd(); ++si)
|
|
||||||
{
|
{
|
||||||
bigg->insert(bigg_m.deriv(*si));
|
bigg->insert(bigg_m.deriv(si));
|
||||||
rcont->insert(r.deriv(*si));
|
rcont->insert(r.deriv(si));
|
||||||
if ((*si)[2] == 0)
|
if (si[2] == 0)
|
||||||
g->insert(g_m.deriv(*si));
|
g->insert(g_m.deriv(si));
|
||||||
}
|
}
|
||||||
|
|
||||||
ts[dim-1] = f.deriv(dim);
|
ts[dim-1] = f.deriv(dim);
|
||||||
|
|
|
@ -362,21 +362,19 @@ TestRunnable::fold_zcont(int nf, int ny, int nu, int nup, int nbigg,
|
||||||
|
|
||||||
for (int d = 2; d <= dim; d++)
|
for (int d = 2; d <= dim; d++)
|
||||||
{
|
{
|
||||||
SymmetrySet ss(d, 4);
|
for (auto &si : SymmetrySet(d, 4))
|
||||||
for (symiterator si(ss); !si.isEnd(); ++si)
|
|
||||||
{
|
{
|
||||||
printf("\tSymmetry: "); (*si).print();
|
printf("\tSymmetry: ");
|
||||||
FGSTensor res(nf, TensorDimens(*si, nvs));
|
si.print();
|
||||||
|
FGSTensor res(nf, TensorDimens(si, nvs));
|
||||||
res.getData().zeros();
|
res.getData().zeros();
|
||||||
clock_t stime = clock();
|
clock_t stime = clock();
|
||||||
for (int l = 1; l <= (*si).dimen(); l++)
|
for (int l = 1; l <= si.dimen(); l++)
|
||||||
{
|
zc.multAndAdd(*(dg.ts[l-1]), res);
|
||||||
zc.multAndAdd(*(dg.ts[l-1]), res);
|
|
||||||
}
|
|
||||||
stime = clock() - stime;
|
stime = clock() - stime;
|
||||||
printf("\t\ttime for symmetry: %8.4g\n",
|
printf("\t\ttime for symmetry: %8.4g\n",
|
||||||
((double) stime)/CLOCKS_PER_SEC);
|
((double) stime)/CLOCKS_PER_SEC);
|
||||||
const FGSTensor *mres = dg.rcont->get(*si);
|
const FGSTensor *mres = dg.rcont->get(si);
|
||||||
res.add(-1.0, *mres);
|
res.add(-1.0, *mres);
|
||||||
double normtmp = res.getData().getMax();
|
double normtmp = res.getData().getMax();
|
||||||
printf("\t\terror normMax: %10.6g\n", normtmp);
|
printf("\t\terror normMax: %10.6g\n", normtmp);
|
||||||
|
@ -419,22 +417,20 @@ TestRunnable::unfold_zcont(int nf, int ny, int nu, int nup, int nbigg,
|
||||||
|
|
||||||
for (int d = 2; d <= dim; d++)
|
for (int d = 2; d <= dim; d++)
|
||||||
{
|
{
|
||||||
SymmetrySet ss(d, 4);
|
for (auto &si : SymmetrySet(d, 4))
|
||||||
for (symiterator si(ss); !si.isEnd(); ++si)
|
|
||||||
{
|
{
|
||||||
printf("\tSymmetry: "); (*si).print();
|
printf("\tSymmetry: ");
|
||||||
UGSTensor res(nf, TensorDimens(*si, nvs));
|
si.print();
|
||||||
|
UGSTensor res(nf, TensorDimens(si, nvs));
|
||||||
res.getData().zeros();
|
res.getData().zeros();
|
||||||
clock_t stime = clock();
|
clock_t stime = clock();
|
||||||
for (int l = 1; l <= (*si).dimen(); l++)
|
for (int l = 1; l <= si.dimen(); l++)
|
||||||
{
|
zc.multAndAdd(*(dg.ts[l-1]), res);
|
||||||
zc.multAndAdd(*(dg.ts[l-1]), res);
|
|
||||||
}
|
|
||||||
stime = clock() - stime;
|
stime = clock() - stime;
|
||||||
printf("\t\ttime for symmetry: %8.4g\n",
|
printf("\t\ttime for symmetry: %8.4g\n",
|
||||||
((double) stime)/CLOCKS_PER_SEC);
|
((double) stime)/CLOCKS_PER_SEC);
|
||||||
FGSTensor fold_res(res);
|
FGSTensor fold_res(res);
|
||||||
const FGSTensor *mres = dg.rcont->get(*si);
|
const FGSTensor *mres = dg.rcont->get(si);
|
||||||
fold_res.add(-1.0, *mres);
|
fold_res.add(-1.0, *mres);
|
||||||
double normtmp = fold_res.getData().getMax();
|
double normtmp = fold_res.getData().getMax();
|
||||||
printf("\t\terror normMax: %10.6g\n", normtmp);
|
printf("\t\terror normMax: %10.6g\n", normtmp);
|
||||||
|
|
Loading…
Reference in New Issue