Dynare++ parser: various modernizations

time-shift
Sébastien Villemot 2019-04-19 17:09:04 +02:00
parent ee891948e0
commit 3915299334
No known key found for this signature in database
GPG Key ID: 2CECE9350ECEBE4A
29 changed files with 668 additions and 897 deletions

View File

@ -10,6 +10,7 @@
#include <limits>
#include <iostream>
#include <algorithm>
using namespace ogp;
@ -19,7 +20,7 @@ AtomAssignings::AtomAssignings(const AtomAssignings &aa, ogp::StaticAtoms &a)
{
// fill the lname2expr
for (auto it : aa.lname2expr)
lname2expr.insert(Tvarintmap::value_type(left_names.query(it.first), it.second));
lname2expr.emplace(left_names.query(it.first), it.second);
}
/** A global symbol for passing info to the AtomAssignings from
@ -36,16 +37,15 @@ extern location_type asgn_lloc;
void
AtomAssignings::parse(int length, const char *stream)
{
auto *buffer = new char[length+2];
strncpy(buffer, stream, length);
auto buffer = std::make_unique<char[]>(length+2);
std::copy_n(stream, length, buffer.get());
buffer[length] = '\0';
buffer[length+1] = '\0';
asgn_lloc.off = 0;
asgn_lloc.ll = 0;
void *p = asgn__scan_buffer(buffer, (unsigned int) length+2);
void *p = asgn__scan_buffer(buffer.get(), static_cast<unsigned int>(length)+2);
aparser = this;
asgn_parse();
delete [] buffer;
asgn__destroy_buffer(p);
}
@ -89,7 +89,7 @@ AtomAssignings::add_assignment_to_double(const char *name, double val)
// register name of the left hand side and put to lname2expr
const char *ss = left_names.insert(name);
lname2expr.insert(Tvarintmap::value_type(ss, order.size()-1));
lname2expr.emplace(ss, order.size()-1);
}
void
@ -173,7 +173,7 @@ AtomAssignings::apply_subst(const AtomSubstitutions::Toldnamemap &mm)
{
const char *newname = itt.first;
const char *nn = left_names.insert(newname);
lname2expr.insert(Tvarintmap::value_type(nn, expr.nformulas()-1));
lname2expr.emplace(nn, expr.nformulas()-1);
}
}
}
@ -182,11 +182,11 @@ AtomAssignings::apply_subst(const AtomSubstitutions::Toldnamemap &mm)
void
AtomAssignings::print() const
{
printf("Atom Assignings\nExpressions:\n");
std::cout << "Atom Assignings\nExpressions:\n";
expr.print();
printf("Left names:\n");
std::cout << "Left names:\n";
for (auto it : lname2expr)
printf("%s ==> %d (t=%d)\n", it.first, expr.formula(it.second), order[it.second]);
std::cout << it.first << u8"" << expr.formula(it.second) << " (t=" << order[it.second] << ")\n";
}
void
@ -207,7 +207,7 @@ AtomAsgnEvaluator::setValues(EvalTree &et) const
if (it == user_values.end())
et.set_nulary(t, nan);
else
et.set_nulary(t, (*it).second);
et.set_nulary(t, it->second);
}
}
}
@ -220,9 +220,9 @@ AtomAsgnEvaluator::set_user_value(const char *name, double val)
{
auto it = user_values.find(t);
if (it == user_values.end())
user_values.insert(Tusrvalmap::value_type(t, val));
user_values.emplace(t, val);
else
(*it).second = val;
it->second = val;
}
}
@ -244,5 +244,5 @@ AtomAsgnEvaluator::get_value(const char *name) const
if (it == aa.lname2expr.end())
return std::numeric_limits<double>::quiet_NaN();
else
return operator[]((*it).second);
return operator[](it->second);
}

View File

@ -51,8 +51,7 @@ namespace ogp
/** Make a copy with provided reference to (posibly different)
* static atoms. */
AtomAssignings(const AtomAssignings &aa, StaticAtoms &a);
virtual ~AtomAssignings()
= default;
virtual ~AtomAssignings() = default;
/** Parse the assignments from the given string. */
void parse(int length, const char *stream);
/** Process a syntax error from bison. */
@ -97,8 +96,7 @@ namespace ogp
std::vector<double>(a.expr.nformulas()), aa(a)
{
}
~AtomAsgnEvaluator()
override = default;
~AtomAsgnEvaluator() override = default;
/** This sets all initial values to NaNs, all constants and
* all values set by user by call set_value. This is called by
* FormulaEvaluator::eval() method, which is called by eval()

View File

@ -15,16 +15,16 @@ AtomSubstitutions::AtomSubstitutions(const AtomSubstitutions &as, const FineAtom
// fill new2old
for (const auto & it : as.new2old)
new2old.insert(Tshiftmap::value_type(ns.query(it.first),
Tshiftname(ns.query(it.second.first),
it.second.second)));
new2old.emplace(ns.query(it.first),
Tshiftname(ns.query(it.second.first),
it.second.second));
// fill old2new
for (const auto & it : as.old2new)
{
Tshiftnameset sset;
for (const auto & itt : it.second)
sset.insert(Tshiftname(ns.query(itt.first), itt.second));
old2new.insert(Toldnamemap::value_type(ns.query(it.first), sset));
sset.emplace(ns.query(itt.first), itt.second);
old2new.emplace(ns.query(it.first), sset);
}
}
@ -34,21 +34,21 @@ AtomSubstitutions::add_substitution(const char *newname, const char *oldname, in
// make sure the storage is from the new_atoms
newname = new_atoms.get_name_storage().query(newname);
oldname = new_atoms.get_name_storage().query(oldname);
if (newname == nullptr || oldname == nullptr)
if (!newname || !oldname)
throw ogu::Exception(__FILE__, __LINE__,
"Bad newname or oldname in AtomSubstitutions::add_substitution");
// insert to new2old map
new2old.insert(Tshiftmap::value_type(newname, Tshiftname(oldname, tshift)));
new2old.emplace(newname, Tshiftname(oldname, tshift));
// insert to old2new map
auto it = old2new.find(oldname);
if (it != old2new.end())
(*it).second.insert(Tshiftname(newname, -tshift));
it->second.emplace(newname, -tshift);
else
{
Tshiftnameset snset;
snset.insert(Tshiftname(newname, -tshift));
old2new.insert(Toldnamemap::value_type(oldname, snset));
snset.emplace(newname, -tshift);
old2new.emplace(oldname, snset);
}
// put to info
@ -68,7 +68,7 @@ AtomSubstitutions::substitutions_finished(VarOrdering::ord_type ot)
// add all new names derived from the old name
Toldnamemap::const_iterator it = old2new.find(oname);
if (it != old2new.end())
for (const auto & itt : (*it).second)
for (const auto & itt : it->second)
na_ext.push_back(itt.first);
}
@ -82,7 +82,7 @@ AtomSubstitutions::get_new4old(const char *oldname, int tshift) const
auto it = old2new.find(oldname);
if (it != old2new.end())
{
const Tshiftnameset &sset = (*it).second;
const Tshiftnameset &sset = it->second;
for (const auto & itt : sset)
if (itt.second == -tshift)
return itt.first;
@ -93,15 +93,14 @@ AtomSubstitutions::get_new4old(const char *oldname, int tshift) const
void
AtomSubstitutions::print() const
{
printf("Atom Substitutions:\nOld ==> New:\n");
std::cout << u8"Atom Substitutions:\nOld ⇒ New:\n";
for (const auto & it : old2new)
for (auto itt = it.second.begin();
itt != it.second.end(); ++itt)
printf(" %s ==> [%s, %d]\n", it.first, (*itt).first, (*itt).second);
for (const auto &itt : it.second)
std::cout << " " << it.first << u8" ⇒ [" << itt.first << ", " << itt.second << "]\n";
printf("Old <== New:\n");
std::cout << u8"Old ⇐ New:\n";
for (const auto & it : new2old)
printf(" [%s, %d] <== %s\n", it.second.first, it.second.second, it.first);
std::cout << " [" << it.second.first << ", " << it.second.second << "] ⇐ " << it.first << '\n';
}
void
@ -113,19 +112,19 @@ SAtoms::substituteAllLagsAndLeads(FormulaParser &fp, AtomSubstitutions &as)
endovarspan(mlead, mlag);
// substitute all endo lagged more than 1
while (nullptr != (name = findEndoWithLeadInInterval(mlag, -2)))
while (name = findEndoWithLeadInInterval(mlag, -2))
makeAuxVariables(name, -1, -2, mlag, fp, as);
// substitute all endo leaded more than 1
while (nullptr != (name = findEndoWithLeadInInterval(2, mlead)))
while (name = findEndoWithLeadInInterval(2, mlead))
makeAuxVariables(name, 1, 2, mlead, fp, as);
exovarspan(mlead, mlag);
// substitute all lagged exo
while (nullptr != (name = findExoWithLeadInInterval(mlag, -1)))
while (name = findExoWithLeadInInterval(mlag, -1))
makeAuxVariables(name, -1, -1, mlag, fp, as);
// substitute all leaded exo
while (nullptr != (name = findExoWithLeadInInterval(1, mlead)))
while (name = findExoWithLeadInInterval(1, mlead))
makeAuxVariables(name, 1, 1, mlead, fp, as);
// notify that substitution have been finished
@ -141,16 +140,16 @@ SAtoms::substituteAllLagsAndExo1Leads(FormulaParser &fp, AtomSubstitutions &as)
endovarspan(mlead, mlag);
// substitute all endo lagged more than 1
while (nullptr != (name = findEndoWithLeadInInterval(mlag, -2)))
while (name = findEndoWithLeadInInterval(mlag, -2))
makeAuxVariables(name, -1, -2, mlag, fp, as);
exovarspan(mlead, mlag);
// substitute all lagged exo
while (nullptr != (name = findExoWithLeadInInterval(mlag, -1)))
while (name = findExoWithLeadInInterval(mlag, -1))
makeAuxVariables(name, -1, -1, mlag, fp, as);
// substitute all leaded exo by 1
while (nullptr != (name = findExoWithLeadInInterval(1, 1)))
while (name = findExoWithLeadInInterval(1, 1))
makeAuxVariables(name, 1, 1, 1, fp, as);
// notify that substitution have been finished
@ -181,8 +180,7 @@ void
SAtoms::attemptAuxName(const char *str, int ll, string &out) const
{
char c = (ll >= 0) ? ((ll == 0) ? 'e' : 'p') : 'm';
char absll[100];
sprintf(absll, "%d", std::abs(ll));
string absll = std::to_string(std::abs(ll));
int iter = 1;
do
{
@ -218,15 +216,13 @@ SAtoms::makeAuxVariables(const char *name, int step, int start, int limit_lead,
// Comment to comments: name="a"; start=-3; step=-1;
char tmp[500];
// recover tree index of a previous atom, i.e. set tprev to a tree
// index of atom "a(-2)"
int tprev = index(name, start-step);
if (tprev == -1)
{
sprintf(tmp, "%s(%d)", name, start-step);
tprev = fp.add_nulary(tmp);
string tmp = string{name} + '(' + std::to_string(start-step) + ')';
tprev = fp.add_nulary(tmp.c_str());
}
int ll = start;
@ -241,19 +237,19 @@ SAtoms::makeAuxVariables(const char *name, int step, int start, int limit_lead,
const char *newname;
string newname_str;
int taux;
if (nullptr == (newname = as.get_new4old(name, ll-step)))
if (!(newname = as.get_new4old(name, ll-step)))
{
attemptAuxName(name, ll-step, newname_str);
newname = newname_str.c_str();
register_uniq_endo(newname);
newname = varnames.query(newname);
sprintf(tmp, "%s(0)", newname);
taux = fp.add_nulary(tmp);
string tmp = string{newname} + "(0)";
taux = fp.add_nulary(tmp.c_str());
// add to substitutions
as.add_substitution(newname, name, ll-step);
// add equation "a_m2(0) = a(-2)", this is taux = tprev
fp.add_formula(fp.add_binary(MINUS, taux, tprev));
fp.add_formula(fp.add_binary(code_t::MINUS, taux, tprev));
}
else
{
@ -273,8 +269,8 @@ SAtoms::makeAuxVariables(const char *name, int step, int start, int limit_lead,
if (t == -1)
{
// no "a(-3)", make t <-> a_m2(-1)
sprintf(tmp, "%s(%d)", newname, step);
t = fp.add_nulary(tmp);
string tmp = string{newname} + '(' + std::to_string(step) + ')';
t = fp.add_nulary(tmp.c_str());
}
else
{

View File

@ -22,8 +22,7 @@ namespace ogp
struct SubstInfo
{
int num_substs{0};
SubstInfo()
= default;
SubstInfo() = default;
};
/** This class tracks all atom substitutions during the job and
@ -72,8 +71,7 @@ namespace ogp
* of old atoms and new atoms, which are supposed to be
* semantically same as the atoms from as. */
AtomSubstitutions(const AtomSubstitutions &as, const FineAtoms &oa, FineAtoms &na);
virtual ~AtomSubstitutions()
= default;
virtual ~AtomSubstitutions() = default;
/** This is called during the substitution job from the
* substitution method of the new atoms. This says that the
* new name, say "a_m3" is a substitution of old name "a"
@ -128,11 +126,8 @@ namespace ogp
: FineAtoms()
{
}
SAtoms(const SAtoms &sa)
= default;
~SAtoms()
override = default;
SAtoms(const SAtoms &sa) = default;
~SAtoms() override = default;
/** This substitutes all lags and leads for all exogenous and
* all lags and leads greater than 1 for all endogenous
* variables. This is useful for perfect foresight problems

View File

@ -2,7 +2,9 @@
#include "parser_exception.hh"
#include "location.hh"
#include "csv_tab.hh"
#include <cstring>
#include <memory>
#include <algorithm>
using namespace ogp;
@ -28,17 +30,16 @@ void
CSVParser::csv_parse(int length, const char *str)
{
// allocate temporary buffer and parse
auto *buffer = new char[length+2];
strncpy(buffer, str, length);
auto buffer = std::make_unique<char[]>(length+2);
std::copy_n(str, length, buffer.get());
buffer[length] = '\0';
buffer[length+1] = '\0';
csv_lloc.off = 0;
csv_lloc.ll = 0;
parsed_string = buffer;
void *p = csv__scan_buffer(buffer, (unsigned int) length+2);
parsed_string = buffer.get();
void *p = csv__scan_buffer(buffer.get(), static_cast<unsigned int>(length)+2);
csv_parser = this;
::csv_parse();
delete [] buffer;
csv__destroy_buffer(p);
parsed_string = nullptr;
}

View File

@ -59,7 +59,7 @@ void
NameStorage::print() const
{
for (auto i : name_store)
printf("%s\n", i);
std::cout << i << '\n';
}
void
@ -69,7 +69,7 @@ Constants::import_constants(const Constants &c, OperationTree &otree, Tintintmap
{
int told = it.first;
int tnew = otree.add_nulary();
tmap.insert(Tintintmap::value_type(told, tnew));
tmap.emplace(told, tnew);
add_constant(tnew, it.second);
}
}
@ -77,16 +77,15 @@ Constants::import_constants(const Constants &c, OperationTree &otree, Tintintmap
void
Constants::setValues(EvalTree &et) const
{
Tconstantmap::const_iterator it;
for (it = cmap.begin(); it != cmap.end(); ++it)
et.set_nulary((*it).first, (*it).second);
for (const auto & it : cmap)
et.set_nulary(it.first, it.second);
}
void
Constants::add_constant(int t, double val)
{
cmap.insert(Tconstantmap::value_type(t, val));
cinvmap.insert(Tconstantinvmap::value_type(val, t));
cmap.emplace(t, val);
cinvmap.emplace(val, t);
}
bool
@ -103,7 +102,7 @@ Constants::get_constant_value(int t) const
{
auto it = cmap.find(t);
if (it != cmap.end())
return (*it).second;
return it->second;
else
{
throw ogu::Exception(__FILE__, __LINE__,
@ -119,7 +118,7 @@ Constants::check(const char *str) const
sscanf(str, "%lf", &d);
auto it = cinvmap.find(d);
if (it != cinvmap.end())
return (*it).second;
return it->second;
else
return -1;
}
@ -127,13 +126,11 @@ Constants::check(const char *str) const
void
Constants::print() const
{
Tconstantmap::const_iterator it;
for (it = cmap.begin(); it != cmap.end(); ++it)
printf("$%d: %8.4g\n", (*it).first, (*it).second);
for (const auto &it : cmap)
printf("$%d: %8.4g\n", it.first, it.second);
}
DynamicAtoms::DynamicAtoms()
= default;
DynamicAtoms::DynamicAtoms() = default;
DynamicAtoms::DynamicAtoms(const DynamicAtoms &da)
: Constants(da),
@ -142,12 +139,10 @@ DynamicAtoms::DynamicAtoms(const DynamicAtoms &da)
{
// copy vars
for (const auto & var : da.vars)
vars.insert(Tvarmap::value_type(varnames.query(var.first),
var.second));
vars.emplace(varnames.query(var.first), var.second);
// copy indices
for (auto indice : da.indices)
indices.insert(Tindexmap::value_type(indice.first,
varnames.query(indice.second)));
indices.emplace(indice.first, varnames.query(indice.second));
}
int
@ -169,10 +164,10 @@ DynamicAtoms::check_variable(const char *name) const
if (it != vars.end())
{
const Tlagmap &lmap = (*it).second;
const Tlagmap &lmap = it->second;
auto itt = lmap.find(ll);
if (itt != lmap.end())
return (*itt).second;
return itt->second;
}
return -1;
}
@ -218,19 +213,19 @@ DynamicAtoms::assign_variable(const char *varname, int ll, int t)
auto it = vars.find(varname);
if (it != vars.end())
{
Tlagmap &lmap = (*it).second;
Tlagmap &lmap = it->second;
if (lmap.end() != lmap.find(ll))
throw ogu::Exception(__FILE__, __LINE__,
"Attempt to assign already allocated variable");
lmap.insert(Tlagmap::value_type(ll, t));
lmap.emplace(ll, t);
}
else
{
Tlagmap lmap;
lmap.insert(Tlagmap::value_type(ll, t));
vars.insert(Tvarmap::value_type(varname, lmap));
lmap.emplace(ll, t);
vars.emplace(varname, lmap);
}
indices.insert(Tindexmap::value_type(t, varname));
indices.emplace(t, varname);
nv++;
if (ll < minlag)
@ -245,11 +240,11 @@ DynamicAtoms::unassign_variable(const char *varname, int ll, int t)
auto it = vars.find(varname);
if (it != vars.end())
{
Tlagmap &lmap = (*it).second;
Tlagmap &lmap = it->second;
auto itt = lmap.find(ll);
if (itt != lmap.end())
{
if ((*itt).second == t)
if (itt->second == t)
{
// erase it from the lagmap; if it becomes empty,
// erase the lagmap from varmap
@ -281,18 +276,16 @@ DynamicAtoms::unassign_variable(const char *varname, int ll, int t)
void
DynamicAtoms::update_minmaxll()
{
minlag = INT_MAX;
maxlead = INT_MIN;
for (Tvarmap::const_iterator it = vars.begin(); it != vars.end(); ++it)
minlag = std::numeric_limits<int>::max();
maxlead = std::numeric_limits<int>::min();
for (const auto &it : vars)
{
const Tlagmap &lmap = (*it).second;
const Tlagmap &lmap = it.second;
for (auto itt : lmap)
{
int ll = itt.first;
if (ll < minlag)
minlag = ll;
if (ll > maxlead)
maxlead = ll;
minlag = std::min(ll, minlag);
maxlead = std::max(ll, maxlead);
}
}
}
@ -316,11 +309,11 @@ DynamicAtoms::varspan(int t, int &mlead, int &mlag) const
auto it = indices.find(t);
if (indices.end() == it)
{
mlead = INT_MIN;
mlag = INT_MAX;
mlead = std::numeric_limits<int>::min();
mlag = std::numeric_limits<int>::max();
return;
}
varspan((*it).second, mlead, mlag);
varspan(it->second, mlead, mlag);
}
void
@ -329,30 +322,28 @@ DynamicAtoms::varspan(const char *name, int &mlead, int &mlag) const
auto it = vars.find(name);
if (vars.end() == it)
{
mlead = INT_MIN;
mlag = INT_MAX;
mlead = std::numeric_limits<int>::min();
mlag = std::numeric_limits<int>::max();
return;
}
const Tlagmap &lmap = (*it).second;
const Tlagmap &lmap = it->second;
auto beg = lmap.begin();
auto end = lmap.rbegin();
mlag = (*beg).first;
mlead = (*end).first;
mlag = beg->first;
mlead = end->first;
}
void
DynamicAtoms::varspan(const vector<const char *> &names, int &mlead, int &mlag) const
{
mlead = INT_MIN;
mlag = INT_MAX;
mlead = std::numeric_limits<int>::min();
mlag = std::numeric_limits<int>::max();
for (auto name : names)
{
int lag, lead;
varspan(name, lead, lag);
if (lead > mlead)
mlead = lead;
if (lag < mlag)
mlag = lag;
mlead = std::max(lead, mlead);
mlag = std::min(lag, mlag);
}
}
@ -368,10 +359,10 @@ DynamicAtoms::index(const char *name, int ll) const
auto it = vars.find(name);
if (vars.end() != it)
{
const Tlagmap &lmap = (*it).second;
const Tlagmap &lmap = it->second;
auto itt = lmap.find(ll);
if (lmap.end() != itt)
return (*itt).second;
return itt->second;
}
return -1;
}
@ -391,7 +382,7 @@ DynamicAtoms::lagmap(const char *name) const
throw ogu::Exception(__FILE__, __LINE__,
std::string("Couldn't find the name ")
+ name + " in DynamicAtoms::lagmap");
return (*it).second;
return it->second;
}
const char *
@ -401,7 +392,7 @@ DynamicAtoms::name(int t) const
if (indices.end() == it)
throw ogu::Exception(__FILE__, __LINE__,
"Couldn't find tree index in DynamicAtoms::name");
return (*it).second;
return it->second;
}
int
@ -410,12 +401,12 @@ DynamicAtoms::lead(int t) const
const char *nam = name(t);
const Tlagmap &lmap = lagmap(nam);
auto it = lmap.begin();
while (it != lmap.end() && (*it).second != t)
while (it != lmap.end() && it->second != t)
++it;
if (lmap.end() == it)
throw ogu::Exception(__FILE__, __LINE__,
"Couldn't find the three index in DynamicAtoms::lead");
return (*it).first;
return it->first;
}
void
@ -434,7 +425,7 @@ DynamicAtoms::print() const
}
printf("indices:\n");
for (auto indice : indices)
printf("t=%d ==> %s\n", indice.first, indice.second);
printf(u8"t=%d ⇒ %s\n", indice.first, indice.second);
}
/** Note that the str has been parsed by the lexicographic
@ -467,7 +458,7 @@ VarOrdering::get_pos_of(int t) const
auto it = positions.find(t);
if (it != positions.end())
{
return (*it).second;
return it->second;
}
else
{
@ -570,7 +561,7 @@ VarOrdering::do_general(ord_type ordering)
if ((*ord)[j] != -1)
{
der_atoms.push_back((*ord)[j]);
positions.insert(std::pair<int, int>((*ord)[j], off));
positions.emplace((*ord)[j], off);
}
// set integer constants
@ -599,7 +590,7 @@ VarOrdering::do_increasing_time()
// setup the matrix of tree indices, if there is no occurrence,
// the index is set to -1
vector<int> ll_init(varnames.size(), -1);
vector<vector<int> > tree_ind(mlead-mlag+1, ll_init);
vector<vector<int>> tree_ind(mlead-mlag+1, ll_init);
for (unsigned int iv = 0; iv < varnames.size(); iv++)
{
try
@ -627,7 +618,7 @@ VarOrdering::do_increasing_time()
{
der_atoms.push_back(t);
int pos = (ll-mlag)*varnames.size() + iv;
positions.insert(map<int, int>::value_type(t, pos));
positions.emplace(t, pos);
}
}
@ -644,31 +635,19 @@ VarOrdering::do_increasing_time()
int mmlag, mmlead;
atoms.varspan(varname, mmlead, mmlag);
if (mmlead == 0 && mmlag == 0)
{
n_stat++;
}
n_stat++;
else if (mmlead <= 0 && mmlag < 0)
{
n_pred++;
}
n_pred++;
else if (mmlead > 0 && mmlag >= 0)
{
n_forw++;
}
n_forw++;
else if (mmlead > 0 && mmlag < 0)
{
n_both++;
}
n_both++;
else if (mmlead < mmlag)
{
// variable does not occur in the tree, cound as static
n_stat++;
}
// variable does not occur in the tree, cound as static
n_stat++;
else
{
throw ogu::Exception(__FILE__, __LINE__,
"A wrong lag/lead of a variable in VarOrdering::do_increasing_time");
}
throw ogu::Exception(__FILE__, __LINE__,
"A wrong lag/lead of a variable in VarOrdering::do_increasing_time");
}
}
@ -681,7 +660,7 @@ VarOrdering::print() const
printf(" %d", der_atom);
printf("\nmap:\n");
for (auto position : positions)
printf(" [%d->%d]", position.first, position.second);
printf(u8" [%d→%d]", position.first, position.second);
printf("\ny2outer:\n");
for (int i : y2outer)
printf(" %d", i);

View File

@ -12,7 +12,8 @@
#include <set>
#include <string>
#include <cstring>
#include <climits>
#include <limits>
#include <memory>
namespace ogp
{
@ -45,11 +46,9 @@ namespace ogp
* allocated or not. */
set<const char *, ltstr> name_set;
public:
NameStorage()
= default;
NameStorage() = default;
NameStorage(const NameStorage &stor);
virtual
~NameStorage();
virtual ~NameStorage();
/** Query for the name. If the name has been stored, it
* returns its address, otherwise 0. */
const char *query(const char *name) const;
@ -59,7 +58,7 @@ namespace ogp
int
num() const
{
return (int) name_store.size();
return static_cast<int>(name_store.size());
}
const char *
get_name(int i) const
@ -80,8 +79,7 @@ namespace ogp
/** Map mapping a tree index of a constant to its double value. */
Tconstantmap cmap;
public:
Constants()
= default;
Constants() = default;
/** Copy constructor. */
Constants(const Constants &c)
: cmap(c.cmap), cinvmap(c.cinvmap)
@ -162,15 +160,14 @@ namespace ogp
/** Number of variables. */
int nv{0};
/** Minimum lag, if there is at least one lag, than this is a negative number. */
int minlag{INT_MAX};
int minlag{std::numeric_limits<int>::max()};
/** Maximum lead, if there is at least one lead, than this is a positive number. */
int maxlead{INT_MIN};
int maxlead{std::numeric_limits<int>::min()};
public:
/** Construct empty DynamicAtoms. */
DynamicAtoms();
DynamicAtoms(const DynamicAtoms &da);
~DynamicAtoms()
override = default;
~DynamicAtoms() override = default;
/** Check the nulary term identified by its string
* representation. The nulary term can be either a constant or
* a variable. If constant, -1 is returned so that it could be
@ -326,7 +323,7 @@ namespace ogp
* follows: y(t-1), x(t-1), z(t-1), [y(t)], [x(t)], z(t),
* x(t+1), where a bracketed expresion means non-existent by
* occupying a space. The map thus will look as follows:
* {5->0, 6->1, 3->2, 2->5, 3->6}. Note that nothing is mapped
* {50, 61, 32, 25, 36}. Note that nothing is mapped
* to positions 3 and 4. */
map<int, int> positions;
/** This maps an ordering of the list of variables in
@ -358,11 +355,10 @@ namespace ogp
VarOrdering(const VarOrdering &vo, const vector<const char *> &vnames,
const DynamicAtoms &a);
VarOrdering(const VarOrdering &vo) = delete;
virtual VarOrdering *clone(const vector<const char *> &vnames,
const DynamicAtoms &a) const = 0;
virtual std::unique_ptr<VarOrdering> clone(const vector<const char *> &vnames,
const DynamicAtoms &a) const = 0;
/** Destructor does nothing here. */
virtual ~VarOrdering()
= default;
virtual ~VarOrdering() = default;
/** This is the method setting the ordering and the map. A
* subclass must reimplement it, possibly using a
* preimplemented ordering. This method must be called by the

View File

@ -31,12 +31,12 @@ AllvarOuterOrdering::AllvarOuterOrdering(const vector<const char *> &allvar_oute
{
auto it = atoms.endo_outer_map.find(allvar[i]);
if (it != atoms.endo_outer_map.end())
endo2all[(*it).second] = i;
endo2all[it->second] = i;
else
{
it = atoms.exo_outer_map.find(allvar[i]);
if (it != atoms.exo_outer_map.end())
exo2all[(*it).second] = i;
exo2all[it->second] = i;
else
throw ogu::Exception(__FILE__, __LINE__,
string("Name ") + allvar[i] + " is neither endogenous nor exogenous variable in AllvarOuterOrdering constructor");
@ -89,7 +89,7 @@ FineAtoms::FineAtoms(const FineAtoms &fa)
throw ogu::Exception(__FILE__, __LINE__,
string("Parameter ") + param + " does not exist in FineAtoms copy cosntructor");
params.push_back(s);
param_outer_map.insert(Tvarintmap::value_type(s, params.size()-1));
param_outer_map.emplace(s, params.size()-1);
}
// fill in endovars
for (auto endovar : fa.endovars)
@ -99,7 +99,7 @@ FineAtoms::FineAtoms(const FineAtoms &fa)
throw ogu::Exception(__FILE__, __LINE__,
string("Endo variable ") + endovar + " does not exist in FineAtoms copy constructor");
endovars.push_back(s);
endo_outer_map.insert(Tvarintmap::value_type(s, endovars.size()-1));
endo_outer_map.emplace(s, endovars.size()-1);
}
// fill in exovars
for (auto exovar : fa.exovars)
@ -109,7 +109,7 @@ FineAtoms::FineAtoms(const FineAtoms &fa)
throw ogu::Exception(__FILE__, __LINE__,
string("Exo variable ") + exovar + " does not exist in FineAtoms copy cosntructor");
exovars.push_back(s);
exo_outer_map.insert(Tvarintmap::value_type(s, exovars.size()-1));
exo_outer_map.emplace(s, exovars.size()-1);
}
if (fa.endo_order)
@ -119,7 +119,7 @@ FineAtoms::FineAtoms(const FineAtoms &fa)
exo_order = fa.exo_order->clone(exovars, *this);
if (fa.allvar_order)
allvar_order = new AllvarOuterOrdering(*(fa.allvar_order), *this);
allvar_order = std::make_unique<AllvarOuterOrdering>(*(fa.allvar_order), *this);
}
int
@ -156,9 +156,7 @@ FineAtoms::parsing_finished(VarOrdering::ord_type ot)
allvar_tmp.insert(allvar_tmp.end(), endovars.begin(), endovars.end());
allvar_tmp.insert(allvar_tmp.end(), exovars.begin(), exovars.end());
if (allvar_order)
delete allvar_order;
allvar_order = new AllvarOuterOrdering(allvar_tmp, *this);
allvar_order = std::make_unique<AllvarOuterOrdering>(allvar_tmp, *this);
}
void
@ -166,9 +164,7 @@ FineAtoms::parsing_finished(VarOrdering::ord_type ot,
const vector<const char *> allvar)
{
make_internal_orderings(ot);
if (allvar_order)
delete allvar_order;
allvar_order = new AllvarOuterOrdering(allvar, *this);
allvar_order = std::make_unique<AllvarOuterOrdering>(allvar, *this);
}
const vector<const char *> &
@ -205,14 +201,12 @@ vector<int>
FineAtoms::variables() const
{
if (endo_order)
{
return der_atoms;
}
return der_atoms;
else
{
throw ogu::Exception(__FILE__, __LINE__,
"FineAtoms::variables called before parsing_finished");
return vector<int>();
return {};
}
}
@ -220,9 +214,7 @@ int
FineAtoms::nstat() const
{
if (endo_order)
{
return endo_order->nstat();
}
return endo_order->nstat();
else
{
throw ogu::Exception(__FILE__, __LINE__,
@ -235,9 +227,7 @@ int
FineAtoms::npred() const
{
if (endo_order)
{
return endo_order->npred();
}
return endo_order->npred();
else
{
throw ogu::Exception(__FILE__, __LINE__,
@ -250,9 +240,7 @@ int
FineAtoms::nboth() const
{
if (endo_order)
{
return endo_order->nboth();
}
return endo_order->nboth();
else
{
throw ogu::Exception(__FILE__, __LINE__,
@ -265,9 +253,7 @@ int
FineAtoms::nforw() const
{
if (endo_order)
{
return endo_order->nforw();
}
return endo_order->nforw();
else
{
throw ogu::Exception(__FILE__, __LINE__,
@ -280,9 +266,7 @@ int
FineAtoms::get_pos_of_endo(int t) const
{
if (endo_order)
{
return endo_order->get_pos_of(t);
}
return endo_order->get_pos_of(t);
else
{
throw ogu::Exception(__FILE__, __LINE__,
@ -295,9 +279,7 @@ int
FineAtoms::get_pos_of_exo(int t) const
{
if (exo_order)
{
return exo_order->get_pos_of(t);
}
return exo_order->get_pos_of(t);
else
{
throw ogu::Exception(__FILE__, __LINE__,
@ -391,7 +373,7 @@ FineAtoms::name2outer_param(const char *name) const
if (it == param_outer_map.end())
throw ogu::Exception(__FILE__, __LINE__,
"Name is not a parameter in FineAtoms::name2outer_param");
return (*it).second;
return it->second;
}
int
@ -401,7 +383,7 @@ FineAtoms::name2outer_endo(const char *name) const
if (it == endo_outer_map.end())
throw ogu::Exception(__FILE__, __LINE__,
"Name is not an endogenous variable in FineAtoms::name2outer_endo");
return (*it).second;
return it->second;
}
int
@ -411,7 +393,7 @@ FineAtoms::name2outer_exo(const char *name) const
if (it == exo_outer_map.end())
throw ogu::Exception(__FILE__, __LINE__,
"Name is not an exogenous variable in FineAtoms::name2outer_exo");
return (*it).second;
return it->second;
}
int
@ -423,12 +405,12 @@ FineAtoms::name2outer_allvar(const char *name) const
auto it = endo_outer_map.find(name);
if (it != endo_outer_map.end())
return allvar_order->get_endo2all()[(*it).second];
return allvar_order->get_endo2all()[it->second];
else
{
it = exo_outer_map.find(name);
if (it != exo_outer_map.end())
return allvar_order->get_exo2all()[(*it).second];
return allvar_order->get_exo2all()[it->second];
}
throw ogu::Exception(__FILE__, __LINE__,
@ -443,7 +425,7 @@ FineAtoms::register_uniq_endo(const char *name)
throw ogp::ParserException(string("Endogenous variable <")+name+"> is not unique.", 0);
const char *ss = varnames.insert(name);
endovars.push_back(ss);
endo_outer_map.insert(Tvarintmap::value_type(ss, endovars.size()-1));
endo_outer_map.emplace(ss, endovars.size()-1);
}
void
@ -453,7 +435,7 @@ FineAtoms::register_uniq_exo(const char *name)
throw ogp::ParserException(string("Exogenous variable <")+name+"> is not unique.", 0);
const char *ss = varnames.insert(name);
exovars.push_back(ss);
exo_outer_map.insert(Tvarintmap::value_type(ss, exovars.size()-1));
exo_outer_map.emplace(ss, exovars.size()-1);
}
void
@ -463,7 +445,7 @@ FineAtoms::register_uniq_param(const char *name)
throw ogp::ParserException(string("Parameter <")+name+"> is not unique.", 0);
const char *ss = varnames.insert(name);
params.push_back(ss);
param_outer_map.insert(Tvarintmap::value_type(ss, params.size()-1));
param_outer_map.emplace(ss, params.size()-1);
}
void
@ -479,12 +461,10 @@ FineAtoms::make_internal_orderings(VarOrdering::ord_type ot)
if (mlag >= -1 && mlead <= 1)
{
// make endo ordering
if (endo_order)
delete endo_order;
if (ot == VarOrdering::pbspbfbf)
endo_order = new EndoVarOrdering1(endovars, *this);
endo_order = std::make_unique<EndoVarOrdering1>(endovars, *this);
else
endo_order = new EndoVarOrdering2(endovars, *this);
endo_order = std::make_unique<EndoVarOrdering2>(endovars, *this);
endo_order->do_ordering();
endo_ordering_done = true;
}
@ -493,9 +473,7 @@ FineAtoms::make_internal_orderings(VarOrdering::ord_type ot)
if (mlag == 0 && mlead == 0)
{
// make exo ordering
if (exo_order)
delete exo_order;
exo_order = new ExoVarOrdering(exovars, *this);
exo_order = std::make_unique<ExoVarOrdering>(exovars, *this);
exo_order->do_ordering();
exo_ordering_done = true;
}
@ -534,22 +512,20 @@ FineAtoms::print() const
endo_order->print();
}
else
{
printf("Endo ordering not created.\n");
}
printf("Endo ordering not created.\n");
if (exo_order)
{
printf("Exo ordering:\n");
exo_order->print();
}
else
{
printf("Exo ordering not created.\n");
}
printf("Exo ordering not created.\n");
printf("endo atoms map:\n");
for (unsigned int i = 0; i < endo_atoms_map.size(); i++)
printf("%d --> %d\n", i, endo_atoms_map[i]);
printf(u8"%d → %d\n", i, endo_atoms_map[i]);
printf("exo atoms map:\n");
for (unsigned int i = 0; i < exo_atoms_map.size(); i++)
printf("%d --> %d\n", i, exo_atoms_map[i]);
printf(u8"%d → %d\n", i, exo_atoms_map[i]);
}

View File

@ -9,6 +9,7 @@
#include <vector>
#include <string>
#include <memory>
namespace ogp
{
@ -32,10 +33,10 @@ namespace ogp
: VarOrdering(vo, vnames, a)
{
}
VarOrdering *
std::unique_ptr<VarOrdering>
clone(const vector<const char *> &vnames, const DynamicAtoms &a) const override
{
return new EndoVarOrdering1(*this, vnames, a);
return std::make_unique<EndoVarOrdering1>(*this, vnames, a);
}
void
do_ordering() override
@ -60,10 +61,10 @@ namespace ogp
: VarOrdering(vo, vnames, a)
{
}
VarOrdering *
std::unique_ptr<VarOrdering>
clone(const vector<const char *> &vnames, const DynamicAtoms &a) const override
{
return new EndoVarOrdering2(*this, vnames, a);
return std::make_unique<EndoVarOrdering2>(*this, vnames, a);
}
void
do_ordering() override
@ -87,10 +88,10 @@ namespace ogp
: VarOrdering(vo, vnames, a)
{
}
VarOrdering *
std::unique_ptr<VarOrdering>
clone(const vector<const char *> &vnames, const DynamicAtoms &a) const override
{
return new ExoVarOrdering(*this, vnames, a);
return std::make_unique<ExoVarOrdering>(*this, vnames, a);
}
void
do_ordering() override
@ -201,14 +202,14 @@ namespace ogp
* to endogenous variables. It is constructed by
* parsing_finished() method, which should be called after all
* parsing jobs have been finished. */
VarOrdering *endo_order{nullptr};
std::unique_ptr<VarOrdering> endo_order;
/** This is the internal ordering of all atoms corresponding
* to exogenous variables. It has the same handling as
* endo_order. */
VarOrdering *exo_order{nullptr};
std::unique_ptr<VarOrdering> exo_order;
/** This is the all variables outer ordering. It is
* constructed by parsing finished. */
AllvarOuterOrdering *allvar_order{nullptr};
std::unique_ptr<AllvarOuterOrdering> allvar_order;
/** This vector defines a set of atoms as tree indices used
* for differentiation. The order of the atoms in this vector
* defines ordering of the derivative tensors. The ordering is
@ -228,20 +229,10 @@ namespace ogp
* atoms of exogenous variables. */
vector<int> exo_atoms_map;
public:
FineAtoms()
= default;
FineAtoms() = default;
FineAtoms(const FineAtoms &fa);
/** Deletes endo_order and exo_order. */
~FineAtoms() override
{
if (endo_order)
delete endo_order;
if (exo_order)
delete exo_order;
if (allvar_order)
delete allvar_order;
}
~FineAtoms() override = default;
/** Overrides DynamicAtoms::check_variable so that the error
* would be raised if the variable name is not declared. A
* variable is declared by inserting it to
@ -387,13 +378,13 @@ namespace ogp
int
nexo() const
{
return (int) exovars.size();
return static_cast<int>(exovars.size());
}
/** Return the number of parameters. */
int
np() const
{
return (int) (params.size());
return static_cast<int>(params.size());
}
/** Register unique endogenous variable name. The order of
* calls defines the endo outer ordering. The method is

View File

@ -47,27 +47,27 @@ extern ogp::FormulaParser* fparser;
equation_list : equation_list equation | equation ;
equation : expression EQUAL_SIGN expression ';'
{fparser->add_formula(fparser->add_binary(ogp::MINUS,$1,$3));}
{fparser->add_formula(fparser->add_binary(ogp::code_t::MINUS,$1,$3));}
| expression ';'
{fparser->add_formula($1);}
;
expression : '(' expression ')' { $$ = $2;}
| expression YPLUS expression {$$=fparser->add_binary(ogp::PLUS,$1,$3);}
| expression YMINUS expression {$$=fparser->add_binary(ogp::MINUS,$1,$3);}
| expression YTIMES expression {$$=fparser->add_binary(ogp::TIMES,$1,$3);}
| expression YDIVIDE expression {$$=fparser->add_binary(ogp::DIVIDE,$1,$3);}
| expression YPOWER expression {$$=fparser->add_binary(ogp::POWER,$1,$3);}
| YMINUS expression %prec YUMINUS {$$=fparser->add_unary(ogp::UMINUS,$2);}
| expression YPLUS expression {$$=fparser->add_binary(ogp::code_t::PLUS,$1,$3);}
| expression YMINUS expression {$$=fparser->add_binary(ogp::code_t::MINUS,$1,$3);}
| expression YTIMES expression {$$=fparser->add_binary(ogp::code_t::TIMES,$1,$3);}
| expression YDIVIDE expression {$$=fparser->add_binary(ogp::code_t::DIVIDE,$1,$3);}
| expression YPOWER expression {$$=fparser->add_binary(ogp::code_t::POWER,$1,$3);}
| YMINUS expression %prec YUMINUS {$$=fparser->add_unary(ogp::code_t::UMINUS,$2);}
| YPLUS expression %prec YUPLUS {$$ = $2;}
| YSIN '(' expression ')' {$$=fparser->add_unary(ogp::SIN,$3);}
| YCOS '(' expression ')' {$$=fparser->add_unary(ogp::COS,$3);}
| YTAN '(' expression ')' {$$=fparser->add_unary(ogp::TAN,$3);}
| YEXP '(' expression ')' {$$=fparser->add_unary(ogp::EXP,$3);}
| YLOG '(' expression ')' {$$=fparser->add_unary(ogp::LOG,$3);}
| YSQRT '(' expression ')' {$$=fparser->add_unary(ogp::SQRT,$3);}
| YERF '(' expression ')' {$$=fparser->add_unary(ogp::ERF,$3);}
| YERFC '(' expression ')' {$$=fparser->add_unary(ogp::ERFC,$3);}
| YSIN '(' expression ')' {$$=fparser->add_unary(ogp::code_t::SIN,$3);}
| YCOS '(' expression ')' {$$=fparser->add_unary(ogp::code_t::COS,$3);}
| YTAN '(' expression ')' {$$=fparser->add_unary(ogp::code_t::TAN,$3);}
| YEXP '(' expression ')' {$$=fparser->add_unary(ogp::code_t::EXP,$3);}
| YLOG '(' expression ')' {$$=fparser->add_unary(ogp::code_t::LOG,$3);}
| YSQRT '(' expression ')' {$$=fparser->add_unary(ogp::code_t::SQRT,$3);}
| YERF '(' expression ')' {$$=fparser->add_unary(ogp::code_t::ERF,$3);}
| YERFC '(' expression ')' {$$=fparser->add_unary(ogp::code_t::ERFC,$3);}
| YDIFF '(' expression ',' NAME ')' {$$=fparser->add_derivative($3, fparser->add_nulary($5));}
| NAME {$$=fparser->add_nulary($1);}
| DNUMBER {$$=fparser->add_nulary($1);}

View File

@ -11,7 +11,7 @@
#include "formula_tab.hh"
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace ogp;
@ -21,29 +21,24 @@ FormulaParser::FormulaParser(const FormulaParser &fp, Atoms &a)
: otree(fp.otree), atoms(a), formulas(fp.formulas), ders()
{
// create derivatives
for (auto der : fp.ders)
ders.push_back(new FormulaDerivatives(*der));
}
FormulaParser::~FormulaParser()
{
destroy_derivatives();
for (const auto &der : fp.ders)
ders.push_back(std::make_unique<FormulaDerivatives>(*der));
}
void
FormulaParser::differentiate(int max_order)
{
destroy_derivatives();
ders.clear();
vector<int> vars;
vars = atoms.variables();
for (int formula : formulas)
ders.push_back(new FormulaDerivatives(otree, vars, formula, max_order));
ders.push_back(std::make_unique<FormulaDerivatives>(otree, vars, formula, max_order));
}
const FormulaDerivatives &
FormulaParser::derivatives(int i) const
{
if (i < (int) ders.size())
if (i < static_cast<int>(ders.size()))
return *(ders[i]);
else
throw ogu::Exception(__FILE__, __LINE__,
@ -108,11 +103,10 @@ FormulaParser::substitute_formulas(const map<int, int> &smap)
int f = add_substitution(formulas[i], smap);
formulas[i] = f;
// update the derivatives if any
if (i < (int) ders.size() && ders[i])
if (i < static_cast<int>(ders.size()) && ders[i])
{
int order = ders[i]->get_order();
delete ders[i];
ders[i] = new FormulaDerivatives(otree, atoms.variables(), formulas[i], order);
ders[i] = std::make_unique<FormulaDerivatives>(otree, atoms.variables(), formulas[i], order);
}
}
}
@ -134,16 +128,15 @@ extern location_type fmla_lloc;
void
FormulaParser::parse(int length, const char *stream)
{
auto *buffer = new char[length+2];
strncpy(buffer, stream, length);
auto buffer = std::make_unique<char[]>(length+2);
std::copy_n(stream, length, buffer.get());
buffer[length] = '\0';
buffer[length+1] = '\0';
fmla_lloc.off = 0;
fmla_lloc.ll = 0;
void *p = fmla__scan_buffer(buffer, (unsigned int) length+2);
void *p = fmla__scan_buffer(buffer.get(), static_cast<unsigned int>(length)+2);
fparser = this;
fmla_parse();
delete [] buffer;
fmla__destroy_buffer(p);
}
@ -158,8 +151,7 @@ FormulaParser::last_formula() const
{
int res = -1;
for (int formula : formulas)
if (res < formula)
res = formula;
res = std::max(res, formula);
return std::max(res, otree.get_last_nulary());
}
@ -170,10 +162,7 @@ FormulaParser::pop_last_formula()
return -1;
int t = formulas.back();
if (formulas.size() == ders.size())
{
delete ders.back();
ders.pop_back();
}
ders.pop_back();
formulas.pop_back();
return t;
}
@ -194,16 +183,6 @@ FormulaParser::print() const
}
}
void
FormulaParser::destroy_derivatives()
{
while (ders.size() > 0)
{
delete ders.back();
ders.pop_back();
}
}
/** This constructor makes a vector of indices for formulas
* corresponding to derivatives of the given formula. The formula is
* supposed to belong to the provided tree, the created derivatives
@ -254,13 +233,11 @@ FormulaDerivatives::FormulaDerivatives(OperationTree &otree,
// build ind2der map
for (unsigned int i = 0; i < indices.size(); i++)
ind2der.insert(Tfmiintmap::value_type(indices[i], i));
ind2der.emplace(indices[i], i);
}
FormulaDerivatives::FormulaDerivatives(const FormulaDerivatives &fd)
= default;
FormulaDerivatives::FormulaDerivatives(const FormulaDerivatives &fd) = default;
int
FormulaDerivatives::derivative(const FoldMultiIndex &mi) const
@ -276,7 +253,7 @@ FormulaDerivatives::derivative(const FoldMultiIndex &mi) const
if (it == ind2der.end())
return OperationTree::zero;
else
return tder[(*it).second];
return tder[it->second];
}
void
@ -299,17 +276,17 @@ FormulaCustomEvaluator::eval(const AtomValues &av, FormulaEvalLoader &loader)
for (unsigned int i = 0; i < terms.size(); i++)
{
double res = etree.eval(terms[i]);
loader.load((int) i, res);
loader.load(static_cast<int>(i), res);
}
}
FoldMultiIndex::FoldMultiIndex(int nv)
: nvar(nv), ord(0), data(new int[ord])
: nvar(nv), ord(0), data(std::make_unique<int[]>(ord))
{
}
FoldMultiIndex::FoldMultiIndex(int nv, int ordd, int ii)
: nvar(nv), ord(ordd), data(new int[ord])
: nvar(nv), ord(ordd), data(std::make_unique<int[]>(ord))
{
for (int i = 0; i < ord; i++)
data[i] = ii;
@ -318,7 +295,7 @@ FoldMultiIndex::FoldMultiIndex(int nv, int ordd, int ii)
/** Note that a monotone sequence mapped by monotone mapping yields a
* monotone sequence. */
FoldMultiIndex::FoldMultiIndex(int nv, const FoldMultiIndex &mi, const vector<int> &mp)
: nvar(nv), ord(mi.ord), data(new int[ord])
: nvar(nv), ord(mi.ord), data(std::make_unique<int[]>(ord))
{
for (int i = 0; i < ord; i++)
{
@ -335,36 +312,31 @@ FoldMultiIndex::FoldMultiIndex(int nv, const FoldMultiIndex &mi, const vector<in
FoldMultiIndex::FoldMultiIndex(const FoldMultiIndex &fmi, int new_orders)
: nvar(fmi.nvar),
ord(fmi.ord+new_orders),
data(new int[ord])
data(std::make_unique<int[]>(ord))
{
memcpy(data, fmi.data, fmi.ord*sizeof(int));
std::copy_n(fmi.data.get(), fmi.ord, data.get());
int new_item = (fmi.ord > 0) ? fmi.data[fmi.ord-1] : 0;
for (int i = fmi.ord; i < ord; i++)
{
data[i] = new_item;
}
data[i] = new_item;
}
FoldMultiIndex::FoldMultiIndex(const FoldMultiIndex &fmi)
: nvar(fmi.nvar),
ord(fmi.ord),
data(new int[fmi.ord])
data(std::make_unique<int[]>(ord))
{
memcpy(data, fmi.data, ord*sizeof(int));
std::copy_n(fmi.data.get(), ord, data.get());
}
const FoldMultiIndex &
FoldMultiIndex::operator=(const FoldMultiIndex &fmi)
{
if (ord != fmi.ord)
{
delete [] data;
data = new int[fmi.ord];
}
data = std::make_unique<int[]>(fmi.ord);
ord = fmi.ord;
nvar = fmi.nvar;
memcpy(data, fmi.data, ord*sizeof(int));
std::copy_n(fmi.data.get(), ord, data.get());
return *this;
}
@ -427,13 +399,10 @@ int
FoldMultiIndex::offset() const
{
// make copy for the recursions
auto *tmp = new int[ord];
for (int i = 0; i < ord; i++)
tmp[i] = data[i];
auto tmp = std::make_unique<int[]>(ord);
std::copy_n(data.get(), ord, tmp.get());
// call the recursive algorithm
int res = offset_recurse(tmp, ord, nvar);
delete [] tmp;
int res = offset_recurse(tmp.get(), ord, nvar);
return res;
}
@ -478,8 +447,8 @@ ltfmi::operator()(const FoldMultiIndex &i1, const FoldMultiIndex &i2) const
FormulaDerEvaluator::FormulaDerEvaluator(const FormulaParser &fp)
: etree(fp.otree, -1)
{
for (auto der : fp.ders)
ders.push_back((const FormulaDerivatives *) der);
for (const auto &der : fp.ders)
ders.push_back(der.get());
der_atoms = fp.atoms.variables();
}
@ -498,28 +467,25 @@ FormulaDerEvaluator::eval(const AtomValues &av, FormulaDerEvalLoader &loader, in
etree.reset_all();
av.setValues(etree);
auto *vars = new int[order];
auto vars = std::make_unique<int[]>(order);
for (unsigned int i = 0; i < ders.size(); i++)
{
for (auto it = ders[i]->ind2der.begin();
it != ders[i]->ind2der.end(); ++it)
for (const auto &it : ders[i]->ind2der)
{
const FoldMultiIndex &mi = (*it).first;
const FoldMultiIndex &mi = it.first;
if (mi.order() == order)
{
// set vars from multiindex mi and variables
for (int k = 0; k < order; k++)
vars[k] = der_atoms[mi[k]];
// evaluate
double res = etree.eval(ders[i]->tder[(*it).second]);
double res = etree.eval(ders[i]->tder[it.second]);
// load
loader.load(i, order, vars, res);
loader.load(i, order, vars.get(), res);
}
}
}
delete [] vars;
}
void
@ -531,7 +497,7 @@ FormulaDerEvaluator::eval(const vector<int> &mp, const AtomValues &av,
int nvar_glob = der_atoms.size();
int nvar = mp.size();
auto *vars = new int[order];
auto vars = std::make_unique<int[]>(order);
for (unsigned int i = 0; i < ders.size(); i++)
{
@ -549,12 +515,10 @@ FormulaDerEvaluator::eval(const vector<int> &mp, const AtomValues &av,
// evaluate derivative
double res = etree.eval(der);
// load
loader.load(i, order, vars, res);
loader.load(i, order, vars.get(), res);
}
mi.increment();
}
while (!mi.past_the_end());
}
delete [] vars;
}

View File

@ -4,6 +4,8 @@
#define OGP_FORMULA_PARSER_H
#include <utility>
#include <memory>
#include <vector>
#include "tree.hh"
@ -16,10 +18,8 @@ namespace ogp
class Atoms
{
public:
Atoms()
= default;
virtual ~Atoms()
= default;
Atoms() = default;
virtual ~Atoms() = default;
/** This returns previously assigned internal index to the
* given atom, or returns -1 if the atom has not been assigned
* yet. The method can raise an exception, if the Atoms
@ -48,8 +48,7 @@ namespace ogp
class AtomValues
{
public:
virtual ~AtomValues()
= default;
virtual ~AtomValues() = default;
virtual void setValues(EvalTree &et) const = 0;
};
@ -110,8 +109,7 @@ namespace ogp
FormulaDerivatives(OperationTree &otree, const vector<int> &vars, int f, int max_order);
/** Copy constructor. */
FormulaDerivatives(const FormulaDerivatives &fd);
virtual ~FormulaDerivatives()
= default;
virtual ~FormulaDerivatives() = default;
/** Random access to the derivatives via multiindex. */
int derivative(const FoldMultiIndex &mi) const;
/** Return the order. */
@ -151,7 +149,7 @@ namespace ogp
vector<int> formulas;
/** The vector to derivatives, each vector corresponds to a
* formula in the vector formulas. */
vector<FormulaDerivatives *> ders;
vector<std::unique_ptr<FormulaDerivatives>> ders;
public:
/** Construct an empty formula parser. */
FormulaParser(Atoms &a)
@ -161,8 +159,7 @@ namespace ogp
FormulaParser(const FormulaParser &fp) = delete;
/** Copy constructor using a different instance of Atoms. */
FormulaParser(const FormulaParser &fp, Atoms &a);
virtual
~FormulaParser();
virtual ~FormulaParser() = default;
/** Requires an addition of the formula; called from the
* parser. */
@ -267,7 +264,7 @@ namespace ogp
int
nformulas() const
{
return (int) (formulas.size());
return static_cast<int>(formulas.size());
}
/** This returns a reference to atoms. */
@ -295,9 +292,6 @@ namespace ogp
/** Debug print. */
void print() const;
private:
/** Destroy all derivatives. */
void destroy_derivatives();
};
/** This is a pure virtual class defining an interface for all
@ -307,8 +301,7 @@ namespace ogp
class FormulaEvalLoader
{
public:
virtual ~FormulaEvalLoader()
= default;
virtual ~FormulaEvalLoader() = default;
/** Set the value res for the given formula. The formula is
* identified by an index corresponding to the ordering in
* which the formulas have been parsed (starting from
@ -368,8 +361,7 @@ namespace ogp
class FormulaDerEvalLoader
{
public:
virtual ~FormulaDerEvalLoader()
= default;
virtual ~FormulaDerEvalLoader() = default;
/** This loads the result of the derivative of the given
* order. The semantics of i is the same as in
* FormulaEvalLoader::load. The indices of variables with
@ -389,7 +381,7 @@ namespace ogp
/** Dimension. */
int ord;
/** The multiindex. */
int *data;
std::unique_ptr<int[]> data;
public:
/** Initializes to the zero derivative. Order is 0, data is
* empty. */
@ -407,10 +399,7 @@ namespace ogp
/** Copy constructor. */
FoldMultiIndex(const FoldMultiIndex &fmi);
/** Desctructor. */
virtual ~FoldMultiIndex()
{
delete [] data;
}
virtual ~FoldMultiIndex() = default;
/** Assignment operator. */
const FoldMultiIndex &operator=(const FoldMultiIndex &fmi);
/** Operator < implementing lexicographic ordering within one
@ -443,7 +432,7 @@ namespace ogp
const int *
ind() const
{
return data;
return data.get();
}
/** Return true if the end of the tensor is reached. The
* result of a subsequent increment should be considered

View File

@ -6,7 +6,9 @@
#include "matrix_parser.hh"
#include "location.hh"
#include "matrix_tab.hh"
#include <cstring>
#include <memory>
#include <algorithm>
using namespace ogp;
@ -29,16 +31,15 @@ MatrixParser::parse(int length, const char *stream)
row_lengths.clear();
nc = 0;
// allocate temporary buffer and parse
auto *buffer = new char[length+2];
strncpy(buffer, stream, length);
auto buffer = std::make_unique<char[]>(length+2);
std::copy_n(stream, length, buffer.get());
buffer[length] = '\0';
buffer[length+1] = '\0';
matrix_lloc.off = 0;
matrix_lloc.ll = 0;
void *p = matrix__scan_buffer(buffer, (unsigned int) length+2);
void *p = matrix__scan_buffer(buffer.get(), static_cast<unsigned int>(length)+2);
mparser = this;
matrix_parse();
delete [] buffer;
matrix__destroy_buffer(p);
}
@ -49,8 +50,7 @@ MatrixParser::add_item(double v)
if (row_lengths.size() == 0)
row_lengths.push_back(0);
(row_lengths.back())++;
if (row_lengths.back() > nc)
nc = row_lengths.back();
nc = std::max(nc, row_lengths.back());
}
void
@ -69,7 +69,7 @@ int
MatrixParser::find_first_non_empty_row(int start) const
{
int r = start;
while (r < (int) row_lengths.size() && row_lengths[r] == 0)
while (r < static_cast<int>(row_lengths.size()) && row_lengths[r] == 0)
r++;
return r;
}

View File

@ -5,7 +5,6 @@
#ifndef OGP_MATRIX_PARSER
#define OGP_MATRIX_PARSER
#include <cstdlib> // For NULL
#include <vector>
namespace ogp
@ -33,19 +32,14 @@ namespace ogp
/** Maximum number of row lengths. */
int nc{0};
public:
MatrixParser()
= default;
MatrixParser(const MatrixParser &mp)
= default;
virtual ~MatrixParser()
= default;
MatrixParser() = default;
MatrixParser(const MatrixParser &mp) = default;
virtual ~MatrixParser() = default;
/** Return a number of read rows. */
int
nrows() const
{
return (int) row_lengths.size();
return static_cast<int>(row_lengths.size());
}
/** Return a maximum number of items in the rows. */
int
@ -91,8 +85,7 @@ namespace ogp
int r{0};
public:
MPIterator()
= default;
MPIterator() = default;
/** Constructs an iterator pointing to the beginning of the
* parsed matrix. */
MPIterator(const MatrixParser &mp);
@ -118,9 +111,7 @@ namespace ogp
return c;
}
/** Assignment operator. */
MPIterator &
operator=(const MPIterator &it)
= default;
MPIterator &operator=(const MPIterator &it) = default;
/** Return true if the iterators are the same, this is if they
* have the same underlying object and the same item index. */
bool

View File

@ -4,7 +4,8 @@
#include "namelist.hh"
#include <cstring>
#include <memory>
#include <algorithm>
using namespace ogp;
@ -19,13 +20,12 @@ void namelist_parse();
void
NameListParser::namelist_parse(int length, const char *stream)
{
auto *buffer = new char[length+2];
strncpy(buffer, stream, length);
auto buffer = std::make_unique<char[]>(length+2);
std::copy_n(str, length, buffer.get());
buffer[length] = '\0';
buffer[length+1] = '\0';
void *p = namelist__scan_buffer(buffer, (unsigned int) length+2);
void *p = namelist__scan_buffer(buffer.get(), static_cast<unsigned int>(length)+2);
name_list_parser = this;
::namelist_parse();
delete [] buffer;
namelist__destroy_buffer(p);
}

View File

@ -7,7 +7,6 @@
namespace ogp
{
/** Parent class of all parsers parsing a namelist. They must
* implement add_name() method and error() method, which is called
* when an parse error occurs.
@ -20,8 +19,7 @@ namespace ogp
class NameListParser
{
public:
virtual ~NameListParser()
= default;
virtual ~NameListParser() = default;
virtual void add_name(const char *name) = 0;
virtual void namelist_error(const char *mes) = 0;
void namelist_parse(int length, const char *text);

View File

@ -3,61 +3,42 @@
// $Id: parser_exception.cpp 2269 2008-11-23 14:33:22Z michel $
#include "parser_exception.hh"
#include <cstring>
#include <cstdio>
using namespace ogp;
ParserException::ParserException(const char *m, int offset)
: mes(new char[strlen(m)+1]), off(offset),
ParserException::ParserException(string m, int offset)
: mes(std::move(m)), off(offset),
aux_i1(-1), aux_i2(-1), aux_i3(-1)
{
strcpy(mes, m);
}
ParserException::ParserException(const string &m, int offset)
: mes(new char[m.size()+1]), off(offset),
aux_i1(-1), aux_i2(-1), aux_i3(-1)
{
strncpy(mes, m.c_str(), m.size());
mes[m.size()] = '\0';
}
ParserException::ParserException(const string &m, const char *dum, int i1)
: mes(new char[m.size()+1]), off(0),
ParserException::ParserException(string m, const char *dum, int i1)
: mes(std::move(m)), off(0),
aux_i1(i1), aux_i2(-1), aux_i3(-1)
{
strncpy(mes, m.c_str(), m.size());
mes[m.size()] = '\0';
}
ParserException::ParserException(const string &m, const char *dum, int i1, int i2)
: mes(new char[m.size()+1]), off(0),
ParserException::ParserException(string m, const char *dum, int i1, int i2)
: mes(std::move(m)), off(0),
aux_i1(i1), aux_i2(i2), aux_i3(-1)
{
strncpy(mes, m.c_str(), m.size());
mes[m.size()] = '\0';
}
ParserException::ParserException(const string &m, const char *dum, int i1, int i2, int i3)
: mes(new char[m.size()+1]), off(0),
ParserException::ParserException(string m, const char *dum, int i1, int i2, int i3)
: mes(std::move(m)), off(0),
aux_i1(i1), aux_i2(i2), aux_i3(i3)
{
strncpy(mes, m.c_str(), m.size());
mes[m.size()] = '\0';
}
ParserException::ParserException(const ParserException &m, int plus_offset)
: mes(nullptr),
aux_i1(-1), aux_i2(-1), aux_i3(-1)
: aux_i1(-1), aux_i2(-1), aux_i3(-1)
{
copy(m);
off += plus_offset;
}
ParserException::ParserException(const ParserException &m, const char *dum, int i)
: mes(nullptr),
aux_i1(-1), aux_i2(-1), aux_i3(-1)
: aux_i1(-1), aux_i2(-1), aux_i3(-1)
{
copy(m);
aux_i3 = m.aux_i2;
@ -66,8 +47,7 @@ ParserException::ParserException(const ParserException &m, const char *dum, int
}
ParserException::ParserException(const ParserException &m, const char *dum, int i1, int i2)
: mes(nullptr),
aux_i1(-1), aux_i2(-1), aux_i3(-1)
: aux_i1(-1), aux_i2(-1), aux_i3(-1)
{
copy(m);
aux_i3 = m.aux_i1;
@ -76,8 +56,7 @@ ParserException::ParserException(const ParserException &m, const char *dum, int
}
ParserException::ParserException(const ParserException &m, const char *dum, int i1, int i2, int i3)
: mes(nullptr),
aux_i1(-1), aux_i2(-1), aux_i3(-1)
: aux_i1(-1), aux_i2(-1), aux_i3(-1)
{
copy(m);
aux_i3 = i3;
@ -85,34 +64,12 @@ ParserException::ParserException(const ParserException &m, const char *dum, int
aux_i1 = i1;
}
ParserException::ParserException(const ParserException &e)
: mes(nullptr),
aux_i1(-1), aux_i2(-1), aux_i3(-1)
{
copy(e);
}
ParserException::~ParserException()
{
delete [] mes;
}
void
ParserException::copy(const ParserException &e)
{
if (mes)
delete [] mes;
mes = new char[strlen(e.mes)+1];
strcpy(mes, e.mes);
mes = e.mes;
off = e.off;
aux_i1 = e.aux_i1;
aux_i2 = e.aux_i2;
aux_i3 = e.aux_i3;
}
void
ParserException::print(FILE *fd) const
{
// todo: to be refined
fprintf(fd, "%s: offset %d\n", mes, off);
}

View File

@ -21,17 +21,16 @@ namespace ogp
class ParserException
{
protected:
char *mes;
string mes;
int off;
int aux_i1;
int aux_i2;
int aux_i3;
public:
ParserException(const char *m, int offset);
ParserException(const string &m, int offset);
ParserException(const string &m, const char *dum, int i1);
ParserException(const string &m, const char *dum, int i1, int i2);
ParserException(const string &m, const char *dum, int i1, int i2, int i3);
ParserException(string m, int offset);
ParserException(string m, const char *dum, int i1);
ParserException(string m, const char *dum, int i1, int i2);
ParserException(string m, const char *dum, int i1, int i2, int i3);
ParserException(const ParserException &e, int plus_offset);
/** Makes a copy and pushes given integer to aux_i1 shuffling
* others and forgetting the last. */
@ -42,11 +41,9 @@ namespace ogp
/** Makes a copy and pushes given three integers to aux_i1, aux_i2, aus_i3 shuffling
* others and forgetting the last three. */
ParserException(const ParserException &e, const char *dum, int i1, int i2, int i3);
ParserException(const ParserException &e);
virtual
~ParserException();
void print(FILE *fd) const;
const char *
ParserException(const ParserException &e) = default;
virtual ~ParserException() = default;
const string &
message() const
{
return mes;

View File

@ -22,14 +22,14 @@ StaticAtoms::StaticAtoms(const StaticAtoms &a)
for (auto var : a.vars)
{
const char *s = varnames.query(var.first);
vars.insert(Tvarmap::value_type(s, var.second));
vars.emplace(s, var.second);
}
// fill indices
for (auto indice : a.indices)
{
const char *s = varnames.query(indice.second);
indices.insert(Tinvmap::value_type(indice.first, s));
indices.emplace(indice.first, s);
}
}
@ -50,7 +50,7 @@ StaticAtoms::import_atoms(const DynamicAtoms &da, OperationTree &otree, Tintintm
for (auto it : lmap)
{
int told = it.second;
tmap.insert(Tintintmap::value_type(told, tnew));
tmap.emplace(told, tnew);
}
}
}
@ -60,13 +60,9 @@ int
StaticAtoms::check(const char *name) const
{
if (DynamicAtoms::is_string_constant(name))
{
return Constants::check(name);
}
return Constants::check(name);
else
{
return check_variable(name);
}
return check_variable(name);
}
int
@ -76,7 +72,7 @@ StaticAtoms::index(const char *name) const
if (it == vars.end())
return -1;
else
return (*it).second;
return it->second;
}
const char *
@ -86,7 +82,7 @@ StaticAtoms::inv_index(int t) const
if (it == indices.end())
return nullptr;
else
return (*it).second;
return it->second;
}
void
@ -101,8 +97,8 @@ StaticAtoms::assign(const char *name, int t)
else
{
const char *ss = varnames.insert(name);
vars.insert(Tvarmap::value_type(ss, t));
indices.insert(Tinvmap::value_type(t, ss));
vars.emplace(ss, t);
indices.emplace(t, ss);
}
}
@ -111,9 +107,7 @@ StaticAtoms::variables() const
{
vector<int> res;
for (auto var : vars)
{
res.push_back(var.second);
}
res.push_back(var.second);
return res;
}
@ -133,5 +127,5 @@ StaticAtoms::print() const
varnames.print();
printf("map to tree indices:\n");
for (auto var : vars)
printf("%s\t->\t%d\n", var.first, var.second);
printf(u8"%s\t\t%d\n", var.first, var.second);
}

View File

@ -9,7 +9,6 @@
namespace ogp
{
class StaticAtoms : public Atoms, public Constants
{
protected:
@ -42,8 +41,7 @@ namespace ogp
import_atoms(da, otree, tmap);
}
/* Destructor. */
~StaticAtoms()
override = default;
~StaticAtoms() override = default;
/** This imports atoms from dynamic atoms inserting the new
* tree indices to the given tree (including constants). The
* mapping from old atoms to new atoms is traced in tmap. */

View File

@ -22,21 +22,21 @@ StaticFineAtoms::StaticFineAtoms(const StaticFineAtoms &sfa)
{
const char *name = varnames.query(sfa.params[i]);
params.push_back(name);
param_outer_map.insert(Tvarintmap::value_type(name, i));
param_outer_map.emplace(name, i);
}
for (unsigned int i = 0; i < sfa.endovars.size(); i++)
{
const char *name = varnames.query(sfa.endovars[i]);
endovars.push_back(name);
endo_outer_map.insert(Tvarintmap::value_type(name, i));
endo_outer_map.emplace(name, i);
}
for (unsigned int i = 0; i < sfa.exovars.size(); i++)
{
const char *name = varnames.query(sfa.exovars[i]);
exovars.push_back(name);
exo_outer_map.insert(Tvarintmap::value_type(name, i));
exo_outer_map.emplace(name, i);
}
}
@ -97,7 +97,7 @@ int
StaticFineAtoms::check_variable(const char *name) const
{
const char *ss = varnames.query(name);
if (ss == nullptr)
if (!ss)
throw ParserException(string("Variable <")+name+"> not declared.", 0);
return index(name);
}
@ -139,7 +139,7 @@ StaticFineAtoms::name2outer_param(const char *name) const
if (it == param_outer_map.end())
throw ogu::Exception(__FILE__, __LINE__,
"Name is not a parameter in StaticFineAtoms::name2outer_param");
return (*it).second;
return it->second;
}
int
@ -149,7 +149,7 @@ StaticFineAtoms::name2outer_endo(const char *name) const
if (it == endo_outer_map.end())
throw ogu::Exception(__FILE__, __LINE__,
"Name is not an endogenous variable in StaticFineAtoms::name2outer_endo");
return (*it).second;
return it->second;
}
int
@ -159,7 +159,7 @@ StaticFineAtoms::name2outer_exo(const char *name) const
if (it == exo_outer_map.end())
throw ogu::Exception(__FILE__, __LINE__,
"Name is not an exogenous variable in StaticFineAtoms::name2outer_exo");
return (*it).second;
return it->second;
}
void
@ -195,10 +195,10 @@ StaticFineAtoms::print() const
StaticAtoms::print();
printf("endo atoms map:\n");
for (unsigned int i = 0; i < endo_atoms_map.size(); i++)
printf("%d --> %d\n", i, endo_atoms_map[i]);
printf(u8"%d → %d\n", i, endo_atoms_map[i]);
printf("exo atoms map:\n");
for (unsigned int i = 0; i < exo_atoms_map.size(); i++)
printf("%d --> %d\n", i, exo_atoms_map[i]);
printf(u8"%d → %d\n", i, exo_atoms_map[i]);
printf("der atoms:\n");
for (unsigned int i = 0; i < der_atoms.size(); i++)
printf("%d\t%d\n", i, der_atoms[i]);
@ -208,30 +208,30 @@ void
StaticFineAtoms::register_endo(const char *name)
{
const char *ss = varnames.query(name);
if (ss == nullptr)
if (!ss)
throw ogp::ParserException(string("Endogenous variable <")
+name+"> not found in storage.", 0);
endovars.push_back(ss);
endo_outer_map.insert(Tvarintmap::value_type(ss, endovars.size()-1));
endo_outer_map.emplace(ss, endovars.size()-1);
}
void
StaticFineAtoms::register_exo(const char *name)
{
const char *ss = varnames.query(name);
if (ss == nullptr)
if (!ss)
throw ogp::ParserException(string("Exogenous variable <")
+name+"> not found in storage.", 0);
exovars.push_back(ss);
exo_outer_map.insert(Tvarintmap::value_type(ss, exovars.size()-1));
exo_outer_map.emplace(ss, exovars.size()-1);
}
void
StaticFineAtoms::register_param(const char *name)
{
const char *ss = varnames.query(name);
if (ss == nullptr)
if (!ss)
throw ogp::ParserException(string("Parameter <")+name+"> not found in storage.", 0);
params.push_back(ss);
param_outer_map.insert(Tvarintmap::value_type(ss, params.size()-1));
param_outer_map.emplace(ss, params.size()-1);
}

View File

@ -10,7 +10,6 @@
namespace ogp
{
/** This class represents static atoms distinguishing between
* parameters, endogenous and exogenous variables. The class
* maintains also ordering of all three categories (referenced as
@ -61,8 +60,7 @@ namespace ogp
* atoms of exogenous variables. */
vector<int> exo_atoms_map;
public:
StaticFineAtoms()
= default;
StaticFineAtoms() = default;
/** Copy constructor making a new storage for atom names. */
StaticFineAtoms(const StaticFineAtoms &sfa);
/** Conversion from dynamic FineAtoms taking its outer
@ -84,8 +82,7 @@ namespace ogp
{
StaticFineAtoms::import_atoms(fa, otree, tmap, dummy);
}
~StaticFineAtoms()
override = default;
~StaticFineAtoms() override = default;
/** This adds atoms from dynamic atoms inserting new tree
* indices to the given tree and tracing the mapping from old
* atoms to new atoms in tmap. The ordering of the static
@ -166,13 +163,13 @@ namespace ogp
int
nexo() const
{
return (int) exovars.size();
return static_cast<int>(exovars.size());
}
/** Return the number of parameters. */
int
np() const
{
return (int) (params.size());
return static_cast<int>(params.size());
}
/** Register unique endogenous variable name. The order of
* calls defines the endo outer ordering. The method is
@ -202,7 +199,6 @@ namespace ogp
* storage. */
void register_param(const char *name);
};
};
#endif

View File

@ -4,8 +4,6 @@
#include "tree.hh"
#include <cstdlib>
#include <cmath>
#include <limits>
@ -25,13 +23,11 @@ int
OperationTree::add_nulary()
{
int op = terms.size();
Operation nulary;
terms.push_back(nulary);
terms.push_back({});
_Tintset s;
s.insert(op);
nul_incidence.push_back(s);
_Tderivmap empty;
derivatives.push_back(empty);
derivatives.push_back({});
last_nulary = op;
return op;
}
@ -40,21 +36,21 @@ int
OperationTree::add_unary(code_t code, int op)
{
if (op == zero
&& (code == UMINUS
|| code == SIN
|| code == TAN
|| code == SQRT
|| code == ERF))
&& (code == code_t::UMINUS
|| code == code_t::SIN
|| code == code_t::TAN
|| code == code_t::SQRT
|| code == code_t::ERF))
return zero;
if ((op == zero && code == LOG) || op == nan)
if ((op == zero && code == code_t::LOG) || op == nan)
return nan;
if (op == zero && (code == EXP
|| code == COS
|| code == ERFC))
if (op == zero && (code == code_t::EXP
|| code == code_t::COS
|| code == code_t::ERFC))
return one;
Operation unary(code, op);
auto i = ((const _Topmap &) opmap).find(unary);
auto i = opmap.find(unary);
if (i == opmap.end())
{
int newop = terms.size();
@ -63,13 +59,13 @@ OperationTree::add_unary(code_t code, int op)
// copy incidence of the operand
nul_incidence.push_back(nul_incidence[op]);
// insert it to opmap
opmap.insert(_Topval(unary, newop));
opmap.emplace(unary, newop);
// add empty map of derivatives
_Tderivmap empty;
derivatives.push_back(empty);
return newop;
}
return (*i).second;
return i->second;
}
int
@ -79,7 +75,7 @@ OperationTree::add_binary(code_t code, int op1, int op2)
if (op1 == nan || op2 == nan)
return nan;
// for plus
if (code == PLUS)
if (code == code_t::PLUS)
{
if (op1 == zero && op2 == zero)
return zero;
@ -89,17 +85,17 @@ OperationTree::add_binary(code_t code, int op1, int op2)
return op1;
}
// for minus
if (code == MINUS)
if (code == code_t::MINUS)
{
if (op1 == zero && op2 == zero)
return zero;
else if (op1 == zero)
return add_unary(UMINUS, op2);
return add_unary(code_t::UMINUS, op2);
else if (op2 == zero)
return op1;
}
// for times
if (code == TIMES)
if (code == code_t::TIMES)
{
if (op1 == zero || op2 == zero)
return zero;
@ -109,7 +105,7 @@ OperationTree::add_binary(code_t code, int op1, int op2)
return op1;
}
// for divide
if (code == DIVIDE)
if (code == code_t::DIVIDE)
{
if (op1 == op2)
return one;
@ -119,7 +115,7 @@ OperationTree::add_binary(code_t code, int op1, int op2)
return nan;
}
// for power
if (code == POWER)
if (code == code_t::POWER)
{
if (op1 == zero && op2 == zero)
return nan;
@ -134,7 +130,7 @@ OperationTree::add_binary(code_t code, int op1, int op2)
}
// order operands of commutative operations
if (code == TIMES || code == PLUS)
if (code == code_t::TIMES || code == code_t::PLUS)
if (op1 > op2)
{
int tmp = op1;
@ -144,7 +140,7 @@ OperationTree::add_binary(code_t code, int op1, int op2)
// construct operation and check/add it
Operation binary(code, op1, op2);
auto i = ((const _Topmap &) opmap).find(binary);
auto i = opmap.find(binary);
if (i == opmap.end())
{
int newop = terms.size();
@ -153,164 +149,159 @@ OperationTree::add_binary(code_t code, int op1, int op2)
nul_incidence.push_back(nul_incidence[op1]);
nul_incidence.back().insert(nul_incidence[op2].begin(), nul_incidence[op2].end());
// add to opmap
opmap.insert(_Topval(binary, newop));
opmap.emplace(binary, newop);
// add empty map of derivatives
_Tderivmap empty;
derivatives.push_back(empty);
return newop;
}
return (*i).second;
return i->second;
}
int
OperationTree::add_derivative(int t, int v)
{
if (t < 0 || t >= (int) terms.size())
if (t < 0 || t >= static_cast<int>(terms.size()))
throw ogu::Exception(__FILE__, __LINE__,
"Wrong value for tree index in OperationTree::add_derivative");
// quick returns for nulary terms or empty incidence
if (terms[t].nary() == 0 && t != v)
{
return zero;
}
return zero;
if (terms[t].nary() == 0 && t == v)
{
return one;
}
return one;
if (nul_incidence[t].end() == nul_incidence[t].find(v))
{
return zero;
}
return zero;
// quick return if the derivative has been registered
_Tderivmap::const_iterator i = derivatives[t].find(v);
auto i = derivatives[t].find(v);
if (i != derivatives[t].end())
return (*i).second;
return i->second;
int res = -1;
switch (terms[t].getCode())
{
case UMINUS:
case code_t::UMINUS:
{
int tmp = add_derivative(terms[t].getOp1(), v);
res = add_unary(UMINUS, tmp);
res = add_unary(code_t::UMINUS, tmp);
break;
}
case LOG:
case code_t::LOG:
{
int tmp = add_derivative(terms[t].getOp1(), v);
res = add_binary(DIVIDE, tmp, terms[t].getOp1());
res = add_binary(code_t::DIVIDE, tmp, terms[t].getOp1());
break;
}
case EXP:
case code_t::EXP:
{
int tmp = add_derivative(terms[t].getOp1(), v);
res = add_binary(TIMES, t, tmp);
res = add_binary(code_t::TIMES, t, tmp);
break;
}
case SIN:
case code_t::SIN:
{
int tmp = add_derivative(terms[t].getOp1(), v);
res = add_binary(TIMES, add_unary(COS, terms[t].getOp1()), tmp);
res = add_binary(code_t::TIMES, add_unary(code_t::COS, terms[t].getOp1()), tmp);
break;
}
case COS:
case code_t::COS:
{
int tmp = add_derivative(terms[t].getOp1(), v);
res = add_unary(UMINUS, add_binary(TIMES, add_unary(SIN, terms[t].getOp1()), tmp));
res = add_unary(code_t::UMINUS, add_binary(code_t::TIMES, add_unary(code_t::SIN, terms[t].getOp1()), tmp));
break;
}
case TAN:
case code_t::TAN:
{
int tmp = add_derivative(terms[t].getOp1(), v);
int tmp2 = add_unary(COS, terms[t].getOp1());
res = add_binary(DIVIDE, tmp, add_binary(TIMES, tmp2, tmp2));
int tmp2 = add_unary(code_t::COS, terms[t].getOp1());
res = add_binary(code_t::DIVIDE, tmp, add_binary(code_t::TIMES, tmp2, tmp2));
break;
}
case SQRT:
case code_t::SQRT:
{
int tmp = add_derivative(terms[t].getOp1(), v);
res = add_binary(DIVIDE, tmp,
add_binary(PLUS, t, t));
res = add_binary(code_t::DIVIDE, tmp,
add_binary(code_t::PLUS, t, t));
break;
}
case ERF:
case code_t::ERF:
{
int tmp = add_binary(TIMES, terms[t].getOp1(), terms[t].getOp1());
tmp = add_unary(UMINUS, tmp);
tmp = add_unary(EXP, tmp);
int tmp = add_binary(code_t::TIMES, terms[t].getOp1(), terms[t].getOp1());
tmp = add_unary(code_t::UMINUS, tmp);
tmp = add_unary(code_t::EXP, tmp);
int der = add_derivative(terms[t].getOp1(), v);
tmp = add_binary(TIMES, tmp, der);
res = add_binary(TIMES, two_over_pi, tmp);
tmp = add_binary(code_t::TIMES, tmp, der);
res = add_binary(code_t::TIMES, two_over_pi, tmp);
break;
}
case ERFC:
case code_t::ERFC:
{
int tmp = add_binary(TIMES, terms[t].getOp1(), terms[t].getOp1());
tmp = add_unary(UMINUS, tmp);
tmp = add_unary(EXP, tmp);
int tmp = add_binary(code_t::TIMES, terms[t].getOp1(), terms[t].getOp1());
tmp = add_unary(code_t::UMINUS, tmp);
tmp = add_unary(code_t::EXP, tmp);
int der = add_derivative(terms[t].getOp1(), v);
tmp = add_binary(TIMES, tmp, der);
tmp = add_binary(TIMES, two_over_pi, tmp);
res = add_unary(UMINUS, tmp);
tmp = add_binary(code_t::TIMES, tmp, der);
tmp = add_binary(code_t::TIMES, two_over_pi, tmp);
res = add_unary(code_t::UMINUS, tmp);
break;
}
case PLUS:
case code_t::PLUS:
{
int tmp1 = add_derivative(terms[t].getOp1(), v);
int tmp2 = add_derivative(terms[t].getOp2(), v);
res = add_binary(PLUS, tmp1, tmp2);
res = add_binary(code_t::PLUS, tmp1, tmp2);
break;
}
case MINUS:
case code_t::MINUS:
{
int tmp1 = add_derivative(terms[t].getOp1(), v);
int tmp2 = add_derivative(terms[t].getOp2(), v);
res = add_binary(MINUS, tmp1, tmp2);
res = add_binary(code_t::MINUS, tmp1, tmp2);
break;
}
case TIMES:
case code_t::TIMES:
{
int tmp1 = add_derivative(terms[t].getOp1(), v);
int tmp2 = add_derivative(terms[t].getOp2(), v);
int res1 = add_binary(TIMES, terms[t].getOp1(), tmp2);
int res2 = add_binary(TIMES, tmp1, terms[t].getOp2());
res = add_binary(PLUS, res1, res2);
int res1 = add_binary(code_t::TIMES, terms[t].getOp1(), tmp2);
int res2 = add_binary(code_t::TIMES, tmp1, terms[t].getOp2());
res = add_binary(code_t::PLUS, res1, res2);
break;
}
case DIVIDE:
case code_t::DIVIDE:
{
int tmp1 = add_derivative(terms[t].getOp1(), v);
int tmp2 = add_derivative(terms[t].getOp2(), v);
if (tmp2 == zero)
res = add_binary(DIVIDE, tmp1, terms[t].getOp2());
res = add_binary(code_t::DIVIDE, tmp1, terms[t].getOp2());
else
{
int nom = add_binary(MINUS,
add_binary(TIMES, tmp1, terms[t].getOp2()),
add_binary(TIMES, tmp2, terms[t].getOp1()));
int den = add_binary(TIMES, terms[t].getOp2(), terms[t].getOp2());
res = add_binary(DIVIDE, nom, den);
int nom = add_binary(code_t::MINUS,
add_binary(code_t::TIMES, tmp1, terms[t].getOp2()),
add_binary(code_t::TIMES, tmp2, terms[t].getOp1()));
int den = add_binary(code_t::TIMES, terms[t].getOp2(), terms[t].getOp2());
res = add_binary(code_t::DIVIDE, nom, den);
}
break;
}
case POWER:
case code_t::POWER:
{
int tmp1 = add_derivative(terms[t].getOp1(), v);
int tmp2 = add_derivative(terms[t].getOp2(), v);
int s1 = add_binary(TIMES, tmp2,
add_binary(TIMES, t,
add_unary(LOG, terms[t].getOp1())));
int s2 = add_binary(TIMES, tmp1,
add_binary(TIMES, terms[t].getOp2(),
add_binary(POWER, terms[t].getOp1(),
add_binary(MINUS, terms[t].getOp2(), one))));
res = add_binary(PLUS, s1, s2);
int s1 = add_binary(code_t::TIMES, tmp2,
add_binary(code_t::TIMES, t,
add_unary(code_t::LOG, terms[t].getOp1())));
int s2 = add_binary(code_t::TIMES, tmp1,
add_binary(code_t::TIMES, terms[t].getOp2(),
add_binary(code_t::POWER, terms[t].getOp1(),
add_binary(code_t::MINUS, terms[t].getOp2(), one))));
res = add_binary(code_t::PLUS, s1, s2);
break;
}
case NONE:
case code_t::NONE:
break;
}
@ -336,7 +327,7 @@ OperationTree::add_substitution(int t, const map<int, int> &subst,
// return substitution of t if it is in the map
auto it = subst.find(t);
if (subst.end() != it)
return (*it).second;
return it->second;
int nary = otree.terms[t].nary();
if (nary == 2)
@ -391,7 +382,7 @@ void
OperationTree::register_derivative(int t, int v, int tder)
{
// todo: might check that the insert inserts a new pair
derivatives[t].insert(_Tderivmap::value_type(v, tder));
derivatives[t].emplace(v, tder);
}
unordered_set<int>
@ -416,9 +407,7 @@ OperationTree::select_terms(int t, const opselector &sel, unordered_set<int> &su
select_terms(op.getOp2(), sel, subterms);
}
else if (op.nary() == 1)
{
select_terms(op.getOp1(), sel, subterms);
}
select_terms(op.getOp1(), sel, subterms);
}
unordered_set<int>
@ -473,23 +462,23 @@ OperationTree::forget_derivative_maps()
}
void
OperationTree::print_operation_tree(int t, FILE *fd, OperationFormatter &f) const
OperationTree::print_operation_tree(int t, std::ostream &os, OperationFormatter &f) const
{
f.format(terms[t], t, fd);
f.format(terms[t], t, os);
}
void
OperationTree::print_operation(int t) const
{
DefaultOperationFormatter dof(*this);
print_operation_tree(t, stdout, dof);
print_operation_tree(t, std::cout, dof);
}
void
OperationTree::update_nul_incidence_after_nularify(int t)
{
unordered_set<int> updated;
for (int tnode = num_constants; tnode < (int) terms.size(); tnode++)
for (int tnode = num_constants; tnode < static_cast<int>(terms.size()); tnode++)
{
const Operation &op = terms[tnode];
if (op.nary() == 2)
@ -535,12 +524,12 @@ OperationTree::update_nul_incidence_after_nularify(int t)
EvalTree::EvalTree(const OperationTree &ot, int last)
: otree(ot),
values(new double[(last == -1) ? ot.terms.size() : last+1]),
flags(new bool[(last == -1) ? ot.terms.size() : last+1]),
values(std::make_unique<double[]>((last == -1) ? ot.terms.size() : last+1)),
flags(std::make_unique<bool[]>((last == -1) ? ot.terms.size() : last+1)),
last_operation((last == -1) ? ot.terms.size()-1 : last)
{
if (last_operation < OperationTree::num_constants-1
|| last_operation > (int) ot.terms.size()-1)
|| last_operation > static_cast<int>(ot.terms.size())-1)
throw ogu::Exception(__FILE__, __LINE__,
"Wrong last in EvalTree constructor.");
@ -594,23 +583,23 @@ EvalTree::eval(int t)
{
double r1 = eval(op.getOp1());
double res;
if (op.getCode() == UMINUS)
if (op.getCode() == code_t::UMINUS)
res = -r1;
else if (op.getCode() == LOG)
else if (op.getCode() == code_t::LOG)
res = log(r1);
else if (op.getCode() == EXP)
else if (op.getCode() == code_t::EXP)
res = exp(r1);
else if (op.getCode() == SIN)
else if (op.getCode() == code_t::SIN)
res = sin(r1);
else if (op.getCode() == COS)
else if (op.getCode() == code_t::COS)
res = cos(r1);
else if (op.getCode() == TAN)
else if (op.getCode() == code_t::TAN)
res = tan(r1);
else if (op.getCode() == SQRT)
else if (op.getCode() == code_t::SQRT)
res = sqrt(r1);
else if (op.getCode() == ERF)
else if (op.getCode() == code_t::ERF)
res = erf(r1);
else if (op.getCode() == ERFC)
else if (op.getCode() == code_t::ERFC)
res = erfc(r1);
else
{
@ -624,19 +613,19 @@ EvalTree::eval(int t)
else if (op.nary() == 2)
{
double res;
if (op.getCode() == PLUS)
if (op.getCode() == code_t::PLUS)
{
double r1 = eval(op.getOp1());
double r2 = eval(op.getOp2());
res = r1 + r2;
}
else if (op.getCode() == MINUS)
else if (op.getCode() == code_t::MINUS)
{
double r1 = eval(op.getOp1());
double r2 = eval(op.getOp2());
res = r1 - r2;
}
else if (op.getCode() == TIMES)
else if (op.getCode() == code_t::TIMES)
{
// pickup less complex formula first
unsigned int nul1 = otree.nulary_of_term(op.getOp1()).size();
@ -664,7 +653,7 @@ EvalTree::eval(int t)
}
}
}
else if (op.getCode() == DIVIDE)
else if (op.getCode() == code_t::DIVIDE)
{
double r1 = eval(op.getOp1());
if (r1 == 0)
@ -675,7 +664,7 @@ EvalTree::eval(int t)
res = r1 / r2;
}
}
else if (op.getCode() == POWER)
else if (op.getCode() == code_t::POWER)
{
// suppose that more complex is the first op in average
double r2 = eval(op.getOp2());
@ -729,7 +718,7 @@ EvalTree::print() const
}
void
DefaultOperationFormatter::format(const Operation &op, int t, FILE *fd)
DefaultOperationFormatter::format(const Operation &op, int t, std::ostream &os)
{
// add to the stop_set
if (stop_set.end() == stop_set.find(t))
@ -745,68 +734,66 @@ DefaultOperationFormatter::format(const Operation &op, int t, FILE *fd)
int t2 = op.getOp2();
const Operation &op2 = otree.terms[t2];
if (op1.nary() > 0)
format(op1, t1, fd);
format(op1, t1, os);
if (op2.nary() > 0)
format(op2, t2, fd);
format(op2, t2, os);
}
if (op.nary() == 1)
{
int t1 = op.getOp1();
const Operation &op1 = otree.terms[t1];
if (op1.nary() > 0)
format(op1, t1, fd);
format(op1, t1, os);
}
// print 'term ='
format_term(t, fd);
fprintf(fd, " = ");
format_term(t, os);
os << " = ";
if (op.nary() == 0)
{
format_nulary(t, fd);
}
format_nulary(t, os);
else if (op.nary() == 1)
{
int t1 = op.getOp1();
const Operation &op1 = otree.terms[t1];
const char *opname = "unknown";
std::string opname = "unknown";
switch (op.getCode())
{
case UMINUS:
case code_t::UMINUS:
opname = "-";
break;
case LOG:
case code_t::LOG:
opname = "log";
break;
case EXP:
case code_t::EXP:
opname = "exp";
break;
case SIN:
case code_t::SIN:
opname = "sin";
break;
case COS:
case code_t::COS:
opname = "cos";
break;
case TAN:
case code_t::TAN:
opname = "tan";
break;
case SQRT:
case code_t::SQRT:
opname = "sqrt";
break;
case ERF:
case code_t::ERF:
opname = "erf";
break;
case ERFC:
case code_t::ERFC:
opname = "erfc";
break;
default:
break;
}
fprintf(fd, "%s(", opname);
os << opname << '(';
if (op1.nary() == 0)
format_nulary(t1, fd);
format_nulary(t1, os);
else
format_term(t1, fd);
fprintf(fd, ")");
format_term(t1, os);
os << ")";
}
else
{
@ -814,65 +801,64 @@ DefaultOperationFormatter::format(const Operation &op, int t, FILE *fd)
const Operation &op1 = otree.terms[t1];
int t2 = op.getOp2();
const Operation &op2 = otree.terms[t2];
const char *opname = "unknown";
std::string opname = "unknown";
switch (op.getCode())
{
case PLUS:
case code_t::PLUS:
opname = "+";
break;
case MINUS:
case code_t::MINUS:
opname = "-";
break;
case TIMES:
case code_t::TIMES:
opname = "*";
break;
case DIVIDE:
case code_t::DIVIDE:
opname = "/";
break;
case POWER:
case code_t::POWER:
opname = "^";
break;
default:
break;
}
if (op1.nary() == 0)
format_nulary(t1, fd);
format_nulary(t1, os);
else
format_term(t1, fd);
fprintf(fd, " %s ", opname);
format_term(t1, os);
os << ' ' << opname << ' ';
if (op2.nary() == 0)
format_nulary(t2, fd);
format_nulary(t2, os);
else
format_term(t2, fd);
format_term(t2, os);
}
print_delim(fd);
print_delim(os);
}
void
DefaultOperationFormatter::format_term(int t, FILE *fd) const
DefaultOperationFormatter::format_term(int t, std::ostream &os) const
{
fprintf(fd, "$%d", t);
os << '$' << t;
}
void
DefaultOperationFormatter::format_nulary(int t, FILE *fd) const
DefaultOperationFormatter::format_nulary(int t, std::ostream &os) const
{
if (t == OperationTree::zero)
fprintf(fd, "0");
os << '0';
else if (t == OperationTree::one)
fprintf(fd, "1");
os << '1';
else if (t == OperationTree::nan)
fprintf(fd, "NaN");
os << "NaN";
else
fprintf(fd, "$%d", t);
os << '$' << t;
}
void
DefaultOperationFormatter::print_delim(FILE *fd) const
DefaultOperationFormatter::print_delim(std::ostream &os) const
{
fprintf(fd, ";\n");
os << ";\n";
}
std::string
@ -907,31 +893,31 @@ OperationStringConvertor::convert(const Operation &op, int t) const
const char *opname = "unknown";
switch (op.getCode())
{
case UMINUS:
case code_t::UMINUS:
opname = "-";
break;
case LOG:
case code_t::LOG:
opname = "log";
break;
case EXP:
case code_t::EXP:
opname = "exp";
break;
case SIN:
case code_t::SIN:
opname = "sin";
break;
case COS:
case code_t::COS:
opname = "cos";
break;
case TAN:
case code_t::TAN:
opname = "tan";
break;
case SQRT:
case code_t::SQRT:
opname = "sqrt";
break;
case ERF:
case code_t::ERF:
opname = "erf";
break;
case ERFC:
case code_t::ERFC:
opname = "erfc";
break;
default:
@ -949,19 +935,19 @@ OperationStringConvertor::convert(const Operation &op, int t) const
const char *opname = "unknown";
switch (op.getCode())
{
case PLUS:
case code_t::PLUS:
opname = "+";
break;
case MINUS:
case code_t::MINUS:
opname = "-";
break;
case TIMES:
case code_t::TIMES:
opname = "*";
break;
case DIVIDE:
case code_t::DIVIDE:
opname = "/";
break;
case POWER:
case code_t::POWER:
opname = "^";
break;
default:
@ -970,15 +956,15 @@ OperationStringConvertor::convert(const Operation &op, int t) const
// decide about parenthesis
bool op1_par = true;
bool op2_par = true;
if (op.getCode() == PLUS)
if (op.getCode() == code_t::PLUS)
{
op1_par = false;
op2_par = false;
}
else if (op.getCode() == MINUS)
else if (op.getCode() == code_t::MINUS)
{
op1_par = false;
if (op2.getCode() != MINUS && op2.getCode() != PLUS)
if (op2.getCode() != code_t::MINUS && op2.getCode() != code_t::PLUS)
op2_par = false;
}
else

View File

@ -8,11 +8,11 @@
#include <map>
#include <unordered_map>
#include <unordered_set>
#include <cstdio>
#include <ostream>
#include <memory>
namespace ogp
{
using std::unordered_set;
using std::unordered_map;
using std::vector;
@ -24,15 +24,15 @@ namespace ogp
* codes, he should update the code of #OperationTree::add_unary,
* #OperationTree::add_binary, and of course
* #OperationTree::add_derivative. */
enum code_t {NONE, UMINUS, LOG, EXP, SIN, COS, TAN, SQRT, ERF,
ERFC, PLUS, MINUS, TIMES, DIVIDE, POWER};
enum class code_t {NONE, UMINUS, LOG, EXP, SIN, COS, TAN, SQRT, ERF,
ERFC, PLUS, MINUS, TIMES, DIVIDE, POWER};
/** Class representing a nulary, unary, or binary operation. */
class Operation
{
protected:
/** Code of the operation. */
code_t code{NONE};
code_t code{code_t::NONE};
/** First operand. If none, then it is -1. */
int op1{-1};
/** Second operand. If none, then it is -1. */
@ -50,18 +50,12 @@ namespace ogp
{
}
/** Constructs a nulary operation. */
Operation()
= default;
Operation() = default;
/** A copy constructor. */
Operation(const Operation &op)
= default;
Operation(const Operation &op) = default;
/** Operator =. */
Operation &
operator=(const Operation &op)
= default;
Operation &operator=(const Operation &op) = default;
/** Operator ==. */
bool
operator==(const Operation &op) const
@ -86,7 +80,7 @@ namespace ogp
size_t
hashval() const
{
return op2+1 + (op1+1)^15 + code^30;
return op2+1 + (op1+1)^15 + static_cast<int>(code)^30;
}
code_t
@ -104,7 +98,6 @@ namespace ogp
{
return op2;
}
};
/** This struct is a predicate for ordering of the operations in
@ -133,8 +126,7 @@ namespace ogp
struct opselector
{
virtual bool operator()(int t) const = 0;
virtual ~opselector()
= default;
virtual ~opselector() = default;
};
/** Forward declaration of OperationFormatter. */
@ -182,7 +174,6 @@ namespace ogp
/** This defines a type for a map mapping the unary and binary
* operations to their indices. */
using _Topmap = unordered_map<Operation, int, ophash>;
using _Topval = _Topmap::value_type;
/** This is the map mapping the unary and binary operations to
* the indices of the terms.*/
@ -205,25 +196,18 @@ namespace ogp
/** The tree index of the last nulary term. */
int last_nulary;
public:
/** This is a number of constants set in the following
* enum. This number reserves space in a vector of terms for
* the constants. */
static const int num_constants = 4;
/** Enumeration for special terms. We need zero, one, nan and
* 2/pi. These will be always first four terms having indices
* zero, one and two, three. If adding anything to this
* enumeration, make sure you have updated num_constants above.*/
enum {zero = 0, one = 1, nan = 2, two_over_pi = 3};
* enumeration, make sure num_constants remains the last one.*/
enum {zero, one, nan, two_over_pi, num_constants};
/** The unique constructor which initializes the object to
* contain only zero, one and nan and two_over_pi.*/
OperationTree();
/** Copy constructor. */
OperationTree(const OperationTree &ot)
= default;
OperationTree(const OperationTree &ot) = default;
/** Add a nulary operation. The caller is responsible for not
* inserting two semantically equivalent nulary operations.
@ -323,7 +307,7 @@ namespace ogp
/** This outputs the operation to the given file descriptor
* using the given OperationFormatter. */
void print_operation_tree(int t, FILE *fd, OperationFormatter &f) const;
void print_operation_tree(int t, std::ostream &os, OperationFormatter &f) const;
/** Debug print of a given operation: */
void print_operation(int t) const;
@ -339,7 +323,7 @@ namespace ogp
int
get_num_op() const
{
return (int) (terms.size());
return static_cast<int>(terms.size());
}
private:
/** This registers a calculated derivative of the term in the
@ -391,9 +375,9 @@ namespace ogp
* are done. */
const OperationTree &otree;
/** The array of values. */
double *const values;
const std::unique_ptr<double[]> values;
/** The array of evaluation flags. */
bool *const flags;
const std::unique_ptr<bool[]> flags;
/** The index of last operation in the EvalTree. Length of
* values and flags will be then last_operation+1. */
int last_operation;
@ -404,10 +388,7 @@ namespace ogp
* (included). */
EvalTree(const OperationTree &otree, int last = -1);
EvalTree(const EvalTree &) = delete;
virtual ~EvalTree()
{
delete [] values; delete [] flags;
}
virtual ~EvalTree() = default;
/** Set evaluation flag to all terms (besides the first
* special terms) to false. */
void reset_all();
@ -431,8 +412,7 @@ namespace ogp
{
public:
/** Empty virtual destructor. */
virtual ~OperationFormatter()
= default;
virtual ~OperationFormatter() = default;
/** Print the formatted operation op with a given tree index t
* to a given descriptor. (See class OperationTree to know
* what is a tree index.) This prints all the tree. This
@ -441,7 +421,7 @@ namespace ogp
* term, the right hand side is a string representation of the
* operation (which will refer to other string representation
* of subterms). */
virtual void format(const Operation &op, int t, FILE *fd) = 0;
virtual void format(const Operation &op, int t, std::ostream &os) = 0;
};
/** The default formatter formats the formulas with a usual syntax
@ -460,23 +440,22 @@ namespace ogp
{
}
/** Format the operation with the default syntax. */
void format(const Operation &op, int t, FILE *fd) override;
void format(const Operation &op, int t, std::ostream &os) override;
/** This prints a string represenation of the given term, for
* example 'tmp10' for term 10. In this implementation it
* prints $10. */
virtual void format_term(int t, FILE *fd) const;
virtual void format_term(int t, std::ostream &os) const;
/** Print a string representation of the nulary term. */
virtual void format_nulary(int t, FILE *fd) const;
virtual void format_nulary(int t, std::ostream &os) const;
/** Print a delimiter between two statements. By default it is
* "\n". */
virtual void print_delim(FILE *fd) const;
virtual void print_delim(std::ostream &os) const;
};
class NularyStringConvertor
{
public:
virtual ~NularyStringConvertor()
= default;
virtual ~NularyStringConvertor() = default;
/** Return the string representation of the atom with the tree
* index t. */
virtual std::string convert(int t) const = 0;
@ -494,8 +473,7 @@ namespace ogp
{
}
/** Empty virtual destructor. */
virtual ~OperationStringConvertor()
= default;
virtual ~OperationStringConvertor() = default;
/** Convert the operation to the string mathematical
* representation. This does not write any equation, just
* returns a string representation of the formula. */

View File

@ -14,6 +14,9 @@
#include <cmath>
#include <climits>
#include <ostream>
#include <memory>
#include <algorithm>
#include <iomanip>
using namespace ogdyn;
@ -117,7 +120,7 @@ DynareModel::print() const
{
int tf = eqs.formula(i);
printf("formula %d:\n", tf);
eqs.getTree().print_operation_tree(tf, stdout, dof);
eqs.getTree().print_operation_tree(tf, std::cout, dof);
}
}
@ -588,43 +591,40 @@ extern ogp::location_type dynglob_lloc;
void
DynareParser::parse_glob(int length, const char *stream)
{
auto *buffer = new char[length+2];
strncpy(buffer, stream, length);
auto buffer = std::make_unique<char[]>(length+2);
std::copy_n(stream, length, buffer.get());
buffer[length] = '\0';
buffer[length+1] = '\0';
void *p = dynglob__scan_buffer(buffer, (unsigned int) length+2);
void *p = dynglob__scan_buffer(buffer.get(), static_cast<unsigned int>(length)+2);
dynare_parser = this;
dynglob_parse();
delete [] buffer;
dynglob__destroy_buffer(p);
}
int
DynareParser::parse_order(int len, const char *str)
{
auto *buf = new char[len+1];
strncpy(buf, str, len);
auto buf = std::make_unique<char[]>(len+1);
std::copy_n(str, len, buf.get());
buf[len] = '\0';
int res;
sscanf(buf, "%d", &res);
delete [] buf;
sscanf(buf.get(), "%d", &res);
return res;
}
int
DynareParser::parse_pldiscount(int len, const char *str)
{
auto *buf = new char[len+1];
strncpy(buf, str, len);
auto buf = std::make_unique<char[]>(len+1);
std::copy_n(str, len, buf.get());
buf[len] = '\0';
if (!atoms.is_type(buf, DynareDynamicAtoms::param))
throw ogp::ParserException(std::string("Name ") + buf + " is not a parameter", 0);
if (!atoms.is_type(buf.get(), DynareDynamicAtoms::param))
throw ogp::ParserException(std::string("Name ") + buf.get() + " is not a parameter", 0);
int t = atoms.index(buf, 0);
int t = atoms.index(buf.get(), 0);
if (t == -1)
t = eqs.add_nulary(buf);
t = eqs.add_nulary(buf.get());
delete [] buf;
return t;
}
@ -712,14 +712,14 @@ NLSelector::operator()(int t) const
}
else if (nary == 1)
{
if (op.getCode() == ogp::UMINUS)
if (op.getCode() == ogp::code_t::UMINUS)
return false;
else
return true;
}
else
{
if (op.getCode() == ogp::TIMES)
if (op.getCode() == ogp::code_t::TIMES)
// if at least one operand is constant, than the TIMES is linear
if (model.is_constant_term(op.getOp1())
|| model.is_constant_term(op.getOp2()))
@ -727,11 +727,11 @@ NLSelector::operator()(int t) const
else
return true;
// both PLUS and MINUS are linear
if (op.getCode() == ogp::PLUS
|| op.getCode() == ogp::MINUS)
if (op.getCode() == ogp::code_t::PLUS
|| op.getCode() == ogp::code_t::MINUS)
return false;
// POWER is linear if exponent or base is 0 or one
if (op.getCode() == ogp::POWER
if (op.getCode() == ogp::code_t::POWER
&& (op.getOp1() == ogp::OperationTree::zero
|| op.getOp1() == ogp::OperationTree::one
|| op.getOp2() == ogp::OperationTree::zero
@ -741,7 +741,7 @@ NLSelector::operator()(int t) const
return true;
// DIVIDE is linear if the denominator is constant, or if
// the nominator is zero
if (op.getCode() == ogp::DIVIDE
if (op.getCode() == ogp::code_t::DIVIDE
&& (op.getOp1() == ogp::OperationTree::zero
|| model.is_constant_term(op.getOp2())))
return false;
@ -792,23 +792,23 @@ DynareSPModel::DynareSPModel(const char **endo, int num_endo,
}
void
ModelSSWriter::write_der0(FILE *fd)
ModelSSWriter::write_der0(std::ostream &os)
{
write_der0_preamble(fd);
write_atom_assignment(fd);
write_der0_preamble(os);
write_atom_assignment(os);
stop_set.clear();
for (int fi = 0; fi < model.eqs.nformulas(); fi++)
otree.print_operation_tree(model.eqs.formula(fi), fd, *this);
otree.print_operation_tree(model.eqs.formula(fi), os, *this);
write_der0_assignment(fd);
write_der0_assignment(os);
}
void
ModelSSWriter::write_der1(FILE *fd)
ModelSSWriter::write_der1(std::ostream &os)
{
write_der1_preamble(fd);
write_atom_assignment(fd);
write_der1_preamble(os);
write_atom_assignment(os);
stop_set.clear();
@ -821,11 +821,11 @@ ModelSSWriter::write_der1(FILE *fd)
{
int t = fder.derivative(ogp::FoldMultiIndex(variables.size(), 1, j));
if (t > 0)
otree.print_operation_tree(t, fd, *this);
otree.print_operation_tree(t, os, *this);
}
}
write_der1_assignment(fd);
write_der1_assignment(os);
}
MatlabSSWriter::MatlabSSWriter(const DynareModel &dm, const char *idd)
@ -835,115 +835,102 @@ MatlabSSWriter::MatlabSSWriter(const DynareModel &dm, const char *idd)
}
void
MatlabSSWriter::write_der0_preamble(FILE *fd) const
MatlabSSWriter::write_der0_preamble(std::ostream &os) const
{
fprintf(fd,
"%% Usage:\n"
"%% out = %s_f(params, y)\n"
"%% where\n"
"%% out is a (%d,1) column vector of the residuals\n"
"%% of the static system\n",
id, model.getAtoms().ny());
write_common1_preamble(fd);
fprintf(fd,
"function out = %s_f(params, y)\n", id);
write_common2_preamble(fd);
os << "% Usage:\n"
<< "% out = " << id << "_f(params, y)\n"
<< "% where\n"
<< "% out is a (" << model.getAtoms().ny() << ",1) column vector of the residuals\n"
<< "% of the static system\n";
write_common1_preamble(os);
os << "function out = " << id << "_f(params, y)\n";
write_common2_preamble(os);
}
void
MatlabSSWriter::write_der1_preamble(FILE *fd) const
MatlabSSWriter::write_der1_preamble(std::ostream &os) const
{
fprintf(fd,
"%% Usage:\n"
"%% out = %s_ff(params, y)\n"
"%% where\n"
"%% out is a (%d,%d) matrix of the first order\n"
"%% derivatives of the static system residuals\n"
"%% columns correspond to endo variables in\n"
"%% the ordering as declared\n",
id, model.getAtoms().ny(), model.getAtoms().ny());
write_common1_preamble(fd);
fprintf(fd,
"function out = %s_ff(params, y)\n", id);
write_common2_preamble(fd);
os << "% Usage:\n"
<< "% out = " << id << "_ff(params, y)\n"
<< "% where\n"
<< "% out is a (" << model.getAtoms().ny() << "," << model.getAtoms().ny() << ") matrix of the first order\n"
<< "% derivatives of the static system residuals\n"
<< "% columns correspond to endo variables in\n"
<< "% the ordering as declared\n";
write_common1_preamble(os);
os << "function out = " << id << "_ff(params, y)\n";
write_common2_preamble(os);
}
void
MatlabSSWriter::write_common1_preamble(FILE *fd) const
MatlabSSWriter::write_common1_preamble(std::ostream &os) const
{
fprintf(fd,
"%% params is a (%d,1) vector of parameter values\n"
"%% in the ordering as declared\n"
"%% y is a (%d,1) vector of endogenous variables\n"
"%% in the ordering as declared\n"
"%%\n"
"%% Created by Dynare++ v. %s\n", model.getAtoms().np(),
model.getAtoms().ny(), DYNVERSION);
os << "% params is a (" << model.getAtoms().np() << ",1) vector of parameter values\n"
<< "% in the ordering as declared\n"
<< "% y is a (" << model.getAtoms().ny() << ",1) vector of endogenous variables\n"
<< "% in the ordering as declared\n"
<< "%\n"
<< "% Created by Dynare++ v. " << DYNVERSION << "\n";
// write ordering of parameters
fprintf(fd, "\n%% params ordering\n%% =====================\n");
os << "\n% params ordering\n% =====================\n";
for (auto parname : model.getAtoms().get_params())
{
fprintf(fd, "%% %s\n", parname);
}
os << "% " << parname << "\n";
// write endogenous variables
fprintf(fd, "%%\n%% y ordering\n%% =====================\n");
os << "%\n% y ordering\n% =====================\n";
for (auto endoname : model.getAtoms().get_endovars())
{
fprintf(fd, "%% %s\n", endoname);
}
fprintf(fd, "\n");
os << "% " << endoname << "\n";
os << "\n";
}
void
MatlabSSWriter::write_common2_preamble(FILE *fd) const
MatlabSSWriter::write_common2_preamble(std::ostream &os) const
{
fprintf(fd, "if size(y) ~= [%d,1]\n\terror('Wrong size of y, must be [%d,1]');\nend\n",
model.getAtoms().ny(), model.getAtoms().ny());
fprintf(fd, "if size(params) ~= [%d,1]\n\terror('Wrong size of params, must be [%d,1]');\nend\n\n",
model.getAtoms().np(), model.getAtoms().np());
os << "if size(y) ~= [" << model.getAtoms().ny() << ",1]\n"
<< "\terror('Wrong size of y, must be [" << model.getAtoms().ny() << ",1]');\nend\n"
<< "if size(params) ~= [" << model.getAtoms().np() << ",1]\n"
<< "\terror('Wrong size of params, must be [" << model.getAtoms().np() << ",1]');\nend\n\n";
}
void
MatlabSSWriter::write_atom_assignment(FILE *fd) const
MatlabSSWriter::write_atom_assignment(std::ostream &os) const
{
// write OperationTree::num_constants
fprintf(fd, "%% hardwired constants\n");
os << "% hardwired constants\n";
ogp::EvalTree etree(model.getParser().getTree(), ogp::OperationTree::num_constants-1);
for (int i = 0; i < ogp::OperationTree::num_constants; i++)
{
format_nulary(i, fd);
format_nulary(i, os);
double g = etree.eval(i);
if (std::isnan(g))
fprintf(fd, " = NaN;\n");
os << " = NaN;\n";
else
fprintf(fd, " = %12.8g;\n", etree.eval(i));
os << " = " << std::defaultfloat << std::setprecision(8) << etree.eval(i) << ";\n";
}
// write numerical constants
fprintf(fd, "%% numerical constants\n");
os << "% numerical constants\n";
const ogp::Constants::Tconstantmap &cmap = model.getAtoms().get_constantmap();
for (auto it : cmap)
{
format_nulary(it.first, fd);
fprintf(fd, " = %12.8g;\n", it.second);
format_nulary(it.first, os);
os << " = " << std::defaultfloat << std::setprecision(8) << it.second << ";\n";
}
// write parameters
fprintf(fd, "%% parameter values\n");
os << "% parameter values\n";
for (unsigned int ip = 0; ip < model.getAtoms().get_params().size(); ip++)
{
const char *parname = model.getAtoms().get_params()[ip];
int t = model.getAtoms().index(parname, 0);
if (t == -1)
{
fprintf(fd, "%% %s not used in the model\n", parname);
}
os << "% " << parname << " not used in the model\n";
else
{
format_nulary(t, fd);
fprintf(fd, " = params(%d); %% %s\n", ip+1, parname);
format_nulary(t, os);
os << " = params(" << ip+1 << "); % " << parname << "\n";
}
}
// write exogenous variables
fprintf(fd, "%% exogenous variables to zeros\n");
os << "% exogenous variables to zeros\n";
for (unsigned int ie = 0; ie < model.getAtoms().get_exovars().size(); ie++)
{
const char *exoname = model.getAtoms().get_exovars()[ie];
@ -952,8 +939,8 @@ MatlabSSWriter::write_atom_assignment(FILE *fd) const
const ogp::DynamicAtoms::Tlagmap &lmap = model.getAtoms().lagmap(exoname);
for (auto it : lmap)
{
format_nulary(it.second, fd);
fprintf(fd, " = 0.0; %% %s\n", exoname);
format_nulary(it.second, os);
os << " = 0.0; % " << exoname << "\n";
}
}
catch (const ogu::Exception &e)
@ -962,43 +949,43 @@ MatlabSSWriter::write_atom_assignment(FILE *fd) const
}
}
// write endogenous variables
fprintf(fd, "%% endogenous variables to y\n");
os << "% endogenous variables to y\n";
for (unsigned int ie = 0; ie < model.getAtoms().get_endovars().size(); ie++)
{
const char *endoname = model.getAtoms().get_endovars()[ie];
const ogp::DynamicAtoms::Tlagmap &lmap = model.getAtoms().lagmap(endoname);
for (auto it : lmap)
{
format_nulary(it.second, fd);
fprintf(fd, " = y(%d); %% %s\n", ie+1, endoname);
format_nulary(it.second, os);
os << " = y(" << ie+1 << "); % " << endoname << "\n";
}
}
fprintf(fd, "\n");
os << "\n";
}
void
MatlabSSWriter::write_der0_assignment(FILE *fd) const
MatlabSSWriter::write_der0_assignment(std::ostream &os) const
{
// initialize out variable
fprintf(fd, "%% setting the output variable\n");
fprintf(fd, "out = zeros(%d, 1);\n", model.getParser().nformulas());
os << "% setting the output variable\n"
<< "out = zeros(" << model.getParser().nformulas() << ", 1);\n";
// fill out with the terms
for (int i = 0; i < model.getParser().nformulas(); i++)
{
fprintf(fd, "out(%d) = ", i+1);
format_term(model.getParser().formula(i), fd);
fprintf(fd, ";\n");
os << "out(" << i+1 << ") = ";
format_term(model.getParser().formula(i), os);
os << ";\n";
}
}
void
MatlabSSWriter::write_der1_assignment(FILE *fd) const
MatlabSSWriter::write_der1_assignment(std::ostream &os) const
{
// initialize out variable
fprintf(fd, "%% setting the output variable\n");
fprintf(fd, "out = zeros(%d, %d);\n", model.getParser().nformulas(), model.getAtoms().ny());
os << "% setting the output variable\n";
os << "out = zeros(" << model.getParser().nformulas() << ", " << model.getAtoms().ny() << ");\n";
// fill out with the terms
const vector<int> &variables = model.getAtoms().variables();
@ -1014,48 +1001,48 @@ MatlabSSWriter::write_der1_assignment(FILE *fd) const
int t = fder.derivative(ogp::FoldMultiIndex(variables.size(), 1, j));
if (t != ogp::OperationTree::zero)
{
fprintf(fd, "out(%d,%d) = out(%d,%d) + ", i+1, yi+1, i+1, yi+1);
format_term(t, fd);
fprintf(fd, "; %% %s(%d)\n", name, model.getAtoms().lead(tvar));
os << "out(" << i+1 << "," << yi+1 << ") = out("<< i+1 << "," << yi+1 << ") + ";
format_term(t, os);
os << "; % " << name << "(" << model.getAtoms().lead(tvar) << ")\n";
}
}
}
}
void
MatlabSSWriter::format_term(int t, FILE *fd) const
MatlabSSWriter::format_term(int t, std::ostream &os) const
{
fprintf(fd, "t%d", t);
os << 't' << t;
}
void
MatlabSSWriter::format_nulary(int t, FILE *fd) const
MatlabSSWriter::format_nulary(int t, std::ostream &os) const
{
fprintf(fd, "a%d", t);
os << 'a' << t;
}
void
DebugOperationFormatter::format_nulary(int t, FILE *fd) const
DebugOperationFormatter::format_nulary(int t, std::ostream &os) const
{
const DynareDynamicAtoms &a = model.getAtoms();
if (t == ogp::OperationTree::zero)
fprintf(fd, "0");
os << '0';
else if (t == ogp::OperationTree::one)
fprintf(fd, "1");
os << '1';
else if (t == ogp::OperationTree::nan)
fprintf(fd, "NaN");
os << "NaN";
else if (t == ogp::OperationTree::two_over_pi)
fprintf(fd, "2/sqrt(PI)");
os << "2/sqrt(PI)";
else if (a.is_constant(t))
fprintf(fd, "%g", a.get_constant_value(t));
os << a.get_constant_value(t);
else
{
int ll = a.lead(t);
const char *name = a.name(t);
std::string name{a.name(t)};
if (ll == 0)
fprintf(fd, "%s", name);
os << name;
else
fprintf(fd, "%s(%d)", name, ll);
os << name << '(' << ll << ')';
}
}

View File

@ -14,6 +14,7 @@
#include <map>
#include <unordered_set>
#include <ostream>
namespace ogdyn
{
@ -405,18 +406,18 @@ namespace ogdyn
* virtual methods for writing a preamble, then assignment of
* atoms, and then assignment for resulting object. These are
* language dependent and are implemented in the subclass. */
void write_der0(FILE *fd);
void write_der0(std::ostream &os);
/** This writes the evaluation of the first order derivative of
the system. It calls pure virtual methods for writing a
preamble, assignment, and assignemnt of the resulting
objects. */
void write_der1(FILE *fd);
void write_der1(std::ostream &os);
protected:
virtual void write_der0_preamble(FILE *fd) const = 0;
virtual void write_der1_preamble(FILE *fd) const = 0;
virtual void write_atom_assignment(FILE *fd) const = 0;
virtual void write_der0_assignment(FILE *fd) const = 0;
virtual void write_der1_assignment(FILE *fd) const = 0;
virtual void write_der0_preamble(std::ostream &os) const = 0;
virtual void write_der1_preamble(std::ostream &os) const = 0;
virtual void write_atom_assignment(std::ostream &os) const = 0;
virtual void write_der0_assignment(std::ostream &os) const = 0;
virtual void write_der1_assignment(std::ostream &os) const = 0;
};
class MatlabSSWriter : public ModelSSWriter
@ -432,24 +433,24 @@ namespace ogdyn
}
protected:
// from ModelSSWriter
void write_der0_preamble(FILE *fd) const override;
void write_der1_preamble(FILE *fd) const override;
void write_der0_preamble(std::ostream &os) const override;
void write_der1_preamble(std::ostream &os) const override;
/** This writes atom assignments. We have four kinds of atoms
* set here: endogenous vars coming from one parameter,
* parameter values given by the second parameter, constants,
* and the OperationTree::num_constants hardwired constants in
* ogp::OperationTree. */
void write_atom_assignment(FILE *fd) const override;
void write_der0_assignment(FILE *fd) const override;
void write_der1_assignment(FILE *fd) const override;
void write_atom_assignment(std::ostream &os) const override;
void write_der0_assignment(std::ostream &os) const override;
void write_der1_assignment(std::ostream &os) const override;
/** This prints t10 for t=10. */
void format_term(int t, FILE *fd) const override;
void format_term(int t, std::ostream &os) const override;
/** This prints a10 for t=10. The atoms a10 are supposed to be
* set by write_atom_assignments(). */
void format_nulary(int t, FILE *fd) const override;
void format_nulary(int t, std::ostream &os) const override;
private:
void write_common1_preamble(FILE *fd) const;
void write_common2_preamble(FILE *fd) const;
void write_common1_preamble(std::ostream &os) const;
void write_common2_preamble(std::ostream &os) const;
};
/** This class implements OperationFormatter for debugging
@ -465,7 +466,7 @@ namespace ogdyn
model(m)
{
}
void format_nulary(int t, FILE *fd) const override;
void format_nulary(int t, std::ostream &os) const override;
};
};

View File

@ -63,7 +63,7 @@ ForwSubstBuilder::substitute_for_term(int t, int i, int j)
info.num_aux_variables++;
const char *ss = model.atoms.get_name_storage().query(name);
int auxt = model.eqs.add_nulary(name);
model.eqs.add_formula(model.eqs.add_binary(ogp::MINUS, auxt, lagt));
model.eqs.add_formula(model.eqs.add_binary(ogp::code_t::MINUS, auxt, lagt));
aux_map.insert(Tsubstmap::value_type(ss, lagt));
// now add variables and equations
// AUXLD_*_*_2 = AUXLD_*_*_1(+1) through
@ -80,7 +80,7 @@ ForwSubstBuilder::substitute_for_term(int t, int i, int j)
ss = model.atoms.get_name_storage().query(name);
auxt = model.eqs.add_nulary(name);
// add AUXLD_*_*_{ll+1} = AUXLD_*_*_{ll}(+1)
model.eqs.add_formula(model.eqs.add_binary(ogp::MINUS, auxt, lastauxt_lead));
model.eqs.add_formula(model.eqs.add_binary(ogp::code_t::MINUS, auxt, lastauxt_lead));
// add substitution to the map; todo: this
// works well because in the context where
// aux_map is used the timing doesn't matter,

View File

@ -11,6 +11,8 @@
#include "../kord/global_check.hh"
#include "../kord/approximation.hh"
#include <fstream>
int
main(int argc, char **argv)
{
@ -51,28 +53,29 @@ main(int argc, char **argv)
irf_list_ind = ((const DynareNameList &) dynare.getExogNames()).selectIndices(params.irf_list);
// write matlab files
FILE *mfd;
std::string mfile1(params.basename);
mfile1 += "_f.m";
if (nullptr == (mfd = fopen(mfile1.c_str(), "w")))
std::ofstream mfd{mfile1, std::ios::out | std::ios::trunc};
if (mfd.fail())
{
fprintf(stderr, "Couldn't open %s for writing.\n", mfile1.c_str());
exit(1);
}
ogdyn::MatlabSSWriter writer0(dynare.getModel(), params.basename.c_str());
writer0.write_der0(mfd);
fclose(mfd);
mfd.close();
std::string mfile2(params.basename);
mfile2 += "_ff.m";
if (nullptr == (mfd = fopen(mfile2.c_str(), "w")))
mfd.open(mfile2, std::ios::out | std::ios::trunc);
if (mfd.fail())
{
fprintf(stderr, "Couldn't open %s for writing.\n", mfile2.c_str());
exit(1);
}
ogdyn::MatlabSSWriter writer1(dynare.getModel(), params.basename.c_str());
writer1.write_der1(mfd);
fclose(mfd);
mfd.close();
// open mat file
std::string matfile(params.basename);
@ -206,7 +209,7 @@ main(int argc, char **argv)
}
catch (const ogp::ParserException &e)
{
printf("Caught parser exception: %s\n", e.message());
std::cout << "Caught parser exception: " << e.message() << std::endl;
return 255;
}

View File

@ -188,11 +188,11 @@ PlannerBuilder::beta_multiply_b()
{
int beta_pow = ogp::OperationTree::one;
for (int ll = 0; ll >= minlag; ll--,
beta_pow = model.eqs.add_binary(ogp::TIMES, beta_pow, tbeta))
beta_pow = model.eqs.add_binary(ogp::code_t::TIMES, beta_pow, tbeta))
for (int yi = 0; yi < diff_b.nrows(); yi++)
if (diff_b(yi, ll-minlag) != ogp::OperationTree::zero)
diff_b(yi, ll-minlag)
= model.eqs.add_binary(ogp::TIMES, beta_pow, diff_b(yi, ll-minlag));
= model.eqs.add_binary(ogp::code_t::TIMES, beta_pow, diff_b(yi, ll-minlag));
}
void
@ -200,21 +200,21 @@ PlannerBuilder::beta_multiply_f()
{
int beta_pow = ogp::OperationTree::one;
for (int ll = 0; ll <= maxlead; ll++,
beta_pow = model.eqs.add_binary(ogp::DIVIDE, beta_pow, tbeta))
beta_pow = model.eqs.add_binary(ogp::code_t::DIVIDE, beta_pow, tbeta))
for (int yi = 0; yi < diff_f.dim1(); yi++)
for (int fi = 0; fi < diff_f.dim2(); fi++)
if (diff_f(yi, fi, ll-minlag) != ogp::OperationTree::zero)
diff_f(yi, fi, ll-minlag)
= model.eqs.add_binary(ogp::TIMES, beta_pow, diff_f(yi, fi, ll-minlag));
= model.eqs.add_binary(ogp::code_t::TIMES, beta_pow, diff_f(yi, fi, ll-minlag));
beta_pow = ogp::OperationTree::one;
for (int ll = 0; ll >= minlag; ll--,
beta_pow = model.eqs.add_binary(ogp::TIMES, beta_pow, tbeta))
beta_pow = model.eqs.add_binary(ogp::code_t::TIMES, beta_pow, tbeta))
for (int yi = 0; yi < diff_f.dim1(); yi++)
for (int fi = 0; fi < diff_f.dim2(); fi++)
if (diff_f(yi, fi, ll-minlag) != ogp::OperationTree::zero)
diff_f(yi, fi, ll-minlag)
= model.eqs.add_binary(ogp::TIMES, beta_pow, diff_f(yi, fi, ll-minlag));
= model.eqs.add_binary(ogp::code_t::TIMES, beta_pow, diff_f(yi, fi, ll-minlag));
}
void
@ -271,7 +271,7 @@ PlannerBuilder::lagrange_mult_f()
sprintf(mult_name, "MULT%d(%d)", fset[fi], -ll);
int tm = model.eqs.add_nulary(mult_name);
diff_f(yi, fi, ll-minlag)
= model.eqs.add_binary(ogp::TIMES, tm, diff_f(yi, fi, ll-minlag));
= model.eqs.add_binary(ogp::code_t::TIMES, tm, diff_f(yi, fi, ll-minlag));
}
}
@ -283,10 +283,10 @@ PlannerBuilder::form_equations()
{
int eq = ogp::OperationTree::zero;
for (int ll = minlag; ll <= 0; ll++)
eq = model.eqs.add_binary(ogp::PLUS, eq, diff_b(yi, ll-minlag));
eq = model.eqs.add_binary(ogp::code_t::PLUS, eq, diff_b(yi, ll-minlag));
for (int fi = 0; fi < diff_f.dim2(); fi++)
for (int ll = minlag; ll <= maxlead; ll++)
eq = model.eqs.add_binary(ogp::PLUS, eq, diff_f(yi, fi, ll-minlag));
eq = model.eqs.add_binary(ogp::code_t::PLUS, eq, diff_f(yi, fi, ll-minlag));
model.eqs.add_formula(eq);
}
@ -295,7 +295,7 @@ PlannerBuilder::form_equations()
it != aux_map.end(); ++it)
{
int t = model.atoms.index((*it).first, 0);
model.eqs.add_formula(model.eqs.add_binary(ogp::MINUS, t, (*it).second));
model.eqs.add_formula(model.eqs.add_binary(ogp::code_t::MINUS, t, (*it).second));
}
}