diff --git a/dynare++/extern/R/Makefile b/dynare++/extern/R/Makefile index 4501ebdb56cf0cab337bb10f2b27fb482f8e16eb..92097b79b3d67e28b2848dafb940859834bd322a 100644 --- a/dynare++/extern/R/Makefile +++ b/dynare++/extern/R/Makefile @@ -1,37 +1,28 @@ RINTERNALS=/usr/share/R/include/ -sylvcppsource := $(wildcard ../../sylv/cc/*.cpp) -sylvhsource := $(wildcard ../../sylv/cc/*.h) -sylvobjects := $(patsubst %.cpp, %.o, $(sylvcppsource)) - -tlcwebsource := $(wildcard ../../tl/cc/*.cweb) -tlcppsource := $(patsubst %.cweb,%.cpp,$(tlcwebsource)) -tlhwebsource := $(wildcard ../../tl/cc/*.hweb) -tlhsource := $(patsubst %.hweb,%.h,$(tlhwebsource)) -tlobjects := $(patsubst %.cweb,%.o,$(tlcwebsource)) - -kordcwebsource := $(wildcard ../../kord/*.cweb) -kordcppsource := $(patsubst %.cweb,%.cpp,$(kordcwebsource)) -kordhwebsource := $(wildcard ../../kord/*.hweb) -kordhsource := $(patsubst %.hweb,%.h,$(kordhwebsource)) -kordobjects := $(patsubst %.cweb,%.o,$(kordcwebsource)) - -integcwebsource := $(wildcard ../../integ/cc/*.cweb) -integcppsource := $(patsubst %.cweb,%.cpp,$(integcwebsource)) -integhwebsource := $(wildcard ../../integ/cc/*.hweb) -integhsource := $(patsubst %.hweb,%.h,$(integhwebsource)) -integobjects := $(patsubst %.cweb,%.o,$(integcwebsource)) - -parserhsource := $(wildcard ../../parser/cc/*.h) -parsercppsource := $(wildcard ../parser/cc/*.cpp) - -utilshsource := $(wildcard ../../utils/cc/*.h) -utilscppsource := $(wildcard ../utils/cc/*.cpp) - -srccpp := dynare3.cpp dynare_model.cpp planner_builder.cpp dynare_atoms.cpp dynare_params.cpp nlsolve.cpp -objects := $(patsubst %.cpp,../../src/%.o,$(srccpp)) \ -$(patsubst %.y,%_ll.o,$(wildcard ../../src/*.y)) \ -$(patsubst %.lex,%_tab.o,$(wildcard ../../src/*.lex)) +sylvcppsource := $(wildcard ../../sylv/cc/*.cc) +sylvhsource := $(wildcard ../../sylv/cc/*.hh) +sylvobjects := $(patsubst %.cc, %.o, $(sylvcppsource)) + +tlcppsource := $(wildcard ../../tl/cc/*.cc) +tlhsource := $(wildcard ../../tl/cc/*.hh) + +kordcppsource := $(wildcard ../../kord/*.cc) +kordhsource := $(wildcard ../../kord/*.hh) + +integcppsource := $(wildcard ../../integ/cc/*.cc) +integhsource := $(wildcard ../../integ/cc/*.hh) + +parserhsource := $(wildcard ../../parser/cc/*.hh) +parsercppsource := $(wildcard ../parser/cc/*.cc) + +utilshsource := $(wildcard ../../utils/cc/*.hh) +utilscppsource := $(wildcard ../utils/cc/*.cc) + +srccpp := dynare3.cc dynare_model.cc planner_builder.cc dynare_atoms.cc dynare_params.cc nlsolve.cc +objects := $(patsubst %.cc,../../src/%.o,$(srccpp)) \ +$(patsubst %.yy,%_ll.o,$(wildcard ../../src/*.yy)) \ +$(patsubst %.ll,%_tab.o,$(wildcard ../../src/*.ll)) PKG_CPPFLAGS= -I../../tl/cc -I../../sylv/cc -I../../kord -I../../src -I../.. -I$(RINTERNALS) PKG_LIBS= ${LAPACK_LIBS} ${BLAS_LIBS} $(objects) $(kordobjects) $(integobjects) $(tlobjects) ../../parser/cc/parser.a ../../utils/cc/utils.a $(sylvobjects) -lpthread -llapack -lcblas -lf77blas -latlas -lg2c -lstdc++ @@ -43,12 +34,12 @@ endif dynareR.so: dynareR.o g++ -shared -o dynareR.so dynareR.o -L/usr/lib/R/lib -lR $(PKG_LIBS) -dynareR.o: dynareR.cpp +dynareR.o: dynareR.cc g++ -I/usr/share/R/include -I/usr/share/R/include $(PKG_CPPFLAGS) \ - -fpic -g -O2 -c dynareR.cpp -o dynareR.o -DDEBUG + -fpic -g -O2 -c dynareR.cc -o dynareR.o -DDEBUG -test: test.cpp dynareR.cpp - g++ -O0 -g -o test test.cpp -DDEBUG $(PKG_LIBS) $(PKG_CPPFLAGS) +test: test.cc dynareR.cc + g++ -O0 -g -o test test.cc -DDEBUG $(PKG_LIBS) $(PKG_CPPFLAGS) test-debug: valgrind --leak-check=yes ./test diff --git a/dynare++/extern/R/dynareR.cc b/dynare++/extern/R/dynareR.cc new file mode 100644 index 0000000000000000000000000000000000000000..4aef455cfa9956cdd61670c86f8cc298e8a591e1 --- /dev/null +++ b/dynare++/extern/R/dynareR.cc @@ -0,0 +1,271 @@ +// $Id: dynareR.cpp 862 2006-08-04 17:34:56Z tamas $ + +// Copyright 2006, Tamas K Papp + +#include "dynare3.hh" // Dynare class +#include "approximation.hh" // Approximation class + +// exceptions +#include "dynare_exception.hh" +#include "parser/cc/parser_exception.hh" +#include "utils/cc/exception.hh" +#include "SylvException.hh" +#include "tl_exception.hh" +#include "kord_exception.hh" + +#include <algorithm> + +#include <string.h> + +#ifdef DEBUG +# include <stdio.h> +#endif + +#include <R_ext/Memory.h> + +/** This file containt the C glue functions for an R interface to + * Dynare++. Although written in standard C (except for the use of + * R_alloc), the indexing, calling and memory management conventions + * of the functions in this file were tailored for R. + * + * It is not recommended that you use this interface for anything else + * but R. + */ + +/** Error codes: these error codes correspond to possible + * exceptions. */ +#define DYNARER_SYLVEXCEPTION 1 +#define DYNARER_DYNAREEXCEPTION 2 +#define DYNARER_OGUEXCEPTION 3 +#define DYNARER_TLEXCEPTION 4 +#define DYNARER_KORDEXCEPTION 5 +#define DYNARER_NAMESMATCHINGERROR 6 + +/** Copies the message into a buffer. The buffer is allocated and + * managed by R, ie it will be garbage collected after the .C call + * returns and the contents are duplicated. + */ +char * +passmessage(const char *errormessage) +{ + long l = strlen(errormessage); + char *em = R_alloc(l, 1); + return strcpy(em, errormessage); +} + +/** This function puts the mapping between the newtotal items after + * nl[offset] and the items in orig into the buffer perm, which has to + * be at least as long as newtotal. The function uses R indexing, + * that is to say, the first index is 1. + */ +int +matchnames(const char **orig, int origtotal, + const NameList &nl, int offset, int newtotal, + int *perm) +{ +#ifdef DEBUG + printf("matching names (R indexing):\n"); +#endif + for (int i = 0; i < newtotal; i++) + { + int j; + for (j = 0; j < origtotal; j++) + if (strcmp(nl.getName(offset+i), *(orig+j)) == 0) + { + *(perm+i) = j+1; +#ifdef DEBUG + printf("%d -> %d\n", i+1, j+1); +#endif + break; + } + if (j == origtotal) + return 1; + } + return 0; +} + +/** dynareR is the interface function. The user provides: + * - a list of endogenous and exogenous variables, a list of + * parameters (and the length of each list) + * - the model equations (modeleq, pointer to a 0-terminated string) + * - the order of expansion (ord) + * - journal file name (jnlfile, can be "/dev/null" for no journal) + * - values for the parametes (parval) + * - variance-covariance matrix (vcov, stacked by columns, R does + * this) + * - initial values for finding the steady state (initval) + * - and the number of steps for the approximation algorithm + * (numsteps) + * + * If successful, the interface will write the results to these + * buffers: + * - tensorbuffer for the steady state and the flattened tensors + * - num_state for the number of endogenous variables that ended up in + * the state + * - mappings to variable names (ordering_state, ordering_endo, + * ordering_exo), indices start from 1 + * - the deterministic steady state (newinitval) + * + * If dynare throws an exception, the interface tries to catch it and + * return an error code (error), and error message (errormessage), and + * if applicable, information on the stability of the model + * (kordcode). errormessage is allocated into R's memory, and will be + * collected after duplication. + */ +extern "C" { + void + dynareR(const char **endo, const int *num_endo, + const char **exo, const int *num_exo, + const char **par, const int *num_par, + const char **equations, const int *ord, const char *jnlfile, + const double *parval, const double *vcov, + const double *initval, + const int *num_steps, + double *tensorbuffer, + int *num_state, int *ordering_state, + int *ordering_endo, int *ordering_exo, + double *newinitval, + int *error, char **errormessage, int *kordcode) + { + // construct the model here + try + { +#ifdef DEBUG // will print only first var names etc. + printf("eq: %s\nendo: %d %s\nexo: %d %s\npar: %d %s\nord: %d\n", + *equations, *num_endo, *endo, *num_exo, *exo, *num_par, *par, *ord); +#endif + // create journal + Journal journal(jnlfile); + // create Dynare object + Dynare dynare(endo, *num_endo, exo, *num_exo, + par, *num_par, *equations, strlen(*equations), + *ord, journal); + // set Vcov and parameter values + copy(parval, parval+(*num_par), dynare.getParams().base()); +#ifdef DEBUG + printf("parameter values (%d):\n", dynare.getParams().length()); + dynare.getParams().print(); +#endif + copy(vcov, vcov+(*num_exo)*(*num_exo), dynare.getVcov().base()); +#ifdef DEBUG + printf("vcov matrix:\n"); + dynare.getVcov().print(); +#endif + // set initial values + Vector iv(initval, *num_endo); +#ifdef DEBUG + printf("initial values:\n"); + iv.print(); +#endif + dynare.setInitOuter(iv); + // construct approximation + tls.init(dynare.order(), + dynare.nstat()+2*dynare.npred()+3*dynare.nboth() + +2*dynare.nforw()+dynare.nexog()); + Approximation approximation(dynare, journal, *num_steps); + approximation.walkStochSteady(); + // write the steady state into the buffer + int ny = dynare.ny(); + const Vector ss(dynare.getSteady()); + // ss = ConstVector(approximation.getSS(), 0); // FIXME allow + // // for nonzero + int s = dynare.getStateNames().getNum(); + int sm = s; + tensorbuffer = copy(ss.base(), ss.base()+ny, tensorbuffer); + // write the tensors into buffer + const UnfoldDecisionRule &udr + = approximation.getUnfoldDecisionRule(); + for (int i = 1; i <= *ord; i++) + { + const UFSTensor *t = udr.get(Symmetry(i)); +#ifdef DEBUG + printf("tensor %d:\n", i); + t->print(); +#endif + tensorbuffer = copy(t->base(), t->base()+ny*sm, tensorbuffer); + sm *= s; + } + // save number of endogenous states + *num_state = s-(*num_exo); + // ordering +#ifdef DEBUG + printf("all endo names:\n"); + dynare.getAllEndoNames().print(); + printf("all state names:\n"); + dynare.getStateNames().print(); +#endif + if (matchnames(endo, *num_endo, dynare.getAllEndoNames(), + 0, *num_endo, ordering_endo) + || matchnames(endo, *num_endo, dynare.getStateNames(), + 0, *num_state, ordering_state) + || matchnames(exo, *num_exo, dynare.getStateNames(), + *num_state, *num_exo, ordering_exo)) + { + *error = DYNARER_NAMESMATCHINGERROR; + *errormessage = "There was a problem when matching names. This is weird and should not happen."; + return; + } + // return new init values (first column of SS matrix) + ConstVector newinit((const GeneralMatrix &)approximation.getSS(), 0); +#ifdef DEBUG + printf("new initial values:\n"); + newinit.print(); +#endif + copy(newinit.base(), newinit.base()+(*num_endo), newinitval); + } + catch (const SylvException &e) + { + *error = DYNARER_SYLVEXCEPTION; + char errorbuffer[501]; + e.printMessage(errorbuffer, 500); + *errormessage = passmessage(errorbuffer); +#ifdef DEBUG + printf("Caught Sylv exception: "); + e.printMessage(); +#endif + return; + } + catch (const DynareException &e) + { + *error = DYNARER_DYNAREEXCEPTION; + *errormessage = passmessage(e.message()); +#ifdef DEBUG + printf("Caught Dynare exception: %s\n", e.message()); +#endif + return; + } + catch (const ogu::Exception &e) + { + *error = DYNARER_OGUEXCEPTION; + *errormessage = passmessage(e.message()); +#ifdef DEBUG + printf("Caught ogu::Exception: "); + e.print(); +#endif + return; + } + catch (const TLException &e) + { + *error = DYNARER_TLEXCEPTION; + *errormessage = passmessage(e.getmessage()); +#ifdef DEBUG + printf("Caugth TL exception: "); + e.print(); +#endif + return; + } + catch (const KordException &e) + { + *error = DYNARER_KORDEXCEPTION; + *errormessage = passmessage(e.getmessage()); + *kordcode = e.code(); // Kord error code +#ifdef DEBUG + printf("Caugth Kord exception: "); + e.print(); +#endif + return; + } + *error = 0; + return; + } +} diff --git a/dynare++/extern/R/dynareR.cpp b/dynare++/extern/R/dynareR.cpp deleted file mode 100644 index 727fe9967c2ad3672fab9c85d607478e7c86f11d..0000000000000000000000000000000000000000 --- a/dynare++/extern/R/dynareR.cpp +++ /dev/null @@ -1,249 +0,0 @@ -// $Id: dynareR.cpp 862 2006-08-04 17:34:56Z tamas $ - -// Copyright 2006, Tamas K Papp - -#include "dynare3.h" // Dynare class -#include "approximation.h" // Approximation class - -// exceptions -#include "dynare_exception.h" -#include "parser/cc/parser_exception.h" -#include "utils/cc/exception.h" -#include "SylvException.h" -#include "tl_exception.h" -#include "kord_exception.h" - -#include <algorithm> - -#include <string.h> - -#ifdef DEBUG -#include <stdio.h> -#endif - -#include <R_ext/Memory.h> - -/** This file containt the C glue functions for an R interface to - * Dynare++. Although written in standard C (except for the use of - * R_alloc), the indexing, calling and memory management conventions - * of the functions in this file were tailored for R. - * - * It is not recommended that you use this interface for anything else - * but R. - */ - -/** Error codes: these error codes correspond to possible - * exceptions. */ -#define DYNARER_SYLVEXCEPTION 1 -#define DYNARER_DYNAREEXCEPTION 2 -#define DYNARER_OGUEXCEPTION 3 -#define DYNARER_TLEXCEPTION 4 -#define DYNARER_KORDEXCEPTION 5 -#define DYNARER_NAMESMATCHINGERROR 6 - -/** Copies the message into a buffer. The buffer is allocated and - * managed by R, ie it will be garbage collected after the .C call - * returns and the contents are duplicated. - */ -char *passmessage(const char *errormessage) { - long l = strlen(errormessage); - char *em = R_alloc(l, 1); - return strcpy(em, errormessage); -} - -/** This function puts the mapping between the newtotal items after - * nl[offset] and the items in orig into the buffer perm, which has to - * be at least as long as newtotal. The function uses R indexing, - * that is to say, the first index is 1. - */ -int matchnames(const char **orig, int origtotal, - const NameList &nl, int offset, int newtotal, - int *perm) { -#ifdef DEBUG - printf("matching names (R indexing):\n"); -#endif - for (int i=0; i < newtotal; i++) { - int j; - for (j=0; j < origtotal; j++) - if (strcmp(nl.getName(offset+i), *(orig+j))==0) { - *(perm+i) = j+1; -#ifdef DEBUG - printf("%d -> %d\n",i+1,j+1); -#endif - break; - } - if (j==origtotal) - return 1; - } - return 0; -} - -/** dynareR is the interface function. The user provides: - * - a list of endogenous and exogenous variables, a list of - * parameters (and the length of each list) - * - the model equations (modeleq, pointer to a 0-terminated string) - * - the order of expansion (ord) - * - journal file name (jnlfile, can be "/dev/null" for no journal) - * - values for the parametes (parval) - * - variance-covariance matrix (vcov, stacked by columns, R does - * this) - * - initial values for finding the steady state (initval) - * - and the number of steps for the approximation algorithm - * (numsteps) - * - * If successful, the interface will write the results to these - * buffers: - * - tensorbuffer for the steady state and the flattened tensors - * - num_state for the number of endogenous variables that ended up in - * the state - * - mappings to variable names (ordering_state, ordering_endo, - * ordering_exo), indices start from 1 - * - the deterministic steady state (newinitval) - * - * If dynare throws an exception, the interface tries to catch it and - * return an error code (error), and error message (errormessage), and - * if applicable, information on the stability of the model - * (kordcode). errormessage is allocated into R's memory, and will be - * collected after duplication. - */ -extern "C" { - void dynareR(const char** endo, const int* num_endo, - const char** exo, const int* num_exo, - const char** par, const int* num_par, - const char** equations, const int* ord, const char* jnlfile, - const double *parval, const double *vcov, - const double *initval, - const int *num_steps, - double* tensorbuffer, - int *num_state, int *ordering_state, - int *ordering_endo, int *ordering_exo, - double *newinitval, - int* error, char **errormessage, int *kordcode) { - // construct the model here - try { -#ifdef DEBUG // will print only first var names etc. - printf("eq: %s\nendo: %d %s\nexo: %d %s\npar: %d %s\nord: %d\n", - *equations,*num_endo,*endo,*num_exo,*exo,*num_par,*par,*ord); -#endif - // create journal - Journal journal(jnlfile); - // create Dynare object - Dynare dynare(endo, *num_endo, exo, *num_exo, - par, *num_par, *equations, strlen(*equations), - *ord, journal); - // set Vcov and parameter values - copy(parval,parval+(*num_par),dynare.getParams().base()); -#ifdef DEBUG - printf("parameter values (%d):\n",dynare.getParams().length()); - dynare.getParams().print(); -#endif - copy(vcov,vcov+(*num_exo)*(*num_exo),dynare.getVcov().base()); -#ifdef DEBUG - printf("vcov matrix:\n"); - dynare.getVcov().print(); -#endif - // set initial values - Vector iv(initval,*num_endo); -#ifdef DEBUG - printf("initial values:\n"); - iv.print(); -#endif - dynare.setInitOuter(iv); - // construct approximation - tls.init(dynare.order(), - dynare.nstat()+2*dynare.npred()+3*dynare.nboth()+ - 2*dynare.nforw()+dynare.nexog()); - Approximation approximation(dynare,journal,*num_steps); - approximation.walkStochSteady(); - // write the steady state into the buffer - int ny = dynare.ny(); - const Vector ss(dynare.getSteady()); -// ss = ConstVector(approximation.getSS(), 0); // FIXME allow -// // for nonzero - int s = dynare.getStateNames().getNum(); - int sm = s; - tensorbuffer = copy(ss.base(),ss.base()+ny,tensorbuffer); - // write the tensors into buffer - const UnfoldDecisionRule& udr = - approximation.getUnfoldDecisionRule(); - for (int i=1; i <= *ord; i++) { - const UFSTensor* t = udr.get(Symmetry(i)); -#ifdef DEBUG - printf("tensor %d:\n", i); - t->print(); -#endif - tensorbuffer = copy(t->base(), t->base()+ny*sm, tensorbuffer); - sm *= s; - } - // save number of endogenous states - *num_state = s-(*num_exo); - // ordering -#ifdef DEBUG - printf("all endo names:\n"); - dynare.getAllEndoNames().print(); - printf("all state names:\n"); - dynare.getStateNames().print(); -#endif - if (matchnames(endo, *num_endo, dynare.getAllEndoNames(), - 0, *num_endo, ordering_endo) || - matchnames(endo, *num_endo, dynare.getStateNames(), - 0, *num_state, ordering_state) || - matchnames(exo, *num_exo, dynare.getStateNames(), - *num_state, *num_exo, ordering_exo)) { - *error = DYNARER_NAMESMATCHINGERROR; - *errormessage = "There was a problem when matching names. This is weird and should not happen."; - return; - } - // return new init values (first column of SS matrix) - ConstVector newinit((const GeneralMatrix&) approximation.getSS(), 0); -#ifdef DEBUG - printf("new initial values:\n"); - newinit.print(); -#endif - copy(newinit.base(),newinit.base()+(*num_endo),newinitval); - } catch (const SylvException &e) { - *error = DYNARER_SYLVEXCEPTION; - char errorbuffer[501]; - e.printMessage(errorbuffer, 500); - *errormessage = passmessage(errorbuffer); -#ifdef DEBUG - printf("Caught Sylv exception: "); - e.printMessage(); -#endif - return; - } catch (const DynareException &e) { - *error = DYNARER_DYNAREEXCEPTION; - *errormessage = passmessage(e.message()); -#ifdef DEBUG - printf("Caught Dynare exception: %s\n", e.message()); -#endif - return; - } catch (const ogu::Exception &e) { - *error = DYNARER_OGUEXCEPTION; - *errormessage = passmessage(e.message()); -#ifdef DEBUG - printf("Caught ogu::Exception: "); - e.print(); -#endif - return; - } catch (const TLException &e) { - *error = DYNARER_TLEXCEPTION; - *errormessage = passmessage(e.getmessage()); -#ifdef DEBUG - printf("Caugth TL exception: "); - e.print(); -#endif - return; - } catch (const KordException &e) { - *error = DYNARER_KORDEXCEPTION; - *errormessage = passmessage(e.getmessage()); - *kordcode = e.code(); // Kord error code -#ifdef DEBUG - printf("Caugth Kord exception: "); - e.print(); -#endif - return; - } - *error = 0; - return;} -} diff --git a/dynare++/extern/R/test.cc b/dynare++/extern/R/test.cc new file mode 100644 index 0000000000000000000000000000000000000000..68de75490479d45b038364befcf63f034e894d86 --- /dev/null +++ b/dynare++/extern/R/test.cc @@ -0,0 +1,34 @@ +#include "dynareR.cc" + +int +main(void) +{ + const char *parameters[] = {"beta", "gamma", "rho", "alpha", "delta"}; + const char *varendo[] = {"k", "c", "a"}; + const char *varexo[] = {"eps"}; + const int numpar = 5; + const int numendo = 3; + const int numexo = 1; + const int ord = 2; + const int numsteps = 0; + const double parval[] = {.99, 2, .9, .3, .025}; + const double vcov[] = {0.001}; + const double initval[] = {0.066, 0.43, 0.01}; + + int e; + double tensorbuffer[100]; + int num_state; + int ordering_state[] = {0, 0, 0}; + int ordering_endo[] = {0, 0, 0}; + int ordering_exo[] = {0}; + double newinitval[] = {0, 0, 0}; + + const char *modeleq[] = {"(c/c(1))^gamma*beta*(alpha*exp(a(1))*k^(alpha-1)+1-delta)=1; a=rho*a(-1)+eps; k+c=exp(a)*k(-1)^alpha+(1-delta)*k(-1);"}; + + dynareR(varendo, &numendo, varexo, &numexo, parameters, &numpar, modeleq, + &ord, "journal", parval, vcov, initval, + &numsteps, tensorbuffer, + &num_state, ordering_state, ordering_endo, ordering_exo, + newinitval, &e); + printf("error code: %d\n", e); +} diff --git a/dynare++/extern/R/test.cpp b/dynare++/extern/R/test.cpp deleted file mode 100644 index 6c843c609e941d2903db35260c840f4472f6fe86..0000000000000000000000000000000000000000 --- a/dynare++/extern/R/test.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include "dynareR.cpp" - -int main(void) { - const char *parameters[] = {"beta","gamma","rho","alpha","delta"}; - const char *varendo[] = {"k","c","a"}; - const char *varexo[] = {"eps"}; - const int numpar = 5; - const int numendo = 3; - const int numexo = 1; - const int ord = 2; - const int numsteps = 0; - const double parval[] = {.99,2,.9,.3,.025}; - const double vcov[] = {0.001}; - const double initval[] = {0.066, 0.43, 0.01}; - - int e; - double tensorbuffer[100]; - int num_state; - int ordering_state[] = {0,0,0}; - int ordering_endo[] = {0,0,0}; - int ordering_exo[] = {0}; - double newinitval[] = {0,0,0}; - - const char *modeleq[] = {"(c/c(1))^gamma*beta*(alpha*exp(a(1))*k^(alpha-1)+1-delta)=1; a=rho*a(-1)+eps; k+c=exp(a)*k(-1)^alpha+(1-delta)*k(-1);"}; - - dynareR(varendo, &numendo, varexo, &numexo, parameters, &numpar, modeleq, - &ord, "journal", parval, vcov, initval, - &numsteps, tensorbuffer, - &num_state, ordering_state, ordering_endo, ordering_exo, - newinitval,&e); - printf("error code: %d\n", e); -} diff --git a/dynare++/extern/matlab/dynare_simul.cc b/dynare++/extern/matlab/dynare_simul.cc new file mode 100644 index 0000000000000000000000000000000000000000..192c8114508b567b895b8059bb60054d7f3a0c59 --- /dev/null +++ b/dynare++/extern/matlab/dynare_simul.cc @@ -0,0 +1,140 @@ +// Copyright (C) 2005-2011, Ondra Kamenik + +// This is the mexFunction providing interface to +// DecisionRule<>::simulate(). It takes the following input +// parameters: +// order the order of approximation, needs order+1 derivatives +// nstat +// npred +// nboth +// nforw +// nexog +// ystart starting value (full vector of endogenous) +// shocks matrix of shocks (nexog x number of period) +// vcov covariance matrix of shocks (nexog x nexog) +// seed integer seed +// ysteady full vector of decision rule's steady +// ... order+1 matrices of derivatives + +// output: +// res simulated results + +#include "dynmex.h" +#include "mex.h" + +#include "decision_rule.hh" +#include "fs_tensor.hh" +#include "SylvException.hh" + +extern "C" { + void + mexFunction(int nlhs, mxArray *plhs[], + int nhrs, const mxArray *prhs[]) + { + if (nhrs < 12 || nlhs != 2) + DYN_MEX_FUNC_ERR_MSG_TXT("dynare_simul_ must have at least 12 input parameters and exactly 2 output arguments.\n"); + + int order = (int) mxGetScalar(prhs[0]); + if (nhrs != 12 + order) + DYN_MEX_FUNC_ERR_MSG_TXT("dynare_simul_ must have exactly 11+order input parameters.\n"); + + int nstat = (int) mxGetScalar(prhs[1]); + int npred = (int) mxGetScalar(prhs[2]); + int nboth = (int) mxGetScalar(prhs[3]); + int nforw = (int) mxGetScalar(prhs[4]); + int nexog = (int) mxGetScalar(prhs[5]); + + const mxArray *const ystart = prhs[6]; + const mxArray *const shocks = prhs[7]; + const mxArray *const vcov = prhs[8]; + int seed = (int) mxGetScalar(prhs[9]); + const mxArray *const ysteady = prhs[10]; + const mwSize *const ystart_dim = mxGetDimensions(ystart); + const mwSize *const shocks_dim = mxGetDimensions(shocks); + const mwSize *const vcov_dim = mxGetDimensions(vcov); + const mwSize *const ysteady_dim = mxGetDimensions(ysteady); + + int ny = nstat + npred + nboth + nforw; + if (ny != (int) ystart_dim[0]) + DYN_MEX_FUNC_ERR_MSG_TXT("ystart has wrong number of rows.\n"); + if (1 != ystart_dim[1]) + DYN_MEX_FUNC_ERR_MSG_TXT("ystart has wrong number of cols.\n"); + int nper = shocks_dim[1]; + if (nexog != (int) shocks_dim[0]) + DYN_MEX_FUNC_ERR_MSG_TXT("shocks has a wrong number of rows.\n"); + if (nexog != (int) vcov_dim[0]) + DYN_MEX_FUNC_ERR_MSG_TXT("vcov has a wrong number of rows.\n"); + if (nexog != (int) vcov_dim[1]) + DYN_MEX_FUNC_ERR_MSG_TXT("vcov has a wrong number of cols.\n"); + if (ny != (int) ysteady_dim[0]) + DYN_MEX_FUNC_ERR_MSG_TXT("ysteady has wrong number of rows.\n"); + if (1 != ysteady_dim[1]) + DYN_MEX_FUNC_ERR_MSG_TXT("ysteady has wrong number of cols.\n"); + + mxArray *res = mxCreateDoubleMatrix(ny, nper, mxREAL); + + try + { + // initialize tensor library + tls.init(order, npred+nboth+nexog); + + // form the polynomial + UTensorPolynomial pol(ny, npred+nboth+nexog); + for (int dim = 0; dim <= order; dim++) + { + const mxArray *gk = prhs[11+dim]; + const mwSize *const gk_dim = mxGetDimensions(gk); + FFSTensor ft(ny, npred+nboth+nexog, dim); + if (ft.ncols() != (int) gk_dim[1]) + { + char buf[1000]; + sprintf(buf, "Wrong number of columns for folded tensor: got %d but I want %d\n", + (int) gk_dim[1], ft.ncols()); + DYN_MEX_FUNC_ERR_MSG_TXT(buf); + } + if (ft.nrows() != (int) gk_dim[0]) + { + char buf[1000]; + sprintf(buf, "Wrong number of rows for folded tensor: got %d but I want %d\n", + (int) gk_dim[0], ft.nrows()); + DYN_MEX_FUNC_ERR_MSG_TXT(buf); + } + ft.zeros(); + ConstTwoDMatrix gk_mat(ft.nrows(), ft.ncols(), mxGetPr(gk)); + ft.add(1.0, gk_mat); + UFSTensor *ut = new UFSTensor(ft); + pol.insert(ut); + } + // form the decision rule + UnfoldDecisionRule + dr(pol, PartitionY(nstat, npred, nboth, nforw), + nexog, ConstVector(mxGetPr(ysteady), ny)); + // form the shock realization + TwoDMatrix shocks_mat(nexog, nper, (const double *)mxGetPr(shocks)); + TwoDMatrix vcov_mat(nexog, nexog, (const double *)mxGetPr(vcov)); + GenShockRealization sr(vcov_mat, shocks_mat, seed); + // simulate and copy the results + Vector ystart_vec((const double *)mxGetPr(ystart), ny); + TwoDMatrix *res_mat + = dr.simulate(DecisionRule::horner, nper, + ystart_vec, sr); + TwoDMatrix res_tmp_mat(ny, nper, mxGetPr(res)); + res_tmp_mat = (const TwoDMatrix &) (*res_mat); + delete res_mat; + plhs[1] = res; + } + catch (const KordException &e) + { + DYN_MEX_FUNC_ERR_MSG_TXT("Caugth Kord exception."); + } + catch (const TLException &e) + { + DYN_MEX_FUNC_ERR_MSG_TXT("Caugth TL exception."); + } + catch (SylvException &e) + { + DYN_MEX_FUNC_ERR_MSG_TXT("Caught Sylv exception."); + } + plhs[0] = mxCreateDoubleScalar(0); + } +}; diff --git a/dynare++/extern/matlab/dynare_simul.cpp b/dynare++/extern/matlab/dynare_simul.cpp deleted file mode 100644 index 03ea0d397e70a6c767dba9e7e3ce3f3eeb7511b2..0000000000000000000000000000000000000000 --- a/dynare++/extern/matlab/dynare_simul.cpp +++ /dev/null @@ -1,129 +0,0 @@ -// Copyright (C) 2005-2011, Ondra Kamenik - -// This is the mexFunction providing interface to -// DecisionRule<>::simulate(). It takes the following input -// parameters: -// order the order of approximation, needs order+1 derivatives -// nstat -// npred -// nboth -// nforw -// nexog -// ystart starting value (full vector of endogenous) -// shocks matrix of shocks (nexog x number of period) -// vcov covariance matrix of shocks (nexog x nexog) -// seed integer seed -// ysteady full vector of decision rule's steady -// ... order+1 matrices of derivatives - -// output: -// res simulated results - -#include "dynmex.h" -#include "mex.h" - -#include "decision_rule.hh" -#include "fs_tensor.hh" -#include "SylvException.h" - -extern "C" { - void mexFunction(int nlhs, mxArray* plhs[], - int nhrs, const mxArray* prhs[]) - { - if (nhrs < 12 || nlhs != 2) - DYN_MEX_FUNC_ERR_MSG_TXT("dynare_simul_ must have at least 12 input parameters and exactly 2 output arguments.\n"); - - int order = (int)mxGetScalar(prhs[0]); - if (nhrs != 12 + order) - DYN_MEX_FUNC_ERR_MSG_TXT("dynare_simul_ must have exactly 11+order input parameters.\n"); - - int nstat = (int)mxGetScalar(prhs[1]); - int npred = (int)mxGetScalar(prhs[2]); - int nboth = (int)mxGetScalar(prhs[3]); - int nforw = (int)mxGetScalar(prhs[4]); - int nexog = (int)mxGetScalar(prhs[5]); - - const mxArray* const ystart = prhs[6]; - const mxArray* const shocks = prhs[7]; - const mxArray* const vcov = prhs[8]; - int seed = (int)mxGetScalar(prhs[9]); - const mxArray* const ysteady = prhs[10]; - const mwSize* const ystart_dim = mxGetDimensions(ystart); - const mwSize* const shocks_dim = mxGetDimensions(shocks); - const mwSize* const vcov_dim = mxGetDimensions(vcov); - const mwSize* const ysteady_dim = mxGetDimensions(ysteady); - - int ny = nstat + npred + nboth + nforw; - if (ny != (int) ystart_dim[0]) - DYN_MEX_FUNC_ERR_MSG_TXT("ystart has wrong number of rows.\n"); - if (1 != ystart_dim[1]) - DYN_MEX_FUNC_ERR_MSG_TXT("ystart has wrong number of cols.\n"); - int nper = shocks_dim[1]; - if (nexog != (int) shocks_dim[0]) - DYN_MEX_FUNC_ERR_MSG_TXT("shocks has a wrong number of rows.\n"); - if (nexog != (int) vcov_dim[0]) - DYN_MEX_FUNC_ERR_MSG_TXT("vcov has a wrong number of rows.\n"); - if (nexog != (int) vcov_dim[1]) - DYN_MEX_FUNC_ERR_MSG_TXT("vcov has a wrong number of cols.\n"); - if (ny != (int) ysteady_dim[0]) - DYN_MEX_FUNC_ERR_MSG_TXT("ysteady has wrong number of rows.\n"); - if (1 != ysteady_dim[1]) - DYN_MEX_FUNC_ERR_MSG_TXT("ysteady has wrong number of cols.\n"); - - mxArray* res = mxCreateDoubleMatrix(ny, nper, mxREAL); - - try { - // initialize tensor library - tls.init(order, npred+nboth+nexog); - - // form the polynomial - UTensorPolynomial pol(ny, npred+nboth+nexog); - for (int dim = 0; dim <= order; dim++) { - const mxArray* gk = prhs[11+dim]; - const mwSize* const gk_dim = mxGetDimensions(gk); - FFSTensor ft(ny, npred+nboth+nexog, dim); - if (ft.ncols() != (int) gk_dim[1]) { - char buf[1000]; - sprintf(buf, "Wrong number of columns for folded tensor: got %d but I want %d\n", - (int) gk_dim[1], ft.ncols()); - DYN_MEX_FUNC_ERR_MSG_TXT(buf); - } - if (ft.nrows() != (int) gk_dim[0]) { - char buf[1000]; - sprintf(buf, "Wrong number of rows for folded tensor: got %d but I want %d\n", - (int) gk_dim[0], ft.nrows()); - DYN_MEX_FUNC_ERR_MSG_TXT(buf); - } - ft.zeros(); - ConstTwoDMatrix gk_mat(ft.nrows(), ft.ncols(), mxGetPr(gk)); - ft.add(1.0, gk_mat); - UFSTensor* ut = new UFSTensor(ft); - pol.insert(ut); - } - // form the decision rule - UnfoldDecisionRule - dr(pol, PartitionY(nstat, npred, nboth, nforw), - nexog, ConstVector(mxGetPr(ysteady), ny)); - // form the shock realization - TwoDMatrix shocks_mat(nexog, nper, (const double*)mxGetPr(shocks)); - TwoDMatrix vcov_mat(nexog, nexog, (const double*)mxGetPr(vcov)); - GenShockRealization sr(vcov_mat, shocks_mat, seed); - // simulate and copy the results - Vector ystart_vec((const double*)mxGetPr(ystart), ny); - TwoDMatrix* res_mat = - dr.simulate(DecisionRule::horner, nper, - ystart_vec, sr); - TwoDMatrix res_tmp_mat(ny, nper, mxGetPr(res)); - res_tmp_mat = (const TwoDMatrix&)(*res_mat); - delete res_mat; - plhs[1] = res; - } catch (const KordException& e) { - DYN_MEX_FUNC_ERR_MSG_TXT("Caugth Kord exception."); - } catch (const TLException& e) { - DYN_MEX_FUNC_ERR_MSG_TXT("Caugth TL exception."); - } catch (SylvException& e) { - DYN_MEX_FUNC_ERR_MSG_TXT("Caught Sylv exception."); - } - plhs[0] = mxCreateDoubleScalar(0); - } -}; diff --git a/dynare++/integ/cc/quasi_mcarlo.hh b/dynare++/integ/cc/quasi_mcarlo.hh index fa9f97ed1d38c76900ee625258db219db2f8af76..5385b688651e97ecd39d65b3ca98e9dc414aefd2 100644 --- a/dynare++/integ/cc/quasi_mcarlo.hh +++ b/dynare++/integ/cc/quasi_mcarlo.hh @@ -28,7 +28,7 @@ #include "int_sequence.hh" #include "quadrature.hh" -#include "Vector.h" +#include "Vector.hh" #include <vector> diff --git a/dynare++/integ/cc/vector_function.hh b/dynare++/integ/cc/vector_function.hh index 7ec856b82f8443eff1bc7ab448c92e2b25b19ea2..bcef366af228be605c7e050839d83c8486e255fe 100644 --- a/dynare++/integ/cc/vector_function.hh +++ b/dynare++/integ/cc/vector_function.hh @@ -16,8 +16,8 @@ #ifndef VECTOR_FUNCTION_H #define VECTOR_FUNCTION_H -#include "Vector.h" -#include "GeneralMatrix.h" +#include "Vector.hh" +#include "GeneralMatrix.hh" #include <vector> diff --git a/dynare++/integ/src/quadrature-points.cc b/dynare++/integ/src/quadrature-points.cc index 7d8358aa604726fdbdd33740653b86b4bf2b20e7..56a4b7052700e4b78cbabec1d2f31f07d7f5852a 100644 --- a/dynare++/integ/src/quadrature-points.cc +++ b/dynare++/integ/src/quadrature-points.cc @@ -1,12 +1,12 @@ // Copyright (C) 2008-2011, Ondra Kamenik -#include "parser/cc/matrix_parser.h" -#include "utils/cc/memory_file.h" -#include "utils/cc/exception.h" -#include "sylv/cc/GeneralMatrix.h" -#include "sylv/cc/Vector.h" -#include "sylv/cc/SymSchurDecomp.h" -#include "sylv/cc/SylvException.h" +#include "parser/cc/matrix_parser.hh" +#include "utils/cc/memory_file.hh" +#include "utils/cc/exception.hh" +#include "sylv/cc/GeneralMatrix.hh" +#include "sylv/cc/Vector.hh" +#include "sylv/cc/SymSchurDecomp.hh" +#include "sylv/cc/SylvException.hh" #include "integ/cc/quadrature.hh" #include "integ/cc/smolyak.hh" #include "integ/cc/product.hh" diff --git a/dynare++/integ/testing/tests.cc b/dynare++/integ/testing/tests.cc index d10e06393cc9ed6802621b9209edee7f34458318..76e2db514a6eca93aa3fcbf8c5d140d9ff144efe 100644 --- a/dynare++/integ/testing/tests.cc +++ b/dynare++/integ/testing/tests.cc @@ -1,18 +1,18 @@ /* $Id: tests.cpp 431 2005-08-16 15:41:01Z kamenik $ */ /* Copyright 2005, Ondra Kamenik */ -#include "GeneralMatrix.h" +#include "GeneralMatrix.hh" #include <dynlapack.h> -#include "SylvException.h" +#include "SylvException.hh" -#include "rfs_tensor.h" -#include "normal_moments.h" +#include "rfs_tensor.hh" +#include "normal_moments.hh" -#include "vector_function.h" -#include "quadrature.h" -#include "smolyak.h" -#include "product.h" -#include "quasi_mcarlo.h" +#include "vector_function.hh" +#include "quadrature.hh" +#include "smolyak.hh" +#include "product.hh" +#include "quasi_mcarlo.hh" #include <cstdio> #include <cstring> diff --git a/dynare++/kord/decision_rule.cc b/dynare++/kord/decision_rule.cc index 3afd8072818c52d8559167d2e5dc544919511570..1287274fd7b686870b45d62653217224430ce454 100644 --- a/dynare++/kord/decision_rule.cc +++ b/dynare++/kord/decision_rule.cc @@ -4,7 +4,7 @@ #include "decision_rule.hh" #include "dynamic_model.hh" -#include "SymSchurDecomp.h" +#include "SymSchurDecomp.hh" #include <dynlapack.h> diff --git a/dynare++/kord/dynamic_model.hh b/dynare++/kord/dynamic_model.hh index 279985f3f2aa60f447d961b8133be2917eff0f62..8cd11c1dd555b604311de2017a1fce9e6b04dd3a 100644 --- a/dynare++/kord/dynamic_model.hh +++ b/dynare++/kord/dynamic_model.hh @@ -13,7 +13,7 @@ #include "t_container.hh" #include "sparse_tensor.hh" -#include "Vector.h" +#include "Vector.hh" /* The class is a virtual pure class which provides an access to names of the variables. */ diff --git a/dynare++/kord/global_check.cc b/dynare++/kord/global_check.cc index d0a5556ef194d01198db5240bdfbda018ee7ad70..f8b90b0c8e21c2fa196eebefd2bd034389dfa6f7 100644 --- a/dynare++/kord/global_check.cc +++ b/dynare++/kord/global_check.cc @@ -1,6 +1,6 @@ // Copyright 2005, Ondra Kamenik -#include "SymSchurDecomp.h" +#include "SymSchurDecomp.hh" #include "global_check.hh" diff --git a/dynare++/kord/korder.hh b/dynare++/kord/korder.hh index 20e7a25417532008103f67645a7cd77d972b0691..5b0b3741b99b8034e2baad94adc8f6224dc9fce9 100644 --- a/dynare++/kord/korder.hh +++ b/dynare++/kord/korder.hh @@ -36,7 +36,7 @@ #include "journal.hh" #include "kord_exception.hh" -#include "GeneralSylvester.h" +#include "GeneralSylvester.hh" #include <dynlapack.h> diff --git a/dynare++/kord/tests.cc b/dynare++/kord/tests.cc index 8e782035d8871f2b2a0ea7b3c7e02a0bcdd564ef..fa60c6040dcdcc6beab1ddcb08df19e3dc341912 100644 --- a/dynare++/kord/tests.cc +++ b/dynare++/kord/tests.cc @@ -3,7 +3,7 @@ #include <cstdlib> #include "korder.hh" -#include "SylvException.h" +#include "SylvException.hh" struct Rand { diff --git a/dynare++/parser/cc/Makefile.am b/dynare++/parser/cc/Makefile.am index a63168651cd4785804fd636e29b2c8cc6ed2aa53..d099909f243e5a79c46eade9e72542750821c2e8 100644 --- a/dynare++/parser/cc/Makefile.am +++ b/dynare++/parser/cc/Makefile.am @@ -3,40 +3,40 @@ noinst_LIBRARIES = libparser.a GENERATED_FILES = assign_tab.cc csv_tab.cc formula_tab.cc matrix_tab.cc namelist_tab.cc assign_tab.hh csv_tab.hh formula_tab.hh matrix_tab.hh namelist_tab.hh assign_ll.cc csv_ll.cc formula_ll.cc matrix_ll.cc namelist_ll.cc libparser_a_SOURCES = \ - location.h \ - namelist.h \ - atom_assignings.cpp \ - atom_assignings.h \ - atom_substitutions.cpp \ - atom_substitutions.h \ - csv_parser.cpp \ - csv_parser.h \ - dynamic_atoms.cpp \ - dynamic_atoms.h \ - fine_atoms.cpp \ - fine_atoms.h \ - formula_parser.cpp \ - formula_parser.h \ - matrix_parser.cpp \ - matrix_parser.h \ - parser_exception.cpp \ - parser_exception.h \ - static_atoms.cpp \ - static_atoms.h \ - static_fine_atoms.cpp \ - static_fine_atoms.h \ - tree.cpp \ - tree.h \ + location.hh \ + namelist.hh \ + atom_assignings.cc \ + atom_assignings.hh \ + atom_substitutions.cc \ + atom_substitutions.hh \ + csv_parser.cc \ + csv_parser.hh \ + dynamic_atoms.cc \ + dynamic_atoms.hh \ + fine_atoms.cc \ + fine_atoms.hh \ + formula_parser.cc \ + formula_parser.hh \ + matrix_parser.cc \ + matrix_parser.hh \ + parser_exception.cc \ + parser_exception.hh \ + static_atoms.cc \ + static_atoms.hh \ + static_fine_atoms.cc \ + static_fine_atoms.hh \ + tree.cc \ + tree.hh \ $(GENERATED_FILES) libparser_a_CPPFLAGS = -I../.. $(BOOST_CPPFLAGS) BUILT_SOURCES = $(GENERATED_FILES) -EXTRA_DIST = assign.y csv.y formula.y matrix.y namelist.y assign.lex csv.lex formula.lex matrix.lex namelist.lex +EXTRA_DIST = assign.yy csv.yy formula.yy matrix.yy namelist.yy assign.ll csv.ll formula.ll matrix.ll namelist.ll -%_tab.cc %_tab.hh: %.y +%_tab.cc %_tab.hh: %.yy $(YACC) -d -o$*_tab.cc $< -%_ll.cc: %.lex +%_ll.cc: %.ll $(LEX) -i -o$@ $< diff --git a/dynare++/parser/cc/assign.lex b/dynare++/parser/cc/assign.ll similarity index 97% rename from dynare++/parser/cc/assign.lex rename to dynare++/parser/cc/assign.ll index 2b74f43448d8cc974e31f7ff50359930d3774e0e..e5ef5706c4d8c821446b895e1e776f368334c042 100644 --- a/dynare++/parser/cc/assign.lex +++ b/dynare++/parser/cc/assign.ll @@ -1,5 +1,5 @@ %{ -#include "location.h" +#include "location.hh" #include "assign_tab.hh" extern YYLTYPE asgn_lloc; diff --git a/dynare++/parser/cc/assign.y b/dynare++/parser/cc/assign.yy similarity index 94% rename from dynare++/parser/cc/assign.y rename to dynare++/parser/cc/assign.yy index 83b30218ef48b6f187024da4c74bef80b232a793..3f1c8aeb5061cb960c71fdbece2fa1ef785ea07d 100644 --- a/dynare++/parser/cc/assign.y +++ b/dynare++/parser/cc/assign.yy @@ -1,8 +1,8 @@ %{ /* Copyright (C) 2006-2011, Ondra Kamenik */ -#include "location.h" -#include "atom_assignings.h" +#include "location.hh" +#include "atom_assignings.hh" #include "assign_tab.hh" #include <stdio.h> diff --git a/dynare++/parser/cc/atom_assignings.cc b/dynare++/parser/cc/atom_assignings.cc new file mode 100644 index 0000000000000000000000000000000000000000..b1b51f65c0c6e3bc34d07592feeda13df30c0390 --- /dev/null +++ b/dynare++/parser/cc/atom_assignings.cc @@ -0,0 +1,252 @@ +// Copyright (C) 2006, Ondra Kamenik + +// $Id: atom_assignings.cpp 92 2007-04-19 11:38:21Z ondra $ + +#include "atom_assignings.hh" +#include "location.hh" +#include "parser_exception.hh" + +#include "utils/cc/exception.hh" + +#include <limits> +#include <iostream> + +using namespace ogp; + +AtomAssignings::AtomAssignings(const AtomAssignings &aa, ogp::StaticAtoms &a) + : atoms(a), expr(aa.expr, atoms), left_names(aa.left_names), + order(aa.order) +{ + // fill the lname2expr + for (Tvarintmap::const_iterator it = aa.lname2expr.begin(); + it != aa.lname2expr.end(); ++it) + lname2expr.insert(Tvarintmap::value_type(left_names.query((*it).first), (*it).second)); +} + +/** A global symbol for passing info to the AtomAssignings from + * asgn_parse(). */ +AtomAssignings *aparser; + +/** The declaration of functions defined in asgn_ll.cc and asgn_tab.cc + * generated from assign.lex assign.y */ +void *asgn__scan_buffer(char *, size_t); +void asgn__destroy_buffer(void *); +void asgn_parse(); +extern location_type asgn_lloc; + +void +AtomAssignings::parse(int length, const char *stream) +{ + char *buffer = new char[length+2]; + strncpy(buffer, stream, length); + 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); + aparser = this; + asgn_parse(); + delete [] buffer; + asgn__destroy_buffer(p); +} + +void +AtomAssignings::error(const char *mes) +{ + throw ParserException(mes, asgn_lloc.off); +} + +void +AtomAssignings::add_assignment_to_double(const char *name, double val) +{ + // if left hand side is a registered atom, insert it to tree + int t; + try + { + if (atoms.check(name)) + t = expr.add_nulary(name); + else + t = -1; + } + catch (const ParserException &e) + { + t = -1; + } + // register left hand side in order + order.push_back(t); + + // add the double to the tree + char tmp[100]; + sprintf(tmp, "%30.25g", val); + try + { + expr.parse(strlen(tmp), tmp); + } + catch (const ParserException &e) + { + // should never happen + throw ParserException(string("Error parsing double ")+tmp+": "+e.message(), 0); + } + + // 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)); +} + +void +AtomAssignings::add_assignment(int asgn_off, const char *str, int name_len, + int right_off, int right_len) +{ + // the order of doing things here is important: since the + // FormulaParser requires that all references from the i-th tree + // refere to trees with index lass than i, so to capture also a + // nulary term for the left hand side, it must be inserted to the + // expression tree before the expression is parsed. + + // find the name in the atoms, make copy of name to be able to put + // '\0' at the end + char *buf = new char[name_len+1]; + strncpy(buf, str, name_len); + buf[name_len] = '\0'; + // if left hand side is a registered atom, insert it to tree + int t; + try + { + t = atoms.check(buf); + if (t == -1) + t = expr.add_nulary(buf); + } + catch (const ParserException &e) + { + atoms.register_name(buf); + t = expr.add_nulary(buf); + } + // register left hand side in order + order.push_back(t); + + // parse expression on the right + try + { + expr.parse(right_len, str+right_off); + } + catch (const ParserException &e) + { + throw ParserException(e, asgn_off+right_off); + } + + // register name of the left hand side and put to lname2expr + const char *ss = left_names.insert(buf); + if (lname2expr.find(ss) != lname2expr.end()) + { + // Prevent the occurrence of #415 + std::cerr << "Changing the value of " << ss << " is not supported. Aborting." << std::endl; + exit(EXIT_FAILURE); + } + lname2expr[ss] = order.size()-1; + + // delete name + delete [] buf; +} + +void +AtomAssignings::apply_subst(const AtomSubstitutions::Toldnamemap &mm) +{ + // go through all old variables and see what are their derived new + // variables + for (AtomSubstitutions::Toldnamemap::const_iterator it = mm.begin(); + it != mm.end(); ++it) + { + const char *oldname = (*it).first; + const AtomSubstitutions::Tshiftnameset &sset = (*it).second; + if (!sset.empty()) + { + int told = atoms.index(oldname); + if (told < 0 && !atoms.get_name_storage().query(oldname)) + atoms.register_name(oldname); + if (told == -1) + told = expr.add_nulary(oldname); + // at least one substitution here, so make an expression + expr.add_formula(told); + // say that this expression is not assigned to any atom + order.push_back(-1); + // now go through all new names derived from the old name and + // reference to the newly added formula + for (AtomSubstitutions::Tshiftnameset::const_iterator itt = sset.begin(); + itt != sset.end(); ++itt) + { + const char *newname = (*itt).first; + const char *nn = left_names.insert(newname); + lname2expr.insert(Tvarintmap::value_type(nn, expr.nformulas()-1)); + } + } + } +} + +void +AtomAssignings::print() const +{ + printf("Atom Assignings\nExpressions:\n"); + expr.print(); + printf("Left names:\n"); + for (Tvarintmap::const_iterator it = lname2expr.begin(); + it != lname2expr.end(); ++it) + printf("%s ==> %d (t=%d)\n", (*it).first, expr.formula((*it).second), order[(*it).second]); +} + +void +AtomAsgnEvaluator::setValues(EvalTree &et) const +{ + // set values of constants + aa.atoms.setValues(et); + + // set values of variables to NaN or to user set values + double nan = std::numeric_limits<double>::quiet_NaN(); + for (int i = 0; i < aa.atoms.nvar(); i++) + { + const char *ss = aa.atoms.name(i); + int t = aa.atoms.index(ss); + if (t >= 0) + { + Tusrvalmap::const_iterator it = user_values.find(t); + if (it == user_values.end()) + et.set_nulary(t, nan); + else + et.set_nulary(t, (*it).second); + } + } +} + +void +AtomAsgnEvaluator::set_user_value(const char *name, double val) +{ + int t = aa.atoms.index(name); + if (t >= 0) + { + Tusrvalmap::iterator it = user_values.find(t); + if (it == user_values.end()) + user_values.insert(Tusrvalmap::value_type(t, val)); + else + (*it).second = val; + } +} + +void +AtomAsgnEvaluator::load(int i, double res) +{ + // set the value + operator[](i) = res; + // if i-th expression is atom, set its value to this EvalTree + int t = aa.order[i]; + if (t >= 0) + etree.set_nulary(t, res); +} + +double +AtomAsgnEvaluator::get_value(const char *name) const +{ + AtomAssignings::Tvarintmap::const_iterator it = aa.lname2expr.find(name); + if (it == aa.lname2expr.end()) + return std::numeric_limits<double>::quiet_NaN(); + else + return operator[]((*it).second); +} diff --git a/dynare++/parser/cc/atom_assignings.cpp b/dynare++/parser/cc/atom_assignings.cpp deleted file mode 100644 index 7b688f259a918b4218d982e556ab3ecb77629d22..0000000000000000000000000000000000000000 --- a/dynare++/parser/cc/atom_assignings.cpp +++ /dev/null @@ -1,225 +0,0 @@ -// Copyright (C) 2006, Ondra Kamenik - -// $Id: atom_assignings.cpp 92 2007-04-19 11:38:21Z ondra $ - -#include "atom_assignings.h" -#include "location.h" -#include "parser_exception.h" - -#include "utils/cc/exception.h" - -#include <limits> -#include <iostream> - -using namespace ogp; - -AtomAssignings::AtomAssignings(const AtomAssignings& aa, ogp::StaticAtoms& a) - : atoms(a), expr(aa.expr, atoms), left_names(aa.left_names), - order(aa.order) -{ - // fill the lname2expr - for (Tvarintmap::const_iterator it = aa.lname2expr.begin(); - it != aa.lname2expr.end(); ++it) - lname2expr.insert(Tvarintmap::value_type(left_names.query((*it).first), (*it).second)); -} - -/** A global symbol for passing info to the AtomAssignings from - * asgn_parse(). */ -AtomAssignings* aparser; - -/** The declaration of functions defined in asgn_ll.cc and asgn_tab.cc - * generated from assign.lex assign.y */ -void* asgn__scan_buffer(char*, size_t); -void asgn__destroy_buffer(void*); -void asgn_parse(); -extern location_type asgn_lloc; - -void AtomAssignings::parse(int length, const char* stream) -{ - char* buffer = new char[length+2]; - strncpy(buffer, stream, length); - 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); - aparser = this; - asgn_parse(); - delete [] buffer; - asgn__destroy_buffer(p); -} - -void AtomAssignings::error(const char* mes) -{ - throw ParserException(mes, asgn_lloc.off); -} - -void AtomAssignings::add_assignment_to_double(const char* name, double val) -{ - // if left hand side is a registered atom, insert it to tree - int t; - try { - if (atoms.check(name)) - t = expr.add_nulary(name); - else - t = -1; - } catch (const ParserException& e) { - t = -1; - } - // register left hand side in order - order.push_back(t); - - // add the double to the tree - char tmp[100]; - sprintf(tmp, "%30.25g", val); - try { - expr.parse(strlen(tmp), tmp); - } catch (const ParserException& e) { - // should never happen - throw ParserException(string("Error parsing double ")+tmp+": "+e.message(), 0); - } - - // 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)); -} - -void AtomAssignings::add_assignment(int asgn_off, const char* str, int name_len, - int right_off, int right_len) -{ - // the order of doing things here is important: since the - // FormulaParser requires that all references from the i-th tree - // refere to trees with index lass than i, so to capture also a - // nulary term for the left hand side, it must be inserted to the - // expression tree before the expression is parsed. - - // find the name in the atoms, make copy of name to be able to put - // '\0' at the end - char* buf = new char[name_len+1]; - strncpy(buf, str, name_len); - buf[name_len] = '\0'; - // if left hand side is a registered atom, insert it to tree - int t; - try { - t = atoms.check(buf); - if (t == -1) - t = expr.add_nulary(buf); - } catch (const ParserException& e) { - atoms.register_name(buf); - t = expr.add_nulary(buf); - } - // register left hand side in order - order.push_back(t); - - // parse expression on the right - try { - expr.parse(right_len, str+right_off); - } catch (const ParserException& e) { - throw ParserException(e, asgn_off+right_off); - } - - // register name of the left hand side and put to lname2expr - const char* ss = left_names.insert(buf); - if (lname2expr.find(ss) != lname2expr.end()) { - // Prevent the occurrence of #415 - std::cerr << "Changing the value of " << ss << " is not supported. Aborting." << std::endl; - exit(EXIT_FAILURE); - } - lname2expr[ss] = order.size()-1; - - // delete name - delete [] buf; -} - -void AtomAssignings::apply_subst(const AtomSubstitutions::Toldnamemap& mm) -{ - // go through all old variables and see what are their derived new - // variables - for (AtomSubstitutions::Toldnamemap::const_iterator it = mm.begin(); - it != mm.end(); ++it) { - const char* oldname = (*it).first; - const AtomSubstitutions::Tshiftnameset& sset = (*it).second; - if (! sset.empty()) { - int told = atoms.index(oldname); - if (told < 0 && ! atoms.get_name_storage().query(oldname)) - atoms.register_name(oldname); - if (told == -1) - told = expr.add_nulary(oldname); - // at least one substitution here, so make an expression - expr.add_formula(told); - // say that this expression is not assigned to any atom - order.push_back(-1); - // now go through all new names derived from the old name and - // reference to the newly added formula - for (AtomSubstitutions::Tshiftnameset::const_iterator itt = sset.begin(); - itt != sset.end(); ++itt) { - const char* newname = (*itt).first; - const char* nn = left_names.insert(newname); - lname2expr.insert(Tvarintmap::value_type(nn, expr.nformulas()-1)); - } - } - } -} - -void AtomAssignings::print() const -{ - printf("Atom Assignings\nExpressions:\n"); - expr.print(); - printf("Left names:\n"); - for (Tvarintmap::const_iterator it = lname2expr.begin(); - it != lname2expr.end(); ++it) - printf("%s ==> %d (t=%d)\n", (*it).first, expr.formula((*it).second), order[(*it).second]); -} - -void AtomAsgnEvaluator::setValues(EvalTree& et) const -{ - // set values of constants - aa.atoms.setValues(et); - - // set values of variables to NaN or to user set values - double nan = std::numeric_limits<double>::quiet_NaN(); - for (int i = 0; i < aa.atoms.nvar(); i++) { - const char* ss = aa.atoms.name(i); - int t = aa.atoms.index(ss); - if (t >= 0) { - Tusrvalmap::const_iterator it = user_values.find(t); - if (it == user_values.end()) - et.set_nulary(t, nan); - else - et.set_nulary(t, (*it).second); - } - } -} - -void AtomAsgnEvaluator::set_user_value(const char* name, double val) -{ - int t = aa.atoms.index(name); - if (t >= 0) { - Tusrvalmap::iterator it = user_values.find(t); - if (it == user_values.end()) - user_values.insert(Tusrvalmap::value_type(t, val)); - else - (*it).second = val; - } -} - -void AtomAsgnEvaluator::load(int i, double res) -{ - // set the value - operator[](i) = res; - // if i-th expression is atom, set its value to this EvalTree - int t = aa.order[i]; - if (t >= 0) - etree.set_nulary(t, res); -} - -double AtomAsgnEvaluator::get_value(const char* name) const -{ - AtomAssignings::Tvarintmap::const_iterator it = aa.lname2expr.find(name); - if (it == aa.lname2expr.end()) - return std::numeric_limits<double>::quiet_NaN(); - else - return operator[]((*it).second); -} - - diff --git a/dynare++/parser/cc/atom_assignings.h b/dynare++/parser/cc/atom_assignings.hh similarity index 98% rename from dynare++/parser/cc/atom_assignings.h rename to dynare++/parser/cc/atom_assignings.hh index 14f11b2cbf247d1df5e7d3193ab0e3bbd5b0f0f3..c4c253b1af90cab2ef4351fa288d5277514c220b 100644 --- a/dynare++/parser/cc/atom_assignings.h +++ b/dynare++/parser/cc/atom_assignings.hh @@ -5,9 +5,9 @@ #ifndef OGP_ATOM_ASSIGNINGS_H #define OGP_ATOM_ASSIGNINGS_H -#include "static_atoms.h" -#include "formula_parser.h" -#include "atom_substitutions.h" +#include "static_atoms.hh" +#include "formula_parser.hh" +#include "atom_substitutions.hh" #include <vector> #include <map> diff --git a/dynare++/parser/cc/atom_substitutions.cc b/dynare++/parser/cc/atom_substitutions.cc new file mode 100644 index 0000000000000000000000000000000000000000..6c556ea71f191a35bb718ad7b239505a32007b63 --- /dev/null +++ b/dynare++/parser/cc/atom_substitutions.cc @@ -0,0 +1,300 @@ +// Copyright (C) 2006, Ondra Kamenik + +// $Id: atom_substitutions.cpp 42 2007-01-22 21:53:24Z ondra $ + +#include "atom_substitutions.hh" +#include "utils/cc/exception.hh" + +using namespace ogp; + +AtomSubstitutions::AtomSubstitutions(const AtomSubstitutions &as, const FineAtoms &oa, + FineAtoms &na) + : old_atoms(oa), new_atoms(na) +{ + const NameStorage &ns = na.get_name_storage(); + + // fill new2old + for (Tshiftmap::const_iterator it = as.new2old.begin(); + it != as.new2old.end(); ++it) + new2old.insert(Tshiftmap::value_type(ns.query((*it).first), + Tshiftname(ns.query((*it).second.first), + (*it).second.second))); + // fill old2new + for (Toldnamemap::const_iterator it = as.old2new.begin(); + it != as.old2new.end(); ++it) + { + Tshiftnameset sset; + for (Tshiftnameset::const_iterator itt = (*it).second.begin(); + itt != (*it).second.end(); ++itt) + sset.insert(Tshiftname(ns.query((*itt).first), (*itt).second)); + old2new.insert(Toldnamemap::value_type(ns.query((*it).first), sset)); + } +} + +void +AtomSubstitutions::add_substitution(const char *newname, const char *oldname, int tshift) +{ + // 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 == NULL || oldname == NULL) + 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))); + // insert to old2new map + Toldnamemap::iterator it = old2new.find(oldname); + if (it != old2new.end()) + (*it).second.insert(Tshiftname(newname, -tshift)); + else + { + Tshiftnameset snset; + snset.insert(Tshiftname(newname, -tshift)); + old2new.insert(Toldnamemap::value_type(oldname, snset)); + } + + // put to info + info.num_substs++; +} + +void +AtomSubstitutions::substitutions_finished(VarOrdering::ord_type ot) +{ + // create an external ordering of new_atoms from old_atoms + const vector<const char *> &oa_ext = old_atoms.get_allvar(); + vector<const char *> na_ext; + for (unsigned int i = 0; i < oa_ext.size(); i++) + { + const char *oname = oa_ext[i]; + // add the old name itself + na_ext.push_back(oname); + // add all new names derived from the old name + Toldnamemap::const_iterator it = old2new.find(oname); + if (it != old2new.end()) + for (Tshiftnameset::const_iterator itt = (*it).second.begin(); + itt != (*it).second.end(); ++itt) + na_ext.push_back((*itt).first); + } + + // call parsing finished for the new_atoms + new_atoms.parsing_finished(ot, na_ext); +} + +const char * +AtomSubstitutions::get_new4old(const char *oldname, int tshift) const +{ + Toldnamemap::const_iterator it = old2new.find(oldname); + if (it != old2new.end()) + { + const Tshiftnameset &sset = (*it).second; + for (Tshiftnameset::const_iterator itt = sset.begin(); + itt != sset.end(); ++itt) + if ((*itt).second == -tshift) + return (*itt).first; + } + return NULL; +} + +void +AtomSubstitutions::print() const +{ + printf("Atom Substitutions:\nOld ==> New:\n"); + for (Toldnamemap::const_iterator it = old2new.begin(); it != old2new.end(); ++it) + for (Tshiftnameset::const_iterator itt = (*it).second.begin(); + itt != (*it).second.end(); ++itt) + printf(" %s ==> [%s, %d]\n", (*it).first, (*itt).first, (*itt).second); + + printf("Old <== New:\n"); + for (Tshiftmap::const_iterator it = new2old.begin(); it != new2old.end(); ++it) + printf(" [%s, %d] <== %s\n", (*it).second.first, (*it).second.second, (*it).first); +} + +void +SAtoms::substituteAllLagsAndLeads(FormulaParser &fp, AtomSubstitutions &as) +{ + const char *name; + + int mlead, mlag; + endovarspan(mlead, mlag); + + // substitute all endo lagged more than 1 + while (NULL != (name = findEndoWithLeadInInterval(mlag, -2))) + makeAuxVariables(name, -1, -2, mlag, fp, as); + // substitute all endo leaded more than 1 + while (NULL != (name = findEndoWithLeadInInterval(2, mlead))) + makeAuxVariables(name, 1, 2, mlead, fp, as); + + exovarspan(mlead, mlag); + + // substitute all lagged exo + while (NULL != (name = findExoWithLeadInInterval(mlag, -1))) + makeAuxVariables(name, -1, -1, mlag, fp, as); + // substitute all leaded exo + while (NULL != (name = findExoWithLeadInInterval(1, mlead))) + makeAuxVariables(name, 1, 1, mlead, fp, as); + + // notify that substitution have been finished + as.substitutions_finished(order_type); +} + +void +SAtoms::substituteAllLagsAndExo1Leads(FormulaParser &fp, AtomSubstitutions &as) +{ + const char *name; + + int mlead, mlag; + endovarspan(mlead, mlag); + + // substitute all endo lagged more than 1 + while (NULL != (name = findEndoWithLeadInInterval(mlag, -2))) + makeAuxVariables(name, -1, -2, mlag, fp, as); + + exovarspan(mlead, mlag); + + // substitute all lagged exo + while (NULL != (name = findExoWithLeadInInterval(mlag, -1))) + makeAuxVariables(name, -1, -1, mlag, fp, as); + // substitute all leaded exo by 1 + while (NULL != (name = findExoWithLeadInInterval(1, 1))) + makeAuxVariables(name, 1, 1, 1, fp, as); + + // notify that substitution have been finished + as.substitutions_finished(order_type); +} + +const char * +SAtoms::findNameWithLeadInInterval(const vector<const char *> &names, + int ll1, int ll2) const +{ + for (unsigned int i = 0; i < names.size(); i++) + { + const char *name = names[i]; + DynamicAtoms::Tvarmap::const_iterator it = vars.find(name); + if (it != vars.end()) + { + const DynamicAtoms::Tlagmap &lmap = (*it).second; + for (DynamicAtoms::Tlagmap::const_iterator itt = lmap.begin(); + itt != lmap.end(); ++itt) + if ((*itt).first >= ll1 && (*itt).first <= ll2) + return name; + } + } + + // nothing found + return NULL; +} + +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)); + int iter = 1; + do + { + out = string(str) + '_'; + for (int i = 0; i < iter; i++) + out += c; + if (ll != 0) + out += absll; + iter++; + } + while (varnames.query(out.c_str())); +} + +void +SAtoms::makeAuxVariables(const char *name, int step, int start, int limit_lead, + FormulaParser &fp, AtomSubstitutions &as) +{ + if (!(step == 1 || step == -1)) + throw ogu::Exception(__FILE__, __LINE__, + "Wrong value of step in SAtoms::makeAuxVariables"); + if (step*start > step*limit_lead) + throw ogu::Exception(__FILE__, __LINE__, + "Wrong value of start in SAtoms::makeAuxVariables"); + + // make sure that we do not go further than necessary, this is + // that the limit lead is not behind maxlead or minlag + int mlead, mlag; + varspan(name, mlead, mlag); + if (step == -1) + limit_lead = std::max(limit_lead, mlag); + else + limit_lead = std::min(limit_lead, mlead); + + // 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); + } + + int ll = start; + do + { + // either create atom "a_m2(0)" with tree index taux and add + // equation "a_m2(0)=a(-2)" + // or + // check if "a_m2(0)" has not been already created (with + // different step), in this case do not add equation "a_m2(0) + // = a(-2)" + const char *newname; + string newname_str; + int taux; + if (NULL == (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); + // 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)); + } + else + { + // example: exogenous EPS and occurrence at both EPS(-1) + // EPS(+1) + // first call makeAuxVariables("EPS",1,1,...) will make endo EPS_p0 = EPS + // second call makeAuxVariables("EPS",-1,-1,...) will use this EPS_p0 + // to substitute for EPS(-1) + taux = index(newname, 0); + if (taux < 0) + throw ogu::Exception(__FILE__, __LINE__, + "Couldn't find tree index of previously substituted variable"); + } + + // create atom "a_m2(-1)" or turn "a(-3)" if any to "a_m2(-1)"; tree index t + int t = index(name, ll); + if (t == -1) + { + // no "a(-3)", make t <-> a_m2(-1) + sprintf(tmp, "%s(%d)", newname, step); + t = fp.add_nulary(tmp); + } + else + { + // turn a(-3) to a_m2(-1) + unassign_variable(name, ll, t); + assign_variable(newname, step, t); + } + + // next iteration starts with tprev <-> "a_m2(-1)" (this will be made equal to "a_m3(0)") + tprev = t; + + ll += step; + } + while (step*ll <= step*limit_lead); +} diff --git a/dynare++/parser/cc/atom_substitutions.cpp b/dynare++/parser/cc/atom_substitutions.cpp deleted file mode 100644 index e6fd79ba38c34dc57514a9f4c54f34bc2e701506..0000000000000000000000000000000000000000 --- a/dynare++/parser/cc/atom_substitutions.cpp +++ /dev/null @@ -1,275 +0,0 @@ -// Copyright (C) 2006, Ondra Kamenik - -// $Id: atom_substitutions.cpp 42 2007-01-22 21:53:24Z ondra $ - -#include "atom_substitutions.h" -#include "utils/cc/exception.h" - -using namespace ogp; - -AtomSubstitutions::AtomSubstitutions(const AtomSubstitutions& as, const FineAtoms& oa, - FineAtoms& na) - : old_atoms(oa), new_atoms(na) -{ - const NameStorage& ns = na.get_name_storage(); - - // fill new2old - for (Tshiftmap::const_iterator it = as.new2old.begin(); - it != as.new2old.end(); ++it) - new2old.insert(Tshiftmap::value_type(ns.query((*it).first), - Tshiftname(ns.query((*it).second.first), - (*it).second.second))); - // fill old2new - for (Toldnamemap::const_iterator it = as.old2new.begin(); - it != as.old2new.end(); ++it) { - Tshiftnameset sset; - for (Tshiftnameset::const_iterator itt = (*it).second.begin(); - itt != (*it).second.end(); ++itt) - sset.insert(Tshiftname(ns.query((*itt).first), (*itt).second)); - old2new.insert(Toldnamemap::value_type(ns.query((*it).first), sset)); - } -} - - -void AtomSubstitutions::add_substitution(const char* newname, const char* oldname, int tshift) -{ - // 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 == NULL || oldname == NULL) - 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))); - // insert to old2new map - Toldnamemap::iterator it = old2new.find(oldname); - if (it != old2new.end()) - (*it).second.insert(Tshiftname(newname, -tshift)); - else { - Tshiftnameset snset; - snset.insert(Tshiftname(newname, -tshift)); - old2new.insert(Toldnamemap::value_type(oldname, snset)); - } - - // put to info - info.num_substs++; -} - -void AtomSubstitutions::substitutions_finished(VarOrdering::ord_type ot) -{ - // create an external ordering of new_atoms from old_atoms - const vector<const char*>& oa_ext = old_atoms.get_allvar(); - vector<const char*> na_ext; - for (unsigned int i = 0; i < oa_ext.size(); i++) { - const char* oname = oa_ext[i]; - // add the old name itself - na_ext.push_back(oname); - // add all new names derived from the old name - Toldnamemap::const_iterator it = old2new.find(oname); - if (it != old2new.end()) - for (Tshiftnameset::const_iterator itt = (*it).second.begin(); - itt != (*it).second.end(); ++itt) - na_ext.push_back((*itt).first); - } - - // call parsing finished for the new_atoms - new_atoms.parsing_finished(ot, na_ext); -} - -const char* AtomSubstitutions::get_new4old(const char* oldname, int tshift) const -{ - Toldnamemap::const_iterator it = old2new.find(oldname); - if (it != old2new.end()) { - const Tshiftnameset& sset = (*it).second; - for (Tshiftnameset::const_iterator itt = sset.begin(); - itt != sset.end(); ++itt) - if ((*itt).second == - tshift) - return (*itt).first; - } - return NULL; -} - -void AtomSubstitutions::print() const -{ - printf("Atom Substitutions:\nOld ==> New:\n"); - for (Toldnamemap::const_iterator it = old2new.begin(); it != old2new.end(); ++it) - for (Tshiftnameset::const_iterator itt = (*it).second.begin(); - itt != (*it).second.end(); ++itt) - printf(" %s ==> [%s, %d]\n", (*it).first, (*itt).first, (*itt).second); - - printf("Old <== New:\n"); - for (Tshiftmap::const_iterator it = new2old.begin(); it != new2old.end(); ++it) - printf(" [%s, %d] <== %s\n", (*it).second.first, (*it).second.second, (*it).first); -} - -void SAtoms::substituteAllLagsAndLeads(FormulaParser& fp, AtomSubstitutions& as) -{ - const char* name; - - int mlead, mlag; - endovarspan(mlead, mlag); - - // substitute all endo lagged more than 1 - while (NULL != (name = findEndoWithLeadInInterval(mlag, -2))) - makeAuxVariables(name, -1, -2, mlag, fp, as); - // substitute all endo leaded more than 1 - while (NULL != (name = findEndoWithLeadInInterval(2, mlead))) - makeAuxVariables(name, 1, 2, mlead, fp, as); - - exovarspan(mlead, mlag); - - // substitute all lagged exo - while (NULL != (name = findExoWithLeadInInterval(mlag, -1))) - makeAuxVariables(name, -1, -1, mlag, fp, as); - // substitute all leaded exo - while (NULL != (name = findExoWithLeadInInterval(1, mlead))) - makeAuxVariables(name, 1, 1, mlead, fp, as); - - // notify that substitution have been finished - as.substitutions_finished(order_type); -} - -void SAtoms::substituteAllLagsAndExo1Leads(FormulaParser& fp, AtomSubstitutions& as) -{ - const char* name; - - int mlead, mlag; - endovarspan(mlead, mlag); - - // substitute all endo lagged more than 1 - while (NULL != (name = findEndoWithLeadInInterval(mlag, -2))) - makeAuxVariables(name, -1, -2, mlag, fp, as); - - exovarspan(mlead, mlag); - - // substitute all lagged exo - while (NULL != (name = findExoWithLeadInInterval(mlag, -1))) - makeAuxVariables(name, -1, -1, mlag, fp, as); - // substitute all leaded exo by 1 - while (NULL != (name = findExoWithLeadInInterval(1,1))) - makeAuxVariables(name, 1, 1, 1, fp, as); - - // notify that substitution have been finished - as.substitutions_finished(order_type); -} - -const char* SAtoms::findNameWithLeadInInterval(const vector<const char*>& names, - int ll1, int ll2) const -{ - for (unsigned int i = 0; i < names.size(); i++) { - const char* name = names[i]; - DynamicAtoms::Tvarmap::const_iterator it = vars.find(name); - if (it != vars.end()) { - const DynamicAtoms::Tlagmap& lmap = (*it).second; - for (DynamicAtoms::Tlagmap::const_iterator itt = lmap.begin(); - itt != lmap.end(); ++itt) - if ((*itt).first >= ll1 && (*itt).first <= ll2) - return name; - } - } - - // nothing found - return NULL; -} - -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)); - int iter = 1; - do { - out = string(str) + '_'; - for (int i = 0; i < iter; i++) - out += c; - if (ll != 0) - out += absll; - iter++; - } while (varnames.query(out.c_str())); -} - -void SAtoms::makeAuxVariables(const char* name, int step, int start, int limit_lead, - FormulaParser& fp, AtomSubstitutions& as) -{ - if (! (step == 1 || step == -1)) - throw ogu::Exception(__FILE__,__LINE__, - "Wrong value of step in SAtoms::makeAuxVariables"); - if (step*start > step*limit_lead) - throw ogu::Exception(__FILE__,__LINE__, - "Wrong value of start in SAtoms::makeAuxVariables"); - - // make sure that we do not go further than necessary, this is - // that the limit lead is not behind maxlead or minlag - int mlead, mlag; - varspan(name, mlead, mlag); - if (step == -1) - limit_lead = std::max(limit_lead, mlag); - else - limit_lead = std::min(limit_lead, mlead); - - // 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); - } - - int ll = start; - do { - // either create atom "a_m2(0)" with tree index taux and add - // equation "a_m2(0)=a(-2)" - // or - // check if "a_m2(0)" has not been already created (with - // different step), in this case do not add equation "a_m2(0) - // = a(-2)" - const char* newname; - string newname_str; - int taux; - if (NULL == (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); - // 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)); - } else { - // example: exogenous EPS and occurrence at both EPS(-1) - // EPS(+1) - // first call makeAuxVariables("EPS",1,1,...) will make endo EPS_p0 = EPS - // second call makeAuxVariables("EPS",-1,-1,...) will use this EPS_p0 - // to substitute for EPS(-1) - taux = index(newname, 0); - if (taux < 0) - throw ogu::Exception(__FILE__,__LINE__, - "Couldn't find tree index of previously substituted variable"); - } - - // create atom "a_m2(-1)" or turn "a(-3)" if any to "a_m2(-1)"; tree index t - int t = index(name, ll); - if (t == -1) { - // no "a(-3)", make t <-> a_m2(-1) - sprintf(tmp, "%s(%d)", newname, step); - t = fp.add_nulary(tmp); - } else { - // turn a(-3) to a_m2(-1) - unassign_variable(name, ll, t); - assign_variable(newname, step, t); - } - - // next iteration starts with tprev <-> "a_m2(-1)" (this will be made equal to "a_m3(0)") - tprev = t; - - ll += step; - } while (step*ll <= step*limit_lead); -} diff --git a/dynare++/parser/cc/atom_substitutions.h b/dynare++/parser/cc/atom_substitutions.hh similarity index 99% rename from dynare++/parser/cc/atom_substitutions.h rename to dynare++/parser/cc/atom_substitutions.hh index a0e060960d7e3abbdfd73c82bc67ed391d4d99a3..9e44ae4e8171a4a7c6895ec149b0ed4756beae89 100644 --- a/dynare++/parser/cc/atom_substitutions.h +++ b/dynare++/parser/cc/atom_substitutions.hh @@ -5,7 +5,7 @@ #ifndef OGP_ATOM_SUBSTITUTIONS_H #define OGP_ATOM_SUBSTITUTIONS_H -#include "fine_atoms.h" +#include "fine_atoms.hh" #include <string> diff --git a/dynare++/parser/cc/csv.lex b/dynare++/parser/cc/csv.ll similarity index 95% rename from dynare++/parser/cc/csv.lex rename to dynare++/parser/cc/csv.ll index a81a277d57a7cb46370517822157dc0b5af6f70c..86adee640e0e31425dad767cbb946cb5f3e3e8d9 100644 --- a/dynare++/parser/cc/csv.lex +++ b/dynare++/parser/cc/csv.ll @@ -1,7 +1,7 @@ %{ // Copyright (C) 2007-2011, Ondra Kamenik -#include "location.h" +#include "location.hh" #include "csv_tab.hh" extern YYLTYPE csv_lloc; diff --git a/dynare++/parser/cc/csv.y b/dynare++/parser/cc/csv.yy similarity index 93% rename from dynare++/parser/cc/csv.y rename to dynare++/parser/cc/csv.yy index c0dcfeba5994232bd0f37adae140bfed54d07ba5..09f458ee38c998ada521f7789cb5047ae3fa7277 100644 --- a/dynare++/parser/cc/csv.y +++ b/dynare++/parser/cc/csv.yy @@ -1,6 +1,6 @@ %{ -#include "location.h" -#include "csv_parser.h" +#include "location.hh" +#include "csv_parser.hh" #include "csv_tab.hh" void csv_error(const char*); diff --git a/dynare++/parser/cc/csv_parser.cc b/dynare++/parser/cc/csv_parser.cc new file mode 100644 index 0000000000000000000000000000000000000000..96f6eaf5db405d70034c90fe22b48972f4820bc4 --- /dev/null +++ b/dynare++/parser/cc/csv_parser.cc @@ -0,0 +1,44 @@ +#include "csv_parser.hh" +#include "parser_exception.hh" +#include "location.hh" +#include "csv_tab.hh" +#include <cstring> + +using namespace ogp; + +/** A global symbol for passing info to the CSVParser from + * csv_parse(). */ +CSVParser *csv_parser; + +/** The declaration of functions defined in csv_ll.cc and + * csv_tab.cc generated from csv.lex and csv.y. */ +void *csv__scan_buffer(char *, unsigned int); +void csv__destroy_buffer(void *); +int csv_parse(); + +extern ogp::location_type csv_lloc; + +void +CSVParser::csv_error(const char *mes) +{ + throw ParserException(mes, csv_lloc.off); +} + +void +CSVParser::csv_parse(int length, const char *str) +{ + // allocate temporary buffer and parse + char *buffer = new char[length+2]; + strncpy(buffer, str, length); + 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); + csv_parser = this; + ::csv_parse(); + delete [] buffer; + csv__destroy_buffer(p); + parsed_string = NULL; +} diff --git a/dynare++/parser/cc/csv_parser.cpp b/dynare++/parser/cc/csv_parser.cpp deleted file mode 100644 index 93f6c3374847cf2806e8c759ff1db361c5a7783f..0000000000000000000000000000000000000000 --- a/dynare++/parser/cc/csv_parser.cpp +++ /dev/null @@ -1,42 +0,0 @@ -#include "csv_parser.h" -#include "parser_exception.h" -#include "location.h" -#include "csv_tab.hh" -#include <cstring> - -using namespace ogp; - -/** A global symbol for passing info to the CSVParser from - * csv_parse(). */ -CSVParser* csv_parser; - -/** The declaration of functions defined in csv_ll.cc and - * csv_tab.cc generated from csv.lex and csv.y. */ -void* csv__scan_buffer(char*, unsigned int); -void csv__destroy_buffer(void*); -int csv_parse(); - -extern ogp::location_type csv_lloc; - -void CSVParser::csv_error(const char* mes) -{ - throw ParserException(mes, csv_lloc.off); -} - -void CSVParser::csv_parse(int length, const char* str) -{ - // allocate temporary buffer and parse - char* buffer = new char[length+2]; - strncpy(buffer, str, length); - 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); - csv_parser = this; - ::csv_parse(); - delete [] buffer; - csv__destroy_buffer(p); - parsed_string = NULL; -} diff --git a/dynare++/parser/cc/csv_parser.h b/dynare++/parser/cc/csv_parser.hh similarity index 100% rename from dynare++/parser/cc/csv_parser.h rename to dynare++/parser/cc/csv_parser.hh diff --git a/dynare++/parser/cc/dynamic_atoms.cc b/dynare++/parser/cc/dynamic_atoms.cc new file mode 100644 index 0000000000000000000000000000000000000000..d8f4241096dd354f9776016876abfb2ddda45f0a --- /dev/null +++ b/dynare++/parser/cc/dynamic_atoms.cc @@ -0,0 +1,710 @@ +// Copyright (C) 2005, Ondra Kamenik + +// $Id: dynamic_atoms.cpp 1362 2007-07-10 11:50:18Z kamenik $ + +#include "utils/cc/exception.hh" +#include "dynamic_atoms.hh" + +#include <cstring> +#include <climits> + +using namespace ogp; + +NameStorage::NameStorage(const NameStorage &stor) +{ + for (unsigned int i = 0; i < stor.name_store.size(); i++) + { + char *str = new char[strlen(stor.name_store[i])+1]; + strcpy(str, stor.name_store[i]); + name_store.push_back(str); + name_set.insert(str); + } +} + +NameStorage::~NameStorage() +{ + while (name_store.size() > 0) + { + delete [] name_store.back(); + name_store.pop_back(); + } +} + +const char * +NameStorage::query(const char *name) const +{ + set<const char *, ltstr>::const_iterator it = name_set.find(name); + if (it == name_set.end()) + return NULL; + else + return (*it); +} + +const char * +NameStorage::insert(const char *name) +{ + set<const char *, ltstr>::const_iterator it = name_set.find(name); + if (it == name_set.end()) + { + char *str = new char[strlen(name)+1]; + strcpy(str, name); + name_store.push_back(str); + name_set.insert(str); + return str; + } + else + { + return (*it); + } +} + +void +NameStorage::print() const +{ + for (unsigned int i = 0; i < name_store.size(); i++) + printf("%s\n", name_store[i]); +} + +void +Constants::import_constants(const Constants &c, OperationTree &otree, Tintintmap &tmap) +{ + for (Tconstantmap::const_iterator it = c.cmap.begin(); + it != c.cmap.end(); ++it) + { + int told = (*it).first; + int tnew = otree.add_nulary(); + tmap.insert(Tintintmap::value_type(told, tnew)); + add_constant(tnew, (*it).second); + } +} + +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); +} + +void +Constants::add_constant(int t, double val) +{ + cmap.insert(Tconstantmap::value_type(t, val)); + cinvmap.insert(Tconstantinvmap::value_type(val, t)); +} + +bool +Constants::is_constant(int t) const +{ + if (t < OperationTree::num_constants) + return true; + Tconstantmap::const_iterator it = cmap.find(t); + return (it != cmap.end()); +} + +double +Constants::get_constant_value(int t) const +{ + Tconstantmap::const_iterator it = cmap.find(t); + if (it != cmap.end()) + return (*it).second; + else + { + throw ogu::Exception(__FILE__, __LINE__, + "Tree index is not constant in Constants::get_constant_value"); + return 0; + } +} + +int +Constants::check(const char *str) const +{ + double d; + sscanf(str, "%lf", &d); + Tconstantinvmap::const_iterator it = cinvmap.find(d); + if (it != cinvmap.end()) + return (*it).second; + else + return -1; +} + +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); +} + +DynamicAtoms::DynamicAtoms() + : nv(0), minlag(INT_MAX), maxlead(INT_MIN) +{ +} + +DynamicAtoms::DynamicAtoms(const DynamicAtoms &da) + : Constants(da), + varnames(da.varnames), vars(), indices(), + nv(da.nv), minlag(da.minlag), maxlead(da.maxlead) +{ + // copy vars + for (Tvarmap::const_iterator it = da.vars.begin(); + it != da.vars.end(); ++it) + vars.insert(Tvarmap::value_type(varnames.query((*it).first), + (*it).second)); + // copy indices + for (Tindexmap::const_iterator it = da.indices.begin(); + it != da.indices.end(); ++it) + indices.insert(Tindexmap::value_type((*it).first, + varnames.query((*it).second))); +} + +int +DynamicAtoms::check(const char *name) const +{ + if (is_string_constant(name)) + return Constants::check(name); + + return check_variable(name); +} + +int +DynamicAtoms::check_variable(const char *name) const +{ + string str; + int ll; + parse_variable(name, str, ll); + Tvarmap::const_iterator it = vars.find(str.c_str()); + + if (it != vars.end()) + { + const Tlagmap &lmap = (*it).second; + Tlagmap::const_iterator itt = lmap.find(ll); + if (itt != lmap.end()) + return (*itt).second; + } + return -1; +} + +void +DynamicAtoms::assign(const char *name, int t) +{ + if (is_string_constant(name)) + assign_constant(name, t); + else + assign_variable(name, t); +} + +void +DynamicAtoms::assign_constant(const char *name, int t) +{ + double val; + sscanf(name, "%lf", &val); + add_constant(t, val); +} + +// parse the name and then call assing_variable(varname, ll, t) + +void +DynamicAtoms::assign_variable(const char *name, int t) +{ + int ll; + string str; + parse_variable(name, str, ll); + // here str is just name without lead/lag + const char *ss = varnames.insert(str.c_str()); + + assign_variable(ss, ll, t); +} + +void +DynamicAtoms::assign_variable(const char *varname, int ll, int t) +{ + if (indices.end() != indices.find(t)) + throw ogu::Exception(__FILE__, __LINE__, + "Attempt to assign already allocated tree index"); + + Tvarmap::iterator it = vars.find(varname); + if (it != vars.end()) + { + 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)); + } + else + { + Tlagmap lmap; + lmap.insert(Tlagmap::value_type(ll, t)); + vars.insert(Tvarmap::value_type(varname, lmap)); + } + indices.insert(Tindexmap::value_type(t, varname)); + + nv++; + if (ll < minlag) + minlag = ll; + if (ll > maxlead) + maxlead = ll; +} + +void +DynamicAtoms::unassign_variable(const char *varname, int ll, int t) +{ + Tvarmap::iterator it = vars.find(varname); + if (it != vars.end()) + { + Tlagmap &lmap = (*it).second; + Tlagmap::iterator itt = lmap.find(ll); + if (itt != lmap.end()) + { + if ((*itt).second == t) + { + // erase it from the lagmap; if it becomes empty, + // erase the lagmap from varmap + lmap.erase(itt); + if (lmap.size() == 0) + vars.erase(it); + // erase it from the indices + Tindexmap::iterator ittt = indices.find(t); + if (ittt != indices.end()) + indices.erase(ittt); + + nv--; + if (ll == minlag || ll == maxlead) + update_minmaxll(); + } + else + throw ogu::Exception(__FILE__, __LINE__, + "Tree index inconsistent in DynamicAtoms::unassign_variable"); + } + else + throw ogu::Exception(__FILE__, __LINE__, + "Lead/lag of the variable not found in DynamicAtoms::unassign_variable"); + } + else + throw ogu::Exception(__FILE__, __LINE__, + "Variable not found in DynamicAtoms::unassign_variable"); +} + +void +DynamicAtoms::update_minmaxll() +{ + minlag = INT_MAX; + maxlead = INT_MIN; + for (Tvarmap::const_iterator it = vars.begin(); it != vars.end(); ++it) + { + const Tlagmap &lmap = (*it).second; + for (Tlagmap::const_iterator itt = lmap.begin(); itt != lmap.end(); ++itt) + { + int ll = (*itt).first; + if (ll < minlag) + minlag = ll; + if (ll > maxlead) + maxlead = ll; + } + } +} + +vector<int> +DynamicAtoms::variables() const +{ + vector<int> res; + for (Tvarmap::const_iterator it = vars.begin(); + it != vars.end(); ++it) + { + const Tlagmap &lmap = (*it).second; + for (Tlagmap::const_iterator itt = lmap.begin(); + itt != lmap.end(); ++itt) + res.push_back((*itt).second); + } + return res; +} + +void +DynamicAtoms::varspan(int t, int &mlead, int &mlag) const +{ + Tindexmap::const_iterator it = indices.find(t); + if (indices.end() == it) + { + mlead = INT_MIN; + mlag = INT_MAX; + return; + } + varspan((*it).second, mlead, mlag); +} + +void +DynamicAtoms::varspan(const char *name, int &mlead, int &mlag) const +{ + Tvarmap::const_iterator it = vars.find(name); + if (vars.end() == it) + { + mlead = INT_MIN; + mlag = INT_MAX; + return; + } + const Tlagmap &lmap = (*it).second; + Tlagmap::const_iterator beg = lmap.begin(); + Tlagmap::const_reverse_iterator end = lmap.rbegin(); + 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; + for (unsigned int i = 0; i < names.size(); i++) + { + int lag, lead; + varspan(names[i], lead, lag); + if (lead > mlead) + mlead = lead; + if (lag < mlag) + mlag = lag; + } +} + +bool +DynamicAtoms::is_named_atom(int t) const +{ + return (indices.end() != indices.find(t)); +} + +int +DynamicAtoms::index(const char *name, int ll) const +{ + Tvarmap::const_iterator it = vars.find(name); + if (vars.end() != it) + { + const Tlagmap &lmap = (*it).second; + Tlagmap::const_iterator itt = lmap.find(ll); + if (lmap.end() != itt) + return (*itt).second; + } + return -1; +} + +bool +DynamicAtoms::is_referenced(const char *name) const +{ + Tvarmap::const_iterator it = vars.find(name); + return it != vars.end(); +} + +const DynamicAtoms::Tlagmap & +DynamicAtoms::lagmap(const char *name) const +{ + Tvarmap::const_iterator it = vars.find(name); + if (vars.end() == it) + throw ogu::Exception(__FILE__, __LINE__, + std::string("Couldn't find the name ") + + name + " in DynamicAtoms::lagmap"); + return (*it).second; +} + +const char * +DynamicAtoms::name(int t) const +{ + Tindexmap::const_iterator it = indices.find(t); + if (indices.end() == it) + throw ogu::Exception(__FILE__, __LINE__, + "Couldn't find tree index in DynamicAtoms::name"); + return (*it).second; +} + +int +DynamicAtoms::lead(int t) const +{ + const char *nam = name(t); + const Tlagmap &lmap = lagmap(nam); + Tlagmap::const_iterator it = lmap.begin(); + 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; +} + +void +DynamicAtoms::print() const +{ + printf("names:\n"); + varnames.print(); + printf("constants:\n"); + Constants::print(); + printf("variables:\n"); + for (Tvarmap::const_iterator it = vars.begin(); + it != vars.end(); ++it) + { + const Tlagmap &lmap = (*it).second; + for (Tlagmap::const_iterator itt = lmap.begin(); + itt != lmap.end(); ++itt) + printf("$%d: %s(%d)\n", (*itt).second, (*it).first, (*itt).first); + } + printf("indices:\n"); + for (Tindexmap::const_iterator it = indices.begin(); + it != indices.end(); ++it) + printf("t=%d ==> %s\n", (*it).first, (*it).second); +} + +/** Note that the str has been parsed by the lexicographic + * analyzer. It can be either a variable or a double. So it is easy to + * recognize it by the first character. */ +bool +DynamicAtoms::is_string_constant(const char *str) +{ + return str[0] == '.' || str[0] == '-' || (str[0] >= '0' && str[0] <= '9'); +} + +VarOrdering::VarOrdering(const VarOrdering &vo, const vector<const char *> &vnames, + const DynamicAtoms &a) + : n_stat(vo.n_stat), n_pred(vo.n_pred), n_both(vo.n_both), n_forw(vo.n_forw), + der_atoms(vo.der_atoms), positions(vo.positions), + outer2y(vo.outer2y), y2outer(vo.y2outer), varnames(vnames), atoms(a) +{ +} + +bool +VarOrdering::check(int t) const +{ + map<int, int>::const_iterator it = positions.find(t); + return it != positions.end(); +} + +int +VarOrdering::get_pos_of(int t) const +{ + map<int, int>::const_iterator it = positions.find(t); + if (it != positions.end()) + { + return (*it).second; + } + else + { + throw ogu::Exception(__FILE__, __LINE__, + "Couldn't find the tree index in VarOrdering::get_pos_of"); + return -1; + } +} + +void +VarOrdering::do_general(ord_type ordering) +{ + // auxiliary vectors for setting der_atoms and map + vector<int> pred_minus; + vector<int> both_minus; + vector<int> stat; + vector<int> pred_pad; + vector<int> both_pad; + vector<int> forw_pad; + vector<int> both_plus; + vector<int> forw_plus; + + // auxiliary vectors for setting y2outer and outer2y + vector<int> y2o_stat; + vector<int> y2o_pred; + vector<int> y2o_both; + vector<int> y2o_forw; + + for (unsigned int i = 0; i < varnames.size(); i++) + { + const char *ss = varnames[i]; + int lead; + int lag; + atoms.varspan(ss, lead, lag); + if (lag == 0 && lead == 0) + { + stat.push_back(atoms.index(ss, 0)); + y2o_stat.push_back(i); + } + else if (lag == -1 && lead < 1) + { + pred_minus.push_back(atoms.index(ss, -1)); + pred_pad.push_back(atoms.index(ss, 0)); + y2o_pred.push_back(i); + } + else if (lag > -1 && lead == 1) + { + forw_pad.push_back(atoms.index(ss, 0)); + forw_plus.push_back(atoms.index(ss, 1)); + y2o_forw.push_back(i); + } + else if (lag == -1 && lead == 1) + { + both_minus.push_back(atoms.index(ss, -1)); + both_pad.push_back(atoms.index(ss, 0)); + both_plus.push_back(atoms.index(ss, 1)); + y2o_both.push_back(i); + } + else + { + throw ogu::Exception(__FILE__, __LINE__, + "A wrong lag/lead of a variable in VarOrdering::do_pbspbfbf"); + } + } + + // here we fill ords according to ordering + vector<int> *ords[8]; + if (ordering == pbspbfbf) + { + ords[0] = &pred_minus; + ords[1] = &both_minus; + ords[2] = &stat; + ords[3] = &pred_pad; + ords[4] = &both_pad; + ords[5] = &forw_pad; + ords[6] = &both_plus; + ords[7] = &forw_plus; + } + else if (ordering == bfspbfpb) + { + ords[0] = &both_plus; + ords[1] = &forw_plus; + ords[2] = &stat; + ords[3] = &pred_pad; + ords[4] = &both_pad; + ords[5] = &forw_pad; + ords[6] = &pred_minus; + ords[7] = &both_minus; + } + else // BEWARE: when implementing a new ordering, check also a + {// code below setting y2outer + throw ogu::Exception(__FILE__, __LINE__, + "Ordering not implemented in VarOrdering::do_general"); + } + + // make der_atoms and positions + int off = 0; + for (unsigned int i = 0; i < 8; i++) + for (unsigned int j = 0; j < (ords[i])->size(); j++, off++) + if ((*(ords[i]))[j] != -1) + { + der_atoms.push_back((*(ords[i]))[j]); + positions.insert(std::pair<int, int>((*(ords[i]))[j], off)); + } + + // set integer constants + n_stat = stat.size(); + n_pred = pred_pad.size(); + n_both = both_pad.size(); + n_forw = forw_pad.size(); + + // make y2outer mapping + y2outer.insert(y2outer.end(), y2o_stat.begin(), y2o_stat.end()); + y2outer.insert(y2outer.end(), y2o_pred.begin(), y2o_pred.end()); + y2outer.insert(y2outer.end(), y2o_both.begin(), y2o_both.end()); + y2outer.insert(y2outer.end(), y2o_forw.begin(), y2o_forw.end()); + // make outer2y mapping + outer2y.resize(y2outer.size(), -1); + for (unsigned int i = 0; i < y2outer.size(); i++) + outer2y[y2outer[i]] = i; +} + +void +VarOrdering::do_increasing_time() +{ + // get maxlead and minlag of the variables + int mlag, mlead; + atoms.varspan(varnames, mlead, mlag); + // 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); + for (unsigned int iv = 0; iv < varnames.size(); iv++) + { + try + { + const DynamicAtoms::Tlagmap &lmap = atoms.lagmap(varnames[iv]); + for (DynamicAtoms::Tlagmap::const_iterator it = lmap.begin(); + it != lmap.end(); ++it) + { + int ll = (*it).first; + int t = (*it).second; + tree_ind[ll-mlag][iv] = t; + } + } + catch (const ogu::Exception &e) + { + // ignore the error of not found variable in the tree + } + } + + // setup der_atoms and positions + for (int ll = mlag; ll <= mlead; ll++) + for (unsigned int iv = 0; iv < varnames.size(); iv++) + { + int t = tree_ind[ll-mlag][iv]; + if (t != -1) + { + der_atoms.push_back(t); + int pos = (ll-mlag)*varnames.size() + iv; + positions.insert(map<int, int>::value_type(t, pos)); + } + } + + // set outer2y and y2outer to identities + for (unsigned int iv = 0; iv < varnames.size(); iv++) + { + outer2y.push_back(iv); + y2outer.push_back(iv); + } + + // set n_stat, n_pred, n_both, and n_forw + for (unsigned int iv = 0; iv < varnames.size(); iv++) + { + int mmlag, mmlead; + atoms.varspan(varnames[iv], mmlead, mmlag); + if (mmlead == 0 && mmlag == 0) + { + n_stat++; + } + else if (mmlead <= 0 && mmlag < 0) + { + n_pred++; + } + else if (mmlead > 0 && mmlag >= 0) + { + n_forw++; + } + else if (mmlead > 0 && mmlag < 0) + { + n_both++; + } + else if (mmlead < mmlag) + { + // 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"); + } + } +} + +void +VarOrdering::print() const +{ + printf("nstat=%d, npred=%d, nboth=%d, nforw=%d\n", n_stat, n_pred, n_both, n_forw); + printf("der_atoms:\n"); + for (unsigned int i = 0; i < der_atoms.size(); i++) + printf(" %d", der_atoms[i]); + printf("\nmap:\n"); + for (map<int, int>::const_iterator it = positions.begin(); it != positions.end(); ++it) + printf(" [%d->%d]", (*it).first, (*it).second); + printf("\ny2outer:\n"); + for (unsigned int i = 0; i < y2outer.size(); i++) + printf(" %d", y2outer[i]); + printf("\nouter2y:\n"); + for (unsigned int i = 0; i < outer2y.size(); i++) + printf(" %d", outer2y[i]); + printf("\n"); +} + +// Local Variables: +// mode:C++ +// End: diff --git a/dynare++/parser/cc/dynamic_atoms.cpp b/dynare++/parser/cc/dynamic_atoms.cpp deleted file mode 100644 index ca6b6dcd219158d9faf22f76da01c2c5ea460332..0000000000000000000000000000000000000000 --- a/dynare++/parser/cc/dynamic_atoms.cpp +++ /dev/null @@ -1,615 +0,0 @@ -// Copyright (C) 2005, Ondra Kamenik - -// $Id: dynamic_atoms.cpp 1362 2007-07-10 11:50:18Z kamenik $ - -#include "utils/cc/exception.h" -#include "dynamic_atoms.h" - -#include <cstring> -#include <climits> - -using namespace ogp; - -NameStorage::NameStorage(const NameStorage& stor) -{ - for (unsigned int i = 0; i < stor.name_store.size(); i++) { - char* str = new char[strlen(stor.name_store[i])+1]; - strcpy(str, stor.name_store[i]); - name_store.push_back(str); - name_set.insert(str); - } -} - -NameStorage::~NameStorage() -{ - while (name_store.size() > 0) { - delete [] name_store.back(); - name_store.pop_back(); - } -} - -const char* NameStorage::query(const char* name) const -{ - set<const char*, ltstr>::const_iterator it = name_set.find(name); - if (it == name_set.end()) - return NULL; - else - return (*it); -} - -const char* NameStorage::insert(const char* name) -{ - set<const char*, ltstr>::const_iterator it = name_set.find(name); - if (it == name_set.end()) { - char* str = new char[strlen(name)+1]; - strcpy(str, name); - name_store.push_back(str); - name_set.insert(str); - return str; - } else { - return (*it); - } -} - -void NameStorage::print() const -{ - for (unsigned int i = 0; i < name_store.size(); i++) - printf("%s\n", name_store[i]); -} - -void Constants::import_constants(const Constants& c, OperationTree& otree, Tintintmap& tmap) -{ - for (Tconstantmap::const_iterator it = c.cmap.begin(); - it != c.cmap.end(); ++it) { - int told = (*it).first; - int tnew = otree.add_nulary(); - tmap.insert(Tintintmap::value_type(told, tnew)); - add_constant(tnew, (*it).second); - } -} - -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); -} - -void Constants::add_constant(int t, double val) -{ - cmap.insert(Tconstantmap::value_type(t, val)); - cinvmap.insert(Tconstantinvmap::value_type(val, t)); -} - -bool Constants::is_constant(int t) const -{ - if (t < OperationTree::num_constants) - return true; - Tconstantmap::const_iterator it = cmap.find(t); - return (it != cmap.end()); -} - -double Constants::get_constant_value(int t) const -{ - Tconstantmap::const_iterator it = cmap.find(t); - if (it != cmap.end()) - return (*it).second; - else { - throw ogu::Exception(__FILE__,__LINE__, - "Tree index is not constant in Constants::get_constant_value"); - return 0; - } -} - -int Constants::check(const char* str) const -{ - double d; - sscanf(str, "%lf", &d); - Tconstantinvmap::const_iterator it = cinvmap.find(d); - if (it != cinvmap.end()) - return (*it).second; - else - return -1; -} - -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); -} - - -DynamicAtoms::DynamicAtoms() - : nv(0), minlag(INT_MAX), maxlead(INT_MIN) -{ -} - -DynamicAtoms::DynamicAtoms(const DynamicAtoms& da) - : Constants(da), - varnames(da.varnames), vars(), indices(), - nv(da.nv), minlag(da.minlag), maxlead(da.maxlead) -{ - // copy vars - for (Tvarmap::const_iterator it = da.vars.begin(); - it != da.vars.end(); ++it) - vars.insert(Tvarmap::value_type(varnames.query((*it).first), - (*it).second)); - // copy indices - for (Tindexmap::const_iterator it = da.indices.begin(); - it != da.indices.end(); ++it) - indices.insert(Tindexmap::value_type((*it).first, - varnames.query((*it).second))); -} - - -int DynamicAtoms::check(const char* name) const -{ - if (is_string_constant(name)) - return Constants::check(name); - - return check_variable(name); -} - -int DynamicAtoms::check_variable(const char* name) const -{ - string str; - int ll; - parse_variable(name, str, ll); - Tvarmap::const_iterator it = vars.find(str.c_str()); - - if (it != vars.end()) { - const Tlagmap& lmap = (*it).second; - Tlagmap::const_iterator itt = lmap.find(ll); - if (itt != lmap.end()) - return (*itt).second; - } - return -1; -} - - -void DynamicAtoms::assign(const char* name, int t) -{ - if (is_string_constant(name)) - assign_constant(name, t); - else - assign_variable(name, t); -} - -void DynamicAtoms::assign_constant(const char* name, int t) -{ - double val; - sscanf(name, "%lf", &val); - add_constant(t, val); -} - -// parse the name and then call assing_variable(varname, ll, t) - -void DynamicAtoms::assign_variable(const char* name, int t) -{ - int ll; - string str; - parse_variable(name, str, ll); - // here str is just name without lead/lag - const char* ss = varnames.insert(str.c_str()); - - assign_variable(ss, ll, t); -} - -void DynamicAtoms::assign_variable(const char* varname, int ll, int t) -{ - if (indices.end() != indices.find(t)) - throw ogu::Exception(__FILE__,__LINE__, - "Attempt to assign already allocated tree index"); - - Tvarmap::iterator it = vars.find(varname); - if (it != vars.end()) { - 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)); - } else { - Tlagmap lmap; - lmap.insert(Tlagmap::value_type(ll, t)); - vars.insert(Tvarmap::value_type(varname, lmap)); - } - indices.insert(Tindexmap::value_type(t, varname)); - - nv++; - if (ll < minlag) - minlag = ll; - if (ll > maxlead) - maxlead = ll; -} - -void DynamicAtoms::unassign_variable(const char* varname, int ll, int t) -{ - Tvarmap::iterator it = vars.find(varname); - if (it != vars.end()) { - Tlagmap& lmap = (*it).second; - Tlagmap::iterator itt = lmap.find(ll); - if (itt != lmap.end()) { - if ((*itt).second == t) { - // erase it from the lagmap; if it becomes empty, - // erase the lagmap from varmap - lmap.erase(itt); - if (lmap.size() == 0) - vars.erase(it); - // erase it from the indices - Tindexmap::iterator ittt = indices.find(t); - if (ittt != indices.end()) - indices.erase(ittt); - - nv--; - if (ll == minlag || ll == maxlead) - update_minmaxll(); - } else - throw ogu::Exception(__FILE__,__LINE__, - "Tree index inconsistent in DynamicAtoms::unassign_variable"); - } else - throw ogu::Exception(__FILE__,__LINE__, - "Lead/lag of the variable not found in DynamicAtoms::unassign_variable"); - } else - throw ogu::Exception(__FILE__,__LINE__, - "Variable not found in DynamicAtoms::unassign_variable"); -} - -void DynamicAtoms::update_minmaxll() -{ - minlag = INT_MAX; - maxlead =INT_MIN; - for (Tvarmap::const_iterator it = vars.begin(); it != vars.end(); ++it) { - const Tlagmap& lmap = (*it).second; - for (Tlagmap::const_iterator itt = lmap.begin(); itt != lmap.end(); ++itt) { - int ll = (*itt).first; - if (ll < minlag) - minlag = ll; - if (ll > maxlead) - maxlead = ll; - } - } -} - -vector<int> DynamicAtoms::variables() const -{ - vector<int> res; - for (Tvarmap::const_iterator it = vars.begin(); - it != vars.end(); ++it) { - const Tlagmap& lmap = (*it).second; - for (Tlagmap::const_iterator itt = lmap.begin(); - itt != lmap.end(); ++itt) - res.push_back((*itt).second); - } - return res; -} - -void DynamicAtoms::varspan(int t, int& mlead, int& mlag) const -{ - Tindexmap::const_iterator it = indices.find(t); - if (indices.end() == it) { - mlead = INT_MIN; - mlag = INT_MAX; - return; - } - varspan((*it).second, mlead, mlag); -} - -void DynamicAtoms::varspan(const char* name, int& mlead, int& mlag) const -{ - Tvarmap::const_iterator it = vars.find(name); - if (vars.end() == it) { - mlead = INT_MIN; - mlag = INT_MAX; - return; - } - const Tlagmap& lmap = (*it).second; - Tlagmap::const_iterator beg = lmap.begin(); - Tlagmap::const_reverse_iterator end = lmap.rbegin(); - 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; - for (unsigned int i = 0; i < names.size(); i++) { - int lag, lead; - varspan(names[i], lead, lag); - if (lead > mlead) - mlead = lead; - if (lag < mlag) - mlag = lag; - } -} - -bool DynamicAtoms::is_named_atom(int t) const -{ - return (indices.end() != indices.find(t)); -} - -int DynamicAtoms::index(const char* name, int ll) const -{ - Tvarmap::const_iterator it = vars.find(name); - if (vars.end() != it) { - const Tlagmap& lmap = (*it).second; - Tlagmap::const_iterator itt = lmap.find(ll); - if (lmap.end() != itt) - return (*itt).second; - } - return -1; -} - -bool DynamicAtoms::is_referenced(const char* name) const -{ - Tvarmap::const_iterator it = vars.find(name); - return it != vars.end(); -} - -const DynamicAtoms::Tlagmap& DynamicAtoms::lagmap(const char* name) const -{ - Tvarmap::const_iterator it = vars.find(name); - if (vars.end() == it) - throw ogu::Exception(__FILE__,__LINE__, - std::string("Couldn't find the name ") - + name + " in DynamicAtoms::lagmap"); - return (*it).second; -} - -const char* DynamicAtoms::name(int t) const -{ - Tindexmap::const_iterator it = indices.find(t); - if (indices.end() == it) - throw ogu::Exception(__FILE__,__LINE__, - "Couldn't find tree index in DynamicAtoms::name"); - return (*it).second; -} - -int DynamicAtoms::lead(int t) const -{ - const char* nam = name(t); - const Tlagmap& lmap = lagmap(nam); - Tlagmap::const_iterator it = lmap.begin(); - 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; -} - -void DynamicAtoms::print() const -{ - printf("names:\n"); - varnames.print(); - printf("constants:\n"); - Constants::print(); - printf("variables:\n"); - for (Tvarmap::const_iterator it = vars.begin(); - it != vars.end(); ++it) { - const Tlagmap& lmap = (*it).second; - for (Tlagmap::const_iterator itt = lmap.begin(); - itt != lmap.end(); ++itt) - printf("$%d: %s(%d)\n", (*itt).second, (*it).first, (*itt).first); - } - printf("indices:\n"); - for (Tindexmap::const_iterator it = indices.begin(); - it != indices.end(); ++it) - printf("t=%d ==> %s\n", (*it).first, (*it).second); -} - -/** Note that the str has been parsed by the lexicographic - * analyzer. It can be either a variable or a double. So it is easy to - * recognize it by the first character. */ -bool DynamicAtoms::is_string_constant(const char* str) -{ - return str[0] == '.' || str[0] == '-' || (str[0] >= '0' && str[0] <= '9'); -} - -VarOrdering::VarOrdering(const VarOrdering& vo, const vector<const char*>& vnames, - const DynamicAtoms& a) - : n_stat(vo.n_stat), n_pred(vo.n_pred), n_both(vo.n_both), n_forw(vo.n_forw), - der_atoms(vo.der_atoms), positions(vo.positions), - outer2y(vo.outer2y), y2outer(vo.y2outer), varnames(vnames), atoms(a) -{ -} - -bool VarOrdering::check(int t) const -{ - map<int,int>::const_iterator it = positions.find(t); - return it != positions.end(); -} - -int VarOrdering::get_pos_of(int t) const -{ - map<int,int>::const_iterator it = positions.find(t); - if (it != positions.end()) { - return (*it).second; - } else { - throw ogu::Exception(__FILE__,__LINE__, - "Couldn't find the tree index in VarOrdering::get_pos_of"); - return -1; - } -} - -void VarOrdering::do_general(ord_type ordering) -{ - // auxiliary vectors for setting der_atoms and map - vector<int> pred_minus; - vector<int> both_minus; - vector<int> stat; - vector<int> pred_pad; - vector<int> both_pad; - vector<int> forw_pad; - vector<int> both_plus; - vector<int> forw_plus; - - // auxiliary vectors for setting y2outer and outer2y - vector<int> y2o_stat; - vector<int> y2o_pred; - vector<int> y2o_both; - vector<int> y2o_forw; - - for (unsigned int i = 0; i < varnames.size(); i++) { - const char* ss = varnames[i]; - int lead; - int lag; - atoms.varspan(ss, lead, lag); - if (lag == 0 && lead == 0) { - stat.push_back(atoms.index(ss, 0)); - y2o_stat.push_back(i); - } else if (lag == -1 && lead < 1) { - pred_minus.push_back(atoms.index(ss, -1)); - pred_pad.push_back(atoms.index(ss, 0)); - y2o_pred.push_back(i); - } else if (lag > -1 && lead == 1) { - forw_pad.push_back(atoms.index(ss, 0)); - forw_plus.push_back(atoms.index(ss, 1)); - y2o_forw.push_back(i); - } else if (lag == -1 && lead == 1) { - both_minus.push_back(atoms.index(ss, -1)); - both_pad.push_back(atoms.index(ss, 0)); - both_plus.push_back(atoms.index(ss, 1)); - y2o_both.push_back(i); - } else { - throw ogu::Exception(__FILE__,__LINE__, - "A wrong lag/lead of a variable in VarOrdering::do_pbspbfbf"); - } - } - - // here we fill ords according to ordering - vector<int>* ords[8]; - if (ordering == pbspbfbf) { - ords[0] = &pred_minus; - ords[1] = &both_minus; - ords[2] = &stat; - ords[3] = &pred_pad; - ords[4] = &both_pad; - ords[5] = &forw_pad; - ords[6] = &both_plus; - ords[7] = &forw_plus; - } else if (ordering == bfspbfpb) { - ords[0] = &both_plus; - ords[1] = &forw_plus; - ords[2] = &stat; - ords[3] = &pred_pad; - ords[4] = &both_pad; - ords[5] = &forw_pad; - ords[6] = &pred_minus; - ords[7] = &both_minus; - } else { // BEWARE: when implementing a new ordering, check also a - // code below setting y2outer - throw ogu::Exception(__FILE__,__LINE__, - "Ordering not implemented in VarOrdering::do_general"); - } - - // make der_atoms and positions - int off = 0; - for (unsigned int i = 0; i < 8; i++) - for (unsigned int j = 0; j < (ords[i])->size(); j++, off++) - if ((*(ords[i]))[j] != -1) { - der_atoms.push_back((*(ords[i]))[j]); - positions.insert(std::pair<int,int>((*(ords[i]))[j], off)); - } - - // set integer constants - n_stat = stat.size(); - n_pred = pred_pad.size(); - n_both = both_pad.size(); - n_forw = forw_pad.size(); - - // make y2outer mapping - y2outer.insert(y2outer.end(), y2o_stat.begin(), y2o_stat.end()); - y2outer.insert(y2outer.end(), y2o_pred.begin(), y2o_pred.end()); - y2outer.insert(y2outer.end(), y2o_both.begin(), y2o_both.end()); - y2outer.insert(y2outer.end(), y2o_forw.begin(), y2o_forw.end()); - // make outer2y mapping - outer2y.resize(y2outer.size(), -1); - for (unsigned int i = 0; i < y2outer.size(); i++) - outer2y[y2outer[i]] = i; -} - -void VarOrdering::do_increasing_time() -{ - // get maxlead and minlag of the variables - int mlag, mlead; - atoms.varspan(varnames, mlead, mlag); - // 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); - for (unsigned int iv = 0; iv < varnames.size(); iv++) { - try { - const DynamicAtoms::Tlagmap& lmap = atoms.lagmap(varnames[iv]); - for (DynamicAtoms::Tlagmap::const_iterator it = lmap.begin(); - it != lmap.end(); ++it) { - int ll = (*it).first; - int t = (*it).second; - tree_ind[ll-mlag][iv] = t; - } - } catch (const ogu::Exception& e) { - // ignore the error of not found variable in the tree - } - } - - // setup der_atoms and positions - for (int ll = mlag; ll <= mlead; ll++) - for (unsigned int iv = 0; iv < varnames.size(); iv++) { - int t = tree_ind[ll-mlag][iv]; - if (t != -1) { - der_atoms.push_back(t); - int pos = (ll-mlag)*varnames.size() + iv; - positions.insert(map<int,int>::value_type(t, pos)); - } - } - - // set outer2y and y2outer to identities - for (unsigned int iv = 0; iv < varnames.size(); iv++) { - outer2y.push_back(iv); - y2outer.push_back(iv); - } - - // set n_stat, n_pred, n_both, and n_forw - for (unsigned int iv = 0; iv < varnames.size(); iv++) { - int mmlag, mmlead; - atoms.varspan(varnames[iv], mmlead, mmlag); - if (mmlead == 0 && mmlag == 0) { - n_stat++; - } else if (mmlead <= 0 && mmlag < 0) { - n_pred++; - } else if (mmlead > 0 && mmlag >=0) { - n_forw++; - } else if (mmlead > 0 && mmlag < 0) { - n_both++; - } else if (mmlead < mmlag) { - // 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"); - } - } -} - -void VarOrdering::print() const -{ - printf("nstat=%d, npred=%d, nboth=%d, nforw=%d\n", n_stat, n_pred, n_both, n_forw); - printf("der_atoms:\n"); - for (unsigned int i = 0; i < der_atoms.size(); i++) - printf(" %d", der_atoms[i]); - printf("\nmap:\n"); - for (map<int,int>::const_iterator it = positions.begin(); it != positions.end(); ++it) - printf(" [%d->%d]", (*it).first, (*it).second); - printf("\ny2outer:\n"); - for (unsigned int i = 0; i < y2outer.size(); i++) - printf(" %d", y2outer[i]); - printf("\nouter2y:\n"); - for (unsigned int i = 0; i < outer2y.size(); i++) - printf(" %d", outer2y[i]); - printf("\n"); -} - -// Local Variables: -// mode:C++ -// End: diff --git a/dynare++/parser/cc/dynamic_atoms.h b/dynare++/parser/cc/dynamic_atoms.hh similarity index 99% rename from dynare++/parser/cc/dynamic_atoms.h rename to dynare++/parser/cc/dynamic_atoms.hh index cf28da2ef67b5e74b9125919c6bc251881d09a21..e4dd3714c643979cb6a8f60877c24bdc36f4ae86 100644 --- a/dynare++/parser/cc/dynamic_atoms.h +++ b/dynare++/parser/cc/dynamic_atoms.hh @@ -5,7 +5,7 @@ #ifndef OGP_DYNAMIC_ATOMS_H #define OGP_DYNAMIC_ATOMS_H -#include "formula_parser.h" +#include "formula_parser.hh" #include <vector> #include <map> diff --git a/dynare++/parser/cc/fine_atoms.cc b/dynare++/parser/cc/fine_atoms.cc new file mode 100644 index 0000000000000000000000000000000000000000..2080452f837caf5348564a8bb58136fdfc73997a --- /dev/null +++ b/dynare++/parser/cc/fine_atoms.cc @@ -0,0 +1,555 @@ +// Copyright (C) 2005, Ondra Kamenik + +// $Id: fine_atoms.cpp 1759 2008-03-31 14:25:20Z kamenik $ + +#include "utils/cc/exception.hh" + +#include "parser_exception.hh" +#include "fine_atoms.hh" + +using namespace ogp; + +AllvarOuterOrdering::AllvarOuterOrdering(const vector<const char *> &allvar_outer, + const FineAtoms &a) + : atoms(a), allvar(), + endo2all(a.get_endovars().size(), -1), + exo2all(a.get_exovars().size(), -1) +{ + // fill in the allvar from allvar_outer + for (unsigned int i = 0; i < allvar_outer.size(); i++) + { + const char *s = atoms.varnames.query(allvar_outer[i]); + if (s) + allvar.push_back(s); + else + throw ogu::Exception(__FILE__, __LINE__, + string("Variable ") + allvar_outer[i] + " is not a declared symbol in AllvarOuterOrdering constructor"); + } + + // fill in endo2all and exo2all + for (unsigned int i = 0; i < allvar.size(); i++) + { + Tvarintmap::const_iterator it = atoms.endo_outer_map.find(allvar[i]); + if (it != atoms.endo_outer_map.end()) + endo2all[(*it).second] = i; + else + { + it = atoms.exo_outer_map.find(allvar[i]); + if (it != atoms.exo_outer_map.end()) + exo2all[(*it).second] = i; + else + throw ogu::Exception(__FILE__, __LINE__, + string("Name ") + allvar[i] + " is neither endogenous nor exogenous variable in AllvarOuterOrdering constructor"); + } + } + + // check whether everything has been filled + unsigned int iendo = 0; + while (iendo < endo2all.size() && endo2all[iendo] != -1) + iendo++; + unsigned int iexo = 0; + while (iexo < exo2all.size() && exo2all[iexo] != -1) + iexo++; + if (iendo < endo2all.size()) + throw ogu::Exception(__FILE__, __LINE__, + string("Endogenous variable ") + atoms.get_endovars()[iendo] + +" not found in outer all ordering in AllvarOuterOrdering constructor"); + if (iexo < exo2all.size()) + throw ogu::Exception(__FILE__, __LINE__, + string("Exogenous variable ") + atoms.get_exovars()[iexo] + +" not found in outer all ordering in AllvarOuterOrdering constructor"); +} + +AllvarOuterOrdering::AllvarOuterOrdering(const AllvarOuterOrdering &avo, + const FineAtoms &a) + : atoms(a), allvar(), + endo2all(avo.endo2all), + exo2all(avo.exo2all) +{ + // fill in the allvar from avo.allvar + for (unsigned int i = 0; i < avo.allvar.size(); i++) + { + const char *s = atoms.varnames.query(avo.allvar[i]); + allvar.push_back(s); + } +} + +FineAtoms::FineAtoms(const FineAtoms &fa) + : DynamicAtoms(fa), params(), endovars(), exovars(), + endo_order(NULL), exo_order(NULL), allvar_order(NULL), + der_atoms(fa.der_atoms), + endo_atoms_map(fa.endo_atoms_map), + exo_atoms_map(fa.exo_atoms_map) +{ + // fill in params + for (unsigned int i = 0; i < fa.params.size(); i++) + { + const char *s = varnames.query(fa.params[i]); + if (!s) + throw ogu::Exception(__FILE__, __LINE__, + string("Parameter ") + fa.params[i] + " does not exist in FineAtoms copy cosntructor"); + params.push_back(s); + param_outer_map.insert(Tvarintmap::value_type(s, params.size()-1)); + } + // fill in endovars + for (unsigned int i = 0; i < fa.endovars.size(); i++) + { + const char *s = varnames.query(fa.endovars[i]); + if (!s) + throw ogu::Exception(__FILE__, __LINE__, + string("Endo variable ") + fa.endovars[i] + " does not exist in FineAtoms copy constructor"); + endovars.push_back(s); + endo_outer_map.insert(Tvarintmap::value_type(s, endovars.size()-1)); + } + // fill in exovars + for (unsigned int i = 0; i < fa.exovars.size(); i++) + { + const char *s = varnames.query(fa.exovars[i]); + if (!s) + throw ogu::Exception(__FILE__, __LINE__, + string("Exo variable ") + fa.exovars[i] + " does not exist in FineAtoms copy cosntructor"); + exovars.push_back(s); + exo_outer_map.insert(Tvarintmap::value_type(s, exovars.size()-1)); + } + + if (fa.endo_order) + endo_order = fa.endo_order->clone(endovars, *this); + + if (fa.exo_order) + exo_order = fa.exo_order->clone(exovars, *this); + + if (fa.allvar_order) + allvar_order = new AllvarOuterOrdering(*(fa.allvar_order), *this); +} + +int +FineAtoms::check_variable(const char *name) const +{ + string str; + int ll; + parse_variable(name, str, ll); + if (varnames.query(str.c_str())) + return DynamicAtoms::check_variable(name); + else + { + throw ParserException(string("Variable <")+str+"> not declared.", 0); + return -1; + } +} + +int +FineAtoms::num_exo_periods() const +{ + int mlead, mlag; + exovarspan(mlead, mlag); + return mlead-mlag+1; +} + +void +FineAtoms::parsing_finished(VarOrdering::ord_type ot) +{ + make_internal_orderings(ot); + + // by default, concatenate outer endo and outer exo and make it as + // allvar outer: + vector<const char *> allvar_tmp; + 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); +} + +void +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); +} + +const vector<const char *> & +FineAtoms::get_allvar() const +{ + if (!allvar_order) + throw ogu::Exception(__FILE__, __LINE__, + "FineAtoms::get_allvars called before parsing_finished"); + + return allvar_order->get_allvar(); +} + +const vector<int> & +FineAtoms::outer_endo2all() const +{ + if (!allvar_order) + throw ogu::Exception(__FILE__, __LINE__, + "FineAtoms::outer_endo2all called before parsing_finished"); + + return allvar_order->get_endo2all(); +} + +const vector<int> & +FineAtoms::outer_exo2all() const +{ + if (!allvar_order) + throw ogu::Exception(__FILE__, __LINE__, + "FineAtoms::outer_exo2all called before parsing_finished"); + + return allvar_order->get_exo2all(); +} + +vector<int> +FineAtoms::variables() const +{ + if (endo_order) + { + return der_atoms; + } + else + { + throw ogu::Exception(__FILE__, __LINE__, + "FineAtoms::variables called before parsing_finished"); + return vector<int>(); + } +} + +int +FineAtoms::nstat() const +{ + if (endo_order) + { + return endo_order->nstat(); + } + else + { + throw ogu::Exception(__FILE__, __LINE__, + "FineAtoms::nstat called before parsing_finished"); + return -1; + } +} + +int +FineAtoms::npred() const +{ + if (endo_order) + { + return endo_order->npred(); + } + else + { + throw ogu::Exception(__FILE__, __LINE__, + "FineAtoms::npred called before parsing_finished"); + return -1; + } +} + +int +FineAtoms::nboth() const +{ + if (endo_order) + { + return endo_order->nboth(); + } + else + { + throw ogu::Exception(__FILE__, __LINE__, + "FineAtoms::nboth called before parsing_finished"); + return -1; + } +} + +int +FineAtoms::nforw() const +{ + if (endo_order) + { + return endo_order->nforw(); + } + else + { + throw ogu::Exception(__FILE__, __LINE__, + "FineAtoms::nforw called before parsing_finished"); + return -1; + } +} + +int +FineAtoms::get_pos_of_endo(int t) const +{ + if (endo_order) + { + return endo_order->get_pos_of(t); + } + else + { + throw ogu::Exception(__FILE__, __LINE__, + "FineAtoms::get_pos_of_endo called before parsing_finished"); + return -1; + } +} + +int +FineAtoms::get_pos_of_exo(int t) const +{ + if (exo_order) + { + return exo_order->get_pos_of(t); + } + else + { + throw ogu::Exception(__FILE__, __LINE__, + "FineAtoms::get_pos_of_exo called before parsing_finished"); + return -1; + } +} + +int +FineAtoms::get_pos_of_all(int t) const +{ + if (endo_order && exo_order) + { + if (endo_order->check(t)) + return endo_order->get_pos_of(t); + else if (exo_order->check(t)) + return endo_order->length() + exo_order->get_pos_of(t); + else + { + throw ogu::Exception(__FILE__, __LINE__, + "Atom is not endo nor exo in FineAtoms::get_pos_of_all"); + return -1; + } + } + else + { + throw ogu::Exception(__FILE__, __LINE__, + "FineAtoms::get_pos_of_exo called before parsing_finished"); + return -1; + } +} + +const vector<int> & +FineAtoms::y2outer_endo() const +{ + if (!endo_order) + throw ogu::Exception(__FILE__, __LINE__, + "FineAtoms::y2outer_endo called before parsing_finished"); + return endo_order->get_y2outer(); +} + +const vector<int> & +FineAtoms::outer2y_endo() const +{ + if (!endo_order) + throw ogu::Exception(__FILE__, __LINE__, + "FineAtoms::outer2y_endo called before parsing_finished"); + return endo_order->get_outer2y(); +} + +const vector<int> & +FineAtoms::y2outer_exo() const +{ + if (!exo_order) + throw ogu::Exception(__FILE__, __LINE__, + "FineAtoms::y2outer_endo called before parsing_finished"); + return exo_order->get_y2outer(); +} + +const vector<int> & +FineAtoms::outer2y_exo() const +{ + if (!exo_order) + throw ogu::Exception(__FILE__, __LINE__, + "FineAtoms::outer2y_exo called before parsing_finished"); + return exo_order->get_outer2y(); +} + +const vector<int> & +FineAtoms::get_endo_atoms_map() const +{ + if (!endo_order) + throw ogu::Exception(__FILE__, __LINE__, + "FineAtoms::get_endo_atoms_map called before parsing_finished"); + return endo_atoms_map; +} + +const vector<int> & +FineAtoms::get_exo_atoms_map() const +{ + if (!exo_order) + throw ogu::Exception(__FILE__, __LINE__, + "FineAtoms::get_exo_atoms_map called before parsing_finished"); + return exo_atoms_map; +} + +int +FineAtoms::name2outer_param(const char *name) const +{ + Tvarintmap::const_iterator it = param_outer_map.find(name); + if (it == param_outer_map.end()) + throw ogu::Exception(__FILE__, __LINE__, + "Name is not a parameter in FineAtoms::name2outer_param"); + return (*it).second; +} + +int +FineAtoms::name2outer_endo(const char *name) const +{ + Tvarintmap::const_iterator it = endo_outer_map.find(name); + if (it == endo_outer_map.end()) + throw ogu::Exception(__FILE__, __LINE__, + "Name is not an endogenous variable in FineAtoms::name2outer_endo"); + return (*it).second; +} + +int +FineAtoms::name2outer_exo(const char *name) const +{ + Tvarintmap::const_iterator it = exo_outer_map.find(name); + if (it == exo_outer_map.end()) + throw ogu::Exception(__FILE__, __LINE__, + "Name is not an exogenous variable in FineAtoms::name2outer_exo"); + return (*it).second; +} + +int +FineAtoms::name2outer_allvar(const char *name) const +{ + if (!allvar_order) + throw ogu::Exception(__FILE__, __LINE__, + "FineAtoms::name2outer_allvar called beore parsing_finished"); + + Tvarintmap::const_iterator it = endo_outer_map.find(name); + if (it != endo_outer_map.end()) + 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]; + } + + throw ogu::Exception(__FILE__, __LINE__, + string("Name ") + name + " is neither endo nor exo variable in FineAtoms::name2outer_allvar"); + return -1; +} + +void +FineAtoms::register_uniq_endo(const char *name) +{ + if (varnames.query(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)); +} + +void +FineAtoms::register_uniq_exo(const char *name) +{ + if (varnames.query(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)); +} + +void +FineAtoms::register_uniq_param(const char *name) +{ + if (varnames.query(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)); +} + +void +FineAtoms::make_internal_orderings(VarOrdering::ord_type ot) +{ + bool endo_ordering_done = false; + bool exo_ordering_done = false; + + order_type = ot; + + int mlead, mlag; + endovarspan(mlead, mlag); + if (mlag >= -1 && mlead <= 1) + { + // make endo ordering + if (endo_order) + delete endo_order; + if (ot == VarOrdering::pbspbfbf) + endo_order = new EndoVarOrdering1(endovars, *this); + else + endo_order = new EndoVarOrdering2(endovars, *this); + endo_order->do_ordering(); + endo_ordering_done = true; + } + + exovarspan(mlead, mlag); + if (mlag == 0 && mlead == 0) + { + // make exo ordering + if (exo_order) + delete exo_order; + exo_order = new ExoVarOrdering(exovars, *this); + exo_order->do_ordering(); + exo_ordering_done = true; + } + + if (endo_ordering_done && exo_ordering_done) + { + // concatenate der atoms from endo_order and exo_order + der_atoms.clear(); + der_atoms.insert(der_atoms.end(), + endo_order->get_der_atoms().begin(), + endo_order->get_der_atoms().end()); + der_atoms.insert(der_atoms.end(), + exo_order->get_der_atoms().begin(), + exo_order->get_der_atoms().end()); + + // create endo_atoms_map; der_atoms is a concatenation, so it is easy + int endo_atoms = endo_order->get_der_atoms().size(); + endo_atoms_map.clear(); + for (int i = 0; i < endo_atoms; i++) + endo_atoms_map.push_back(i); + // create exo_atoms_map + int exo_atoms = exo_order->get_der_atoms().size(); + exo_atoms_map.clear(); + for (int i = 0; i < exo_atoms; i++) + exo_atoms_map.push_back(endo_atoms + i); + } +} + +void +FineAtoms::print() const +{ + DynamicAtoms::print(); + if (endo_order) + { + printf("Endo ordering:\n"); + endo_order->print(); + } + else + { + printf("Endo ordering not created.\n"); + } + if (exo_order) + { + printf("Exo ordering:\n"); + exo_order->print(); + } + else + { + 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("exo atoms map:\n"); + for (unsigned int i = 0; i < exo_atoms_map.size(); i++) + printf("%d --> %d\n", i, exo_atoms_map[i]); +} diff --git a/dynare++/parser/cc/fine_atoms.cpp b/dynare++/parser/cc/fine_atoms.cpp deleted file mode 100644 index 17920b8ad5e1b6c456dcae40ac9044da5fb43a96..0000000000000000000000000000000000000000 --- a/dynare++/parser/cc/fine_atoms.cpp +++ /dev/null @@ -1,482 +0,0 @@ -// Copyright (C) 2005, Ondra Kamenik - -// $Id: fine_atoms.cpp 1759 2008-03-31 14:25:20Z kamenik $ - -#include "utils/cc/exception.h" - -#include "parser_exception.h" -#include "fine_atoms.h" - -using namespace ogp; - -AllvarOuterOrdering::AllvarOuterOrdering(const vector<const char*>& allvar_outer, - const FineAtoms& a) - : atoms(a), allvar(), - endo2all(a.get_endovars().size(), -1), - exo2all(a.get_exovars().size(), -1) -{ - // fill in the allvar from allvar_outer - for (unsigned int i = 0; i < allvar_outer.size(); i++) { - const char* s = atoms.varnames.query(allvar_outer[i]); - if (s) - allvar.push_back(s); - else - throw ogu::Exception(__FILE__, __LINE__, - string("Variable ") + allvar_outer[i] + " is not a declared symbol in AllvarOuterOrdering constructor"); - } - - // fill in endo2all and exo2all - for (unsigned int i = 0; i < allvar.size(); i++) { - Tvarintmap::const_iterator it = atoms.endo_outer_map.find(allvar[i]); - if (it != atoms.endo_outer_map.end()) - endo2all[(*it).second] = i; - else { - it = atoms.exo_outer_map.find(allvar[i]); - if (it != atoms.exo_outer_map.end()) - exo2all[(*it).second] = i; - else - throw ogu::Exception(__FILE__, __LINE__, - string("Name ") + allvar[i] + " is neither endogenous nor exogenous variable in AllvarOuterOrdering constructor"); - } - } - - // check whether everything has been filled - unsigned int iendo = 0; - while (iendo < endo2all.size() && endo2all[iendo] != -1) iendo++; - unsigned int iexo = 0; - while (iexo < exo2all.size() && exo2all[iexo] != -1) iexo++; - if (iendo < endo2all.size()) - throw ogu::Exception(__FILE__, __LINE__, - string("Endogenous variable ") + atoms.get_endovars()[iendo] + - " not found in outer all ordering in AllvarOuterOrdering constructor"); - if (iexo < exo2all.size()) - throw ogu::Exception(__FILE__, __LINE__, - string("Exogenous variable ") + atoms.get_exovars()[iexo] + - " not found in outer all ordering in AllvarOuterOrdering constructor"); -} - -AllvarOuterOrdering::AllvarOuterOrdering(const AllvarOuterOrdering& avo, - const FineAtoms& a) - : atoms(a), allvar(), - endo2all(avo.endo2all), - exo2all(avo.exo2all) -{ - // fill in the allvar from avo.allvar - for (unsigned int i = 0; i < avo.allvar.size(); i++) { - const char* s = atoms.varnames.query(avo.allvar[i]); - allvar.push_back(s); - } -} - - -FineAtoms::FineAtoms(const FineAtoms& fa) - : DynamicAtoms(fa), params(), endovars(), exovars(), - endo_order(NULL), exo_order(NULL), allvar_order(NULL), - der_atoms(fa.der_atoms), - endo_atoms_map(fa.endo_atoms_map), - exo_atoms_map(fa.exo_atoms_map) -{ - // fill in params - for (unsigned int i = 0; i < fa.params.size(); i++) { - const char* s = varnames.query(fa.params[i]); - if (! s) - throw ogu::Exception(__FILE__, __LINE__, - string("Parameter ") + fa.params[i] + " does not exist in FineAtoms copy cosntructor"); - params.push_back(s); - param_outer_map.insert(Tvarintmap::value_type(s, params.size()-1)); - } - // fill in endovars - for (unsigned int i = 0; i < fa.endovars.size(); i++) { - const char* s = varnames.query(fa.endovars[i]); - if (! s) - throw ogu::Exception(__FILE__, __LINE__, - string("Endo variable ") + fa.endovars[i] + " does not exist in FineAtoms copy constructor"); - endovars.push_back(s); - endo_outer_map.insert(Tvarintmap::value_type(s, endovars.size()-1)); - } - // fill in exovars - for (unsigned int i = 0; i < fa.exovars.size(); i++) { - const char* s = varnames.query(fa.exovars[i]); - if (! s) - throw ogu::Exception(__FILE__, __LINE__, - string("Exo variable ") + fa.exovars[i] + " does not exist in FineAtoms copy cosntructor"); - exovars.push_back(s); - exo_outer_map.insert(Tvarintmap::value_type(s, exovars.size()-1)); - } - - if (fa.endo_order) - endo_order = fa.endo_order->clone(endovars, *this); - - if (fa.exo_order) - exo_order = fa.exo_order->clone(exovars, *this); - - if (fa.allvar_order) - allvar_order = new AllvarOuterOrdering(*(fa.allvar_order), *this); -} - -int FineAtoms::check_variable(const char* name) const -{ - string str; - int ll; - parse_variable(name, str, ll); - if (varnames.query(str.c_str())) - return DynamicAtoms::check_variable(name); - else { - throw ParserException(string("Variable <")+str+"> not declared.",0); - return -1; - } -} - -int FineAtoms::num_exo_periods() const -{ - int mlead, mlag; - exovarspan(mlead, mlag); - return mlead-mlag+1; -} - -void FineAtoms::parsing_finished(VarOrdering::ord_type ot) -{ - make_internal_orderings(ot); - - // by default, concatenate outer endo and outer exo and make it as - // allvar outer: - vector<const char*> allvar_tmp; - 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); -} - -void 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); -} - -const vector<const char*>& FineAtoms::get_allvar() const -{ - if (! allvar_order) - throw ogu::Exception(__FILE__,__LINE__, - "FineAtoms::get_allvars called before parsing_finished"); - - return allvar_order->get_allvar(); -} - -const vector<int>& FineAtoms::outer_endo2all() const -{ - if (! allvar_order) - throw ogu::Exception(__FILE__,__LINE__, - "FineAtoms::outer_endo2all called before parsing_finished"); - - return allvar_order->get_endo2all(); -} - -const vector<int>& FineAtoms::outer_exo2all() const -{ - if (! allvar_order) - throw ogu::Exception(__FILE__,__LINE__, - "FineAtoms::outer_exo2all called before parsing_finished"); - - return allvar_order->get_exo2all(); -} - - -vector<int> FineAtoms::variables() const -{ - if (endo_order) { - return der_atoms; - } else { - throw ogu::Exception(__FILE__,__LINE__, - "FineAtoms::variables called before parsing_finished"); - return vector<int>(); - } -} - -int FineAtoms::nstat() const -{ - if (endo_order) { - return endo_order->nstat(); - } else { - throw ogu::Exception(__FILE__,__LINE__, - "FineAtoms::nstat called before parsing_finished"); - return -1; - } -} - -int FineAtoms::npred() const -{ - if (endo_order) { - return endo_order->npred(); - } else { - throw ogu::Exception(__FILE__,__LINE__, - "FineAtoms::npred called before parsing_finished"); - return -1; - } -} - -int FineAtoms::nboth() const -{ - if (endo_order) { - return endo_order->nboth(); - } else { - throw ogu::Exception(__FILE__,__LINE__, - "FineAtoms::nboth called before parsing_finished"); - return -1; - } -} - -int FineAtoms::nforw() const -{ - if (endo_order) { - return endo_order->nforw(); - } else { - throw ogu::Exception(__FILE__,__LINE__, - "FineAtoms::nforw called before parsing_finished"); - return -1; - } -} - -int FineAtoms::get_pos_of_endo(int t) const -{ - if (endo_order) { - return endo_order->get_pos_of(t); - } else { - throw ogu::Exception(__FILE__,__LINE__, - "FineAtoms::get_pos_of_endo called before parsing_finished"); - return -1; - } -} - -int FineAtoms::get_pos_of_exo(int t) const -{ - if (exo_order) { - return exo_order->get_pos_of(t); - } else { - throw ogu::Exception(__FILE__,__LINE__, - "FineAtoms::get_pos_of_exo called before parsing_finished"); - return -1; - } -} - -int FineAtoms::get_pos_of_all(int t) const -{ - if (endo_order && exo_order) { - if (endo_order->check(t)) - return endo_order->get_pos_of(t); - else if (exo_order->check(t)) - return endo_order->length() + exo_order->get_pos_of(t); - else { - throw ogu::Exception(__FILE__,__LINE__, - "Atom is not endo nor exo in FineAtoms::get_pos_of_all"); - return -1; - } - } else { - throw ogu::Exception(__FILE__,__LINE__, - "FineAtoms::get_pos_of_exo called before parsing_finished"); - return -1; - } -} - -const vector<int>& FineAtoms::y2outer_endo() const -{ - if (! endo_order) - throw ogu::Exception(__FILE__,__LINE__, - "FineAtoms::y2outer_endo called before parsing_finished"); - return endo_order->get_y2outer(); -} - -const vector<int>& FineAtoms::outer2y_endo() const -{ - if (! endo_order) - throw ogu::Exception(__FILE__,__LINE__, - "FineAtoms::outer2y_endo called before parsing_finished"); - return endo_order->get_outer2y(); -} - -const vector<int>& FineAtoms::y2outer_exo() const -{ - if (! exo_order) - throw ogu::Exception(__FILE__,__LINE__, - "FineAtoms::y2outer_endo called before parsing_finished"); - return exo_order->get_y2outer(); -} - -const vector<int>& FineAtoms::outer2y_exo() const -{ - if (! exo_order) - throw ogu::Exception(__FILE__,__LINE__, - "FineAtoms::outer2y_exo called before parsing_finished"); - return exo_order->get_outer2y(); -} - -const vector<int>& FineAtoms::get_endo_atoms_map() const -{ - if (! endo_order) - throw ogu::Exception(__FILE__,__LINE__, - "FineAtoms::get_endo_atoms_map called before parsing_finished"); - return endo_atoms_map; -} - -const vector<int>& FineAtoms::get_exo_atoms_map() const -{ - if (! exo_order) - throw ogu::Exception(__FILE__,__LINE__, - "FineAtoms::get_exo_atoms_map called before parsing_finished"); - return exo_atoms_map; -} - -int FineAtoms::name2outer_param(const char* name) const -{ - Tvarintmap::const_iterator it = param_outer_map.find(name); - if (it == param_outer_map.end()) - throw ogu::Exception(__FILE__,__LINE__, - "Name is not a parameter in FineAtoms::name2outer_param"); - return (*it).second; -} - -int FineAtoms::name2outer_endo(const char* name) const -{ - Tvarintmap::const_iterator it = endo_outer_map.find(name); - if (it == endo_outer_map.end()) - throw ogu::Exception(__FILE__,__LINE__, - "Name is not an endogenous variable in FineAtoms::name2outer_endo"); - return (*it).second; -} - -int FineAtoms::name2outer_exo(const char* name) const -{ - Tvarintmap::const_iterator it = exo_outer_map.find(name); - if (it == exo_outer_map.end()) - throw ogu::Exception(__FILE__,__LINE__, - "Name is not an exogenous variable in FineAtoms::name2outer_exo"); - return (*it).second; -} - -int FineAtoms::name2outer_allvar(const char* name) const -{ - if (! allvar_order) - throw ogu::Exception(__FILE__,__LINE__, - "FineAtoms::name2outer_allvar called beore parsing_finished"); - - Tvarintmap::const_iterator it = endo_outer_map.find(name); - if (it != endo_outer_map.end()) - 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]; - } - - throw ogu::Exception(__FILE__,__LINE__, - string("Name ") + name + " is neither endo nor exo variable in FineAtoms::name2outer_allvar"); - return -1; -} - -void FineAtoms::register_uniq_endo(const char* name) -{ - if (varnames.query(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)); -} - -void FineAtoms::register_uniq_exo(const char* name) -{ - if (varnames.query(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)); -} - -void FineAtoms::register_uniq_param(const char* name) -{ - if (varnames.query(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)); -} - -void FineAtoms::make_internal_orderings(VarOrdering::ord_type ot) -{ - bool endo_ordering_done = false; - bool exo_ordering_done = false; - - order_type = ot; - - int mlead, mlag; - endovarspan(mlead, mlag); - if (mlag >= -1 && mlead <= 1) { - // make endo ordering - if (endo_order) - delete endo_order; - if (ot == VarOrdering::pbspbfbf) - endo_order = new EndoVarOrdering1(endovars, *this); - else - endo_order = new EndoVarOrdering2(endovars, *this); - endo_order->do_ordering(); - endo_ordering_done = true; - } - - exovarspan(mlead, mlag); - if (mlag == 0 && mlead == 0) { - // make exo ordering - if (exo_order) - delete exo_order; - exo_order = new ExoVarOrdering(exovars, *this); - exo_order->do_ordering(); - exo_ordering_done = true; - } - - if (endo_ordering_done && exo_ordering_done) { - // concatenate der atoms from endo_order and exo_order - der_atoms.clear(); - der_atoms.insert(der_atoms.end(), - endo_order->get_der_atoms().begin(), - endo_order->get_der_atoms().end()); - der_atoms.insert(der_atoms.end(), - exo_order->get_der_atoms().begin(), - exo_order->get_der_atoms().end()); - - // create endo_atoms_map; der_atoms is a concatenation, so it is easy - int endo_atoms = endo_order->get_der_atoms().size(); - endo_atoms_map.clear(); - for (int i = 0; i < endo_atoms; i++) - endo_atoms_map.push_back(i); - // create exo_atoms_map - int exo_atoms = exo_order->get_der_atoms().size(); - exo_atoms_map.clear(); - for (int i = 0; i < exo_atoms; i++) - exo_atoms_map.push_back(endo_atoms + i); - } -} - -void FineAtoms::print() const -{ - DynamicAtoms::print(); - if (endo_order) { - printf("Endo ordering:\n"); - endo_order->print(); - } else { - printf("Endo ordering not created.\n"); - } - if (exo_order) { - printf("Exo ordering:\n"); - exo_order->print(); - } else { - 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("exo atoms map:\n"); - for (unsigned int i = 0; i < exo_atoms_map.size(); i++) - printf("%d --> %d\n", i, exo_atoms_map[i]); -} diff --git a/dynare++/parser/cc/fine_atoms.h b/dynare++/parser/cc/fine_atoms.hh similarity index 99% rename from dynare++/parser/cc/fine_atoms.h rename to dynare++/parser/cc/fine_atoms.hh index 27e5a384165e3c6e3b34a005d8d38eb435aae6aa..610b6b7c48b676c61f458720cc4276b585abdbce 100644 --- a/dynare++/parser/cc/fine_atoms.h +++ b/dynare++/parser/cc/fine_atoms.hh @@ -5,7 +5,7 @@ #ifndef OGP_FINE_ATOMS_H #define OGP_FINE_ATOMS_H -#include "dynamic_atoms.h" +#include "dynamic_atoms.hh" #include <vector> #include <string> diff --git a/dynare++/parser/cc/formula.lex b/dynare++/parser/cc/formula.ll similarity index 98% rename from dynare++/parser/cc/formula.lex rename to dynare++/parser/cc/formula.ll index 15254afd2fc5f6701b60d626832ec10188fb6ee7..8747b6e88399b9bc2ad124c2dc3962cea5fc5d7a 100644 --- a/dynare++/parser/cc/formula.lex +++ b/dynare++/parser/cc/formula.ll @@ -1,5 +1,5 @@ %{ -#include "location.h" +#include "location.hh" #include "formula_tab.hh" extern YYLTYPE fmla_lloc; diff --git a/dynare++/parser/cc/formula.y b/dynare++/parser/cc/formula.yy similarity index 98% rename from dynare++/parser/cc/formula.y rename to dynare++/parser/cc/formula.yy index c687febd7e3d4934253dcee6195f73257014a41b..8cb954a2955db4c5a99339543d1f1900cb0ef934 100644 --- a/dynare++/parser/cc/formula.y +++ b/dynare++/parser/cc/formula.yy @@ -3,8 +3,8 @@ #include <cstdio> -#include "location.h" -#include "formula_parser.h" +#include "location.hh" +#include "formula_parser.hh" #include "formula_tab.hh" void fmla_error(const char*); diff --git a/dynare++/parser/cc/formula_parser.cc b/dynare++/parser/cc/formula_parser.cc new file mode 100644 index 0000000000000000000000000000000000000000..58e6743902ee5c68c79283ce975f1678dfa74433 --- /dev/null +++ b/dynare++/parser/cc/formula_parser.cc @@ -0,0 +1,566 @@ +// Copyright (C) 2005, Ondra Kamenik + +// $Id: formula_parser.cpp 2268 2008-11-22 10:38:03Z michel $ + +#include "utils/cc/pascal_triangle.hh" +#include "utils/cc/exception.hh" + +#include "parser_exception.hh" +#include "location.hh" +#include "formula_parser.hh" +#include "formula_tab.hh" + +#include <cmath> + +using namespace ogp; + +extern location_type fmla_lloc; + +FormulaParser::FormulaParser(const FormulaParser &fp, Atoms &a) + : otree(fp.otree), atoms(a), formulas(fp.formulas), ders() +{ + // create derivatives + for (unsigned int i = 0; i < fp.ders.size(); i++) + ders.push_back(new FormulaDerivatives(*(fp.ders[i]))); +} + +FormulaParser::~FormulaParser() +{ + destroy_derivatives(); +} + +void +FormulaParser::differentiate(int max_order) +{ + destroy_derivatives(); + vector<int> vars; + vars = atoms.variables(); + for (unsigned int i = 0; i < formulas.size(); i++) + ders.push_back(new FormulaDerivatives(otree, vars, formulas[i], max_order)); +} + +const FormulaDerivatives & +FormulaParser::derivatives(int i) const +{ + if (i < (int) ders.size()) + return *(ders[i]); + else + throw ogu::Exception(__FILE__, __LINE__, + "Wrong formula index in FormulaParser::derivatives"); + return *(ders[0]); // just because of compiler +} + +void +FormulaParser::add_formula(int t) +{ + formulas.push_back(t); +} + +int +FormulaParser::add_binary(code_t code, int t1, int t2) +{ + return otree.add_binary(code, t1, t2); +} + +int +FormulaParser::add_unary(code_t code, int t) +{ + return otree.add_unary(code, t); +} + +int +FormulaParser::add_nulary(const char *str) +{ + int t = -1; + try + { + t = atoms.check(str); + } + catch (const ParserException &e) + { + throw ParserException(e, fmla_lloc.off); + } + if (t == -1) + { + t = otree.add_nulary(); + atoms.assign(str, t); + } + return t; +} + +void +FormulaParser::add_subst_formulas(const map<int, int> &subst, const FormulaParser &fp) +{ + for (int i = 0; i < fp.nformulas(); i++) + { + int f = add_substitution(fp.formula(i), subst, fp); + add_formula(f); + } +} + +void +FormulaParser::substitute_formulas(const map<int, int> &smap) +{ + for (int i = 0; i < nformulas(); i++) + { + // make substitution and replace the formula for it + int f = add_substitution(formulas[i], smap); + formulas[i] = f; + // update the derivatives if any + if (i < (int) ders.size() && ders[i]) + { + int order = ders[i]->get_order(); + delete ders[i]; + ders[i] = new FormulaDerivatives(otree, atoms.variables(), formulas[i], order); + } + } +} + +/** Global symbols for passing info to parser. */ +FormulaParser *fparser; + +/** The declarations of functions defined in formula_ll.cc and + * formula_tab.cc generated from formula.lex and formula.y */ +void *fmla__scan_buffer(char *, size_t); +void fmla__destroy_buffer(void *); +int fmla_parse(); +extern location_type fmla_lloc; + +/** This makes own copy of provided data, sets the buffer for the + * parser with fmla_scan_buffer, and launches fmla_parse(). Note that + * the pointer returned from fmla_scan_buffer must be freed at the + * end. */ +void +FormulaParser::parse(int length, const char *stream) +{ + char *buffer = new char[length+2]; + strncpy(buffer, stream, length); + 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); + fparser = this; + fmla_parse(); + delete [] buffer; + fmla__destroy_buffer(p); +} + +void +FormulaParser::error(const char *mes) const +{ + throw ParserException(mes, fmla_lloc.off); +} + +int +FormulaParser::last_formula() const +{ + int res = -1; + for (unsigned int i = 0; i < formulas.size(); i++) + if (res < formulas[i]) + res = formulas[i]; + return std::max(res, otree.get_last_nulary()); +} + +int +FormulaParser::pop_last_formula() +{ + if (formulas.size() == 0) + return -1; + int t = formulas.back(); + if (formulas.size() == ders.size()) + { + delete ders.back(); + ders.pop_back(); + } + formulas.pop_back(); + return t; +} + +void +FormulaParser::print() const +{ + atoms.print(); + for (unsigned int i = 0; i < formulas.size(); i++) + { + printf("formula %d:\n", formulas[i]); + otree.print_operation(formulas[i]); + } + for (unsigned int i = 0; i < ders.size(); i++) + { + printf("derivatives for the formula %d:\n", formulas[i]); + ders[i]->print(otree); + } +} + +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 + * are added to the tree. + * + * The algorithm is as follows. todo: update description of the + * algorithm + */ +FormulaDerivatives::FormulaDerivatives(OperationTree &otree, + const vector<int> &vars, int f, int max_order) + : nvar(vars.size()), order(max_order) +{ + FoldMultiIndex fmi_zero(nvar); + tder.push_back(f); + indices.push_back(fmi_zero); + unsigned int last_order_beg = 0; + unsigned int last_order_end = tder.size(); + + for (int k = 1; k <= order; k++) + { + // interval <last_order_beg,last_order_end) is guaranteed + // here to contain at least one item + for (unsigned int run = last_order_beg; run < last_order_end; run++) + { + // shift one order from the run + FoldMultiIndex fmi(indices[run], 1); + // set starting variable from the run, note that if k=1, + // the shift order ctor of fmi will set it to zero + int ivar_start = fmi[k-1]; + for (int ivar = ivar_start; ivar < nvar; ivar++, fmi.increment()) + { + int der = otree.add_derivative(tder[run], vars[ivar]); + if (der != OperationTree::zero) + { + tder.push_back(der); + indices.push_back(fmi); + } + } + } + + // set new last_order_beg and last_order_end + last_order_beg = last_order_end; + last_order_end = tder.size(); + // if there was no new derivative, break out from the loop + if (last_order_beg >= last_order_end) + break; + } + + // build ind2der map + for (unsigned int i = 0; i < indices.size(); i++) + ind2der.insert(Tfmiintmap::value_type(indices[i], i)); + +} + +FormulaDerivatives::FormulaDerivatives(const FormulaDerivatives &fd) + : tder(fd.tder), indices(fd.indices), ind2der(fd.ind2der), + nvar(fd.nvar), order(fd.order) +{ +} + +int +FormulaDerivatives::derivative(const FoldMultiIndex &mi) const +{ + if (mi.order() > order) + throw ogu::Exception(__FILE__, __LINE__, + "Wrong order of multi-index in FormulaDerivatives::derivative"); + if (mi.nv() != nvar) + throw ogu::Exception(__FILE__, __LINE__, + "Wrong multi-index variables in FormulaDerivatives::derivative"); + + Tfmiintmap::const_iterator it = ind2der.find(mi); + if (it == ind2der.end()) + return OperationTree::zero; + else + return tder[(*it).second]; +} + +void +FormulaDerivatives::print(const OperationTree &otree) const +{ + for (Tfmiintmap::const_iterator it = ind2der.begin(); + it != ind2der.end(); ++it) + { + printf("derivative "); + (*it).first.print(); + printf(" is formula %d\n", tder[(*it).second]); + otree.print_operation(tder[(*it).second]); + } +} + +void +FormulaCustomEvaluator::eval(const AtomValues &av, FormulaEvalLoader &loader) +{ + etree.reset_all(); + av.setValues(etree); + for (unsigned int i = 0; i < terms.size(); i++) + { + double res = etree.eval(terms[i]); + loader.load((int) i, res); + } +} + +FoldMultiIndex::FoldMultiIndex(int nv) + : nvar(nv), ord(0), data(new int[ord]) +{ +} + +FoldMultiIndex::FoldMultiIndex(int nv, int ordd, int ii) + : nvar(nv), ord(ordd), data(new int[ord]) +{ + for (int i = 0; i < ord; i++) + data[i] = 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]) +{ + for (int i = 0; i < ord; i++) + { + if (i < ord-1 && mp[i+1] < mp[i]) + throw ogu::Exception(__FILE__, __LINE__, + "Mapping not monotone in FoldMultiIndex constructor"); + if (mp[mi[i]] >= nv || mp[mi[i]] < 0) + throw ogu::Exception(__FILE__, __LINE__, + "Mapping out of bounds in FoldMultiIndex constructor"); + data[i] = mp[mi[i]]; + } +} + +FoldMultiIndex::FoldMultiIndex(const FoldMultiIndex &fmi, int new_orders) + : nvar(fmi.nvar), + ord(fmi.ord+new_orders), + data(new int[ord]) +{ + memcpy(data, fmi.data, fmi.ord*sizeof(int)); + int new_item = (fmi.ord > 0) ? fmi.data[fmi.ord-1] : 0; + for (int i = fmi.ord; i < ord; i++) + { + data[i] = new_item; + } +} + +FoldMultiIndex::FoldMultiIndex(const FoldMultiIndex &fmi) + : nvar(fmi.nvar), + ord(fmi.ord), + data(new int[fmi.ord]) +{ + memcpy(data, fmi.data, ord*sizeof(int)); +} + +const FoldMultiIndex & +FoldMultiIndex::operator=(const FoldMultiIndex &fmi) +{ + if (ord != fmi.ord) + { + delete [] data; + data = new int[fmi.ord]; + } + + ord = fmi.ord; + nvar = fmi.nvar; + memcpy(data, fmi.data, ord*sizeof(int)); + + return *this; +} + +bool +FoldMultiIndex::operator<(const FoldMultiIndex &fmi) const +{ + if (nvar != fmi.nvar) + ogu::Exception(__FILE__, __LINE__, + "Different nvar in FoldMultiIndex::operator<"); + + if (ord < fmi.ord) + return true; + if (ord > fmi.ord) + return false; + + int i = 0; + while (i < ord && data[i] == fmi.data[i]) + i++; + if (i == ord) + return false; + else + return data[i] < fmi.data[i]; +} + +bool +FoldMultiIndex::operator==(const FoldMultiIndex &fmi) const +{ + bool res = true; + res = res && (nvar == fmi.nvar) && (ord == fmi.ord); + if (res) + for (int i = 0; i < ord; i++) + if (data[i] != fmi.data[i]) + return false; + return res; +} + +void +FoldMultiIndex::increment() +{ + if (ord == 0) + return; + + int k = ord-1; + data[k]++; + while (k > 0 && data[k] == nvar) + { + data[k] = 0; + data[--k]++; + } + for (int kk = 1; kk < ord; kk++) + if (data[kk-1] > data[kk]) + data[kk] = data[kk-1]; +} + +// For description of an algorithm for calculation of folded offset, +// see Tensor Library Documentation, Ondra Kamenik, 2005, description +// of FTensor::getOffsetRecurse(). +int +FoldMultiIndex::offset() const +{ + // make copy for the recursions + int *tmp = new int[ord]; + for (int i = 0; i < ord; i++) + tmp[i] = data[i]; + // call the recursive algorithm + int res = offset_recurse(tmp, ord, nvar); + + delete [] tmp; + return res; +} + +void +FoldMultiIndex::print() const +{ + printf("["); + for (int i = 0; i < ord; i++) + printf("%d ", data[i]); + printf("]"); +} + +int +FoldMultiIndex::offset_recurse(int *data, int len, int nv) +{ + if (len == 0) + return 0; + // calculate length of initial constant indices + int prefix = 1; + while (prefix < len && data[0] == data[prefix]) + prefix++; + + int m = data[0]; + int s1 = ptriang.noverk(nv+len-1, len) - ptriang.noverk(nv-m+len-1, len); + + // cancel m from the rest of the sequence + for (int i = prefix; i < len; i++) + data[i] -= m; + + // calculate offset of the remaining sequence + int s2 = offset_recurse(data+prefix, len-prefix, nv-m); + // return the sum + return s1+s2; +} + +bool +ltfmi::operator()(const FoldMultiIndex &i1, const FoldMultiIndex &i2) const +{ + return i1 < i2; +} + +FormulaDerEvaluator::FormulaDerEvaluator(const FormulaParser &fp) + : etree(fp.otree, -1) +{ + for (unsigned int i = 0; i < fp.ders.size(); i++) + ders.push_back((const FormulaDerivatives *) (fp.ders[i])); + + der_atoms = fp.atoms.variables(); +} + +void +FormulaDerEvaluator::eval(const AtomValues &av, FormulaDerEvalLoader &loader, int order) +{ + if (ders.size() == 0) + return; + int maxorder = ders[0]->order; + + if (order > maxorder) + throw ogu::Exception(__FILE__, __LINE__, + "Wrong order in FormulaDerEvaluator::eval"); + + etree.reset_all(); + av.setValues(etree); + + int *vars = new int[order]; + + for (unsigned int i = 0; i < ders.size(); i++) + { + for (FormulaDerivatives::Tfmiintmap::const_iterator it = ders[i]->ind2der.begin(); + it != ders[i]->ind2der.end(); ++it) + { + 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]); + // load + loader.load(i, order, vars, res); + } + } + } + + delete [] vars; +} + +void +FormulaDerEvaluator::eval(const vector<int> &mp, const AtomValues &av, + FormulaDerEvalLoader &loader, int order) +{ + etree.reset_all(); + av.setValues(etree); + + int nvar_glob = der_atoms.size(); + int nvar = mp.size(); + int *vars = new int[order]; + + for (unsigned int i = 0; i < ders.size(); i++) + { + FoldMultiIndex mi(nvar, order); + do + { + // find index of the derivative in the tensor + FoldMultiIndex mi_glob(nvar_glob, mi, mp); + int der = ders[i]->derivative(mi_glob); + if (der != OperationTree::zero) + { + // set vars from the global multiindex + for (int k = 0; k < order; k++) + vars[k] = der_atoms[mi_glob[k]]; + // evaluate derivative + double res = etree.eval(der); + // load + loader.load(i, order, vars, res); + } + mi.increment(); + } + while (!mi.past_the_end()); + } + + delete [] vars; +} + +// Local Variables: +// mode:C++ +// End: diff --git a/dynare++/parser/cc/formula_parser.cpp b/dynare++/parser/cc/formula_parser.cpp deleted file mode 100644 index cd3c26101d47e031534049d1e52d0ea154c4b5c6..0000000000000000000000000000000000000000 --- a/dynare++/parser/cc/formula_parser.cpp +++ /dev/null @@ -1,517 +0,0 @@ -// Copyright (C) 2005, Ondra Kamenik - -// $Id: formula_parser.cpp 2268 2008-11-22 10:38:03Z michel $ - -#include "utils/cc/pascal_triangle.h" -#include "utils/cc/exception.h" - -#include "parser_exception.h" -#include "location.h" -#include "formula_parser.h" -#include "formula_tab.hh" - -#include <cmath> - -using namespace ogp; - -extern location_type fmla_lloc; - -FormulaParser::FormulaParser(const FormulaParser& fp, Atoms& a) - : otree(fp.otree), atoms(a), formulas(fp.formulas), ders() -{ - // create derivatives - for (unsigned int i = 0; i < fp.ders.size(); i++) - ders.push_back(new FormulaDerivatives(*(fp.ders[i]))); -} - -FormulaParser::~FormulaParser() -{ - destroy_derivatives(); -} - -void FormulaParser::differentiate(int max_order) -{ - destroy_derivatives(); - vector<int> vars; - vars = atoms.variables(); - for (unsigned int i = 0; i < formulas.size(); i++) - ders.push_back(new FormulaDerivatives(otree, vars, formulas[i], max_order)); -} - -const FormulaDerivatives& FormulaParser::derivatives(int i) const -{ - if (i < (int)ders.size()) - return *(ders[i]); - else - throw ogu::Exception(__FILE__,__LINE__, - "Wrong formula index in FormulaParser::derivatives"); - return *(ders[0]); // just because of compiler -} - - - -void FormulaParser::add_formula(int t) -{ - formulas.push_back(t); -} - -int FormulaParser::add_binary(code_t code, int t1, int t2) -{ - return otree.add_binary(code, t1, t2); -} - -int FormulaParser::add_unary(code_t code, int t) -{ - return otree.add_unary(code, t); -} - -int FormulaParser::add_nulary(const char* str) -{ - int t = -1; - try { - t = atoms.check(str); - } catch (const ParserException& e) { - throw ParserException(e, fmla_lloc.off); - } - if (t == -1) { - t = otree.add_nulary(); - atoms.assign(str, t); - } - return t; -} - -void FormulaParser::add_subst_formulas(const map<int,int>& subst, const FormulaParser& fp) -{ - for (int i = 0; i < fp.nformulas(); i++) { - int f = add_substitution(fp.formula(i), subst, fp); - add_formula(f); - } -} - -void FormulaParser::substitute_formulas(const map<int,int>& smap) -{ - for (int i = 0; i < nformulas(); i++) { - // make substitution and replace the formula for it - int f = add_substitution(formulas[i], smap); - formulas[i] = f; - // update the derivatives if any - if (i < (int)ders.size() && ders[i]) { - int order = ders[i]->get_order(); - delete ders[i]; - ders[i] = new FormulaDerivatives(otree, atoms.variables(), formulas[i], order); - } - } -} - -/** Global symbols for passing info to parser. */ -FormulaParser* fparser; - -/** The declarations of functions defined in formula_ll.cc and - * formula_tab.cc generated from formula.lex and formula.y */ -void* fmla__scan_buffer(char*, size_t); -void fmla__destroy_buffer(void*); -int fmla_parse(); -extern location_type fmla_lloc; - -/** This makes own copy of provided data, sets the buffer for the - * parser with fmla_scan_buffer, and launches fmla_parse(). Note that - * the pointer returned from fmla_scan_buffer must be freed at the - * end. */ -void FormulaParser::parse(int length, const char* stream) -{ - char* buffer = new char[length+2]; - strncpy(buffer, stream, length); - 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); - fparser = this; - fmla_parse(); - delete [] buffer; - fmla__destroy_buffer(p); -} - -void FormulaParser::error(const char* mes) const -{ - throw ParserException(mes, fmla_lloc.off); -} - -int FormulaParser::last_formula() const -{ - int res = -1; - for (unsigned int i = 0; i < formulas.size(); i++) - if (res < formulas[i]) - res = formulas[i]; - return std::max(res, otree.get_last_nulary()); -} - -int FormulaParser::pop_last_formula() -{ - if (formulas.size() == 0) - return -1; - int t = formulas.back(); - if (formulas.size() == ders.size()) { - delete ders.back(); - ders.pop_back(); - } - formulas.pop_back(); - return t; -} - -void FormulaParser::print() const -{ - atoms.print(); - for (unsigned int i = 0; i < formulas.size(); i++) { - printf("formula %d:\n", formulas[i]); - otree.print_operation(formulas[i]); - } - for (unsigned int i = 0; i < ders.size(); i++) { - printf("derivatives for the formula %d:\n", formulas[i]); - ders[i]->print(otree); - } -} - -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 - * are added to the tree. - * - * The algorithm is as follows. todo: update description of the - * algorithm -*/ -FormulaDerivatives::FormulaDerivatives(OperationTree& otree, - const vector<int>& vars, int f, int max_order) - : nvar(vars.size()), order(max_order) -{ - FoldMultiIndex fmi_zero(nvar); - tder.push_back(f); - indices.push_back(fmi_zero); - unsigned int last_order_beg = 0; - unsigned int last_order_end = tder.size(); - - for (int k = 1; k <= order; k++) { - // interval <last_order_beg,last_order_end) is guaranteed - // here to contain at least one item - for (unsigned int run = last_order_beg; run < last_order_end; run++) { - // shift one order from the run - FoldMultiIndex fmi(indices[run], 1); - // set starting variable from the run, note that if k=1, - // the shift order ctor of fmi will set it to zero - int ivar_start = fmi[k-1]; - for (int ivar = ivar_start; ivar < nvar; ivar++, fmi.increment()) { - int der = otree.add_derivative(tder[run], vars[ivar]); - if (der != OperationTree::zero) { - tder.push_back(der); - indices.push_back(fmi); - } - } - } - - // set new last_order_beg and last_order_end - last_order_beg = last_order_end; - last_order_end = tder.size(); - // if there was no new derivative, break out from the loop - if (last_order_beg >= last_order_end) - break; - } - - // build ind2der map - for (unsigned int i = 0; i < indices.size(); i++) - ind2der.insert(Tfmiintmap::value_type(indices[i], i)); - -} - -FormulaDerivatives::FormulaDerivatives(const FormulaDerivatives& fd) - : tder(fd.tder), indices(fd.indices), ind2der(fd.ind2der), - nvar(fd.nvar), order(fd.order) -{ -} - -int FormulaDerivatives::derivative(const FoldMultiIndex& mi) const -{ - if (mi.order() > order) - throw ogu::Exception(__FILE__,__LINE__, - "Wrong order of multi-index in FormulaDerivatives::derivative"); - if (mi.nv() != nvar) - throw ogu::Exception(__FILE__,__LINE__, - "Wrong multi-index variables in FormulaDerivatives::derivative"); - - Tfmiintmap::const_iterator it = ind2der.find(mi); - if (it == ind2der.end()) - return OperationTree::zero; - else - return tder[(*it).second]; -} - -void FormulaDerivatives::print(const OperationTree& otree) const -{ - for (Tfmiintmap::const_iterator it = ind2der.begin(); - it != ind2der.end(); ++it) { - printf("derivative "); - (*it).first.print(); - printf(" is formula %d\n", tder[(*it).second]); - otree.print_operation(tder[(*it).second]); - } -} - -void FormulaCustomEvaluator::eval(const AtomValues& av, FormulaEvalLoader& loader) -{ - etree.reset_all(); - av.setValues(etree); - for (unsigned int i = 0; i < terms.size(); i++) { - double res = etree.eval(terms[i]); - loader.load((int)i, res); - } -} - -FoldMultiIndex::FoldMultiIndex(int nv) - : nvar(nv), ord(0), data(new int[ord]) -{ -} - -FoldMultiIndex::FoldMultiIndex(int nv, int ordd, int ii) - : nvar(nv), ord(ordd), data(new int[ord]) -{ - for (int i = 0; i < ord; i++) - data[i] = 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]) -{ - for (int i = 0; i < ord; i++) { - if (i < ord-1 && mp[i+1] < mp[i]) - throw ogu::Exception(__FILE__,__LINE__, - "Mapping not monotone in FoldMultiIndex constructor"); - if (mp[mi[i]] >= nv || mp[mi[i]] < 0) - throw ogu::Exception(__FILE__,__LINE__, - "Mapping out of bounds in FoldMultiIndex constructor"); - data[i] = mp[mi[i]]; - } -} - -FoldMultiIndex::FoldMultiIndex(const FoldMultiIndex& fmi, int new_orders) - : nvar(fmi.nvar), - ord(fmi.ord+new_orders), - data(new int[ord]) -{ - memcpy(data, fmi.data, fmi.ord*sizeof(int)); - int new_item = (fmi.ord > 0)? fmi.data[fmi.ord-1] : 0; - for (int i = fmi.ord; i < ord; i++) { - data[i] = new_item; - } -} - -FoldMultiIndex::FoldMultiIndex(const FoldMultiIndex& fmi) - : nvar(fmi.nvar), - ord(fmi.ord), - data(new int[fmi.ord]) -{ - memcpy(data, fmi.data, ord*sizeof(int)); -} - -const FoldMultiIndex& FoldMultiIndex::operator=(const FoldMultiIndex& fmi) -{ - if (ord != fmi.ord) { - delete [] data; - data = new int[fmi.ord]; - } - - ord = fmi.ord; - nvar = fmi.nvar; - memcpy(data, fmi.data, ord*sizeof(int)); - - return *this; -} - -bool FoldMultiIndex::operator<(const FoldMultiIndex& fmi) const -{ - if (nvar != fmi.nvar) - ogu::Exception(__FILE__,__LINE__, - "Different nvar in FoldMultiIndex::operator<"); - - if (ord < fmi.ord) - return true; - if (ord > fmi.ord) - return false; - - int i = 0; - while (i < ord && data[i] == fmi.data[i]) - i++; - if (i == ord) - return false; - else - return data[i] < fmi.data[i]; -} - -bool FoldMultiIndex::operator==(const FoldMultiIndex& fmi) const -{ - bool res = true; - res = res && (nvar == fmi.nvar) && (ord == fmi.ord); - if (res) - for (int i = 0; i < ord; i++) - if (data[i] != fmi.data[i]) - return false; - return res; -} - -void FoldMultiIndex::increment() -{ - if (ord == 0) - return; - - int k = ord-1; - data[k]++; - while (k > 0 && data[k] == nvar) { - data[k] = 0; - data[--k]++; - } - for (int kk = 1; kk < ord; kk++) - if (data[kk-1] > data[kk]) - data[kk] = data[kk-1]; -} - - -// For description of an algorithm for calculation of folded offset, -// see Tensor Library Documentation, Ondra Kamenik, 2005, description -// of FTensor::getOffsetRecurse(). -int FoldMultiIndex::offset() const -{ - // make copy for the recursions - int* tmp = new int[ord]; - for (int i = 0; i < ord; i++) - tmp[i] = data[i]; - // call the recursive algorithm - int res = offset_recurse(tmp, ord, nvar); - - delete [] tmp; - return res; -} - -void FoldMultiIndex::print() const -{ - printf("["); - for (int i = 0; i < ord; i++) - printf("%d ", data[i]); - printf("]"); -} - -int FoldMultiIndex::offset_recurse(int* data, int len, int nv) -{ - if (len == 0) - return 0; - // calculate length of initial constant indices - int prefix = 1; - while (prefix < len && data[0] == data[prefix]) - prefix++; - - int m = data[0]; - int s1 = ptriang.noverk(nv+len-1, len) - ptriang.noverk(nv-m+len-1,len); - - // cancel m from the rest of the sequence - for (int i = prefix; i < len; i++) - data[i] -= m; - - // calculate offset of the remaining sequence - int s2 = offset_recurse(data+prefix, len-prefix, nv-m); - // return the sum - return s1+s2; -} - - -bool ltfmi::operator()(const FoldMultiIndex& i1, const FoldMultiIndex& i2) const -{ - return i1 < i2; -} - - -FormulaDerEvaluator::FormulaDerEvaluator(const FormulaParser& fp) - : etree(fp.otree, -1) -{ - for (unsigned int i = 0; i < fp.ders.size(); i++) - ders.push_back((const FormulaDerivatives*)(fp.ders[i])); - - der_atoms = fp.atoms.variables(); -} - -void FormulaDerEvaluator::eval(const AtomValues& av, FormulaDerEvalLoader& loader, int order) -{ - if (ders.size() == 0) - return; - int maxorder = ders[0]->order; - - if (order > maxorder) - throw ogu::Exception(__FILE__,__LINE__, - "Wrong order in FormulaDerEvaluator::eval"); - - etree.reset_all(); - av.setValues(etree); - - int* vars = new int[order]; - - for (unsigned int i = 0; i < ders.size(); i++) { - for (FormulaDerivatives::Tfmiintmap::const_iterator it = ders[i]->ind2der.begin(); - it != ders[i]->ind2der.end(); ++it) { - 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]); - // load - loader.load(i, order, vars, res); - } - } - } - - delete [] vars; -} - -void FormulaDerEvaluator::eval(const vector<int>& mp, const AtomValues& av, - FormulaDerEvalLoader& loader, int order) -{ - etree.reset_all(); - av.setValues(etree); - - int nvar_glob = der_atoms.size(); - int nvar = mp.size(); - int* vars = new int[order]; - - for (unsigned int i = 0; i < ders.size(); i++) { - FoldMultiIndex mi(nvar, order); - do { - // find index of the derivative in the tensor - FoldMultiIndex mi_glob(nvar_glob, mi, mp); - int der = ders[i]->derivative(mi_glob); - if (der != OperationTree::zero) { - // set vars from the global multiindex - for (int k = 0; k < order; k++) - vars[k] = der_atoms[mi_glob[k]]; - // evaluate derivative - double res = etree.eval(der); - // load - loader.load(i, order, vars, res); - } - mi.increment(); - } while (! mi.past_the_end()); - } - - delete [] vars; -} - - -// Local Variables: -// mode:C++ -// End: diff --git a/dynare++/parser/cc/formula_parser.h b/dynare++/parser/cc/formula_parser.hh similarity index 99% rename from dynare++/parser/cc/formula_parser.h rename to dynare++/parser/cc/formula_parser.hh index 5cd4476e5103ac2d4d14eb278b2205670deb9118..1f2302063bc84d2b2e9d47f930518e60cb653e5b 100644 --- a/dynare++/parser/cc/formula_parser.h +++ b/dynare++/parser/cc/formula_parser.hh @@ -3,7 +3,7 @@ #ifndef OGP_FORMULA_PARSER_H #define OGP_FORMULA_PARSER_H -#include "tree.h" +#include "tree.hh" namespace ogp { diff --git a/dynare++/parser/cc/location.h b/dynare++/parser/cc/location.hh similarity index 100% rename from dynare++/parser/cc/location.h rename to dynare++/parser/cc/location.hh diff --git a/dynare++/parser/cc/matrix.lex b/dynare++/parser/cc/matrix.ll similarity index 97% rename from dynare++/parser/cc/matrix.lex rename to dynare++/parser/cc/matrix.ll index 880b8eca621fda2b083d66a6ba838c38f357719f..51c4c85dcb75b32db18a79ee5e0c54216e515aee 100644 --- a/dynare++/parser/cc/matrix.lex +++ b/dynare++/parser/cc/matrix.ll @@ -1,7 +1,7 @@ %{ // Copyright (C) 2006-2011, Ondra Kamenik -#include "location.h" +#include "location.hh" #include "matrix_tab.hh" extern YYLTYPE matrix_lloc; diff --git a/dynare++/parser/cc/matrix.y b/dynare++/parser/cc/matrix.yy similarity index 96% rename from dynare++/parser/cc/matrix.y rename to dynare++/parser/cc/matrix.yy index ef48f4c83ac2935674a216bb6e33271a08b5602f..a2fa51db527e1fbcec7cd0594ad287a23e12b136 100644 --- a/dynare++/parser/cc/matrix.y +++ b/dynare++/parser/cc/matrix.yy @@ -1,8 +1,8 @@ // Copyright (C) 2006-2011, Ondra Kamenik %{ -#include "location.h" -#include "matrix_parser.h" +#include "location.hh" +#include "matrix_parser.hh" #include "matrix_tab.hh" void matrix_error(const char*); diff --git a/dynare++/parser/cc/matrix_parser.cc b/dynare++/parser/cc/matrix_parser.cc new file mode 100644 index 0000000000000000000000000000000000000000..68b664f6618e719947bea3ee9c97bdaed303c972 --- /dev/null +++ b/dynare++/parser/cc/matrix_parser.cc @@ -0,0 +1,112 @@ +// Copyright (C) 2006, Ondra Kamenik + +// $Id: matrix_parser.cpp 2269 2008-11-23 14:33:22Z michel $ + +#include "parser_exception.hh" +#include "matrix_parser.hh" +#include "location.hh" +#include "matrix_tab.hh" +#include <cstring> + +using namespace ogp; + +/** A global symbol for passing info to the MatrixParser from + * matrix_parse(). */ +MatrixParser *mparser; + +/** The declaration of functions defined in matrix_ll.cc and + * matrix_tab.cc generated from matrix.lex and matrix.y. */ +void *matrix__scan_buffer(char *, size_t); +void matrix__destroy_buffer(void *); +int matrix_parse(); +extern ogp::location_type matrix_lloc; + +void +MatrixParser::parse(int length, const char *stream) +{ + // reinitialize the object + data.clear(); + row_lengths.clear(); + nc = 0; + // allocate temporary buffer and parse + char *buffer = new char[length+2]; + strncpy(buffer, stream, length); + 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); + mparser = this; + matrix_parse(); + delete [] buffer; + matrix__destroy_buffer(p); +} + +void +MatrixParser::add_item(double v) +{ + data.push_back(v); + if (row_lengths.size() == 0) + row_lengths.push_back(0); + (row_lengths.back())++; + if (row_lengths.back() > nc) + nc = row_lengths.back(); +} + +void +MatrixParser::start_row() +{ + row_lengths.push_back(0); +} + +void +MatrixParser::error(const char *mes) const +{ + throw ParserException(mes, matrix_lloc.off); +} + +int +MatrixParser::find_first_non_empty_row(int start) const +{ + int r = start; + while (r < (int) row_lengths.size() && row_lengths[r] == 0) + r++; + return r; +} + +MPIterator +MatrixParser::begin() const +{ + MPIterator it(*this); + return it; +} + +MPIterator +MatrixParser::end() const +{ + MPIterator it(*this, "end"); + return it; +} + +MPIterator::MPIterator(const MatrixParser &mp) + : p(&mp), i(0), c(0), r(mp.find_first_non_empty_row()) +{ +} + +MPIterator::MPIterator(const MatrixParser &mp, const char *dummy) + : p(&mp), i(mp.data.size()), c(0), r(mp.row_lengths.size()) +{ +} + +MPIterator & +MPIterator::operator++() +{ + i++; + c++; + if (p->row_lengths[r] <= c) + { + c = 0; + r = p->find_first_non_empty_row(r+1); + } + return *this; +} diff --git a/dynare++/parser/cc/matrix_parser.cpp b/dynare++/parser/cc/matrix_parser.cpp deleted file mode 100644 index eadbd3533037498c6167033c9c0b73aca301645c..0000000000000000000000000000000000000000 --- a/dynare++/parser/cc/matrix_parser.cpp +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright (C) 2006, Ondra Kamenik - -// $Id: matrix_parser.cpp 2269 2008-11-23 14:33:22Z michel $ - -#include "parser_exception.h" -#include "matrix_parser.h" -#include "location.h" -#include "matrix_tab.hh" -#include <cstring> - -using namespace ogp; - -/** A global symbol for passing info to the MatrixParser from - * matrix_parse(). */ -MatrixParser* mparser; - -/** The declaration of functions defined in matrix_ll.cc and - * matrix_tab.cc generated from matrix.lex and matrix.y. */ -void* matrix__scan_buffer(char*, size_t); -void matrix__destroy_buffer(void*); -int matrix_parse(); -extern ogp::location_type matrix_lloc; - -void MatrixParser::parse(int length, const char* stream) -{ - // reinitialize the object - data.clear(); - row_lengths.clear(); - nc = 0; - // allocate temporary buffer and parse - char* buffer = new char[length+2]; - strncpy(buffer, stream, length); - 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); - mparser = this; - matrix_parse(); - delete [] buffer; - matrix__destroy_buffer(p); -} - -void MatrixParser::add_item(double v) -{ - data.push_back(v); - if (row_lengths.size() == 0) - row_lengths.push_back(0); - (row_lengths.back())++; - if (row_lengths.back() > nc) - nc = row_lengths.back(); -} - -void MatrixParser::start_row() -{ - row_lengths.push_back(0); -} - -void MatrixParser::error(const char* mes) const -{ - throw ParserException(mes, matrix_lloc.off); -} - -int MatrixParser::find_first_non_empty_row(int start) const -{ - int r = start; - while (r < (int)row_lengths.size() && row_lengths[r] == 0) - r++; - return r; -} - -MPIterator MatrixParser::begin() const -{ - MPIterator it(*this); - return it; -} - -MPIterator MatrixParser::end() const -{ - MPIterator it(*this, "end"); - return it; -} - -MPIterator::MPIterator(const MatrixParser& mp) - : p(&mp), i(0), c(0), r(mp.find_first_non_empty_row()) -{} - -MPIterator::MPIterator(const MatrixParser& mp, const char* dummy) - : p(&mp), i(mp.data.size()), c(0), r(mp.row_lengths.size()) -{} - -MPIterator& MPIterator::operator++() -{ - i++; - c++; - if (p->row_lengths[r] <= c) { - c = 0; - r = p->find_first_non_empty_row(r+1); - } - return *this; -} diff --git a/dynare++/parser/cc/matrix_parser.h b/dynare++/parser/cc/matrix_parser.hh similarity index 100% rename from dynare++/parser/cc/matrix_parser.h rename to dynare++/parser/cc/matrix_parser.hh diff --git a/dynare++/parser/cc/namelist.cc b/dynare++/parser/cc/namelist.cc new file mode 100644 index 0000000000000000000000000000000000000000..c9c148e2a623724d4221d247741c2144c0ee0a7a --- /dev/null +++ b/dynare++/parser/cc/namelist.cc @@ -0,0 +1,31 @@ +// Copyright (C) 2006, Ondra Kamenik + +// $Id: namelist.cpp 42 2007-01-22 21:53:24Z ondra $ + +#include "namelist.hh" + +#include <cstring> + +using namespace ogp; + +/** A global symbol for passing info to NameListParser from its + * parser. */ +NameListParser *name_list_parser; + +void *namelist__scan_buffer(char *, unsigned int); +void namelist__destroy_buffer(void *); +void namelist_parse(); + +void +NameListParser::namelist_parse(int length, const char *stream) +{ + char *buffer = new char[length+2]; + strncpy(buffer, stream, length); + buffer[length] = '\0'; + buffer[length+1] = '\0'; + void *p = namelist__scan_buffer(buffer, (unsigned int) length+2); + name_list_parser = this; + ::namelist_parse(); + delete [] buffer; + namelist__destroy_buffer(p); +} diff --git a/dynare++/parser/cc/namelist.cpp b/dynare++/parser/cc/namelist.cpp deleted file mode 100644 index 03bf9a51c9a891b373ded9724c6931ce1bd86986..0000000000000000000000000000000000000000 --- a/dynare++/parser/cc/namelist.cpp +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (C) 2006, Ondra Kamenik - -// $Id: namelist.cpp 42 2007-01-22 21:53:24Z ondra $ - -#include "namelist.h" - -#include <cstring> - -using namespace ogp; - -/** A global symbol for passing info to NameListParser from its - * parser. */ -NameListParser* name_list_parser; - -void* namelist__scan_buffer(char*, unsigned int); -void namelist__destroy_buffer(void*); -void namelist_parse(); - -void NameListParser::namelist_parse(int length, const char* stream) -{ - char* buffer = new char[length+2]; - strncpy(buffer, stream, length); - buffer[length] = '\0'; - buffer[length+1] = '\0'; - void* p = namelist__scan_buffer(buffer, (unsigned int)length+2); - name_list_parser = this; - ::namelist_parse(); - delete [] buffer; - namelist__destroy_buffer(p); -} diff --git a/dynare++/parser/cc/namelist.h b/dynare++/parser/cc/namelist.hh similarity index 100% rename from dynare++/parser/cc/namelist.h rename to dynare++/parser/cc/namelist.hh diff --git a/dynare++/parser/cc/namelist.lex b/dynare++/parser/cc/namelist.ll similarity index 97% rename from dynare++/parser/cc/namelist.lex rename to dynare++/parser/cc/namelist.ll index 0a14f904f97dc0068f678ff562f283c4cb8782f0..506ef997037f80c8c3cd157d797e984fc147fecc 100644 --- a/dynare++/parser/cc/namelist.lex +++ b/dynare++/parser/cc/namelist.ll @@ -1,5 +1,5 @@ %{ -#include "location.h" +#include "location.hh" #include "namelist_tab.hh" extern YYLTYPE namelist_lloc; diff --git a/dynare++/parser/cc/namelist.y b/dynare++/parser/cc/namelist.yy similarity index 93% rename from dynare++/parser/cc/namelist.y rename to dynare++/parser/cc/namelist.yy index 7d41d4890b20c306115fc93b86409ab5f3510872..762e478547aaeb10a1662bcc44d0e91d3450facb 100644 --- a/dynare++/parser/cc/namelist.y +++ b/dynare++/parser/cc/namelist.yy @@ -1,8 +1,8 @@ // Copyright (C) 2007-2011, Ondra Kamenik %{ -#include "location.h" -#include "namelist.h" +#include "location.hh" +#include "namelist.hh" #include "namelist_tab.hh" void namelist_error(const char*); diff --git a/dynare++/parser/cc/parser_exception.cc b/dynare++/parser/cc/parser_exception.cc new file mode 100644 index 0000000000000000000000000000000000000000..e9512b58247700033a2ec9dce421d68f7c9259ef --- /dev/null +++ b/dynare++/parser/cc/parser_exception.cc @@ -0,0 +1,118 @@ +// Copyright (C) 2006, Ondra Kamenik + +// $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), + 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), + 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), + 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), + 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(NULL), + 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(NULL), + aux_i1(-1), aux_i2(-1), aux_i3(-1) +{ + copy(m); + aux_i3 = m.aux_i2; + aux_i2 = m.aux_i1; + aux_i1 = i; +} + +ParserException::ParserException(const ParserException &m, const char *dum, int i1, int i2) + : mes(NULL), + aux_i1(-1), aux_i2(-1), aux_i3(-1) +{ + copy(m); + aux_i3 = m.aux_i1; + aux_i2 = i2; + aux_i1 = i1; +} + +ParserException::ParserException(const ParserException &m, const char *dum, int i1, int i2, int i3) + : mes(NULL), + aux_i1(-1), aux_i2(-1), aux_i3(-1) +{ + copy(m); + aux_i3 = i3; + aux_i2 = i2; + aux_i1 = i1; +} + +ParserException::ParserException(const ParserException &e) + : mes(NULL), + 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); + 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); +} diff --git a/dynare++/parser/cc/parser_exception.cpp b/dynare++/parser/cc/parser_exception.cpp deleted file mode 100644 index fbd0e28f95cf8b5b20bcb3304e1fadf0326fcc54..0000000000000000000000000000000000000000 --- a/dynare++/parser/cc/parser_exception.cpp +++ /dev/null @@ -1,117 +0,0 @@ -// Copyright (C) 2006, Ondra Kamenik - -// $Id: parser_exception.cpp 2269 2008-11-23 14:33:22Z michel $ - -#include "parser_exception.h" -#include <cstring> -#include <cstdio> - -using namespace ogp; - -ParserException::ParserException(const char* m, int offset) - : mes(new char[strlen(m)+1]), 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), - 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), - 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), - 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(NULL), - 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(NULL), - aux_i1(-1), aux_i2(-1), aux_i3(-1) -{ - copy(m); - aux_i3 = m.aux_i2; - aux_i2 = m.aux_i1; - aux_i1 = i; -} - -ParserException::ParserException(const ParserException& m, const char* dum, int i1, int i2) - : mes(NULL), - aux_i1(-1), aux_i2(-1), aux_i3(-1) -{ - copy(m); - aux_i3 = m.aux_i1; - aux_i2 = i2; - aux_i1 = i1; -} - -ParserException::ParserException(const ParserException& m, const char* dum, int i1, int i2, int i3) - : mes(NULL), - aux_i1(-1), aux_i2(-1), aux_i3(-1) -{ - copy(m); - aux_i3 = i3; - aux_i2 = i2; - aux_i1 = i1; -} - - -ParserException::ParserException(const ParserException& e) - : mes(NULL), - 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); - 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); -} diff --git a/dynare++/parser/cc/parser_exception.h b/dynare++/parser/cc/parser_exception.hh similarity index 100% rename from dynare++/parser/cc/parser_exception.h rename to dynare++/parser/cc/parser_exception.hh diff --git a/dynare++/parser/cc/static_atoms.cc b/dynare++/parser/cc/static_atoms.cc new file mode 100644 index 0000000000000000000000000000000000000000..288f2a37a08e78807fb668013bf8f7c2645e6489 --- /dev/null +++ b/dynare++/parser/cc/static_atoms.cc @@ -0,0 +1,141 @@ +// Copyright (C) 2006, Ondra Kamenik + +// $Id: static_atoms.cpp 1360 2007-07-10 11:44:20Z kamenik $ + +#include "static_atoms.hh" +#include "utils/cc/exception.hh" + +using namespace ogp; + +StaticAtoms::StaticAtoms(const StaticAtoms &a) + : Atoms(), Constants(a), varnames(a.varnames), + varorder(), vars(), indices() +{ + // fill varorder + for (unsigned int i = 0; i < a.varorder.size(); i++) + { + const char *s = varnames.query(a.varorder[i]); + varorder.push_back(s); + } + + // fill vars + for (Tvarmap::const_iterator it = a.vars.begin(); + it != a.vars.end(); ++it) + { + const char *s = varnames.query((*it).first); + vars.insert(Tvarmap::value_type(s, (*it).second)); + } + + // fill indices + for (Tinvmap::const_iterator it = a.indices.begin(); + it != a.indices.end(); ++it) + { + const char *s = varnames.query((*it).second); + indices.insert(Tinvmap::value_type((*it).first, s)); + } +} + +void +StaticAtoms::import_atoms(const DynamicAtoms &da, OperationTree &otree, Tintintmap &tmap) +{ + Constants::import_constants(da, otree, tmap); + + for (int i = 0; i < da.get_name_storage().num(); i++) + { + const char *name = da.get_name_storage().get_name(i); + register_name(name); + int tnew = otree.add_nulary(); + assign(name, tnew); + if (da.is_referenced(name)) + { + const DynamicAtoms::Tlagmap &lmap = da.lagmap(name); + for (DynamicAtoms::Tlagmap::const_iterator it = lmap.begin(); + it != lmap.end(); ++it) + { + int told = (*it).second; + tmap.insert(Tintintmap::value_type(told, tnew)); + } + } + } +} + +int +StaticAtoms::check(const char *name) const +{ + if (DynamicAtoms::is_string_constant(name)) + { + return Constants::check(name); + } + else + { + return check_variable(name); + } +} + +int +StaticAtoms::index(const char *name) const +{ + Tvarmap::const_iterator it = vars.find(name); + if (it == vars.end()) + return -1; + else + return (*it).second; +} + +const char * +StaticAtoms::inv_index(int t) const +{ + Tinvmap::const_iterator it = indices.find(t); + if (it == indices.end()) + return NULL; + else + return (*it).second; +} + +void +StaticAtoms::assign(const char *name, int t) +{ + if (DynamicAtoms::is_string_constant(name)) + { + double val; + sscanf(name, "%lf", &val); + add_constant(t, val); + } + else + { + const char *ss = varnames.insert(name); + vars.insert(Tvarmap::value_type(ss, t)); + indices.insert(Tinvmap::value_type(t, ss)); + } +} + +vector<int> +StaticAtoms::variables() const +{ + vector<int> res; + for (Tvarmap::const_iterator it = vars.begin(); + it != vars.end(); ++it) + { + res.push_back((*it).second); + } + return res; +} + +void +StaticAtoms::register_name(const char *name) +{ + const char *ss = varnames.insert(name); + varorder.push_back(ss); +} + +void +StaticAtoms::print() const +{ + printf("constants:\n"); + Constants::print(); + printf("variable names:\n"); + varnames.print(); + printf("map to tree indices:\n"); + for (Tvarmap::const_iterator it = vars.begin(); it != vars.end(); ++it) + printf("%s\t->\t%d\n", (*it).first, (*it).second); +} diff --git a/dynare++/parser/cc/static_atoms.cpp b/dynare++/parser/cc/static_atoms.cpp deleted file mode 100644 index 7276cc0c9a90e9b40dd39f0a6dff566e99e317de..0000000000000000000000000000000000000000 --- a/dynare++/parser/cc/static_atoms.cpp +++ /dev/null @@ -1,121 +0,0 @@ -// Copyright (C) 2006, Ondra Kamenik - -// $Id: static_atoms.cpp 1360 2007-07-10 11:44:20Z kamenik $ - -#include "static_atoms.h" -#include "utils/cc/exception.h" - -using namespace ogp; - -StaticAtoms::StaticAtoms(const StaticAtoms& a) - : Atoms(), Constants(a), varnames(a.varnames), - varorder(), vars(), indices() -{ - // fill varorder - for (unsigned int i = 0; i < a.varorder.size(); i++) { - const char* s = varnames.query(a.varorder[i]); - varorder.push_back(s); - } - - // fill vars - for (Tvarmap::const_iterator it = a.vars.begin(); - it != a.vars.end(); ++it) { - const char* s = varnames.query((*it).first); - vars.insert(Tvarmap::value_type(s, (*it).second)); - } - - // fill indices - for (Tinvmap::const_iterator it = a.indices.begin(); - it != a.indices.end(); ++it) { - const char* s = varnames.query((*it).second); - indices.insert(Tinvmap::value_type((*it).first, s)); - } -} - -void StaticAtoms::import_atoms(const DynamicAtoms& da, OperationTree& otree, Tintintmap& tmap) -{ - Constants::import_constants(da, otree, tmap); - - for (int i = 0; i < da.get_name_storage().num(); i++) { - const char* name = da.get_name_storage().get_name(i); - register_name(name); - int tnew = otree.add_nulary(); - assign(name, tnew); - if (da.is_referenced(name)) { - const DynamicAtoms::Tlagmap& lmap = da.lagmap(name); - for (DynamicAtoms::Tlagmap::const_iterator it = lmap.begin(); - it != lmap.end(); ++it) { - int told = (*it).second; - tmap.insert(Tintintmap::value_type(told, tnew)); - } - } - } -} - - -int StaticAtoms::check(const char* name) const -{ - if (DynamicAtoms::is_string_constant(name)) { - return Constants::check(name); - } else { - return check_variable(name); - } -} - -int StaticAtoms::index(const char* name) const -{ - Tvarmap::const_iterator it = vars.find(name); - if (it == vars.end()) - return -1; - else - return (*it).second; -} - -const char* StaticAtoms::inv_index(int t) const -{ - Tinvmap::const_iterator it = indices.find(t); - if (it == indices.end()) - return NULL; - else - return (*it).second; -} - -void StaticAtoms::assign(const char* name, int t) -{ - if (DynamicAtoms::is_string_constant(name)) { - double val; - sscanf(name, "%lf", &val); - add_constant(t, val); - } else { - const char* ss = varnames.insert(name); - vars.insert(Tvarmap::value_type(ss, t)); - indices.insert(Tinvmap::value_type(t, ss)); - } -} - -vector<int> StaticAtoms::variables() const -{ - vector<int> res; - for (Tvarmap::const_iterator it = vars.begin(); - it != vars.end(); ++it) { - res.push_back((*it).second); - } - return res; -} - -void StaticAtoms::register_name(const char* name) -{ - const char* ss = varnames.insert(name); - varorder.push_back(ss); -} - -void StaticAtoms::print() const -{ - printf("constants:\n"); - Constants::print(); - printf("variable names:\n"); - varnames.print(); - printf("map to tree indices:\n"); - for (Tvarmap::const_iterator it = vars.begin(); it != vars.end(); ++it) - printf("%s\t->\t%d\n", (*it).first, (*it).second); -} diff --git a/dynare++/parser/cc/static_atoms.h b/dynare++/parser/cc/static_atoms.hh similarity index 99% rename from dynare++/parser/cc/static_atoms.h rename to dynare++/parser/cc/static_atoms.hh index e94825d2933f49f2f7e5b2c72ce7732ad03a385e..cb362dea1caf33c323066790397412c7b95b3129 100644 --- a/dynare++/parser/cc/static_atoms.h +++ b/dynare++/parser/cc/static_atoms.hh @@ -5,7 +5,7 @@ #ifndef OGP_STATIC_ATOMS #define OGP_STATIC_ATOMS -#include "dynamic_atoms.h" +#include "dynamic_atoms.hh" namespace ogp { diff --git a/dynare++/parser/cc/static_fine_atoms.cc b/dynare++/parser/cc/static_fine_atoms.cc new file mode 100644 index 0000000000000000000000000000000000000000..807e9df8c6fa9a099b5ef3acf068470e43eed86c --- /dev/null +++ b/dynare++/parser/cc/static_fine_atoms.cc @@ -0,0 +1,237 @@ +// Copyright (C) 2006, Ondra Kamenik + +// $Id: static_fine_atoms.cpp 82 2007-04-19 11:33:30Z ondra $ + +#include "utils/cc/exception.hh" + +#include "static_fine_atoms.hh" +#include "parser_exception.hh" + +using namespace ogp; + +StaticFineAtoms::StaticFineAtoms(const StaticFineAtoms &sfa) + : StaticAtoms(sfa), + params(), param_outer_map(), + endovars(), endo_outer_map(), + exovars(), exo_outer_map(), + der_atoms(sfa.der_atoms), + endo_atoms_map(sfa.endo_atoms_map), + exo_atoms_map(sfa.exo_atoms_map) +{ + for (unsigned int i = 0; i < sfa.params.size(); i++) + { + const char *name = varnames.query(sfa.params[i]); + params.push_back(name); + param_outer_map.insert(Tvarintmap::value_type(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)); + } + + 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)); + } +} + +void +StaticFineAtoms::import_atoms(const FineAtoms &fa, OperationTree &otree, Tintintmap &tmap) +{ + StaticAtoms::import_atoms(fa, otree, tmap); + + // we just need to put parameters, endovars, and exovars to + // respective vectors, the names are already in the storage + + // parameters + const vector<const char *> &fa_params = fa.get_params(); + for (unsigned int i = 0; i < fa_params.size(); i++) + register_param(fa_params[i]); + + // endogenous + const vector<const char *> &fa_endovars = fa.get_endovars(); + for (unsigned int i = 0; i < fa_endovars.size(); i++) + register_endo(fa_endovars[i]); + + // exogenous + const vector<const char *> &fa_exovars = fa.get_exovars(); + for (unsigned int i = 0; i < fa_exovars.size(); i++) + register_exo(fa_exovars[i]); + + parsing_finished(); +} + +void +StaticFineAtoms::import_atoms(const FineAtoms &fa, OperationTree &otree, Tintintmap &tmap, + const char *dummy) +{ + StaticAtoms::import_atoms(fa, otree, tmap); + + // we just need to put parameters, endovars, and exovars to + // respective vectors, the names are already in the storage + + // parameters + const vector<const char *> &fa_params = fa.get_params(); + for (unsigned int i = 0; i < fa_params.size(); i++) + register_param(fa_params[i]); + + // endogenous + const vector<const char *> &fa_endovars = fa.get_endovars(); + for (unsigned int i = 0; i < fa_endovars.size(); i++) + register_endo(fa_endovars[fa.y2outer_endo()[i]]); + + // exogenous + const vector<const char *> &fa_exovars = fa.get_exovars(); + for (unsigned int i = 0; i < fa_exovars.size(); i++) + register_exo(fa_exovars[fa.y2outer_exo()[i]]); + + parsing_finished(); +} + +int +StaticFineAtoms::check_variable(const char *name) const +{ + const char *ss = varnames.query(name); + if (ss == NULL) + throw ParserException(string("Variable <")+name+"> not declared.", 0); + return index(name); +} + +void +StaticFineAtoms::parsing_finished() +{ + // build der_atoms, and endo_atoms_map and exo_atoms_map + der_atoms.clear(); + endo_atoms_map.clear(); + exo_atoms_map.clear(); + + // go through all endo and exo insert tree indices, ignore names + // whose tree index is -1 (those which are not referenced) + for (unsigned int i = 0; i < endovars.size(); i++) + { + int t = index(endovars[i]); + if (t != -1) + { + endo_atoms_map.push_back(der_atoms.size()); + der_atoms.push_back(t); + } + } + for (unsigned int i = 0; i < exovars.size(); i++) + { + int t = index(exovars[i]); + if (t != -1) + { + exo_atoms_map.push_back(der_atoms.size()); + der_atoms.push_back(t); + } + } +} + +int +StaticFineAtoms::name2outer_param(const char *name) const +{ + Tvarintmap::const_iterator it = param_outer_map.find(name); + if (it == param_outer_map.end()) + throw ogu::Exception(__FILE__, __LINE__, + "Name is not a parameter in StaticFineAtoms::name2outer_param"); + return (*it).second; +} + +int +StaticFineAtoms::name2outer_endo(const char *name) const +{ + Tvarintmap::const_iterator it = endo_outer_map.find(name); + if (it == endo_outer_map.end()) + throw ogu::Exception(__FILE__, __LINE__, + "Name is not an endogenous variable in StaticFineAtoms::name2outer_endo"); + return (*it).second; +} + +int +StaticFineAtoms::name2outer_exo(const char *name) const +{ + Tvarintmap::const_iterator it = exo_outer_map.find(name); + if (it == exo_outer_map.end()) + throw ogu::Exception(__FILE__, __LINE__, + "Name is not an exogenous variable in StaticFineAtoms::name2outer_exo"); + return (*it).second; +} + +void +StaticFineAtoms::register_uniq_endo(const char *name) +{ + if (varnames.query(name)) + throw ogp::ParserException(string("Endogenous variable <")+name+"> is not unique.", 0); + const char *ss = varnames.insert(name); + register_endo(ss); +} + +void +StaticFineAtoms::register_uniq_exo(const char *name) +{ + if (varnames.query(name)) + throw ogp::ParserException(string("Exogenous variable <")+name+"> is not unique.", 0); + const char *ss = varnames.insert(name); + register_exo(ss); +} + +void +StaticFineAtoms::register_uniq_param(const char *name) +{ + if (varnames.query(name)) + throw ogp::ParserException(string("Parameter <")+name+"> is not unique.", 0); + const char *ss = varnames.insert(name); + register_param(ss); +} + +void +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("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("der atoms:\n"); + for (unsigned int i = 0; i < der_atoms.size(); i++) + printf("%d\t%d\n", i, der_atoms[i]); +} + +void +StaticFineAtoms::register_endo(const char *name) +{ + const char *ss = varnames.query(name); + if (ss == NULL) + 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)); +} + +void +StaticFineAtoms::register_exo(const char *name) +{ + const char *ss = varnames.query(name); + if (ss == NULL) + 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)); +} + +void +StaticFineAtoms::register_param(const char *name) +{ + const char *ss = varnames.query(name); + if (ss == NULL) + 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)); +} diff --git a/dynare++/parser/cc/static_fine_atoms.cpp b/dynare++/parser/cc/static_fine_atoms.cpp deleted file mode 100644 index 9c5f90a14ea441229ba8e7402a871c643b359697..0000000000000000000000000000000000000000 --- a/dynare++/parser/cc/static_fine_atoms.cpp +++ /dev/null @@ -1,217 +0,0 @@ -// Copyright (C) 2006, Ondra Kamenik - -// $Id: static_fine_atoms.cpp 82 2007-04-19 11:33:30Z ondra $ - -#include "utils/cc/exception.h" - -#include "static_fine_atoms.h" -#include "parser_exception.h" - -using namespace ogp; - -StaticFineAtoms::StaticFineAtoms(const StaticFineAtoms& sfa) - : StaticAtoms(sfa), - params(), param_outer_map(), - endovars(), endo_outer_map(), - exovars(), exo_outer_map(), - der_atoms(sfa.der_atoms), - endo_atoms_map(sfa.endo_atoms_map), - exo_atoms_map(sfa.exo_atoms_map) -{ - for (unsigned int i = 0; i < sfa.params.size(); i++) { - const char* name = varnames.query(sfa.params[i]); - params.push_back(name); - param_outer_map.insert(Tvarintmap::value_type(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)); - } - - 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)); - } -} - -void StaticFineAtoms::import_atoms(const FineAtoms& fa, OperationTree& otree, Tintintmap& tmap) -{ - StaticAtoms::import_atoms(fa, otree, tmap); - - // we just need to put parameters, endovars, and exovars to - // respective vectors, the names are already in the storage - - // parameters - const vector<const char*>& fa_params = fa.get_params(); - for (unsigned int i = 0; i < fa_params.size(); i++) - register_param(fa_params[i]); - - // endogenous - const vector<const char*>& fa_endovars = fa.get_endovars(); - for (unsigned int i = 0; i < fa_endovars.size(); i++) - register_endo(fa_endovars[i]); - - // exogenous - const vector<const char*>& fa_exovars = fa.get_exovars(); - for (unsigned int i = 0; i < fa_exovars.size(); i++) - register_exo(fa_exovars[i]); - - parsing_finished(); -} - -void StaticFineAtoms::import_atoms(const FineAtoms& fa, OperationTree& otree, Tintintmap& tmap, - const char* dummy) -{ - StaticAtoms::import_atoms(fa, otree, tmap); - - // we just need to put parameters, endovars, and exovars to - // respective vectors, the names are already in the storage - - // parameters - const vector<const char*>& fa_params = fa.get_params(); - for (unsigned int i = 0; i < fa_params.size(); i++) - register_param(fa_params[i]); - - // endogenous - const vector<const char*>& fa_endovars = fa.get_endovars(); - for (unsigned int i = 0; i < fa_endovars.size(); i++) - register_endo(fa_endovars[fa.y2outer_endo()[i]]); - - // exogenous - const vector<const char*>& fa_exovars = fa.get_exovars(); - for (unsigned int i = 0; i < fa_exovars.size(); i++) - register_exo(fa_exovars[fa.y2outer_exo()[i]]); - - parsing_finished(); -} - -int StaticFineAtoms::check_variable(const char* name) const -{ - const char* ss = varnames.query(name); - if (ss == NULL) - throw ParserException(string("Variable <")+name+"> not declared.",0); - return index(name); -} - -void StaticFineAtoms::parsing_finished() -{ - // build der_atoms, and endo_atoms_map and exo_atoms_map - der_atoms.clear(); - endo_atoms_map.clear(); - exo_atoms_map.clear(); - - // go through all endo and exo insert tree indices, ignore names - // whose tree index is -1 (those which are not referenced) - for (unsigned int i = 0; i < endovars.size(); i++) { - int t = index(endovars[i]); - if (t != -1) { - endo_atoms_map.push_back(der_atoms.size()); - der_atoms.push_back(t); - } - } - for (unsigned int i = 0; i < exovars.size(); i++) { - int t = index(exovars[i]); - if (t != -1) { - exo_atoms_map.push_back(der_atoms.size()); - der_atoms.push_back(t); - } - } -} - -int StaticFineAtoms::name2outer_param(const char* name) const -{ - Tvarintmap::const_iterator it = param_outer_map.find(name); - if (it == param_outer_map.end()) - throw ogu::Exception(__FILE__,__LINE__, - "Name is not a parameter in StaticFineAtoms::name2outer_param"); - return (*it).second; -} - -int StaticFineAtoms::name2outer_endo(const char* name) const -{ - Tvarintmap::const_iterator it = endo_outer_map.find(name); - if (it == endo_outer_map.end()) - throw ogu::Exception(__FILE__,__LINE__, - "Name is not an endogenous variable in StaticFineAtoms::name2outer_endo"); - return (*it).second; -} - -int StaticFineAtoms::name2outer_exo(const char* name) const -{ - Tvarintmap::const_iterator it = exo_outer_map.find(name); - if (it == exo_outer_map.end()) - throw ogu::Exception(__FILE__,__LINE__, - "Name is not an exogenous variable in StaticFineAtoms::name2outer_exo"); - return (*it).second; -} - -void StaticFineAtoms::register_uniq_endo(const char* name) -{ - if (varnames.query(name)) - throw ogp::ParserException(string("Endogenous variable <")+name+"> is not unique.",0); - const char* ss = varnames.insert(name); - register_endo(ss); -} - -void StaticFineAtoms::register_uniq_exo(const char* name) -{ - if (varnames.query(name)) - throw ogp::ParserException(string("Exogenous variable <")+name+"> is not unique.",0); - const char* ss = varnames.insert(name); - register_exo(ss); -} - -void StaticFineAtoms::register_uniq_param(const char* name) -{ - if (varnames.query(name)) - throw ogp::ParserException(string("Parameter <")+name+"> is not unique.",0); - const char* ss = varnames.insert(name); - register_param(ss); -} - -void 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("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("der atoms:\n"); - for (unsigned int i = 0; i < der_atoms.size(); i++) - printf("%d\t%d\n",i, der_atoms[i]); -} - -void StaticFineAtoms::register_endo(const char* name) -{ - const char* ss = varnames.query(name); - if (ss == NULL) - 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)); -} - -void StaticFineAtoms::register_exo(const char* name) -{ - const char* ss = varnames.query(name); - if (ss == NULL) - 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)); -} - -void StaticFineAtoms::register_param(const char* name) -{ - const char* ss = varnames.query(name); - if (ss == NULL) - 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)); -} - diff --git a/dynare++/parser/cc/static_fine_atoms.h b/dynare++/parser/cc/static_fine_atoms.hh similarity index 99% rename from dynare++/parser/cc/static_fine_atoms.h rename to dynare++/parser/cc/static_fine_atoms.hh index c4247f4a737b815e08fb00e91b97b4710248c572..7d2758ea20363e6315a9eb24cebfbebb45bfbb15 100644 --- a/dynare++/parser/cc/static_fine_atoms.h +++ b/dynare++/parser/cc/static_fine_atoms.hh @@ -5,8 +5,8 @@ #ifndef OGP_STATIC_FINE_ATOMS_H #define OGP_STATIC_FINE_ATOMS_H -#include "static_atoms.h" -#include "fine_atoms.h" +#include "static_atoms.hh" +#include "fine_atoms.hh" namespace ogp { diff --git a/dynare++/parser/cc/tree.cc b/dynare++/parser/cc/tree.cc new file mode 100644 index 0000000000000000000000000000000000000000..200500d9f2b835a0b66f8ba2a1b9a28b67e97b75 --- /dev/null +++ b/dynare++/parser/cc/tree.cc @@ -0,0 +1,1036 @@ +// Copyright (C) 2005-2011, Ondra Kamenik + +#include "utils/cc/exception.hh" + +#include "tree.hh" + +#include <cstdlib> + +#include <cmath> +#include <limits> + +#ifdef __MINGW32__ +# define __CROSS_COMPILATION__ +#endif + +#ifdef __MINGW64__ +# define __CROSS_COMPILATION__ +#endif + +#ifdef __CROSS_COMPILATION__ +# define M_PI 3.14159265358979323846 +#endif + +using namespace ogp; + +/** Here we just implement complementary error function without + * declaring it for uses from outside this unit. The implementation is taken from "Numerical Recipes in C" 2nd ed. 1992 p. 221, */ +double +erffc(double x) +{ + double z = std::abs(x); + double t = 1/(1+0.5*z); + double r = t*exp(-z*z-1.26551223+t*(1.00002368+t*(0.37409196+t*(0.09678418+t*(-0.18628806+t*(0.27886807+t*(-1.13520398+t*(1.48851587+t*(-0.82215223+t*0.17087277))))))))); + return x >= 0 ? r : 2-r; +} + +/** Here we initialize OperationTree to contain only zero, one, nan + * and two_over_pi terms. */ +OperationTree::OperationTree() +{ + last_nulary = -1; + // allocate space for the constants + for (int i = 0; i < num_constants; i++) + add_nulary(); +} + +int +OperationTree::add_nulary() +{ + int op = terms.size(); + Operation nulary; + terms.push_back(nulary); + _Tintset s; + s.insert(op); + nul_incidence.push_back(s); + _Tderivmap empty; + derivatives.push_back(empty); + last_nulary = op; + return op; +} + +int +OperationTree::add_unary(code_t code, int op) +{ + if (op == zero + && (code == UMINUS + || code == SIN + || code == TAN + || code == SQRT + || code == ERF)) + return zero; + if ((op == zero && code == LOG) || op == nan) + return nan; + if (op == zero && (code == EXP + || code == COS + || code == ERFC)) + return one; + + Operation unary(code, op); + _Topmap::const_iterator i = ((const _Topmap &) opmap).find(unary); + if (i == opmap.end()) + { + int newop = terms.size(); + // add to the terms + terms.push_back(unary); + // copy incidence of the operand + nul_incidence.push_back(nul_incidence[op]); + // insert it to opmap + opmap.insert(_Topval(unary, newop)); + // add empty map of derivatives + _Tderivmap empty; + derivatives.push_back(empty); + return newop; + } + return (*i).second; +} + +int +OperationTree::add_binary(code_t code, int op1, int op2) +{ + // quick exits for special values + if (op1 == nan || op2 == nan) + return nan; + // for plus + if (code == PLUS) + { + if (op1 == zero && op2 == zero) + return zero; + else if (op1 == zero) + return op2; + else if (op2 == zero) + return op1; + } + // for minus + if (code == MINUS) + { + if (op1 == zero && op2 == zero) + return zero; + else if (op1 == zero) + return add_unary(UMINUS, op2); + else if (op2 == zero) + return op1; + } + // for times + if (code == TIMES) + { + if (op1 == zero || op2 == zero) + return zero; + else if (op1 == one) + return op2; + else if (op2 == one) + return op1; + } + // for divide + if (code == DIVIDE) + { + if (op1 == op2) + return one; + else if (op1 == zero) + return zero; + else if (op2 == zero) + return nan; + } + // for power + if (code == POWER) + { + if (op1 == zero && op2 == zero) + return nan; + else if (op1 == zero) + return zero; + else if (op2 == zero) + return one; + else if (op1 == one) + return one; + else if (op2 == one) + return op1; + } + + // order operands of commutative operations + if (code == TIMES || code == PLUS) + if (op1 > op2) + { + int tmp = op1; + op1 = op2; + op2 = tmp; + } + + // construct operation and check/add it + Operation binary(code, op1, op2); + _Topmap::const_iterator i = ((const _Topmap &) opmap).find(binary); + if (i == opmap.end()) + { + int newop = terms.size(); + terms.push_back(binary); + // sum both sets of incidenting nulary operations + 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)); + // add empty map of derivatives + _Tderivmap empty; + derivatives.push_back(empty); + return newop; + } + return (*i).second; +} + +int +OperationTree::add_derivative(int t, int v) +{ + if (t < 0 || t >= (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; + } + if (terms[t].nary() == 0 && t == v) + { + return one; + } + if (nul_incidence[t].end() == nul_incidence[t].find(v)) + { + return zero; + } + + // quick return if the derivative has been registered + _Tderivmap::const_iterator i = derivatives[t].find(v); + if (i != derivatives[t].end()) + return (*i).second; + + int res = -1; + switch (terms[t].getCode()) + { + + case UMINUS: + { + int tmp = add_derivative(terms[t].getOp1(), v); + res = add_unary(UMINUS, tmp); + break; + } + case LOG: + { + int tmp = add_derivative(terms[t].getOp1(), v); + res = add_binary(DIVIDE, tmp, terms[t].getOp1()); + break; + } + case EXP: + { + int tmp = add_derivative(terms[t].getOp1(), v); + res = add_binary(TIMES, t, tmp); + break; + } + case SIN: + { + int tmp = add_derivative(terms[t].getOp1(), v); + res = add_binary(TIMES, add_unary(COS, terms[t].getOp1()), tmp); + break; + } + case COS: + { + int tmp = add_derivative(terms[t].getOp1(), v); + res = add_unary(UMINUS, add_binary(TIMES, add_unary(SIN, terms[t].getOp1()), tmp)); + break; + } + case 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)); + break; + } + case SQRT: + { + int tmp = add_derivative(terms[t].getOp1(), v); + res = add_binary(DIVIDE, tmp, + add_binary(PLUS, t, t)); + break; + } + case ERF: + { + int tmp = add_binary(TIMES, terms[t].getOp1(), terms[t].getOp1()); + tmp = add_unary(UMINUS, tmp); + tmp = add_unary(EXP, tmp); + int der = add_derivative(terms[t].getOp1(), v); + tmp = add_binary(TIMES, tmp, der); + res = add_binary(TIMES, two_over_pi, tmp); + break; + } + case ERFC: + { + int tmp = add_binary(TIMES, terms[t].getOp1(), terms[t].getOp1()); + tmp = add_unary(UMINUS, tmp); + tmp = add_unary(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); + break; + } + case PLUS: + { + int tmp1 = add_derivative(terms[t].getOp1(), v); + int tmp2 = add_derivative(terms[t].getOp2(), v); + res = add_binary(PLUS, tmp1, tmp2); + break; + } + case MINUS: + { + int tmp1 = add_derivative(terms[t].getOp1(), v); + int tmp2 = add_derivative(terms[t].getOp2(), v); + res = add_binary(MINUS, tmp1, tmp2); + break; + } + case 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); + break; + } + case 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()); + 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); + } + break; + } + case 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); + break; + } + case NONE: + break; + } + + if (res == -1) + throw ogu::Exception(__FILE__, __LINE__, + "Unknown operation code."); + + register_derivative(t, v, res); + + return res; +} + +int +OperationTree::add_substitution(int t, const map<int, int> &subst) +{ + return add_substitution(t, subst, *this); +} + +int +OperationTree::add_substitution(int t, const map<int, int> &subst, + const OperationTree &otree) +{ + // return substitution of t if it is in the map + map<int, int>::const_iterator it = subst.find(t); + if (subst.end() != it) + return (*it).second; + + int nary = otree.terms[t].nary(); + if (nary == 2) + { + // return the binary operation of the substituted terms + int t1 = add_substitution(otree.terms[t].getOp1(), subst, otree); + int t2 = add_substitution(otree.terms[t].getOp2(), subst, otree); + return add_binary(otree.terms[t].getCode(), t1, t2); + } + else if (nary == 1) + { + // return the unary operation of the substituted term + int t1 = add_substitution(otree.terms[t].getOp1(), subst, otree); + return add_unary(otree.terms[t].getCode(), t1); + } + else + { + // if t is not the first num_constants, and otree is not this + // tree, then raise and exception. Otherwise return t, since + // it is either a special term (having the same semantics in + // both trees), or the trees are the same, hence t has the + // same semantics + if (t < num_constants || this == &otree) + return t; + else + { + throw ogu::Exception(__FILE__, __LINE__, + "Incomplete substitution map in OperationTree::add_substitution"); + return -1; + } + } +} + +void +OperationTree::nularify(int t) +{ + // remove the original operation from opmap + _Topmap::iterator it = opmap.find(terms[t]); + if (it != opmap.end()) + opmap.erase(it); + // turn the operation to nulary + Operation nulary_op; + terms[t] = nulary_op; + // update last nulary + if (last_nulary < t) + last_nulary = t; + // update nul_incidence information for all terms including t + update_nul_incidence_after_nularify(t); +} + +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)); +} + +unordered_set<int> +OperationTree::select_terms(int t, const opselector &sel) const +{ + unordered_set<int> subterms; + select_terms(t, sel, subterms); + return subterms; +} + +void +OperationTree::select_terms(int t, const opselector &sel, unordered_set<int> &subterms) const +{ + const Operation &op = terms[t]; + + if (sel(t)) + subterms.insert(t); + else + if (op.nary() == 2) + { + select_terms(op.getOp1(), sel, subterms); + select_terms(op.getOp2(), sel, subterms); + } + else if (op.nary() == 1) + { + select_terms(op.getOp1(), sel, subterms); + } +} + +unordered_set<int> +OperationTree::select_terms_inv(int t, const opselector &sel) const +{ + unordered_set<int> subterms; + select_terms_inv(t, sel, subterms); + return subterms; +} + +bool +OperationTree::select_terms_inv(int t, const opselector &sel, unordered_set<int> &subterms) const +{ + const Operation &op = terms[t]; + + if (op.nary() == 2) + { + bool a1 = select_terms_inv(op.getOp1(), sel, subterms); + bool a2 = select_terms_inv(op.getOp2(), sel, subterms); + if (a1 && a2 && sel(t)) + { + subterms.insert(t); + return true; + } + } + else if (op.nary() == 1) + { + bool a1 = select_terms_inv(op.getOp1(), sel, subterms); + if (a1 && sel(t)) + { + subterms.insert(t); + return true; + } + } + else + { + if (sel(t)) + { + subterms.insert(t); + return true; + } + } + + return false; +} + +void +OperationTree::forget_derivative_maps() +{ + for (unsigned int i = 0; i < derivatives.size(); i++) + derivatives[i].clear(); +} + +void +OperationTree::print_operation_tree(int t, FILE *fd, OperationFormatter &f) const +{ + f.format(terms[t], t, fd); +} + +void +OperationTree::print_operation(int t) const +{ + DefaultOperationFormatter dof(*this); + print_operation_tree(t, stdout, dof); +} + +void +OperationTree::update_nul_incidence_after_nularify(int t) +{ + unordered_set<int> updated; + for (int tnode = num_constants; tnode < (int) terms.size(); tnode++) + { + const Operation &op = terms[tnode]; + if (op.nary() == 2) + { + int op1 = op.getOp1(); + int op2 = op.getOp2(); + if (op1 >= tnode || op2 >= tnode) + throw ogu::Exception(__FILE__, __LINE__, + "Tree disorder asserted"); + bool updated1 = (updated.end() != updated.find(op1)); + bool updated2 = (updated.end() != updated.find(op2)); + if (updated1 || updated2) + { + nul_incidence[tnode] = nul_incidence[op1]; + nul_incidence[tnode].insert(nul_incidence[op2].begin(), nul_incidence[op2].end()); + updated.insert(tnode); + } + } + else if (op.nary() == 1) + { + int op1 = op.getOp1(); + if (op1 >= tnode) + throw ogu::Exception(__FILE__, __LINE__, + "Tree disorder asserted"); + bool updated1 = (updated.end() != updated.find(op1)); + if (updated1) + { + nul_incidence[tnode] = nul_incidence[op1]; + updated.insert(tnode); + } + } + else if (op.nary() == 0) + { + if (tnode == t) + { + nul_incidence[tnode].clear(); + nul_incidence[tnode].insert(tnode); + updated.insert(tnode); + } + } + } +} + +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]), + last_operation((last == -1) ? ot.terms.size()-1 : last) +{ + if (last_operation < OperationTree::num_constants-1 + || last_operation > (int) ot.terms.size()-1) + throw ogu::Exception(__FILE__, __LINE__, + "Wrong last in EvalTree constructor."); + + values[0] = 0.0; + flags[0] = true; + values[1] = 1.0; + flags[1] = true; + values[2] = std::numeric_limits<double>::quiet_NaN(); + flags[2] = true; + values[3] = 2.0/sqrt(M_PI); + flags[3] = true; + // this sets from num_constants on + reset_all(); +} + +void +EvalTree::reset_all() +{ + for (int i = OperationTree::num_constants; i <= last_operation; i++) + flags[i] = false; +} + +void +EvalTree::set_nulary(int t, double val) +{ + if (t < 0 || t > last_operation) + throw ogu::Exception(__FILE__, __LINE__, + "The tree index out of bounds in EvalTree::set_nulary"); + if (t < OperationTree::num_constants || otree.terms[t].nary() != 0) + throw ogu::Exception(__FILE__, __LINE__, + "The term is not nulary assignable in EvalTree::set_nulary"); + + values[t] = val; + flags[t] = true; +} + +double +EvalTree::eval(int t) +{ + if (t < 0 || t > last_operation) + throw ogu::Exception(__FILE__, __LINE__, + "The tree index out of bounds in EvalTree::eval"); + if (otree.terms[t].nary() == 0 && flags[t] == false) + throw ogu::Exception(__FILE__, __LINE__, + "Nulary term has not been assigned a value in EvalTree::eval"); + + if (!flags[t]) + { + const Operation &op = otree.terms[t]; + if (op.nary() == 1) + { + double r1 = eval(op.getOp1()); + double res; + if (op.getCode() == UMINUS) + res = -r1; + else if (op.getCode() == LOG) + res = log(r1); + else if (op.getCode() == EXP) + res = exp(r1); + else if (op.getCode() == SIN) + res = sin(r1); + else if (op.getCode() == COS) + res = cos(r1); + else if (op.getCode() == TAN) + res = tan(r1); + else if (op.getCode() == SQRT) + res = sqrt(r1); + else if (op.getCode() == ERF) + res = 1-erffc(r1); + else if (op.getCode() == ERFC) + res = erffc(r1); + else + { + throw ogu::Exception(__FILE__, __LINE__, + "Unknown unary operation code in EvalTree::eval"); + res = 0.0; + } + values[t] = res; + flags[t] = true; + } + else if (op.nary() == 2) + { + double res; + if (op.getCode() == PLUS) + { + double r1 = eval(op.getOp1()); + double r2 = eval(op.getOp2()); + res = r1 + r2; + } + else if (op.getCode() == MINUS) + { + double r1 = eval(op.getOp1()); + double r2 = eval(op.getOp2()); + res = r1 - r2; + } + else if (op.getCode() == TIMES) + { + // pickup less complex formula first + unsigned int nul1 = otree.nulary_of_term(op.getOp1()).size(); + unsigned int nul2 = otree.nulary_of_term(op.getOp2()).size(); + if (nul1 < nul2) + { + double r1 = eval(op.getOp1()); + if (r1 == 0.0) + res = 0.0; + else + { + double r2 = eval(op.getOp2()); + res = r1 * r2; + } + } + else + { + double r2 = eval(op.getOp2()); + if (r2 == 0) + res = 0.0; + else + { + double r1 = eval(op.getOp1()); + res = r1*r2; + } + } + } + else if (op.getCode() == DIVIDE) + { + double r1 = eval(op.getOp1()); + if (r1 == 0) + res = 0.0; + else + { + double r2 = eval(op.getOp2()); + res = r1 / r2; + } + } + else if (op.getCode() == POWER) + { + // suppose that more complex is the first op in average + double r2 = eval(op.getOp2()); + if (r2 == 0.0) + res = 1.0; + else + { + double r1 = eval(op.getOp1()); + res = pow(r1, r2); + } + } + else + { + throw ogu::Exception(__FILE__, __LINE__, + "Unknown binary operation code in EvalTree::eval"); + res = 0.0; + } + values[t] = res; + flags[t] = true; + } + return values[t]; + } + + // if (! std::isfinite(values[t])) + // printf("Tree value t=%d is not finite = %f\n", t, values[t]); + + return values[t]; +} + +void +EvalTree::print() const +{ + printf("last_op=%d\n", last_operation); + printf(" 0 1 2 3 4 5 6 7 8 9\n"); + printf("----------------------------------------------------------------\n"); + for (int i = 0; i <= (last_operation+1)/10; i++) + { + printf("%-3d|", i); + int j = 0; + while (j < 10 && 10*i+j < last_operation+1) + { + int k = 10*i+j; + if (flags[k]) + printf(" %5.1g", values[k]); + else + printf(" -----"); + j++; + } + printf("\n"); + } +} + +void +DefaultOperationFormatter::format(const Operation &op, int t, FILE *fd) +{ + // add to the stop_set + if (stop_set.end() == stop_set.find(t)) + stop_set.insert(t); + else + return; + + // call recursively non-nulary terms of the operation + if (op.nary() == 2) + { + int t1 = op.getOp1(); + const Operation &op1 = otree.terms[t1]; + int t2 = op.getOp2(); + const Operation &op2 = otree.terms[t2]; + if (op1.nary() > 0) + format(op1, t1, fd); + if (op2.nary() > 0) + format(op2, t2, fd); + } + if (op.nary() == 1) + { + int t1 = op.getOp1(); + const Operation &op1 = otree.terms[t1]; + if (op1.nary() > 0) + format(op1, t1, fd); + } + + // print 'term =' + format_term(t, fd); + fprintf(fd, " = "); + if (op.nary() == 0) + { + format_nulary(t, fd); + } + else if (op.nary() == 1) + { + int t1 = op.getOp1(); + const Operation &op1 = otree.terms[t1]; + const char *opname = "unknown"; + switch (op.getCode()) + { + case UMINUS: + opname = "-"; + break; + case LOG: + opname = "log"; + break; + case EXP: + opname = "exp"; + break; + case SIN: + opname = "sin"; + break; + case COS: + opname = "cos"; + break; + case TAN: + opname = "tan"; + break; + case SQRT: + opname = "sqrt"; + break; + case ERF: + opname = "erf"; + break; + case ERFC: + opname = "erfc"; + break; + default: + break; + } + fprintf(fd, "%s(", opname); + if (op1.nary() == 0) + format_nulary(t1, fd); + else + format_term(t1, fd); + fprintf(fd, ")"); + } + else + { + int t1 = op.getOp1(); + const Operation &op1 = otree.terms[t1]; + int t2 = op.getOp2(); + const Operation &op2 = otree.terms[t2]; + const char *opname = "unknown"; + switch (op.getCode()) + { + case PLUS: + opname = "+"; + break; + case MINUS: + opname = "-"; + break; + case TIMES: + opname = "*"; + break; + case DIVIDE: + opname = "/"; + break; + case POWER: + opname = "^"; + break; + default: + break; + } + if (op1.nary() == 0) + format_nulary(t1, fd); + else + format_term(t1, fd); + fprintf(fd, " %s ", opname); + if (op2.nary() == 0) + format_nulary(t2, fd); + else + format_term(t2, fd); + } + + print_delim(fd); + +} + +void +DefaultOperationFormatter::format_term(int t, FILE *fd) const +{ + fprintf(fd, "$%d", t); +} + +void +DefaultOperationFormatter::format_nulary(int t, FILE *fd) const +{ + if (t == OperationTree::zero) + fprintf(fd, "0"); + else if (t == OperationTree::one) + fprintf(fd, "1"); + else if (t == OperationTree::nan) + fprintf(fd, "NaN"); + else + fprintf(fd, "$%d", t); +} + +void +DefaultOperationFormatter::print_delim(FILE *fd) const +{ + fprintf(fd, ";\n"); +} + +std::string +OperationStringConvertor::convert(const Operation &op, int t) const +{ + if (op.nary() == 0) + { + if (t < OperationTree::num_constants) + if (t == OperationTree::zero) + return std::string("0"); + else if (t == OperationTree::one) + return std::string("1"); + else if (t == OperationTree::nan) + return std::string("NaN"); + else if (t == OperationTree::two_over_pi) + { + char buf[100]; + sprintf(buf, "%20.16g", 2.0/std::sqrt(M_PI)); + return std::string(buf); + } + else + { + return std::string("error!error"); + } + else + return nulsc.convert(t); + } + else if (op.nary() == 1) + { + int t1 = op.getOp1(); + const Operation &op1 = otree.operation(t1); + const char *opname = "unknown"; + switch (op.getCode()) + { + case UMINUS: + opname = "-"; + break; + case LOG: + opname = "log"; + break; + case EXP: + opname = "exp"; + break; + case SIN: + opname = "sin"; + break; + case COS: + opname = "cos"; + break; + case TAN: + opname = "tan"; + break; + case SQRT: + opname = "sqrt"; + break; + case ERF: + opname = "erf"; + break; + case ERFC: + opname = "erfc"; + break; + default: + break; + } + std::string s1 = convert(op1, t1); + return std::string(opname) + "(" + s1 + ")"; + } + else + { + int t1 = op.getOp1(); + const Operation &op1 = otree.operation(t1); + int t2 = op.getOp2(); + const Operation &op2 = otree.operation(t2); + const char *opname = "unknown"; + switch (op.getCode()) + { + case PLUS: + opname = "+"; + break; + case MINUS: + opname = "-"; + break; + case TIMES: + opname = "*"; + break; + case DIVIDE: + opname = "/"; + break; + case POWER: + opname = "^"; + break; + default: + break; + } + // decide about parenthesis + bool op1_par = true; + bool op2_par = true; + if (op.getCode() == PLUS) + { + op1_par = false; + op2_par = false; + } + else if (op.getCode() == MINUS) + { + op1_par = false; + if (op2.getCode() != MINUS && op2.getCode() != PLUS) + op2_par = false; + } + else + { + if (op1.nary() < 2) + op1_par = false; + if (op2.nary() < 2) + op2_par = false; + } + + std::string res; + if (op1_par) + res += "("; + res += convert(op1, t1); + if (op1_par) + res += ")"; + res += " "; + res += opname; + res += " "; + if (op2_par) + res += "("; + res += convert(op2, t2); + if (op2_par) + res += ")"; + + return res; + } +} + +// Local Variables: +// mode:C++ +// End: diff --git a/dynare++/parser/cc/tree.cpp b/dynare++/parser/cc/tree.cpp deleted file mode 100644 index 3ab37e77696896eb1183c7f0a95dd91e00a0c24d..0000000000000000000000000000000000000000 --- a/dynare++/parser/cc/tree.cpp +++ /dev/null @@ -1,928 +0,0 @@ -// Copyright (C) 2005-2011, Ondra Kamenik - - -#include "utils/cc/exception.h" - -#include "tree.h" - -#include <cstdlib> - -#include <cmath> -#include <limits> - -#ifdef __MINGW32__ -#define __CROSS_COMPILATION__ -#endif - -#ifdef __MINGW64__ -#define __CROSS_COMPILATION__ -#endif - -#ifdef __CROSS_COMPILATION__ -#define M_PI 3.14159265358979323846 -#endif - - -using namespace ogp; - - -/** Here we just implement complementary error function without - * declaring it for uses from outside this unit. The implementation is taken from "Numerical Recipes in C" 2nd ed. 1992 p. 221, */ -double erffc(double x) -{ - double z = std::abs(x); - double t = 1/(1+0.5*z); - double r = t*exp(-z*z-1.26551223+t*(1.00002368+t*(0.37409196+t*(0.09678418+t*(-0.18628806+t*(0.27886807+t*(-1.13520398+t*(1.48851587+t*(-0.82215223+t*0.17087277))))))))); - return x >= 0 ? r : 2-r; -} - -/** Here we initialize OperationTree to contain only zero, one, nan - * and two_over_pi terms. */ -OperationTree::OperationTree() -{ - last_nulary = -1; - // allocate space for the constants - for (int i = 0; i < num_constants; i++) - add_nulary(); -} - -int OperationTree::add_nulary() -{ - int op = terms.size(); - Operation nulary; - terms.push_back(nulary); - _Tintset s; - s.insert(op); - nul_incidence.push_back(s); - _Tderivmap empty; - derivatives.push_back(empty); - last_nulary = op; - return op; -} - -int OperationTree::add_unary(code_t code, int op) -{ - if (op == zero && - (code == UMINUS || - code == SIN || - code == TAN || - code == SQRT || - code == ERF)) - return zero; - if ((op == zero && code == LOG) || op == nan) - return nan; - if (op == zero && (code == EXP || - code == COS || - code == ERFC)) - return one; - - Operation unary(code, op); - _Topmap::const_iterator i = ((const _Topmap&)opmap).find(unary); - if (i == opmap.end()) { - int newop = terms.size(); - // add to the terms - terms.push_back(unary); - // copy incidence of the operand - nul_incidence.push_back(nul_incidence[op]); - // insert it to opmap - opmap.insert(_Topval(unary, newop)); - // add empty map of derivatives - _Tderivmap empty; - derivatives.push_back(empty); - return newop; - } - return (*i).second; -} - -int OperationTree::add_binary(code_t code, int op1, int op2) -{ - // quick exits for special values - if (op1 == nan || op2 == nan) - return nan; - // for plus - if (code == PLUS) { - if (op1 == zero && op2 == zero) - return zero; - else if (op1 == zero) - return op2; - else if (op2 == zero) - return op1; - } - // for minus - if (code == MINUS) { - if (op1 == zero && op2 == zero) - return zero; - else if (op1 == zero) - return add_unary(UMINUS, op2); - else if (op2 == zero) - return op1; - } - // for times - if (code == TIMES) { - if (op1 == zero || op2 == zero) - return zero; - else if (op1 == one) - return op2; - else if (op2 == one) - return op1; - } - // for divide - if (code == DIVIDE) { - if (op1 == op2) - return one; - else if (op1 == zero) - return zero; - else if (op2 == zero) - return nan; - } - // for power - if (code == POWER) { - if (op1 == zero && op2 == zero) - return nan; - else if (op1 == zero) - return zero; - else if (op2 == zero) - return one; - else if (op1 == one) - return one; - else if (op2 == one) - return op1; - } - - // order operands of commutative operations - if (code == TIMES || code == PLUS) - if (op1 > op2) { - int tmp = op1; - op1 = op2; - op2 = tmp; - } - - // construct operation and check/add it - Operation binary(code, op1, op2); - _Topmap::const_iterator i = ((const _Topmap&)opmap).find(binary); - if (i == opmap.end()) { - int newop = terms.size(); - terms.push_back(binary); - // sum both sets of incidenting nulary operations - 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)); - // add empty map of derivatives - _Tderivmap empty; - derivatives.push_back(empty); - return newop; - } - return (*i).second; -} - -int OperationTree::add_derivative(int t, int v) -{ - if (t < 0 || t >= (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; - } - if (terms[t].nary() == 0 && t == v) { - return one; - } - if (nul_incidence[t].end() == nul_incidence[t].find(v)) { - return zero; - } - - // quick return if the derivative has been registered - _Tderivmap::const_iterator i = derivatives[t].find(v); - if (i != derivatives[t].end()) - return (*i).second; - - int res = -1; - switch (terms[t].getCode()) { - - case UMINUS: - { - int tmp = add_derivative(terms[t].getOp1(), v); - res = add_unary(UMINUS, tmp); - break; - } - case LOG: - { - int tmp = add_derivative(terms[t].getOp1(), v); - res = add_binary(DIVIDE, tmp, terms[t].getOp1()); - break; - } - case EXP: - { - int tmp = add_derivative(terms[t].getOp1(), v); - res = add_binary(TIMES, t, tmp); - break; - } - case SIN: - { - int tmp = add_derivative(terms[t].getOp1(), v); - res = add_binary(TIMES, add_unary(COS, terms[t].getOp1()), tmp); - break; - } - case COS: - { - int tmp = add_derivative(terms[t].getOp1(), v); - res = add_unary(UMINUS, add_binary(TIMES, add_unary(SIN, terms[t].getOp1()), tmp)); - break; - } - case 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)); - break; - } - case SQRT: - { - int tmp = add_derivative(terms[t].getOp1(), v); - res = add_binary(DIVIDE, tmp, - add_binary(PLUS, t, t)); - break; - } - case ERF: - { - int tmp = add_binary(TIMES, terms[t].getOp1(), terms[t].getOp1()); - tmp = add_unary(UMINUS, tmp); - tmp = add_unary(EXP, tmp); - int der = add_derivative(terms[t].getOp1(), v); - tmp = add_binary(TIMES, tmp, der); - res = add_binary(TIMES, two_over_pi, tmp); - break; - } - case ERFC: - { - int tmp = add_binary(TIMES, terms[t].getOp1(), terms[t].getOp1()); - tmp = add_unary(UMINUS, tmp); - tmp = add_unary(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); - break; - } - case PLUS: - { - int tmp1 = add_derivative(terms[t].getOp1(), v); - int tmp2 = add_derivative(terms[t].getOp2(), v); - res = add_binary(PLUS, tmp1, tmp2); - break; - } - case MINUS: - { - int tmp1 = add_derivative(terms[t].getOp1(), v); - int tmp2 = add_derivative(terms[t].getOp2(), v); - res = add_binary(MINUS, tmp1, tmp2); - break; - } - case 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); - break; - } - case 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()); - 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); - } - break; - } - case 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); - break; - } - case NONE: - break; - } - - if (res == -1) - throw ogu::Exception(__FILE__,__LINE__, - "Unknown operation code."); - - register_derivative(t, v, res); - - return res; -} - -int OperationTree::add_substitution(int t, const map<int,int>& subst) -{ - return add_substitution(t, subst, *this); -} - -int OperationTree::add_substitution(int t, const map<int,int>& subst, - const OperationTree& otree) -{ - // return substitution of t if it is in the map - map<int,int>::const_iterator it = subst.find(t); - if (subst.end() != it) - return (*it).second; - - int nary = otree.terms[t].nary(); - if (nary == 2) { - // return the binary operation of the substituted terms - int t1 = add_substitution(otree.terms[t].getOp1(), subst, otree); - int t2 = add_substitution(otree.terms[t].getOp2(), subst, otree); - return add_binary(otree.terms[t].getCode(), t1, t2); - } else if (nary == 1) { - // return the unary operation of the substituted term - int t1 = add_substitution(otree.terms[t].getOp1(), subst, otree); - return add_unary(otree.terms[t].getCode(), t1); - } else { - // if t is not the first num_constants, and otree is not this - // tree, then raise and exception. Otherwise return t, since - // it is either a special term (having the same semantics in - // both trees), or the trees are the same, hence t has the - // same semantics - if (t < num_constants || this == &otree) - return t; - else { - throw ogu::Exception(__FILE__,__LINE__, - "Incomplete substitution map in OperationTree::add_substitution"); - return -1; - } - } -} - - -void OperationTree::nularify(int t) -{ - // remove the original operation from opmap - _Topmap::iterator it = opmap.find(terms[t]); - if (it != opmap.end()) - opmap.erase(it); - // turn the operation to nulary - Operation nulary_op; - terms[t] = nulary_op; - // update last nulary - if (last_nulary < t) - last_nulary = t; - // update nul_incidence information for all terms including t - update_nul_incidence_after_nularify(t); -} - -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)); -} - -unordered_set<int> OperationTree::select_terms(int t, const opselector& sel) const -{ - unordered_set<int> subterms; - select_terms(t, sel, subterms); - return subterms; -} - -void OperationTree::select_terms(int t, const opselector& sel, unordered_set<int>& subterms) const -{ - const Operation& op = terms[t]; - - if (sel(t)) - subterms.insert(t); - else - if (op.nary() == 2) { - select_terms(op.getOp1(), sel, subterms); - select_terms(op.getOp2(), sel, subterms); - } else if (op.nary() == 1) { - select_terms(op.getOp1(), sel, subterms); - } -} - -unordered_set<int> OperationTree::select_terms_inv(int t, const opselector& sel) const -{ - unordered_set<int> subterms; - select_terms_inv(t, sel, subterms); - return subterms; -} - -bool OperationTree::select_terms_inv(int t, const opselector& sel, unordered_set<int>& subterms) const -{ - const Operation& op = terms[t]; - - if (op.nary() == 2) { - bool a1 = select_terms_inv(op.getOp1(), sel, subterms); - bool a2 = select_terms_inv(op.getOp2(), sel, subterms); - if (a1 && a2 && sel(t)) { - subterms.insert(t); - return true; - } - } else if (op.nary() == 1) { - bool a1 = select_terms_inv(op.getOp1(), sel, subterms); - if (a1 && sel(t)) { - subterms.insert(t); - return true; - } - } else { - if (sel(t)) { - subterms.insert(t); - return true; - } - } - - return false; -} - -void OperationTree::forget_derivative_maps() -{ - for (unsigned int i = 0; i < derivatives.size(); i++) - derivatives[i].clear(); -} - - -void OperationTree::print_operation_tree(int t, FILE* fd, OperationFormatter& f) const -{ - f.format(terms[t], t, fd); -} - -void OperationTree::print_operation(int t) const -{ - DefaultOperationFormatter dof(*this); - print_operation_tree(t, stdout, dof); -} - -void OperationTree::update_nul_incidence_after_nularify(int t) -{ - unordered_set<int> updated; - for (int tnode = num_constants; tnode < (int)terms.size(); tnode++) { - const Operation& op = terms[tnode]; - if (op.nary() == 2) { - int op1 = op.getOp1(); - int op2 = op.getOp2(); - if (op1 >= tnode || op2 >= tnode) - throw ogu::Exception(__FILE__,__LINE__, - "Tree disorder asserted"); - bool updated1 = (updated.end() != updated.find(op1)); - bool updated2 = (updated.end() != updated.find(op2)); - if (updated1 || updated2) { - nul_incidence[tnode] = nul_incidence[op1]; - nul_incidence[tnode].insert(nul_incidence[op2].begin(), nul_incidence[op2].end()); - updated.insert(tnode); - } - } else if (op.nary() == 1) { - int op1 = op.getOp1(); - if (op1 >= tnode) - throw ogu::Exception(__FILE__,__LINE__, - "Tree disorder asserted"); - bool updated1 = (updated.end() != updated.find(op1)); - if (updated1) { - nul_incidence[tnode] = nul_incidence[op1]; - updated.insert(tnode); - } - } else if (op.nary() == 0) { - if (tnode == t) { - nul_incidence[tnode].clear(); - nul_incidence[tnode].insert(tnode); - updated.insert(tnode); - } - } - } -} - - -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]), - last_operation((last==-1)? ot.terms.size()-1 : last) -{ - if (last_operation < OperationTree::num_constants-1 || - last_operation > (int)ot.terms.size()-1) - throw ogu::Exception(__FILE__,__LINE__, - "Wrong last in EvalTree constructor."); - - values[0] = 0.0; - flags[0] = true; - values[1] = 1.0; - flags[1] = true; - values[2] = std::numeric_limits<double>::quiet_NaN(); - flags[2] = true; - values[3] = 2.0/sqrt(M_PI); - flags[3] = true; - // this sets from num_constants on - reset_all(); -} - -void EvalTree::reset_all() -{ - for (int i = OperationTree::num_constants; i <= last_operation; i++) - flags[i] = false; -} - -void EvalTree::set_nulary(int t, double val) -{ - if (t < 0 || t > last_operation) - throw ogu::Exception(__FILE__,__LINE__, - "The tree index out of bounds in EvalTree::set_nulary"); - if (t < OperationTree::num_constants || otree.terms[t].nary() != 0) - throw ogu::Exception(__FILE__,__LINE__, - "The term is not nulary assignable in EvalTree::set_nulary"); - - values[t] = val; - flags[t] = true; -} - -double EvalTree::eval(int t) -{ - if (t < 0 || t > last_operation) - throw ogu::Exception(__FILE__,__LINE__, - "The tree index out of bounds in EvalTree::eval"); - if (otree.terms[t].nary() == 0 && flags[t] == false) - throw ogu::Exception(__FILE__,__LINE__, - "Nulary term has not been assigned a value in EvalTree::eval"); - - if (! flags[t]) { - const Operation& op = otree.terms[t]; - if (op.nary() == 1) { - double r1 = eval(op.getOp1()); - double res; - if (op.getCode() == UMINUS) - res = -r1; - else if (op.getCode() == LOG) - res = log(r1); - else if (op.getCode() == EXP) - res = exp(r1); - else if (op.getCode() == SIN) - res = sin(r1); - else if (op.getCode() == COS) - res = cos(r1); - else if (op.getCode() == TAN) - res = tan(r1); - else if (op.getCode() == SQRT) - res = sqrt(r1); - else if (op.getCode() == ERF) - res = 1-erffc(r1); - else if (op.getCode() == ERFC) - res = erffc(r1); - else { - throw ogu::Exception(__FILE__,__LINE__, - "Unknown unary operation code in EvalTree::eval"); - res = 0.0; - } - values[t] = res; - flags[t] = true; - } else if (op.nary() == 2) { - double res; - if (op.getCode() == PLUS) { - double r1 = eval(op.getOp1()); - double r2 = eval(op.getOp2()); - res = r1 + r2; - } else if (op.getCode() == MINUS) { - double r1 = eval(op.getOp1()); - double r2 = eval(op.getOp2()); - res = r1 - r2; - } else if (op.getCode() == TIMES) { - // pickup less complex formula first - unsigned int nul1 = otree.nulary_of_term(op.getOp1()).size(); - unsigned int nul2 = otree.nulary_of_term(op.getOp2()).size(); - if (nul1 < nul2) { - double r1 = eval(op.getOp1()); - if (r1 == 0.0) - res = 0.0; - else { - double r2 = eval(op.getOp2()); - res = r1 * r2; - } - } else { - double r2 = eval(op.getOp2()); - if (r2 == 0) - res = 0.0; - else { - double r1 = eval(op.getOp1()); - res = r1*r2; - } - } - } else if (op.getCode() == DIVIDE) { - double r1 = eval(op.getOp1()); - if (r1 == 0) - res = 0.0; - else { - double r2 = eval(op.getOp2()); - res = r1 / r2; - } - } else if (op.getCode() == POWER) { - // suppose that more complex is the first op in average - double r2 = eval(op.getOp2()); - if (r2 == 0.0) - res = 1.0; - else { - double r1 = eval(op.getOp1()); - res = pow(r1, r2); - } - } else { - throw ogu::Exception(__FILE__,__LINE__, - "Unknown binary operation code in EvalTree::eval"); - res = 0.0; - } - values[t] = res; - flags[t] = true; - } - return values[t]; - } - - // if (! std::isfinite(values[t])) - // printf("Tree value t=%d is not finite = %f\n", t, values[t]); - - return values[t]; -} - -void EvalTree::print() const -{ - printf("last_op=%d\n", last_operation); - printf(" 0 1 2 3 4 5 6 7 8 9\n"); - printf("----------------------------------------------------------------\n"); - for (int i = 0; i <= (last_operation+1)/10; i++) { - printf("%-3d|", i); - int j = 0; - while (j < 10 && 10*i+j < last_operation+1) { - int k = 10*i+j; - if (flags[k]) - printf(" %5.1g", values[k]); - else - printf(" -----"); - j++; - } - printf("\n"); - } -} - -void DefaultOperationFormatter::format(const Operation& op, int t, FILE* fd) -{ - // add to the stop_set - if (stop_set.end() == stop_set.find(t)) - stop_set.insert(t); - else - return; - - // call recursively non-nulary terms of the operation - if (op.nary() == 2) { - int t1 = op.getOp1(); - const Operation& op1 = otree.terms[t1]; - int t2 = op.getOp2(); - const Operation& op2 = otree.terms[t2]; - if (op1.nary() > 0) - format(op1, t1, fd); - if (op2.nary() > 0) - format(op2, t2, fd); - } - if (op.nary() == 1) { - int t1 = op.getOp1(); - const Operation& op1 = otree.terms[t1]; - if (op1.nary() > 0) - format(op1, t1, fd); - } - - // print 'term =' - format_term(t, fd); - fprintf(fd, " = "); - if (op.nary() == 0) { - format_nulary(t, fd); - } else if (op.nary() == 1) { - int t1 = op.getOp1(); - const Operation& op1 = otree.terms[t1]; - const char* opname = "unknown"; - switch (op.getCode()) { - case UMINUS: - opname = "-"; - break; - case LOG: - opname = "log"; - break; - case EXP: - opname = "exp"; - break; - case SIN: - opname = "sin"; - break; - case COS: - opname = "cos"; - break; - case TAN: - opname = "tan"; - break; - case SQRT: - opname = "sqrt"; - break; - case ERF: - opname = "erf"; - break; - case ERFC: - opname = "erfc"; - break; - default: - break; - } - fprintf(fd, "%s(", opname); - if (op1.nary() == 0) - format_nulary(t1, fd); - else - format_term(t1, fd); - fprintf(fd, ")"); - } else { - int t1 = op.getOp1(); - const Operation& op1 = otree.terms[t1]; - int t2 = op.getOp2(); - const Operation& op2 = otree.terms[t2]; - const char* opname = "unknown"; - switch (op.getCode()) { - case PLUS: - opname = "+"; - break; - case MINUS: - opname = "-"; - break; - case TIMES: - opname = "*"; - break; - case DIVIDE: - opname = "/"; - break; - case POWER: - opname = "^"; - break; - default: - break; - } - if (op1.nary() == 0) - format_nulary(t1, fd); - else - format_term(t1, fd); - fprintf(fd, " %s ", opname); - if (op2.nary() == 0) - format_nulary(t2, fd); - else - format_term(t2, fd); - } - - print_delim(fd); - -} - -void DefaultOperationFormatter::format_term(int t, FILE* fd) const -{ - fprintf(fd, "$%d", t); -} - -void DefaultOperationFormatter::format_nulary(int t, FILE* fd) const -{ - if (t == OperationTree::zero) - fprintf(fd, "0"); - else if (t == OperationTree::one) - fprintf(fd, "1"); - else if (t == OperationTree::nan) - fprintf(fd, "NaN"); - else - fprintf(fd, "$%d", t); -} - -void DefaultOperationFormatter::print_delim(FILE* fd) const -{ - fprintf(fd, ";\n"); -} - -std::string OperationStringConvertor::convert(const Operation& op, int t) const -{ - if (op.nary() == 0) { - if (t < OperationTree::num_constants) - if (t == OperationTree::zero) - return std::string("0"); - else if (t == OperationTree::one) - return std::string("1"); - else if (t == OperationTree::nan) - return std::string("NaN"); - else if (t == OperationTree::two_over_pi) { - char buf[100]; - sprintf(buf, "%20.16g", 2.0/std::sqrt(M_PI)); - return std::string(buf); - } else { - return std::string("error!error"); - } - else - return nulsc.convert(t); - } else if (op.nary() == 1) { - int t1 = op.getOp1(); - const Operation& op1 = otree.operation(t1); - const char* opname = "unknown"; - switch (op.getCode()) { - case UMINUS: - opname = "-"; - break; - case LOG: - opname = "log"; - break; - case EXP: - opname = "exp"; - break; - case SIN: - opname = "sin"; - break; - case COS: - opname = "cos"; - break; - case TAN: - opname = "tan"; - break; - case SQRT: - opname = "sqrt"; - break; - case ERF: - opname = "erf"; - break; - case ERFC: - opname = "erfc"; - break; - default: - break; - } - std::string s1 = convert(op1, t1); - return std::string(opname) + "(" + s1 + ")"; - } else { - int t1 = op.getOp1(); - const Operation& op1 = otree.operation(t1); - int t2 = op.getOp2(); - const Operation& op2 = otree.operation(t2); - const char* opname = "unknown"; - switch (op.getCode()) { - case PLUS: - opname = "+"; - break; - case MINUS: - opname = "-"; - break; - case TIMES: - opname = "*"; - break; - case DIVIDE: - opname = "/"; - break; - case POWER: - opname = "^"; - break; - default: - break; - } - // decide about parenthesis - bool op1_par = true; - bool op2_par = true; - if (op.getCode() == PLUS) { - op1_par = false; - op2_par = false; - } else if (op.getCode() == MINUS) { - op1_par = false; - if (op2.getCode() != MINUS && op2.getCode() != PLUS) - op2_par = false; - } else { - if (op1.nary() < 2) - op1_par = false; - if (op2.nary() < 2) - op2_par = false; - } - - std::string res; - if (op1_par) - res += "("; - res += convert(op1, t1); - if (op1_par) - res += ")"; - res += " "; - res += opname; - res += " "; - if (op2_par) - res += "("; - res += convert(op2, t2); - if (op2_par) - res += ")"; - - return res; - } -} - -// Local Variables: -// mode:C++ -// End: diff --git a/dynare++/parser/cc/tree.h b/dynare++/parser/cc/tree.hh similarity index 100% rename from dynare++/parser/cc/tree.h rename to dynare++/parser/cc/tree.hh diff --git a/dynare++/src/Makefile.am b/dynare++/src/Makefile.am index 126264c34d529b8002d089defddfab2241b1d1f7..e3b56ee1e5299eb8320a30e7bb3558679d2a4317 100644 --- a/dynare++/src/Makefile.am +++ b/dynare++/src/Makefile.am @@ -3,22 +3,22 @@ bin_PROGRAMS = dynare++ GENERATED_FILES = dynglob_ll.cc dynglob_tab.cc dynglob_tab.hh dynare___SOURCES = \ - main.cpp \ - dynare3.cpp \ - dynare_atoms.h \ - dynare_model.h \ - forw_subst_builder.h \ - planner_builder.cpp \ - dynare3.h \ - dynare_exception.h \ - dynare_params.cpp \ - planner_builder.h \ - dynare_atoms.cpp \ - dynare_model.cpp \ - dynare_params.h \ - forw_subst_builder.cpp \ - nlsolve.cpp \ - nlsolve.h \ + main.cc \ + dynare3.cc \ + dynare_atoms.hh \ + dynare_model.hh \ + forw_subst_builder.hh \ + planner_builder.cc \ + dynare3.hh \ + dynare_exception.hh \ + dynare_params.cc \ + planner_builder.hh \ + dynare_atoms.cc \ + dynare_model.cc \ + dynare_params.hh \ + forw_subst_builder.cc \ + nlsolve.cc \ + nlsolve.hh \ $(GENERATED_FILES) dynare___CPPFLAGS = -I../sylv/cc -I../tl/cc -I../kord -I../integ/cc -I.. -I$(top_srcdir)/mex/sources -DDYNVERSION=\"$(PACKAGE_VERSION)\" $(BOOST_CPPFLAGS) $(CPPFLAGS_MATIO) @@ -27,10 +27,10 @@ dynare___LDADD = ../kord/libkord.a ../integ/cc/libinteg.a ../tl/cc/libtl.a ../pa dynare___CXXFLAGS = $(AM_CXXFLAGS) $(PTHREAD_CFLAGS) BUILT_SOURCES = $(GENERATED_FILES) -EXTRA_DIST = dynglob.lex dynglob.y +EXTRA_DIST = dynglob.ll dynglob.yy -dynglob_tab.cc dynglob_tab.hh: dynglob.y - $(YACC) -d -odynglob_tab.cc dynglob.y +dynglob_tab.cc dynglob_tab.hh: dynglob.yy + $(YACC) -d -odynglob_tab.cc dynglob.yy -dynglob_ll.cc: dynglob.lex - $(LEX) -i -odynglob_ll.cc dynglob.lex +dynglob_ll.cc: dynglob.ll + $(LEX) -i -odynglob_ll.cc dynglob.ll diff --git a/dynare++/src/dynare3.cc b/dynare++/src/dynare3.cc new file mode 100644 index 0000000000000000000000000000000000000000..80826598e7128df39a12464d5bc646eceef62ea0 --- /dev/null +++ b/dynare++/src/dynare3.cc @@ -0,0 +1,390 @@ +#include "dynare3.hh" +#include "dynare_exception.hh" +#include "planner_builder.hh" +#include "forw_subst_builder.hh" + +#include "utils/cc/memory_file.hh" +#include "utils/cc/exception.hh" +#include "parser/cc/parser_exception.hh" +#include "parser/cc/atom_substitutions.hh" +#include "../tl/cc/tl_exception.hh" +#include "../kord/kord_exception.hh" + +#ifndef DYNVERSION +# define DYNVERSION "unknown" +#endif + +/**************************************************************************************/ +/* DynareNameList class */ +/**************************************************************************************/ +vector<int> +DynareNameList::selectIndices(const vector<const char *> &ns) const +{ + vector<int> res; + for (unsigned int i = 0; i < ns.size(); i++) + { + int j = 0; + while (j < getNum() && strcmp(getName(j), ns[i]) != 0) + j++; + if (j == getNum()) + throw DynareException(__FILE__, __LINE__, + string("Couldn't find name for ") + ns[i] + +" in DynareNameList::selectIndices"); + res.push_back(j); + } + return res; +} + +/**************************************************************************************/ +/* Dynare class */ +/**************************************************************************************/ + +Dynare::Dynare(const char *modname, int ord, double sstol, Journal &jr) + : journal(jr), model(NULL), ysteady(NULL), md(1), dnl(NULL), denl(NULL), dsnl(NULL), + fe(NULL), fde(NULL), ss_tol(sstol) +{ + // make memory file + ogu::MemoryFile mf(modname); + if (mf.exists()) + { + try + { + model = new ogdyn::DynareParser(mf.base(), mf.length(), ord); + } + catch (const ogp::ParserException &pe) + { + int line; + int col; + mf.line_and_col(pe.offset(), line, col); + throw DynareException(pe.message(), modname, line, col); + } + ysteady = new Vector(model->getAtoms().ny()); + dnl = new DynareNameList(*this); + denl = new DynareExogNameList(*this); + dsnl = new DynareStateNameList(*this, *dnl, *denl); + fe = new ogp::FormulaEvaluator(model->getParser()); + fde = new ogp::FormulaDerEvaluator(model->getParser()); + writeModelInfo(journal); + } + else + { + throw DynareException(__FILE__, __LINE__, string("Could not open model file ")+modname); + } +} + +Dynare::Dynare(const char **endo, int num_endo, + const char **exo, int num_exo, + const char **par, int num_par, + const char *equations, int len, int ord, + double sstol, Journal &jr) + : journal(jr), model(NULL), ysteady(NULL), md(1), dnl(NULL), denl(NULL), dsnl(NULL), + fe(NULL), fde(NULL), ss_tol(sstol) +{ + try + { + model = new ogdyn::DynareSPModel(endo, num_endo, exo, num_exo, par, num_par, + equations, len, ord); + } + catch (const ogp::ParserException &pe) + { + throw DynareException(pe.message(), pe.offset()); + } + ysteady = new Vector(model->getAtoms().ny()); + dnl = new DynareNameList(*this); + denl = new DynareExogNameList(*this); + dsnl = new DynareStateNameList(*this, *dnl, *denl); + fe = new ogp::FormulaEvaluator(model->getParser()); + fde = new ogp::FormulaDerEvaluator(model->getParser()); + writeModelInfo(journal); +} + +Dynare::Dynare(const Dynare &dynare) + : journal(dynare.journal), model(NULL), + ysteady(NULL), md(dynare.md), + dnl(NULL), denl(NULL), dsnl(NULL), fe(NULL), fde(NULL), + ss_tol(dynare.ss_tol) +{ + model = dynare.model->clone(); + ysteady = new Vector(*(dynare.ysteady)); + dnl = new DynareNameList(*this); + denl = new DynareExogNameList(*this); + dsnl = new DynareStateNameList(*this, *dnl, *denl); + fe = new ogp::FormulaEvaluator(model->getParser()); + fde = new ogp::FormulaDerEvaluator(model->getParser()); +} + +Dynare::~Dynare() +{ + if (model) + delete model; + if (ysteady) + delete ysteady; + if (dnl) + delete dnl; + if (dsnl) + delete dsnl; + if (denl) + delete denl; + if (fe) + delete fe; + if (fde) + delete fde; +} + +void +Dynare::writeMat(mat_t *fd, const char *prefix) const +{ + char tmp[100]; + sprintf(tmp, "%s_vars", prefix); + getAllEndoNames().writeMat(fd, tmp); + getAllEndoNames().writeMatIndices(fd, prefix); + sprintf(tmp, "%s_state_vars", prefix); + getStateNames().writeMat(fd, tmp); + sprintf(tmp, "%s_shocks", prefix); + getExogNames().writeMat(fd, tmp); + getExogNames().writeMatIndices(fd, prefix); + sprintf(tmp, "%s_vcov_exo", prefix); + model->getVcov().writeMat(fd, tmp); + TwoDMatrix aux(1, 1); + sprintf(tmp, "%s_nstat", prefix); + aux.get(0, 0) = nstat(); + aux.writeMat(fd, tmp); + sprintf(tmp, "%s_npred", prefix); + aux.get(0, 0) = npred(); + aux.writeMat(fd, tmp); + sprintf(tmp, "%s_nboth", prefix); + aux.get(0, 0) = nboth(); + aux.writeMat(fd, tmp); + sprintf(tmp, "%s_nforw", prefix); + aux.get(0, 0) = nforw(); + aux.writeMat(fd, tmp); +} + +void +Dynare::writeDump(const std::string &basename) const +{ + std::string fname(basename); + fname += ".dump"; + std::ofstream out(fname.c_str()); + model->dump_model(out); + out.close(); +} + +void +Dynare::solveDeterministicSteady(Vector &steady) +{ + JournalRecordPair pa(journal); + pa << "Non-linear solver for deterministic steady state" << endrec; + steady = (const Vector &) model->getInit(); + DynareVectorFunction dvf(*this); + DynareJacobian dj(*this); + ogu::NLSolver nls(dvf, dj, 500, ss_tol, journal); + int iter; + if (!nls.solve(steady, iter)) + throw DynareException(__FILE__, __LINE__, + "Could not obtain convergence in non-linear solver"); +} + +// evaluate system at given y_t=y_{t+1}=y_{t-1}, and given shocks x_t +void +Dynare::evaluateSystem(Vector &out, const Vector &yy, const Vector &xx) +{ + ConstVector yym(yy, nstat(), nys()); + ConstVector yyp(yy, nstat()+npred(), nyss()); + evaluateSystem(out, yym, yy, yyp, xx); +} + +// evaluate system at given y^*_{t-1}, y_t, y^{**}_{t+1} and at +// exogenous x_t, all three vectors yym, yy, and yyp have the +// respective lengths of y^*_{t-1}, y_t, y^{**}_{t+1} +void +Dynare::evaluateSystem(Vector &out, const Vector &yym, const Vector &yy, + const Vector &yyp, const Vector &xx) +{ + ogdyn::DynareAtomValues dav(model->getAtoms(), model->getParams(), yym, yy, yyp, xx); + DynareEvalLoader del(model->getAtoms(), out); + fe->eval(dav, del); +} + +void +Dynare::calcDerivatives(const Vector &yy, const Vector &xx) +{ + ConstVector yym(yy, nstat(), nys()); + ConstVector yyp(yy, nstat()+npred(), nyss()); + ogdyn::DynareAtomValues dav(model->getAtoms(), model->getParams(), yym, yy, yyp, xx); + DynareDerEvalLoader ddel(model->getAtoms(), md, model->getOrder()); + for (int iord = 1; iord <= model->getOrder(); iord++) + fde->eval(dav, ddel, iord); +} + +void +Dynare::calcDerivativesAtSteady() +{ + Vector xx(nexog()); + xx.zeros(); + calcDerivatives(*ysteady, xx); +} + +void +Dynare::writeModelInfo(Journal &jr) const +{ + // write info on variables + { + JournalRecordPair rp(journal); + rp << "Information on variables" << endrec; + JournalRecord rec1(journal); + rec1 << "Number of endogenous: " << ny() << endrec; + JournalRecord rec2(journal); + rec2 << "Number of exogenous: " << nexog() << endrec; + JournalRecord rec3(journal); + rec3 << "Number of static: " << nstat() << endrec; + JournalRecord rec4(journal); + rec4 << "Number of predetermined: " << npred()+nboth() << endrec; + JournalRecord rec5(journal); + rec5 << "Number of forward looking: " << nforw()+nboth() << endrec; + JournalRecord rec6(journal); + rec6 << "Number of both: " << nboth() << endrec; + } + + // write info on planner variables + const ogdyn::PlannerInfo *pinfo = model->get_planner_info(); + if (pinfo) + { + JournalRecordPair rp(journal); + rp << "Information on planner variables" << endrec; + JournalRecord rec1(journal); + rec1 << "Number of Lagrange multipliers: " << pinfo->num_lagrange_mults << endrec; + JournalRecord rec2(journal); + rec2 << "Number of auxiliary variables: " << pinfo->num_aux_variables << endrec; + JournalRecord rec3(journal); + rec3 << "Number of new terms in the tree: " << pinfo->num_new_terms << endrec; + } + + // write info on forward substitutions + const ogdyn::ForwSubstInfo *finfo = model->get_forw_subst_info(); + if (finfo) + { + JournalRecordPair rp(journal); + rp << "Information on forward substitutions" << endrec; + JournalRecord rec1(journal); + rec1 << "Number of affected equations: " << finfo->num_affected_equations << endrec; + JournalRecord rec2(journal); + rec2 << "Number of substituted terms: " << finfo->num_subst_terms << endrec; + JournalRecord rec3(journal); + rec3 << "Number of auxiliary variables: " << finfo->num_aux_variables << endrec; + JournalRecord rec4(journal); + rec4 << "Number of new terms in the tree: " << finfo->num_new_terms << endrec; + } + + // write info on substitutions + const ogp::SubstInfo *sinfo = model->get_subst_info(); + if (sinfo) + { + JournalRecordPair rp(journal); + rp << "Information on substitutions" << endrec; + JournalRecord rec1(journal); + rec1 << "Number of substitutions: " << sinfo->num_substs << endrec; + } +} + +DynareNameList::DynareNameList(const Dynare &dynare) +{ + for (int i = 0; i < dynare.ny(); i++) + { + int j = dynare.model->getAtoms().y2outer_endo()[i]; + const char *name = dynare.model->getAtoms().get_endovars()[j]; + names.push_back(name); + } +} + +DynareStateNameList::DynareStateNameList(const Dynare &dynare, const DynareNameList &dnl, + const DynareExogNameList &denl) +{ + for (int i = 0; i < dynare.nys(); i++) + names.push_back(dnl.getName(i+dynare.nstat())); + for (int i = 0; i < dynare.nexog(); i++) + names.push_back(denl.getName(i)); +} + +DynareExogNameList::DynareExogNameList(const Dynare &dynare) +{ + for (int i = 0; i < dynare.nexog(); i++) + { + int j = dynare.model->getAtoms().y2outer_exo()[i]; + const char *name = dynare.model->getAtoms().get_exovars()[j]; + names.push_back(name); + } +} + +DynareEvalLoader::DynareEvalLoader(const ogp::FineAtoms &a, Vector &out) + : Vector(out) +{ + if (a.ny() != out.length()) + throw DynareException(__FILE__, __LINE__, "Wrong length of out vector in DynareEvalLoader constructor"); +} + +/** This clears the container of model derivatives and initializes it + * inserting empty sparse tensors up to the given order. */ +DynareDerEvalLoader::DynareDerEvalLoader(const ogp::FineAtoms &a, + TensorContainer<FSSparseTensor> &mod_ders, + int order) + : atoms(a), md(mod_ders) +{ + md.clear(); + for (int iord = 1; iord <= order; iord++) + { + FSSparseTensor *t = new FSSparseTensor(iord, atoms.ny()+atoms.nys()+atoms.nyss()+atoms.nexo(), atoms.ny()); + md.insert(t); + } +} + +void +DynareDerEvalLoader::load(int i, int iord, const int *vars, double res) +{ + FSSparseTensor *t = md.get(Symmetry(iord)); + IntSequence s(iord, 0); + for (int j = 0; j < iord; j++) + s[j] = atoms.get_pos_of_all(vars[j]); + t->insert(s, i, res); +} + +DynareJacobian::DynareJacobian(Dynare &dyn) + : Jacobian(dyn.ny()), d(dyn) +{ + zeros(); +} + +void +DynareJacobian::eval(const Vector &yy) +{ + ogdyn::DynareSteadyAtomValues + dav(d.getModel().getAtoms(), d.getModel().getParams(), yy); + zeros(); + d.fde->eval(dav, *this, 1); +} + +void +DynareJacobian::load(int i, int iord, const int *vars, double res) +{ + if (iord != 1) + throw DynareException(__FILE__, __LINE__, + "Derivative order different from order=1 in DynareJacobian::load"); + + int t = vars[0]; + int j = d.getModel().getAtoms().get_pos_of_all(t); + if (j < d.nyss()) + get(i, j+d.nstat()+d.npred()) += res; + else if (j < d.nyss()+d.ny()) + get(i, j-d.nyss()) += res; + else if (j < d.nyss()+d.ny()+d.nys()) + get(i, j-d.nyss()-d.ny()+d.nstat()) += res; +} + +void +DynareVectorFunction::eval(const ConstVector &in, Vector &out) +{ + check_for_eval(in, out); + Vector xx(d.nexog()); + xx.zeros(); + d.evaluateSystem(out, in, xx); +} diff --git a/dynare++/src/dynare3.cpp b/dynare++/src/dynare3.cpp deleted file mode 100644 index a5f0cbdabca088b46162d0030c253eaeb06c8999..0000000000000000000000000000000000000000 --- a/dynare++/src/dynare3.cpp +++ /dev/null @@ -1,364 +0,0 @@ - -#include "dynare3.h" -#include "dynare_exception.h" -#include "planner_builder.h" -#include "forw_subst_builder.h" - -#include "utils/cc/memory_file.h" -#include "utils/cc/exception.h" -#include "parser/cc/parser_exception.h" -#include "parser/cc/atom_substitutions.h" -#include "../tl/cc/tl_exception.hh" -#include "../kord/kord_exception.hh" - -#ifndef DYNVERSION -#define DYNVERSION "unknown" -#endif - - -/**************************************************************************************/ -/* DynareNameList class */ -/**************************************************************************************/ -vector<int> DynareNameList::selectIndices(const vector<const char*>& ns) const -{ - vector<int> res; - for (unsigned int i = 0; i < ns.size(); i++) { - int j = 0; - while (j < getNum() && strcmp(getName(j), ns[i]) != 0) - j++; - if (j == getNum()) - throw DynareException(__FILE__, __LINE__, - string("Couldn't find name for ") + ns[i] + - " in DynareNameList::selectIndices"); - res.push_back(j); - } - return res; -} - -/**************************************************************************************/ -/* Dynare class */ -/**************************************************************************************/ - -Dynare::Dynare(const char* modname, int ord, double sstol, Journal& jr) - : journal(jr), model(NULL), ysteady(NULL), md(1), dnl(NULL), denl(NULL), dsnl(NULL), - fe(NULL), fde(NULL), ss_tol(sstol) -{ - // make memory file - ogu::MemoryFile mf(modname); - if (mf.exists()) { - try { - model = new ogdyn::DynareParser(mf.base(), mf.length(), ord); - } catch (const ogp::ParserException& pe) { - int line; - int col; - mf.line_and_col(pe.offset(), line, col); - throw DynareException(pe.message(), modname, line, col); - } - ysteady = new Vector(model->getAtoms().ny()); - dnl = new DynareNameList(*this); - denl = new DynareExogNameList(*this); - dsnl = new DynareStateNameList(*this, *dnl, *denl); - fe = new ogp::FormulaEvaluator(model->getParser()); - fde = new ogp::FormulaDerEvaluator(model->getParser()); - writeModelInfo(journal); - } else { - throw DynareException(__FILE__, __LINE__, string("Could not open model file ")+modname); - } -} - -Dynare::Dynare(const char** endo, int num_endo, - const char** exo, int num_exo, - const char** par, int num_par, - const char* equations, int len, int ord, - double sstol, Journal& jr) - : journal(jr), model(NULL), ysteady(NULL), md(1), dnl(NULL), denl(NULL), dsnl(NULL), - fe(NULL), fde(NULL), ss_tol(sstol) -{ - try { - model = new ogdyn::DynareSPModel(endo, num_endo, exo, num_exo, par, num_par, - equations, len, ord); - } catch (const ogp::ParserException& pe) { - throw DynareException(pe.message(), pe.offset()); - } - ysteady = new Vector(model->getAtoms().ny()); - dnl = new DynareNameList(*this); - denl = new DynareExogNameList(*this); - dsnl = new DynareStateNameList(*this, *dnl, *denl); - fe = new ogp::FormulaEvaluator(model->getParser()); - fde = new ogp::FormulaDerEvaluator(model->getParser()); - writeModelInfo(journal); -} - -Dynare::Dynare(const Dynare& dynare) - : journal(dynare.journal), model(NULL), - ysteady(NULL), md(dynare.md), - dnl(NULL), denl(NULL), dsnl(NULL), fe(NULL), fde(NULL), - ss_tol(dynare.ss_tol) -{ - model = dynare.model->clone(); - ysteady = new Vector(*(dynare.ysteady)); - dnl = new DynareNameList(*this); - denl = new DynareExogNameList(*this); - dsnl = new DynareStateNameList(*this, *dnl, *denl); - fe = new ogp::FormulaEvaluator(model->getParser()); - fde = new ogp::FormulaDerEvaluator(model->getParser()); -} - -Dynare::~Dynare() -{ - if (model) - delete model; - if (ysteady) - delete ysteady; - if (dnl) - delete dnl; - if (dsnl) - delete dsnl; - if (denl) - delete denl; - if (fe) - delete fe; - if (fde) - delete fde; -} - -void Dynare::writeMat(mat_t* fd, const char* prefix) const -{ - char tmp[100]; - sprintf(tmp, "%s_vars", prefix); - getAllEndoNames().writeMat(fd, tmp); - getAllEndoNames().writeMatIndices(fd, prefix); - sprintf(tmp, "%s_state_vars", prefix); - getStateNames().writeMat(fd, tmp); - sprintf(tmp, "%s_shocks", prefix); - getExogNames().writeMat(fd, tmp); - getExogNames().writeMatIndices(fd, prefix); - sprintf(tmp, "%s_vcov_exo", prefix); - model->getVcov().writeMat(fd, tmp); - TwoDMatrix aux(1,1); - sprintf(tmp, "%s_nstat", prefix); - aux.get(0,0) = nstat(); - aux.writeMat(fd, tmp); - sprintf(tmp, "%s_npred", prefix); - aux.get(0,0) = npred(); - aux.writeMat(fd, tmp); - sprintf(tmp, "%s_nboth", prefix); - aux.get(0,0) = nboth(); - aux.writeMat(fd, tmp); - sprintf(tmp, "%s_nforw", prefix); - aux.get(0,0) = nforw(); - aux.writeMat(fd, tmp); -} - -void Dynare::writeDump(const std::string& basename) const -{ - std::string fname(basename); - fname += ".dump"; - std::ofstream out(fname.c_str()); - model->dump_model(out); - out.close(); -} - -void Dynare::solveDeterministicSteady(Vector& steady) -{ - JournalRecordPair pa(journal); - pa << "Non-linear solver for deterministic steady state" << endrec; - steady = (const Vector&) model->getInit(); - DynareVectorFunction dvf(*this); - DynareJacobian dj(*this); - ogu::NLSolver nls(dvf, dj, 500, ss_tol, journal); - int iter; - if (! nls.solve(steady, iter)) - throw DynareException(__FILE__, __LINE__, - "Could not obtain convergence in non-linear solver"); -} - -// evaluate system at given y_t=y_{t+1}=y_{t-1}, and given shocks x_t -void Dynare::evaluateSystem(Vector& out, const Vector& yy, const Vector& xx) -{ - ConstVector yym(yy, nstat(), nys()); - ConstVector yyp(yy, nstat()+npred(), nyss()); - evaluateSystem(out, yym, yy, yyp, xx); -} - -// evaluate system at given y^*_{t-1}, y_t, y^{**}_{t+1} and at -// exogenous x_t, all three vectors yym, yy, and yyp have the -// respective lengths of y^*_{t-1}, y_t, y^{**}_{t+1} -void Dynare::evaluateSystem(Vector& out, const Vector& yym, const Vector& yy, - const Vector& yyp, const Vector& xx) -{ - ogdyn::DynareAtomValues dav(model->getAtoms(), model->getParams(), yym, yy, yyp, xx); - DynareEvalLoader del(model->getAtoms(), out); - fe->eval(dav, del); -} - -void Dynare::calcDerivatives(const Vector& yy, const Vector& xx) -{ - ConstVector yym(yy, nstat(), nys()); - ConstVector yyp(yy, nstat()+npred(), nyss()); - ogdyn::DynareAtomValues dav(model->getAtoms(), model->getParams(), yym, yy, yyp, xx); - DynareDerEvalLoader ddel(model->getAtoms(), md, model->getOrder()); - for (int iord = 1; iord <= model->getOrder(); iord++) - fde->eval(dav, ddel, iord); -} - -void Dynare::calcDerivativesAtSteady() -{ - Vector xx(nexog()); - xx.zeros(); - calcDerivatives(*ysteady, xx); -} - -void Dynare::writeModelInfo(Journal& jr) const -{ - // write info on variables - { - JournalRecordPair rp(journal); - rp << "Information on variables" << endrec; - JournalRecord rec1(journal); - rec1 << "Number of endogenous: " << ny() << endrec; - JournalRecord rec2(journal); - rec2 << "Number of exogenous: " << nexog() << endrec; - JournalRecord rec3(journal); - rec3 << "Number of static: " << nstat() << endrec; - JournalRecord rec4(journal); - rec4 << "Number of predetermined: " << npred()+nboth() << endrec; - JournalRecord rec5(journal); - rec5 << "Number of forward looking: " << nforw()+nboth() << endrec; - JournalRecord rec6(journal); - rec6 << "Number of both: " << nboth() << endrec; - } - - // write info on planner variables - const ogdyn::PlannerInfo* pinfo = model->get_planner_info(); - if (pinfo) { - JournalRecordPair rp(journal); - rp << "Information on planner variables" << endrec; - JournalRecord rec1(journal); - rec1 << "Number of Lagrange multipliers: " << pinfo->num_lagrange_mults << endrec; - JournalRecord rec2(journal); - rec2 << "Number of auxiliary variables: " << pinfo->num_aux_variables << endrec; - JournalRecord rec3(journal); - rec3 << "Number of new terms in the tree: " << pinfo->num_new_terms << endrec; - } - - // write info on forward substitutions - const ogdyn::ForwSubstInfo* finfo = model->get_forw_subst_info(); - if (finfo) { - JournalRecordPair rp(journal); - rp << "Information on forward substitutions" << endrec; - JournalRecord rec1(journal); - rec1 << "Number of affected equations: " << finfo->num_affected_equations << endrec; - JournalRecord rec2(journal); - rec2 << "Number of substituted terms: " << finfo->num_subst_terms << endrec; - JournalRecord rec3(journal); - rec3 << "Number of auxiliary variables: " << finfo->num_aux_variables << endrec; - JournalRecord rec4(journal); - rec4 << "Number of new terms in the tree: " << finfo->num_new_terms << endrec; - } - - // write info on substitutions - const ogp::SubstInfo* sinfo = model->get_subst_info(); - if (sinfo) { - JournalRecordPair rp(journal); - rp << "Information on substitutions" << endrec; - JournalRecord rec1(journal); - rec1 << "Number of substitutions: " << sinfo->num_substs << endrec; - } -} - -DynareNameList::DynareNameList(const Dynare& dynare) -{ - for (int i = 0; i < dynare.ny(); i++) { - int j = dynare.model->getAtoms().y2outer_endo()[i]; - const char* name = dynare.model->getAtoms().get_endovars()[j]; - names.push_back(name); - } -} - -DynareStateNameList::DynareStateNameList(const Dynare& dynare, const DynareNameList& dnl, - const DynareExogNameList& denl) -{ - for (int i = 0; i < dynare.nys(); i++) - names.push_back(dnl.getName(i+dynare.nstat())); - for (int i = 0; i < dynare.nexog(); i++) - names.push_back(denl.getName(i)); -} - -DynareExogNameList::DynareExogNameList(const Dynare& dynare) -{ - for (int i = 0; i < dynare.nexog(); i++) { - int j = dynare.model->getAtoms().y2outer_exo()[i]; - const char* name = dynare.model->getAtoms().get_exovars()[j]; - names.push_back(name); - } -} - -DynareEvalLoader::DynareEvalLoader(const ogp::FineAtoms& a, Vector& out) - : Vector(out) -{ - if (a.ny() != out.length()) - throw DynareException(__FILE__, __LINE__, "Wrong length of out vector in DynareEvalLoader constructor"); -} - -/** This clears the container of model derivatives and initializes it - * inserting empty sparse tensors up to the given order. */ -DynareDerEvalLoader::DynareDerEvalLoader(const ogp::FineAtoms& a, - TensorContainer<FSSparseTensor>& mod_ders, - int order) - : atoms(a), md(mod_ders) -{ - md.clear(); - for (int iord = 1; iord <= order; iord++) { - FSSparseTensor* t = new FSSparseTensor(iord, atoms.ny()+atoms.nys()+atoms.nyss()+atoms.nexo(), atoms.ny()); - md.insert(t); - } -} - -void DynareDerEvalLoader::load(int i, int iord, const int* vars, double res) -{ - FSSparseTensor* t = md.get(Symmetry(iord)); - IntSequence s(iord, 0); - for (int j = 0; j < iord; j++) - s[j] = atoms.get_pos_of_all(vars[j]); - t->insert(s, i, res); -} - -DynareJacobian::DynareJacobian(Dynare& dyn) - : Jacobian(dyn.ny()), d(dyn) -{ - zeros(); -} - -void DynareJacobian::eval(const Vector& yy) -{ - ogdyn::DynareSteadyAtomValues - dav(d.getModel().getAtoms(), d.getModel().getParams(), yy); - zeros(); - d.fde->eval(dav, *this, 1); -} - -void DynareJacobian::load(int i, int iord, const int* vars, double res) -{ - if (iord != 1) - throw DynareException(__FILE__, __LINE__, - "Derivative order different from order=1 in DynareJacobian::load"); - - int t = vars[0]; - int j = d.getModel().getAtoms().get_pos_of_all(t); - if (j < d.nyss()) - get(i, j+d.nstat()+d.npred()) += res; - else if (j < d.nyss()+d.ny()) - get(i, j-d.nyss()) += res; - else if (j < d.nyss()+d.ny()+d.nys()) - get(i, j-d.nyss()-d.ny()+d.nstat()) += res; -} - -void DynareVectorFunction::eval(const ConstVector& in, Vector& out) -{ - check_for_eval(in, out); - Vector xx(d.nexog()); - xx.zeros(); - d.evaluateSystem(out, in, xx); -} - diff --git a/dynare++/src/dynare3.h b/dynare++/src/dynare3.hh similarity index 99% rename from dynare++/src/dynare3.h rename to dynare++/src/dynare3.hh index 59d37055ee4c00f1f1530893184a59fa09f02d03..04eea833ed0459d2b7a7675ed2a36e862f33d57d 100644 --- a/dynare++/src/dynare3.h +++ b/dynare++/src/dynare3.hh @@ -9,8 +9,8 @@ #include "../kord/decision_rule.hh" #include "../kord/dynamic_model.hh" -#include "dynare_model.h" -#include "nlsolve.h" +#include "dynare_model.hh" +#include "nlsolve.hh" #include <vector> diff --git a/dynare++/src/dynare_atoms.cc b/dynare++/src/dynare_atoms.cc new file mode 100644 index 0000000000000000000000000000000000000000..026631d9f2d5d94355e8094566ecf2add11e7d26 --- /dev/null +++ b/dynare++/src/dynare_atoms.cc @@ -0,0 +1,310 @@ +// Copyright (C) 2006, Ondra Kamenik + +// $Id: dynare_atoms.cpp 1765 2008-03-31 14:32:08Z kamenik $ + +#include "parser/cc/parser_exception.hh" +#include "utils/cc/exception.hh" + +#include "dynare_atoms.hh" + +#include <string> +#include <cmath> + +using namespace ogdyn; +using std::string; + +void +DynareStaticAtoms::register_name(const char *name) +{ + if (varnames.query(name)) + throw ogp::ParserException(string("The name ")+name+" is not unique.", 0); + StaticAtoms::register_name(name); +} + +int +DynareStaticAtoms::check_variable(const char *name) const +{ + if (0 == varnames.query(name)) + throw ogp::ParserException(std::string("Unknown name <")+name+">", 0); + Tvarmap::const_iterator it = vars.find(name); + if (it == vars.end()) + return -1; + else + return (*it).second; +} + +DynareDynamicAtoms::DynareDynamicAtoms(const DynareDynamicAtoms &dda) + : SAtoms(dda) +{ + // fill atom_type + for (Tatypemap::const_iterator it = dda.atom_type.begin(); + it != dda.atom_type.end(); ++it) + atom_type.insert(Tatypemap::value_type(varnames.query((*it).first), (*it).second)); +} + +void +DynareDynamicAtoms::parse_variable(const char *in, std::string &out, int &ll) const +{ + ll = 0; + std::string str = in; + int left = str.find_first_of("({"); + if (left != -1) + { + out = str.substr(0, left); + left++; + int right = str.find_first_of(")}", left); + if ((int) string::npos == right) + throw ogp::ParserException( + string("Syntax error when parsing Dynare atom <")+in+">.", 0); + std::string tmp(str, left, right-left); + sscanf(tmp.c_str(), "%d", &ll); + } + else + { + out = in; + } +} + +void +DynareDynamicAtoms::register_uniq_endo(const char *name) +{ + FineAtoms::register_uniq_endo(name); + atom_type.insert(Tatypemap::value_type(varnames.query(name), endovar)); +} + +void +DynareDynamicAtoms::register_uniq_exo(const char *name) +{ + FineAtoms::register_uniq_exo(name); + atom_type.insert(Tatypemap::value_type(varnames.query(name), exovar)); +} + +void +DynareDynamicAtoms::register_uniq_param(const char *name) +{ + FineAtoms::register_uniq_param(name); + atom_type.insert(Tatypemap::value_type(varnames.query(name), param)); +} + +bool +DynareDynamicAtoms::is_type(const char *name, atype tp) const +{ + Tatypemap::const_iterator it = atom_type.find(name); + if (it != atom_type.end() && (*it).second == tp) + return true; + else + return false; +} + +void +DynareDynamicAtoms::print() const +{ + SAtoms::print(); + printf("Name types:\n"); + for (Tatypemap::const_iterator it = atom_type.begin(); + it != atom_type.end(); ++it) + printf("name=%s type=%s\n", (*it).first, + ((*it).second == endovar) ? "endovar" : (((*it).second == exovar) ? "exovar" : "param")); +} + +std::string +DynareDynamicAtoms::convert(int t) const +{ + if (t < ogp::OperationTree::num_constants) + { + throw ogu::Exception(__FILE__, __LINE__, + "Tree index is a built-in constant in DynareDynamicAtoms::convert"); + return std::string(); + } + if (is_constant(t)) + { + double v = get_constant_value(t); + char buf[100]; + sprintf(buf, "%20.16g", v); + const char *s = buf; + while (*s == ' ') + ++s; + return std::string(s); + } + + const char *s = name(t); + if (is_type(s, endovar)) + { + int ll = lead(t); + char buf[100]; + if (ll) + sprintf(buf, "%s(%d)", s, ll); + else + sprintf(buf, "%s", s); + return std::string(buf); + } + + return std::string(s); +} + +void +DynareAtomValues::setValues(ogp::EvalTree &et) const +{ + // set constants + atoms.setValues(et); + + // set parameteres + for (unsigned int i = 0; i < atoms.get_params().size(); i++) + { + if (atoms.is_referenced(atoms.get_params()[i])) + { + const ogp::DynamicAtoms::Tlagmap &lmap = atoms.lagmap(atoms.get_params()[i]); + for (ogp::DynamicAtoms::Tlagmap::const_iterator it = lmap.begin(); + it != lmap.end(); ++it) + { + int t = (*it).second; + et.set_nulary(t, paramvals[i]); + } + } + } + + // set endogenous + for (unsigned int outer_i = 0; outer_i < atoms.get_endovars().size(); outer_i++) + { + if (atoms.is_referenced(atoms.get_endovars()[outer_i])) + { + const ogp::DynamicAtoms::Tlagmap &lmap = atoms.lagmap(atoms.get_endovars()[outer_i]); + for (ogp::DynamicAtoms::Tlagmap::const_iterator it = lmap.begin(); + it != lmap.end(); ++it) + { + int ll = (*it).first; + int t = (*it).second; + int i = atoms.outer2y_endo()[outer_i]; + if (ll == -1) + { + et.set_nulary(t, yym[i-atoms.nstat()]); + } + else if (ll == 0) + et.set_nulary(t, yy[i]); + else + et.set_nulary(t, yyp[i-atoms.nstat()-atoms.npred()]); + } + } + } + + // set exogenous + for (unsigned int outer_i = 0; outer_i < atoms.get_exovars().size(); outer_i++) + { + if (atoms.is_referenced(atoms.get_exovars()[outer_i])) + { + const ogp::DynamicAtoms::Tlagmap &lmap = atoms.lagmap(atoms.get_exovars()[outer_i]); + for (ogp::DynamicAtoms::Tlagmap::const_iterator it = lmap.begin(); + it != lmap.end(); ++it) + { + int ll = (*it).first; + if (ll == 0) // this is always true because of checks + { + int t = (*it).second; + int i = atoms.outer2y_exo()[outer_i]; + et.set_nulary(t, xx[i]); + } + } + } + } +} + +void +DynareStaticSteadyAtomValues::setValues(ogp::EvalTree &et) const +{ + // set constants + atoms_static.setValues(et); + + // set parameters + for (unsigned int i = 0; i < atoms_static.get_params().size(); i++) + { + const char *name = atoms_static.get_params()[i]; + int t = atoms_static.index(name); + if (t != -1) + { + int idyn = atoms.name2outer_param(name); + et.set_nulary(t, paramvals[idyn]); + } + } + + // set endogenous + for (unsigned int i = 0; i < atoms_static.get_endovars().size(); i++) + { + const char *name = atoms_static.get_endovars()[i]; + int t = atoms_static.index(name); + if (t != -1) + { + int idyn = atoms.outer2y_endo()[atoms.name2outer_endo(name)]; + et.set_nulary(t, yy[idyn]); + } + } + + // set exogenous + for (unsigned int i = 0; i < atoms_static.get_exovars().size(); i++) + { + const char *name = atoms_static.get_exovars()[i]; + int t = atoms_static.index(name); + if (t != -1) + et.set_nulary(t, 0.0); + } +} + +DynareSteadySubstitutions::DynareSteadySubstitutions(const ogp::FineAtoms &a, + const ogp::OperationTree &tree, + const Tsubstmap &subst, + const Vector &pvals, Vector &yy) + : atoms(a), y(yy) +{ + // fill the vector of left and right hand sides + for (Tsubstmap::const_iterator it = subst.begin(); + it != subst.end(); ++it) + { + left_hand_sides.push_back((*it).first); + right_hand_sides.push_back((*it).second); + } + + // evaluate right hand sides + DynareSteadyAtomValues dsav(atoms, pvals, y); + ogp::FormulaCustomEvaluator fe(tree, right_hand_sides); + fe.eval(dsav, *this); +} + +void +DynareSteadySubstitutions::load(int i, double res) +{ + const char *name = left_hand_sides[i]; + int iouter = atoms.name2outer_endo(name); + int iy = atoms.outer2y_endo()[iouter]; + if (!std::isfinite(y[iy])) + y[iy] = res; +} + +DynareStaticSteadySubstitutions:: +DynareStaticSteadySubstitutions(const ogp::FineAtoms &a, const ogp::StaticFineAtoms &sa, + const ogp::OperationTree &tree, + const Tsubstmap &subst, + const Vector &pvals, Vector &yy) + : atoms(a), atoms_static(sa), y(yy) +{ + // fill the vector of left and right hand sides + for (Tsubstmap::const_iterator it = subst.begin(); + it != subst.end(); ++it) + { + left_hand_sides.push_back((*it).first); + right_hand_sides.push_back((*it).second); + } + + // evaluate right hand sides + DynareStaticSteadyAtomValues dsav(atoms, atoms_static, pvals, y); + ogp::FormulaCustomEvaluator fe(tree, right_hand_sides); + fe.eval(dsav, *this); +} + +void +DynareStaticSteadySubstitutions::load(int i, double res) +{ + const char *name = left_hand_sides[i]; + int iouter = atoms.name2outer_endo(name); + int iy = atoms.outer2y_endo()[iouter]; + if (!std::isfinite(y[iy])) + y[iy] = res; +} diff --git a/dynare++/src/dynare_atoms.cpp b/dynare++/src/dynare_atoms.cpp deleted file mode 100644 index c1ae58bc40c7db5a1010124025b4bfcef5314121..0000000000000000000000000000000000000000 --- a/dynare++/src/dynare_atoms.cpp +++ /dev/null @@ -1,274 +0,0 @@ -// Copyright (C) 2006, Ondra Kamenik - -// $Id: dynare_atoms.cpp 1765 2008-03-31 14:32:08Z kamenik $ - -#include "parser/cc/parser_exception.h" -#include "utils/cc/exception.h" - -#include "dynare_atoms.h" - -#include <string> -#include <cmath> - -using namespace ogdyn; -using std::string; - -void DynareStaticAtoms::register_name(const char* name) -{ - if (varnames.query(name)) - throw ogp::ParserException(string("The name ")+name+" is not unique.", 0); - StaticAtoms::register_name(name); -} - -int DynareStaticAtoms::check_variable(const char* name) const -{ - if (0 == varnames.query(name)) - throw ogp::ParserException(std::string("Unknown name <")+name+">", 0); - Tvarmap::const_iterator it = vars.find(name); - if (it == vars.end()) - return -1; - else - return (*it).second; -} - -DynareDynamicAtoms::DynareDynamicAtoms(const DynareDynamicAtoms& dda) - : SAtoms(dda) -{ - // fill atom_type - for (Tatypemap::const_iterator it = dda.atom_type.begin(); - it != dda.atom_type.end(); ++it) - atom_type.insert(Tatypemap::value_type(varnames.query((*it).first), (*it).second)); -} - -void DynareDynamicAtoms::parse_variable(const char* in, std::string& out, int& ll) const -{ - ll = 0; - std::string str = in; - int left = str.find_first_of("({"); - if (left != -1) { - out = str.substr(0, left); - left++; - int right = str.find_first_of(")}", left); - if ((int)string::npos == right) - throw ogp::ParserException( - string("Syntax error when parsing Dynare atom <")+in+">.", 0); - std::string tmp(str, left, right-left); - sscanf(tmp.c_str(), "%d", &ll); - } else { - out = in; - } -} - -void DynareDynamicAtoms::register_uniq_endo(const char* name) -{ - FineAtoms::register_uniq_endo(name); - atom_type.insert(Tatypemap::value_type(varnames.query(name), endovar)); -} - -void DynareDynamicAtoms::register_uniq_exo(const char* name) -{ - FineAtoms::register_uniq_exo(name); - atom_type.insert(Tatypemap::value_type(varnames.query(name), exovar)); -} - -void DynareDynamicAtoms::register_uniq_param(const char* name) -{ - FineAtoms::register_uniq_param(name); - atom_type.insert(Tatypemap::value_type(varnames.query(name), param)); -} - -bool DynareDynamicAtoms::is_type(const char* name, atype tp) const -{ - Tatypemap::const_iterator it = atom_type.find(name); - if (it != atom_type.end() && (*it).second == tp) - return true; - else - return false; -} - -void DynareDynamicAtoms::print() const -{ - SAtoms::print(); - printf("Name types:\n"); - for (Tatypemap::const_iterator it = atom_type.begin(); - it != atom_type.end(); ++it) - printf("name=%s type=%s\n", (*it).first, - ((*it).second == endovar) ? "endovar" : (((*it).second == exovar)? "exovar" : "param")); -} - -std::string DynareDynamicAtoms::convert(int t) const -{ - if (t < ogp::OperationTree::num_constants) { - throw ogu::Exception(__FILE__,__LINE__, - "Tree index is a built-in constant in DynareDynamicAtoms::convert"); - return std::string(); - } - if (is_constant(t)) { - double v = get_constant_value(t); - char buf[100]; - sprintf(buf, "%20.16g", v); - const char* s = buf; - while (*s == ' ') - ++s; - return std::string(s); - } - - const char* s = name(t); - if (is_type(s, endovar)) { - int ll = lead(t); - char buf[100]; - if (ll) - sprintf(buf, "%s(%d)", s, ll); - else - sprintf(buf, "%s", s); - return std::string(buf); - } - - return std::string(s); -} - - -void DynareAtomValues::setValues(ogp::EvalTree& et) const -{ - // set constants - atoms.setValues(et); - - // set parameteres - for (unsigned int i = 0; i < atoms.get_params().size(); i++) { - if (atoms.is_referenced(atoms.get_params()[i])) { - const ogp::DynamicAtoms::Tlagmap& lmap = atoms.lagmap(atoms.get_params()[i]); - for (ogp::DynamicAtoms::Tlagmap::const_iterator it = lmap.begin(); - it != lmap.end(); ++it) { - int t = (*it).second; - et.set_nulary(t, paramvals[i]); - } - } - } - - // set endogenous - for (unsigned int outer_i = 0; outer_i < atoms.get_endovars().size(); outer_i++) { - if (atoms.is_referenced(atoms.get_endovars()[outer_i])) { - const ogp::DynamicAtoms::Tlagmap& lmap = atoms.lagmap(atoms.get_endovars()[outer_i]); - for (ogp::DynamicAtoms::Tlagmap::const_iterator it = lmap.begin(); - it != lmap.end(); ++it) { - int ll = (*it).first; - int t = (*it).second; - int i = atoms.outer2y_endo()[outer_i]; - if (ll == -1) { - et.set_nulary(t, yym[i-atoms.nstat()]); - } - else if (ll == 0) - et.set_nulary(t, yy[i]); - else - et.set_nulary(t, yyp[i-atoms.nstat()-atoms.npred()]); - } - } - } - - // set exogenous - for (unsigned int outer_i = 0; outer_i < atoms.get_exovars().size(); outer_i++) { - if (atoms.is_referenced(atoms.get_exovars()[outer_i])) { - const ogp::DynamicAtoms::Tlagmap& lmap = atoms.lagmap(atoms.get_exovars()[outer_i]); - for (ogp::DynamicAtoms::Tlagmap::const_iterator it = lmap.begin(); - it != lmap.end(); ++it) { - int ll = (*it).first; - if (ll == 0) { // this is always true because of checks - int t = (*it).second; - int i = atoms.outer2y_exo()[outer_i]; - et.set_nulary(t, xx[i]); - } - } - } - } -} - -void DynareStaticSteadyAtomValues::setValues(ogp::EvalTree& et) const -{ - // set constants - atoms_static.setValues(et); - - // set parameters - for (unsigned int i = 0; i < atoms_static.get_params().size(); i++) { - const char* name = atoms_static.get_params()[i]; - int t = atoms_static.index(name); - if (t != -1) { - int idyn = atoms.name2outer_param(name); - et.set_nulary(t, paramvals[idyn]); - } - } - - // set endogenous - for (unsigned int i = 0; i < atoms_static.get_endovars().size(); i++) { - const char* name = atoms_static.get_endovars()[i]; - int t = atoms_static.index(name); - if (t != -1) { - int idyn = atoms.outer2y_endo()[atoms.name2outer_endo(name)]; - et.set_nulary(t, yy[idyn]); - } - } - - // set exogenous - for (unsigned int i = 0; i < atoms_static.get_exovars().size(); i++) { - const char* name = atoms_static.get_exovars()[i]; - int t = atoms_static.index(name); - if (t != -1) - et.set_nulary(t, 0.0); - } -} - -DynareSteadySubstitutions::DynareSteadySubstitutions(const ogp::FineAtoms& a, - const ogp::OperationTree& tree, - const Tsubstmap& subst, - const Vector& pvals, Vector& yy) - : atoms(a), y(yy) -{ - // fill the vector of left and right hand sides - for (Tsubstmap::const_iterator it = subst.begin(); - it != subst.end(); ++it) { - left_hand_sides.push_back((*it).first); - right_hand_sides.push_back((*it).second); - } - - // evaluate right hand sides - DynareSteadyAtomValues dsav(atoms, pvals, y); - ogp::FormulaCustomEvaluator fe(tree, right_hand_sides); - fe.eval(dsav, *this); -} - -void DynareSteadySubstitutions::load(int i, double res) -{ - const char* name = left_hand_sides[i]; - int iouter = atoms.name2outer_endo(name); - int iy = atoms.outer2y_endo()[iouter]; - if (! std::isfinite(y[iy])) - y[iy] = res; -} - -DynareStaticSteadySubstitutions:: -DynareStaticSteadySubstitutions(const ogp::FineAtoms& a, const ogp::StaticFineAtoms& sa, - const ogp::OperationTree& tree, - const Tsubstmap& subst, - const Vector& pvals, Vector& yy) - : atoms(a), atoms_static(sa), y(yy) -{ - // fill the vector of left and right hand sides - for (Tsubstmap::const_iterator it = subst.begin(); - it != subst.end(); ++it) { - left_hand_sides.push_back((*it).first); - right_hand_sides.push_back((*it).second); - } - - // evaluate right hand sides - DynareStaticSteadyAtomValues dsav(atoms, atoms_static, pvals, y); - ogp::FormulaCustomEvaluator fe(tree, right_hand_sides); - fe.eval(dsav, *this); -} - -void DynareStaticSteadySubstitutions::load(int i, double res) -{ - const char* name = left_hand_sides[i]; - int iouter = atoms.name2outer_endo(name); - int iy = atoms.outer2y_endo()[iouter]; - if (! std::isfinite(y[iy])) - y[iy] = res; -} diff --git a/dynare++/src/dynare_atoms.h b/dynare++/src/dynare_atoms.hh similarity index 97% rename from dynare++/src/dynare_atoms.h rename to dynare++/src/dynare_atoms.hh index 68b9381990a3afbdec4897906e0958001815dad8..d43b56a4578f53f9e1d914c81a84252524ccd18e 100644 --- a/dynare++/src/dynare_atoms.h +++ b/dynare++/src/dynare_atoms.hh @@ -5,12 +5,12 @@ #ifndef OGDYN_DYNARE_ATOMS_H #define OGDYN_DYNARE_ATOMS_H -#include "sylv/cc/Vector.h" +#include "sylv/cc/Vector.hh" -#include "parser/cc/static_atoms.h" -#include "parser/cc/static_fine_atoms.h" -#include "parser/cc/atom_substitutions.h" -#include "parser/cc/tree.h" +#include "parser/cc/static_atoms.hh" +#include "parser/cc/static_fine_atoms.hh" +#include "parser/cc/atom_substitutions.hh" +#include "parser/cc/tree.hh" #include <map> #include <vector> diff --git a/dynare++/src/dynare_exception.h b/dynare++/src/dynare_exception.hh similarity index 100% rename from dynare++/src/dynare_exception.h rename to dynare++/src/dynare_exception.hh diff --git a/dynare++/src/dynare_model.cc b/dynare++/src/dynare_model.cc new file mode 100644 index 0000000000000000000000000000000000000000..1b40fae1d96f926edf3267120a6fb998c9b4b14e --- /dev/null +++ b/dynare++/src/dynare_model.cc @@ -0,0 +1,1075 @@ +// Copyright (C) 2006-2011, Ondra Kamenik + +#include "parser/cc/parser_exception.hh" +#include "parser/cc/location.hh" +#include "utils/cc/exception.hh" +#include "dynare_model.hh" +#include "dynare_exception.hh" +#include "planner_builder.hh" +#include "forw_subst_builder.hh" + +#include <cstdlib> + +#include <string> +#include <cmath> +#include <climits> + +using namespace ogdyn; + +ParsedMatrix::ParsedMatrix(const ogp::MatrixParser &mp) + : TwoDMatrix(mp.nrows(), mp.ncols()) +{ + zeros(); + for (ogp::MPIterator it = mp.begin(); it != mp.end(); ++it) + get(it.row(), it.col()) = *it; +} + +DynareModel::DynareModel() + : atoms(), eqs(atoms), order(-1), + param_vals(0), init_vals(0), vcov_mat(0), + t_plobjective(-1), t_pldiscount(-1), + pbuilder(NULL), fbuilder(NULL), + atom_substs(NULL), old_atoms(NULL) +{ +} + +DynareModel::DynareModel(const DynareModel &dm) + : atoms(dm.atoms), eqs(dm.eqs, atoms), order(dm.order), + param_vals(0), init_vals(0), vcov_mat(0), + t_plobjective(dm.t_plobjective), + t_pldiscount(dm.t_pldiscount), + pbuilder(NULL), fbuilder(NULL), + atom_substs(NULL), old_atoms(NULL) +{ + if (dm.param_vals) + param_vals = new Vector((const Vector &) *(dm.param_vals)); + if (dm.init_vals) + init_vals = new Vector((const Vector &) *(dm.init_vals)); + if (dm.vcov_mat) + vcov_mat = new TwoDMatrix((const TwoDMatrix &) *(dm.vcov_mat)); + if (dm.old_atoms) + old_atoms = new DynareDynamicAtoms((const DynareDynamicAtoms &) *(dm.old_atoms)); + if (dm.atom_substs) + atom_substs = new ogp::AtomSubstitutions((*dm.atom_substs), *old_atoms, atoms); + if (dm.pbuilder) + pbuilder = new PlannerBuilder(*(dm.pbuilder), *this); + if (dm.fbuilder) + fbuilder = new ForwSubstBuilder(*(dm.fbuilder), *this); +} + +DynareModel::~DynareModel() +{ + if (param_vals) + delete param_vals; + if (init_vals) + delete init_vals; + if (vcov_mat) + delete vcov_mat; + if (old_atoms) + delete old_atoms; + if (atom_substs) + delete atom_substs; + if (pbuilder) + delete pbuilder; + if (fbuilder) + delete fbuilder; +} + +const PlannerInfo * +DynareModel::get_planner_info() const +{ + if (pbuilder) + return &(pbuilder->get_info()); + return NULL; +} + +const ForwSubstInfo * +DynareModel::get_forw_subst_info() const +{ + if (fbuilder) + return &(fbuilder->get_info()); + return NULL; +} + +const ogp::SubstInfo * +DynareModel::get_subst_info() const +{ + if (atom_substs) + return &(atom_substs->get_info()); + return NULL; +} + +void +DynareModel::setInitOuter(const Vector &x) +{ + if (x.length() != atoms.ny()) + throw DynareException(__FILE__, __LINE__, + "Wrong length of vector in DynareModel::setInitOuter"); + for (int i = 0; i < atoms.ny(); i++) + (*init_vals)[i] = x[atoms.y2outer_endo()[i]]; +} + +void +DynareModel::print() const +{ + printf("all atoms:\n"); + atoms.print(); + printf("formulas:\n"); + DebugOperationFormatter dof(*this); + for (int i = 0; i < eqs.nformulas(); i++) + { + int tf = eqs.formula(i); + printf("formula %d:\n", tf); + eqs.getTree().print_operation_tree(tf, stdout, dof); + } +} + +void +DynareModel::dump_model(std::ostream &os) const +{ + // endogenous variable declaration + os << "var"; + for (int i = 0; i < (int) atoms.get_endovars().size(); i++) + os << " " << atoms.get_endovars()[i]; + os << ";\n\n"; + + // exogenous variables + os << "varexo"; + for (int i = 0; i < (int) atoms.get_exovars().size(); i++) + os << " " << atoms.get_exovars()[i]; + os << ";\n\n"; + + // parameters + os << "parameters"; + for (int i = 0; i < (int) atoms.get_params().size(); i++) + os << " " << atoms.get_params()[i]; + os << ";\n\n"; + + // parameter values + os.precision(16); + for (int i = 0; i < (int) atoms.get_params().size(); i++) + os << atoms.get_params()[i] << "=" << getParams()[i] << ";\n"; + os << "\n\n"; + + // model section + ogp::OperationStringConvertor osc(atoms, getParser().getTree()); + os << "model;\n"; + for (int i = 0; i < getParser().nformulas(); i++) + { + os << "// Equation " << i << "\n0 = "; + int t = getParser().formula(i); + os << osc.convert(getParser().getTree().operation(t), t); + os << ";\n"; + } + os << "end;\n"; + + // initval as steady state + os << "initval;\n"; + for (int i = 0; i < (int) atoms.get_endovars().size(); i++) + os << atoms.get_endovars()[atoms.y2outer_endo()[i]] << "=" << getInit()[i] << ";\n"; + os << "end;\n"; +} + +void +DynareModel::add_name(const char *name, int flag) +{ + if (flag == 1) + { + // endogenous + atoms.register_uniq_endo(name); + } + else if (flag == 2) + { + // exogenous + atoms.register_uniq_exo(name); + } + else if (flag == 3) + { + // parameter + atoms.register_uniq_param(name); + } + else + { + throw DynareException(__FILE__, __LINE__, + "Unrecognized flag value."); + } +} + +void +DynareModel::check_model() const +{ + if (order == -1) + throw DynareException(__FILE__, __LINE__, + "Order of approximation not set in DynareModel::check_model"); + + if (atoms.ny() != eqs.nformulas()) + { + char mes[1000]; + sprintf(mes, "Model has %d equations for %d endogenous variables", eqs.nformulas(), atoms.ny()); + throw DynareException(__FILE__, __LINE__, mes); + } + + // check whether all nulary terms of all formulas in eqs are + // either constant or assigned to a name + for (int i = 0; i < eqs.nformulas(); i++) + { + int ft = eqs.formula(i); + const unordered_set<int> &nuls = eqs.nulary_of_term(ft); + for (unordered_set<int>::const_iterator it = nuls.begin(); + it != nuls.end(); ++it) + if (!atoms.is_constant(*it) && !atoms.is_named_atom(*it)) + throw DynareException(__FILE__, __LINE__, + "Dangling nulary term found, internal error."); + } + + int mlag, mlead; + atoms.exovarspan(mlead, mlag); + if (atoms.nexo() > 0 && (mlead != 0 || mlag != 0)) + throw DynareException(__FILE__, __LINE__, + "The model contains occurrences of lagged/leaded exogenous variables"); + + atoms.endovarspan(mlead, mlag); + if (mlead > 1 || mlag < -1) + throw DynareException(__FILE__, __LINE__, + "The model contains occurrences of too lagged/leaded endogenous variables"); + + // check the dimension of vcov matrix + if (getAtoms().nexo() != getVcov().nrows()) + throw DynareException(__FILE__, __LINE__, + "Dimension of VCOV matrix does not correspond to the shocks"); +} + +int +DynareModel::variable_shift(int t, int tshift) +{ + const char *name = atoms.name(t); + if (atoms.is_type(name, DynareDynamicAtoms::param) + || atoms.is_constant(t)) + throw DynareException(__FILE__, __LINE__, + "The tree index is not a variable in DynareModel::variable_shift"); + int ll = atoms.lead(t) + tshift; + int res = atoms.index(name, ll); + if (res == -1) + { + std::string str(name); + str += '('; + char tmp[50]; + sprintf(tmp, "%d", ll); + str += tmp; + str += ')'; + res = eqs.add_nulary(str.c_str()); + } + return res; +} + +void +DynareModel::variable_shift_map(const unordered_set<int> &a_set, int tshift, + map<int, int> &s_map) +{ + s_map.clear(); + for (unordered_set<int>::const_iterator it = a_set.begin(); + it != a_set.end(); ++it) + { + int t = *it; + // make shift map only for non-constants and non-parameters + if (!atoms.is_constant(t)) + { + const char *name = atoms.name(t); + if (atoms.is_type(name, DynareDynamicAtoms::endovar) + || atoms.is_type(name, DynareDynamicAtoms::exovar)) + { + int tt = variable_shift(t, tshift); + s_map.insert(map<int, int>::value_type(t, tt)); + } + } + } +} + +void +DynareModel::termspan(int t, int &mlead, int &mlag) const +{ + mlead = INT_MIN; + mlag = INT_MAX; + const unordered_set<int> &nul_terms = eqs.nulary_of_term(t); + for (unordered_set<int>::const_iterator ni = nul_terms.begin(); + ni != nul_terms.end(); ++ni) + { + if (!atoms.is_constant(*ni) + && (atoms.is_type(atoms.name(*ni), DynareDynamicAtoms::endovar) + || atoms.is_type(atoms.name(*ni), DynareDynamicAtoms::exovar))) + { + int ll = atoms.lead(*ni); + if (ll < mlag) + mlag = ll; + if (ll > mlead) + mlead = ll; + } + } +} + +bool +DynareModel::is_constant_term(int t) const +{ + const unordered_set<int> &nul_terms = eqs.nulary_of_term(t); + for (unordered_set<int>::const_iterator ni = nul_terms.begin(); + ni != nul_terms.end(); ++ni) + if (!atoms.is_constant(*ni) + && !atoms.is_type(atoms.name(*ni), DynareDynamicAtoms::param)) + return false; + return true; +} + +unordered_set<int> +DynareModel::get_nonlinear_subterms(int t) const +{ + NLSelector nls(*this); + return eqs.getTree().select_terms(t, nls); +} + +void +DynareModel::substitute_atom_for_term(const char *name, int ll, int t) +{ + // if the term t is itself a named atom (parameter, exo, endo), + // then we have to unassign it first + if (atoms.is_named_atom(t)) + atoms.unassign_variable(atoms.name(t), atoms.lead(t), t); + // assign allocated tree index + // for the term now to name(ll) + atoms.assign_variable(name, ll, t); + // make operation t nulary in operation tree + eqs.nularify(t); +} + +void +DynareModel::final_job() +{ + if (t_plobjective != -1 && t_pldiscount != -1) + { + // at this moment include all equations and all variables; in + // future we will exclude purely exogenous processes; todo: + PlannerBuilder::Tvarset vset; + for (int i = 0; i < atoms.ny(); i++) + vset.insert(atoms.get_endovars()[i]); + PlannerBuilder::Teqset eset; + for (int i = 0; i < eqs.nformulas(); i++) + eset.push_back(i); + + // construct the planner builder, this adds a lot of stuff to + // the model + if (pbuilder) + delete pbuilder; + pbuilder = new PlannerBuilder(*this, vset, eset); + } + + // construct ForwSubstBuilder + if (fbuilder) + delete fbuilder; + fbuilder = new ForwSubstBuilder(*this); + + // call parsing_finished (this will define an outer ordering of all variables) + atoms.parsing_finished(ogp::VarOrdering::bfspbfpb); + // make a copy of atoms and name it old_atoms + if (old_atoms) + delete old_atoms; + old_atoms = new DynareDynamicAtoms(atoms); + // construct empty substitutions from old_atoms to atoms + if (atom_substs) + delete atom_substs; + atom_substs = new ogp::AtomSubstitutions(*old_atoms, atoms); + // do the actual substitution, it will also call + // parsing_finished for atoms which creates internal orderings + atoms.substituteAllLagsAndExo1Leads(eqs, *atom_substs); +} + +extern ogp::location_type dynglob_lloc; + +DynareParser::DynareParser(const char *stream, int len, int ord) + : DynareModel(), + pa_atoms(), paramset(pa_atoms), + ia_atoms(), initval(ia_atoms), vcov(), + model_beg(0), model_end(-1), + paramset_beg(0), paramset_end(-1), + initval_beg(0), initval_end(-1), + vcov_beg(0), vcov_end(-1), + order_beg(0), order_end(-1), + plobjective_beg(0), plobjective_end(-1), + pldiscount_beg(0), pldiscount_end(-1) +{ + // global parse + try + { + parse_glob(len, stream); + } + catch (const ogp::ParserException &e) + { + throw ogp::ParserException(e, dynglob_lloc.off); + } + // setting parameters parse + try + { + if (paramset_end > paramset_beg) + paramset.parse(paramset_end-paramset_beg, stream+paramset_beg); + } + catch (const ogp::ParserException &e) + { + throw ogp::ParserException(e, paramset_beg); + } + // model parse + try + { + if (model_end > model_beg) + eqs.parse(model_end-model_beg, stream+model_beg); + else + throw ogp::ParserException("Model section not found.", 0); + } + catch (const ogp::ParserException &e) + { + throw ogp::ParserException(e, model_beg); + } + // initval setting parse + try + { + if (initval_end > initval_beg) + initval.parse(initval_end-initval_beg, stream+initval_beg); + } + catch (const ogp::ParserException &e) + { + throw ogp::ParserException(e, initval_beg); + } + // vcov parse + try + { + if (vcov_end > vcov_beg) + { + vcov.parse(vcov_end-vcov_beg, stream+vcov_beg); + } + } + catch (const ogp::ParserException &e) + { + throw ogp::ParserException(e, vcov_beg); + } + // planner objective parse + try + { + if (plobjective_end > plobjective_beg) + { + eqs.parse(plobjective_end-plobjective_beg, stream+plobjective_beg); + t_plobjective = eqs.pop_last_formula(); + } + } + catch (const ogp::ParserException &e) + { + throw ogp::ParserException(e, plobjective_beg); + } + // planner discount parse + try + { + if (pldiscount_end > pldiscount_beg) + { + t_pldiscount = parse_pldiscount(pldiscount_end - pldiscount_beg, + stream + pldiscount_beg); + } + } + catch (const ogp::ParserException &e) + { + throw ogp::ParserException(e, pldiscount_beg); + } + // order parse + try + { + if (order_end > order_beg) + { + order = parse_order(order_end > order_beg, stream + order_beg); + } + } + catch (const ogp::ParserException &e) + { + throw ogp::ParserException(e, order_beg); + } + + // check the overridden order + if (ord != -1) + order = ord; + + // end parsing job, add planner's FOCs, make substitutions + DynareModel::final_job(); + + // calculate parameters + calc_params(); + // calculate initial values + calc_init(); + + if (vcov_end > vcov_beg) + vcov_mat = new ParsedMatrix(vcov); + else + { + // vcov has not been asserted, set it to unit matrix + vcov_mat = new TwoDMatrix(atoms.nexo(), atoms.nexo()); + vcov_mat->unit(); + } + + // check the model + check_model(); + + // differentiate + if (order >= 1) + eqs.differentiate(order); +} + +DynareParser::DynareParser(const DynareParser &dp) + : DynareModel(dp), + pa_atoms(dp.pa_atoms), paramset(dp.paramset, pa_atoms), + ia_atoms(dp.ia_atoms), initval(dp.initval, ia_atoms), vcov(dp.vcov), + model_beg(dp.model_beg), model_end(dp.model_end), + paramset_beg(dp.paramset_beg), paramset_end(dp.paramset_end), + initval_beg(dp.initval_beg), initval_end(dp.initval_end), + vcov_beg(dp.vcov_beg), vcov_end(dp.vcov_end), + order_beg(dp.order_beg), order_end(dp.order_end), + plobjective_beg(dp.plobjective_beg), plobjective_end(dp.plobjective_end), + pldiscount_beg(dp.pldiscount_beg), pldiscount_end(dp.pldiscount_end) +{ +} + +DynareParser::~DynareParser() +{ +} + +void +DynareParser::add_name(const char *name, int flag) +{ + DynareModel::add_name(name, flag); + // register with static atoms used for atom assignements + if (flag == 1) + { + // endogenous + ia_atoms.register_name(name); + } + else if (flag == 2) + { + // exogenous + ia_atoms.register_name(name); + } + else if (flag == 3) + { + // parameter + pa_atoms.register_name(name); + ia_atoms.register_name(name); + } + else + { + throw DynareException(__FILE__, __LINE__, + "Unrecognized flag value."); + } +} + +void +DynareParser::error(const char *mes) +{ + // throwing zero offset since this exception will be caugth at + // constructor + throw ogp::ParserException(mes, 0); +} + +void +DynareParser::print() const +{ + DynareModel::print(); + printf("parameter atoms:\n"); + paramset.print(); + printf("initval atoms:\n"); + initval.print(); + printf("model position: %d %d\n", model_beg, model_end); + printf("paramset position: %d %d\n", paramset_beg, paramset_end); + printf("initval position: %d %d\n", initval_beg, initval_end); +} + +/** A global symbol for passing info to the DynareParser from + * parser. */ +DynareParser *dynare_parser; + +/** The declarations of functions defined in dynglob_ll.cc and + * dynglob_tab.cc generated from dynglob.lex and dynglob.y */ +void *dynglob__scan_buffer(char *, size_t); +void dynglob__destroy_buffer(void *); +void dynglob_parse(); +extern ogp::location_type dynglob_lloc; + +void +DynareParser::parse_glob(int length, const char *stream) +{ + char *buffer = new char[length+2]; + strncpy(buffer, stream, length); + buffer[length] = '\0'; + buffer[length+1] = '\0'; + void *p = dynglob__scan_buffer(buffer, (unsigned int) length+2); + dynare_parser = this; + dynglob_parse(); + delete [] buffer; + dynglob__destroy_buffer(p); +} + +int +DynareParser::parse_order(int len, const char *str) +{ + char *buf = new char[len+1]; + strncpy(buf, str, len); + buf[len] = '\0'; + int res; + sscanf(buf, "%d", &res); + delete [] buf; + return res; +} + +int +DynareParser::parse_pldiscount(int len, const char *str) +{ + char *buf = new char[len+1]; + strncpy(buf, str, len); + buf[len] = '\0'; + if (!atoms.is_type(buf, DynareDynamicAtoms::param)) + throw ogp::ParserException(std::string("Name ") + buf + " is not a parameter", 0); + + int t = atoms.index(buf, 0); + if (t == -1) + t = eqs.add_nulary(buf); + + delete [] buf; + return t; +} + +void +DynareParser::calc_params() +{ + if (param_vals) + delete param_vals; + + param_vals = new Vector(atoms.np()); + ogp::AtomAsgnEvaluator aae(paramset); + aae.eval(); + for (int i = 0; i < atoms.np(); i++) + (*param_vals)[i] = aae.get_value(atoms.get_params()[i]); + + for (unsigned int i = 0; i < atoms.get_params().size(); i++) + if (!std::isfinite((*param_vals)[i])) + printf("dynare++: warning: value for parameter %s is not finite\n", + atoms.get_params()[i]); +} + +void +DynareParser::calc_init() +{ + // update initval atoms assignings according to substitutions + if (atom_substs) + initval.apply_subst(atom_substs->get_old2new()); + + // calculate the vector of initial values + if (init_vals) + delete init_vals; + init_vals = new Vector(atoms.ny()); + ogp::AtomAsgnEvaluator aae(initval); + // set parameters + for (int ip = 0; ip < atoms.np(); ip++) + aae.set_user_value(atoms.get_params()[ip], (*param_vals)[ip]); + // set exogenous to zeros + for (int ie = 0; ie < atoms.nexo(); ie++) + aae.set_user_value(atoms.get_exovars()[ie], 0.0); + // evaluate + aae.eval(); + // set results to internally ordered vector init_vals + for (int outer = 0; outer < atoms.ny(); outer++) + { + int i = atoms.outer2y_endo()[outer]; + (*init_vals)[i] = aae.get_value(atoms.get_endovars()[outer]); + } + + // if the planner's FOCs have been added, then add estimate of + // Lagrange multipliers to the vector + if (pbuilder) + { + MultInitSS mis(*pbuilder, *param_vals, *init_vals); + } + + // if forward substitution builder has been created, we have to + // its substitutions and evaluate them + if (fbuilder) + ogdyn::DynareSteadySubstitutions dss(atoms, eqs.getTree(), + fbuilder->get_aux_map(), *param_vals, *init_vals); + + for (unsigned int i = 0; i < atoms.get_endovars().size(); i++) + if (!std::isfinite((*init_vals)[i])) + printf("dynare++: warning: initval for <%s> is not finite\n", + atoms.get_endovars()[atoms.y2outer_endo()[i]]); +} + +// this returns false for linear functions +bool +NLSelector::operator()(int t) const +{ + const ogp::Operation &op = model.getParser().getTree().operation(t); + const DynareDynamicAtoms &atoms = model.getAtoms(); + // if the term is constant, return false + if (model.is_constant_term(t)) + return false; + int nary = op.nary(); + if (nary == 0) + { + if (atoms.is_type(atoms.name(t), DynareDynamicAtoms::endovar) + || atoms.is_type(atoms.name(t), DynareDynamicAtoms::exovar)) + return true; + else + return false; + } + else if (nary == 1) + { + if (op.getCode() == ogp::UMINUS) + return false; + else + return true; + } + else + { + if (op.getCode() == ogp::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())) + return false; + else + return true; + // both PLUS and MINUS are linear + if (op.getCode() == ogp::PLUS + || op.getCode() == ogp::MINUS) + return false; + // POWER is linear if exponent or base is 0 or one + if (op.getCode() == ogp::POWER + && (op.getOp1() == ogp::OperationTree::zero + || op.getOp1() == ogp::OperationTree::one + || op.getOp2() == ogp::OperationTree::zero + || op.getOp2() == ogp::OperationTree::one)) + return false; + else + return true; + // DIVIDE is linear if the denominator is constant, or if + // the nominator is zero + if (op.getCode() == ogp::DIVIDE + && (op.getOp1() == ogp::OperationTree::zero + || model.is_constant_term(op.getOp2()))) + return false; + else + return true; + } + + throw DynareException(__FILE__, __LINE__, + "Wrong operation in operation tree"); + return false; +} + +DynareSPModel::DynareSPModel(const char **endo, int num_endo, + const char **exo, int num_exo, + const char **par, int num_par, + const char *equations, int len, + int ord) + : DynareModel() +{ + // set the order + order = ord; + + // add names + for (int i = 0; i < num_endo; i++) + add_name(endo[i], 1); + for (int i = 0; i < num_exo; i++) + add_name(exo[i], 2); + for (int i = 0; i < num_par; i++) + add_name(par[i], 3); + + // parse the equations + eqs.parse(len, equations); + + // parsing finished + atoms.parsing_finished(ogp::VarOrdering::bfspbfpb); + + // create what has to be created from DynareModel + param_vals = new Vector(atoms.np()); + init_vals = new Vector(atoms.ny()); + vcov_mat = new TwoDMatrix(atoms.nexo(), atoms.nexo()); + + // check the model + check_model(); + + // differentiate + if (order >= 1) + eqs.differentiate(order); +} + +void +ModelSSWriter::write_der0(FILE *fd) +{ + write_der0_preamble(fd); + write_atom_assignment(fd); + + stop_set.clear(); + for (int fi = 0; fi < model.eqs.nformulas(); fi++) + otree.print_operation_tree(model.eqs.formula(fi), fd, *this); + + write_der0_assignment(fd); +} + +void +ModelSSWriter::write_der1(FILE *fd) +{ + write_der1_preamble(fd); + write_atom_assignment(fd); + + stop_set.clear(); + + const vector<int> &variables = model.getAtoms().variables(); + const vector<int> &eam = model.getAtoms().get_endo_atoms_map(); + for (int i = 0; i < model.getParser().nformulas(); i++) + { + const ogp::FormulaDerivatives &fder = model.getParser().derivatives(i); + for (unsigned int j = 0; j < eam.size(); j++) + { + int t = fder.derivative(ogp::FoldMultiIndex(variables.size(), 1, eam[j])); + if (t > 0) + otree.print_operation_tree(t, fd, *this); + } + } + + write_der1_assignment(fd); +} + +MatlabSSWriter::MatlabSSWriter(const DynareModel &dm, const char *idd) + : ModelSSWriter(dm), id(new char[strlen(idd)+1]) +{ + strcpy(id, idd); +} + +void +MatlabSSWriter::write_der0_preamble(FILE *fd) 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); +} + +void +MatlabSSWriter::write_der1_preamble(FILE *fd) 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); +} + +void +MatlabSSWriter::write_common1_preamble(FILE *fd) 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); + // write ordering of parameters + fprintf(fd, "\n%% params ordering\n%% =====================\n"); + for (unsigned int ip = 0; ip < model.getAtoms().get_params().size(); ip++) + { + const char *parname = model.getAtoms().get_params()[ip]; + fprintf(fd, "%% %s\n", parname); + } + // write endogenous variables + fprintf(fd, "%%\n%% y ordering\n%% =====================\n"); + for (unsigned int ie = 0; ie < model.getAtoms().get_endovars().size(); ie++) + { + const char *endoname = model.getAtoms().get_endovars()[ie]; + fprintf(fd, "%% %s\n", endoname); + } + fprintf(fd, "\n"); +} + +void +MatlabSSWriter::write_common2_preamble(FILE *fd) 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()); +} + +void +MatlabSSWriter::write_atom_assignment(FILE *fd) const +{ + // write OperationTree::num_constants + fprintf(fd, "%% 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); + double g = etree.eval(i); + if (std::isnan(g)) + fprintf(fd, " = NaN;\n"); + else + fprintf(fd, " = %12.8g;\n", etree.eval(i)); + } + // write numerical constants + fprintf(fd, "%% numerical constants\n"); + const ogp::Constants::Tconstantmap &cmap = model.getAtoms().get_constantmap(); + for (ogp::Constants::Tconstantmap::const_iterator it = cmap.begin(); + it != cmap.end(); ++it) + { + format_nulary((*it).first, fd); + fprintf(fd, " = %12.8g;\n", (*it).second); + } + // write parameters + fprintf(fd, "%% 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); + } + else + { + format_nulary(t, fd); + fprintf(fd, " = params(%d); %% %s\n", ip+1, parname); + } + } + // write exogenous variables + fprintf(fd, "%% 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]; + try + { + const ogp::DynamicAtoms::Tlagmap &lmap = model.getAtoms().lagmap(exoname); + for (ogp::DynamicAtoms::Tlagmap::const_iterator it = lmap.begin(); + it != lmap.end(); ++it) + { + format_nulary((*it).second, fd); + fprintf(fd, " = 0.0; %% %s\n", exoname); + } + } + catch (const ogu::Exception &e) + { + // ignore the error of not found variable in the tree + } + } + // write endogenous variables + fprintf(fd, "%% 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 (ogp::DynamicAtoms::Tlagmap::const_iterator it = lmap.begin(); + it != lmap.end(); ++it) + { + format_nulary((*it).second, fd); + fprintf(fd, " = y(%d); %% %s\n", ie+1, endoname); + } + } + fprintf(fd, "\n"); +} + +void +MatlabSSWriter::write_der0_assignment(FILE *fd) const +{ + + // initialize out variable + fprintf(fd, "%% setting the output variable\n"); + fprintf(fd, "out = zeros(%d, 1);\n", model.getParser().nformulas()); + + // 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"); + } +} + +void +MatlabSSWriter::write_der1_assignment(FILE *fd) const +{ + // initialize out variable + fprintf(fd, "%% setting the output variable\n"); + fprintf(fd, "out = zeros(%d, %d);\n", model.getParser().nformulas(), model.getAtoms().ny()); + + // fill out with the terms + const vector<int> &variables = model.getAtoms().variables(); + const vector<int> &eam = model.getAtoms().get_endo_atoms_map(); + for (int i = 0; i < model.getParser().nformulas(); i++) + { + const ogp::FormulaDerivatives &fder = model.getParser().derivatives(i); + for (unsigned int j = 0; j < eam.size(); j++) + { + int tvar = variables[eam[j]]; + const char *name = model.getAtoms().name(tvar); + int yi = model.getAtoms().name2outer_endo(name); + int t = fder.derivative(ogp::FoldMultiIndex(variables.size(), 1, eam[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)); + } + } + } +} + +void +MatlabSSWriter::format_term(int t, FILE *fd) const +{ + fprintf(fd, "t%d", t); +} + +void +MatlabSSWriter::format_nulary(int t, FILE *fd) const +{ + fprintf(fd, "a%d", t); +} + +void +DebugOperationFormatter::format_nulary(int t, FILE *fd) const +{ + const DynareDynamicAtoms &a = model.getAtoms(); + + if (t == ogp::OperationTree::zero) + fprintf(fd, "0"); + else if (t == ogp::OperationTree::one) + fprintf(fd, "1"); + else if (t == ogp::OperationTree::nan) + fprintf(fd, "NaN"); + else if (t == ogp::OperationTree::two_over_pi) + fprintf(fd, "2/sqrt(PI)"); + else if (a.is_constant(t)) + fprintf(fd, "%g", a.get_constant_value(t)); + else + { + int ll = a.lead(t); + const char *name = a.name(t); + if (ll == 0) + fprintf(fd, "%s", name); + else + fprintf(fd, "%s(%d)", name, ll); + } +} diff --git a/dynare++/src/dynare_model.cpp b/dynare++/src/dynare_model.cpp deleted file mode 100644 index 91d8dda2e4018f1928c30f24aeb84571275194f5..0000000000000000000000000000000000000000 --- a/dynare++/src/dynare_model.cpp +++ /dev/null @@ -1,957 +0,0 @@ -// Copyright (C) 2006-2011, Ondra Kamenik - -#include "parser/cc/parser_exception.h" -#include "parser/cc/location.h" -#include "utils/cc/exception.h" -#include "dynare_model.h" -#include "dynare_exception.h" -#include "planner_builder.h" -#include "forw_subst_builder.h" - -#include <cstdlib> - -#include <string> -#include <cmath> -#include <climits> - -using namespace ogdyn; - -ParsedMatrix::ParsedMatrix(const ogp::MatrixParser& mp) - : TwoDMatrix(mp.nrows(), mp.ncols()) -{ - zeros(); - for (ogp::MPIterator it = mp.begin(); it != mp.end(); ++it) - get(it.row(), it.col()) = *it; -} - -DynareModel::DynareModel() - : atoms(), eqs(atoms), order(-1), - param_vals(0), init_vals(0), vcov_mat(0), - t_plobjective(-1), t_pldiscount(-1), - pbuilder(NULL), fbuilder(NULL), - atom_substs(NULL), old_atoms(NULL) -{} - -DynareModel::DynareModel(const DynareModel& dm) - : atoms(dm.atoms), eqs(dm.eqs, atoms), order(dm.order), - param_vals(0), init_vals(0), vcov_mat(0), - t_plobjective(dm.t_plobjective), - t_pldiscount(dm.t_pldiscount), - pbuilder(NULL), fbuilder(NULL), - atom_substs(NULL), old_atoms(NULL) -{ - if (dm.param_vals) - param_vals = new Vector((const Vector&)*(dm.param_vals)); - if (dm.init_vals) - init_vals = new Vector((const Vector&)*(dm.init_vals)); - if (dm.vcov_mat) - vcov_mat = new TwoDMatrix((const TwoDMatrix&)*(dm.vcov_mat)); - if (dm.old_atoms) - old_atoms = new DynareDynamicAtoms((const DynareDynamicAtoms&)*(dm.old_atoms)); - if (dm.atom_substs) - atom_substs = new ogp::AtomSubstitutions((*dm.atom_substs), *old_atoms, atoms); - if (dm.pbuilder) - pbuilder = new PlannerBuilder(*(dm.pbuilder), *this); - if (dm.fbuilder) - fbuilder = new ForwSubstBuilder(*(dm.fbuilder), *this); -} - -DynareModel::~DynareModel() -{ - if (param_vals) - delete param_vals; - if (init_vals) - delete init_vals; - if (vcov_mat) - delete vcov_mat; - if (old_atoms) - delete old_atoms; - if (atom_substs) - delete atom_substs; - if (pbuilder) - delete pbuilder; - if (fbuilder) - delete fbuilder; -} - -const PlannerInfo* DynareModel::get_planner_info() const -{ - if (pbuilder) - return &(pbuilder->get_info()); - return NULL; -} - -const ForwSubstInfo* DynareModel::get_forw_subst_info() const -{ - if (fbuilder) - return &(fbuilder->get_info()); - return NULL; -} - -const ogp::SubstInfo* DynareModel::get_subst_info() const -{ - if (atom_substs) - return &(atom_substs->get_info()); - return NULL; -} - -void DynareModel::setInitOuter(const Vector& x) -{ - if (x.length() != atoms.ny()) - throw DynareException(__FILE__, __LINE__, - "Wrong length of vector in DynareModel::setInitOuter"); - for (int i = 0; i < atoms.ny(); i++) - (*init_vals)[i] = x[atoms.y2outer_endo()[i]]; -} - -void DynareModel::print() const -{ - printf("all atoms:\n"); - atoms.print(); - printf("formulas:\n"); - DebugOperationFormatter dof(*this); - for (int i = 0; i < eqs.nformulas(); i++) { - int tf = eqs.formula(i); - printf("formula %d:\n", tf); - eqs.getTree().print_operation_tree(tf, stdout, dof); - } -} - -void DynareModel::dump_model(std::ostream& os) const -{ - // endogenous variable declaration - os << "var"; - for (int i = 0; i < (int)atoms.get_endovars().size(); i++) - os << " " << atoms.get_endovars()[i]; - os << ";\n\n"; - - // exogenous variables - os << "varexo"; - for (int i = 0; i < (int)atoms.get_exovars().size(); i++) - os << " " << atoms.get_exovars()[i]; - os << ";\n\n"; - - // parameters - os << "parameters"; - for (int i = 0; i < (int)atoms.get_params().size(); i++) - os << " " << atoms.get_params()[i]; - os << ";\n\n"; - - // parameter values - os.precision(16); - for (int i = 0; i < (int)atoms.get_params().size(); i++) - os << atoms.get_params()[i] << "=" << getParams()[i] << ";\n"; - os << "\n\n"; - - // model section - ogp::OperationStringConvertor osc(atoms, getParser().getTree()); - os << "model;\n"; - for (int i = 0; i < getParser().nformulas(); i++) { - os << "// Equation " << i << "\n0 = "; - int t = getParser().formula(i); - os << osc.convert(getParser().getTree().operation(t), t); - os << ";\n"; - } - os << "end;\n"; - - // initval as steady state - os << "initval;\n"; - for (int i = 0; i < (int)atoms.get_endovars().size(); i++) - os << atoms.get_endovars()[atoms.y2outer_endo()[i]] << "=" << getInit()[i] << ";\n"; - os << "end;\n"; -} - -void DynareModel::add_name(const char* name, int flag) -{ - if (flag == 1) { - // endogenous - atoms.register_uniq_endo(name); - } else if (flag == 2) { - // exogenous - atoms.register_uniq_exo(name); - } else if (flag == 3) { - // parameter - atoms.register_uniq_param(name); - } else { - throw DynareException(__FILE__, __LINE__, - "Unrecognized flag value."); - } -} - -void DynareModel::check_model() const -{ - if (order == -1) - throw DynareException(__FILE__,__LINE__, - "Order of approximation not set in DynareModel::check_model"); - - if (atoms.ny() != eqs.nformulas()) { - char mes[1000]; - sprintf(mes, "Model has %d equations for %d endogenous variables", eqs.nformulas(), atoms.ny()); - throw DynareException(__FILE__, __LINE__, mes); - } - - // check whether all nulary terms of all formulas in eqs are - // either constant or assigned to a name - for (int i = 0; i < eqs.nformulas(); i++) { - int ft = eqs.formula(i); - const unordered_set<int>& nuls = eqs.nulary_of_term(ft); - for (unordered_set<int>::const_iterator it = nuls.begin(); - it != nuls.end(); ++it) - if (! atoms.is_constant(*it) && ! atoms.is_named_atom(*it)) - throw DynareException(__FILE__,__LINE__, - "Dangling nulary term found, internal error."); - } - - int mlag, mlead; - atoms.exovarspan(mlead, mlag); - if (atoms.nexo() > 0 && (mlead != 0 || mlag != 0)) - throw DynareException(__FILE__,__LINE__, - "The model contains occurrences of lagged/leaded exogenous variables"); - - atoms.endovarspan(mlead, mlag); - if (mlead > 1 || mlag < -1) - throw DynareException(__FILE__,__LINE__, - "The model contains occurrences of too lagged/leaded endogenous variables"); - - // check the dimension of vcov matrix - if (getAtoms().nexo() != getVcov().nrows()) - throw DynareException(__FILE__,__LINE__, - "Dimension of VCOV matrix does not correspond to the shocks"); -} - -int DynareModel::variable_shift(int t, int tshift) -{ - const char* name = atoms.name(t); - if (atoms.is_type(name, DynareDynamicAtoms::param) || - atoms.is_constant(t)) - throw DynareException(__FILE__, __LINE__, - "The tree index is not a variable in DynareModel::variable_shift"); - int ll = atoms.lead(t) + tshift; - int res = atoms.index(name, ll); - if (res == -1) { - std::string str(name); - str += '('; - char tmp[50]; - sprintf(tmp,"%d",ll); - str += tmp; - str += ')'; - res = eqs.add_nulary(str.c_str()); - } - return res; -} - -void DynareModel::variable_shift_map(const unordered_set<int>& a_set, int tshift, - map<int,int>& s_map) -{ - s_map.clear(); - for (unordered_set<int>::const_iterator it = a_set.begin(); - it != a_set.end(); ++it) { - int t = *it; - // make shift map only for non-constants and non-parameters - if (! atoms.is_constant(t)) { - const char* name = atoms.name(t); - if (atoms.is_type(name, DynareDynamicAtoms::endovar) || - atoms.is_type(name, DynareDynamicAtoms::exovar)) { - int tt = variable_shift(t, tshift); - s_map.insert(map<int,int>::value_type(t,tt)); - } - } - } -} - -void DynareModel::termspan(int t, int& mlead, int& mlag) const -{ - mlead = INT_MIN; - mlag = INT_MAX; - const unordered_set<int>& nul_terms = eqs.nulary_of_term(t); - for (unordered_set<int>::const_iterator ni = nul_terms.begin(); - ni != nul_terms.end(); ++ni) { - if (!atoms.is_constant(*ni) && - (atoms.is_type(atoms.name(*ni), DynareDynamicAtoms::endovar) || - atoms.is_type(atoms.name(*ni), DynareDynamicAtoms::exovar))) { - int ll = atoms.lead(*ni); - if (ll < mlag) - mlag = ll; - if (ll > mlead) - mlead = ll; - } - } -} - -bool DynareModel::is_constant_term(int t) const -{ - const unordered_set<int>& nul_terms = eqs.nulary_of_term(t); - for (unordered_set<int>::const_iterator ni = nul_terms.begin(); - ni != nul_terms.end(); ++ni) - if (! atoms.is_constant(*ni) && - ! atoms.is_type(atoms.name(*ni), DynareDynamicAtoms::param)) - return false; - return true; -} - -unordered_set<int> DynareModel::get_nonlinear_subterms(int t) const -{ - NLSelector nls(*this); - return eqs.getTree().select_terms(t, nls); -} - -void DynareModel::substitute_atom_for_term(const char* name, int ll, int t) -{ - // if the term t is itself a named atom (parameter, exo, endo), - // then we have to unassign it first - if (atoms.is_named_atom(t)) - atoms.unassign_variable(atoms.name(t), atoms.lead(t), t); - // assign allocated tree index - // for the term now to name(ll) - atoms.assign_variable(name, ll, t); - // make operation t nulary in operation tree - eqs.nularify(t); -} - -void DynareModel::final_job() -{ - if (t_plobjective != -1 && t_pldiscount != -1) { - // at this moment include all equations and all variables; in - // future we will exclude purely exogenous processes; todo: - PlannerBuilder::Tvarset vset; - for (int i = 0; i < atoms.ny(); i++) - vset.insert(atoms.get_endovars()[i]); - PlannerBuilder::Teqset eset; - for (int i = 0; i < eqs.nformulas(); i++) - eset.push_back(i); - - // construct the planner builder, this adds a lot of stuff to - // the model - if (pbuilder) - delete pbuilder; - pbuilder = new PlannerBuilder(*this, vset, eset); - } - - // construct ForwSubstBuilder - if (fbuilder) - delete fbuilder; - fbuilder = new ForwSubstBuilder(*this); - - // call parsing_finished (this will define an outer ordering of all variables) - atoms.parsing_finished(ogp::VarOrdering::bfspbfpb); - // make a copy of atoms and name it old_atoms - if (old_atoms) - delete old_atoms; - old_atoms = new DynareDynamicAtoms(atoms); - // construct empty substitutions from old_atoms to atoms - if (atom_substs) - delete atom_substs; - atom_substs = new ogp::AtomSubstitutions(*old_atoms, atoms); - // do the actual substitution, it will also call - // parsing_finished for atoms which creates internal orderings - atoms.substituteAllLagsAndExo1Leads(eqs, *atom_substs); -} - -extern ogp::location_type dynglob_lloc; - -DynareParser::DynareParser(const char* stream, int len, int ord) - : DynareModel(), - pa_atoms(), paramset(pa_atoms), - ia_atoms(), initval(ia_atoms), vcov(), - model_beg(0), model_end(-1), - paramset_beg(0), paramset_end(-1), - initval_beg(0), initval_end(-1), - vcov_beg(0), vcov_end(-1), - order_beg(0), order_end(-1), - plobjective_beg(0), plobjective_end(-1), - pldiscount_beg(0), pldiscount_end(-1) -{ - // global parse - try { - parse_glob(len, stream); - } catch (const ogp::ParserException& e) { - throw ogp::ParserException(e, dynglob_lloc.off); - } - // setting parameters parse - try { - if (paramset_end > paramset_beg) - paramset.parse(paramset_end-paramset_beg, stream+paramset_beg); - } catch (const ogp::ParserException& e) { - throw ogp::ParserException(e, paramset_beg); - } - // model parse - try { - if (model_end > model_beg) - eqs.parse(model_end-model_beg, stream+model_beg); - else - throw ogp::ParserException("Model section not found.", 0); - } catch (const ogp::ParserException& e) { - throw ogp::ParserException(e, model_beg); - } - // initval setting parse - try { - if (initval_end > initval_beg) - initval.parse(initval_end-initval_beg, stream+initval_beg); - } catch (const ogp::ParserException& e) { - throw ogp::ParserException(e, initval_beg); - } - // vcov parse - try { - if (vcov_end > vcov_beg) { - vcov.parse(vcov_end-vcov_beg, stream+vcov_beg); - } - } catch (const ogp::ParserException& e) { - throw ogp::ParserException(e, vcov_beg); - } - // planner objective parse - try { - if (plobjective_end > plobjective_beg) { - eqs.parse(plobjective_end-plobjective_beg, stream+plobjective_beg); - t_plobjective = eqs.pop_last_formula(); - } - } catch (const ogp::ParserException& e) { - throw ogp::ParserException(e, plobjective_beg); - } - // planner discount parse - try { - if (pldiscount_end > pldiscount_beg) { - t_pldiscount = parse_pldiscount(pldiscount_end - pldiscount_beg, - stream + pldiscount_beg); - } - } catch (const ogp::ParserException& e) { - throw ogp::ParserException(e, pldiscount_beg); - } - // order parse - try { - if (order_end > order_beg) { - order = parse_order(order_end > order_beg, stream + order_beg); - } - } catch (const ogp::ParserException& e) { - throw ogp::ParserException(e, order_beg); - } - - // check the overridden order - if (ord != -1) - order = ord; - - // end parsing job, add planner's FOCs, make substitutions - DynareModel::final_job(); - - // calculate parameters - calc_params(); - // calculate initial values - calc_init(); - - if (vcov_end > vcov_beg) - vcov_mat = new ParsedMatrix(vcov); - else { - // vcov has not been asserted, set it to unit matrix - vcov_mat = new TwoDMatrix(atoms.nexo(), atoms.nexo()); - vcov_mat->unit(); - } - - // check the model - check_model(); - - // differentiate - if (order >= 1) - eqs.differentiate(order); -} - -DynareParser::DynareParser(const DynareParser& dp) - : DynareModel(dp), - pa_atoms(dp.pa_atoms), paramset(dp.paramset, pa_atoms), - ia_atoms(dp.ia_atoms), initval(dp.initval, ia_atoms), vcov(dp.vcov), - model_beg(dp.model_beg), model_end(dp.model_end), - paramset_beg(dp.paramset_beg), paramset_end(dp.paramset_end), - initval_beg(dp.initval_beg), initval_end(dp.initval_end), - vcov_beg(dp.vcov_beg), vcov_end(dp.vcov_end), - order_beg(dp.order_beg), order_end(dp.order_end), - plobjective_beg(dp.plobjective_beg), plobjective_end(dp.plobjective_end), - pldiscount_beg(dp.pldiscount_beg), pldiscount_end(dp.pldiscount_end) -{ -} - -DynareParser::~DynareParser() -{ -} - -void DynareParser::add_name(const char* name, int flag) -{ - DynareModel::add_name(name, flag); - // register with static atoms used for atom assignements - if (flag == 1) { - // endogenous - ia_atoms.register_name(name); - } else if (flag == 2) { - // exogenous - ia_atoms.register_name(name); - } else if (flag == 3) { - // parameter - pa_atoms.register_name(name); - ia_atoms.register_name(name); - } else { - throw DynareException(__FILE__, __LINE__, - "Unrecognized flag value."); - } -} - -void DynareParser::error(const char* mes) -{ - // throwing zero offset since this exception will be caugth at - // constructor - throw ogp::ParserException(mes, 0); -} - -void DynareParser::print() const -{ - DynareModel::print(); - printf("parameter atoms:\n"); - paramset.print(); - printf("initval atoms:\n"); - initval.print(); - printf("model position: %d %d\n", model_beg, model_end); - printf("paramset position: %d %d\n", paramset_beg, paramset_end); - printf("initval position: %d %d\n", initval_beg, initval_end); -} - -/** A global symbol for passing info to the DynareParser from - * parser. */ -DynareParser* dynare_parser; - -/** The declarations of functions defined in dynglob_ll.cc and - * dynglob_tab.cc generated from dynglob.lex and dynglob.y */ -void* dynglob__scan_buffer(char*, size_t); -void dynglob__destroy_buffer(void*); -void dynglob_parse(); -extern ogp::location_type dynglob_lloc; - -void DynareParser::parse_glob(int length, const char* stream) -{ - char* buffer = new char[length+2]; - strncpy(buffer, stream, length); - buffer[length] = '\0'; - buffer[length+1] = '\0'; - void* p = dynglob__scan_buffer(buffer, (unsigned int)length+2); - dynare_parser = this; - dynglob_parse(); - delete [] buffer; - dynglob__destroy_buffer(p); -} - - -int DynareParser::parse_order(int len, const char* str) -{ - char* buf = new char[len+1]; - strncpy(buf, str, len); - buf[len] = '\0'; - int res; - sscanf(buf, "%d", &res); - delete [] buf; - return res; -} - -int DynareParser::parse_pldiscount(int len, const char* str) -{ - char* buf = new char[len+1]; - strncpy(buf, str, len); - buf[len] = '\0'; - if (! atoms.is_type(buf, DynareDynamicAtoms::param)) - throw ogp::ParserException(std::string("Name ") + buf + " is not a parameter", 0); - - int t = atoms.index(buf, 0); - if (t == -1) - t = eqs.add_nulary(buf); - - delete [] buf; - return t; -} - -void DynareParser::calc_params() -{ - if (param_vals) - delete param_vals; - - param_vals = new Vector(atoms.np()); - ogp::AtomAsgnEvaluator aae(paramset); - aae.eval(); - for (int i = 0; i < atoms.np(); i++) - (*param_vals)[i] = aae.get_value(atoms.get_params()[i]); - - for (unsigned int i = 0; i < atoms.get_params().size(); i++) - if (! std::isfinite((*param_vals)[i])) - printf("dynare++: warning: value for parameter %s is not finite\n", - atoms.get_params()[i]); -} - -void DynareParser::calc_init() -{ - // update initval atoms assignings according to substitutions - if (atom_substs) - initval.apply_subst(atom_substs->get_old2new()); - - // calculate the vector of initial values - if (init_vals) - delete init_vals; - init_vals = new Vector(atoms.ny()); - ogp::AtomAsgnEvaluator aae(initval); - // set parameters - for (int ip = 0; ip < atoms.np(); ip++) - aae.set_user_value(atoms.get_params()[ip], (*param_vals)[ip]); - // set exogenous to zeros - for (int ie = 0; ie < atoms.nexo(); ie++) - aae.set_user_value(atoms.get_exovars()[ie], 0.0); - // evaluate - aae.eval(); - // set results to internally ordered vector init_vals - for (int outer = 0; outer < atoms.ny(); outer++) { - int i = atoms.outer2y_endo()[outer]; - (*init_vals)[i] = aae.get_value(atoms.get_endovars()[outer]); - } - - // if the planner's FOCs have been added, then add estimate of - // Lagrange multipliers to the vector - if (pbuilder) { - MultInitSS mis(*pbuilder, *param_vals, *init_vals); - } - - // if forward substitution builder has been created, we have to - // its substitutions and evaluate them - if (fbuilder) - ogdyn::DynareSteadySubstitutions dss(atoms, eqs.getTree(), - fbuilder->get_aux_map(), *param_vals, *init_vals); - - for (unsigned int i = 0; i < atoms.get_endovars().size(); i++) - if (! std::isfinite((*init_vals)[i])) - printf("dynare++: warning: initval for <%s> is not finite\n", - atoms.get_endovars()[atoms.y2outer_endo()[i]]); -} - -// this returns false for linear functions -bool NLSelector::operator()(int t) const -{ - const ogp::Operation& op = model.getParser().getTree().operation(t); - const DynareDynamicAtoms& atoms = model.getAtoms(); - // if the term is constant, return false - if (model.is_constant_term(t)) - return false; - int nary = op.nary(); - if (nary == 0) { - if (atoms.is_type(atoms.name(t), DynareDynamicAtoms::endovar) || - atoms.is_type(atoms.name(t), DynareDynamicAtoms::exovar)) - return true; - else - return false; - } else if (nary == 1) { - if (op.getCode() == ogp::UMINUS) - return false; - else - return true; - } else { - if (op.getCode() == ogp::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())) - return false; - else - return true; - // both PLUS and MINUS are linear - if (op.getCode() == ogp::PLUS || - op.getCode() == ogp::MINUS) - return false; - // POWER is linear if exponent or base is 0 or one - if (op.getCode() == ogp::POWER && - (op.getOp1() == ogp::OperationTree::zero || - op.getOp1() == ogp::OperationTree::one || - op.getOp2() == ogp::OperationTree::zero || - op.getOp2() == ogp::OperationTree::one)) - return false; - else - return true; - // DIVIDE is linear if the denominator is constant, or if - // the nominator is zero - if (op.getCode() == ogp::DIVIDE && - (op.getOp1() == ogp::OperationTree::zero || - model.is_constant_term(op.getOp2()))) - return false; - else - return true; - } - - throw DynareException(__FILE__, __LINE__, - "Wrong operation in operation tree"); - return false; -} - -DynareSPModel::DynareSPModel(const char** endo, int num_endo, - const char** exo, int num_exo, - const char** par, int num_par, - const char* equations, int len, - int ord) - : DynareModel() -{ - // set the order - order = ord; - - // add names - for (int i = 0; i < num_endo; i++) - add_name(endo[i], 1); - for (int i = 0; i < num_exo; i++) - add_name(exo[i], 2); - for (int i = 0; i < num_par; i++) - add_name(par[i], 3); - - // parse the equations - eqs.parse(len, equations); - - // parsing finished - atoms.parsing_finished(ogp::VarOrdering::bfspbfpb); - - // create what has to be created from DynareModel - param_vals = new Vector(atoms.np()); - init_vals = new Vector(atoms.ny()); - vcov_mat = new TwoDMatrix(atoms.nexo(), atoms.nexo()); - - // check the model - check_model(); - - // differentiate - if (order >= 1) - eqs.differentiate(order); -} - -void ModelSSWriter::write_der0(FILE* fd) -{ - write_der0_preamble(fd); - write_atom_assignment(fd); - - stop_set.clear(); - for (int fi = 0; fi < model.eqs.nformulas(); fi++) - otree.print_operation_tree(model.eqs.formula(fi), fd, *this); - - write_der0_assignment(fd); -} - -void ModelSSWriter::write_der1(FILE* fd) -{ - write_der1_preamble(fd); - write_atom_assignment(fd); - - stop_set.clear(); - - const vector<int>& variables = model.getAtoms().variables(); - const vector<int>& eam = model.getAtoms().get_endo_atoms_map(); - for (int i = 0; i < model.getParser().nformulas(); i++) { - const ogp::FormulaDerivatives& fder = model.getParser().derivatives(i); - for (unsigned int j = 0; j < eam.size(); j++) { - int t = fder.derivative(ogp::FoldMultiIndex(variables.size(), 1, eam[j])); - if (t > 0) - otree.print_operation_tree(t, fd, *this); - } - } - - write_der1_assignment(fd); -} - -MatlabSSWriter::MatlabSSWriter(const DynareModel& dm, const char* idd) - : ModelSSWriter(dm), id(new char[strlen(idd)+1]) -{ - strcpy(id, idd); -} - - -void MatlabSSWriter::write_der0_preamble(FILE* fd) 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); -} - -void MatlabSSWriter::write_der1_preamble(FILE* fd) 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); -} - -void MatlabSSWriter::write_common1_preamble(FILE* fd) 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); - // write ordering of parameters - fprintf(fd, "\n%% params ordering\n%% =====================\n"); - for (unsigned int ip = 0; ip < model.getAtoms().get_params().size(); ip++) { - const char* parname = model.getAtoms().get_params()[ip]; - fprintf(fd, "%% %s\n", parname); - } - // write endogenous variables - fprintf(fd, "%%\n%% y ordering\n%% =====================\n"); - for (unsigned int ie = 0; ie < model.getAtoms().get_endovars().size(); ie++) { - const char* endoname = model.getAtoms().get_endovars()[ie]; - fprintf(fd, "%% %s\n", endoname); - } - fprintf(fd,"\n"); -} - -void MatlabSSWriter::write_common2_preamble(FILE* fd) 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()); -} - -void MatlabSSWriter::write_atom_assignment(FILE* fd) const -{ - // write OperationTree::num_constants - fprintf(fd, "%% 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); - double g = etree.eval(i); - if (std::isnan(g)) - fprintf(fd, " = NaN;\n"); - else - fprintf(fd, " = %12.8g;\n", etree.eval(i)); - } - // write numerical constants - fprintf(fd, "%% numerical constants\n"); - const ogp::Constants::Tconstantmap& cmap = model.getAtoms().get_constantmap(); - for (ogp::Constants::Tconstantmap::const_iterator it = cmap.begin(); - it != cmap.end(); ++it) { - format_nulary((*it).first, fd); - fprintf(fd, " = %12.8g;\n", (*it).second); - } - // write parameters - fprintf(fd, "%% 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); - } else { - format_nulary(t, fd); - fprintf(fd, " = params(%d); %% %s\n", ip+1, parname); - } - } - // write exogenous variables - fprintf(fd, "%% 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]; - try { - const ogp::DynamicAtoms::Tlagmap& lmap = model.getAtoms().lagmap(exoname); - for (ogp::DynamicAtoms::Tlagmap::const_iterator it = lmap.begin(); - it != lmap.end(); ++it) { - format_nulary((*it).second, fd); - fprintf(fd, " = 0.0; %% %s\n", exoname); - } - } catch (const ogu::Exception& e) { - // ignore the error of not found variable in the tree - } - } - // write endogenous variables - fprintf(fd, "%% 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 (ogp::DynamicAtoms::Tlagmap::const_iterator it = lmap.begin(); - it != lmap.end(); ++it) { - format_nulary((*it).second, fd); - fprintf(fd, " = y(%d); %% %s\n", ie+1, endoname); - } - } - fprintf(fd,"\n"); -} - -void MatlabSSWriter::write_der0_assignment(FILE* fd) const -{ - - // initialize out variable - fprintf(fd, "%% setting the output variable\n"); - fprintf(fd, "out = zeros(%d, 1);\n", model.getParser().nformulas()); - - // 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"); - } -} - -void MatlabSSWriter::write_der1_assignment(FILE* fd) const -{ - // initialize out variable - fprintf(fd, "%% setting the output variable\n"); - fprintf(fd, "out = zeros(%d, %d);\n", model.getParser().nformulas(), model.getAtoms().ny()); - - // fill out with the terms - const vector<int>& variables = model.getAtoms().variables(); - const vector<int>& eam = model.getAtoms().get_endo_atoms_map(); - for (int i = 0; i < model.getParser().nformulas(); i++) { - const ogp::FormulaDerivatives& fder = model.getParser().derivatives(i); - for (unsigned int j = 0; j < eam.size(); j++) { - int tvar = variables[eam[j]]; - const char* name = model.getAtoms().name(tvar); - int yi = model.getAtoms().name2outer_endo(name); - int t = fder.derivative(ogp::FoldMultiIndex(variables.size(), 1, eam[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)); - } - } - } -} - -void MatlabSSWriter::format_term(int t, FILE* fd) const -{ - fprintf(fd, "t%d", t); -} - -void MatlabSSWriter::format_nulary(int t, FILE* fd) const -{ - fprintf(fd, "a%d", t); -} - -void DebugOperationFormatter::format_nulary(int t, FILE* fd) const -{ - const DynareDynamicAtoms& a = model.getAtoms(); - - if (t == ogp::OperationTree::zero) - fprintf(fd, "0"); - else if (t == ogp::OperationTree::one) - fprintf(fd, "1"); - else if (t == ogp::OperationTree::nan) - fprintf(fd, "NaN"); - else if (t == ogp::OperationTree::two_over_pi) - fprintf(fd, "2/sqrt(PI)"); - else if (a.is_constant(t)) - fprintf(fd, "%g", a.get_constant_value(t)); - else { - int ll = a.lead(t); - const char* name = a.name(t); - if (ll == 0) - fprintf(fd, "%s", name); - else - fprintf(fd, "%s(%d)", name, ll); - } -} diff --git a/dynare++/src/dynare_model.h b/dynare++/src/dynare_model.hh similarity index 99% rename from dynare++/src/dynare_model.h rename to dynare++/src/dynare_model.hh index 543a5e3937f7f4de59bc93fddee8c0c06b296418..5321bd6230c39748735e265e8c598a8a73e9e988 100644 --- a/dynare++/src/dynare_model.h +++ b/dynare++/src/dynare_model.hh @@ -3,14 +3,14 @@ #ifndef OGDYN_DYNARE_MODEL #define OGDYN_DYNARE_MODEL -#include "parser/cc/matrix_parser.h" -#include "parser/cc/atom_assignings.h" +#include "parser/cc/matrix_parser.hh" +#include "parser/cc/atom_assignings.hh" -#include "dynare_atoms.h" +#include "dynare_atoms.hh" #include "twod_matrix.hh" -#include "Vector.h" -#include "GeneralMatrix.h" +#include "Vector.hh" +#include "GeneralMatrix.hh" #include <map> #include <boost/unordered_set.hpp> diff --git a/dynare++/src/dynare_params.cc b/dynare++/src/dynare_params.cc new file mode 100644 index 0000000000000000000000000000000000000000..c94f38ca12163bebb6c4e7de02f7bbaac2240b5b --- /dev/null +++ b/dynare++/src/dynare_params.cc @@ -0,0 +1,278 @@ +// Copyright (C) 2004-2011, Ondra Kamenik + +#include "dynare_params.hh" + +#include <getopt.h> +#include <cstdio> +#include <cstring> + +const char *help_str += "usage: dynare++ [--help] [--version] [options] <model file>\n" + "\n" + " --help print this message and return\n" + " --version print version and return\n" + "\n" + "options:\n" + " --per <num> number of periods simulated after burnt [100]\n" + " --burn <num> number of periods burnt [0]\n" + " --sim <num> number of simulations [80]\n" + " --rtper <num> number of RT periods simulated after burnt [0]\n" + " --rtsim <num> number of RT simulations [0]\n" + " --condper <num> number of periods in cond. simulations [0]\n" + " --condsim <num> number of conditional simulations [0]\n" + " --steps <num> steps towards stoch. SS [0=deter.]\n" + " --centralize centralize the rule [do centralize]\n" + " --no-centralize do not centralize the rule [do centralize]\n" + " --prefix <string> prefix of variables in Mat-4 file [\"dyn\"]\n" + " --seed <num> random number generator seed [934098]\n" + " --order <num> order of approximation [no default]\n" + " --threads <num> number of max parallel threads [2]\n" + " --ss-tol <num> steady state calcs tolerance [1.e-13]\n" + " --check pesPES check model residuals [no checks]\n" + " lower/upper case switches off/on\n" + " pP checking along simulation path\n" + " eE checking on ellipse\n" + " sS checking along shocks\n" + " --check-evals <num> max number of evals per residual [1000]\n" + " --check-num <num> number of checked points [10]\n" + " --check-scale <num> scaling of checked points [2.0]\n" + " --no-irfs shuts down IRF simulations [do IRFs]\n" + " --irfs performs IRF simulations [do IRFs]\n" + " --qz-criterium <num> threshold for stable eigenvalues [1.000001]\n" + "\n\n"; + +// returns the pointer to the first character after the last slash or +// backslash in the string +const char *dyn_basename(const char *str); + +DynareParams::DynareParams(int argc, char **argv) + : modname(NULL), num_per(100), num_burn(0), num_sim(80), + num_rtper(0), num_rtsim(0), + num_condper(0), num_condsim(0), + num_threads(2), num_steps(0), + prefix("dyn"), seed(934098), order(-1), ss_tol(1.e-13), + check_along_path(false), check_along_shocks(false), + check_on_ellipse(false), check_evals(1000), check_num(10), check_scale(2.0), + do_irfs_all(true), do_centralize(true), qz_criterium(1.0+1e-6), + help(false), version(false) +{ + if (argc == 1 || !strcmp(argv[1], "--help")) + { + help = true; + return; + } + if (argc == 1 || !strcmp(argv[1], "--version")) + { + version = true; + return; + } + + modname = argv[argc-1]; + argc--; + + struct option const opts [] = { + {"periods", required_argument, NULL, opt_per}, + {"per", required_argument, NULL, opt_per}, + {"burn", required_argument, NULL, opt_burn}, + {"simulations", required_argument, NULL, opt_sim}, + {"sim", required_argument, NULL, opt_sim}, + {"rtperiods", required_argument, NULL, opt_rtper}, + {"rtper", required_argument, NULL, opt_rtper}, + {"rtsimulations", required_argument, NULL, opt_rtsim}, + {"rtsim", required_argument, NULL, opt_rtsim}, + {"condperiods", required_argument, NULL, opt_condper}, + {"condper", required_argument, NULL, opt_condper}, + {"condsimulations", required_argument, NULL, opt_condsim}, + {"condsim", required_argument, NULL, opt_condsim}, + {"prefix", required_argument, NULL, opt_prefix}, + {"threads", required_argument, NULL, opt_threads}, + {"steps", required_argument, NULL, opt_steps}, + {"seed", required_argument, NULL, opt_seed}, + {"order", required_argument, NULL, opt_order}, + {"ss-tol", required_argument, NULL, opt_ss_tol}, + {"check", required_argument, NULL, opt_check}, + {"check-scale", required_argument, NULL, opt_check_scale}, + {"check-evals", required_argument, NULL, opt_check_evals}, + {"check-num", required_argument, NULL, opt_check_num}, + {"qz-criterium", required_argument, NULL, opt_qz_criterium}, + {"no-irfs", no_argument, NULL, opt_noirfs}, + {"irfs", no_argument, NULL, opt_irfs}, + {"centralize", no_argument, NULL, opt_centralize}, + {"no-centralize", no_argument, NULL, opt_no_centralize}, + {"help", no_argument, NULL, opt_help}, + {"version", no_argument, NULL, opt_version}, + {NULL, 0, NULL, 0} + }; + + int ret; + int index; + while (-1 != (ret = getopt_long(argc, argv, "", opts, &index))) + { + switch (ret) + { + case opt_per: + if (1 != sscanf(optarg, "%d", &num_per)) + fprintf(stderr, "Couldn't parse integer %s, ignored\n", optarg); + break; + case opt_burn: + if (1 != sscanf(optarg, "%d", &num_burn)) + fprintf(stderr, "Couldn't parse integer %s, ignored\n", optarg); + break; + case opt_sim: + if (1 != sscanf(optarg, "%d", &num_sim)) + fprintf(stderr, "Couldn't parse integer %s, ignored\n", optarg); + break; + case opt_rtper: + if (1 != sscanf(optarg, "%d", &num_rtper)) + fprintf(stderr, "Couldn't parse integer %s, ignored\n", optarg); + break; + case opt_rtsim: + if (1 != sscanf(optarg, "%d", &num_rtsim)) + fprintf(stderr, "Couldn't parse integer %s, ignored\n", optarg); + break; + case opt_condper: + if (1 != sscanf(optarg, "%d", &num_condper)) + fprintf(stderr, "Couldn't parse integer %s, ignored\n", optarg); + break; + case opt_condsim: + if (1 != sscanf(optarg, "%d", &num_condsim)) + fprintf(stderr, "Couldn't parse integer %s, ignored\n", optarg); + break; + case opt_prefix: + prefix = optarg; + break; + case opt_threads: + if (1 != sscanf(optarg, "%d", &num_threads)) + fprintf(stderr, "Couldn't parse integer %s, ignored\n", optarg); + break; + case opt_steps: + if (1 != sscanf(optarg, "%d", &num_steps)) + fprintf(stderr, "Couldn't parse integer %s, ignored\n", optarg); + break; + case opt_seed: + if (1 != sscanf(optarg, "%d", &seed)) + fprintf(stderr, "Couldn't parse integer %s, ignored\n", optarg); + break; + case opt_order: + if (1 != sscanf(optarg, "%d", &order)) + fprintf(stderr, "Couldn't parse integer %s, ignored\n", optarg); + break; + case opt_ss_tol: + if (1 != sscanf(optarg, "%lf", &ss_tol)) + fprintf(stderr, "Couldn't parse float %s, ignored\n", optarg); + break; + case opt_check: + processCheckFlags(optarg); + break; + case opt_check_scale: + if (1 != sscanf(optarg, "%lf", &check_scale)) + fprintf(stderr, "Couldn't parse float %s, ignored\n", optarg); + break; + case opt_check_evals: + if (1 != sscanf(optarg, "%d", &check_evals)) + fprintf(stderr, "Couldn't parse integer %s, ignored\n", optarg); + break; + case opt_check_num: + if (1 != sscanf(optarg, "%d", &check_num)) + fprintf(stderr, "Couldn't parse integer %s, ignored\n", optarg); + break; + case opt_noirfs: + irf_list.clear(); + do_irfs_all = false; + break; + case opt_irfs: + processIRFList(argc, argv); + if (irf_list.empty()) + do_irfs_all = true; + else + do_irfs_all = false; + break; + case opt_centralize: + do_centralize = true; + break; + case opt_no_centralize: + do_centralize = false; + break; + case opt_qz_criterium: + if (1 != sscanf(optarg, "%lf", &qz_criterium)) + fprintf(stderr, "Couldn't parse float %s, ignored\n", optarg); + break; + case opt_help: + help = true; + break; + case opt_version: + version = true; + break; + case '?': + fprintf(stderr, "Unknown option, ignored\n"); + break; + } + } + + // make basename (get rid of the extension) + basename = dyn_basename(modname); + std::string::size_type i = basename.rfind('.'); + if (i != std::string::npos) + basename.erase(i); +} + +void +DynareParams::printHelp() const +{ + printf("%s", help_str); +} + +void +DynareParams::processCheckFlags(const char *flags) +{ + for (unsigned int i = 0; i < strlen(flags); i++) + { + switch (flags[i]) + { + case 'p': + check_along_path = false; + break; + case 'P': + check_along_path = true; + break; + case 'e': + check_on_ellipse = false; + break; + case 'E': + check_on_ellipse = true; + break; + case 's': + check_along_shocks = false; + break; + case 'S': + check_along_shocks = true; + break; + default: + fprintf(stderr, "Unknown check type selection character <%c>, ignored.\n", flags[i]); + } + } +} + +void +DynareParams::processIRFList(int argc, char **argv) +{ + irf_list.clear(); + while (optind < argc && *(argv[optind]) != '-') + { + irf_list.push_back(argv[optind]); + optind++; + } +} + +const char * +dyn_basename(const char *str) +{ + int i = strlen(str); + while (i > 0 && str[i-1] != '/' && str[i-1] != '\\') + i--; + return str+i; +} + +// Local Variables: +// mode:C++ +// End: diff --git a/dynare++/src/dynare_params.cpp b/dynare++/src/dynare_params.cpp deleted file mode 100644 index 95a76a674c8c3b4c7e27b0f8dbfe38552fdc0c23..0000000000000000000000000000000000000000 --- a/dynare++/src/dynare_params.cpp +++ /dev/null @@ -1,267 +0,0 @@ -// Copyright (C) 2004-2011, Ondra Kamenik - -#include "dynare_params.h" - -#include <getopt.h> -#include <cstdio> -#include <cstring> - -const char* help_str = -"usage: dynare++ [--help] [--version] [options] <model file>\n" -"\n" -" --help print this message and return\n" -" --version print version and return\n" -"\n" -"options:\n" -" --per <num> number of periods simulated after burnt [100]\n" -" --burn <num> number of periods burnt [0]\n" -" --sim <num> number of simulations [80]\n" -" --rtper <num> number of RT periods simulated after burnt [0]\n" -" --rtsim <num> number of RT simulations [0]\n" -" --condper <num> number of periods in cond. simulations [0]\n" -" --condsim <num> number of conditional simulations [0]\n" -" --steps <num> steps towards stoch. SS [0=deter.]\n" -" --centralize centralize the rule [do centralize]\n" -" --no-centralize do not centralize the rule [do centralize]\n" -" --prefix <string> prefix of variables in Mat-4 file [\"dyn\"]\n" -" --seed <num> random number generator seed [934098]\n" -" --order <num> order of approximation [no default]\n" -" --threads <num> number of max parallel threads [2]\n" -" --ss-tol <num> steady state calcs tolerance [1.e-13]\n" -" --check pesPES check model residuals [no checks]\n" -" lower/upper case switches off/on\n" -" pP checking along simulation path\n" -" eE checking on ellipse\n" -" sS checking along shocks\n" -" --check-evals <num> max number of evals per residual [1000]\n" -" --check-num <num> number of checked points [10]\n" -" --check-scale <num> scaling of checked points [2.0]\n" -" --no-irfs shuts down IRF simulations [do IRFs]\n" -" --irfs performs IRF simulations [do IRFs]\n" -" --qz-criterium <num> threshold for stable eigenvalues [1.000001]\n" -"\n\n"; - -// returns the pointer to the first character after the last slash or -// backslash in the string -const char* dyn_basename(const char* str); - -DynareParams::DynareParams(int argc, char** argv) - : modname(NULL), num_per(100), num_burn(0), num_sim(80), - num_rtper(0), num_rtsim(0), - num_condper(0), num_condsim(0), - num_threads(2), num_steps(0), - prefix("dyn"), seed(934098), order(-1), ss_tol(1.e-13), - check_along_path(false), check_along_shocks(false), - check_on_ellipse(false), check_evals(1000), check_num(10), check_scale(2.0), - do_irfs_all(true), do_centralize(true), qz_criterium(1.0+1e-6), - help(false), version(false) -{ - if (argc == 1 || !strcmp(argv[1],"--help")) { - help = true; - return; - } - if (argc == 1 || !strcmp(argv[1],"--version")) { - version = true; - return; - } - - modname = argv[argc-1]; - argc--; - - struct option const opts [] = { - {"periods", required_argument, NULL, opt_per}, - {"per", required_argument, NULL, opt_per}, - {"burn", required_argument, NULL, opt_burn}, - {"simulations", required_argument, NULL, opt_sim}, - {"sim", required_argument, NULL, opt_sim}, - {"rtperiods", required_argument, NULL, opt_rtper}, - {"rtper", required_argument, NULL, opt_rtper}, - {"rtsimulations", required_argument, NULL, opt_rtsim}, - {"rtsim", required_argument, NULL, opt_rtsim}, - {"condperiods", required_argument, NULL, opt_condper}, - {"condper", required_argument, NULL, opt_condper}, - {"condsimulations", required_argument, NULL, opt_condsim}, - {"condsim", required_argument, NULL, opt_condsim}, - {"prefix", required_argument, NULL, opt_prefix}, - {"threads", required_argument, NULL, opt_threads}, - {"steps", required_argument, NULL, opt_steps}, - {"seed", required_argument, NULL, opt_seed}, - {"order", required_argument, NULL, opt_order}, - {"ss-tol", required_argument, NULL, opt_ss_tol}, - {"check", required_argument, NULL, opt_check}, - {"check-scale", required_argument, NULL, opt_check_scale}, - {"check-evals", required_argument, NULL, opt_check_evals}, - {"check-num", required_argument, NULL, opt_check_num}, - {"qz-criterium",required_argument, NULL, opt_qz_criterium}, - {"no-irfs", no_argument, NULL, opt_noirfs}, - {"irfs", no_argument, NULL, opt_irfs}, - {"centralize", no_argument, NULL, opt_centralize}, - {"no-centralize", no_argument, NULL, opt_no_centralize}, - {"help", no_argument, NULL, opt_help}, - {"version", no_argument, NULL, opt_version}, - {NULL, 0, NULL, 0} - }; - - int ret; - int index; - while (-1 != (ret = getopt_long(argc, argv, "", opts, &index))) { - switch (ret) { - case opt_per: - if (1 != sscanf(optarg, "%d", &num_per)) - fprintf(stderr, "Couldn't parse integer %s, ignored\n", optarg); - break; - case opt_burn: - if (1 != sscanf(optarg, "%d", &num_burn)) - fprintf(stderr, "Couldn't parse integer %s, ignored\n", optarg); - break; - case opt_sim: - if (1 != sscanf(optarg, "%d", &num_sim)) - fprintf(stderr, "Couldn't parse integer %s, ignored\n", optarg); - break; - case opt_rtper: - if (1 != sscanf(optarg, "%d", &num_rtper)) - fprintf(stderr, "Couldn't parse integer %s, ignored\n", optarg); - break; - case opt_rtsim: - if (1 != sscanf(optarg, "%d", &num_rtsim)) - fprintf(stderr, "Couldn't parse integer %s, ignored\n", optarg); - break; - case opt_condper: - if (1 != sscanf(optarg, "%d", &num_condper)) - fprintf(stderr, "Couldn't parse integer %s, ignored\n", optarg); - break; - case opt_condsim: - if (1 != sscanf(optarg, "%d", &num_condsim)) - fprintf(stderr, "Couldn't parse integer %s, ignored\n", optarg); - break; - case opt_prefix: - prefix = optarg; - break; - case opt_threads: - if (1 != sscanf(optarg, "%d", &num_threads)) - fprintf(stderr, "Couldn't parse integer %s, ignored\n", optarg); - break; - case opt_steps: - if (1 != sscanf(optarg, "%d", &num_steps)) - fprintf(stderr, "Couldn't parse integer %s, ignored\n", optarg); - break; - case opt_seed: - if (1 != sscanf(optarg, "%d", &seed)) - fprintf(stderr, "Couldn't parse integer %s, ignored\n", optarg); - break; - case opt_order: - if (1 != sscanf(optarg, "%d", &order)) - fprintf(stderr, "Couldn't parse integer %s, ignored\n", optarg); - break; - case opt_ss_tol: - if (1 != sscanf(optarg, "%lf", &ss_tol)) - fprintf(stderr, "Couldn't parse float %s, ignored\n", optarg); - break; - case opt_check: - processCheckFlags(optarg); - break; - case opt_check_scale: - if (1 != sscanf(optarg, "%lf", &check_scale)) - fprintf(stderr, "Couldn't parse float %s, ignored\n", optarg); - break; - case opt_check_evals: - if (1 != sscanf(optarg, "%d", &check_evals)) - fprintf(stderr, "Couldn't parse integer %s, ignored\n", optarg); - break; - case opt_check_num: - if (1 != sscanf(optarg, "%d", &check_num)) - fprintf(stderr, "Couldn't parse integer %s, ignored\n", optarg); - break; - case opt_noirfs: - irf_list.clear(); - do_irfs_all = false; - break; - case opt_irfs: - processIRFList(argc, argv); - if (irf_list.empty()) - do_irfs_all = true; - else - do_irfs_all = false; - break; - case opt_centralize: - do_centralize = true; - break; - case opt_no_centralize: - do_centralize = false; - break; - case opt_qz_criterium: - if (1 != sscanf(optarg, "%lf", &qz_criterium)) - fprintf(stderr, "Couldn't parse float %s, ignored\n", optarg); - break; - case opt_help: - help = true; - break; - case opt_version: - version = true; - break; - case '?': - fprintf(stderr, "Unknown option, ignored\n"); - break; - } - } - - // make basename (get rid of the extension) - basename = dyn_basename(modname); - std::string::size_type i = basename.rfind('.'); - if (i != std::string::npos) - basename.erase(i); -} - -void DynareParams::printHelp() const -{ - printf("%s", help_str); -} - -void DynareParams::processCheckFlags(const char* flags) -{ - for (unsigned int i = 0; i < strlen(flags); i++) { - switch (flags[i]) { - case 'p': - check_along_path = false; - break; - case 'P': - check_along_path = true; - break; - case 'e': - check_on_ellipse = false; - break; - case 'E': - check_on_ellipse = true; - break; - case 's': - check_along_shocks = false; - break; - case 'S': - check_along_shocks = true; - break; - default: - fprintf(stderr, "Unknown check type selection character <%c>, ignored.\n", flags[i]); - } - } -} - -void DynareParams::processIRFList(int argc, char** argv) -{ - irf_list.clear(); - while (optind < argc && *(argv[optind]) != '-') { - irf_list.push_back(argv[optind]); - optind++; - } -} - -const char* dyn_basename(const char* str) -{ - int i = strlen(str); - while (i > 0 && str[i-1] != '/' && str[i-1] != '\\') - i--; - return str+i; -} - -// Local Variables: -// mode:C++ -// End: diff --git a/dynare++/src/dynare_params.h b/dynare++/src/dynare_params.hh similarity index 100% rename from dynare++/src/dynare_params.h rename to dynare++/src/dynare_params.hh diff --git a/dynare++/src/dynglob.lex b/dynare++/src/dynglob.ll similarity index 97% rename from dynare++/src/dynglob.lex rename to dynare++/src/dynglob.ll index aaf4e4a5f264341799b316a43e18bce88cdf671b..6450bd63a95706d8d6236fabdbd3471d75ab69f5 100644 --- a/dynare++/src/dynglob.lex +++ b/dynare++/src/dynglob.ll @@ -1,5 +1,5 @@ %{ -#include "parser/cc/location.h" +#include "parser/cc/location.hh" #include "dynglob_tab.hh" extern YYLTYPE dynglob_lloc; diff --git a/dynare++/src/dynglob.y b/dynare++/src/dynglob.yy similarity index 98% rename from dynare++/src/dynglob.y rename to dynare++/src/dynglob.yy index 536a474a2ce4239fceccac2f1b1145742a6a9647..a15287abbdc0965eec005899789bcaa4384d0457 100644 --- a/dynare++/src/dynglob.y +++ b/dynare++/src/dynglob.yy @@ -1,8 +1,8 @@ %{ // Copyright (C) 2006-2011, Ondra Kamenik -#include "parser/cc/location.h" -#include "dynare_model.h" +#include "parser/cc/location.hh" +#include "dynare_model.hh" #include "dynglob_tab.hh" #include <stdio.h> diff --git a/dynare++/src/forw_subst_builder.cc b/dynare++/src/forw_subst_builder.cc new file mode 100644 index 0000000000000000000000000000000000000000..10a97fb997cbd9c98cad434202fcf22bc175bc4e --- /dev/null +++ b/dynare++/src/forw_subst_builder.cc @@ -0,0 +1,133 @@ +// Copyright (C) 2006-2011, Ondra Kamenik + +#include "forw_subst_builder.hh" + +using namespace ogdyn; + +ForwSubstBuilder::ForwSubstBuilder(DynareModel &m) + : model(m) +{ + info.num_new_terms -= model.getParser().getTree().get_num_op(); + + // go through all equations + int neq = model.eqs.nformulas(); + for (int i = 0; i < neq; i++) + { + int ft = model.eqs.formula(i); + int mlead, mlag; + model.termspan(ft, mlead, mlag); + // if equation is too forward looking + if (mlead > 1) + { + info.num_affected_equations++; + // break it to non-linear terms + unordered_set<int> nlt = model.get_nonlinear_subterms(ft); + int j = 0; // indexes subterms + // and make substitutions for all these non-linear subterms + for (unordered_set<int>::const_iterator it = nlt.begin(); + it != nlt.end(); ++it, ++j) + substitute_for_term(*it, i, j); + } + } + // unassign all variables with lead greater than 1 + unassign_gt_1_leads(); + + // forget the derivatives in the tree because some variables could + // have been unassigned + model.eqs.getTree().forget_derivative_maps(); + + info.num_new_terms += model.getParser().getTree().get_num_op(); +} + +void +ForwSubstBuilder::substitute_for_term(int t, int i, int j) +{ + int mlead, mlag; + model.termspan(t, mlead, mlag); + if (mlead > 1) + { + info.num_subst_terms++; + // Example for comments: let t = f(x(+4)) + // first make lagsubst be substitution setting f(x(+4)) to f(x(+1)) + // this is lag = -3 (1-mlead) + map<int, int> lagsubst; + unordered_set<int> nult = model.eqs.nulary_of_term(t);// make copy of nult! + model.variable_shift_map(nult, 1-mlead, lagsubst); + int lagt = model.eqs.add_substitution(t, lagsubst); + + // now maxlead of lagt is +1 + // add AUXLD_*_*_1 = f(x(+1)) to the model + char name[100]; + sprintf(name, "AUXLD_%d_%d_%d", i, j, 1); + model.atoms.register_uniq_endo(name); + 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)); + aux_map.insert(Tsubstmap::value_type(ss, lagt)); + // now add variables and equations + // AUXLD_*_*_2 = AUXLD_*_*_1(+1) through + // AUXLD_*_*_{mlead-1} = AUXLD_*_*_{mlead-2}(+1) + for (int ll = 1; ll <= mlead-2; ll++) + { + // create AUXLD_*_*_{ll}(+1) + sprintf(name, "AUXLD_%d_%d_%d(+1)", i, j, ll); + int lastauxt_lead = model.eqs.add_nulary(name); + // create AUXLD_*_*{ll+1} + sprintf(name, "AUXLD_%d_%d_%d", i, j, ll+1); + model.atoms.register_uniq_endo(name); + info.num_aux_variables++; + 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)); + // add substitution to the map; todo: this + // works well because in the context where + // aux_map is used the timing doesn't matter, + // however, it is misleading, needs to be + // changed + aux_map.insert(Tsubstmap::value_type(ss, lagt)); + } + + // now we have to substitute AUXLD_*_*{mlead-1}(+1) for t + sprintf(name, "AUXLD_%d_%d_%d", i, j, mlead-1); + ss = model.atoms.get_name_storage().query(name); + model.substitute_atom_for_term(ss, +1, t); + } +} + +void +ForwSubstBuilder::unassign_gt_1_leads(const char *name) +{ + const char *ss = model.atoms.get_name_storage().query(name); + int mlead, mlag; + model.atoms.varspan(name, mlead, mlag); + for (int ll = 2; ll <= mlead; ll++) + { + int t = model.atoms.index(ss, ll); + if (t != -1) + model.atoms.unassign_variable(ss, ll, t); + } +} + +void +ForwSubstBuilder::unassign_gt_1_leads() +{ + const vector<const char *> &endovars = model.atoms.get_endovars(); + for (unsigned int i = 0; i < endovars.size(); i++) + unassign_gt_1_leads(endovars[i]); + const vector<const char *> &exovars = model.atoms.get_exovars(); + for (unsigned int i = 0; i < exovars.size(); i++) + unassign_gt_1_leads(exovars[i]); +} + +ForwSubstBuilder::ForwSubstBuilder(const ForwSubstBuilder &b, DynareModel &m) + : model(m) +{ + for (Tsubstmap::const_iterator it = b.aux_map.begin(); + it != b.aux_map.end(); ++it) + { + const char *ss = m.atoms.get_name_storage().query((*it).first); + aux_map.insert(Tsubstmap::value_type(ss, (*it).second)); + } +} diff --git a/dynare++/src/forw_subst_builder.cpp b/dynare++/src/forw_subst_builder.cpp deleted file mode 100644 index e2fa6cf55838c502afdcc17a3ce0e8c03b4cb8ae..0000000000000000000000000000000000000000 --- a/dynare++/src/forw_subst_builder.cpp +++ /dev/null @@ -1,125 +0,0 @@ -// Copyright (C) 2006-2011, Ondra Kamenik - - -#include "forw_subst_builder.h" - -using namespace ogdyn; - -ForwSubstBuilder::ForwSubstBuilder(DynareModel& m) - : model(m) -{ - info.num_new_terms -= model.getParser().getTree().get_num_op(); - - // go through all equations - int neq = model.eqs.nformulas(); - for (int i = 0; i < neq; i++) { - int ft = model.eqs.formula(i); - int mlead, mlag; - model.termspan(ft, mlead, mlag); - // if equation is too forward looking - if (mlead > 1) { - info.num_affected_equations++; - // break it to non-linear terms - unordered_set<int> nlt = model.get_nonlinear_subterms(ft); - int j = 0; // indexes subterms - // and make substitutions for all these non-linear subterms - for (unordered_set<int>::const_iterator it = nlt.begin(); - it != nlt.end(); ++it, ++j) - substitute_for_term(*it, i, j); - } - } - // unassign all variables with lead greater than 1 - unassign_gt_1_leads(); - - // forget the derivatives in the tree because some variables could - // have been unassigned - model.eqs.getTree().forget_derivative_maps(); - - info.num_new_terms += model.getParser().getTree().get_num_op(); -} - -void ForwSubstBuilder::substitute_for_term(int t, int i, int j) -{ - int mlead, mlag; - model.termspan(t, mlead, mlag); - if (mlead > 1) { - info.num_subst_terms++; - // Example for comments: let t = f(x(+4)) - // first make lagsubst be substitution setting f(x(+4)) to f(x(+1)) - // this is lag = -3 (1-mlead) - map<int,int> lagsubst; - unordered_set<int> nult = model.eqs.nulary_of_term(t);// make copy of nult! - model.variable_shift_map(nult, 1-mlead, lagsubst); - int lagt = model.eqs.add_substitution(t, lagsubst); - - // now maxlead of lagt is +1 - // add AUXLD_*_*_1 = f(x(+1)) to the model - char name[100]; - sprintf(name, "AUXLD_%d_%d_%d", i, j, 1); - model.atoms.register_uniq_endo(name); - 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)); - aux_map.insert(Tsubstmap::value_type(ss, lagt)); - // now add variables and equations - // AUXLD_*_*_2 = AUXLD_*_*_1(+1) through - // AUXLD_*_*_{mlead-1} = AUXLD_*_*_{mlead-2}(+1) - for (int ll = 1; ll <= mlead-2; ll++) { - // create AUXLD_*_*_{ll}(+1) - sprintf(name, "AUXLD_%d_%d_%d(+1)", i, j, ll); - int lastauxt_lead = model.eqs.add_nulary(name); - // create AUXLD_*_*{ll+1} - sprintf(name, "AUXLD_%d_%d_%d", i, j, ll+1); - model.atoms.register_uniq_endo(name); - info.num_aux_variables++; - 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)); - // add substitution to the map; todo: this - // works well because in the context where - // aux_map is used the timing doesn't matter, - // however, it is misleading, needs to be - // changed - aux_map.insert(Tsubstmap::value_type(ss, lagt)); - } - - // now we have to substitute AUXLD_*_*{mlead-1}(+1) for t - sprintf(name, "AUXLD_%d_%d_%d", i, j, mlead-1); - ss = model.atoms.get_name_storage().query(name); - model.substitute_atom_for_term(ss, +1, t); - } -} - -void ForwSubstBuilder::unassign_gt_1_leads(const char* name) -{ - const char* ss = model.atoms.get_name_storage().query(name); - int mlead, mlag; - model.atoms.varspan(name, mlead, mlag); - for (int ll = 2; ll <= mlead; ll++) { - int t = model.atoms.index(ss, ll); - if (t != -1) - model.atoms.unassign_variable(ss, ll, t); - } -} - -void ForwSubstBuilder::unassign_gt_1_leads() -{ - const vector<const char*>& endovars = model.atoms.get_endovars(); - for (unsigned int i = 0; i < endovars.size(); i++) - unassign_gt_1_leads(endovars[i]); - const vector<const char*>& exovars = model.atoms.get_exovars(); - for (unsigned int i = 0; i < exovars.size(); i++) - unassign_gt_1_leads(exovars[i]); -} - -ForwSubstBuilder::ForwSubstBuilder(const ForwSubstBuilder& b, DynareModel& m) - : model(m) -{ - for (Tsubstmap::const_iterator it = b.aux_map.begin(); - it != b.aux_map.end(); ++it) { - const char* ss = m.atoms.get_name_storage().query((*it).first); - aux_map.insert(Tsubstmap::value_type(ss, (*it).second)); - } -} diff --git a/dynare++/src/forw_subst_builder.h b/dynare++/src/forw_subst_builder.hh similarity index 99% rename from dynare++/src/forw_subst_builder.h rename to dynare++/src/forw_subst_builder.hh index 9a51c2cbce1f114aac6ea756ea670dec2c58e091..3b920748f477ca1847df819fa8467f0c1dd12caf 100644 --- a/dynare++/src/forw_subst_builder.h +++ b/dynare++/src/forw_subst_builder.hh @@ -5,7 +5,7 @@ #ifndef FORW_SUBST_BUILDER_H #define FORW_SUBST_BUILDER_H -#include "dynare_model.h" +#include "dynare_model.hh" namespace ogdyn { diff --git a/dynare++/src/main.cc b/dynare++/src/main.cc new file mode 100644 index 0000000000000000000000000000000000000000..9169a998d0d2bd1a1f392ecba3dbd624291514a7 --- /dev/null +++ b/dynare++/src/main.cc @@ -0,0 +1,214 @@ +// Copyright (C) 2004-2011, Ondra Kamenik + +#include "dynare3.hh" +#include "dynare_exception.hh" +#include "dynare_params.hh" + +#include "utils/cc/exception.hh" +#include "parser/cc/parser_exception.hh" +#include "../sylv/cc/SylvException.hh" +#include "../kord/random.hh" +#include "../kord/global_check.hh" +#include "../kord/approximation.hh" + +int +main(int argc, char **argv) +{ + DynareParams params(argc, argv); + if (params.help) + { + params.printHelp(); + return 0; + } + if (params.version) + { + printf("Dynare++ v. %s. Copyright (C) 2004-2011, Ondra Kamenik\n", + DYNVERSION); + printf("Dynare++ comes with ABSOLUTELY NO WARRANTY and is distributed under\n"); + printf("GPL: modules integ, tl, kord, sylv, src, extern and documentation\n"); + printf("LGPL: modules parser, utils\n"); + printf(" for GPL see http://www.gnu.org/licenses/gpl.html\n"); + printf(" for LGPL see http://www.gnu.org/licenses/lgpl.html\n"); + return 0; + } + THREAD_GROUP::max_parallel_threads = params.num_threads; + + try + { + // make journal name and journal + std::string jname(params.basename); + jname += ".jnl"; + Journal journal(jname.c_str()); + + // make dynare object + Dynare dynare(params.modname, params.order, params.ss_tol, journal); + // make list of shocks for which we will do IRFs + vector<int> irf_list_ind; + if (params.do_irfs_all) + for (int i = 0; i < dynare.nexog(); i++) + irf_list_ind.push_back(i); + else + 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 (NULL == (mfd = fopen(mfile1.c_str(), "w"))) + { + 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); + + std::string mfile2(params.basename); + mfile2 += "_ff.m"; + if (NULL == (mfd = fopen(mfile2.c_str(), "w"))) + { + 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); + + // open mat file + std::string matfile(params.basename); + matfile += ".mat"; + mat_t *matfd = Mat_Create(matfile.c_str(), NULL); + if (matfd == NULL) + { + fprintf(stderr, "Couldn't open %s for writing.\n", matfile.c_str()); + exit(1); + } + + // write info about the model (dimensions and variables) + dynare.writeMat(matfd, params.prefix); + // write the dump file corresponding to the input + dynare.writeDump(params.basename); + + system_random_generator.initSeed(params.seed); + + tls.init(dynare.order(), + dynare.nstat()+2*dynare.npred()+3*dynare.nboth() + +2*dynare.nforw()+dynare.nexog()); + + Approximation app(dynare, journal, params.num_steps, params.do_centralize, params.qz_criterium); + try + { + app.walkStochSteady(); + } + catch (const KordException &e) + { + // tell about the exception and continue + printf("Caught (not yet fatal) Kord exception: "); + e.print(); + JournalRecord rec(journal); + rec << "Solution routine not finished (" << e.get_message() + << "), see what happens" << endrec; + } + + std::string ss_matrix_name(params.prefix); + ss_matrix_name += "_steady_states"; + ConstTwoDMatrix(app.getSS()).writeMat(matfd, ss_matrix_name.c_str()); + + // check the approximation + if (params.check_along_path || params.check_along_shocks + || params.check_on_ellipse) + { + GlobalChecker gcheck(app, THREAD_GROUP::max_parallel_threads, journal); + if (params.check_along_shocks) + gcheck.checkAlongShocksAndSave(matfd, params.prefix, + params.getCheckShockPoints(), + params.getCheckShockScale(), + params.check_evals); + if (params.check_on_ellipse) + gcheck.checkOnEllipseAndSave(matfd, params.prefix, + params.getCheckEllipsePoints(), + params.getCheckEllipseScale(), + params.check_evals); + if (params.check_along_path) + gcheck.checkAlongSimulationAndSave(matfd, params.prefix, + params.getCheckPathPoints(), + params.check_evals); + } + + // write the folded decision rule to the Mat-4 file + app.getFoldDecisionRule().writeMat(matfd, params.prefix); + + // simulate conditional + if (params.num_condper > 0 && params.num_condsim > 0) + { + SimResultsDynamicStats rescond(dynare.numeq(), params.num_condper, 0); + ConstVector det_ss(app.getSS(), 0); + rescond.simulate(params.num_condsim, app.getFoldDecisionRule(), det_ss, dynare.getVcov(), journal); + rescond.writeMat(matfd, params.prefix); + } + + // simulate unconditional + //const DecisionRule& dr = app.getUnfoldDecisionRule(); + const DecisionRule &dr = app.getFoldDecisionRule(); + if (params.num_per > 0 && params.num_sim > 0) + { + SimResultsStats res(dynare.numeq(), params.num_per, params.num_burn); + res.simulate(params.num_sim, dr, dynare.getSteady(), dynare.getVcov(), journal); + res.writeMat(matfd, params.prefix); + + // impulse response functions + if (!irf_list_ind.empty()) + { + IRFResults irf(dynare, dr, res, irf_list_ind, journal); + irf.writeMat(matfd, params.prefix); + } + } + + // simulate with real-time statistics + if (params.num_rtper > 0 && params.num_rtsim > 0) + { + RTSimResultsStats rtres(dynare.numeq(), params.num_rtper, params.num_burn); + rtres.simulate(params.num_rtsim, dr, dynare.getSteady(), dynare.getVcov(), journal); + rtres.writeMat(matfd, params.prefix); + } + + Mat_Close(matfd); + + } + catch (const KordException &e) + { + printf("Caugth Kord exception: "); + e.print(); + return e.code(); + } + catch (const TLException &e) + { + printf("Caugth TL exception: "); + e.print(); + return 255; + } + catch (SylvException &e) + { + printf("Caught Sylv exception: "); + e.printMessage(); + return 255; + } + catch (const DynareException &e) + { + printf("Caught Dynare exception: %s\n", e.message()); + return 255; + } + catch (const ogu::Exception &e) + { + printf("Caught ogu::Exception: "); + e.print(); + return 255; + } + catch (const ogp::ParserException &e) + { + printf("Caught parser exception: %s\n", e.message()); + return 255; + } + + return 0; +} diff --git a/dynare++/src/main.cpp b/dynare++/src/main.cpp deleted file mode 100644 index 665ab468d9aa614e1a5eb17b8cc094b3515e1192..0000000000000000000000000000000000000000 --- a/dynare++/src/main.cpp +++ /dev/null @@ -1,188 +0,0 @@ -// Copyright (C) 2004-2011, Ondra Kamenik - -#include "dynare3.h" -#include "dynare_exception.h" -#include "dynare_params.h" - -#include "utils/cc/exception.h" -#include "parser/cc/parser_exception.h" -#include "../sylv/cc/SylvException.h" -#include "../kord/random.hh" -#include "../kord/global_check.hh" -#include "../kord/approximation.hh" - -int main(int argc, char** argv) -{ - DynareParams params(argc, argv); - if (params.help) { - params.printHelp(); - return 0; - } - if (params.version) { - printf("Dynare++ v. %s. Copyright (C) 2004-2011, Ondra Kamenik\n", - DYNVERSION); - printf("Dynare++ comes with ABSOLUTELY NO WARRANTY and is distributed under\n"); - printf("GPL: modules integ, tl, kord, sylv, src, extern and documentation\n"); - printf("LGPL: modules parser, utils\n"); - printf(" for GPL see http://www.gnu.org/licenses/gpl.html\n"); - printf(" for LGPL see http://www.gnu.org/licenses/lgpl.html\n"); - return 0; - } - THREAD_GROUP::max_parallel_threads = params.num_threads; - - try { - // make journal name and journal - std::string jname(params.basename); - jname += ".jnl"; - Journal journal(jname.c_str()); - - // make dynare object - Dynare dynare(params.modname, params.order, params.ss_tol, journal); - // make list of shocks for which we will do IRFs - vector<int> irf_list_ind; - if (params.do_irfs_all) - for (int i = 0; i < dynare.nexog(); i++) - irf_list_ind.push_back(i); - else - 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 (NULL == (mfd=fopen(mfile1.c_str(), "w"))) { - 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); - - std::string mfile2(params.basename); - mfile2 += "_ff.m"; - if (NULL == (mfd=fopen(mfile2.c_str(), "w"))) { - 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); - - // open mat file - std::string matfile(params.basename); - matfile += ".mat"; - mat_t* matfd = Mat_Create(matfile.c_str(), NULL); - if (matfd == NULL) { - fprintf(stderr, "Couldn't open %s for writing.\n", matfile.c_str()); - exit(1); - } - - // write info about the model (dimensions and variables) - dynare.writeMat(matfd, params.prefix); - // write the dump file corresponding to the input - dynare.writeDump(params.basename); - - - system_random_generator.initSeed(params.seed); - - tls.init(dynare.order(), - dynare.nstat()+2*dynare.npred()+3*dynare.nboth()+ - 2*dynare.nforw()+dynare.nexog()); - - Approximation app(dynare, journal, params.num_steps, params.do_centralize, params.qz_criterium); - try { - app.walkStochSteady(); - } catch (const KordException& e) { - // tell about the exception and continue - printf("Caught (not yet fatal) Kord exception: "); - e.print(); - JournalRecord rec(journal); - rec << "Solution routine not finished (" << e.get_message() - << "), see what happens" << endrec; - } - - std::string ss_matrix_name(params.prefix); - ss_matrix_name += "_steady_states"; - ConstTwoDMatrix(app.getSS()).writeMat(matfd, ss_matrix_name.c_str()); - - // check the approximation - if (params.check_along_path || params.check_along_shocks - || params.check_on_ellipse) { - GlobalChecker gcheck(app, THREAD_GROUP::max_parallel_threads, journal); - if (params.check_along_shocks) - gcheck.checkAlongShocksAndSave(matfd, params.prefix, - params.getCheckShockPoints(), - params.getCheckShockScale(), - params.check_evals); - if (params.check_on_ellipse) - gcheck.checkOnEllipseAndSave(matfd, params.prefix, - params.getCheckEllipsePoints(), - params.getCheckEllipseScale(), - params.check_evals); - if (params.check_along_path) - gcheck.checkAlongSimulationAndSave(matfd, params.prefix, - params.getCheckPathPoints(), - params.check_evals); - } - - // write the folded decision rule to the Mat-4 file - app.getFoldDecisionRule().writeMat(matfd, params.prefix); - - // simulate conditional - if (params.num_condper > 0 && params.num_condsim > 0) { - SimResultsDynamicStats rescond(dynare.numeq(), params.num_condper, 0); - ConstVector det_ss(app.getSS(),0); - rescond.simulate(params.num_condsim, app.getFoldDecisionRule(), det_ss, dynare.getVcov(), journal); - rescond.writeMat(matfd, params.prefix); - } - - // simulate unconditional - //const DecisionRule& dr = app.getUnfoldDecisionRule(); - const DecisionRule& dr = app.getFoldDecisionRule(); - if (params.num_per > 0 && params.num_sim > 0) { - SimResultsStats res(dynare.numeq(), params.num_per, params.num_burn); - res.simulate(params.num_sim, dr, dynare.getSteady(), dynare.getVcov(), journal); - res.writeMat(matfd, params.prefix); - - // impulse response functions - if (! irf_list_ind.empty()) { - IRFResults irf(dynare, dr, res, irf_list_ind, journal); - irf.writeMat(matfd, params.prefix); - } - } - - // simulate with real-time statistics - if (params.num_rtper > 0 && params.num_rtsim > 0) { - RTSimResultsStats rtres(dynare.numeq(), params.num_rtper, params.num_burn); - rtres.simulate(params.num_rtsim, dr, dynare.getSteady(), dynare.getVcov(), journal); - rtres.writeMat(matfd, params.prefix); - } - - Mat_Close(matfd); - - } catch (const KordException& e) { - printf("Caugth Kord exception: "); - e.print(); - return e.code(); - } catch (const TLException& e) { - printf("Caugth TL exception: "); - e.print(); - return 255; - } catch (SylvException& e) { - printf("Caught Sylv exception: "); - e.printMessage(); - return 255; - } catch (const DynareException& e) { - printf("Caught Dynare exception: %s\n", e.message()); - return 255; - } catch (const ogu::Exception& e) { - printf("Caught ogu::Exception: "); - e.print(); - return 255; - } catch (const ogp::ParserException& e) { - printf("Caught parser exception: %s\n", e.message()); - return 255; - } - - return 0; -} diff --git a/dynare++/src/nlsolve.cc b/dynare++/src/nlsolve.cc new file mode 100644 index 0000000000000000000000000000000000000000..8b5419ca2f6ecf45c577a7ff08bdd9b878edfb2f --- /dev/null +++ b/dynare++/src/nlsolve.cc @@ -0,0 +1,265 @@ +// Copyright (C) 2006, Ondra Kamenik + +// $Id: nlsolve.cpp 762 2006-05-22 13:00:07Z kamenik $ + +#include "nlsolve.hh" +#include "dynare_exception.hh" + +#include <cmath> + +using namespace ogu; + +/** This should not be greater than DBL_EPSILON^(1/2). */ +double GoldenSectionSearch::tol = 1.e-4; + +/** This is equal to the golden section ratio. */ +double GoldenSectionSearch::golden = (3.-std::sqrt(5.))/2; + +double +GoldenSectionSearch::search(OneDFunction &f, double x1, double x2) +{ + double b; + if (init_bracket(f, x1, x2, b)) + { + double fb = f.eval(b); + double f1 = f.eval(x1); + f.eval(x2); + double dx; + do + { + double w = (b-x1)/(x2-x1); + dx = std::abs((1-2*w)*(x2-x1)); + double x; + if (b-x1 > x2-b) + x = b - dx; + else + x = b + dx; + double fx = f.eval(x); + if (!std::isfinite(fx)) + return x1; + if (b-x1 > x2-b) + { + // x is on the left from b + if (f1 > fx && fx < fb) + { + // pickup bracket [f1,fx,fb] + x2 = b; + fb = fx; + b = x; + } + else + { + // pickup bracket [fx,fb,fx2] + f1 = fx; + x1 = x; + } + } + else + { + // x is on the right from b + if (f1 > fb && fb < fx) + { + // pickup bracket [f1,fb,fx] + x2 = x; + } + else + { + // pickup bracket [fb,fx,f2] + f1 = fb; + x1 = b; + fb = fx; + b = x; + } + } + } + while (dx > tol); + } + return b; +} + +bool +GoldenSectionSearch::init_bracket(OneDFunction &f, double x1, double &x2, double &b) +{ + double f1 = f.eval(x1); + if (!std::isfinite(f1)) + throw DynareException(__FILE__, __LINE__, + "Safer point not finite in GoldenSectionSearch::init_bracket"); + + int cnt = 0; + bool bracket_found = false; + do + { + bool finite_found = search_for_finite(f, x1, x2, b); + if (!finite_found) + { + b = x1; + return false; + } + double f2 = f.eval(x2); + double fb = f.eval(b); + double bsym = 2*x2 - b; + double fbsym = f.eval(bsym); + // now we know that f1, f2, and fb are finite + if (std::isfinite(fbsym)) + { + // we have four numbers f1, fb, f2, fbsym, we test for the + // following combinations to find the bracket: + // [f1,f2,fbsym], [f1,fb,fbsym] and [f1,fb,fbsym] + if (f1 > f2 && f2 < fbsym) + { + bracket_found = true; + b = x2; + x2 = bsym; + } + else if (f1 > fb && fb < fbsym) + { + bracket_found = true; + x2 = bsym; + } + else if (f1 > fb && fb < f2) + { + bracket_found = true; + } + else + { + double newx2 = b; + // choose the smallest value in case we end + if (f1 > fbsym) + { + // the smallest value is on the other end, we do + // not want to continue + b = bsym; + return false; + } + else + b = x1; + // move x2 to b in case we continue + x2 = newx2; + } + } + else + { + // we have only three numbers, we test for the bracket, + // and if not found, we set b as potential result and + // shorten x2 as potential init value for next cycle + if (f1 > fb && fb < f2) + bracket_found = true; + else + { + double newx2 = b; + // choose the smaller value in case we end + if (f1 > f2) + b = x2; + else + b = x1; + // move x2 to b in case we continue + x2 = newx2; + } + } + cnt++; + } + while (!bracket_found && cnt < 5); + + return bracket_found; +} + +/** This moves x2 toward to x1 until the function at x2 is finite and + * b as a golden section between x1 and x2 yields also finite f. */ +bool +GoldenSectionSearch::search_for_finite(OneDFunction &f, double x1, double &x2, double &b) +{ + int cnt = 0; + bool found = false; + do + { + double f2 = f.eval(x2); + b = (1-golden)*x1 + golden*x2; + double fb = f.eval(b); + found = std::isfinite(f2) && std::isfinite(fb); + if (!found) + x2 = b; + cnt++; + } + while (!found && cnt < 5); + + return found; +} + +void +VectorFunction::check_for_eval(const ConstVector &in, Vector &out) const +{ + if (inDim() != in.length() || outDim() != out.length()) + throw DynareException(__FILE__, __LINE__, + "Wrong dimensions in VectorFunction::check_for_eval"); +} + +double +NLSolver::eval(double lambda) +{ + Vector xx((const Vector &)x); + xx.add(1-lambda, xcauchy); + xx.add(lambda, xnewton); + Vector ff(func.outDim()); + func.eval(xx, ff); + return ff.dot(ff); +} + +bool +NLSolver::solve(Vector &xx, int &iter) +{ + JournalRecord rec(journal); + rec << "Iter lambda residual" << endrec; + JournalRecord rec1(journal); + rec1 << "---------------------------" << endrec; + char tmpbuf[14]; + + x = (const Vector &) xx; + iter = 0; + // setup fx + Vector fx(func.outDim()); + func.eval(x, fx); + if (!fx.isFinite()) + throw DynareException(__FILE__, __LINE__, + "Initial guess does not yield finite residual in NLSolver::solve"); + bool converged = fx.getMax() < tol; + JournalRecord rec2(journal); + sprintf(tmpbuf, "%10.6g", fx.getMax()); + rec2 << iter << " N/A " << tmpbuf << endrec; + while (!converged && iter < max_iter) + { + // setup Jacobian + jacob.eval(x); + // calculate cauchy step + Vector g(func.inDim()); + g.zeros(); + ConstTwoDMatrix(jacob).multaVecTrans(g, fx); + Vector Jg(func.inDim()); + Jg.zeros(); + ConstTwoDMatrix(jacob).multaVec(Jg, g); + double m = -g.dot(g)/Jg.dot(Jg); + xcauchy = (const Vector &) g; + xcauchy.mult(m); + // calculate newton step + xnewton = (const Vector &) fx; + ConstTwoDMatrix(jacob).multInvLeft(xnewton); + xnewton.mult(-1); + + // line search + double lambda = GoldenSectionSearch::search(*this, 0, 1); + x.add(1-lambda, xcauchy); + x.add(lambda, xnewton); + // evaluate func + func.eval(x, fx); + converged = fx.getMax() < tol; + + // iter + iter++; + + JournalRecord rec3(journal); + sprintf(tmpbuf, "%10.6g", fx.getMax()); + rec3 << iter << " " << lambda << " " << tmpbuf << endrec; + } + xx = (const Vector &) x; + + return converged; +} diff --git a/dynare++/src/nlsolve.cpp b/dynare++/src/nlsolve.cpp deleted file mode 100644 index 1210176b3f6d8a853e198976754f1c66ba057e51..0000000000000000000000000000000000000000 --- a/dynare++/src/nlsolve.cpp +++ /dev/null @@ -1,228 +0,0 @@ -// Copyright (C) 2006, Ondra Kamenik - -// $Id: nlsolve.cpp 762 2006-05-22 13:00:07Z kamenik $ - -#include "nlsolve.h" -#include "dynare_exception.h" - -#include <cmath> - -using namespace ogu; - -/** This should not be greater than DBL_EPSILON^(1/2). */ -double GoldenSectionSearch::tol = 1.e-4; - -/** This is equal to the golden section ratio. */ -double GoldenSectionSearch::golden = (3.-std::sqrt(5.))/2; - -double GoldenSectionSearch::search(OneDFunction& f, double x1, double x2) -{ - double b; - if (init_bracket(f, x1, x2, b)) { - double fb = f.eval(b); - double f1 = f.eval(x1); - f.eval(x2); - double dx; - do { - double w = (b-x1)/(x2-x1); - dx = std::abs((1-2*w)*(x2-x1)); - double x; - if (b-x1 > x2-b) - x = b - dx; - else - x = b + dx; - double fx = f.eval(x); - if (! std::isfinite(fx)) - return x1; - if (b-x1 > x2-b) { - // x is on the left from b - if (f1 > fx && fx < fb) { - // pickup bracket [f1,fx,fb] - x2 = b; - fb = fx; - b = x; - } else { - // pickup bracket [fx,fb,fx2] - f1 = fx; - x1 = x; - } - } else { - // x is on the right from b - if (f1 > fb && fb < fx) { - // pickup bracket [f1,fb,fx] - x2 = x; - } else { - // pickup bracket [fb,fx,f2] - f1 = fb; - x1 = b; - fb = fx; - b = x; - } - } - } while(dx > tol); - } - return b; -} - -bool GoldenSectionSearch::init_bracket(OneDFunction& f, double x1, double& x2, double& b) -{ - double f1 = f.eval(x1); - if (! std::isfinite(f1)) - throw DynareException(__FILE__, __LINE__, - "Safer point not finite in GoldenSectionSearch::init_bracket"); - - int cnt = 0; - bool bracket_found = false; - do { - bool finite_found = search_for_finite(f, x1, x2, b); - if (! finite_found) { - b = x1; - return false; - } - double f2 = f.eval(x2); - double fb = f.eval(b); - double bsym = 2*x2 - b; - double fbsym = f.eval(bsym); - // now we know that f1, f2, and fb are finite - if (std::isfinite(fbsym)) { - // we have four numbers f1, fb, f2, fbsym, we test for the - // following combinations to find the bracket: - // [f1,f2,fbsym], [f1,fb,fbsym] and [f1,fb,fbsym] - if (f1 > f2 && f2 < fbsym) { - bracket_found = true; - b = x2; - x2 = bsym; - } else if (f1 > fb && fb < fbsym) { - bracket_found = true; - x2 = bsym; - } else if (f1 > fb && fb < f2) { - bracket_found = true; - } else { - double newx2 = b; - // choose the smallest value in case we end - if (f1 > fbsym) { - // the smallest value is on the other end, we do - // not want to continue - b = bsym; - return false; - } else - b = x1; - // move x2 to b in case we continue - x2 = newx2; - } - } else { - // we have only three numbers, we test for the bracket, - // and if not found, we set b as potential result and - // shorten x2 as potential init value for next cycle - if (f1 > fb && fb < f2) - bracket_found = true; - else { - double newx2 = b; - // choose the smaller value in case we end - if (f1 > f2) - b = x2; - else - b = x1; - // move x2 to b in case we continue - x2 = newx2; - } - } - cnt++; - } while (! bracket_found && cnt < 5); - - return bracket_found; -} - -/** This moves x2 toward to x1 until the function at x2 is finite and - * b as a golden section between x1 and x2 yields also finite f. */ -bool GoldenSectionSearch::search_for_finite(OneDFunction& f, double x1, double& x2, double&b) -{ - int cnt = 0; - bool found = false; - do { - double f2 = f.eval(x2); - b = (1-golden)*x1 + golden*x2; - double fb = f.eval(b); - found = std::isfinite(f2) && std::isfinite(fb); - if (! found) - x2 = b; - cnt++; - } while (! found && cnt < 5); - - return found; -} - -void VectorFunction::check_for_eval(const ConstVector& in, Vector& out) const -{ - if (inDim() != in.length() || outDim() != out.length()) - throw DynareException(__FILE__, __LINE__, - "Wrong dimensions in VectorFunction::check_for_eval"); -} - -double NLSolver::eval(double lambda) -{ - Vector xx((const Vector&)x); - xx.add(1-lambda, xcauchy); - xx.add(lambda, xnewton); - Vector ff(func.outDim()); - func.eval(xx, ff); - return ff.dot(ff); -} - -bool NLSolver::solve(Vector& xx, int& iter) -{ - JournalRecord rec(journal); - rec << "Iter lambda residual" << endrec; - JournalRecord rec1(journal); - rec1 << "---------------------------" << endrec; - char tmpbuf[14]; - - x = (const Vector&)xx; - iter = 0; - // setup fx - Vector fx(func.outDim()); - func.eval(x, fx); - if (!fx.isFinite()) - throw DynareException(__FILE__,__LINE__, - "Initial guess does not yield finite residual in NLSolver::solve"); - bool converged = fx.getMax() < tol; - JournalRecord rec2(journal); - sprintf(tmpbuf, "%10.6g", fx.getMax()); - rec2 << iter << " N/A " << tmpbuf << endrec; - while (! converged && iter < max_iter) { - // setup Jacobian - jacob.eval(x); - // calculate cauchy step - Vector g(func.inDim()); - g.zeros(); - ConstTwoDMatrix(jacob).multaVecTrans(g, fx); - Vector Jg(func.inDim()); - Jg.zeros(); - ConstTwoDMatrix(jacob).multaVec(Jg, g); - double m = -g.dot(g)/Jg.dot(Jg); - xcauchy = (const Vector&) g; - xcauchy.mult(m); - // calculate newton step - xnewton = (const Vector&) fx; - ConstTwoDMatrix(jacob).multInvLeft(xnewton); - xnewton.mult(-1); - - // line search - double lambda = GoldenSectionSearch::search(*this, 0, 1); - x.add(1-lambda, xcauchy); - x.add(lambda, xnewton); - // evaluate func - func.eval(x, fx); - converged = fx.getMax() < tol; - - // iter - iter++; - - JournalRecord rec3(journal); - sprintf(tmpbuf, "%10.6g", fx.getMax()); - rec3 << iter << " " << lambda << " " << tmpbuf << endrec; - } - xx = (const Vector&)x; - - return converged; -} diff --git a/dynare++/src/nlsolve.h b/dynare++/src/nlsolve.hh similarity index 100% rename from dynare++/src/nlsolve.h rename to dynare++/src/nlsolve.hh diff --git a/dynare++/src/planner_builder.cc b/dynare++/src/planner_builder.cc new file mode 100644 index 0000000000000000000000000000000000000000..b3d4035259b9502f13ae40ca8d46742a539b8e69 --- /dev/null +++ b/dynare++/src/planner_builder.cc @@ -0,0 +1,419 @@ +// Copyright (C) 2006, Ondra Kamenik + +// $Id$ + +#include "planner_builder.hh" +#include "dynare_exception.hh" + +#include <cmath> + +using namespace ogdyn; + +const IntegerMatrix & +IntegerMatrix::operator=(const IntegerMatrix &im) +{ + if (nr != im.nr || nc != im.nc) + throw DynareException(__FILE__, __LINE__, + "Matrices have different dimensions in IntegerMatrix::operator="); + memcpy(data, im.data, nr*nc*sizeof(int)); + return *this; +} + +const IntegerArray3 & +IntegerArray3::operator=(const IntegerArray3 &ia3) +{ + if (n1 != ia3.n1 || n2 != ia3.n2 || n3 != ia3.n3) + throw DynareException(__FILE__, __LINE__, + "Arrays have different dimensions in IntegerArray3::operator="); + memcpy(data, ia3.data, n1*n2*n3*sizeof(int)); + return *this; +} + +PlannerBuilder::PlannerBuilder(DynareModel &m, const Tvarset &yyset, + const Teqset &ffset) + : yset(), fset(ffset), model(m), + tb(model.t_plobjective), tbeta(model.t_pldiscount), + maxlead(model.atoms.get_maxlead()), + minlag(model.atoms.get_minlag()), + diff_b(yyset.size(), 1-minlag), + diff_f(yyset.size(), fset.size(), 1+maxlead-minlag), + static_atoms(), + static_tree(), + diff_b_static(yyset.size(), 1-minlag), + diff_f_static(yyset.size(), fset.size(), 1+maxlead-minlag) +{ + info.num_new_terms -= model.getParser().getTree().get_num_op(); + + fill_yset(m.atoms.get_name_storage(), yyset); + + add_derivatives_of_b(); + add_derivatives_of_f(); + shift_derivatives_of_b(); + shift_derivatives_of_f(); + beta_multiply_b(); + beta_multiply_f(); + make_static_version(); + lagrange_mult_f(); + form_equations(); + + info.num_new_terms += model.getParser().getTree().get_num_op(); +} + +PlannerBuilder::PlannerBuilder(const PlannerBuilder &pb, ogdyn::DynareModel &m) + : yset(), fset(pb.fset), model(m), + tb(pb.tb), tbeta(pb.tbeta), + maxlead(pb.maxlead), minlag(pb.minlag), + diff_b(pb.diff_b), diff_f(pb.diff_f), + static_atoms(pb.static_atoms), + static_tree(pb.static_tree), + diff_b_static(pb.diff_b_static), + diff_f_static(pb.diff_f_static), + aux_map(), static_aux_map() + +{ + fill_yset(m.atoms.get_name_storage(), pb.yset); + fill_aux_map(m.atoms.get_name_storage(), pb.aux_map, pb.static_aux_map); +} + +void +PlannerBuilder::add_derivatives_of_b() +{ + int yi = 0; + for (Tvarset::const_iterator yname = yset.begin(); + yname != yset.end(); ++yname, yi++) + for (int ll = minlag; ll <= 0; ll++) + { + int yt = model.atoms.index(*yname, ll); + if (yt != -1) + diff_b(yi, ll-minlag) = model.eqs.add_derivative(tb, yt); + else + diff_b(yi, ll-minlag) = ogp::OperationTree::zero; + } +} + +void +PlannerBuilder::add_derivatives_of_f() +{ + int yi = 0; + for (Tvarset::const_iterator yname = yset.begin(); + yname != yset.end(); ++yname, yi++) + for (unsigned int fi = 0; fi < fset.size(); fi++) + for (int ll = minlag; ll <= maxlead; ll++) + { + int yt = model.atoms.index(*yname, ll); + if (yt != -1) + diff_f(yi, fi, ll-minlag) + = model.eqs.add_derivative(model.eqs.formula(fset[fi]), yt); + else + diff_f(yi, fi, ll-minlag) = ogp::OperationTree::zero; + } +} + +void +PlannerBuilder::shift_derivatives_of_b() +{ + map<int, int> subst; + for (int yi = 0; yi < diff_b.nrows(); yi++) + for (int ll = minlag; ll < 0; ll++) + if (diff_b(yi, ll-minlag) != ogp::OperationTree::zero) + { + model.variable_shift_map(model.eqs.nulary_of_term(diff_b(yi, ll-minlag)), + -ll, subst); + diff_b(yi, ll-minlag) = model.eqs.add_substitution(diff_b(yi, ll-minlag), subst); + } +} + +void +PlannerBuilder::shift_derivatives_of_f() +{ + map<int, int> subst; + for (int yi = 0; yi < diff_f.dim1(); yi++) + for (int fi = 0; fi < diff_f.dim2(); fi++) + { + // first do it leads which are put under expectation before t: no problem + for (int ll = 0; ll <= maxlead; ll++) + if (diff_f(yi, fi, ll-minlag) != ogp::OperationTree::zero) + { + model.variable_shift_map(model.eqs.nulary_of_term(diff_f(yi, fi, ll-minlag)), + -ll, subst); + diff_f(yi, fi, ll-minlag) + = model.eqs.add_substitution(diff_f(yi, fi, ll-minlag), subst); + } + // now do it for lags, these are put as leads under + // expectations after time t, so we have to introduce + // auxiliary variables at time t, and make leads of them here + for (int ll = minlag; ll < 0; ll++) + { + int ft = diff_f(yi, fi, ll-minlag); + if (ft != ogp::OperationTree::zero) + { + // if the ft term has a lead, than we need to + // introduce an auxiliary variable z_t, define it + // as E_t[ft] and put z_{t-ll} to the + // equation. Otherwise, we just put leaded ft to + // the equation directly. + int ft_maxlead, ft_minlag; + model.termspan(ft, ft_maxlead, ft_minlag); + if (ft_maxlead > 0) + { + // make an auxiliary variable + char name[100]; + sprintf(name, "AUX_%d_%d_%d", yi, fset[fi], -ll); + model.atoms.register_uniq_endo(name); + info.num_aux_variables++; + int taux = model.eqs.add_nulary(name); + sprintf(name, "AUX_%d_%d_%d(%d)", yi, fset[fi], -ll, -ll); + int taux_leaded = model.eqs.add_nulary(name); + // put aux_leaded to the equation + diff_f(yi, fi, ll-minlag) = taux_leaded; + // save auxiliary variable and the term + aux_map.insert(Tsubstmap::value_type(model.atoms.name(taux), ft)); + } + else + { + // no auxiliary variable is needed and the + // term ft can be leaded in place + model.variable_shift_map(model.eqs.nulary_of_term(ft), -ll, subst); + diff_f(yi, fi, ll-minlag) + = model.eqs.add_substitution(ft, subst); + } + } + } + } +} + +void +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)) + 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)); +} + +void +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)) + 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)); + + beta_pow = ogp::OperationTree::one; + for (int ll = 0; ll >= minlag; ll--, + beta_pow = model.eqs.add_binary(ogp::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)); +} + +void +PlannerBuilder::make_static_version() +{ + // map holding substitutions from dynamic to static + ogp::StaticFineAtoms::Tintintmap tmap; + + // fill static atoms with outer ordering + static_atoms.import_atoms(model.atoms, static_tree, tmap); + + // go through diff_b and fill diff_b_static + for (int ll = minlag; ll <= 0; ll++) + for (int yi = 0; yi < diff_b.nrows(); yi++) + diff_b_static(yi, ll-minlag) + = static_tree.add_substitution(diff_b(yi, ll-minlag), + tmap, model.eqs.getTree()); + + // go through diff_f and fill diff_f_static + for (int ll = minlag; ll <= maxlead; ll++) + for (int yi = 0; yi < diff_f.dim1(); yi++) + for (int fi = 0; fi < diff_f.dim2(); fi++) + diff_f_static(yi, fi, ll-minlag) + = static_tree.add_substitution(diff_f(yi, fi, ll-minlag), + tmap, model.eqs.getTree()); + + // go through aux_map and fill static_aux_map + for (Tsubstmap::const_iterator it = aux_map.begin(); + it != aux_map.end(); ++it) + { + int tstatic = static_tree.add_substitution((*it).second, tmap, model.eqs.getTree()); + const char *name = static_atoms.get_name_storage().query((*it).first); + static_aux_map.insert(Tsubstmap::value_type(name, tstatic)); + } +} + +void +PlannerBuilder::lagrange_mult_f() +{ + // register multipliers + char mult_name[100]; + for (int fi = 0; fi < diff_f.dim2(); fi++) + { + sprintf(mult_name, "MULT%d", fset[fi]); + model.atoms.register_uniq_endo(mult_name); + info.num_lagrange_mults++; + } + // multiply with the multipliers + for (int yi = 0; yi < diff_f.dim1(); yi++) + for (int fi = 0; fi < diff_f.dim2(); fi++) + for (int ll = minlag; ll <= maxlead; ll++) + if (diff_f(yi, fi, ll-minlag) != ogp::OperationTree::zero) + { + 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)); + } +} + +void +PlannerBuilder::form_equations() +{ + // add planner's FOCs + for (int yi = 0; yi < diff_f.dim1(); yi++) + { + 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)); + 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)); + model.eqs.add_formula(eq); + } + + // add equations for auxiliary variables + for (Tsubstmap::const_iterator it = aux_map.begin(); + 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)); + } +} + +void +PlannerBuilder::fill_yset(const ogp::NameStorage &ns, + const PlannerBuilder::Tvarset &yyset) +{ + for (Tvarset::const_iterator it = yyset.begin(); it != yyset.end(); ++it) + yset.insert(ns.query(*it)); +} + +void +PlannerBuilder::fill_aux_map(const ogp::NameStorage &ns, const Tsubstmap &aaux_map, + const Tsubstmap &astatic_aux_map) +{ + // fill aux_map + for (Tsubstmap::const_iterator it = aaux_map.begin(); + it != aaux_map.end(); ++it) + aux_map.insert(Tsubstmap::value_type(ns.query((*it).first), (*it).second)); + + // fill static_aux_map + for (Tsubstmap::const_iterator it = astatic_aux_map.begin(); + it != astatic_aux_map.end(); ++it) + static_aux_map.insert(Tsubstmap::value_type(static_atoms.get_name_storage().query((*it).first), + (*it).second)); +} + +MultInitSS::MultInitSS(const PlannerBuilder &pb, const Vector &pvals, Vector &yy) + : builder(pb), b(builder.diff_b_static.nrows()), + F(builder.diff_f_static.dim1(), builder.diff_f_static.dim2()) +{ + b.zeros(); + F.zeros(); + + // first evaluate substitutions (auxiliary variables) from the builder + ogdyn::DynareStaticSteadySubstitutions dss(builder.model.atoms, builder.static_atoms, + builder.static_tree, + builder.static_aux_map, pvals, yy); + + // gather all the terms from builder.diff_b_static and + // builder.diff_f_static to the vector, the ordering is important, + // since the index of this vector will have to be decoded to the + // position in b and F. + vector<int> terms; + for (int yi = 0; yi < builder.diff_b_static.nrows(); yi++) + for (int l = 0; l < builder.diff_b_static.ncols(); l++) + terms.push_back(builder.diff_b_static(yi, l)); + for (int yi = 0; yi < builder.diff_f_static.dim1(); yi++) + for (int fi = 0; fi < builder.diff_f_static.dim2(); fi++) + for (int l = 0; l < builder.diff_f_static.dim3(); l++) + terms.push_back(builder.diff_f_static(yi, fi, l)); + + // evaluate the terms, it will call a series of load(i,res), which + // sum the results through lags/leads to b and F + DynareStaticSteadyAtomValues dssav(builder.model.atoms, builder.static_atoms, pvals, yy); + ogp::FormulaCustomEvaluator fe(builder.static_tree, terms); + fe.eval(dssav, *this); + + // solve overdetermined system b+F*lambda=0 using SVD decomposition + SVDDecomp decomp(F); + Vector lambda(builder.diff_f_static.dim2()); + decomp.solve(b, lambda); + lambda.mult(-1); + + // take values of lambda and put it to yy + for (int fi = 0; fi < builder.diff_f_static.dim2(); fi++) + { + char mult_name[100]; + sprintf(mult_name, "MULT%d", builder.fset[fi]); + int iouter = builder.model.atoms.name2outer_endo(mult_name); + int iy = builder.model.atoms.outer2y_endo()[iouter]; + if (!std::isfinite(yy[iy])) + yy[iy] = lambda[fi]; + + // go through all substitutions of the multiplier and set them + // as well + if (builder.model.atom_substs) + { + const ogp::AtomSubstitutions::Toldnamemap &old2new + = builder.model.atom_substs->get_old2new(); + const ogp::AtomSubstitutions::Toldnamemap::const_iterator it + = old2new.find(mult_name); + if (it != old2new.end()) + { + const ogp::AtomSubstitutions::Tshiftnameset &sset = (*it).second; + for (ogp::AtomSubstitutions::Tshiftnameset::const_iterator itt = sset.begin(); + itt != sset.end(); ++itt) + { + const char *newname = (*itt).first; + int iouter = builder.model.atoms.name2outer_endo(newname); + int iy = builder.model.atoms.outer2y_endo()[iouter]; + if (!std::isfinite(yy[iy])) + yy[iy] = lambda[fi]; + } + } + } + } +} + +void +MultInitSS::load(int i, double res) +{ + // we can afford it, since the evaluator sets res to exact zero if + // the term is zero + if (res == 0) + return; + // decode i and add to either b or F + if (i < builder.diff_b_static.nrows()*builder.diff_b_static.ncols()) + { + // add to b + b[i / builder.diff_b_static.ncols()] += res; + } + else + { + // add to F + i -= builder.diff_b_static.nrows()*builder.diff_b_static.ncols(); + int yifi = i / builder.diff_f_static.dim3(); + int yi = yifi / builder.diff_f_static.dim2(); + int fi = yifi % builder.diff_f_static.dim2(); + F.get(yi, fi) += res; + } +} diff --git a/dynare++/src/planner_builder.cpp b/dynare++/src/planner_builder.cpp deleted file mode 100644 index 6958a8ab62d3f46b3e3733ff065f16ba09402519..0000000000000000000000000000000000000000 --- a/dynare++/src/planner_builder.cpp +++ /dev/null @@ -1,385 +0,0 @@ -// Copyright (C) 2006, Ondra Kamenik - -// $Id$ - -#include "planner_builder.h" -#include "dynare_exception.h" - -#include <cmath> - -using namespace ogdyn; - -const IntegerMatrix& IntegerMatrix::operator=(const IntegerMatrix& im) -{ - if (nr != im.nr || nc != im.nc) - throw DynareException(__FILE__,__LINE__, - "Matrices have different dimensions in IntegerMatrix::operator="); - memcpy(data, im.data, nr*nc*sizeof(int)); - return *this; -} - -const IntegerArray3& IntegerArray3::operator=(const IntegerArray3& ia3) -{ - if (n1 != ia3.n1 || n2 != ia3.n2 || n3 != ia3.n3) - throw DynareException(__FILE__,__LINE__, - "Arrays have different dimensions in IntegerArray3::operator="); - memcpy(data, ia3.data, n1*n2*n3*sizeof(int)); - return *this; -} - - -PlannerBuilder::PlannerBuilder(DynareModel& m, const Tvarset& yyset, - const Teqset& ffset) - : yset(), fset(ffset), model(m), - tb(model.t_plobjective), tbeta(model.t_pldiscount), - maxlead(model.atoms.get_maxlead()), - minlag(model.atoms.get_minlag()), - diff_b(yyset.size(), 1-minlag), - diff_f(yyset.size(), fset.size(), 1+maxlead-minlag), - static_atoms(), - static_tree(), - diff_b_static(yyset.size(), 1-minlag), - diff_f_static(yyset.size(), fset.size(), 1+maxlead-minlag) -{ - info.num_new_terms -= model.getParser().getTree().get_num_op(); - - fill_yset(m.atoms.get_name_storage(), yyset); - - add_derivatives_of_b(); - add_derivatives_of_f(); - shift_derivatives_of_b(); - shift_derivatives_of_f(); - beta_multiply_b(); - beta_multiply_f(); - make_static_version(); - lagrange_mult_f(); - form_equations(); - - info.num_new_terms += model.getParser().getTree().get_num_op(); -} - -PlannerBuilder::PlannerBuilder(const PlannerBuilder& pb, ogdyn::DynareModel& m) - : yset(), fset(pb.fset), model(m), - tb(pb.tb), tbeta(pb.tbeta), - maxlead(pb.maxlead), minlag(pb.minlag), - diff_b(pb.diff_b), diff_f(pb.diff_f), - static_atoms(pb.static_atoms), - static_tree(pb.static_tree), - diff_b_static(pb.diff_b_static), - diff_f_static(pb.diff_f_static), - aux_map(), static_aux_map() - -{ - fill_yset(m.atoms.get_name_storage(), pb.yset); - fill_aux_map(m.atoms.get_name_storage(), pb.aux_map, pb.static_aux_map); -} - -void PlannerBuilder::add_derivatives_of_b() -{ - int yi = 0; - for (Tvarset::const_iterator yname = yset.begin(); - yname != yset.end(); ++yname, yi++) - for (int ll = minlag; ll <= 0; ll++) { - int yt = model.atoms.index(*yname, ll); - if (yt != -1) - diff_b(yi, ll-minlag) = model.eqs.add_derivative(tb, yt); - else - diff_b(yi, ll-minlag) = ogp::OperationTree::zero; - } -} - -void PlannerBuilder::add_derivatives_of_f() -{ - int yi = 0; - for (Tvarset::const_iterator yname = yset.begin(); - yname != yset.end(); ++yname, yi++) - for (unsigned int fi = 0; fi < fset.size(); fi++) - for (int ll = minlag; ll <= maxlead; ll++) { - int yt = model.atoms.index(*yname, ll); - if (yt != -1) - diff_f(yi, fi, ll-minlag) = - model.eqs.add_derivative(model.eqs.formula(fset[fi]), yt); - else - diff_f(yi, fi, ll-minlag) = ogp::OperationTree::zero; - } -} - -void PlannerBuilder::shift_derivatives_of_b() -{ - map<int,int> subst; - for (int yi = 0; yi < diff_b.nrows(); yi++) - for (int ll = minlag; ll < 0; ll++) - if (diff_b(yi, ll-minlag) != ogp::OperationTree::zero) { - model.variable_shift_map(model.eqs.nulary_of_term(diff_b(yi, ll-minlag)), - -ll, subst); - diff_b(yi, ll-minlag) = model.eqs.add_substitution(diff_b(yi, ll-minlag), subst); - } -} - -void PlannerBuilder::shift_derivatives_of_f() -{ - map<int,int> subst; - for (int yi = 0; yi < diff_f.dim1(); yi++) - for (int fi = 0; fi < diff_f.dim2(); fi++) { - // first do it leads which are put under expectation before t: no problem - for (int ll = 0; ll <= maxlead; ll++) - if (diff_f(yi, fi, ll-minlag) != ogp::OperationTree::zero) { - model.variable_shift_map(model.eqs.nulary_of_term(diff_f(yi, fi, ll-minlag)), - -ll, subst); - diff_f(yi, fi, ll-minlag) = - model.eqs.add_substitution(diff_f(yi, fi, ll-minlag), subst); - } - // now do it for lags, these are put as leads under - // expectations after time t, so we have to introduce - // auxiliary variables at time t, and make leads of them here - for (int ll = minlag; ll < 0; ll++) { - int ft = diff_f(yi, fi, ll-minlag); - if (ft != ogp::OperationTree::zero) { - // if the ft term has a lead, than we need to - // introduce an auxiliary variable z_t, define it - // as E_t[ft] and put z_{t-ll} to the - // equation. Otherwise, we just put leaded ft to - // the equation directly. - int ft_maxlead, ft_minlag; - model.termspan(ft, ft_maxlead, ft_minlag); - if (ft_maxlead > 0) { - // make an auxiliary variable - char name[100]; - sprintf(name, "AUX_%d_%d_%d", yi, fset[fi], -ll); - model.atoms.register_uniq_endo(name); - info.num_aux_variables++; - int taux = model.eqs.add_nulary(name); - sprintf(name, "AUX_%d_%d_%d(%d)", yi, fset[fi], -ll, -ll); - int taux_leaded = model.eqs.add_nulary(name); - // put aux_leaded to the equation - diff_f(yi, fi, ll-minlag) = taux_leaded; - // save auxiliary variable and the term - aux_map.insert(Tsubstmap::value_type(model.atoms.name(taux), ft)); - } else { - // no auxiliary variable is needed and the - // term ft can be leaded in place - model.variable_shift_map(model.eqs.nulary_of_term(ft), -ll, subst); - diff_f(yi, fi, ll-minlag) = - model.eqs.add_substitution(ft, subst); - } - } - } - } -} - -void 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)) - 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)); -} - -void 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)) - 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)); - - beta_pow = ogp::OperationTree::one; - for (int ll = 0; ll >= minlag; ll--, - beta_pow = model.eqs.add_binary(ogp::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)); -} - -void PlannerBuilder::make_static_version() -{ - // map holding substitutions from dynamic to static - ogp::StaticFineAtoms::Tintintmap tmap; - - // fill static atoms with outer ordering - static_atoms.import_atoms(model.atoms, static_tree, tmap); - - // go through diff_b and fill diff_b_static - for (int ll = minlag; ll <= 0; ll++) - for (int yi = 0; yi < diff_b.nrows(); yi++) - diff_b_static(yi, ll-minlag) = - static_tree.add_substitution(diff_b(yi, ll-minlag), - tmap, model.eqs.getTree()); - - // go through diff_f and fill diff_f_static - for (int ll = minlag; ll <= maxlead; ll++) - for (int yi = 0; yi < diff_f.dim1(); yi++) - for (int fi = 0; fi < diff_f.dim2(); fi++) - diff_f_static(yi, fi, ll-minlag) = - static_tree.add_substitution(diff_f(yi, fi, ll-minlag), - tmap, model.eqs.getTree()); - - // go through aux_map and fill static_aux_map - for (Tsubstmap::const_iterator it = aux_map.begin(); - it != aux_map.end(); ++it) { - int tstatic = static_tree.add_substitution((*it).second, tmap, model.eqs.getTree()); - const char* name = static_atoms.get_name_storage().query((*it).first); - static_aux_map.insert(Tsubstmap::value_type(name, tstatic)); - } -} - - -void PlannerBuilder::lagrange_mult_f() -{ - // register multipliers - char mult_name[100]; - for (int fi = 0; fi < diff_f.dim2(); fi++) { - sprintf(mult_name, "MULT%d", fset[fi]); - model.atoms.register_uniq_endo(mult_name); - info.num_lagrange_mults++; - } - // multiply with the multipliers - for (int yi = 0; yi < diff_f.dim1(); yi++) - for (int fi = 0; fi < diff_f.dim2(); fi++) - for (int ll = minlag; ll <= maxlead; ll++) - if (diff_f(yi, fi, ll-minlag) != ogp::OperationTree::zero) { - 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)); - } -} - -void PlannerBuilder::form_equations() -{ - // add planner's FOCs - for (int yi = 0; yi < diff_f.dim1(); yi++) { - 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)); - 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)); - model.eqs.add_formula(eq); - } - - // add equations for auxiliary variables - for (Tsubstmap::const_iterator it = aux_map.begin(); - 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)); - } -} - -void PlannerBuilder::fill_yset(const ogp::NameStorage& ns, - const PlannerBuilder::Tvarset& yyset) -{ - for (Tvarset::const_iterator it = yyset.begin(); it != yyset.end(); ++it) - yset.insert(ns.query(*it)); -} - -void PlannerBuilder::fill_aux_map(const ogp::NameStorage& ns, const Tsubstmap& aaux_map, - const Tsubstmap& astatic_aux_map) -{ - // fill aux_map - for (Tsubstmap::const_iterator it = aaux_map.begin(); - it != aaux_map.end(); ++it) - aux_map.insert(Tsubstmap::value_type(ns.query((*it).first), (*it).second)); - - // fill static_aux_map - for (Tsubstmap::const_iterator it = astatic_aux_map.begin(); - it != astatic_aux_map.end(); ++it) - static_aux_map.insert(Tsubstmap::value_type(static_atoms.get_name_storage().query((*it).first), - (*it).second)); -} - -MultInitSS::MultInitSS(const PlannerBuilder& pb, const Vector& pvals, Vector& yy) - : builder(pb), b(builder.diff_b_static.nrows()), - F(builder.diff_f_static.dim1(), builder.diff_f_static.dim2()) -{ - b.zeros(); - F.zeros(); - - // first evaluate substitutions (auxiliary variables) from the builder - ogdyn::DynareStaticSteadySubstitutions dss(builder.model.atoms, builder.static_atoms, - builder.static_tree, - builder.static_aux_map, pvals, yy); - - // gather all the terms from builder.diff_b_static and - // builder.diff_f_static to the vector, the ordering is important, - // since the index of this vector will have to be decoded to the - // position in b and F. - vector<int> terms; - for (int yi = 0; yi < builder.diff_b_static.nrows(); yi++) - for (int l = 0; l < builder.diff_b_static.ncols(); l++) - terms.push_back(builder.diff_b_static(yi, l)); - for (int yi = 0; yi < builder.diff_f_static.dim1(); yi++) - for (int fi = 0; fi < builder.diff_f_static.dim2(); fi++) - for (int l = 0; l < builder.diff_f_static.dim3(); l++) - terms.push_back(builder.diff_f_static(yi, fi, l)); - - // evaluate the terms, it will call a series of load(i,res), which - // sum the results through lags/leads to b and F - DynareStaticSteadyAtomValues dssav(builder.model.atoms, builder.static_atoms, pvals, yy); - ogp::FormulaCustomEvaluator fe(builder.static_tree, terms); - fe.eval(dssav, *this); - - // solve overdetermined system b+F*lambda=0 using SVD decomposition - SVDDecomp decomp(F); - Vector lambda(builder.diff_f_static.dim2()); - decomp.solve(b, lambda); - lambda.mult(-1); - - // take values of lambda and put it to yy - for (int fi = 0; fi < builder.diff_f_static.dim2(); fi++) { - char mult_name[100]; - sprintf(mult_name, "MULT%d", builder.fset[fi]); - int iouter = builder.model.atoms.name2outer_endo(mult_name); - int iy = builder.model.atoms.outer2y_endo()[iouter]; - if (! std::isfinite(yy[iy])) - yy[iy] = lambda[fi]; - - // go through all substitutions of the multiplier and set them - // as well - if (builder.model.atom_substs) { - const ogp::AtomSubstitutions::Toldnamemap& old2new = - builder.model.atom_substs->get_old2new(); - const ogp::AtomSubstitutions::Toldnamemap::const_iterator it = - old2new.find(mult_name); - if (it != old2new.end()) { - const ogp::AtomSubstitutions::Tshiftnameset& sset = (*it).second; - for (ogp::AtomSubstitutions::Tshiftnameset::const_iterator itt = sset.begin(); - itt != sset.end(); ++itt) { - const char* newname = (*itt).first; - int iouter = builder.model.atoms.name2outer_endo(newname); - int iy = builder.model.atoms.outer2y_endo()[iouter]; - if (! std::isfinite(yy[iy])) - yy[iy] = lambda[fi]; - } - } - } - } -} - -void MultInitSS::load(int i, double res) -{ - // we can afford it, since the evaluator sets res to exact zero if - // the term is zero - if (res == 0) - return; - // decode i and add to either b or F - if (i < builder.diff_b_static.nrows()*builder.diff_b_static.ncols()) { - // add to b - b[i / builder.diff_b_static.ncols()] += res; - } else { - // add to F - i -= builder.diff_b_static.nrows()*builder.diff_b_static.ncols(); - int yifi = i / builder.diff_f_static.dim3(); - int yi = yifi / builder.diff_f_static.dim2(); - int fi = yifi % builder.diff_f_static.dim2(); - F.get(yi, fi) += res; - } -} diff --git a/dynare++/src/planner_builder.h b/dynare++/src/planner_builder.hh similarity index 99% rename from dynare++/src/planner_builder.h rename to dynare++/src/planner_builder.hh index 4d888d9051c300706761f879890de059d623ed14..b62b76a1eb55313893e1adae50ad979408d0450d 100644 --- a/dynare++/src/planner_builder.h +++ b/dynare++/src/planner_builder.hh @@ -3,7 +3,7 @@ #ifndef PLANNER_BUILDER_H #define PLANNER_BUILDER_H -#include "dynare_model.h" +#include "dynare_model.hh" namespace ogdyn { diff --git a/dynare++/sylv/cc/BlockDiagonal.cc b/dynare++/sylv/cc/BlockDiagonal.cc new file mode 100644 index 0000000000000000000000000000000000000000..daf7a38302e49df06280aa60646e4088bcd44ab8 --- /dev/null +++ b/dynare++/sylv/cc/BlockDiagonal.cc @@ -0,0 +1,355 @@ +/* $Header: /var/lib/cvs/dynare_cpp/sylv/cc/BlockDiagonal.cpp,v 1.1.1.1 2004/06/04 13:00:20 kamenik Exp $ */ + +/* Tag $Name: $ */ + +#include "BlockDiagonal.hh" + +#include <cstdio> +#include <cstring> + +BlockDiagonal::BlockDiagonal(const double *d, int d_size) + : QuasiTriangular(d, d_size), + row_len(new int[d_size]), col_len(new int[d_size]) +{ + for (int i = 0; i < d_size; i++) + { + row_len[i] = d_size; + col_len[i] = 0; + } +} + +BlockDiagonal::BlockDiagonal(const QuasiTriangular &t) + : QuasiTriangular(t), + row_len(new int[t.numRows()]), col_len(new int[t.numRows()]) +{ + for (int i = 0; i < t.numRows(); i++) + { + row_len[i] = t.numRows(); + col_len[i] = 0; + } +} + +BlockDiagonal::BlockDiagonal(int p, const BlockDiagonal &b) + : QuasiTriangular(p, b), + row_len(new int[b.numRows()]), col_len(new int[b.numRows()]) +{ + memcpy(row_len, b.row_len, b.numRows()*sizeof(int)); + memcpy(col_len, b.col_len, b.numRows()*sizeof(int)); +} + +BlockDiagonal::BlockDiagonal(const BlockDiagonal &b) + : QuasiTriangular(b), + row_len(new int[b.numRows()]), col_len(new int[b.numRows()]) +{ + memcpy(row_len, b.row_len, b.numRows()*sizeof(int)); + memcpy(col_len, b.col_len, b.numRows()*sizeof(int)); +} + +/* put zeroes to right upper submatrix whose first column is defined + * by 'edge' */ +void +BlockDiagonal::setZerosToRU(diag_iter edge) +{ + int iedge = (*edge).getIndex(); + for (int i = 0; i < iedge; i++) + for (int j = iedge; j < numCols(); j++) + get(i, j) = 0.0; +} + +/* Updates row_len and col_len so that there are zeroes in upper right part, this + * |T1 0 | + * |0 T2|. The first column of T2 is given by diagonal iterator 'edge'. + + * Note the semantics of row_len and col_len. row_len[i] is distance + * of the right-most non-zero element of i-th row from the left, and + * col_len[j] is distance of top-most non-zero element of j-th column + * to the top. (First element has distance 1). + */ +void +BlockDiagonal::setZeroBlockEdge(diag_iter edge) +{ + setZerosToRU(edge); + + int iedge = (*edge).getIndex(); + for (diag_iter run = diag_begin(); run != edge; ++run) + { + int ind = (*run).getIndex(); + if (row_len[ind] > iedge) + { + row_len[ind] = iedge; + if (!(*run).isReal()) + row_len[ind+1] = iedge; + } + } + for (diag_iter run = edge; run != diag_end(); ++run) + { + int ind = (*run).getIndex(); + if (col_len[ind] < iedge) + { + col_len[ind] = iedge; + if (!(*run).isReal()) + col_len[ind+1] = iedge; + } + } +} + +BlockDiagonal::const_col_iter +BlockDiagonal::col_begin(const DiagonalBlock &b) const +{ + int jbar = b.getIndex(); + int d_size = diagonal.getSize(); + return const_col_iter(&getData()[jbar*d_size + col_len[jbar]], d_size, + b.isReal(), col_len[jbar]); +} + +BlockDiagonal::col_iter +BlockDiagonal::col_begin(const DiagonalBlock &b) +{ + int jbar = b.getIndex(); + int d_size = diagonal.getSize(); + return col_iter(&getData()[jbar*d_size + col_len[jbar]], d_size, + b.isReal(), col_len[jbar]); +} + +BlockDiagonal::const_row_iter +BlockDiagonal::row_end(const DiagonalBlock &b) const +{ + int jbar = b.getIndex(); + int d_size = diagonal.getSize(); + return const_row_iter(&getData()[d_size*row_len[jbar]+jbar], d_size, + b.isReal(), row_len[jbar]); +} + +BlockDiagonal::row_iter +BlockDiagonal::row_end(const DiagonalBlock &b) +{ + int jbar = b.getIndex(); + int d_size = diagonal.getSize(); + return row_iter(&getData()[d_size*row_len[jbar]+jbar], d_size, + b.isReal(), row_len[jbar]); +} + +int +BlockDiagonal::getNumZeros() const +{ + int sum = 0; + for (int i = 0; i < diagonal.getSize(); i++) + { + sum += diagonal.getSize() - row_len[i]; + } + return sum; +} + +QuasiTriangular::const_diag_iter +BlockDiagonal::findBlockStart(const_diag_iter from) const +{ + if (from != diag_end()) + { + ++from; + while (from != diag_end() + && col_len[(*from).getIndex()] != (*from).getIndex()) + ++from; + } + return from; +} + +int +BlockDiagonal::getLargestBlock() const +{ + int largest = 0; + const_diag_iter start = diag_begin(); + const_diag_iter end = findBlockStart(start); + while (start != diag_end()) + { + int si = (*start).getIndex(); + int ei = diagonal.getSize(); + if (end != diag_end()) + ei = (*end).getIndex(); + if (largest < ei-si) + largest = ei-si; + start = end; + end = findBlockStart(start); + } + return largest; +} + +void +BlockDiagonal::savePartOfX(int si, int ei, const KronVector &x, Vector &work) +{ + for (int i = si; i < ei; i++) + { + ConstKronVector xi(x, i); + Vector target(work, (i-si)*xi.length(), xi.length()); + target = xi; + } +} + +void +BlockDiagonal::multKronBlock(const_diag_iter start, const_diag_iter end, + KronVector &x, Vector &work) const +{ + int si = (*start).getIndex(); + int ei = diagonal.getSize(); + if (end != diag_end()) + ei = (*end).getIndex(); + savePartOfX(si, ei, x, work); + + for (const_diag_iter di = start; di != end; ++di) + { + int jbar = (*di).getIndex(); + if ((*di).isReal()) + { + KronVector xi(x, jbar); + xi.zeros(); + Vector wi(work, (jbar-si)*xi.length(), xi.length()); + xi.add(*((*di).getAlpha()), wi); + for (const_row_iter ri = row_begin(*di); ri != row_end(*di); ++ri) + { + int col = ri.getCol(); + Vector wj(work, (col-si)*xi.length(), xi.length()); + xi.add(*ri, wj); + } + } + else + { + KronVector xi(x, jbar); + KronVector xii(x, jbar+1); + xi.zeros(); + xii.zeros(); + Vector wi(work, (jbar-si)*xi.length(), xi.length()); + Vector wii(work, (jbar+1-si)*xi.length(), xi.length()); + xi.add(*((*di).getAlpha()), wi); + xi.add((*di).getBeta1(), wii); + xii.add((*di).getBeta2(), wi); + xii.add(*((*di).getAlpha()), wii); + for (const_row_iter ri = row_begin(*di); ri != row_end(*di); ++ri) + { + int col = ri.getCol(); + Vector wj(work, (col-si)*xi.length(), xi.length()); + xi.add(ri.a(), wj); + xii.add(ri.b(), wj); + } + } + } +} + +void +BlockDiagonal::multKronBlockTrans(const_diag_iter start, const_diag_iter end, + KronVector &x, Vector &work) const +{ + int si = (*start).getIndex(); + int ei = diagonal.getSize(); + if (end != diag_end()) + ei = (*end).getIndex(); + savePartOfX(si, ei, x, work); + + for (const_diag_iter di = start; di != end; ++di) + { + int jbar = (*di).getIndex(); + if ((*di).isReal()) + { + KronVector xi(x, jbar); + xi.zeros(); + Vector wi(work, (jbar-si)*xi.length(), xi.length()); + xi.add(*((*di).getAlpha()), wi); + for (const_col_iter ci = col_begin(*di); ci != col_end(*di); ++ci) + { + int row = ci.getRow(); + Vector wj(work, (row-si)*xi.length(), xi.length()); + xi.add(*ci, wj); + } + } + else + { + KronVector xi(x, jbar); + KronVector xii(x, jbar+1); + xi.zeros(); + xii.zeros(); + Vector wi(work, (jbar-si)*xi.length(), xi.length()); + Vector wii(work, (jbar+1-si)*xi.length(), xi.length()); + xi.add(*((*di).getAlpha()), wi); + xi.add((*di).getBeta2(), wii); + xii.add((*di).getBeta1(), wi); + xii.add(*((*di).getAlpha()), wii); + for (const_col_iter ci = col_begin(*di); ci != col_end(*di); ++ci) + { + int row = ci.getRow(); + Vector wj(work, (row-si)*xi.length(), xi.length()); + xi.add(ci.a(), wj); + xii.add(ci.b(), wj); + } + } + } +} + +void +BlockDiagonal::multKron(KronVector &x) const +{ + int largest = getLargestBlock(); + Vector work(largest *x.getN()*power(x.getM(), x.getDepth()-1)); + const_diag_iter start = diag_begin(); + const_diag_iter end = findBlockStart(start); + while (start != diag_end()) + { + multKronBlock(start, end, x, work); + start = end; + end = findBlockStart(start); + } +} + +void +BlockDiagonal::multKronTrans(KronVector &x) const +{ + int largest = getLargestBlock(); + Vector work(largest *x.getN()*power(x.getM(), x.getDepth()-1)); + const_diag_iter start = diag_begin(); + const_diag_iter end = findBlockStart(start); + while (start != diag_end()) + { + multKronBlockTrans(start, end, x, work); + start = end; + end = findBlockStart(start); + } +} + +void +BlockDiagonal::printInfo() const +{ + printf("Block sizes:"); + int num_blocks = 0; + const_diag_iter start = diag_begin(); + const_diag_iter end = findBlockStart(start); + while (start != diag_end()) + { + int si = (*start).getIndex(); + int ei = diagonal.getSize(); + if (end != diag_end()) + ei = (*end).getIndex(); + printf(" %d", ei-si); + num_blocks++; + start = end; + end = findBlockStart(start); + } + printf("\nNum blocks: %d\n", num_blocks); + printf("There are %d zeros out of %d\n", + getNumZeros(), getNumOffdiagonal()); +} + +int +BlockDiagonal::getNumBlocks() const +{ + int num_blocks = 0; + const_diag_iter start = diag_begin(); + const_diag_iter end = findBlockStart(start); + while (start != diag_end()) + { + num_blocks++; + start = end; + end = findBlockStart(start); + } + return num_blocks; +} + +// Local Variables: +// mode:C++ +// End: diff --git a/dynare++/sylv/cc/BlockDiagonal.cpp b/dynare++/sylv/cc/BlockDiagonal.cpp deleted file mode 100644 index ea461dc4a15276c1ae6d2b893ed1317e0a3d2b37..0000000000000000000000000000000000000000 --- a/dynare++/sylv/cc/BlockDiagonal.cpp +++ /dev/null @@ -1,321 +0,0 @@ -/* $Header: /var/lib/cvs/dynare_cpp/sylv/cc/BlockDiagonal.cpp,v 1.1.1.1 2004/06/04 13:00:20 kamenik Exp $ */ - -/* Tag $Name: $ */ - -#include "BlockDiagonal.h" - -#include <cstdio> -#include <cstring> - -BlockDiagonal::BlockDiagonal(const double* d, int d_size) - : QuasiTriangular(d, d_size), - row_len(new int[d_size]), col_len(new int[d_size]) -{ - for (int i = 0; i < d_size; i++) { - row_len[i] = d_size; - col_len[i] = 0; - } -} - -BlockDiagonal::BlockDiagonal(const QuasiTriangular& t) - : QuasiTriangular(t), - row_len(new int[t.numRows()]), col_len(new int[t.numRows()]) -{ - for (int i = 0; i < t.numRows(); i++) { - row_len[i] = t.numRows(); - col_len[i] = 0; - } -} - -BlockDiagonal::BlockDiagonal(int p, const BlockDiagonal& b) - : QuasiTriangular(p, b), - row_len(new int[b.numRows()]), col_len(new int[b.numRows()]) -{ - memcpy(row_len, b.row_len, b.numRows()*sizeof(int)); - memcpy(col_len, b.col_len, b.numRows()*sizeof(int)); -} - -BlockDiagonal::BlockDiagonal(const BlockDiagonal& b) - : QuasiTriangular(b), - row_len(new int[b.numRows()]), col_len(new int[b.numRows()]) -{ - memcpy(row_len, b.row_len, b.numRows()*sizeof(int)); - memcpy(col_len, b.col_len, b.numRows()*sizeof(int)); -} - -/* put zeroes to right upper submatrix whose first column is defined - * by 'edge' */ -void BlockDiagonal::setZerosToRU(diag_iter edge) -{ - int iedge = (*edge).getIndex(); - for (int i = 0; i < iedge; i++) - for (int j = iedge; j < numCols(); j++) - get(i,j) = 0.0; -} - -/* Updates row_len and col_len so that there are zeroes in upper right part, this - * |T1 0 | - * |0 T2|. The first column of T2 is given by diagonal iterator 'edge'. - - * Note the semantics of row_len and col_len. row_len[i] is distance - * of the right-most non-zero element of i-th row from the left, and - * col_len[j] is distance of top-most non-zero element of j-th column - * to the top. (First element has distance 1). - */ -void BlockDiagonal::setZeroBlockEdge(diag_iter edge) -{ - setZerosToRU(edge); - - int iedge = (*edge).getIndex(); - for (diag_iter run = diag_begin(); run != edge; ++run) { - int ind = (*run).getIndex(); - if (row_len[ind] > iedge) { - row_len[ind] = iedge; - if (!(*run).isReal()) - row_len[ind+1] = iedge; - } - } - for (diag_iter run = edge; run != diag_end(); ++run) { - int ind = (*run).getIndex(); - if (col_len[ind] < iedge) { - col_len[ind] = iedge; - if (!(*run).isReal()) - col_len[ind+1] = iedge; - } - } -} - -BlockDiagonal::const_col_iter -BlockDiagonal::col_begin(const DiagonalBlock& b) const -{ - int jbar = b.getIndex(); - int d_size = diagonal.getSize(); - return const_col_iter(&getData()[jbar*d_size + col_len[jbar]], d_size, - b.isReal(), col_len[jbar]); -} - -BlockDiagonal::col_iter -BlockDiagonal::col_begin(const DiagonalBlock& b) -{ - int jbar = b.getIndex(); - int d_size = diagonal.getSize(); - return col_iter(&getData()[jbar*d_size + col_len[jbar]], d_size, - b.isReal(), col_len[jbar]); -} - - -BlockDiagonal::const_row_iter -BlockDiagonal::row_end(const DiagonalBlock& b) const -{ - int jbar = b.getIndex(); - int d_size = diagonal.getSize(); - return const_row_iter(&getData()[d_size*row_len[jbar]+jbar], d_size, - b.isReal(), row_len[jbar]); -} - -BlockDiagonal::row_iter -BlockDiagonal::row_end(const DiagonalBlock& b) -{ - int jbar = b.getIndex(); - int d_size = diagonal.getSize(); - return row_iter(&getData()[d_size*row_len[jbar]+jbar], d_size, - b.isReal(), row_len[jbar]); -} - -int BlockDiagonal::getNumZeros() const -{ - int sum = 0; - for (int i = 0; i < diagonal.getSize(); i++) { - sum += diagonal.getSize() - row_len[i]; - } - return sum; -} - -QuasiTriangular::const_diag_iter -BlockDiagonal::findBlockStart(const_diag_iter from) const -{ - if (from != diag_end()) { - ++from; - while (from != diag_end() && - col_len[(*from).getIndex()] != (*from).getIndex()) - ++from; - } - return from; -} - -int BlockDiagonal::getLargestBlock() const -{ - int largest = 0; - const_diag_iter start = diag_begin(); - const_diag_iter end = findBlockStart(start); - while (start != diag_end()) { - int si = (*start).getIndex(); - int ei = diagonal.getSize(); - if (end != diag_end()) - ei = (*end).getIndex(); - if (largest < ei-si) - largest = ei-si; - start = end; - end = findBlockStart(start); - } - return largest; -} - - -void BlockDiagonal::savePartOfX(int si, int ei, const KronVector& x, Vector& work) -{ - for (int i = si; i < ei; i++) { - ConstKronVector xi(x, i); - Vector target(work, (i-si)*xi.length(), xi.length()); - target = xi; - } -} - -void BlockDiagonal::multKronBlock(const_diag_iter start, const_diag_iter end, - KronVector& x, Vector& work) const -{ - int si = (*start).getIndex(); - int ei = diagonal.getSize(); - if (end != diag_end()) - ei = (*end).getIndex(); - savePartOfX(si, ei, x, work); - - for (const_diag_iter di = start; di != end; ++di) { - int jbar = (*di).getIndex(); - if ((*di).isReal()) { - KronVector xi(x, jbar); - xi.zeros(); - Vector wi(work, (jbar-si)*xi.length(), xi.length()); - xi.add(*((*di).getAlpha()), wi); - for (const_row_iter ri = row_begin(*di); ri != row_end(*di); ++ri) { - int col = ri.getCol(); - Vector wj(work, (col-si)*xi.length(), xi.length()); - xi.add(*ri, wj); - } - } else { - KronVector xi(x, jbar); - KronVector xii(x, jbar+1); - xi.zeros(); - xii.zeros(); - Vector wi(work, (jbar-si)*xi.length(), xi.length()); - Vector wii(work, (jbar+1-si)*xi.length(), xi.length()); - xi.add(*((*di).getAlpha()), wi); - xi.add((*di).getBeta1(), wii); - xii.add((*di).getBeta2(), wi); - xii.add(*((*di).getAlpha()), wii); - for (const_row_iter ri = row_begin(*di); ri != row_end(*di); ++ri) { - int col = ri.getCol(); - Vector wj(work, (col-si)*xi.length(), xi.length()); - xi.add(ri.a(), wj); - xii.add(ri.b(), wj); - } - } - } -} - -void BlockDiagonal::multKronBlockTrans(const_diag_iter start, const_diag_iter end, - KronVector& x, Vector& work) const -{ - int si = (*start).getIndex(); - int ei = diagonal.getSize(); - if (end != diag_end()) - ei = (*end).getIndex(); - savePartOfX(si, ei, x, work); - - for (const_diag_iter di = start; di != end; ++di) { - int jbar = (*di).getIndex(); - if ((*di).isReal()) { - KronVector xi(x, jbar); - xi.zeros(); - Vector wi(work, (jbar-si)*xi.length(), xi.length()); - xi.add(*((*di).getAlpha()), wi); - for (const_col_iter ci = col_begin(*di); ci != col_end(*di); ++ci) { - int row = ci.getRow(); - Vector wj(work, (row-si)*xi.length(), xi.length()); - xi.add(*ci, wj); - } - } else { - KronVector xi(x, jbar); - KronVector xii(x, jbar+1); - xi.zeros(); - xii.zeros(); - Vector wi(work, (jbar-si)*xi.length(), xi.length()); - Vector wii(work, (jbar+1-si)*xi.length(), xi.length()); - xi.add(*((*di).getAlpha()), wi); - xi.add((*di).getBeta2(), wii); - xii.add((*di).getBeta1(), wi); - xii.add(*((*di).getAlpha()), wii); - for (const_col_iter ci = col_begin(*di); ci != col_end(*di); ++ci) { - int row = ci.getRow(); - Vector wj(work, (row-si)*xi.length(), xi.length()); - xi.add(ci.a(), wj); - xii.add(ci.b(), wj); - } - } - } -} - -void BlockDiagonal::multKron(KronVector& x) const -{ - int largest = getLargestBlock(); - Vector work(largest*x.getN()*power(x.getM(),x.getDepth()-1)); - const_diag_iter start = diag_begin(); - const_diag_iter end = findBlockStart(start); - while (start != diag_end()) { - multKronBlock(start, end, x, work); - start = end; - end = findBlockStart(start); - } -} - - -void BlockDiagonal::multKronTrans(KronVector& x) const -{ - int largest = getLargestBlock(); - Vector work(largest*x.getN()*power(x.getM(),x.getDepth()-1)); - const_diag_iter start = diag_begin(); - const_diag_iter end = findBlockStart(start); - while (start != diag_end()) { - multKronBlockTrans(start, end, x, work); - start = end; - end = findBlockStart(start); - } -} - -void BlockDiagonal::printInfo() const -{ - printf("Block sizes:"); - int num_blocks = 0; - const_diag_iter start = diag_begin(); - const_diag_iter end = findBlockStart(start); - while (start != diag_end()) { - int si = (*start).getIndex(); - int ei = diagonal.getSize(); - if (end != diag_end()) - ei = (*end).getIndex(); - printf(" %d", ei-si); - num_blocks++; - start = end; - end = findBlockStart(start); - } - printf("\nNum blocks: %d\n", num_blocks); - printf("There are %d zeros out of %d\n", - getNumZeros(), getNumOffdiagonal()); -} - -int BlockDiagonal::getNumBlocks() const -{ - int num_blocks = 0; - const_diag_iter start = diag_begin(); - const_diag_iter end = findBlockStart(start); - while (start != diag_end()) { - num_blocks++; - start = end; - end = findBlockStart(start); - } - return num_blocks; -} - -// Local Variables: -// mode:C++ -// End: diff --git a/dynare++/sylv/cc/BlockDiagonal.h b/dynare++/sylv/cc/BlockDiagonal.hh similarity index 98% rename from dynare++/sylv/cc/BlockDiagonal.h rename to dynare++/sylv/cc/BlockDiagonal.hh index f449653385da4d385d4b7af825d4411784523944..d1acc1ae65263e892d8d1d594e60c17ca5ab8d70 100644 --- a/dynare++/sylv/cc/BlockDiagonal.h +++ b/dynare++/sylv/cc/BlockDiagonal.hh @@ -5,7 +5,7 @@ #ifndef BLOCK_DIAGONAL_H #define BLOCK_DIAGONAL_H -#include "QuasiTriangular.h" +#include "QuasiTriangular.hh" class BlockDiagonal : public QuasiTriangular { diff --git a/dynare++/sylv/cc/GeneralMatrix.cc b/dynare++/sylv/cc/GeneralMatrix.cc new file mode 100644 index 0000000000000000000000000000000000000000..c035248b9a3b104b52f9ce1cea2e5d6424bb8d4d --- /dev/null +++ b/dynare++/sylv/cc/GeneralMatrix.cc @@ -0,0 +1,613 @@ +/* $Header: /var/lib/cvs/dynare_cpp/sylv/cc/GeneralMatrix.cpp,v 1.4 2004/11/24 20:41:59 kamenik Exp $ */ + +/* Tag $Name: $ */ + +#include "SylvException.hh" +#include "GeneralMatrix.hh" + +#include <dynblas.h> +#include <dynlapack.h> + +#include <cstdio> +#include <cstring> +#include <cstdlib> +#include <cmath> +#include <limits> + +int GeneralMatrix::md_length = 32; + +GeneralMatrix::GeneralMatrix(const GeneralMatrix &m) + : data(m.rows*m.cols), rows(m.rows), cols(m.cols), ld(m.rows) +{ + copy(m); +} + +GeneralMatrix::GeneralMatrix(const ConstGeneralMatrix &m) + : data(m.rows*m.cols), rows(m.rows), cols(m.cols), ld(m.rows) +{ + copy(m); +} + +GeneralMatrix::GeneralMatrix(const GeneralMatrix &m, const char *dummy) + : data(m.rows*m.cols), rows(m.cols), cols(m.rows), ld(m.cols) +{ + for (int i = 0; i < m.rows; i++) + for (int j = 0; j < m.cols; j++) + get(j, i) = m.get(i, j); +} + +GeneralMatrix::GeneralMatrix(const ConstGeneralMatrix &m, const char *dummy) + : data(m.rows*m.cols), rows(m.cols), cols(m.rows), ld(m.cols) +{ + for (int i = 0; i < m.rows; i++) + for (int j = 0; j < m.cols; j++) + get(j, i) = m.get(i, j); +} + +GeneralMatrix::GeneralMatrix(const GeneralMatrix &m, int i, int j, int nrows, int ncols) + : data(nrows*ncols), rows(nrows), cols(ncols), ld(nrows) +{ + copy(m, i, j); +} + +GeneralMatrix::GeneralMatrix(GeneralMatrix &m, int i, int j, int nrows, int ncols) + : data(m.base()+m.ld*j+i, m.ld*(ncols-1)+nrows), rows(nrows), cols(ncols), ld(m.ld) +{ +} + +GeneralMatrix::GeneralMatrix(const GeneralMatrix &a, const GeneralMatrix &b) + : data(a.rows*b.cols), rows(a.rows), cols(b.cols), ld(a.rows) +{ + gemm("N", a, "N", b, 1.0, 0.0); +} + +GeneralMatrix::GeneralMatrix(const GeneralMatrix &a, const GeneralMatrix &b, const char *dum) + : data(a.rows*b.rows), rows(a.rows), cols(b.rows), ld(a.rows) +{ + gemm("N", a, "T", b, 1.0, 0.0); +} + +GeneralMatrix::GeneralMatrix(const GeneralMatrix &a, const char *dum, const GeneralMatrix &b) + : data(a.cols*b.cols), rows(a.cols), cols(b.cols), ld(a.cols) +{ + gemm("T", a, "N", b, 1.0, 0.0); +} + +GeneralMatrix::GeneralMatrix(const GeneralMatrix &a, const char *dum1, + const GeneralMatrix &b, const char *dum2) + : data(a.cols*b.rows), rows(a.cols), cols(b.rows), ld(a.cols) +{ + gemm("T", a, "T", b, 1.0, 0.0); +} + +GeneralMatrix::~GeneralMatrix() +{ +} + +void +GeneralMatrix::place(const ConstGeneralMatrix &m, int i, int j) +{ + if (i + m.numRows() > numRows() + || j + m.numCols() > numCols()) + throw SYLV_MES_EXCEPTION("Bad submatrix placement, matrix dimensions exceeded."); + + GeneralMatrix tmpsub(*this, i, j, m.numRows(), m.numCols()); + tmpsub.copy(m); +} + +void +GeneralMatrix::mult(const ConstGeneralMatrix &a, const ConstGeneralMatrix &b) +{ + gemm("N", a, "N", b, 1.0, 0.0); +} + +void +GeneralMatrix::multAndAdd(const ConstGeneralMatrix &a, const ConstGeneralMatrix &b, + double mult) +{ + gemm("N", a, "N", b, mult, 1.0); +} + +void +GeneralMatrix::multAndAdd(const ConstGeneralMatrix &a, const ConstGeneralMatrix &b, + const char *dum, double mult) +{ + gemm("N", a, "T", b, mult, 1.0); +} + +void +GeneralMatrix::multAndAdd(const ConstGeneralMatrix &a, const char *dum, + const ConstGeneralMatrix &b, double mult) +{ + gemm("T", a, "N", b, mult, 1.0); +} + +void +GeneralMatrix::multAndAdd(const ConstGeneralMatrix &a, const char *dum1, + const ConstGeneralMatrix &b, const char *dum2, double mult) +{ + gemm("T", a, "T", b, mult, 1.0); +} + +void +GeneralMatrix::addOuter(const ConstVector &a, double mult) +{ + if (numRows() != numCols()) + throw SYLV_MES_EXCEPTION("Matrix is not square in GeneralMatrix::addOuter."); + if (numRows() != a.length()) + throw SYLV_MES_EXCEPTION("Wrong length of a vector in GeneralMatrix::addOuter."); + + // since BLAS dsyr (symmetric rank 1 update) assumes symmetricity, we do this manually + for (int i = 0; i < numRows(); i++) + for (int j = i; j < numRows(); j++) + { + double s = mult*a[i]*a[j]; + get(i, j) = get(i, j) + s; + if (i != j) + get(j, i) = get(j, i) + s; + } +} + +void +GeneralMatrix::multRight(const ConstGeneralMatrix &m) +{ + gemm_partial_right("N", m, 1.0, 0.0); +} + +void +GeneralMatrix::multLeft(const ConstGeneralMatrix &m) +{ + gemm_partial_left("N", m, 1.0, 0.0); +} + +void +GeneralMatrix::multRightTrans(const ConstGeneralMatrix &m) +{ + gemm_partial_right("T", m, 1.0, 0.0); +} + +void +GeneralMatrix::multLeftTrans(const ConstGeneralMatrix &m) +{ + gemm_partial_left("T", m, 1.0, 0.0); +} + +// here we must be careful for ld +void +GeneralMatrix::zeros() +{ + if (ld == rows) + data.zeros(); + else + { + for (int i = 0; i < rows; i++) + for (int j = 0; j < cols; j++) + get(i, j) = 0; + } +} + +void +GeneralMatrix::unit() +{ + for (int i = 0; i < rows; i++) + for (int j = 0; j < cols; j++) + if (i == j) + get(i, j) = 1.0; + else + get(i, j) = 0.0; +} + +void +GeneralMatrix::nans() +{ + for (int i = 0; i < rows; i++) + for (int j = 0; j < cols; j++) + get(i, j) = std::numeric_limits<double>::quiet_NaN(); +} + +void +GeneralMatrix::infs() +{ + for (int i = 0; i < rows; i++) + for (int j = 0; j < cols; j++) + get(i, j) = std::numeric_limits<double>::infinity(); +} + +// here we must be careful for ld +void +GeneralMatrix::mult(double a) +{ + if (ld == rows) + data.mult(a); + else + { + for (int i = 0; i < rows; i++) + for (int j = 0; j < cols; j++) + get(i, j) *= a; + } +} + +// here we must be careful for ld +void +GeneralMatrix::add(double a, const ConstGeneralMatrix &m) +{ + if (m.numRows() != rows || m.numCols() != cols) + throw SYLV_MES_EXCEPTION("Matrix has different size in GeneralMatrix::add."); + + if (ld == rows && m.ld == m.rows) + data.add(a, m.data); + else + { + for (int i = 0; i < rows; i++) + for (int j = 0; j < cols; j++) + get(i, j) += a*m.get(i, j); + } +} + +void +GeneralMatrix::add(double a, const ConstGeneralMatrix &m, const char *dum) +{ + if (m.numRows() != cols || m.numCols() != rows) + throw SYLV_MES_EXCEPTION("Matrix has different size in GeneralMatrix::add."); + + for (int i = 0; i < rows; i++) + for (int j = 0; j < cols; j++) + get(i, j) += a*m.get(j, i); +} + +void +GeneralMatrix::copy(const ConstGeneralMatrix &m, int ioff, int joff) +{ + for (int i = 0; i < rows; i++) + for (int j = 0; j < cols; j++) + get(i, j) = m.get(i+ioff, j+joff); +} + +void +GeneralMatrix::gemm(const char *transa, const ConstGeneralMatrix &a, + const char *transb, const ConstGeneralMatrix &b, + double alpha, double beta) +{ + int opa_rows = a.numRows(); + int opa_cols = a.numCols(); + if (!strcmp(transa, "T")) + { + opa_rows = a.numCols(); + opa_cols = a.numRows(); + } + int opb_rows = b.numRows(); + int opb_cols = b.numCols(); + if (!strcmp(transb, "T")) + { + opb_rows = b.numCols(); + opb_cols = b.numRows(); + } + + if (opa_rows != numRows() + || opb_cols != numCols() + || opa_cols != opb_rows) + { + throw SYLV_MES_EXCEPTION("Wrong dimensions for matrix multiplication."); + } + + blas_int m = opa_rows; + blas_int n = opb_cols; + blas_int k = opa_cols; + blas_int lda = a.ld; + blas_int ldb = b.ld; + blas_int ldc = ld; + if (lda > 0 && ldb > 0 && ldc > 0) + { + dgemm(transa, transb, &m, &n, &k, &alpha, a.data.base(), &lda, + b.data.base(), &ldb, &beta, data.base(), &ldc); + } + else if (numRows()*numCols() > 0) + { + if (beta == 0.0) + zeros(); + else + mult(beta); + } +} + +void +GeneralMatrix::gemm_partial_left(const char *trans, const ConstGeneralMatrix &m, + double alpha, double beta) +{ + int icol; + for (icol = 0; icol + md_length < cols; icol += md_length) + { + GeneralMatrix incopy((const GeneralMatrix &)*this, 0, icol, rows, md_length); + GeneralMatrix inplace((GeneralMatrix&)*this, 0, icol, rows, md_length); + inplace.gemm(trans, m, "N", ConstGeneralMatrix(incopy), alpha, beta); + } + if (cols > icol) + { + GeneralMatrix incopy((const GeneralMatrix &)*this, 0, icol, rows, cols - icol); + GeneralMatrix inplace((GeneralMatrix&)*this, 0, icol, rows, cols - icol); + inplace.gemm(trans, m, "N", ConstGeneralMatrix(incopy), alpha, beta); + } +} + +void +GeneralMatrix::gemm_partial_right(const char *trans, const ConstGeneralMatrix &m, + double alpha, double beta) +{ + int irow; + for (irow = 0; irow + md_length < rows; irow += md_length) + { + GeneralMatrix incopy((const GeneralMatrix &)*this, irow, 0, md_length, cols); + GeneralMatrix inplace((GeneralMatrix&)*this, irow, 0, md_length, cols); + inplace.gemm("N", ConstGeneralMatrix(incopy), trans, m, alpha, beta); + } + if (rows > irow) + { + GeneralMatrix incopy((const GeneralMatrix &)*this, irow, 0, rows - irow, cols); + GeneralMatrix inplace((GeneralMatrix&)*this, irow, 0, rows - irow, cols); + inplace.gemm("N", ConstGeneralMatrix(incopy), trans, m, alpha, beta); + } +} + +ConstGeneralMatrix::ConstGeneralMatrix(const GeneralMatrix &m, int i, int j, int nrows, int ncols) + : data(m.getData(), j*m.getLD()+i, (ncols-1)*m.getLD()+nrows), rows(nrows), cols(ncols), ld(m.getLD()) +{ + // can check that the submatirx is fully in the matrix +} + +ConstGeneralMatrix::ConstGeneralMatrix(const ConstGeneralMatrix &m, int i, int j, int nrows, int ncols) + : data(m.getData(), j*m.getLD()+i, (ncols-1)*m.getLD()+nrows), rows(nrows), cols(ncols), ld(m.getLD()) +{ + // can check that the submatirx is fully in the matrix +} + +ConstGeneralMatrix::ConstGeneralMatrix(const GeneralMatrix &m) + : data(m.data), rows(m.rows), cols(m.cols), ld(m.ld) +{ +} + +double +ConstGeneralMatrix::getNormInf() const +{ + double norm = 0.0; + for (int i = 0; i < numRows(); i++) + { + ConstVector rowi(data.base()+i, ld, cols); + double normi = rowi.getNorm1(); + if (norm < normi) + norm = normi; + } + return norm; +} + +double +ConstGeneralMatrix::getNorm1() const +{ + double norm = 0.0; + for (int j = 0; j < numCols(); j++) + { + ConstVector colj(data.base()+ld *j, 1, rows); + double normj = colj.getNorm1(); + if (norm < normj) + norm = normj; + } + return norm; +} + +void +ConstGeneralMatrix::multVec(double a, Vector &x, double b, const ConstVector &d) const +{ + if (x.length() != rows || cols != d.length()) + { + throw SYLV_MES_EXCEPTION("Wrong dimensions for vector multiply."); + } + if (rows > 0) + { + blas_int mm = rows; + blas_int nn = cols; + double alpha = b; + blas_int lda = ld; + blas_int incx = d.skip(); + double beta = a; + blas_int incy = x.skip(); + dgemv("N", &mm, &nn, &alpha, data.base(), &lda, d.base(), &incx, + &beta, x.base(), &incy); + } + +} + +void +ConstGeneralMatrix::multVecTrans(double a, Vector &x, double b, + const ConstVector &d) const +{ + if (x.length() != cols || rows != d.length()) + { + throw SYLV_MES_EXCEPTION("Wrong dimensions for vector multiply."); + } + if (rows > 0) + { + blas_int mm = rows; + blas_int nn = cols; + double alpha = b; + blas_int lda = rows; + blas_int incx = d.skip(); + double beta = a; + blas_int incy = x.skip(); + dgemv("T", &mm, &nn, &alpha, data.base(), &lda, d.base(), &incx, + &beta, x.base(), &incy); + } +} + +/* m = inv(this)*m */ +void +ConstGeneralMatrix::multInvLeft(const char *trans, int mrows, int mcols, int mld, double *d) const +{ + if (rows != cols) + { + throw SYLV_MES_EXCEPTION("The matrix is not square for inversion."); + } + if (cols != mrows) + { + throw SYLV_MES_EXCEPTION("Wrong dimensions for matrix inverse mutliply."); + } + + if (rows > 0) + { + GeneralMatrix inv(*this); + lapack_int *ipiv = new lapack_int[rows]; + lapack_int info; + lapack_int rows2 = rows, mcols2 = mcols, mld2 = mld; + dgetrf(&rows2, &rows2, inv.getData().base(), &rows2, ipiv, &info); + dgetrs(trans, &rows2, &mcols2, inv.base(), &rows2, ipiv, d, + &mld2, &info); + delete [] ipiv; + } +} + +/* m = inv(this)*m */ +void +ConstGeneralMatrix::multInvLeft(GeneralMatrix &m) const +{ + multInvLeft("N", m.numRows(), m.numCols(), m.getLD(), m.getData().base()); +} + +/* m = inv(this')*m */ +void +ConstGeneralMatrix::multInvLeftTrans(GeneralMatrix &m) const +{ + multInvLeft("T", m.numRows(), m.numCols(), m.getLD(), m.getData().base()); +} + +/* d = inv(this)*d */ +void +ConstGeneralMatrix::multInvLeft(Vector &d) const +{ + if (d.skip() != 1) + { + throw SYLV_MES_EXCEPTION("Skip!=1 not implemented in ConstGeneralMatrix::multInvLeft(Vector&)"); + } + + multInvLeft("N", d.length(), 1, d.length(), d.base()); +} + +/* d = inv(this')*d */ +void +ConstGeneralMatrix::multInvLeftTrans(Vector &d) const +{ + if (d.skip() != 1) + { + throw SYLV_MES_EXCEPTION("Skip!=1 not implemented in ConstGeneralMatrix::multInvLeft(Vector&)"); + } + + multInvLeft("T", d.length(), 1, d.length(), d.base()); +} + +bool +ConstGeneralMatrix::isFinite() const +{ + for (int i = 0; i < numRows(); i++) + for (int j = 0; j < numCols(); j++) + if (!std::isfinite(get(i, j))) + return false; + return true; +} + +bool +ConstGeneralMatrix::isZero() const +{ + for (int i = 0; i < numRows(); i++) + for (int j = 0; j < numCols(); j++) + if (get(i, j) != 0.0) + return false; + return true; +} + +void +ConstGeneralMatrix::print() const +{ + printf("rows=%d, cols=%d\n", rows, cols); + for (int i = 0; i < rows; i++) + { + printf("row %d:\n", i); + for (int j = 0; j < cols; j++) + { + printf("%6.3g ", get(i, j)); + } + printf("\n"); + } +} + +void +SVDDecomp::construct(const GeneralMatrix &A) +{ + // quick exit if empty matrix + if (minmn == 0) + { + U.unit(); + VT.unit(); + conv = true; + return; + } + + // make copy of the matrix + GeneralMatrix AA(A); + + lapack_int m = AA.numRows(); + lapack_int n = AA.numCols(); + double *a = AA.base(); + lapack_int lda = AA.getLD(); + double *s = sigma.base(); + double *u = U.base(); + lapack_int ldu = U.getLD(); + double *vt = VT.base(); + lapack_int ldvt = VT.getLD(); + double tmpwork; + lapack_int lwork = -1; + lapack_int info; + + lapack_int *iwork = new lapack_int[8*minmn]; + // query for optimal lwork + dgesdd("A", &m, &n, a, &lda, s, u, &ldu, vt, &ldvt, &tmpwork, + &lwork, iwork, &info); + lwork = (lapack_int) tmpwork; + Vector work(lwork); + // do the decomposition + dgesdd("A", &m, &n, a, &lda, s, u, &ldu, vt, &ldvt, work.base(), + &lwork, iwork, &info); + delete [] iwork; + if (info < 0) + throw SYLV_MES_EXCEPTION("Internal error in SVDDecomp constructor"); + if (info == 0) + conv = true; +} + +void +SVDDecomp::solve(const GeneralMatrix &B, GeneralMatrix &X) const +{ + if (B.numRows() != U.numRows()) + throw SYLV_MES_EXCEPTION("Incompatible number of rows "); + + // reciprocal condition number for determination of zeros in the + // end of sigma + double rcond = 1e-13; + + // solve U: B = U^T*B + GeneralMatrix UTB(U, "trans", B); + // determine nz=number of zeros in the end of sigma + int nz = 0; + while (nz < minmn && sigma[minmn-1-nz] < rcond*sigma[0]) + nz++; + // take relevant B for sigma inversion + int m = U.numRows(); + int n = VT.numCols(); + GeneralMatrix Bprime(UTB, m-minmn, 0, minmn-nz, B.numCols()); + // solve sigma + for (int i = 0; i < minmn-nz; i++) + Vector(i, Bprime).mult(1.0/sigma[i]); + // solve VT + X.zeros(); + //- copy Bprime to right place of X + for (int i = 0; i < minmn-nz; i++) + Vector(n-minmn+i, X) = ConstVector(i, Bprime); + //- multiply with VT + X.multLeftTrans(VT); +} diff --git a/dynare++/sylv/cc/GeneralMatrix.cpp b/dynare++/sylv/cc/GeneralMatrix.cpp deleted file mode 100644 index 75834f522e4eb367ee6876475b9d0db6aef138fe..0000000000000000000000000000000000000000 --- a/dynare++/sylv/cc/GeneralMatrix.cpp +++ /dev/null @@ -1,556 +0,0 @@ -/* $Header: /var/lib/cvs/dynare_cpp/sylv/cc/GeneralMatrix.cpp,v 1.4 2004/11/24 20:41:59 kamenik Exp $ */ - -/* Tag $Name: $ */ - - -#include "SylvException.h" -#include "GeneralMatrix.h" - -#include <dynblas.h> -#include <dynlapack.h> - -#include <cstdio> -#include <cstring> -#include <cstdlib> -#include <cmath> -#include <limits> - -int GeneralMatrix::md_length = 32; - -GeneralMatrix::GeneralMatrix(const GeneralMatrix& m) - : data(m.rows*m.cols), rows(m.rows), cols(m.cols), ld(m.rows) -{ - copy(m); -} - -GeneralMatrix::GeneralMatrix(const ConstGeneralMatrix& m) - : data(m.rows*m.cols), rows(m.rows), cols(m.cols), ld(m.rows) -{ - copy(m); -} - -GeneralMatrix::GeneralMatrix(const GeneralMatrix& m, const char* dummy) - : data(m.rows*m.cols), rows(m.cols), cols(m.rows), ld(m.cols) -{ - for (int i = 0; i < m.rows; i++) - for (int j = 0; j < m.cols; j++) - get(j,i) = m.get(i,j); -} - -GeneralMatrix::GeneralMatrix(const ConstGeneralMatrix& m, const char* dummy) - : data(m.rows*m.cols), rows(m.cols), cols(m.rows), ld(m.cols) -{ - for (int i = 0; i < m.rows; i++) - for (int j = 0; j < m.cols; j++) - get(j,i) = m.get(i,j); -} - - -GeneralMatrix::GeneralMatrix(const GeneralMatrix& m, int i, int j, int nrows, int ncols) - : data(nrows*ncols), rows(nrows), cols(ncols), ld(nrows) -{ - copy(m, i, j); -} - -GeneralMatrix::GeneralMatrix(GeneralMatrix& m, int i, int j, int nrows, int ncols) - : data(m.base()+m.ld*j+i, m.ld*(ncols-1)+nrows), rows(nrows), cols(ncols), ld(m.ld) -{} - -GeneralMatrix::GeneralMatrix(const GeneralMatrix& a, const GeneralMatrix& b) - : data(a.rows*b.cols), rows(a.rows), cols(b.cols), ld(a.rows) -{ - gemm("N", a, "N", b, 1.0, 0.0); -} - -GeneralMatrix::GeneralMatrix(const GeneralMatrix& a, const GeneralMatrix& b, const char* dum) - : data(a.rows*b.rows), rows(a.rows), cols(b.rows), ld(a.rows) -{ - gemm("N", a, "T", b, 1.0, 0.0); -} - -GeneralMatrix::GeneralMatrix(const GeneralMatrix& a, const char* dum, const GeneralMatrix& b) - : data(a.cols*b.cols), rows(a.cols), cols(b.cols), ld(a.cols) -{ - gemm("T", a, "N", b, 1.0, 0.0); -} - -GeneralMatrix::GeneralMatrix(const GeneralMatrix& a, const char* dum1, - const GeneralMatrix& b, const char* dum2) - : data(a.cols*b.rows), rows(a.cols), cols(b.rows), ld(a.cols) -{ - gemm("T", a, "T", b, 1.0, 0.0); -} - - - -GeneralMatrix::~GeneralMatrix() -{ -} - - - -void GeneralMatrix::place(const ConstGeneralMatrix& m, int i, int j) -{ - if (i + m.numRows() > numRows() || - j + m.numCols() > numCols()) - throw SYLV_MES_EXCEPTION("Bad submatrix placement, matrix dimensions exceeded."); - - GeneralMatrix tmpsub(*this, i, j, m.numRows(), m.numCols()); - tmpsub.copy(m); -} - -void GeneralMatrix::mult(const ConstGeneralMatrix& a, const ConstGeneralMatrix& b) -{ - gemm("N", a, "N", b, 1.0, 0.0); -} - -void GeneralMatrix::multAndAdd(const ConstGeneralMatrix& a, const ConstGeneralMatrix& b, - double mult) -{ - gemm("N", a, "N", b, mult, 1.0); -} - -void GeneralMatrix::multAndAdd(const ConstGeneralMatrix& a, const ConstGeneralMatrix& b, - const char* dum, double mult) -{ - gemm("N", a, "T", b, mult, 1.0); -} - -void GeneralMatrix::multAndAdd(const ConstGeneralMatrix& a, const char* dum, - const ConstGeneralMatrix& b, double mult) -{ - gemm("T", a, "N", b, mult, 1.0); -} - -void GeneralMatrix::multAndAdd(const ConstGeneralMatrix& a, const char* dum1, - const ConstGeneralMatrix& b, const char* dum2, double mult) -{ - gemm("T", a, "T", b, mult, 1.0); -} - -void GeneralMatrix::addOuter(const ConstVector& a, double mult) -{ - if (numRows() != numCols()) - throw SYLV_MES_EXCEPTION("Matrix is not square in GeneralMatrix::addOuter."); - if (numRows() != a.length()) - throw SYLV_MES_EXCEPTION("Wrong length of a vector in GeneralMatrix::addOuter."); - - // since BLAS dsyr (symmetric rank 1 update) assumes symmetricity, we do this manually - for (int i = 0; i < numRows(); i++) - for (int j = i; j < numRows(); j++) { - double s = mult*a[i]*a[j]; - get(i,j) = get(i,j) + s; - if (i != j) - get(j,i) = get(j,i) + s; - } -} - - -void GeneralMatrix::multRight(const ConstGeneralMatrix& m) -{ - gemm_partial_right("N", m, 1.0, 0.0); -} - -void GeneralMatrix::multLeft(const ConstGeneralMatrix& m) -{ - gemm_partial_left("N", m, 1.0, 0.0); -} - -void GeneralMatrix::multRightTrans(const ConstGeneralMatrix& m) -{ - gemm_partial_right("T", m, 1.0, 0.0); -} - -void GeneralMatrix::multLeftTrans(const ConstGeneralMatrix& m) -{ - gemm_partial_left("T", m, 1.0, 0.0); -} - -// here we must be careful for ld -void GeneralMatrix::zeros() -{ - if (ld == rows) - data.zeros(); - else { - for (int i = 0; i < rows; i++) - for (int j = 0; j < cols; j++) - get(i,j) = 0; - } -} - -void GeneralMatrix::unit() -{ - for (int i = 0; i < rows; i++) - for (int j = 0; j < cols; j++) - if (i == j) - get(i,j) = 1.0; - else - get(i,j) = 0.0; -} - -void GeneralMatrix::nans() -{ - for (int i = 0; i < rows; i++) - for (int j = 0; j < cols; j++) - get(i,j) = std::numeric_limits<double>::quiet_NaN(); -} - -void GeneralMatrix::infs() -{ - for (int i = 0; i < rows; i++) - for (int j = 0; j < cols; j++) - get(i,j) = std::numeric_limits<double>::infinity(); -} - - -// here we must be careful for ld -void GeneralMatrix::mult(double a) -{ - if (ld == rows) - data.mult(a); - else { - for (int i = 0; i < rows; i++) - for (int j = 0; j < cols; j++) - get(i,j) *= a; - } -} - -// here we must be careful for ld -void GeneralMatrix::add(double a, const ConstGeneralMatrix& m) -{ - if (m.numRows() != rows || m.numCols() != cols) - throw SYLV_MES_EXCEPTION("Matrix has different size in GeneralMatrix::add."); - - if (ld == rows && m.ld == m.rows) - data.add(a, m.data); - else { - for (int i = 0; i < rows; i++) - for (int j = 0; j < cols; j++) - get(i,j) += a*m.get(i,j); - } -} - -void GeneralMatrix::add(double a, const ConstGeneralMatrix& m, const char* dum) -{ - if (m.numRows() != cols || m.numCols() != rows) - throw SYLV_MES_EXCEPTION("Matrix has different size in GeneralMatrix::add."); - - for (int i = 0; i < rows; i++) - for (int j = 0; j < cols; j++) - get(i,j) += a*m.get(j,i); -} - -void GeneralMatrix::copy(const ConstGeneralMatrix& m, int ioff, int joff) -{ - for (int i = 0; i < rows; i++) - for (int j = 0; j < cols; j++) - get(i,j) = m.get(i+ioff,j+joff); -} - -void GeneralMatrix::gemm(const char* transa, const ConstGeneralMatrix& a, - const char* transb, const ConstGeneralMatrix& b, - double alpha, double beta) -{ - int opa_rows = a.numRows(); - int opa_cols = a.numCols(); - if (!strcmp(transa, "T")) { - opa_rows = a.numCols(); - opa_cols = a.numRows(); - } - int opb_rows = b.numRows(); - int opb_cols = b.numCols(); - if (!strcmp(transb, "T")) { - opb_rows = b.numCols(); - opb_cols = b.numRows(); - } - - if (opa_rows != numRows() || - opb_cols != numCols() || - opa_cols != opb_rows) { - throw SYLV_MES_EXCEPTION("Wrong dimensions for matrix multiplication."); - } - - blas_int m = opa_rows; - blas_int n = opb_cols; - blas_int k = opa_cols; - blas_int lda = a.ld; - blas_int ldb = b.ld; - blas_int ldc = ld; - if (lda > 0 && ldb > 0 && ldc > 0) { - dgemm(transa, transb, &m, &n, &k, &alpha, a.data.base(), &lda, - b.data.base(), &ldb, &beta, data.base(), &ldc); - } else if (numRows()*numCols() > 0) { - if (beta == 0.0) - zeros(); - else - mult(beta); - } -} - -void GeneralMatrix::gemm_partial_left(const char* trans, const ConstGeneralMatrix& m, - double alpha, double beta) -{ - int icol; - for (icol = 0; icol + md_length < cols; icol += md_length) { - GeneralMatrix incopy((const GeneralMatrix&)*this, 0, icol, rows, md_length); - GeneralMatrix inplace((GeneralMatrix&)*this, 0, icol, rows, md_length); - inplace.gemm(trans, m, "N", ConstGeneralMatrix(incopy), alpha, beta); - } - if (cols > icol) { - GeneralMatrix incopy((const GeneralMatrix&)*this, 0, icol, rows, cols - icol); - GeneralMatrix inplace((GeneralMatrix&)*this, 0, icol, rows, cols - icol); - inplace.gemm(trans, m, "N", ConstGeneralMatrix(incopy), alpha, beta); - } -} - -void GeneralMatrix::gemm_partial_right(const char* trans, const ConstGeneralMatrix& m, - double alpha, double beta) -{ - int irow; - for (irow = 0; irow + md_length < rows; irow += md_length) { - GeneralMatrix incopy((const GeneralMatrix&)*this, irow, 0, md_length, cols); - GeneralMatrix inplace((GeneralMatrix&)*this, irow, 0, md_length, cols); - inplace.gemm("N", ConstGeneralMatrix(incopy), trans, m, alpha, beta); - } - if (rows > irow) { - GeneralMatrix incopy((const GeneralMatrix&)*this, irow, 0, rows - irow, cols); - GeneralMatrix inplace((GeneralMatrix&)*this, irow, 0, rows - irow, cols); - inplace.gemm("N", ConstGeneralMatrix(incopy), trans, m, alpha, beta); - } -} - -ConstGeneralMatrix::ConstGeneralMatrix(const GeneralMatrix& m, int i, int j, int nrows, int ncols) - : data(m.getData(), j*m.getLD()+i, (ncols-1)*m.getLD()+nrows), rows(nrows), cols(ncols), ld(m.getLD()) -{ - // can check that the submatirx is fully in the matrix -} - -ConstGeneralMatrix::ConstGeneralMatrix(const ConstGeneralMatrix& m, int i, int j, int nrows, int ncols) - : data(m.getData(), j*m.getLD()+i, (ncols-1)*m.getLD()+nrows), rows(nrows), cols(ncols), ld(m.getLD()) -{ - // can check that the submatirx is fully in the matrix -} - - -ConstGeneralMatrix::ConstGeneralMatrix(const GeneralMatrix& m) - : data(m.data), rows(m.rows), cols(m.cols), ld(m.ld) {} - -double ConstGeneralMatrix::getNormInf() const -{ - double norm = 0.0; - for (int i = 0; i < numRows(); i++) { - ConstVector rowi(data.base()+i, ld, cols); - double normi = rowi.getNorm1(); - if (norm < normi) - norm = normi; - } - return norm; -} - -double ConstGeneralMatrix::getNorm1() const -{ - double norm = 0.0; - for (int j = 0; j < numCols(); j++) { - ConstVector colj(data.base()+ld*j, 1, rows); - double normj = colj.getNorm1(); - if (norm < normj) - norm = normj; - } - return norm; -} - -void ConstGeneralMatrix::multVec(double a, Vector& x, double b, const ConstVector& d) const -{ - if (x.length() != rows || cols != d.length()) { - throw SYLV_MES_EXCEPTION("Wrong dimensions for vector multiply."); - } - if (rows > 0) { - blas_int mm = rows; - blas_int nn = cols; - double alpha = b; - blas_int lda = ld; - blas_int incx = d.skip(); - double beta = a; - blas_int incy = x.skip(); - dgemv("N", &mm, &nn, &alpha, data.base(), &lda, d.base(), &incx, - &beta, x.base(), &incy); - } - -} - -void ConstGeneralMatrix::multVecTrans(double a, Vector& x, double b, - const ConstVector& d) const -{ - if (x.length() != cols || rows != d.length()) { - throw SYLV_MES_EXCEPTION("Wrong dimensions for vector multiply."); - } - if (rows > 0) { - blas_int mm = rows; - blas_int nn = cols; - double alpha = b; - blas_int lda = rows; - blas_int incx = d.skip(); - double beta = a; - blas_int incy = x.skip(); - dgemv("T", &mm, &nn, &alpha, data.base(), &lda, d.base(), &incx, - &beta, x.base(), &incy); - } -} - -/* m = inv(this)*m */ -void ConstGeneralMatrix::multInvLeft(const char* trans, int mrows, int mcols, int mld, double* d) const -{ - if (rows != cols) { - throw SYLV_MES_EXCEPTION("The matrix is not square for inversion."); - } - if (cols != mrows) { - throw SYLV_MES_EXCEPTION("Wrong dimensions for matrix inverse mutliply."); - } - - if (rows > 0) { - GeneralMatrix inv(*this); - lapack_int* ipiv = new lapack_int[rows]; - lapack_int info; - lapack_int rows2 = rows, mcols2 = mcols, mld2 = mld; - dgetrf(&rows2, &rows2, inv.getData().base(), &rows2, ipiv, &info); - dgetrs(trans, &rows2, &mcols2, inv.base(), &rows2, ipiv, d, - &mld2, &info); - delete [] ipiv; - } -} - -/* m = inv(this)*m */ -void ConstGeneralMatrix::multInvLeft(GeneralMatrix& m) const -{ - multInvLeft("N", m.numRows(), m.numCols(), m.getLD(), m.getData().base()); -} - -/* m = inv(this')*m */ -void ConstGeneralMatrix::multInvLeftTrans(GeneralMatrix& m) const -{ - multInvLeft("T", m.numRows(), m.numCols(), m.getLD(), m.getData().base()); -} - -/* d = inv(this)*d */ -void ConstGeneralMatrix::multInvLeft(Vector& d) const -{ - if (d.skip() != 1) { - throw SYLV_MES_EXCEPTION("Skip!=1 not implemented in ConstGeneralMatrix::multInvLeft(Vector&)"); - } - - multInvLeft("N", d.length(), 1, d.length(), d.base()); -} - -/* d = inv(this')*d */ -void ConstGeneralMatrix::multInvLeftTrans(Vector& d) const -{ - if (d.skip() != 1) { - throw SYLV_MES_EXCEPTION("Skip!=1 not implemented in ConstGeneralMatrix::multInvLeft(Vector&)"); - } - - multInvLeft("T", d.length(), 1, d.length(), d.base()); -} - - -bool ConstGeneralMatrix::isFinite() const -{ - for (int i = 0; i < numRows(); i++) - for (int j = 0; j < numCols(); j++) - if (! std::isfinite(get(i,j))) - return false; - return true; -} - -bool ConstGeneralMatrix::isZero() const -{ - for (int i = 0; i < numRows(); i++) - for (int j = 0; j < numCols(); j++) - if (get(i,j) != 0.0) - return false; - return true; -} - -void ConstGeneralMatrix::print() const -{ - printf("rows=%d, cols=%d\n",rows, cols); - for (int i = 0; i < rows; i++) { - printf("row %d:\n",i); - for (int j = 0; j < cols; j++) { - printf("%6.3g ",get(i,j)); - } - printf("\n"); - } -} - -void SVDDecomp::construct(const GeneralMatrix& A) -{ - // quick exit if empty matrix - if (minmn == 0) { - U.unit(); - VT.unit(); - conv = true; - return; - } - - // make copy of the matrix - GeneralMatrix AA(A); - - lapack_int m = AA.numRows(); - lapack_int n = AA.numCols(); - double* a = AA.base(); - lapack_int lda = AA.getLD(); - double* s = sigma.base(); - double* u = U.base(); - lapack_int ldu = U.getLD(); - double* vt = VT.base(); - lapack_int ldvt = VT.getLD(); - double tmpwork; - lapack_int lwork = -1; - lapack_int info; - - lapack_int* iwork = new lapack_int[8*minmn]; - // query for optimal lwork - dgesdd("A", &m, &n, a, &lda, s, u, &ldu, vt, &ldvt, &tmpwork, - &lwork, iwork, &info); - lwork = (lapack_int)tmpwork; - Vector work(lwork); - // do the decomposition - dgesdd("A", &m, &n, a, &lda, s, u, &ldu, vt, &ldvt, work.base(), - &lwork, iwork, &info); - delete [] iwork; - if (info < 0) - throw SYLV_MES_EXCEPTION("Internal error in SVDDecomp constructor"); - if (info == 0) - conv = true; -} - -void SVDDecomp::solve(const GeneralMatrix& B, GeneralMatrix& X) const -{ - if (B.numRows() != U.numRows()) - throw SYLV_MES_EXCEPTION("Incompatible number of rows "); - - // reciprocal condition number for determination of zeros in the - // end of sigma - double rcond = 1e-13; - - // solve U: B = U^T*B - GeneralMatrix UTB(U, "trans", B); - // determine nz=number of zeros in the end of sigma - int nz = 0; - while (nz < minmn && sigma[minmn-1-nz] < rcond*sigma[0]) - nz++; - // take relevant B for sigma inversion - int m = U.numRows(); - int n = VT.numCols(); - GeneralMatrix Bprime(UTB, m-minmn, 0, minmn-nz, B.numCols()); - // solve sigma - for (int i = 0; i < minmn-nz; i++) - Vector(i, Bprime).mult(1.0/sigma[i]); - // solve VT - X.zeros(); - //- copy Bprime to right place of X - for (int i = 0; i < minmn-nz; i++) - Vector(n-minmn+i, X) = ConstVector(i, Bprime); - //- multiply with VT - X.multLeftTrans(VT); -} diff --git a/dynare++/sylv/cc/GeneralMatrix.h b/dynare++/sylv/cc/GeneralMatrix.hh similarity index 99% rename from dynare++/sylv/cc/GeneralMatrix.h rename to dynare++/sylv/cc/GeneralMatrix.hh index 494dcf40677956d9df97d4eada2e5a84b6efc373..b85dbb4da9e169442756d04addc1ce8d5600296a 100644 --- a/dynare++/sylv/cc/GeneralMatrix.h +++ b/dynare++/sylv/cc/GeneralMatrix.hh @@ -5,7 +5,7 @@ #ifndef GENERAL_MATRIX_H #define GENERAL_MATRIX_H -#include "Vector.h" +#include "Vector.hh" #include <algorithm> diff --git a/dynare++/sylv/cc/GeneralSylvester.cc b/dynare++/sylv/cc/GeneralSylvester.cc new file mode 100644 index 0000000000000000000000000000000000000000..930b6adb786e3b54cf0bc32b6e7cdbab6fc431f9 --- /dev/null +++ b/dynare++/sylv/cc/GeneralSylvester.cc @@ -0,0 +1,141 @@ +/* $Header: /var/lib/cvs/dynare_cpp/sylv/cc/GeneralSylvester.cpp,v 1.1.1.1 2004/06/04 13:00:20 kamenik Exp $ */ + +/* Tag $Name: $ */ + +#include "GeneralSylvester.hh" +#include "SchurDecomp.hh" +#include "SylvException.hh" +#include "TriangularSylvester.hh" +#include "IterativeSylvester.hh" + +#include <ctime> + +GeneralSylvester::GeneralSylvester(int ord, int n, int m, int zero_cols, + const double *da, const double *db, + const double *dc, const double *dd, + const SylvParams &ps) + : pars(ps), + mem_driver(pars, 1, m, n, ord), order(ord), a(da, n), + b(db, n, n-zero_cols), c(dc, m), d(dd, n, power(m, order)), + solved(false) +{ + init(); +} + +GeneralSylvester::GeneralSylvester(int ord, int n, int m, int zero_cols, + const double *da, const double *db, + const double *dc, double *dd, + const SylvParams &ps) + : pars(ps), + mem_driver(pars, 0, m, n, ord), order(ord), a(da, n), + b(db, n, n-zero_cols), c(dc, m), d(dd, n, power(m, order)), + solved(false) +{ + init(); +} + +GeneralSylvester::GeneralSylvester(int ord, int n, int m, int zero_cols, + const double *da, const double *db, + const double *dc, const double *dd, + bool alloc_for_check) + : pars(alloc_for_check), + mem_driver(pars, 1, m, n, ord), order(ord), a(da, n), + b(db, n, n-zero_cols), c(dc, m), d(dd, n, power(m, order)), + solved(false) +{ + init(); +} + +GeneralSylvester::GeneralSylvester(int ord, int n, int m, int zero_cols, + const double *da, const double *db, + const double *dc, double *dd, + bool alloc_for_check) + : pars(alloc_for_check), + mem_driver(pars, 0, m, n, ord), order(ord), a(da, n), + b(db, n, n-zero_cols), c(dc, m), d(dd, n, power(m, order)), + solved(false) +{ + init(); +} + +void +GeneralSylvester::init() +{ + GeneralMatrix ainvb(b); + double rcond1; + double rcondinf; + a.multInvLeft2(ainvb, d, rcond1, rcondinf); + pars.rcondA1 = rcond1; + pars.rcondAI = rcondinf; + bdecomp = new SchurDecompZero(ainvb); + cdecomp = new SimilarityDecomp(c.getData().base(), c.numRows(), *(pars.bs_norm)); + cdecomp->check(pars, c); + cdecomp->infoToPars(pars); + if (*(pars.method) == SylvParams::recurse) + sylv = new TriangularSylvester(*bdecomp, *cdecomp); + else + sylv = new IterativeSylvester(*bdecomp, *cdecomp); +} + +void +GeneralSylvester::solve() +{ + if (solved) + throw SYLV_MES_EXCEPTION("Attempt to run solve() more than once."); + + mem_driver.setStackMode(true); + + clock_t start = clock(); + // multiply d + d.multLeftITrans(bdecomp->getQ()); + d.multRightKron(cdecomp->getQ(), order); + // convert to KronVector + KronVector dkron(d.getData(), getM(), getN(), order); + // solve + sylv->solve(pars, dkron); + // multiply d back + d.multLeftI(bdecomp->getQ()); + d.multRightKron(cdecomp->getInvQ(), order); + clock_t end = clock(); + pars.cpu_time = ((double) (end-start))/CLOCKS_PER_SEC; + + mem_driver.setStackMode(false); + + solved = true; +} + +void +GeneralSylvester::check(const double *ds) +{ + if (!solved) + throw SYLV_MES_EXCEPTION("Cannot run check on system, which is not solved yet."); + + mem_driver.setStackMode(true); + + // calculate xcheck = AX+BXC^i-D + SylvMatrix dcheck(d.numRows(), d.numCols()); + dcheck.multLeft(b.numRows()-b.numCols(), b, d); + dcheck.multRightKron(c, order); + dcheck.multAndAdd(a, d); + ConstVector dv(ds, d.numRows()*d.numCols()); + dcheck.getData().add(-1.0, dv); + // calculate relative norms + pars.mat_err1 = dcheck.getNorm1()/d.getNorm1(); + pars.mat_errI = dcheck.getNormInf()/d.getNormInf(); + pars.mat_errF = dcheck.getData().getNorm()/d.getData().getNorm(); + pars.vec_err1 = dcheck.getData().getNorm1()/d.getData().getNorm1(); + pars.vec_errI = dcheck.getData().getMax()/d.getData().getMax(); + + mem_driver.setStackMode(false); +} + +GeneralSylvester::~GeneralSylvester() +{ + delete bdecomp; + delete cdecomp; + delete sylv; +} + +// Local Variables: +// mode:C++ +// End: diff --git a/dynare++/sylv/cc/GeneralSylvester.cpp b/dynare++/sylv/cc/GeneralSylvester.cpp deleted file mode 100644 index 81453a91a8431d91a4389872161388b113472bae..0000000000000000000000000000000000000000 --- a/dynare++/sylv/cc/GeneralSylvester.cpp +++ /dev/null @@ -1,138 +0,0 @@ -/* $Header: /var/lib/cvs/dynare_cpp/sylv/cc/GeneralSylvester.cpp,v 1.1.1.1 2004/06/04 13:00:20 kamenik Exp $ */ - -/* Tag $Name: $ */ - -#include "GeneralSylvester.h" -#include "SchurDecomp.h" -#include "SylvException.h" -#include "TriangularSylvester.h" -#include "IterativeSylvester.h" - -#include <ctime> - -GeneralSylvester::GeneralSylvester(int ord, int n, int m, int zero_cols, - const double* da, const double* db, - const double* dc, const double* dd, - const SylvParams& ps) - : pars(ps), - mem_driver(pars, 1, m, n, ord), order(ord), a(da, n), - b(db, n, n-zero_cols), c(dc, m), d(dd, n, power(m, order)), - solved(false) -{ - init(); -} - -GeneralSylvester::GeneralSylvester(int ord, int n, int m, int zero_cols, - const double* da, const double* db, - const double* dc, double* dd, - const SylvParams& ps) - : pars(ps), - mem_driver(pars, 0, m, n, ord), order(ord), a(da, n), - b(db, n, n-zero_cols), c(dc, m), d(dd, n, power(m, order)), - solved(false) -{ - init(); -} - -GeneralSylvester::GeneralSylvester(int ord, int n, int m, int zero_cols, - const double* da, const double* db, - const double* dc, const double* dd, - bool alloc_for_check) - : pars(alloc_for_check), - mem_driver(pars, 1, m, n, ord), order(ord), a(da, n), - b(db, n, n-zero_cols), c(dc, m), d(dd, n, power(m, order)), - solved(false) -{ - init(); -} - -GeneralSylvester::GeneralSylvester(int ord, int n, int m, int zero_cols, - const double* da, const double* db, - const double* dc, double* dd, - bool alloc_for_check) - : pars(alloc_for_check), - mem_driver(pars, 0, m, n, ord), order(ord), a(da, n), - b(db, n, n-zero_cols), c(dc, m), d(dd, n, power(m, order)), - solved(false) -{ - init(); -} - -void GeneralSylvester::init() -{ - GeneralMatrix ainvb(b); - double rcond1; - double rcondinf; - a.multInvLeft2(ainvb, d, rcond1, rcondinf); - pars.rcondA1 = rcond1; - pars.rcondAI = rcondinf; - bdecomp = new SchurDecompZero(ainvb); - cdecomp = new SimilarityDecomp(c.getData().base(), c.numRows(), *(pars.bs_norm)); - cdecomp->check(pars, c); - cdecomp->infoToPars(pars); - if (*(pars.method) == SylvParams::recurse) - sylv = new TriangularSylvester(*bdecomp, *cdecomp); - else - sylv = new IterativeSylvester(*bdecomp, *cdecomp); -} - -void GeneralSylvester::solve() -{ - if (solved) - throw SYLV_MES_EXCEPTION("Attempt to run solve() more than once."); - - mem_driver.setStackMode(true); - - clock_t start = clock(); - // multiply d - d.multLeftITrans(bdecomp->getQ()); - d.multRightKron(cdecomp->getQ(), order); - // convert to KronVector - KronVector dkron(d.getData(), getM(), getN(), order); - // solve - sylv->solve(pars, dkron); - // multiply d back - d.multLeftI(bdecomp->getQ()); - d.multRightKron(cdecomp->getInvQ(), order); - clock_t end = clock(); - pars.cpu_time = ((double)(end-start))/CLOCKS_PER_SEC; - - mem_driver.setStackMode(false); - - solved = true; -} - -void GeneralSylvester::check(const double* ds) -{ - if (!solved) - throw SYLV_MES_EXCEPTION("Cannot run check on system, which is not solved yet."); - - mem_driver.setStackMode(true); - - // calculate xcheck = AX+BXC^i-D - SylvMatrix dcheck(d.numRows(), d.numCols()); - dcheck.multLeft(b.numRows()-b.numCols(), b, d); - dcheck.multRightKron(c, order); - dcheck.multAndAdd(a,d); - ConstVector dv(ds, d.numRows()*d.numCols()); - dcheck.getData().add(-1.0, dv); - // calculate relative norms - pars.mat_err1 = dcheck.getNorm1()/d.getNorm1(); - pars.mat_errI = dcheck.getNormInf()/d.getNormInf(); - pars.mat_errF = dcheck.getData().getNorm()/d.getData().getNorm(); - pars.vec_err1 = dcheck.getData().getNorm1()/d.getData().getNorm1(); - pars.vec_errI = dcheck.getData().getMax()/d.getData().getMax(); - - mem_driver.setStackMode(false); -} - -GeneralSylvester::~GeneralSylvester() -{ - delete bdecomp; - delete cdecomp; - delete sylv; -} - -// Local Variables: -// mode:C++ -// End: diff --git a/dynare++/sylv/cc/GeneralSylvester.h b/dynare++/sylv/cc/GeneralSylvester.hh similarity index 94% rename from dynare++/sylv/cc/GeneralSylvester.h rename to dynare++/sylv/cc/GeneralSylvester.hh index 9e2603f48ce1580861d224b14738c7ca6cb6223a..c1a596f158b1007d827839a90d6368cdc84e1fc0 100644 --- a/dynare++/sylv/cc/GeneralSylvester.h +++ b/dynare++/sylv/cc/GeneralSylvester.hh @@ -5,10 +5,10 @@ #ifndef GENERAL_SYLVESTER_H #define GENERAL_SYLVESTER_H -#include "SylvMatrix.h" -#include "SylvMemory.h" -#include "SimilarityDecomp.h" -#include "SylvesterSolver.h" +#include "SylvMatrix.hh" +#include "SylvMemory.hh" +#include "SimilarityDecomp.hh" +#include "SylvesterSolver.hh" class GeneralSylvester { diff --git a/dynare++/sylv/cc/IterativeSylvester.cc b/dynare++/sylv/cc/IterativeSylvester.cc new file mode 100644 index 0000000000000000000000000000000000000000..92fe05ab4885174dd6facecb354b46afd1f21fc5 --- /dev/null +++ b/dynare++/sylv/cc/IterativeSylvester.cc @@ -0,0 +1,57 @@ +/* $Header: /var/lib/cvs/dynare_cpp/sylv/cc/IterativeSylvester.cpp,v 1.1.1.1 2004/06/04 13:00:20 kamenik Exp $ */ + +/* Tag $Name: $ */ + +#include "IterativeSylvester.hh" +#include "KronUtils.hh" + +void +IterativeSylvester::solve(SylvParams &pars, KronVector &x) const +{ + int max_steps = *(pars.max_num_iter); + int steps = 1; + double max_norm = *(pars.convergence_tol); + double norm = performFirstStep(x); + + QuasiTriangular *kpow = matrixK->clone(); + QuasiTriangular *fpow = matrixF->clone(); + while (steps < max_steps &&norm > max_norm) + { + kpow->multRight(SqSylvMatrix(*kpow)); // be careful to make copy + fpow->multRight(SqSylvMatrix(*fpow)); // also here + norm = performStep(*kpow, *fpow, x); + steps++; + } + + delete fpow; + delete kpow; + + pars.converged = (norm <= max_norm); + pars.iter_last_norm = norm; + pars.num_iter = steps; +} + +double +IterativeSylvester::performFirstStep(KronVector &x) const +{ + KronVector xtmp((const KronVector &)x); + KronUtils::multKron(*matrixF, *matrixK, xtmp); + x.add(-1., xtmp); + double norm = xtmp.getMax(); + return norm; +} + +double +IterativeSylvester::performStep(const QuasiTriangular &k, const QuasiTriangular &f, + KronVector &x) +{ + KronVector xtmp((const KronVector &)x); + KronUtils::multKron(f, k, xtmp); + x.add(1.0, xtmp); + double norm = xtmp.getMax(); + return norm; +} + +// Local Variables: +// mode:C++ +// End: diff --git a/dynare++/sylv/cc/IterativeSylvester.cpp b/dynare++/sylv/cc/IterativeSylvester.cpp deleted file mode 100644 index e585f655af909abb7df393dc0b6e98106b572067..0000000000000000000000000000000000000000 --- a/dynare++/sylv/cc/IterativeSylvester.cpp +++ /dev/null @@ -1,53 +0,0 @@ -/* $Header: /var/lib/cvs/dynare_cpp/sylv/cc/IterativeSylvester.cpp,v 1.1.1.1 2004/06/04 13:00:20 kamenik Exp $ */ - -/* Tag $Name: $ */ - -#include "IterativeSylvester.h" -#include "KronUtils.h" - -void IterativeSylvester::solve(SylvParams& pars, KronVector& x) const -{ - int max_steps = *(pars.max_num_iter); - int steps = 1; - double max_norm = *(pars.convergence_tol); - double norm = performFirstStep(x); - - QuasiTriangular* kpow = matrixK->clone(); - QuasiTriangular* fpow = matrixF->clone(); - while (steps < max_steps && norm > max_norm) { - kpow->multRight(SqSylvMatrix(*kpow)); // be careful to make copy - fpow->multRight(SqSylvMatrix(*fpow)); // also here - norm = performStep(*kpow, *fpow, x); - steps++; - } - - delete fpow; - delete kpow; - - pars.converged = (norm <= max_norm); - pars.iter_last_norm = norm; - pars.num_iter = steps; -} - -double IterativeSylvester::performFirstStep(KronVector& x) const -{ - KronVector xtmp((const KronVector&)x); - KronUtils::multKron(*matrixF, *matrixK, xtmp); - x.add(-1., xtmp); - double norm = xtmp.getMax(); - return norm; -} - -double IterativeSylvester::performStep(const QuasiTriangular& k, const QuasiTriangular& f, - KronVector& x) -{ - KronVector xtmp((const KronVector&)x); - KronUtils::multKron(f, k, xtmp); - x.add(1.0, xtmp); - double norm = xtmp.getMax(); - return norm; -} - -// Local Variables: -// mode:C++ -// End: diff --git a/dynare++/sylv/cc/IterativeSylvester.h b/dynare++/sylv/cc/IterativeSylvester.hh similarity index 89% rename from dynare++/sylv/cc/IterativeSylvester.h rename to dynare++/sylv/cc/IterativeSylvester.hh index 6e30d75d0939c1054176e9f1efcb81136f9ea3eb..3163f8fbb42d123d2424d18c12317eb1803c25fb 100644 --- a/dynare++/sylv/cc/IterativeSylvester.h +++ b/dynare++/sylv/cc/IterativeSylvester.hh @@ -5,10 +5,10 @@ #ifndef ITERATIVE_SYLVESTER_H #define ITERATIVE_SYLVESTER_H -#include "SylvesterSolver.h" -#include "KronVector.h" -#include "QuasiTriangular.h" -#include "SimilarityDecomp.h" +#include "SylvesterSolver.hh" +#include "KronVector.hh" +#include "QuasiTriangular.hh" +#include "SimilarityDecomp.hh" class IterativeSylvester : public SylvesterSolver { diff --git a/dynare++/sylv/cc/KronUtils.cc b/dynare++/sylv/cc/KronUtils.cc new file mode 100644 index 0000000000000000000000000000000000000000..b3b9740bc9de6f12020d2ebf9ad6c05e034bb7e6 --- /dev/null +++ b/dynare++/sylv/cc/KronUtils.cc @@ -0,0 +1,73 @@ +/* $Header: /var/lib/cvs/dynare_cpp/sylv/cc/KronUtils.cpp,v 1.1.1.1 2004/06/04 13:00:31 kamenik Exp $ */ + +/* Tag $Name: $ */ + +#include "KronUtils.hh" + +void +KronUtils::multAtLevel(int level, const QuasiTriangular &t, + KronVector &x) +{ + if (0 < level && level < x.getDepth()) + { + for (int i = 0; i < x.getM(); i++) + { + KronVector xi(x, i); + multAtLevel(level, t, xi); + } + } + else if (0 == level && 0 < x.getDepth()) + { + GeneralMatrix tmp(x.base(), x.getN(), power(x.getM(), x.getDepth())); + t.multLeftOther(tmp); + } + else if (0 == level && 0 == x.getDepth()) + { + Vector b((const Vector &)x); + t.multVec(x, b); + } + else // 0 < level == depth + { + t.multKron(x); + } +} + +void +KronUtils::multAtLevelTrans(int level, const QuasiTriangular &t, + KronVector &x) +{ + if (0 < level && level < x.getDepth()) + { + for (int i = 0; i < x.getM(); i++) + { + KronVector xi(x, i); + multAtLevelTrans(level, t, xi); + } + } + else if (0 == level && 0 < x.getDepth()) + { + GeneralMatrix tmp(x.base(), x.getN(), power(x.getM(), x.getDepth())); + t.multLeftOtherTrans(tmp); + } + else if (level == 0 && 0 == x.getDepth()) + { + Vector b((const Vector &)x); + t.multVecTrans(x, b); + } + else // 0 < level == depth + { + t.multKronTrans(x); + } +} + +void +KronUtils::multKron(const QuasiTriangular &f, const QuasiTriangular &k, + KronVector &x) +{ + multAtLevel(0, k, x); + if (x.getDepth() > 0) + { + for (int level = 1; level <= x.getDepth(); level++) + multAtLevelTrans(level, f, x); + } +} diff --git a/dynare++/sylv/cc/KronUtils.cpp b/dynare++/sylv/cc/KronUtils.cpp deleted file mode 100644 index 013d16520537eba421a47a4edf6e9d592f6d723b..0000000000000000000000000000000000000000 --- a/dynare++/sylv/cc/KronUtils.cpp +++ /dev/null @@ -1,53 +0,0 @@ -/* $Header: /var/lib/cvs/dynare_cpp/sylv/cc/KronUtils.cpp,v 1.1.1.1 2004/06/04 13:00:31 kamenik Exp $ */ - -/* Tag $Name: $ */ - -#include "KronUtils.h" - -void KronUtils::multAtLevel(int level, const QuasiTriangular& t, - KronVector& x) -{ - if (0 < level && level < x.getDepth()) { - for (int i = 0; i < x.getM(); i++) { - KronVector xi(x, i); - multAtLevel(level, t, xi); - } - } else if (0 == level && 0 < x.getDepth()) { - GeneralMatrix tmp(x.base(), x.getN(), power(x.getM(),x.getDepth())); - t.multLeftOther(tmp); - } else if (0 == level && 0 == x.getDepth()) { - Vector b((const Vector&)x); - t.multVec(x,b); - } else { // 0 < level == depth - t.multKron(x); - } -} - -void KronUtils::multAtLevelTrans(int level, const QuasiTriangular& t, - KronVector& x) -{ - if (0 < level && level < x.getDepth()) { - for (int i = 0; i < x.getM(); i++) { - KronVector xi(x, i); - multAtLevelTrans(level, t, xi); - } - } else if (0 == level && 0 < x.getDepth()) { - GeneralMatrix tmp(x.base(), x.getN(), power(x.getM(),x.getDepth())); - t.multLeftOtherTrans(tmp); - } else if (level == 0 && 0 == x.getDepth()) { - Vector b((const Vector&)x); - t.multVecTrans(x,b); - } else { // 0 < level == depth - t.multKronTrans(x); - } -} - -void KronUtils::multKron(const QuasiTriangular& f, const QuasiTriangular& k, - KronVector& x) -{ - multAtLevel(0, k, x); - if (x.getDepth() > 0) { - for (int level = 1; level <= x.getDepth(); level++) - multAtLevelTrans(level, f, x); - } -} diff --git a/dynare++/sylv/cc/KronUtils.h b/dynare++/sylv/cc/KronUtils.hh similarity index 94% rename from dynare++/sylv/cc/KronUtils.h rename to dynare++/sylv/cc/KronUtils.hh index a0d2339f065bb9fe59a6c6b007cc05387549a0a4..0f4c11f2b8f1bd899228a03963b9c6b4c8e7c95d 100644 --- a/dynare++/sylv/cc/KronUtils.h +++ b/dynare++/sylv/cc/KronUtils.hh @@ -5,8 +5,8 @@ #ifndef KRON_UTILS_H #define KRON_UTILS_H -#include "KronVector.h" -#include "QuasiTriangular.h" +#include "KronVector.hh" +#include "QuasiTriangular.hh" class KronUtils { diff --git a/dynare++/sylv/cc/KronVector.cc b/dynare++/sylv/cc/KronVector.cc new file mode 100644 index 0000000000000000000000000000000000000000..7897d571e8883a028ddef7f5660a99b310fc3bd7 --- /dev/null +++ b/dynare++/sylv/cc/KronVector.cc @@ -0,0 +1,121 @@ +/* $Header: /var/lib/cvs/dynare_cpp/sylv/cc/KronVector.cpp,v 1.1.1.1 2004/06/04 13:00:31 kamenik Exp $ */ + +/* Tag $Name: $ */ + +#include "KronVector.hh" +#include "SylvException.hh" + +int +power(int m, int depth) +{ + int p = 1; + for (int i = 0; i < depth; i++) + { + p *= m; + } + return p; +} + +KronVector::KronVector(int mm, int nn, int dp) + : Vector(power(mm, dp)*nn), m(mm), n(nn), depth(dp) +{ +} + +KronVector::KronVector(Vector &v, int mm, int nn, int dp) + : Vector(v), m(mm), n(nn), depth(dp) +{ + len = power(m, depth)*n; + if (v.length() != length()) + { + throw SYLV_MES_EXCEPTION("Bad conversion KronVector from Vector."); + } +} + +KronVector::KronVector(KronVector &v, int i) + : Vector(v, i*power(v.m, v.depth-1)*v.n, power(v.m, v.depth-1)*v.n), m(v.m), n(v.n), + depth(v.depth-1) +{ + if (depth < 0) + { + throw SYLV_MES_EXCEPTION("Bad KronVector pick, depth < 0."); + } +} + +KronVector::KronVector(const ConstKronVector &v) + : Vector(v.length()), m(v.getM()), n(v.getN()), depth(v.getDepth()) +{ + Vector::operator=(v); +} + +const KronVector & +KronVector::operator=(const ConstKronVector &v) +{ + Vector::operator=(v); + m = v.getM(); + n = v.getN(); + depth = v.getDepth(); + return *this; +} + +const KronVector & +KronVector::operator=(const Vector &v) +{ + if (length() != v.length()) + { + throw SYLV_MES_EXCEPTION("Wrong lengths for vector operator =."); + } + Vector::operator=(v); + return *this; +} + +ConstKronVector::ConstKronVector(const KronVector &v) + : ConstVector(v), m(v.getM()), n(v.getN()), depth(v.getDepth()) +{ +} + +ConstKronVector::ConstKronVector(const ConstKronVector &v) + : ConstVector(power(v.getM(), v.getDepth())*v.getN()), m(v.getM()), n(v.getN()), + depth(v.getDepth()) +{ +} + +ConstKronVector::ConstKronVector(const Vector &v, int mm, int nn, int dp) + : ConstVector(v), m(mm), n(nn), depth(dp) +{ + len = power(m, depth)*n; + if (v.length() != length()) + { + throw SYLV_MES_EXCEPTION("Bad conversion KronVector from Vector."); + } +} + +ConstKronVector::ConstKronVector(const ConstVector &v, int mm, int nn, int dp) + : ConstVector(v), m(mm), n(nn), depth(dp) +{ + len = power(m, depth)*n; + if (v.length() != length()) + { + throw SYLV_MES_EXCEPTION("Bad conversion KronVector from Vector."); + } +} + +ConstKronVector::ConstKronVector(const KronVector &v, int i) + : ConstVector(v, i*power(v.getM(), v.getDepth()-1)*v.getN(), + power(v.getM(), v.getDepth()-1)*v.getN()), + m(v.getM()), n(v.getN()), depth(v.getDepth()-1) +{ + if (depth < 0) + { + throw SYLV_MES_EXCEPTION("Bad KronVector pick, depth < 0."); + } +} + +ConstKronVector::ConstKronVector(const ConstKronVector &v, int i) + : ConstVector(v, i*power(v.m, v.depth-1)*v.n, power(v.m, v.depth-1)*v.n), + m(v.getM()), n(v.getN()), depth(v.getDepth()-1) +{ + if (depth < 0) + { + throw SYLV_MES_EXCEPTION("Bad KronVector pick, depth < 0."); + } +} diff --git a/dynare++/sylv/cc/KronVector.cpp b/dynare++/sylv/cc/KronVector.cpp deleted file mode 100644 index 71da28f7b6150b00167f83eb96ef0f17ee50e75a..0000000000000000000000000000000000000000 --- a/dynare++/sylv/cc/KronVector.cpp +++ /dev/null @@ -1,109 +0,0 @@ -/* $Header: /var/lib/cvs/dynare_cpp/sylv/cc/KronVector.cpp,v 1.1.1.1 2004/06/04 13:00:31 kamenik Exp $ */ - -/* Tag $Name: $ */ - -#include "KronVector.h" -#include "SylvException.h" - -int power(int m, int depth) -{ - int p = 1; - for (int i = 0; i < depth; i++) { - p *= m; - } - return p; -} - -KronVector::KronVector(int mm, int nn, int dp) - : Vector(power(mm,dp)*nn), m(mm), n(nn), depth(dp) -{} - -KronVector::KronVector(Vector& v, int mm, int nn, int dp) - : Vector(v), m(mm), n(nn), depth(dp) -{ - len = power(m,depth)*n; - if (v.length() != length()) { - throw SYLV_MES_EXCEPTION("Bad conversion KronVector from Vector."); - } -} - -KronVector::KronVector(KronVector& v, int i) - : Vector(v, i*power(v.m,v.depth-1)*v.n, power(v.m, v.depth-1)*v.n), m(v.m), n(v.n), - depth(v.depth-1) -{ - if (depth < 0) { - throw SYLV_MES_EXCEPTION("Bad KronVector pick, depth < 0."); - } -} - -KronVector::KronVector(const ConstKronVector& v) - : Vector(v.length()), m(v.getM()), n(v.getN()), depth(v.getDepth()) -{ - Vector::operator=(v); -} - -const KronVector& KronVector::operator=(const ConstKronVector& v) -{ - Vector::operator=(v); - m=v.getM(); - n=v.getN(); - depth = v.getDepth(); - return *this; -} - -const KronVector& KronVector::operator=(const Vector& v) -{ - if (length() != v.length()) { - throw SYLV_MES_EXCEPTION("Wrong lengths for vector operator =."); - } - Vector::operator=(v); - return *this; -} - - - -ConstKronVector::ConstKronVector(const KronVector& v) - : ConstVector(v), m(v.getM()), n(v.getN()), depth(v.getDepth()) -{} - -ConstKronVector::ConstKronVector(const ConstKronVector& v) - : ConstVector(power(v.getM(),v.getDepth())*v.getN()), m(v.getM()), n(v.getN()), - depth(v.getDepth()) -{} - -ConstKronVector::ConstKronVector(const Vector& v, int mm, int nn, int dp) - : ConstVector(v), m(mm), n(nn), depth(dp) -{ - len = power(m,depth)*n; - if (v.length() != length()) { - throw SYLV_MES_EXCEPTION("Bad conversion KronVector from Vector."); - } -} - -ConstKronVector::ConstKronVector(const ConstVector& v, int mm, int nn, int dp) - : ConstVector(v), m(mm), n(nn), depth(dp) -{ - len = power(m,depth)*n; - if (v.length() != length()) { - throw SYLV_MES_EXCEPTION("Bad conversion KronVector from Vector."); - } -} - -ConstKronVector::ConstKronVector(const KronVector& v, int i) - : ConstVector(v, i*power(v.getM(),v.getDepth()-1)*v.getN(), - power(v.getM(),v.getDepth()-1)*v.getN()), - m(v.getM()), n(v.getN()), depth(v.getDepth()-1) -{ - if (depth < 0) { - throw SYLV_MES_EXCEPTION("Bad KronVector pick, depth < 0."); - } -} - -ConstKronVector::ConstKronVector(const ConstKronVector& v, int i) - : ConstVector(v, i*power(v.m,v.depth-1)*v.n, power(v.m,v.depth-1)*v.n), - m(v.getM()), n(v.getN()), depth(v.getDepth()-1) -{ - if (depth < 0) { - throw SYLV_MES_EXCEPTION("Bad KronVector pick, depth < 0."); - } -} diff --git a/dynare++/sylv/cc/KronVector.h b/dynare++/sylv/cc/KronVector.hh similarity index 98% rename from dynare++/sylv/cc/KronVector.h rename to dynare++/sylv/cc/KronVector.hh index dc8b6fb919e4f8fe598935d0d3cae29d53a1879d..b381288368849b5d79e02322983e52ea58139ca9 100644 --- a/dynare++/sylv/cc/KronVector.h +++ b/dynare++/sylv/cc/KronVector.hh @@ -5,7 +5,7 @@ #ifndef KRON_VECTOR_H #define KRON_VECTOR_H -#include "Vector.h" +#include "Vector.hh" class ConstKronVector; diff --git a/dynare++/sylv/cc/Makefile.am b/dynare++/sylv/cc/Makefile.am index d84d3922e3c8bbed474cc5a10bc5229c2c0fe8ae..175e7f92ffb4fcdb3b86f7d3cb09a82bfb50440d 100644 --- a/dynare++/sylv/cc/Makefile.am +++ b/dynare++/sylv/cc/Makefile.am @@ -4,40 +4,40 @@ noinst_LIBRARIES = libsylv.a libsylv_a_CPPFLAGS = -I$(top_srcdir)/mex/sources libsylv_a_SOURCES = \ - IterativeSylvester.cpp \ - SylvMatrix.h \ - QuasiTriangular.cpp \ - QuasiTriangularZero.cpp \ - TriangularSylvester.h \ - GeneralMatrix.cpp \ - SylvMemory.h \ - SylvException.h \ - GeneralSylvester.cpp \ - GeneralMatrix.h \ - Vector.h \ - SchurDecompEig.h \ - QuasiTriangularZero.h \ - SimilarityDecomp.cpp \ - BlockDiagonal.h \ - SylvesterSolver.h \ - SylvException.cpp \ - SimilarityDecomp.h \ - IterativeSylvester.h \ - SchurDecompEig.cpp \ - KronUtils.h \ - Vector.cpp \ - TriangularSylvester.cpp \ - GeneralSylvester.h \ - SylvParams.cpp \ - SchurDecomp.h \ - SymSchurDecomp.h \ - BlockDiagonal.cpp \ - SylvParams.h \ - KronVector.cpp \ - SylvMemory.cpp \ - SymSchurDecomp.cpp \ - SylvMatrix.cpp \ - QuasiTriangular.h \ - SchurDecomp.cpp \ - KronVector.h \ - KronUtils.cpp + BlockDiagonal.cc \ + BlockDiagonal.hh \ + GeneralMatrix.cc \ + GeneralMatrix.hh \ + GeneralSylvester.cc \ + GeneralSylvester.hh \ + IterativeSylvester.cc \ + IterativeSylvester.hh \ + KronUtils.cc \ + KronUtils.hh \ + KronVector.cc \ + KronVector.hh \ + QuasiTriangular.cc \ + QuasiTriangular.hh \ + QuasiTriangularZero.cc \ + QuasiTriangularZero.hh \ + SchurDecomp.cc \ + SchurDecomp.hh \ + SchurDecompEig.cc \ + SchurDecompEig.hh \ + SimilarityDecomp.cc \ + SimilarityDecomp.hh \ + SylvException.cc \ + SylvException.hh \ + SylvMatrix.cc \ + SylvMatrix.hh \ + SylvMemory.cc \ + SylvMemory.hh \ + SylvParams.cc \ + SylvParams.hh \ + SylvesterSolver.hh \ + SymSchurDecomp.cc \ + SymSchurDecomp.hh \ + TriangularSylvester.cc \ + TriangularSylvester.hh \ + Vector.cc \ + Vector.hh diff --git a/dynare++/sylv/cc/QuasiTriangular.cc b/dynare++/sylv/cc/QuasiTriangular.cc new file mode 100644 index 0000000000000000000000000000000000000000..ef502b50ad2a9814cdcdb92be87956f8789c7196 --- /dev/null +++ b/dynare++/sylv/cc/QuasiTriangular.cc @@ -0,0 +1,773 @@ +/* $Header: /var/lib/cvs/dynare_cpp/sylv/cc/QuasiTriangular.cpp,v 1.1.1.1 2004/06/04 13:00:31 kamenik Exp $ */ + +/* Tag $Name: $ */ + +#include "QuasiTriangular.hh" +#include "SylvException.hh" +#include "SchurDecomp.hh" + +#include <dynblas.h> + +#include <cstdio> +#include <cmath> + +using namespace std; + +double +DiagonalBlock::getDeterminant() const +{ + return (*alpha)*(*alpha) + getSBeta(); +} + +double +DiagonalBlock::getSBeta() const +{ + return -(*beta1)*(*beta2); +} + +double +DiagonalBlock::getSize() const +{ + if (real) + return abs(*alpha); + else + return sqrt(getDeterminant()); +} + +// this function makes Diagonal inconsistent, it should only be used +// on temorary matrices, which will not be used any more, e.g. in +// QuasiTriangular::solve (we need fast performance) +void +DiagonalBlock::setReal() +{ + *beta1 = 0; + *beta2 = 0; + real = true; +} + +void +DiagonalBlock::checkBlock(const double *d, int d_size) +{ + const double *a1 = d + jbar*d_size+jbar; + const double *b1 = a1 + d_size; + const double *b2 = a1 + 1; + const double *a2 = b1 + 1; + if (a1 != alpha.a1) + throw SYLV_MES_EXCEPTION("Bad alpha1."); + if (!real && b1 != beta1) + throw SYLV_MES_EXCEPTION("Bad beta1."); + if (!real && b2 != beta2) + throw SYLV_MES_EXCEPTION("Bad beta2."); + if (!real && a2 != alpha.a2) + throw SYLV_MES_EXCEPTION("Bad alpha2."); +} + +Diagonal::Diagonal(double *data, int d_size) +{ + int nc = getNumComplex(data, d_size); // return nc <= d_size/2 + num_all = d_size - nc; + num_real = d_size - 2*nc; + + int jbar = 0; + int j = 0; + while (j < num_all) + { + int id = jbar*d_size + jbar; // index of diagonal block in data + int ill = id + 1; // index of element below the diagonal + int iur = id + d_size; // index of element right to diagonal + int idd = id + d_size + 1; // index of element next on diagonal + if ((jbar < d_size-1) && !isZero(data[ill])) + { + // it is not last column and we have nonzero below diagonal + DiagonalBlock b(jbar, false, &data[id], &data[idd], + &data[iur], &data[ill]); + blocks.push_back(b); + jbar++; + } + else + { + // it is last column or we have zero below diagonal + DiagonalBlock b(jbar, true, &data[id], &data[id], NULL, NULL); + blocks.push_back(b); + } + jbar++; + j++; + } +} + +Diagonal::Diagonal(double *data, const Diagonal &d) +{ + num_all = d.num_all; + num_real = d.num_real; + int d_size = d.getSize(); + for (const_diag_iter it = d.begin(); it != d.end(); ++it) + { + const DiagonalBlock &dit = *it; + double *beta1 = NULL; + double *beta2 = NULL; + int id = dit.getIndex()*(d_size+1); + int idd = id; + if (!dit.isReal()) + { + beta1 = &data[id+d_size]; + beta2 = &data[id+1]; + idd = id + d_size + 1; + } + DiagonalBlock b(dit.getIndex(), dit.isReal(), + &data[id], &data[idd], beta1, beta2); + blocks.push_back(b); + } +} + +void +Diagonal::copy(const Diagonal &d) +{ + num_all = d.num_all; + num_real = d.num_real; + blocks = d.blocks; +} + +int +Diagonal::getNumComplex(const double *data, int d_size) +{ + int num_complex = 0; + int in = 1; + for (int i = 0; i < d_size-1; i++, in = in + d_size + 1) + { + if (!isZero(data[in])) + { + num_complex++; + if (in < d_size - 2 && !isZero(data[in + d_size +1])) + { + throw SYLV_MES_EXCEPTION("Matrix is not quasi-triangular"); + } + } + } + return num_complex; +} + +void +Diagonal::changeBase(double *p) +{ + int d_size = getSize(); + for (diag_iter it = begin(); it != end(); ++it) + { + const DiagonalBlock &b = *it; + int jbar = b.getIndex(); + int base = d_size*jbar + jbar; + if (b.isReal()) + { + DiagonalBlock bnew(jbar, true, &p[base], &p[base], + NULL, NULL); + *it = bnew; + } + else + { + DiagonalBlock bnew(jbar, false, &p[base], &p[base+d_size+1], + &p[base+d_size], &p[base+1]); + *it = bnew; + } + } +} + +void +Diagonal::getEigenValues(Vector &eig) const +{ + int d_size = getSize(); + if (eig.length() != 2*d_size) + { + char mes[500]; + sprintf(mes, "Wrong length of vector for eigenvalues len=%d, should be=%d.\n", + eig.length(), 2*d_size); + throw SYLV_MES_EXCEPTION(mes); + } + for (const_diag_iter it = begin(); it != end(); ++it) + { + const DiagonalBlock &b = *it; + int ind = b.getIndex(); + eig[2*ind] = *(b.getAlpha()); + if (b.isReal()) + { + eig[2*ind+1] = 0.0; + } + else + { + double beta = sqrt(b.getSBeta()); + eig[2*ind+1] = beta; + eig[2*ind+2] = eig[2*ind]; + eig[2*ind+3] = -beta; + } + } +} + +/* swaps logically blocks 'it', and '++it'. remember to move also + * addresses, alpha, beta1, beta2. This is a dirty (but most + * effective) way how to do it. */ +void +Diagonal::swapLogically(diag_iter it) +{ + diag_iter itp = it; + ++itp; + + if ((*it).isReal() && !(*itp).isReal()) + { + // first is real, second is complex + double *d1 = (*it).alpha.a1; + double *d2 = (*itp).alpha.a1; + double *d3 = (*itp).alpha.a2; + // swap + DiagonalBlock new_it((*it).jbar, d1, d2); + *it = new_it; + DiagonalBlock new_itp((*itp).jbar+1, d3); + *itp = new_itp; + } + else if (!(*it).isReal() && (*itp).isReal()) + { + // first is complex, second is real + double *d1 = (*it).alpha.a1; + double *d2 = (*it).alpha.a2; + double *d3 = (*itp).alpha.a1; + // swap + DiagonalBlock new_it((*it).jbar, d1); + *it = new_it; + DiagonalBlock new_itp((*itp).jbar-1, d2, d3); + *itp = new_itp; + } +} + +void +Diagonal::checkConsistency(diag_iter it) +{ + if (!(*it).isReal() && isZero((*it).getBeta2())) + { + (*it).getBeta2() = 0.0; // put exact zero + int jbar = (*it).getIndex(); + double *d2 = (*it).alpha.a2; + (*it).alpha.a2 = (*it).alpha.a1; + (*it).real = true; + (*it).beta1 = 0; + (*it).beta2 = 0; + DiagonalBlock b(jbar+1, d2); + blocks.insert((++it).iter(), b); + num_real += 2; + num_all++; + } +} + +double +Diagonal::getAverageSize(diag_iter start, diag_iter end) +{ + double res = 0; + int num = 0; + for (diag_iter run = start; run != end; ++run) + { + num++; + res += (*run).getSize(); + } + if (num > 0) + res = res/num; + return res; +} + +Diagonal::diag_iter +Diagonal::findClosestBlock(diag_iter start, diag_iter end, double a) +{ + diag_iter closest = start; + double minim = 1.0e100; + for (diag_iter run = start; run != end; ++run) + { + double dist = abs(a - (*run).getSize()); + if (dist < minim) + { + minim = dist; + closest = run; + } + } + return closest; +} + +Diagonal::diag_iter +Diagonal::findNextLargerBlock(diag_iter start, diag_iter end, double a) +{ + diag_iter closest = start; + double minim = 1.0e100; + for (diag_iter run = start; run != end; ++run) + { + double dist = (*run).getSize() - a; + if ((0 <= dist) && (dist < minim)) + { + minim = dist; + closest = run; + } + } + return closest; +} + +void +Diagonal::print() const +{ + printf("Num real: %d, num complex: %d\n", getNumReal(), getNumComplex()); + for (const_diag_iter it = begin(); it != end(); ++it) + { + if ((*it).isReal()) + { + printf("real: jbar=%d, alpha=%f\n", (*it).getIndex(), *((*it).getAlpha())); + } + else + { + printf("complex: jbar=%d, alpha=%f, beta1=%f, beta2=%f\n", + (*it).getIndex(), *((*it).getAlpha()), (*it).getBeta1(), (*it).getBeta2()); + } + } +} + +double Diagonal::EPS = 1.0e-300; + +bool +Diagonal::isZero(double p) +{ + return (abs(p) < EPS); +} + +QuasiTriangular::const_col_iter +QuasiTriangular::col_begin(const DiagonalBlock &b) const +{ + int jbar = b.getIndex(); + int d_size = diagonal.getSize(); + return const_col_iter(&getData()[jbar*d_size], d_size, b.isReal(), 0); +} + +QuasiTriangular::col_iter +QuasiTriangular::col_begin(const DiagonalBlock &b) +{ + int jbar = b.getIndex(); + int d_size = diagonal.getSize(); + return col_iter(&getData()[jbar*d_size], d_size, b.isReal(), 0); +} + +QuasiTriangular::const_row_iter +QuasiTriangular::row_begin(const DiagonalBlock &b) const +{ + int jbar = b.getIndex(); + int d_size = diagonal.getSize(); + int off = jbar*d_size+jbar+d_size; + int col = jbar+1; + if (!b.isReal()) + { + off = off + d_size; + col++; + } + return const_row_iter(&getData()[off], d_size, b.isReal(), col); +} + +QuasiTriangular::row_iter +QuasiTriangular::row_begin(const DiagonalBlock &b) +{ + int jbar = b.getIndex(); + int d_size = diagonal.getSize(); + int off = jbar*d_size+jbar+d_size; + int col = jbar+1; + if (!b.isReal()) + { + off = off + d_size; + col++; + } + return row_iter(&getData()[off], d_size, b.isReal(), col); +} + +QuasiTriangular::const_col_iter +QuasiTriangular::col_end(const DiagonalBlock &b) const +{ + int jbar = b.getIndex(); + int d_size = diagonal.getSize(); + return const_col_iter(getData().base()+jbar*d_size+jbar, d_size, b.isReal(), + jbar); +} + +QuasiTriangular::col_iter +QuasiTriangular::col_end(const DiagonalBlock &b) +{ + int jbar = b.getIndex(); + int d_size = diagonal.getSize(); + return col_iter(&getData()[jbar*d_size+jbar], d_size, b.isReal(), jbar); +} + +QuasiTriangular::const_row_iter +QuasiTriangular::row_end(const DiagonalBlock &b) const +{ + int jbar = b.getIndex(); + int d_size = diagonal.getSize(); + return const_row_iter(&getData()[d_size*d_size+jbar], d_size, b.isReal(), + d_size); +} + +QuasiTriangular::row_iter +QuasiTriangular::row_end(const DiagonalBlock &b) +{ + int jbar = b.getIndex(); + int d_size = diagonal.getSize(); + return row_iter(&getData()[d_size*d_size+jbar], d_size, b.isReal(), d_size); +} + +QuasiTriangular::QuasiTriangular(double r, const QuasiTriangular &t) + : SqSylvMatrix(t.numRows()), diagonal(getData().base(), t.diagonal) +{ + setMatrix(r, t); +} + +QuasiTriangular::QuasiTriangular(double r, const QuasiTriangular &t, + double rr, const QuasiTriangular &tt) + : SqSylvMatrix(t.numRows()), diagonal(getData().base(), t.diagonal) +{ + setMatrix(r, t); + addMatrix(rr, tt); +} + +QuasiTriangular::QuasiTriangular(const QuasiTriangular &t) + : SqSylvMatrix(t), diagonal(getData().base(), t.diagonal) +{ +} + +QuasiTriangular::QuasiTriangular(const double *d, int d_size) + : SqSylvMatrix(d, d_size), diagonal(getData().base(), d_size) +{ +} + +QuasiTriangular::~QuasiTriangular() +{ +} + +QuasiTriangular::QuasiTriangular(int p, const QuasiTriangular &t) + : SqSylvMatrix(t.numRows()), diagonal(getData().base(), t.diagonal) +{ + Vector aux(t.getData()); + blas_int d_size = diagonal.getSize(); + double alpha = 1.0; + double beta = 0.0; + dgemm("N", "N", &d_size, &d_size, &d_size, &alpha, aux.base(), + &d_size, t.getData().base(), &d_size, &beta, getData().base(), &d_size); +} + +QuasiTriangular::QuasiTriangular(const SchurDecomp &decomp) + : SqSylvMatrix(decomp.getT()), + diagonal(getData().base(), decomp.getDim()) +{ +} + +/* this pads matrix with intial columns with zeros */ +QuasiTriangular::QuasiTriangular(const SchurDecompZero &decomp) + : SqSylvMatrix(decomp.getDim()) +{ + // nullify first decomp.getZeroCols() columns + int zeros = decomp.getZeroCols()*decomp.getDim(); + Vector zv(getData(), 0, zeros); + zv.zeros(); + // fill right upper part with decomp.getRU() + for (int i = 0; i < decomp.getRU().numRows(); i++) + { + for (int j = 0; j < decomp.getRU().numCols(); j++) + { + getData()[(j+decomp.getZeroCols())*decomp.getDim()+i] = decomp.getRU().get(i, j); + } + } + // fill right lower part with decomp.getT() + for (int i = 0; i < decomp.getT().numRows(); i++) + { + for (int j = 0; j < decomp.getT().numCols(); j++) + { + getData()[(j+decomp.getZeroCols())*decomp.getDim()+decomp.getZeroCols()+i] + = decomp.getT().get(i, j); + } + } + // construct diagonal + Diagonal *const d = new Diagonal(getData().base(), decomp.getDim()); + diagonal = *d; + delete d; +} + +void +QuasiTriangular::setMatrix(double r, const QuasiTriangular &t) +{ + getData().zeros(); + getData().add(r, t.getData()); +} + +void +QuasiTriangular::setMatrixViaIter(double r, const QuasiTriangular &t) +{ + register double rr = r; + diag_iter dil = diag_begin(); + const_diag_iter dir = t.diag_begin(); + for (; dil != diag_end(); ++dil, ++dir) + { + (*dil).getAlpha() = rr*(*(*dir).getAlpha()); + if (!(*dil).isReal()) + { + (*dil).getBeta1() = rr*(*dir).getBeta1(); + (*dil).getBeta2() = rr*(*dir).getBeta2(); + } + col_iter cil = col_begin(*dil); + const_col_iter cir = t.col_begin(*dir); + for (; cil != col_end(*dil); ++cil, ++cir) + { + if ((*dil).isReal()) + { + *cil = rr*(*cir); + } + else + { + cil.a() = rr*cir.a(); + cil.b() = rr*cir.b(); + } + } + } +} + +void +QuasiTriangular::addMatrix(double r, const QuasiTriangular &t) +{ + getData().add(r, t.getData()); +} + +void +QuasiTriangular::addMatrixViaIter(double r, const QuasiTriangular &t) +{ + register double rr = r; + diag_iter dil = diag_begin(); + const_diag_iter dir = t.diag_begin(); + for (; dil != diag_end(); ++dil, ++dir) + { + (*dil).getAlpha() = (*(*dil).getAlpha()) + rr*(*(*dir).getAlpha()); + if (!(*dil).isReal()) + { + (*dil).getBeta1() += rr*(*dir).getBeta1(); + (*dil).getBeta2() += rr*(*dir).getBeta2(); + } + col_iter cil = col_begin(*dil); + const_col_iter cir = t.col_begin(*dir); + for (; cil != col_end(*dil); ++cil, ++cir) + { + if ((*dil).isReal()) + { + *cil += rr*(*cir); + } + else + { + cil.a() += rr*cir.a(); + cil.b() += rr*cir.b(); + } + } + } +} + +void +QuasiTriangular::addUnit() +{ + for (diag_iter di = diag_begin(); di != diag_end(); ++di) + { + (*di).getAlpha() = *((*di).getAlpha()) + 1.0; + } +} + +void +QuasiTriangular::solve(Vector &x, const ConstVector &b, double &eig_min) +{ + x = b; + solvePre(x, eig_min); +} + +void +QuasiTriangular::solveTrans(Vector &x, const ConstVector &b, double &eig_min) +{ + x = b; + solvePreTrans(x, eig_min); +} + +void +QuasiTriangular::solvePre(Vector &x, double &eig_min) +{ + addUnit(); + for (diag_iter di = diag_begin(); di != diag_end(); ++di) + { + double eig_size; + if (!(*di).isReal()) + { + eig_size = (*di).getDeterminant(); + eliminateLeft((*di).getIndex()+1, (*di).getIndex(), x); + } + else + { + eig_size = *(*di).getAlpha()*(*(*di).getAlpha()); + } + if (eig_size < eig_min) + eig_min = eig_size; + } + + blas_int nn = diagonal.getSize(); + blas_int lda = diagonal.getSize(); + blas_int incx = x.skip(); + dtrsv("U", "N", "N", &nn, getData().base(), &lda, x.base(), &incx); +} + +void +QuasiTriangular::solvePreTrans(Vector &x, double &eig_min) +{ + addUnit(); + for (diag_iter di = diag_begin(); di != diag_end(); ++di) + { + double eig_size; + if (!(*di).isReal()) + { + eig_size = (*di).getDeterminant(); + eliminateRight((*di).getIndex()+1, (*di).getIndex(), x); + } + else + { + eig_size = *(*di).getAlpha()*(*(*di).getAlpha()); + } + if (eig_size < eig_min) + eig_min = eig_size; + } + + blas_int nn = diagonal.getSize(); + blas_int lda = diagonal.getSize(); + blas_int incx = x.skip(); + dtrsv("U", "T", "N", &nn, getData().base(), &lda, x.base(), &incx); +} + +/* calculates x = Tb */ +void +QuasiTriangular::multVec(Vector &x, const ConstVector &b) const +{ + x = b; + blas_int nn = diagonal.getSize(); + blas_int lda = diagonal.getSize(); + blas_int incx = x.skip(); + dtrmv("U", "N", "N", &nn, getData().base(), &lda, x.base(), &incx); + for (const_diag_iter di = diag_begin(); di != diag_end(); ++di) + { + if (!(*di).isReal()) + { + int jbar = (*di).getIndex(); + x[jbar+1] += (*di).getBeta2()*(b[jbar]); + } + } +} + +void +QuasiTriangular::multVecTrans(Vector &x, const ConstVector &b) const +{ + x = b; + blas_int nn = diagonal.getSize(); + blas_int lda = diagonal.getSize(); + blas_int incx = x.skip(); + dtrmv("U", "T", "N", &nn, getData().base(), &lda, x.base(), &incx); + for (const_diag_iter di = diag_begin(); di != diag_end(); ++di) + { + if (!(*di).isReal()) + { + int jbar = (*di).getIndex(); + x[jbar] += (*di).getBeta2()*b[jbar+1]; + } + } +} + +void +QuasiTriangular::multaVec(Vector &x, const ConstVector &b) const +{ + Vector tmp((const Vector &)x); // new copy + multVec(x, b); + x.add(1.0, tmp); +} + +void +QuasiTriangular::multaVecTrans(Vector &x, const ConstVector &b) const +{ + Vector tmp((const Vector &)x); // new copy + multVecTrans(x, b); + x.add(1.0, tmp); +} + +/* calculates x=x+(T\otimes I)b, where size of I is given by b (KronVector) */ +void +QuasiTriangular::multaKron(KronVector &x, const ConstKronVector &b) const +{ + int id = b.getN()*power(b.getM(), b.getDepth()-1); + ConstGeneralMatrix b_resh(b.base(), id, b.getM()); + GeneralMatrix x_resh(x.base(), id, b.getM()); + x_resh.multAndAdd(b_resh, ConstGeneralMatrix(*this), "trans"); +} + +/* calculates x=x+(T'\otimes I)b, where size of I is given by b (KronVector) */ +void +QuasiTriangular::multaKronTrans(KronVector &x, const ConstKronVector &b) const +{ + int id = b.getN()*power(b.getM(), b.getDepth()-1); + ConstGeneralMatrix b_resh(b.base(), id, b.getM()); + GeneralMatrix x_resh(x.base(), id, b.getM()); + x_resh.multAndAdd(b_resh, ConstGeneralMatrix(*this)); +} + +void +QuasiTriangular::multKron(KronVector &x) const +{ + KronVector b((const KronVector &)x); // make copy + x.zeros(); + multaKron(x, b); +} + +void +QuasiTriangular::multKronTrans(KronVector &x) const +{ + KronVector b((const KronVector &)x); // make copy + x.zeros(); + multaKronTrans(x, b); +} + +void +QuasiTriangular::multLeftOther(GeneralMatrix &a) const +{ + a.multLeft(*this); +} + +void +QuasiTriangular::multLeftOtherTrans(GeneralMatrix &a) const +{ + a.multLeftTrans(*this); +} + +void +QuasiTriangular::swapDiagLogically(diag_iter it) +{ + diagonal.swapLogically(it); +} + +void +QuasiTriangular::checkDiagConsistency(diag_iter it) +{ + diagonal.checkConsistency(it); +} + +double +QuasiTriangular::getAverageDiagSize(diag_iter start, diag_iter end) +{ + return diagonal.getAverageSize(start, end); +} + +QuasiTriangular::diag_iter +QuasiTriangular::findClosestDiagBlock(diag_iter start, diag_iter end, double a) +{ + return diagonal.findClosestBlock(start, end, a); +} + +QuasiTriangular::diag_iter +QuasiTriangular::findNextLargerBlock(diag_iter start, diag_iter end, double a) +{ + return diagonal.findNextLargerBlock(start, end, a); +} + +int +QuasiTriangular::getNumOffdiagonal() const +{ + return diagonal.getSize()*(diagonal.getSize()-1)/2 - diagonal.getNumComplex(); +} diff --git a/dynare++/sylv/cc/QuasiTriangular.cpp b/dynare++/sylv/cc/QuasiTriangular.cpp deleted file mode 100644 index d6b742f72d17684c3b6aa35f53c679b2d3865638..0000000000000000000000000000000000000000 --- a/dynare++/sylv/cc/QuasiTriangular.cpp +++ /dev/null @@ -1,682 +0,0 @@ -/* $Header: /var/lib/cvs/dynare_cpp/sylv/cc/QuasiTriangular.cpp,v 1.1.1.1 2004/06/04 13:00:31 kamenik Exp $ */ - -/* Tag $Name: $ */ - -#include "QuasiTriangular.h" -#include "SylvException.h" -#include "SchurDecomp.h" - -#include <dynblas.h> - -#include <cstdio> -#include <cmath> - -using namespace std; - -double DiagonalBlock::getDeterminant() const -{ - return (*alpha)*(*alpha) + getSBeta(); -} - -double DiagonalBlock::getSBeta() const -{ - return -(*beta1)*(*beta2); -} - -double DiagonalBlock::getSize() const -{ - if (real) - return abs(*alpha); - else - return sqrt(getDeterminant()); -} - -// this function makes Diagonal inconsistent, it should only be used -// on temorary matrices, which will not be used any more, e.g. in -// QuasiTriangular::solve (we need fast performance) -void DiagonalBlock::setReal() -{ - *beta1 = 0; - *beta2 = 0; - real = true; -} - -void DiagonalBlock::checkBlock(const double* d, int d_size) -{ - const double* a1 = d + jbar*d_size+jbar; - const double* b1 = a1 + d_size; - const double* b2 = a1 + 1; - const double* a2 = b1 + 1; - if (a1 != alpha.a1) - throw SYLV_MES_EXCEPTION("Bad alpha1."); - if (!real && b1 != beta1) - throw SYLV_MES_EXCEPTION("Bad beta1."); - if (!real && b2 != beta2) - throw SYLV_MES_EXCEPTION("Bad beta2."); - if (!real && a2 != alpha.a2) - throw SYLV_MES_EXCEPTION("Bad alpha2."); -} - -Diagonal::Diagonal(double* data, int d_size) -{ - int nc = getNumComplex(data, d_size); // return nc <= d_size/2 - num_all = d_size - nc; - num_real = d_size - 2*nc; - - int jbar = 0; - int j = 0; - while (j < num_all) { - int id = jbar*d_size + jbar; // index of diagonal block in data - int ill = id + 1; // index of element below the diagonal - int iur = id + d_size; // index of element right to diagonal - int idd = id + d_size + 1; // index of element next on diagonal - if ((jbar < d_size-1) && !isZero(data[ill])) { - // it is not last column and we have nonzero below diagonal - DiagonalBlock b(jbar, false, &data[id], &data[idd], - &data[iur], &data[ill]); - blocks.push_back(b); - jbar++; - } else { - // it is last column or we have zero below diagonal - DiagonalBlock b(jbar, true, &data[id], &data[id], NULL, NULL); - blocks.push_back(b); - } - jbar++; - j++; - } -} - - -Diagonal::Diagonal(double* data, const Diagonal& d) -{ - num_all = d.num_all; - num_real = d.num_real; - int d_size = d.getSize(); - for (const_diag_iter it = d.begin(); it != d.end(); ++it) { - const DiagonalBlock& dit = *it; - double* beta1 = NULL; - double* beta2 = NULL; - int id = dit.getIndex()*(d_size+1); - int idd = id; - if (! dit.isReal()) { - beta1 = &data[id+d_size]; - beta2 = &data[id+1]; - idd = id + d_size + 1; - } - DiagonalBlock b(dit.getIndex(), dit.isReal(), - &data[id], &data[idd], beta1, beta2); - blocks.push_back(b); - } -} - - -void Diagonal::copy(const Diagonal& d) -{ - num_all = d.num_all; - num_real = d.num_real; - blocks = d.blocks; -} - -int Diagonal::getNumComplex(const double* data, int d_size) -{ - int num_complex = 0; - int in = 1; - for (int i = 0; i < d_size-1; i++, in = in + d_size + 1) { - if (! isZero(data[in])) { - num_complex++; - if (in < d_size - 2 && ! isZero(data[in + d_size +1])) { - throw SYLV_MES_EXCEPTION("Matrix is not quasi-triangular"); - } - } - } - return num_complex; -} - -void Diagonal::changeBase(double* p) -{ - int d_size = getSize(); - for (diag_iter it = begin(); it != end(); ++it) { - const DiagonalBlock& b = *it; - int jbar = b.getIndex(); - int base = d_size*jbar + jbar; - if (b.isReal()) { - DiagonalBlock bnew(jbar, true, &p[base], &p[base], - NULL, NULL); - *it = bnew; - } else { - DiagonalBlock bnew(jbar, false, &p[base], &p[base+d_size+1], - &p[base+d_size], &p[base+1]); - *it = bnew; - } - } -} - -void Diagonal::getEigenValues(Vector& eig) const -{ - int d_size = getSize(); - if (eig.length() != 2*d_size) { - char mes[500]; - sprintf(mes, "Wrong length of vector for eigenvalues len=%d, should be=%d.\n", - eig.length(), 2*d_size); - throw SYLV_MES_EXCEPTION(mes); - } - for (const_diag_iter it = begin(); it != end(); ++it) { - const DiagonalBlock& b = *it; - int ind = b.getIndex(); - eig[2*ind] = *(b.getAlpha()); - if (b.isReal()) { - eig[2*ind+1] = 0.0; - } else { - double beta = sqrt(b.getSBeta()); - eig[2*ind+1] = beta; - eig[2*ind+2] = eig[2*ind]; - eig[2*ind+3] = -beta; - } - } -} - -/* swaps logically blocks 'it', and '++it'. remember to move also - * addresses, alpha, beta1, beta2. This is a dirty (but most - * effective) way how to do it. */ -void Diagonal::swapLogically(diag_iter it) -{ - diag_iter itp = it; - ++itp; - - if ((*it).isReal() && !(*itp).isReal()) { - // first is real, second is complex - double* d1 = (*it).alpha.a1; - double* d2 = (*itp).alpha.a1; - double* d3 = (*itp).alpha.a2; - // swap - DiagonalBlock new_it((*it).jbar, d1, d2); - *it = new_it; - DiagonalBlock new_itp((*itp).jbar+1, d3); - *itp = new_itp; - } else if (!(*it).isReal() && (*itp).isReal()) { - // first is complex, second is real - double* d1 = (*it).alpha.a1; - double* d2 = (*it).alpha.a2; - double* d3 = (*itp).alpha.a1; - // swap - DiagonalBlock new_it((*it).jbar, d1); - *it = new_it; - DiagonalBlock new_itp((*itp).jbar-1, d2, d3); - *itp = new_itp; - } -} - -void Diagonal::checkConsistency(diag_iter it) -{ - if (!(*it).isReal() && isZero((*it).getBeta2())) { - (*it).getBeta2() = 0.0; // put exact zero - int jbar = (*it).getIndex(); - double* d2 = (*it).alpha.a2; - (*it).alpha.a2 = (*it).alpha.a1; - (*it).real = true; - (*it).beta1 = 0; - (*it).beta2 = 0; - DiagonalBlock b(jbar+1, d2); - blocks.insert((++it).iter(), b); - num_real += 2; - num_all++; - } -} - -double Diagonal::getAverageSize(diag_iter start, diag_iter end) -{ - double res = 0; - int num = 0; - for (diag_iter run = start; run != end; ++run) { - num++; - res += (*run).getSize(); - } - if (num > 0) - res = res/num; - return res; -} - -Diagonal::diag_iter Diagonal::findClosestBlock(diag_iter start, diag_iter end, double a) -{ - diag_iter closest = start; - double minim = 1.0e100; - for (diag_iter run = start; run != end; ++run) { - double dist = abs(a - (*run).getSize()); - if (dist < minim) { - minim = dist; - closest = run; - } - } - return closest; -} - -Diagonal::diag_iter Diagonal::findNextLargerBlock(diag_iter start, diag_iter end, double a) -{ - diag_iter closest = start; - double minim = 1.0e100; - for (diag_iter run = start; run != end; ++run) { - double dist = (*run).getSize() - a; - if ((0 <= dist) && (dist < minim)) { - minim = dist; - closest = run; - } - } - return closest; -} - -void Diagonal::print() const -{ - printf("Num real: %d, num complex: %d\n",getNumReal(), getNumComplex()); - for (const_diag_iter it = begin(); it != end(); ++it) { - if ((*it).isReal()) { - printf("real: jbar=%d, alpha=%f\n", (*it).getIndex(), *((*it).getAlpha())); - } - else { - printf("complex: jbar=%d, alpha=%f, beta1=%f, beta2=%f\n", - (*it).getIndex(), *((*it).getAlpha()), (*it).getBeta1(), (*it).getBeta2()); - } - } -} - -double Diagonal::EPS = 1.0e-300; - -bool Diagonal::isZero(double p) -{ - return (abs(p)<EPS); -} - - -QuasiTriangular::const_col_iter -QuasiTriangular::col_begin(const DiagonalBlock& b) const -{ - int jbar = b.getIndex(); - int d_size = diagonal.getSize(); - return const_col_iter(&getData()[jbar*d_size], d_size, b.isReal(), 0); -} - -QuasiTriangular::col_iter -QuasiTriangular::col_begin(const DiagonalBlock& b) -{ - int jbar = b.getIndex(); - int d_size = diagonal.getSize(); - return col_iter(&getData()[jbar*d_size], d_size, b.isReal(), 0); -} - -QuasiTriangular::const_row_iter -QuasiTriangular::row_begin(const DiagonalBlock& b) const -{ - int jbar = b.getIndex(); - int d_size = diagonal.getSize(); - int off = jbar*d_size+jbar+d_size; - int col = jbar+1; - if (!b.isReal()) { - off = off + d_size; - col++; - } - return const_row_iter(&getData()[off], d_size, b.isReal(), col); -} - - -QuasiTriangular::row_iter -QuasiTriangular::row_begin(const DiagonalBlock& b) -{ - int jbar = b.getIndex(); - int d_size = diagonal.getSize(); - int off = jbar*d_size+jbar+d_size; - int col = jbar+1; - if (!b.isReal()) { - off = off + d_size; - col++; - } - return row_iter(&getData()[off], d_size, b.isReal(), col); -} - -QuasiTriangular::const_col_iter -QuasiTriangular::col_end(const DiagonalBlock& b) const -{ - int jbar = b.getIndex(); - int d_size = diagonal.getSize(); - return const_col_iter(getData().base()+jbar*d_size+jbar, d_size, b.isReal(), - jbar); -} - -QuasiTriangular::col_iter -QuasiTriangular::col_end(const DiagonalBlock& b) -{ - int jbar = b.getIndex(); - int d_size = diagonal.getSize(); - return col_iter(&getData()[jbar*d_size+jbar], d_size, b.isReal(), jbar); -} - -QuasiTriangular::const_row_iter -QuasiTriangular::row_end(const DiagonalBlock& b) const -{ - int jbar = b.getIndex(); - int d_size = diagonal.getSize(); - return const_row_iter(&getData()[d_size*d_size+jbar], d_size, b.isReal(), - d_size); -} - -QuasiTriangular::row_iter -QuasiTriangular::row_end(const DiagonalBlock& b) -{ - int jbar = b.getIndex(); - int d_size = diagonal.getSize(); - return row_iter(&getData()[d_size*d_size+jbar], d_size, b.isReal(), d_size); -} - -QuasiTriangular::QuasiTriangular(double r, const QuasiTriangular& t) - : SqSylvMatrix(t.numRows()), diagonal(getData().base(), t.diagonal) -{ - setMatrix(r, t); -} - -QuasiTriangular::QuasiTriangular(double r, const QuasiTriangular& t, - double rr, const QuasiTriangular& tt) - : SqSylvMatrix(t.numRows()), diagonal(getData().base(), t.diagonal) -{ - setMatrix(r, t); - addMatrix(rr, tt); -} - -QuasiTriangular::QuasiTriangular(const QuasiTriangular& t) - : SqSylvMatrix(t), diagonal(getData().base(), t.diagonal) -{ -} - -QuasiTriangular::QuasiTriangular(const double* d, int d_size) - : SqSylvMatrix(d, d_size), diagonal(getData().base(), d_size) -{} - -QuasiTriangular::~QuasiTriangular() -{ -} - -QuasiTriangular::QuasiTriangular(int p, const QuasiTriangular& t) - : SqSylvMatrix(t.numRows()), diagonal(getData().base(), t.diagonal) -{ - Vector aux(t.getData()); - blas_int d_size = diagonal.getSize(); - double alpha = 1.0; - double beta = 0.0; - dgemm("N", "N", &d_size, &d_size, &d_size, &alpha, aux.base(), - &d_size, t.getData().base(), &d_size, &beta, getData().base(), &d_size); -} - -QuasiTriangular::QuasiTriangular(const SchurDecomp& decomp) - : SqSylvMatrix(decomp.getT()), - diagonal(getData().base(), decomp.getDim()) -{ -} - -/* this pads matrix with intial columns with zeros */ -QuasiTriangular::QuasiTriangular(const SchurDecompZero& decomp) - : SqSylvMatrix(decomp.getDim()) -{ - // nullify first decomp.getZeroCols() columns - int zeros = decomp.getZeroCols()*decomp.getDim(); - Vector zv(getData(), 0, zeros); - zv.zeros(); - // fill right upper part with decomp.getRU() - for (int i = 0; i < decomp.getRU().numRows(); i++) { - for (int j = 0; j < decomp.getRU().numCols(); j++) { - getData()[(j+decomp.getZeroCols())*decomp.getDim()+i] = decomp.getRU().get(i,j); - } - } - // fill right lower part with decomp.getT() - for (int i = 0; i < decomp.getT().numRows(); i++) { - for (int j = 0; j < decomp.getT().numCols(); j++) { - getData()[(j+decomp.getZeroCols())*decomp.getDim()+decomp.getZeroCols()+i] = - decomp.getT().get(i,j); - } - } - // construct diagonal - Diagonal* const d = new Diagonal(getData().base(), decomp.getDim()); - diagonal = *d; - delete d; -} - -void QuasiTriangular::setMatrix(double r, const QuasiTriangular& t) -{ - getData().zeros(); - getData().add(r, t.getData()); -} - -void QuasiTriangular::setMatrixViaIter(double r, const QuasiTriangular& t) -{ - register double rr = r; - diag_iter dil = diag_begin(); - const_diag_iter dir = t.diag_begin(); - for ( ; dil != diag_end(); ++dil, ++dir) { - (*dil).getAlpha() = rr*(*(*dir).getAlpha()); - if (! (*dil).isReal()) { - (*dil).getBeta1() = rr*(*dir).getBeta1(); - (*dil).getBeta2() = rr*(*dir).getBeta2(); - } - col_iter cil = col_begin(*dil); - const_col_iter cir = t.col_begin(*dir); - for ( ; cil != col_end(*dil); ++cil, ++cir) { - if ((*dil).isReal()) { - *cil = rr*(*cir); - } else { - cil.a() = rr*cir.a(); - cil.b() = rr*cir.b(); - } - } - } -} - -void QuasiTriangular::addMatrix(double r, const QuasiTriangular& t) -{ - getData().add(r, t.getData()); -} - -void QuasiTriangular::addMatrixViaIter(double r, const QuasiTriangular& t) -{ - register double rr = r; - diag_iter dil = diag_begin(); - const_diag_iter dir = t.diag_begin(); - for ( ; dil != diag_end(); ++dil, ++dir) { - (*dil).getAlpha() = (*(*dil).getAlpha()) + rr*(*(*dir).getAlpha()); - if (! (*dil).isReal()) { - (*dil).getBeta1() += rr*(*dir).getBeta1(); - (*dil).getBeta2() += rr*(*dir).getBeta2(); - } - col_iter cil = col_begin(*dil); - const_col_iter cir = t.col_begin(*dir); - for ( ; cil != col_end(*dil); ++cil, ++cir) { - if ((*dil).isReal()) { - *cil += rr*(*cir); - } else { - cil.a() += rr*cir.a(); - cil.b() += rr*cir.b(); - } - } - } -} - -void QuasiTriangular::addUnit() -{ - for (diag_iter di = diag_begin(); di != diag_end(); ++di) { - (*di).getAlpha() = *((*di).getAlpha()) + 1.0; - } -} - -void QuasiTriangular::solve(Vector& x, const ConstVector& b, double& eig_min) -{ - x = b; - solvePre(x, eig_min); -} - -void QuasiTriangular::solveTrans(Vector& x, const ConstVector& b, double& eig_min) -{ - x = b; - solvePreTrans(x, eig_min); -} - -void QuasiTriangular::solvePre(Vector& x, double& eig_min) -{ - addUnit(); - for (diag_iter di = diag_begin(); di != diag_end(); ++di) { - double eig_size; - if (!(*di).isReal()) { - eig_size = (*di).getDeterminant(); - eliminateLeft((*di).getIndex()+1, (*di).getIndex(), x); - } else { - eig_size = *(*di).getAlpha()*(*(*di).getAlpha()); - } - if (eig_size < eig_min) - eig_min = eig_size; - } - - blas_int nn = diagonal.getSize(); - blas_int lda = diagonal.getSize(); - blas_int incx = x.skip(); - dtrsv("U", "N", "N", &nn, getData().base(), &lda, x.base(), &incx); -} - -void QuasiTriangular::solvePreTrans(Vector& x, double& eig_min) -{ - addUnit(); - for (diag_iter di = diag_begin(); di != diag_end(); ++di) { - double eig_size; - if (!(*di).isReal()) { - eig_size = (*di).getDeterminant(); - eliminateRight((*di).getIndex()+1, (*di).getIndex(), x); - } else { - eig_size = *(*di).getAlpha()*(*(*di).getAlpha()); - } - if (eig_size < eig_min) - eig_min = eig_size; - } - - blas_int nn = diagonal.getSize(); - blas_int lda = diagonal.getSize(); - blas_int incx = x.skip(); - dtrsv("U", "T", "N", &nn, getData().base(), &lda, x.base(), &incx); -} - - -/* calculates x = Tb */ -void QuasiTriangular::multVec(Vector& x, const ConstVector& b) const -{ - x = b; - blas_int nn = diagonal.getSize(); - blas_int lda = diagonal.getSize(); - blas_int incx = x.skip(); - dtrmv("U", "N", "N", &nn, getData().base(), &lda, x.base(), &incx); - for (const_diag_iter di = diag_begin(); di != diag_end(); ++di) { - if (!(*di).isReal()) { - int jbar = (*di).getIndex(); - x[jbar+1] += (*di).getBeta2()*(b[jbar]); - } - } -} - - -void QuasiTriangular::multVecTrans(Vector& x, const ConstVector& b) const -{ - x = b; - blas_int nn = diagonal.getSize(); - blas_int lda = diagonal.getSize(); - blas_int incx = x.skip(); - dtrmv("U", "T", "N", &nn, getData().base(), &lda, x.base(), &incx); - for (const_diag_iter di = diag_begin(); di != diag_end(); ++di) { - if (!(*di).isReal()) { - int jbar = (*di).getIndex(); - x[jbar] += (*di).getBeta2()*b[jbar+1]; - } - } -} - -void QuasiTriangular::multaVec(Vector& x, const ConstVector& b) const -{ - Vector tmp((const Vector&) x); // new copy - multVec(x, b); - x.add(1.0, tmp); -} - -void QuasiTriangular::multaVecTrans(Vector& x, const ConstVector& b) const -{ - Vector tmp((const Vector&) x); // new copy - multVecTrans(x, b); - x.add(1.0, tmp); -} - -/* calculates x=x+(T\otimes I)b, where size of I is given by b (KronVector) */ -void QuasiTriangular::multaKron(KronVector& x, const ConstKronVector& b) const -{ - int id = b.getN()*power(b.getM(), b.getDepth()-1); - ConstGeneralMatrix b_resh(b.base(), id, b.getM()); - GeneralMatrix x_resh(x.base(), id, b.getM()); - x_resh.multAndAdd(b_resh, ConstGeneralMatrix(*this), "trans"); -} - - -/* calculates x=x+(T'\otimes I)b, where size of I is given by b (KronVector) */ -void -QuasiTriangular::multaKronTrans(KronVector& x, const ConstKronVector& b) const -{ - int id = b.getN()*power(b.getM(), b.getDepth()-1); - ConstGeneralMatrix b_resh(b.base(), id, b.getM()); - GeneralMatrix x_resh(x.base(), id, b.getM()); - x_resh.multAndAdd(b_resh, ConstGeneralMatrix(*this)); -} - - -void QuasiTriangular::multKron(KronVector& x) const -{ - KronVector b((const KronVector&)x); // make copy - x.zeros(); - multaKron(x, b); -} - -void -QuasiTriangular::multKronTrans(KronVector& x) const -{ - KronVector b((const KronVector&)x); // make copy - x.zeros(); - multaKronTrans(x, b); -} - -void QuasiTriangular::multLeftOther(GeneralMatrix& a) const -{ - a.multLeft(*this); -} - -void QuasiTriangular::multLeftOtherTrans(GeneralMatrix& a) const -{ - a.multLeftTrans(*this); -} - -void QuasiTriangular::swapDiagLogically(diag_iter it) -{ - diagonal.swapLogically(it); -} - -void QuasiTriangular::checkDiagConsistency(diag_iter it) -{ - diagonal.checkConsistency(it); -} - -double QuasiTriangular::getAverageDiagSize(diag_iter start, diag_iter end) -{ - return diagonal.getAverageSize(start, end); -} - -QuasiTriangular::diag_iter -QuasiTriangular::findClosestDiagBlock(diag_iter start, diag_iter end, double a) -{ - return diagonal.findClosestBlock(start, end, a); -} - -QuasiTriangular::diag_iter -QuasiTriangular::findNextLargerBlock(diag_iter start, diag_iter end, double a) -{ - return diagonal.findNextLargerBlock(start, end, a); -} - -int QuasiTriangular::getNumOffdiagonal() const -{ - return diagonal.getSize()*(diagonal.getSize()-1)/2 - diagonal.getNumComplex(); -} diff --git a/dynare++/sylv/cc/QuasiTriangular.h b/dynare++/sylv/cc/QuasiTriangular.hh similarity index 99% rename from dynare++/sylv/cc/QuasiTriangular.h rename to dynare++/sylv/cc/QuasiTriangular.hh index d09fede07021373f32389ee2bb204c01943c4bae..6794f8e6db4bedd2415d2061d2e18a32c50cb50e 100644 --- a/dynare++/sylv/cc/QuasiTriangular.h +++ b/dynare++/sylv/cc/QuasiTriangular.hh @@ -5,9 +5,9 @@ #ifndef QUASI_TRIANGULAR_H #define QUASI_TRIANGULAR_H -#include "Vector.h" -#include "KronVector.h" -#include "SylvMatrix.h" +#include "Vector.hh" +#include "KronVector.hh" +#include "SylvMatrix.hh" #include <list> diff --git a/dynare++/sylv/cc/QuasiTriangularZero.cc b/dynare++/sylv/cc/QuasiTriangularZero.cc new file mode 100644 index 0000000000000000000000000000000000000000..737736b30cb101e945da643be48f767bd7e4d875 --- /dev/null +++ b/dynare++/sylv/cc/QuasiTriangularZero.cc @@ -0,0 +1,157 @@ +/* $Header: /var/lib/cvs/dynare_cpp/sylv/cc/QuasiTriangularZero.cpp,v 1.1.1.1 2004/06/04 13:00:44 kamenik Exp $ */ + +/* Tag $Name: $ */ + +#include "QuasiTriangularZero.hh" +#include "SchurDecomp.hh" +#include "SylvMatrix.hh" +#include "SylvException.hh" + +#include <cstdio> + +QuasiTriangularZero::QuasiTriangularZero(int num_zeros, const double *d, + int d_size) + : QuasiTriangular(SqSylvMatrix(GeneralMatrix(d, num_zeros+d_size, d_size), + num_zeros, 0, d_size).getData().base(), + d_size), + nz(num_zeros), + ru(GeneralMatrix(d, num_zeros+d_size, d_size), 0, 0, num_zeros, d_size) +{ +} + +QuasiTriangularZero::QuasiTriangularZero(double r, + const QuasiTriangularZero &t) + : QuasiTriangular(r, t), + nz(t.nz), + ru(t.ru) +{ + ru.mult(r); +} + +QuasiTriangularZero::QuasiTriangularZero(double r, + const QuasiTriangularZero &t, + double rr, + const QuasiTriangularZero &tt) + : QuasiTriangular(r, t, rr, tt), + nz(t.nz), + ru(t.ru) +{ + ru.mult(r); + ru.add(rr, tt.ru); +} + +QuasiTriangularZero::QuasiTriangularZero(int p, const QuasiTriangularZero &t) + : QuasiTriangular(p, t), + nz(t.nz), + ru(t.ru) +{ + ru.multRight(t); +} + +QuasiTriangularZero::QuasiTriangularZero(const SchurDecompZero &decomp) + : QuasiTriangular(decomp.getT().getData().base(), + decomp.getT().numRows()), + nz(decomp.getZeroCols()), + ru(decomp.getRU()) +{ +} + +QuasiTriangularZero::QuasiTriangularZero(const QuasiTriangular &t) + : QuasiTriangular(t), + nz(0), ru(0, t.getDiagonal().getSize()) +{ +} + +QuasiTriangularZero::~QuasiTriangularZero() +{ +} + +void +QuasiTriangularZero::solvePre(Vector &x, double &eig_min) +{ + Vector xu(x, 0, nz); + Vector xl(x, nz, x.length()-nz); + QuasiTriangular::solvePre(xl, eig_min); + ru.multsVec(xu, xl); + if (nz > 0) + eig_min = (eig_min > 1.0) ? 1.0 : eig_min; +} + +void +QuasiTriangularZero::solvePreTrans(Vector &x, double &eig_min) +{ + Vector xu(x, 0, nz); + Vector xl(x, nz, x.length()-nz); + ru.multsVecTrans(xl, xu); + QuasiTriangular::solvePreTrans(xl, eig_min); + if (nz > 0) + eig_min = (eig_min > 1.0) ? 1.0 : eig_min; +} + +void +QuasiTriangularZero::multVec(Vector &x, const ConstVector &b) const +{ + x.zeros(); + multaVec(x, b); +} + +void +QuasiTriangularZero::multVecTrans(Vector &x, const ConstVector &b) const +{ + x.zeros(); + multaVecTrans(x, b); +} + +void +QuasiTriangularZero::multaVec(Vector &x, const ConstVector &b) const +{ + ConstVector bl(b, nz, b.length()-nz); + Vector xu(x, 0, nz); + Vector xl(x, nz, x.length()-nz); + xu.zeros(); + ru.multaVec(xu, bl); + QuasiTriangular::multVec(xl, bl); +} + +void +QuasiTriangularZero::multaVecTrans(Vector &x, const ConstVector &b) const +{ + ConstVector bu(b, 0, b.length()); + ConstVector bl(b, nz, b.length()-nz); + Vector xu(x, 0, nz); + Vector xl(x, nz, x.length()-nz); + xu.zeros(); + QuasiTriangular::multVecTrans(xl, bl); + ru.multaVecTrans(xl, bu); +} + +void +QuasiTriangularZero::multLeftOther(GeneralMatrix &a) const +{ + GeneralMatrix a1(a, 0, 0, nz, a.numCols()); + GeneralMatrix a2(a, nz, 0, a.numRows()-nz, a.numCols()); + a1.mult(ru, a2); + QuasiTriangular::multLeftOther(a2); +} + +void +QuasiTriangularZero::print() const +{ + printf("super=\n"); + QuasiTriangular::print(); + printf("nz=%d\n", nz); + printf("ru=\n"); + ru.print(); +} + +void +QuasiTriangularZero::multKron(KronVector &x) const +{ + throw SYLV_MES_EXCEPTION("Attempt to run QuasiTriangularZero::multKron."); +} + +void +QuasiTriangularZero::multKronTrans(KronVector &x) const +{ + throw SYLV_MES_EXCEPTION("Attempt to run QuasiTriangularZero::multKronTrans."); +} diff --git a/dynare++/sylv/cc/QuasiTriangularZero.cpp b/dynare++/sylv/cc/QuasiTriangularZero.cpp deleted file mode 100644 index a7e9213b94da403a4ff37fe35f66eea87be7f602..0000000000000000000000000000000000000000 --- a/dynare++/sylv/cc/QuasiTriangularZero.cpp +++ /dev/null @@ -1,148 +0,0 @@ -/* $Header: /var/lib/cvs/dynare_cpp/sylv/cc/QuasiTriangularZero.cpp,v 1.1.1.1 2004/06/04 13:00:44 kamenik Exp $ */ - -/* Tag $Name: $ */ - -#include "QuasiTriangularZero.h" -#include "SchurDecomp.h" -#include "SylvMatrix.h" -#include "SylvException.h" - -#include <cstdio> - -QuasiTriangularZero::QuasiTriangularZero(int num_zeros, const double* d, - int d_size) - : QuasiTriangular(SqSylvMatrix(GeneralMatrix(d, num_zeros+d_size, d_size), - num_zeros, 0, d_size).getData().base(), - d_size), - nz(num_zeros), - ru(GeneralMatrix(d, num_zeros+d_size, d_size), 0, 0, num_zeros, d_size) -{ -} - -QuasiTriangularZero::QuasiTriangularZero(double r, - const QuasiTriangularZero& t) - : QuasiTriangular(r, t), - nz(t.nz), - ru(t.ru) -{ - ru.mult(r); -} - -QuasiTriangularZero::QuasiTriangularZero(double r, - const QuasiTriangularZero& t, - double rr, - const QuasiTriangularZero& tt) - : QuasiTriangular(r, t, rr, tt), - nz(t.nz), - ru(t.ru) -{ - ru.mult(r); - ru.add(rr, tt.ru); -} - -QuasiTriangularZero::QuasiTriangularZero(int p, const QuasiTriangularZero& t) - : QuasiTriangular(p, t), - nz(t.nz), - ru(t.ru) -{ - ru.multRight(t); -} - -QuasiTriangularZero::QuasiTriangularZero(const SchurDecompZero& decomp) - : QuasiTriangular(decomp.getT().getData().base(), - decomp.getT().numRows()), - nz(decomp.getZeroCols()), - ru(decomp.getRU()) -{ -} - -QuasiTriangularZero::QuasiTriangularZero(const QuasiTriangular& t) - : QuasiTriangular(t), - nz(0), ru(0, t.getDiagonal().getSize()) -{ -} - -QuasiTriangularZero::~QuasiTriangularZero() -{ -} - -void QuasiTriangularZero::solvePre(Vector& x, double& eig_min) -{ - Vector xu(x, 0, nz); - Vector xl(x, nz, x.length()-nz); - QuasiTriangular::solvePre(xl, eig_min); - ru.multsVec(xu, xl); - if (nz > 0) - eig_min = (eig_min > 1.0)? 1.0 : eig_min; -} - -void QuasiTriangularZero::solvePreTrans(Vector& x, double& eig_min) -{ - Vector xu(x, 0, nz); - Vector xl(x, nz, x.length()-nz); - ru.multsVecTrans(xl, xu); - QuasiTriangular::solvePreTrans(xl, eig_min); - if (nz > 0) - eig_min = (eig_min > 1.0)? 1.0 : eig_min; -} - -void QuasiTriangularZero::multVec(Vector& x, const ConstVector& b) const -{ - x.zeros(); - multaVec(x, b); -} - -void QuasiTriangularZero::multVecTrans(Vector& x, const ConstVector& b) const -{ - x.zeros(); - multaVecTrans(x, b); -} - -void QuasiTriangularZero::multaVec(Vector& x, const ConstVector& b) const -{ - ConstVector bl(b, nz, b.length()-nz); - Vector xu(x, 0, nz); - Vector xl(x, nz, x.length()-nz); - xu.zeros(); - ru.multaVec(xu, bl); - QuasiTriangular::multVec(xl, bl); -} - -void QuasiTriangularZero::multaVecTrans(Vector& x, const ConstVector& b) const -{ - ConstVector bu(b, 0, b.length()); - ConstVector bl(b, nz, b.length()-nz); - Vector xu(x, 0, nz); - Vector xl(x, nz, x.length()-nz); - xu.zeros(); - QuasiTriangular::multVecTrans(xl, bl); - ru.multaVecTrans(xl, bu); -} - -void QuasiTriangularZero::multLeftOther(GeneralMatrix& a) const -{ - GeneralMatrix a1(a, 0, 0, nz, a.numCols()); - GeneralMatrix a2(a, nz, 0, a.numRows()-nz, a.numCols()); - a1.mult(ru, a2); - QuasiTriangular::multLeftOther(a2); -} - -void QuasiTriangularZero::print() const -{ - printf("super=\n"); - QuasiTriangular::print(); - printf("nz=%d\n",nz); - printf("ru=\n"); - ru.print(); -} - -void QuasiTriangularZero::multKron(KronVector& x) const -{ - throw SYLV_MES_EXCEPTION("Attempt to run QuasiTriangularZero::multKron."); -} - -void QuasiTriangularZero::multKronTrans(KronVector& x) const -{ - throw SYLV_MES_EXCEPTION("Attempt to run QuasiTriangularZero::multKronTrans."); -} - diff --git a/dynare++/sylv/cc/QuasiTriangularZero.h b/dynare++/sylv/cc/QuasiTriangularZero.hh similarity index 97% rename from dynare++/sylv/cc/QuasiTriangularZero.h rename to dynare++/sylv/cc/QuasiTriangularZero.hh index 243c02123f5ee6fcf05c9d6dc106c6fbf77b8fc7..049f6a802b2eb923ae0a368038ef7ee9581621fb 100644 --- a/dynare++/sylv/cc/QuasiTriangularZero.h +++ b/dynare++/sylv/cc/QuasiTriangularZero.hh @@ -5,8 +5,8 @@ #ifndef QUASI_TRIANGULAR_ZERO_H #define QUASI_TRIANGULAR_ZERO_H -#include "QuasiTriangular.h" -#include "GeneralMatrix.h" +#include "QuasiTriangular.hh" +#include "GeneralMatrix.hh" class QuasiTriangularZero : public QuasiTriangular { diff --git a/dynare++/sylv/cc/SchurDecomp.cc b/dynare++/sylv/cc/SchurDecomp.cc new file mode 100644 index 0000000000000000000000000000000000000000..265a53a37c8116fac1e0b4e4eacd5eeb00877751 --- /dev/null +++ b/dynare++/sylv/cc/SchurDecomp.cc @@ -0,0 +1,71 @@ +/* $Header: /var/lib/cvs/dynare_cpp/sylv/cc/SchurDecomp.cpp,v 1.1.1.1 2004/06/04 13:00:44 kamenik Exp $ */ + +/* Tag $Name: $ */ + +#include "SchurDecomp.hh" + +#include <dynlapack.h> + +SchurDecomp::SchurDecomp(const SqSylvMatrix &m) + : q_destroy(true), t_destroy(true) +{ + lapack_int rows = m.numRows(); + q = new SqSylvMatrix(rows); + SqSylvMatrix auxt(m); + lapack_int sdim; + double *const wr = new double[rows]; + double *const wi = new double[rows]; + lapack_int lwork = 6*rows; + double *const work = new double[lwork]; + lapack_int info; + dgees("V", "N", 0, &rows, auxt.base(), &rows, &sdim, + wr, wi, q->base(), &rows, + work, &lwork, 0, &info); + delete [] work; + delete [] wi; + delete [] wr; + t = new QuasiTriangular(auxt.base(), rows); +} + +SchurDecomp::SchurDecomp(const QuasiTriangular &tr) + : q_destroy(true), t_destroy(true) +{ + q = new SqSylvMatrix(tr.numRows()); + q->setUnit(); + t = new QuasiTriangular(tr); +} + +SchurDecomp::SchurDecomp(QuasiTriangular &tr) + : q_destroy(true), t_destroy(false) +{ + q = new SqSylvMatrix(tr.numRows()); + q->setUnit(); + t = &tr; +} + +SchurDecomp::~SchurDecomp() +{ + if (t_destroy) + delete t; + if (q_destroy) + delete q; +} + +int +SchurDecomp::getDim() const +{ + return t->numRows(); +} + +SchurDecompZero::SchurDecompZero(const GeneralMatrix &m) + : SchurDecomp(SqSylvMatrix(m, m.numRows()-m.numCols(), 0, m.numCols())), + ru(m, 0, 0, m.numRows()-m.numCols(), m.numCols()) +{ + ru.multRight(getQ()); +} + +int +SchurDecompZero::getDim() const +{ + return getT().numRows()+ru.numRows(); +} diff --git a/dynare++/sylv/cc/SchurDecomp.cpp b/dynare++/sylv/cc/SchurDecomp.cpp deleted file mode 100644 index f76b48b177ca4569f8c897069a92847e39ca831a..0000000000000000000000000000000000000000 --- a/dynare++/sylv/cc/SchurDecomp.cpp +++ /dev/null @@ -1,71 +0,0 @@ -/* $Header: /var/lib/cvs/dynare_cpp/sylv/cc/SchurDecomp.cpp,v 1.1.1.1 2004/06/04 13:00:44 kamenik Exp $ */ - -/* Tag $Name: $ */ - -#include "SchurDecomp.h" - -#include <dynlapack.h> - -SchurDecomp::SchurDecomp(const SqSylvMatrix& m) - : q_destroy(true), t_destroy(true) -{ - lapack_int rows = m.numRows(); - q = new SqSylvMatrix(rows); - SqSylvMatrix auxt(m); - lapack_int sdim; - double* const wr = new double[rows]; - double* const wi = new double[rows]; - lapack_int lwork = 6*rows; - double* const work = new double[lwork]; - lapack_int info; - dgees("V", "N", 0, &rows, auxt.base(), &rows, &sdim, - wr, wi, q->base(), &rows, - work, &lwork, 0, &info); - delete [] work; - delete [] wi; - delete [] wr; - t = new QuasiTriangular(auxt.base(), rows); -} - -SchurDecomp::SchurDecomp(const QuasiTriangular& tr) - : q_destroy(true), t_destroy(true) -{ - q = new SqSylvMatrix(tr.numRows()); - q->setUnit(); - t = new QuasiTriangular(tr); -} - -SchurDecomp::SchurDecomp(QuasiTriangular& tr) - : q_destroy(true), t_destroy(false) -{ - q = new SqSylvMatrix(tr.numRows()); - q->setUnit(); - t = &tr; -} - -SchurDecomp::~SchurDecomp() -{ - if (t_destroy) - delete t; - if (q_destroy) - delete q; -} - -int SchurDecomp::getDim() const -{ - return t->numRows(); -} - -SchurDecompZero::SchurDecompZero(const GeneralMatrix& m) - : SchurDecomp(SqSylvMatrix(m, m.numRows()-m.numCols(), 0, m.numCols())), - ru(m, 0, 0, m.numRows()-m.numCols(), m.numCols()) -{ - ru.multRight(getQ()); -} - -int SchurDecompZero::getDim() const -{ - return getT().numRows()+ru.numRows(); -} - - diff --git a/dynare++/sylv/cc/SchurDecomp.h b/dynare++/sylv/cc/SchurDecomp.hh similarity index 95% rename from dynare++/sylv/cc/SchurDecomp.h rename to dynare++/sylv/cc/SchurDecomp.hh index 9e83c92219269003bc6f552ec8d8bff0ebd1649e..8dd53525b75351917bfbf2010b091f47b48682b9 100644 --- a/dynare++/sylv/cc/SchurDecomp.h +++ b/dynare++/sylv/cc/SchurDecomp.hh @@ -5,8 +5,8 @@ #ifndef SCHUR_DECOMP_H #define SCHUR_DECOMP_H -#include "SylvMatrix.h" -#include "QuasiTriangular.h" +#include "SylvMatrix.hh" +#include "QuasiTriangular.hh" class QuasiTriangular; class SchurDecomp diff --git a/dynare++/sylv/cc/SchurDecompEig.cc b/dynare++/sylv/cc/SchurDecompEig.cc new file mode 100644 index 0000000000000000000000000000000000000000..751b52818df6c4eecea820355ac2d8f7e44c83c2 --- /dev/null +++ b/dynare++/sylv/cc/SchurDecompEig.cc @@ -0,0 +1,101 @@ +#include "SchurDecompEig.hh" +#include "SylvException.hh" + +#include <dynlapack.h> + +/* bubble diagonal 1-1, or 2-2 block from position 'from' to position + * 'to'. If an eigenvalue cannot be swapped with its neighbour, the + * neighbour is bubbled also in front. The method returns a new + * position 'to', where the original block pointed by 'to' happens to + * appear at the end. 'from' must be greater than 'to'. + */ +SchurDecompEig::diag_iter +SchurDecompEig::bubbleEigen(diag_iter from, diag_iter to) +{ + diag_iter run = from; + while (run != to) + { + diag_iter runm = run; + if (!tryToSwap(run, runm) && runm == to) + { + ++to; + } + else + { + // bubble all eigenvalues from runm(incl.) to run(excl.), + // this includes either bubbling generated eigenvalues due + // to split, or an eigenvalue which couldn't be swapped + while (runm != run) + { + to = bubbleEigen(runm, to); + ++runm; + } + } + } + return to; +} + +/* this tries to swap two neighbouring eigenvalues, 'it' and '--it', + * and returns 'itadd'. If the blocks can be swapped, new eigenvalues + * can emerge due to possible 2-2 block splits. 'it' then points to + * the last eigenvalue coming from block pointed by 'it' at the + * begining, and 'itadd' points to the first. On swap failure, 'it' is + * not changed, and 'itadd' points to previous eignevalue (which must + * be moved backwards before). In either case, it is necessary to + * resolve eigenvalues from 'itadd' to 'it', before the 'it' can be + * resolved. + * The success is signaled by returned true. + */ +bool +SchurDecompEig::tryToSwap(diag_iter &it, diag_iter &itadd) +{ + itadd = it; + --itadd; + + lapack_int n = getDim(); + lapack_int ifst = (*it).getIndex() + 1; + lapack_int ilst = (*itadd).getIndex() + 1; + double *work = new double[n]; + lapack_int info; + dtrexc("V", &n, getT().base(), &n, getQ().base(), &n, &ifst, &ilst, work, + &info); + delete [] work; + if (info < 0) + { + throw SYLV_MES_EXCEPTION("Wrong argument to dtrexc."); + } + + if (info == 0) + { + // swap successful + getT().swapDiagLogically(itadd); + //check for 2-2 block splits + getT().checkDiagConsistency(it); + getT().checkDiagConsistency(itadd); + // and go back by 'it' in NEW eigenvalue set + --it; + return true; + } + return false; +} + +void +SchurDecompEig::orderEigen() +{ + diag_iter run = getT().diag_begin(); + diag_iter runp = run; + ++runp; + double last_size = 0.0; + while (runp != getT().diag_end()) + { + diag_iter least = getT().findNextLargerBlock(run, getT().diag_end(), + last_size); + last_size = (*least).getSize(); + if (run == least) + ++run; + else + run = bubbleEigen(least, run); + runp = run; + ++runp; + } +} diff --git a/dynare++/sylv/cc/SchurDecompEig.cpp b/dynare++/sylv/cc/SchurDecompEig.cpp deleted file mode 100644 index b2fda2e0d64e4ca9e1095eb194e13f379edca661..0000000000000000000000000000000000000000 --- a/dynare++/sylv/cc/SchurDecompEig.cpp +++ /dev/null @@ -1,92 +0,0 @@ -#include "SchurDecompEig.h" -#include "SylvException.h" - -#include <dynlapack.h> - -/* bubble diagonal 1-1, or 2-2 block from position 'from' to position - * 'to'. If an eigenvalue cannot be swapped with its neighbour, the - * neighbour is bubbled also in front. The method returns a new - * position 'to', where the original block pointed by 'to' happens to - * appear at the end. 'from' must be greater than 'to'. - */ -SchurDecompEig::diag_iter -SchurDecompEig::bubbleEigen(diag_iter from, diag_iter to) -{ - diag_iter run = from; - while (run != to) { - diag_iter runm = run; - if (!tryToSwap(run, runm) && runm == to) { - ++to; - } else { - // bubble all eigenvalues from runm(incl.) to run(excl.), - // this includes either bubbling generated eigenvalues due - // to split, or an eigenvalue which couldn't be swapped - while (runm != run) { - to = bubbleEigen(runm, to); - ++runm; - } - } - } - return to; -} - -/* this tries to swap two neighbouring eigenvalues, 'it' and '--it', - * and returns 'itadd'. If the blocks can be swapped, new eigenvalues - * can emerge due to possible 2-2 block splits. 'it' then points to - * the last eigenvalue coming from block pointed by 'it' at the - * begining, and 'itadd' points to the first. On swap failure, 'it' is - * not changed, and 'itadd' points to previous eignevalue (which must - * be moved backwards before). In either case, it is necessary to - * resolve eigenvalues from 'itadd' to 'it', before the 'it' can be - * resolved. - * The success is signaled by returned true. - */ -bool SchurDecompEig::tryToSwap(diag_iter& it, diag_iter& itadd) -{ - itadd = it; - --itadd; - - lapack_int n = getDim(); - lapack_int ifst = (*it).getIndex() + 1; - lapack_int ilst = (*itadd).getIndex() + 1; - double* work = new double[n]; - lapack_int info; - dtrexc("V", &n, getT().base(), &n, getQ().base(), &n, &ifst, &ilst, work, - &info); - delete [] work; - if (info < 0) { - throw SYLV_MES_EXCEPTION("Wrong argument to dtrexc."); - } - - if (info == 0) { - // swap successful - getT().swapDiagLogically(itadd); - //check for 2-2 block splits - getT().checkDiagConsistency(it); - getT().checkDiagConsistency(itadd); - // and go back by 'it' in NEW eigenvalue set - --it; - return true; - } - return false; -} - - -void SchurDecompEig::orderEigen() -{ - diag_iter run = getT().diag_begin(); - diag_iter runp = run; - ++runp; - double last_size = 0.0; - while (runp != getT().diag_end()) { - diag_iter least = getT().findNextLargerBlock(run, getT().diag_end(), - last_size); - last_size = (*least).getSize(); - if (run == least) - ++run; - else - run = bubbleEigen(least, run); - runp = run; - ++runp; - } -} diff --git a/dynare++/sylv/cc/SchurDecompEig.h b/dynare++/sylv/cc/SchurDecompEig.hh similarity index 93% rename from dynare++/sylv/cc/SchurDecompEig.h rename to dynare++/sylv/cc/SchurDecompEig.hh index 567f457831acd4a8f22fac71c9e575b89b675f37..6b9a7747e4aaaface84c413daeecceb20b27c4b7 100644 --- a/dynare++/sylv/cc/SchurDecompEig.h +++ b/dynare++/sylv/cc/SchurDecompEig.hh @@ -7,8 +7,8 @@ #ifndef SCHUR_DECOMP_EIG_H #define SCHUR_DECOMP_EIG_H -#include "SchurDecomp.h" -#include "QuasiTriangular.h" +#include "SchurDecomp.hh" +#include "QuasiTriangular.hh" class SchurDecompEig : public SchurDecomp { diff --git a/dynare++/sylv/cc/SimilarityDecomp.cc b/dynare++/sylv/cc/SimilarityDecomp.cc new file mode 100644 index 0000000000000000000000000000000000000000..7c23e3c2f858dbed1bd61074f5b4bcfe5368eacd --- /dev/null +++ b/dynare++/sylv/cc/SimilarityDecomp.cc @@ -0,0 +1,171 @@ +/* $Header: /var/lib/cvs/dynare_cpp/sylv/cc/SimilarityDecomp.cpp,v 1.1.1.1 2004/06/04 13:00:44 kamenik Exp $ */ + +/* Tag $Name: $ */ + +#include "SimilarityDecomp.hh" +#include "SchurDecomp.hh" +#include "SchurDecompEig.hh" +#include "SylvException.hh" + +#include <dynlapack.h> + +#include <cmath> + +SimilarityDecomp::SimilarityDecomp(const double *d, int d_size, double log10norm) +{ + SchurDecomp sd(SqSylvMatrix(d, d_size)); + q = new SqSylvMatrix(sd.getQ()); + b = new BlockDiagonal(sd.getT()); + invq = new SqSylvMatrix(d_size); + invq->setUnit(); + invq->multLeftTrans(sd.getQ()); + double norm = pow(10.0, log10norm); + diagonalize(norm); +} + +SimilarityDecomp::~SimilarityDecomp() +{ + delete invq; + delete b; + delete q; +} + +void +SimilarityDecomp::getXDim(diag_iter start, diag_iter end, + int &rows, int &cols) const +{ + int si = (*start).getIndex(); + int ei = (*end).getIndex(); + cols = b->numRows() - ei; + rows = ei - si; +} + +/* find solution of X for diagonal block given by start(incl.) and + * end(excl.). If the solution cannot be found, or it is greater than + * norm, X is not changed and flase is returned. + */ +bool +SimilarityDecomp::solveX(diag_iter start, diag_iter end, + GeneralMatrix &X, double norm) const +{ + int si = (*start).getIndex(); + int ei = (*end).getIndex(); + + SqSylvMatrix A((const GeneralMatrix &)*b, si, si, X.numRows()); + SqSylvMatrix B((const GeneralMatrix &)*b, ei, ei, X.numCols()); + GeneralMatrix C((const GeneralMatrix &)*b, si, ei, X.numRows(), X.numCols()); + + lapack_int isgn = -1; + lapack_int m = A.numRows(); + lapack_int n = B.numRows(); + double scale; + lapack_int info; + dtrsyl("N", "N", &isgn, &m, &n, A.base(), &m, B.base(), &n, + C.base(), &m, &scale, &info); + if (info < -1) + throw SYLV_MES_EXCEPTION("Wrong parameter to LAPACK dtrsyl."); + + if (info == 1 || scale < 1) + return false; + if (C.getData().getMax() > norm) + return false; + + X = C; + return true; +} + +/* multiply Q and invQ with (I -X; 0 I), and (I X; 0 I). This also sets X=-X. */ +void +SimilarityDecomp::updateTransform(diag_iter start, diag_iter end, + GeneralMatrix &X) +{ + int si = (*start).getIndex(); + int ei = (*end).getIndex(); + + SqSylvMatrix iX(q->numRows()); + iX.setUnit(); + iX.place(X, si, ei); + invq->GeneralMatrix::multLeft(iX); + + iX.setUnit(); + X.mult(-1.0); + iX.place(X, si, ei); + q->multRight(iX); +} + +void +SimilarityDecomp::bringGuiltyBlock(diag_iter start, diag_iter &end) +{ + double av = b->getAverageDiagSize(start, end); + diag_iter guilty = b->findClosestDiagBlock(end, b->diag_end(), av); + SchurDecompEig sd((QuasiTriangular&)*b); // works on b including diagonal structure + end = sd.bubbleEigen(guilty, end); // iterators are valid + ++end; + q->multRight(sd.getQ()); + invq->multLeftTrans(sd.getQ()); +} + +void +SimilarityDecomp::diagonalize(double norm) +{ + diag_iter start = b->diag_begin(); + diag_iter end = start; + ++end; + + while (end != b->diag_end()) + { + int xrows; + int xcols; + getXDim(start, end, xrows, xcols); + GeneralMatrix X(xrows, xcols); + if (solveX(start, end, X, norm)) + { + updateTransform(start, end, X); + b->setZeroBlockEdge(end); + start = end; + ++end; + } + else + { + bringGuiltyBlock(start, end); // moves with end + } + } +} + +void +SimilarityDecomp::check(SylvParams &pars, const GeneralMatrix &m) const +{ + // M - Q*B*inv(Q) + SqSylvMatrix c(getQ(), getB()); + c.multRight(getInvQ()); + c.add(-1.0, m); + pars.f_err1 = c.getNorm1(); + pars.f_errI = c.getNormInf(); + + // I - Q*inv(Q) + c.setUnit(); + c.mult(-1); + c.multAndAdd(getQ(), getInvQ()); + pars.viv_err1 = c.getNorm1(); + pars.viv_errI = c.getNormInf(); + + // I - inv(Q)*Q + c.setUnit(); + c.mult(-1); + c.multAndAdd(getInvQ(), getQ()); + pars.ivv_err1 = c.getNorm1(); + pars.ivv_errI = c.getNormInf(); +} + +void +SimilarityDecomp::infoToPars(SylvParams &pars) const +{ + pars.f_blocks = getB().getNumBlocks(); + pars.f_largest = getB().getLargestBlock(); + pars.f_zeros = getB().getNumZeros(); + pars.f_offdiag = getB().getNumOffdiagonal(); +} + +// Local Variables: +// mode:C++ +// End: diff --git a/dynare++/sylv/cc/SimilarityDecomp.cpp b/dynare++/sylv/cc/SimilarityDecomp.cpp deleted file mode 100644 index 9f9b091b2f61634b7914535413e375fa6438f4f2..0000000000000000000000000000000000000000 --- a/dynare++/sylv/cc/SimilarityDecomp.cpp +++ /dev/null @@ -1,160 +0,0 @@ -/* $Header: /var/lib/cvs/dynare_cpp/sylv/cc/SimilarityDecomp.cpp,v 1.1.1.1 2004/06/04 13:00:44 kamenik Exp $ */ - -/* Tag $Name: $ */ - -#include "SimilarityDecomp.h" -#include "SchurDecomp.h" -#include "SchurDecompEig.h" -#include "SylvException.h" - -#include <dynlapack.h> - -#include <cmath> - -SimilarityDecomp::SimilarityDecomp(const double* d, int d_size, double log10norm) -{ - SchurDecomp sd(SqSylvMatrix(d, d_size)); - q = new SqSylvMatrix(sd.getQ()); - b = new BlockDiagonal(sd.getT()); - invq = new SqSylvMatrix(d_size); - invq->setUnit(); - invq->multLeftTrans(sd.getQ()); - double norm = pow(10.0, log10norm); - diagonalize(norm); -} - -SimilarityDecomp::~SimilarityDecomp() -{ - delete invq; - delete b; - delete q; -} - -void SimilarityDecomp::getXDim(diag_iter start, diag_iter end, - int &rows, int& cols) const -{ - int si = (*start).getIndex(); - int ei = (*end).getIndex(); - cols = b->numRows() - ei; - rows = ei - si; -} - -/* find solution of X for diagonal block given by start(incl.) and - * end(excl.). If the solution cannot be found, or it is greater than - * norm, X is not changed and flase is returned. - */ -bool SimilarityDecomp::solveX(diag_iter start, diag_iter end, - GeneralMatrix& X, double norm) const -{ - int si = (*start).getIndex(); - int ei = (*end).getIndex(); - - SqSylvMatrix A((const GeneralMatrix&)*b, si, si, X.numRows()); - SqSylvMatrix B((const GeneralMatrix&)*b, ei, ei, X.numCols()); - GeneralMatrix C((const GeneralMatrix&)*b, si, ei, X.numRows(), X.numCols()); - - lapack_int isgn = -1; - lapack_int m = A.numRows(); - lapack_int n = B.numRows(); - double scale; - lapack_int info; - dtrsyl("N", "N", &isgn, &m, &n, A.base(), &m, B.base(), &n, - C.base(), &m, &scale, &info); - if (info < -1) - throw SYLV_MES_EXCEPTION("Wrong parameter to LAPACK dtrsyl."); - - if (info == 1 || scale < 1) - return false; - if (C.getData().getMax() > norm) - return false; - - X = C; - return true; -} - -/* multiply Q and invQ with (I -X; 0 I), and (I X; 0 I). This also sets X=-X. */ -void SimilarityDecomp::updateTransform(diag_iter start, diag_iter end, - GeneralMatrix& X) -{ - int si = (*start).getIndex(); - int ei = (*end).getIndex(); - - SqSylvMatrix iX(q->numRows()); - iX.setUnit(); - iX.place(X, si, ei); - invq->GeneralMatrix::multLeft(iX); - - iX.setUnit(); - X.mult(-1.0); - iX.place(X, si, ei); - q->multRight(iX); -} - -void SimilarityDecomp::bringGuiltyBlock(diag_iter start, diag_iter& end) -{ - double av = b->getAverageDiagSize(start, end); - diag_iter guilty = b->findClosestDiagBlock(end, b->diag_end(), av); - SchurDecompEig sd((QuasiTriangular&)*b); // works on b including diagonal structure - end = sd.bubbleEigen(guilty, end); // iterators are valid - ++end; - q->multRight(sd.getQ()); - invq->multLeftTrans(sd.getQ()); -} - -void SimilarityDecomp::diagonalize(double norm) -{ - diag_iter start = b->diag_begin(); - diag_iter end = start; - ++end; - - while (end != b->diag_end()) { - int xrows; - int xcols; - getXDim(start, end, xrows, xcols); - GeneralMatrix X(xrows, xcols); - if (solveX(start, end, X, norm)) { - updateTransform(start, end, X); - b->setZeroBlockEdge(end); - start = end; - ++end; - } else { - bringGuiltyBlock(start, end); // moves with end - } - } -} - -void SimilarityDecomp::check(SylvParams& pars, const GeneralMatrix& m) const -{ - // M - Q*B*inv(Q) - SqSylvMatrix c(getQ(), getB()); - c.multRight(getInvQ()); - c.add(-1.0, m); - pars.f_err1 = c.getNorm1(); - pars.f_errI = c.getNormInf(); - - // I - Q*inv(Q) - c.setUnit(); - c.mult(-1); - c.multAndAdd(getQ(), getInvQ()); - pars.viv_err1 = c.getNorm1(); - pars.viv_errI = c.getNormInf(); - - // I - inv(Q)*Q - c.setUnit(); - c.mult(-1); - c.multAndAdd(getInvQ(), getQ()); - pars.ivv_err1 = c.getNorm1(); - pars.ivv_errI = c.getNormInf(); -} - -void SimilarityDecomp::infoToPars(SylvParams& pars) const -{ - pars.f_blocks = getB().getNumBlocks(); - pars.f_largest = getB().getLargestBlock(); - pars.f_zeros = getB().getNumZeros(); - pars.f_offdiag = getB().getNumOffdiagonal(); -} - -// Local Variables: -// mode:C++ -// End: diff --git a/dynare++/sylv/cc/SimilarityDecomp.h b/dynare++/sylv/cc/SimilarityDecomp.hh similarity index 93% rename from dynare++/sylv/cc/SimilarityDecomp.h rename to dynare++/sylv/cc/SimilarityDecomp.hh index 107da24e0cc2dfa43ea2b12d78a818e5938ab868..6cc275efc993c2428f86569da84a8669b912569d 100644 --- a/dynare++/sylv/cc/SimilarityDecomp.h +++ b/dynare++/sylv/cc/SimilarityDecomp.hh @@ -5,9 +5,9 @@ #ifndef SIMILARITY_DECOMP_H #define SIMILARITY_DECOMP_H -#include "SylvMatrix.h" -#include "BlockDiagonal.h" -#include "SylvParams.h" +#include "SylvMatrix.hh" +#include "BlockDiagonal.hh" +#include "SylvParams.hh" class SimilarityDecomp { diff --git a/dynare++/sylv/cc/SylvException.cc b/dynare++/sylv/cc/SylvException.cc new file mode 100644 index 0000000000000000000000000000000000000000..4e2c88e26cdfdcdfc28b8c703bd2b916cf5f9a0b --- /dev/null +++ b/dynare++/sylv/cc/SylvException.cc @@ -0,0 +1,74 @@ +/* $Header: /var/lib/cvs/dynare_cpp/sylv/cc/SylvException.cpp,v 1.2 2004/10/01 10:30:40 kamenik Exp $ */ + +/* Tag $Name: $ */ + +#include "SylvException.hh" + +#include <cstring> +#include <cstdio> + +SylvException::SylvException(const char *f, int l, const SylvException *s) +{ + strcpy(file, f); + line = l; + source = s; +} + +SylvException::~SylvException() +{ + if (source != NULL) + { + delete source; + } +} + +void +SylvException::printMessage() const +{ + char mes[1500]; + mes[0] = '\0'; + printMessage(mes, 1499); + puts(mes); +} + +int +SylvException::printMessage(char *str, int maxlen) const +{ + int remain = maxlen; + if (source != NULL) + { + remain = source->printMessage(str, maxlen); + } + char aux[100]; + sprintf(aux, "From %s:%d\n", file, line); + int newremain = remain - strlen(aux); + if (newremain < 0) + { + aux[remain] = '\0'; + newremain = 0; + } + strcat(str, aux); + return newremain; +} + +SylvExceptionMessage::SylvExceptionMessage(const char *f, int i, + const char *mes) + : SylvException(f, i, NULL) +{ + strcpy(message, mes); +} + +int +SylvExceptionMessage::printMessage(char *str, int maxlen) const +{ + char aux[600]; + sprintf(aux, "At %s:%d:%s\n", file, line, message); + int newremain = maxlen - strlen(aux); + if (newremain < 0) + { + aux[maxlen] = '\0'; + newremain = 0; + } + strcat(str, aux); + return newremain; +} diff --git a/dynare++/sylv/cc/SylvException.cpp b/dynare++/sylv/cc/SylvException.cpp deleted file mode 100644 index 43206138cf129ce72760c06839a190993ea6af55..0000000000000000000000000000000000000000 --- a/dynare++/sylv/cc/SylvException.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/* $Header: /var/lib/cvs/dynare_cpp/sylv/cc/SylvException.cpp,v 1.2 2004/10/01 10:30:40 kamenik Exp $ */ - -/* Tag $Name: $ */ - -#include "SylvException.h" - -#include <cstring> -#include <cstdio> - -SylvException::SylvException(const char* f, int l, const SylvException* s) -{ - strcpy(file,f); - line = l; - source = s; -} - -SylvException::~SylvException() -{ - if (source != NULL) { - delete source; - } -} - -void SylvException::printMessage() const -{ - char mes[1500]; - mes[0] = '\0'; - printMessage(mes, 1499); - puts(mes); -} - -int SylvException::printMessage(char* str, int maxlen) const -{ - int remain = maxlen; - if (source != NULL) { - remain = source->printMessage(str, maxlen); - } - char aux[100]; - sprintf(aux, "From %s:%d\n", file, line); - int newremain = remain - strlen(aux); - if (newremain < 0) { - aux[remain] = '\0'; - newremain = 0; - } - strcat(str, aux); - return newremain; -} - -SylvExceptionMessage::SylvExceptionMessage(const char* f, int i, - const char* mes) - : SylvException(f,i,NULL) -{ - strcpy(message,mes); -} - -int SylvExceptionMessage::printMessage(char* str, int maxlen) const -{ - char aux[600]; - sprintf(aux, "At %s:%d:%s\n", file, line, message); - int newremain = maxlen - strlen(aux); - if (newremain < 0) { - aux[maxlen] = '\0'; - newremain = 0; - } - strcat(str, aux); - return newremain; -} - - diff --git a/dynare++/sylv/cc/SylvException.h b/dynare++/sylv/cc/SylvException.hh similarity index 97% rename from dynare++/sylv/cc/SylvException.h rename to dynare++/sylv/cc/SylvException.hh index 5beb212a370a7d9f20b73f1f5c2b0c010eba6977..2bc1757ce2f602d6bd69abc863a4495afc8fef3e 100644 --- a/dynare++/sylv/cc/SylvException.h +++ b/dynare++/sylv/cc/SylvException.hh @@ -5,7 +5,7 @@ #ifndef SYLV_EXCEPTION_H #define SYLV_EXCEPTION_H -#include "SylvMemory.h" +#include "SylvMemory.hh" class SylvException : public MallocAllocator { diff --git a/dynare++/sylv/cc/SylvMatrix.cc b/dynare++/sylv/cc/SylvMatrix.cc new file mode 100644 index 0000000000000000000000000000000000000000..5a4059ec6e02832d898367353a530c4502c5b647 --- /dev/null +++ b/dynare++/sylv/cc/SylvMatrix.cc @@ -0,0 +1,291 @@ +/* $Header: /var/lib/cvs/dynare_cpp/sylv/cc/SylvMatrix.cpp,v 1.1.1.1 2004/06/04 13:00:44 kamenik Exp $ */ + +/* Tag $Name: $ */ + +#include "SylvException.hh" +#include "SylvMatrix.hh" + +#include <dynblas.h> +#include <dynlapack.h> + +#include <cstdio> +#include <cstring> +#include <cmath> + +void +SylvMatrix::multLeftI(const SqSylvMatrix &m) +{ + int off = rows - m.numRows(); + if (off < 0) + { + throw SYLV_MES_EXCEPTION("Wrong matrix dimensions for multLeftI."); + } + GeneralMatrix subtmp(*this, off, 0, m.numRows(), cols); + subtmp.multLeft(m); +} + +void +SylvMatrix::multLeftITrans(const SqSylvMatrix &m) +{ + int off = rows - m.numRows(); + if (off < 0) + { + throw SYLV_MES_EXCEPTION("Wrong matrix dimensions for multLeftITrans."); + } + GeneralMatrix subtmp(*this, off, 0, m.numRows(), cols); + subtmp.multLeftTrans(m); +} + +void +SylvMatrix::multLeft(int zero_cols, const GeneralMatrix &a, const GeneralMatrix &b) +{ + int off = a.numRows() - a.numCols(); + if (off < 0 || a.numRows() != rows || off != zero_cols + || rows != b.numRows() || cols != b.numCols()) + { + throw SYLV_MES_EXCEPTION("Wrong matrix dimensions for multLeft."); + } + // here we cannot call SylvMatrix::gemm since it would require + // another copy of (usually big) b (we are not able to do inplace + // submatrix of const GeneralMatrix) + if (a.getLD() > 0 && ld > 0) + { + blas_int mm = a.numRows(); + blas_int nn = cols; + blas_int kk = a.numCols(); + double alpha = 1.0; + blas_int lda = a.getLD(); + blas_int ldb = ld; + double beta = 0.0; + blas_int ldc = ld; + dgemm("N", "N", &mm, &nn, &kk, &alpha, a.getData().base(), &lda, + b.getData().base()+off, &ldb, &beta, data.base(), &ldc); + } +} + +void +SylvMatrix::multRightKron(const SqSylvMatrix &m, int order) +{ + if (power(m.numRows(), order) != cols) + { + throw SYLV_MES_EXCEPTION("Wrong number of cols for right kron multiply."); + } + KronVector auxrow(m.numRows(), m.numRows(), order-1); + for (int i = 0; i < rows; i++) + { + Vector rowi(data.base()+i, rows, cols); + KronVector rowikron(rowi, m.numRows(), m.numRows(), order-1); + auxrow = rowi; // copy data + m.multVecKronTrans(rowikron, auxrow); + } +} + +void +SylvMatrix::multRightKronTrans(const SqSylvMatrix &m, int order) +{ + if (power(m.numRows(), order) != cols) + { + throw SYLV_MES_EXCEPTION("Wrong number of cols for right kron multiply."); + } + + KronVector auxrow(m.numRows(), m.numRows(), order-1); + for (int i = 0; i < rows; i++) + { + Vector rowi(data.base()+i, rows, cols); + KronVector rowikron(rowi, m.numRows(), m.numRows(), order-1); + auxrow = rowi; // copy data + m.multVecKron(rowikron, auxrow); + } +} + +void +SylvMatrix::eliminateLeft(int row, int col, Vector &x) +{ + double d = get(col, col); + double e = get(row, col); + if (std::abs(d) > std::abs(e)) + { + get(row, col) = 0.0; + double mult = e/d; + for (int i = col + 1; i < numCols(); i++) + { + get(row, i) = get(row, i) - mult*get(col, i); + } + x[row] = x[row] - mult*x[col]; + } + else if (std::abs(e) > std::abs(d)) + { + get(row, col) = 0.0; + get(col, col) = e; + double mult = d/e; + for (int i = col + 1; i < numCols(); i++) + { + double tx = get(col, i); + double ty = get(row, i); + get(col, i) = ty; + get(row, i) = tx - mult*ty; + } + double tx = x[col]; + double ty = x[row]; + x[col] = ty; + x[row] = tx - mult*ty; + } +} + +void +SylvMatrix::eliminateRight(int row, int col, Vector &x) +{ + double d = get(row, row); + double e = get(row, col); + + if (std::abs(d) > std::abs(e)) + { + get(row, col) = 0.0; + double mult = e/d; + for (int i = 0; i < row; i++) + { + get(i, col) = get(i, col) - mult*get(i, row); + } + x[col] = x[col] - mult*x[row]; + } + else if (std::abs(e) > std::abs(d)) + { + get(row, col) = 0.0; + get(row, row) = e; + double mult = d/e; + for (int i = 0; i < row; i++) + { + double tx = get(i, row); + double ty = get(i, col); + get(i, row) = ty; + get(i, col) = tx - mult*ty; + } + double tx = x[row]; + double ty = x[col]; + x[row] = ty; + x[col] = tx - mult*ty; + } +} + +SqSylvMatrix::SqSylvMatrix(const GeneralMatrix &a, const GeneralMatrix &b) + : SylvMatrix(a, b) +{ + if (rows != cols) + throw SYLV_MES_EXCEPTION("Wrong matrix dimensions in multiplication constructor of square matrix."); +} + +void +SqSylvMatrix::multVecKron(KronVector &x, const KronVector &d) const +{ + x.zeros(); + if (d.getDepth() == 0) + { + multaVec(x, d); + } + else + { + KronVector aux(x.getM(), x.getN(), x.getDepth()); + for (int i = 0; i < x.getM(); i++) + { + KronVector auxi(aux, i); + ConstKronVector di(d, i); + multVecKron(auxi, di); + } + for (int i = 0; i < rows; i++) + { + KronVector xi(x, i); + for (int j = 0; j < cols; j++) + { + KronVector auxj(aux, j); + xi.add(get(i, j), auxj); + } + } + } +} + +void +SqSylvMatrix::multVecKronTrans(KronVector &x, const KronVector &d) const +{ + x.zeros(); + if (d.getDepth() == 0) + { + multaVecTrans(x, d); + } + else + { + KronVector aux(x.getM(), x.getN(), x.getDepth()); + for (int i = 0; i < x.getM(); i++) + { + KronVector auxi(aux, i); + ConstKronVector di(d, i); + multVecKronTrans(auxi, di); + } + for (int i = 0; i < rows; i++) + { + KronVector xi(x, i); + for (int j = 0; j < cols; j++) + { + KronVector auxj(aux, j); + xi.add(get(j, i), auxj); + } + } + } +} + +void +SqSylvMatrix::multInvLeft2(GeneralMatrix &a, GeneralMatrix &b, + double &rcond1, double &rcondinf) const +{ + if (rows != a.numRows() || rows != b.numRows()) + { + throw SYLV_MES_EXCEPTION("Wrong dimensions for multInvLeft2."); + } + // PLU factorization + Vector inv(data); + lapack_int *const ipiv = new lapack_int[rows]; + lapack_int info; + lapack_int rows2 = rows; + dgetrf(&rows2, &rows2, inv.base(), &rows2, ipiv, &info); + // solve a + lapack_int acols = a.numCols(); + double *abase = a.base(); + dgetrs("N", &rows2, &acols, inv.base(), &rows2, ipiv, + abase, &rows2, &info); + // solve b + lapack_int bcols = b.numCols(); + double *bbase = b.base(); + dgetrs("N", &rows2, &bcols, inv.base(), &rows2, ipiv, + bbase, &rows2, &info); + delete [] ipiv; + + // condition numbers + double *const work = new double[4*rows]; + lapack_int *const iwork = new lapack_int[rows]; + double norm1 = getNorm1(); + dgecon("1", &rows2, inv.base(), &rows2, &norm1, &rcond1, + work, iwork, &info); + double norminf = getNormInf(); + dgecon("I", &rows2, inv.base(), &rows2, &norminf, &rcondinf, + work, iwork, &info); + delete [] iwork; + delete [] work; +} + +void +SqSylvMatrix::setUnit() +{ + for (int i = 0; i < rows; i++) + { + for (int j = 0; j < cols; j++) + { + if (i == j) + get(i, j) = 1.0; + else + get(i, j) = 0.0; + } + } +} + +// Local Variables: +// mode:C++ +// End: diff --git a/dynare++/sylv/cc/SylvMatrix.cpp b/dynare++/sylv/cc/SylvMatrix.cpp deleted file mode 100644 index 6935815e0d5ae749222c631eb8db60e91b5d6ad8..0000000000000000000000000000000000000000 --- a/dynare++/sylv/cc/SylvMatrix.cpp +++ /dev/null @@ -1,252 +0,0 @@ -/* $Header: /var/lib/cvs/dynare_cpp/sylv/cc/SylvMatrix.cpp,v 1.1.1.1 2004/06/04 13:00:44 kamenik Exp $ */ - -/* Tag $Name: $ */ - -#include "SylvException.h" -#include "SylvMatrix.h" - -#include <dynblas.h> -#include <dynlapack.h> - -#include <cstdio> -#include <cstring> -#include <cmath> - -void SylvMatrix::multLeftI(const SqSylvMatrix& m) -{ - int off = rows - m.numRows(); - if (off < 0) { - throw SYLV_MES_EXCEPTION("Wrong matrix dimensions for multLeftI."); - } - GeneralMatrix subtmp(*this, off, 0, m.numRows(), cols); - subtmp.multLeft(m); -} - -void SylvMatrix::multLeftITrans(const SqSylvMatrix& m) -{ - int off = rows - m.numRows(); - if (off < 0) { - throw SYLV_MES_EXCEPTION("Wrong matrix dimensions for multLeftITrans."); - } - GeneralMatrix subtmp(*this, off, 0, m.numRows(), cols); - subtmp.multLeftTrans(m); -} - - -void SylvMatrix::multLeft(int zero_cols, const GeneralMatrix& a, const GeneralMatrix& b) -{ - int off = a.numRows() - a.numCols(); - if (off < 0 || a.numRows() != rows || off != zero_cols || - rows != b.numRows() || cols != b.numCols()) { - throw SYLV_MES_EXCEPTION("Wrong matrix dimensions for multLeft."); - } - // here we cannot call SylvMatrix::gemm since it would require - // another copy of (usually big) b (we are not able to do inplace - // submatrix of const GeneralMatrix) - if (a.getLD() > 0 && ld > 0) { - blas_int mm = a.numRows(); - blas_int nn = cols; - blas_int kk = a.numCols(); - double alpha = 1.0; - blas_int lda = a.getLD(); - blas_int ldb = ld; - double beta = 0.0; - blas_int ldc = ld; - dgemm("N", "N", &mm, &nn, &kk, &alpha, a.getData().base(), &lda, - b.getData().base()+off, &ldb, &beta, data.base(), &ldc); - } -} - - -void SylvMatrix::multRightKron(const SqSylvMatrix& m, int order) -{ - if (power(m.numRows(), order) != cols) { - throw SYLV_MES_EXCEPTION("Wrong number of cols for right kron multiply."); - } - KronVector auxrow(m.numRows(), m.numRows(), order-1); - for (int i = 0; i < rows; i++) { - Vector rowi(data.base()+i, rows, cols); - KronVector rowikron(rowi, m.numRows(), m.numRows(), order-1); - auxrow = rowi; // copy data - m.multVecKronTrans(rowikron, auxrow); - } -} - -void SylvMatrix::multRightKronTrans(const SqSylvMatrix& m, int order) -{ - if (power(m.numRows(), order) != cols) { - throw SYLV_MES_EXCEPTION("Wrong number of cols for right kron multiply."); - } - - KronVector auxrow(m.numRows(), m.numRows(), order-1); - for (int i = 0; i < rows; i++) { - Vector rowi(data.base()+i, rows, cols); - KronVector rowikron(rowi, m.numRows(), m.numRows(), order-1); - auxrow = rowi; // copy data - m.multVecKron(rowikron, auxrow); - } -} - -void SylvMatrix::eliminateLeft(int row, int col, Vector& x) -{ - double d = get(col, col); - double e = get(row, col); - if (std::abs(d) > std::abs(e)) { - get(row, col) = 0.0; - double mult = e/d; - for (int i = col + 1; i < numCols(); i++) { - get(row, i) = get(row, i) - mult*get(col, i); - } - x[row] = x[row] - mult*x[col]; - } else if (std::abs(e) > std::abs(d)) { - get(row, col) = 0.0; - get(col, col) = e; - double mult = d/e; - for (int i = col + 1; i < numCols(); i++) { - double tx = get(col, i); - double ty = get(row, i); - get(col, i) = ty; - get(row, i) = tx - mult*ty; - } - double tx = x[col]; - double ty = x[row]; - x[col] = ty; - x[row] = tx - mult*ty; - } -} - -void SylvMatrix::eliminateRight(int row, int col, Vector& x) -{ - double d = get(row, row); - double e = get(row, col); - - if (std::abs(d) > std::abs(e)) { - get(row, col) = 0.0; - double mult = e/d; - for (int i = 0; i < row; i++) { - get(i, col) = get(i, col) - mult*get(i, row); - } - x[col] = x[col] - mult*x[row]; - } else if (std::abs(e) > std::abs(d)) { - get(row, col) = 0.0; - get(row, row) = e; - double mult = d/e; - for (int i = 0; i < row; i++) { - double tx = get(i, row); - double ty = get(i, col); - get(i, row) = ty; - get(i, col) = tx - mult*ty; - } - double tx = x[row]; - double ty = x[col]; - x[row] = ty; - x[col] = tx - mult*ty; - } -} - - - -SqSylvMatrix::SqSylvMatrix(const GeneralMatrix& a, const GeneralMatrix& b) - : SylvMatrix(a,b) -{ - if (rows != cols) - throw SYLV_MES_EXCEPTION("Wrong matrix dimensions in multiplication constructor of square matrix."); -} - -void SqSylvMatrix::multVecKron(KronVector& x, const KronVector& d) const -{ - x.zeros(); - if (d.getDepth() == 0) { - multaVec(x, d); - } else { - KronVector aux(x.getM(), x.getN(), x.getDepth()); - for (int i = 0; i < x.getM(); i++) { - KronVector auxi(aux, i); - ConstKronVector di(d, i); - multVecKron(auxi, di); - } - for (int i = 0; i < rows; i++) { - KronVector xi(x, i); - for (int j = 0; j < cols; j++) { - KronVector auxj(aux, j); - xi.add(get(i,j),auxj); - } - } - } -} - - -void SqSylvMatrix::multVecKronTrans(KronVector& x, const KronVector& d) const -{ - x.zeros(); - if (d.getDepth() == 0) { - multaVecTrans(x, d); - } else { - KronVector aux(x.getM(), x.getN(), x.getDepth()); - for (int i = 0; i < x.getM(); i++) { - KronVector auxi(aux, i); - ConstKronVector di(d, i); - multVecKronTrans(auxi, di); - } - for (int i = 0; i < rows; i++) { - KronVector xi(x, i); - for (int j = 0; j < cols; j++) { - KronVector auxj(aux, j); - xi.add(get(j,i), auxj); - } - } - } -} - -void SqSylvMatrix::multInvLeft2(GeneralMatrix& a, GeneralMatrix& b, - double& rcond1, double& rcondinf) const -{ - if (rows != a.numRows() || rows != b.numRows()) { - throw SYLV_MES_EXCEPTION("Wrong dimensions for multInvLeft2."); - } - // PLU factorization - Vector inv(data); - lapack_int * const ipiv = new lapack_int[rows]; - lapack_int info; - lapack_int rows2 = rows; - dgetrf(&rows2, &rows2, inv.base(), &rows2, ipiv, &info); - // solve a - lapack_int acols = a.numCols(); - double* abase = a.base(); - dgetrs("N", &rows2, &acols, inv.base(), &rows2, ipiv, - abase, &rows2, &info); - // solve b - lapack_int bcols = b.numCols(); - double* bbase = b.base(); - dgetrs("N", &rows2, &bcols, inv.base(), &rows2, ipiv, - bbase, &rows2, &info); - delete [] ipiv; - - // condition numbers - double* const work = new double[4*rows]; - lapack_int* const iwork = new lapack_int[rows]; - double norm1 = getNorm1(); - dgecon("1", &rows2, inv.base(), &rows2, &norm1, &rcond1, - work, iwork, &info); - double norminf = getNormInf(); - dgecon("I", &rows2, inv.base(), &rows2, &norminf, &rcondinf, - work, iwork, &info); - delete [] iwork; - delete [] work; -} - -void SqSylvMatrix::setUnit() -{ - for (int i = 0; i < rows; i++) { - for (int j = 0; j < cols; j++) { - if (i==j) - get(i,j) = 1.0; - else - get(i,j) = 0.0; - } - } -} - -// Local Variables: -// mode:C++ -// End: diff --git a/dynare++/sylv/cc/SylvMatrix.h b/dynare++/sylv/cc/SylvMatrix.hh similarity index 98% rename from dynare++/sylv/cc/SylvMatrix.h rename to dynare++/sylv/cc/SylvMatrix.hh index 063e6b30b75ba3e5a037a62bc5a895eb01162a57..9c6b3ea0cc73ada92f76882a2c71bfb69b2c3e29 100644 --- a/dynare++/sylv/cc/SylvMatrix.h +++ b/dynare++/sylv/cc/SylvMatrix.hh @@ -5,8 +5,8 @@ #ifndef SYLV_MATRIX_H #define SYLV_MATRIX_H -#include "GeneralMatrix.h" -#include "KronVector.h" +#include "GeneralMatrix.hh" +#include "KronVector.hh" class SqSylvMatrix; diff --git a/dynare++/sylv/cc/SylvMemory.cc b/dynare++/sylv/cc/SylvMemory.cc new file mode 100644 index 0000000000000000000000000000000000000000..57eee9af17ee6b8e12cb037499abc4405113aac1 --- /dev/null +++ b/dynare++/sylv/cc/SylvMemory.cc @@ -0,0 +1,238 @@ +/* $Header: /var/lib/cvs/dynare_cpp/sylv/cc/SylvMemory.cpp,v 1.1.1.1 2004/06/04 13:00:49 kamenik Exp $ */ + +/* Tag $Name: $ */ + +#include "SylvMemory.hh" +#include "SylvException.hh" +#include "KronVector.hh" + +#if defined(MATLAB_MEX_FILE) || defined(OCTAVE_MEX_FILE) +# include <dynmex.h> +#endif + +#include <cmath> +#include <cstdio> +#include <cstdlib> + +/**********************************************************/ +/* SylvMemoryPool */ +/**********************************************************/ + +SylvMemoryPool memory_pool; + +SylvMemoryPool::SylvMemoryPool() + : base(0), length(0), allocated(0), stack_mode(false) +{ +} + +void +SylvMemoryPool::init(size_t size) +{ +#ifdef USE_MEMORY_POOL + length = size; + +# if defined(MATLAB_MEX_FILE) || defined(OCTAVE_MEX_FILE) + if (base) + throw SYLV_MES_EXCEPTION("Attempt to use matlab memory pool twice."); + base = (char *) mxMalloc(length); +# else + base = (char *) malloc(length); +# endif + +#else + throw SYLV_MES_EXCEPTION("SylvMemoryPool::init() called for non memory pool code."); +#endif +} + +void * +SylvMemoryPool::allocate(size_t size) +{ +#ifdef USE_MEMORY_POOL + if (allocated + size < length) + { + char *res = base + allocated; + allocated += size; + return res; + } + else + { + throw SYLV_MES_EXCEPTION("Run out of memory space"); + } +#else + throw SYLV_MES_EXCEPTION("SylvMemoryPool::allocate() called for non memory pool code."); +#endif +} + +void +SylvMemoryPool::free(void *p) +{ +#ifdef USE_MEMORY_POOL + int offset = ((char *) p) - base; + +# ifdef DEBUG + if (offset < 0) + throw SYLV_MES_EXCEPTION("SylvMemoryPool::free() frees wrong address < begin."); + if (offset >= (int) length) + throw SYLV_MES_EXCEPTION("SylvMemoryPool::free() frees wrong address > end."); +# endif + + if (stack_mode && offset >= 0 && offset < (int) allocated) + allocated = offset; + +#else + throw SYLV_MES_EXCEPTION("SylvMemoryPool::free() called for non memory pool code."); +#endif +} + +void +SylvMemoryPool::setStackMode(bool mode) +{ + stack_mode = mode; +} + +SylvMemoryPool::~SylvMemoryPool() +{ + reset(); +} + +void +SylvMemoryPool::reset() +{ +#if !defined(MATLAB_MEX_FILE) && !defined(OCTAVE_MEX_FILE) + delete [] base; + base = 0; + allocated = 0; + length = 0; + stack_mode = false; +#endif +} + +/**********************************************************/ +/* global new and delete */ +/**********************************************************/ + +#ifdef USE_MEMORY_POOL + +void * +operator new(size_t size) +{ + return memory_pool.allocate(size); +} + +void * +operator new[](size_t size) +{ + return memory_pool.allocate(size); +} + +void +operator delete(void *p) +{ + memory_pool.free(p); +} + +void +operator delete[](void *p) +{ + memory_pool.free(p); +} + +#endif + +/**********************************************************/ +/* saved version of global new and delete */ +/**********************************************************/ + +#ifdef USE_MEMORY_POOL +void * +MallocAllocator::operator new(size_t size) +{ +# if defined(MATLAB_MEX_FILE) || defined(OCTAVE_MEX_FILE) + throw SYLV_MES_EXCEPTION("Attempt to call wrong memory allocator."); +# else + void *res = malloc(size); + if (!res) + throw SYLV_MES_EXCEPTION("Malloc unable to allocate memory."); + return res; +# endif +} + +void * +MallocAllocator::operator new[](size_t size) +{ +# if defined(MATLAB_MEX_FILE) || defined(OCTAVE_MEX_FILE) + throw SYLV_MES_EXCEPTION("Attempt to call wrong memory allocator."); +# else + void *res = malloc(size); + if (!res) + throw SYLV_MES_EXCEPTION("Malloc unable allocate memory."); + return res; +# endif +} + +void +MallocAllocator::operator delete(void *p) +{ +# if defined(MATLAB_MEX_FILE) || defined(OCTAVE_MEX_FILE) + throw SYLV_MES_EXCEPTION("Attempt to call wrong memory destructor."); +# else + free(p); +# endif +} + +void +MallocAllocator::operator delete[](void *p) +{ +# if defined(MATLAB_MEX_FILE) || defined(OCTAVE_MEX_FILE) + throw SYLV_MES_EXCEPTION("Attempt to call wrong memory destructor."); +# else + free(p); +# endif +} + +#endif + +/**********************************************************/ +/* SylvMemoryDriver */ +/**********************************************************/ + +void +SylvMemoryDriver::allocate(int num_d, int m, int n, int order) +{ +#ifdef USE_MEMORY_POOL + int x_cols = power(m, order); + int total = num_d*x_cols*n; // storage for big matrices + total += x_cols; // storage for one extra row of a big matrix + int dig_vectors = (int) ceil(((double) (power(m, order)-1))/(m-1)); + total += 8*n*dig_vectors; // storage for kron vectors instantiated during solv + total += 50*(m*m+n*n); // some storage for small square matrices + total *= sizeof(double); // everything in doubles + memory_pool.init(total); +#endif +} + +SylvMemoryDriver::SylvMemoryDriver(int num_d, int m, int n, int order) +{ + allocate(num_d, m, n, order); +} + +SylvMemoryDriver::SylvMemoryDriver(const SylvParams &pars, int num_d, + int m, int n, int order) +{ + if (*(pars.method) == SylvParams::iter) + num_d++; + if (*(pars.want_check)) + num_d++; + allocate(num_d, m, n, order); +} + +SylvMemoryDriver::~SylvMemoryDriver() +{ + memory_pool.reset(); +} + +void +SylvMemoryDriver::setStackMode(bool mode) +{ + memory_pool.setStackMode(mode); +} diff --git a/dynare++/sylv/cc/SylvMemory.cpp b/dynare++/sylv/cc/SylvMemory.cpp deleted file mode 100644 index 8f7a21738948fc1b8ea0a0dd208e08865fc16ad2..0000000000000000000000000000000000000000 --- a/dynare++/sylv/cc/SylvMemory.cpp +++ /dev/null @@ -1,221 +0,0 @@ -/* $Header: /var/lib/cvs/dynare_cpp/sylv/cc/SylvMemory.cpp,v 1.1.1.1 2004/06/04 13:00:49 kamenik Exp $ */ - -/* Tag $Name: $ */ - -#include "SylvMemory.h" -#include "SylvException.h" -#include "KronVector.h" - -#if defined(MATLAB_MEX_FILE) || defined(OCTAVE_MEX_FILE) -# include <dynmex.h> -#endif - -#include <cmath> -#include <cstdio> -#include <cstdlib> - -/**********************************************************/ -/* SylvMemoryPool */ -/**********************************************************/ - -SylvMemoryPool memory_pool; - -SylvMemoryPool::SylvMemoryPool() - : base(0), length(0), allocated(0), stack_mode(false) -{ -} - -void SylvMemoryPool::init(size_t size) -{ -#ifdef USE_MEMORY_POOL - length = size; - -#if defined(MATLAB_MEX_FILE) || defined(OCTAVE_MEX_FILE) - if (base) - throw SYLV_MES_EXCEPTION("Attempt to use matlab memory pool twice."); - base = (char*) mxMalloc(length); -#else - base = (char*) malloc(length); -#endif - -#else - throw SYLV_MES_EXCEPTION("SylvMemoryPool::init() called for non memory pool code."); -#endif -} - -void* SylvMemoryPool::allocate(size_t size) -{ -#ifdef USE_MEMORY_POOL - if (allocated + size < length) { - char* res = base + allocated; - allocated += size; - return res; - } else { - throw SYLV_MES_EXCEPTION("Run out of memory space"); - } -#else - throw SYLV_MES_EXCEPTION("SylvMemoryPool::allocate() called for non memory pool code."); -#endif -} - -void SylvMemoryPool::free(void* p) -{ -#ifdef USE_MEMORY_POOL - int offset = ((char*)p) - base; - -#ifdef DEBUG - if (offset < 0) - throw SYLV_MES_EXCEPTION("SylvMemoryPool::free() frees wrong address < begin."); - if (offset >= (int)length) - throw SYLV_MES_EXCEPTION("SylvMemoryPool::free() frees wrong address > end."); -#endif - - if (stack_mode && offset >= 0 && offset < (int)allocated) - allocated = offset; - -#else - throw SYLV_MES_EXCEPTION("SylvMemoryPool::free() called for non memory pool code."); -#endif -} - -void SylvMemoryPool::setStackMode(bool mode) -{ - stack_mode = mode; -} - -SylvMemoryPool::~SylvMemoryPool() -{ - reset(); -} - -void SylvMemoryPool::reset() -{ -#if !defined(MATLAB_MEX_FILE) && !defined(OCTAVE_MEX_FILE) - delete [] base; - base = 0; - allocated = 0; - length = 0; - stack_mode = false; -#endif -} - -/**********************************************************/ -/* global new and delete */ -/**********************************************************/ - -#ifdef USE_MEMORY_POOL - -void* operator new(size_t size) -{ - return memory_pool.allocate(size); -} - -void* operator new[](size_t size) -{ - return memory_pool.allocate(size); -} - -void operator delete(void* p) -{ - memory_pool.free(p); -} - -void operator delete[](void* p) -{ - memory_pool.free(p); -} - -#endif - -/**********************************************************/ -/* saved version of global new and delete */ -/**********************************************************/ - -#ifdef USE_MEMORY_POOL -void* MallocAllocator::operator new(size_t size) -{ -#if defined(MATLAB_MEX_FILE) || defined(OCTAVE_MEX_FILE) - throw SYLV_MES_EXCEPTION("Attempt to call wrong memory allocator."); -#else - void* res = malloc(size); - if (!res) - throw SYLV_MES_EXCEPTION("Malloc unable to allocate memory."); - return res; -#endif -} - -void* MallocAllocator::operator new[](size_t size) -{ -#if defined(MATLAB_MEX_FILE) || defined(OCTAVE_MEX_FILE) - throw SYLV_MES_EXCEPTION("Attempt to call wrong memory allocator."); -#else - void* res = malloc(size); - if (!res) - throw SYLV_MES_EXCEPTION("Malloc unable allocate memory."); - return res; -#endif -} - -void MallocAllocator::operator delete(void* p) -{ -#if defined(MATLAB_MEX_FILE) || defined(OCTAVE_MEX_FILE) - throw SYLV_MES_EXCEPTION("Attempt to call wrong memory destructor."); -#else - free(p); -#endif -} - -void MallocAllocator::operator delete[](void* p) -{ -#if defined(MATLAB_MEX_FILE) || defined(OCTAVE_MEX_FILE) - throw SYLV_MES_EXCEPTION("Attempt to call wrong memory destructor."); -#else - free(p); -#endif -} - -#endif - - -/**********************************************************/ -/* SylvMemoryDriver */ -/**********************************************************/ - -void SylvMemoryDriver::allocate(int num_d, int m, int n, int order) -{ -#ifdef USE_MEMORY_POOL - int x_cols = power(m,order); - int total = num_d*x_cols*n; // storage for big matrices - total += x_cols; // storage for one extra row of a big matrix - int dig_vectors = (int)ceil(((double)(power(m,order)-1))/(m-1)); - total += 8*n*dig_vectors; // storage for kron vectors instantiated during solv - total += 50*(m*m+n*n); // some storage for small square matrices - total *= sizeof(double); // everything in doubles - memory_pool.init(total); -#endif -} - - -SylvMemoryDriver::SylvMemoryDriver(int num_d, int m, int n, int order) -{ - allocate(num_d, m, n, order); -} - -SylvMemoryDriver::SylvMemoryDriver(const SylvParams& pars, int num_d, - int m, int n, int order) -{ - if (*(pars.method) == SylvParams::iter) - num_d++; - if (*(pars.want_check)) - num_d++; - allocate(num_d, m, n, order); -} - -SylvMemoryDriver::~SylvMemoryDriver() -{ - memory_pool.reset(); -} - -void SylvMemoryDriver::setStackMode(bool mode) { - memory_pool.setStackMode(mode); -} diff --git a/dynare++/sylv/cc/SylvMemory.h b/dynare++/sylv/cc/SylvMemory.hh similarity index 98% rename from dynare++/sylv/cc/SylvMemory.h rename to dynare++/sylv/cc/SylvMemory.hh index 48a0fcd3dc095779c70d69f230ec0ed6369fa9c9..73a35dfc7f38e1a6ed07abcfcaaf28d47fc59052 100644 --- a/dynare++/sylv/cc/SylvMemory.h +++ b/dynare++/sylv/cc/SylvMemory.hh @@ -5,7 +5,7 @@ #ifndef SYLV_MEMORY_H #define SYLV_MEMORY_H -#include "SylvParams.h" +#include "SylvParams.hh" #include <new> diff --git a/dynare++/sylv/cc/SylvParams.cc b/dynare++/sylv/cc/SylvParams.cc new file mode 100644 index 0000000000000000000000000000000000000000..6d03ef39de1570452bbee3a911a7c032642a1385 --- /dev/null +++ b/dynare++/sylv/cc/SylvParams.cc @@ -0,0 +1,241 @@ +/* $Header: /var/lib/cvs/dynare_cpp/sylv/cc/SylvParams.cpp,v 1.1.1.1 2004/06/04 13:00:52 kamenik Exp $ */ + +/* Tag $Name: $ */ + +#include "SylvParams.hh" + +void +SylvParams::print(const char *prefix) const +{ + print(stdout, prefix); +} + +void +SylvParams::print(FILE *fdesc, const char *prefix) const +{ + rcondA1.print(fdesc, prefix, "reci. cond1 A ", "%8.4g"); + rcondAI.print(fdesc, prefix, "reci. condInf A ", "%8.4g"); + bs_norm.print(fdesc, prefix, "log10 diag norm ", "%8.4g"); + f_err1.print(fdesc, prefix, "abs. err 1 F diag ", "%8.4g"); + f_errI.print(fdesc, prefix, "abs. err I F diag ", "%8.4g"); + viv_err1.print(fdesc, prefix, "abs. err 1 V*invV ", "%8.4g"); + viv_errI.print(fdesc, prefix, "abs. err I V*invV ", "%8.4g"); + ivv_err1.print(fdesc, prefix, "abs. err 1 invV*V ", "%8.4g"); + ivv_errI.print(fdesc, prefix, "abs. err I invV*V ", "%8.4g"); + f_blocks.print(fdesc, prefix, "num blocks in F ", "%d"); + f_largest.print(fdesc, prefix, "largest block in F ", "%d"); + f_zeros.print(fdesc, prefix, "num zeros in F ", "%d"); + f_offdiag.print(fdesc, prefix, "num offdiag in F ", "%d"); + if (*method == iter) + { + converged.print(fdesc, prefix, "converged ", "%d"); + convergence_tol.print(fdesc, prefix, "convergence tol. ", "%8.4g"); + iter_last_norm.print(fdesc, prefix, "last norm ", "%8.4g"); + max_num_iter.print(fdesc, prefix, "max num iter ", "%d"); + num_iter.print(fdesc, prefix, "num iter ", "%d"); + } + else + { + eig_min.print(fdesc, prefix, "minimum eigenvalue ", "%8.4g"); + } + mat_err1.print(fdesc, prefix, "rel. matrix norm1 ", "%8.4g"); + mat_errI.print(fdesc, prefix, "rel. matrix normInf", "%8.4g"); + mat_errF.print(fdesc, prefix, "rel. matrix normFro", "%8.4g"); + vec_err1.print(fdesc, prefix, "rel. vector norm1 ", "%8.4g"); + vec_errI.print(fdesc, prefix, "rel. vector normInf", "%8.4g"); + cpu_time.print(fdesc, prefix, "time (CPU secs) ", "%8.4g"); +} + +void +SylvParams::copy(const SylvParams &p) +{ + method = p.method; + convergence_tol = p.convergence_tol; + max_num_iter = p.max_num_iter; + bs_norm = p.bs_norm; + want_check = p.want_check; + converged = p.converged; + iter_last_norm = p.iter_last_norm; + num_iter = p.num_iter; + f_err1 = p.f_err1; + f_errI = p.f_errI; + viv_err1 = p.viv_err1; + viv_errI = p.viv_errI; + ivv_err1 = p.ivv_err1; + ivv_errI = p.ivv_errI; + f_blocks = p.f_blocks; + f_largest = p.f_largest; + f_zeros = p.f_zeros; + f_offdiag = p.f_offdiag; + rcondA1 = p.rcondA1; + rcondAI = p.rcondAI; + eig_min = p.eig_min; + mat_err1 = p.mat_err1; + mat_errI = p.mat_errI; + mat_errF = p.mat_errF; + vec_err1 = p.vec_err1; + vec_errI = p.vec_errI; + cpu_time = p.cpu_time; +} + +void +SylvParams::setArrayNames(int &num, const char **names) const +{ + num = 0; + if (method.getStatus() != undef) + names[num++] = "method"; + if (convergence_tol.getStatus() != undef) + names[num++] = "convergence_tol"; + if (max_num_iter.getStatus() != undef) + names[num++] = "max_num_iter"; + if (bs_norm.getStatus() != undef) + names[num++] = "bs_norm"; + if (converged.getStatus() != undef) + names[num++] = "converged"; + if (iter_last_norm.getStatus() != undef) + names[num++] = "iter_last_norm"; + if (num_iter.getStatus() != undef) + names[num++] = "num_iter"; + if (f_err1.getStatus() != undef) + names[num++] = "f_err1"; + if (f_errI.getStatus() != undef) + names[num++] = "f_errI"; + if (viv_err1.getStatus() != undef) + names[num++] = "viv_err1"; + if (viv_errI.getStatus() != undef) + names[num++] = "viv_errI"; + if (ivv_err1.getStatus() != undef) + names[num++] = "ivv_err1"; + if (ivv_errI.getStatus() != undef) + names[num++] = "ivv_errI"; + if (f_blocks.getStatus() != undef) + names[num++] = "f_blocks"; + if (f_largest.getStatus() != undef) + names[num++] = "f_largest"; + if (f_zeros.getStatus() != undef) + names[num++] = "f_zeros"; + if (f_offdiag.getStatus() != undef) + names[num++] = "f_offdiag"; + if (rcondA1.getStatus() != undef) + names[num++] = "rcondA1"; + if (rcondAI.getStatus() != undef) + names[num++] = "rcondAI"; + if (eig_min.getStatus() != undef) + names[num++] = "eig_min"; + if (mat_err1.getStatus() != undef) + names[num++] = "mat_err1"; + if (mat_errI.getStatus() != undef) + names[num++] = "mat_errI"; + if (mat_errF.getStatus() != undef) + names[num++] = "mat_errF"; + if (vec_err1.getStatus() != undef) + names[num++] = "vec_err1"; + if (vec_errI.getStatus() != undef) + names[num++] = "vec_errI"; + if (cpu_time.getStatus() != undef) + names[num++] = "cpu_time"; +} + +#if defined(MATLAB_MEX_FILE) || defined(OCTAVE_MEX_FILE) +mxArray * +SylvParams::DoubleParamItem::createMatlabArray() const +{ + return mxCreateDoubleScalar(value); +} + +mxArray * +SylvParams::IntParamItem::createMatlabArray() const +{ + mxArray *res = mxCreateNumericMatrix(1, 1, mxINT32_CLASS, mxREAL); + *((int *) mxGetData(res)) = value; + return res; +} + +mxArray * +SylvParams::BoolParamItem::createMatlabArray() const +{ + if (value) + return mxCreateString("true"); + else + return mxCreateString("false"); +} + +mxArray * +SylvParams::MethodParamItem::createMatlabArray() const +{ + if (value == iter) + return mxCreateString("iterative"); + else + return mxCreateString("recursive"); +} + +mxArray * +SylvParams::createStructArray() const +{ + const char *names[50]; + int num; + setArrayNames(num, names); + const mwSize dims[] = {1, 1}; + mxArray *const res = mxCreateStructArray(2, dims, num, names); + + int i = 0; + if (method.getStatus() != undef) + mxSetFieldByNumber(res, 0, i++, method.createMatlabArray()); + if (convergence_tol.getStatus() != undef) + mxSetFieldByNumber(res, 0, i++, convergence_tol.createMatlabArray()); + if (max_num_iter.getStatus() != undef) + mxSetFieldByNumber(res, 0, i++, max_num_iter.createMatlabArray()); + if (bs_norm.getStatus() != undef) + mxSetFieldByNumber(res, 0, i++, bs_norm.createMatlabArray()); + if (converged.getStatus() != undef) + mxSetFieldByNumber(res, 0, i++, converged.createMatlabArray()); + if (iter_last_norm.getStatus() != undef) + mxSetFieldByNumber(res, 0, i++, iter_last_norm.createMatlabArray()); + if (num_iter.getStatus() != undef) + mxSetFieldByNumber(res, 0, i++, num_iter.createMatlabArray()); + if (f_err1.getStatus() != undef) + mxSetFieldByNumber(res, 0, i++, f_err1.createMatlabArray()); + if (f_errI.getStatus() != undef) + mxSetFieldByNumber(res, 0, i++, f_errI.createMatlabArray()); + if (viv_err1.getStatus() != undef) + mxSetFieldByNumber(res, 0, i++, viv_err1.createMatlabArray()); + if (viv_errI.getStatus() != undef) + mxSetFieldByNumber(res, 0, i++, viv_errI.createMatlabArray()); + if (ivv_err1.getStatus() != undef) + mxSetFieldByNumber(res, 0, i++, ivv_err1.createMatlabArray()); + if (ivv_errI.getStatus() != undef) + mxSetFieldByNumber(res, 0, i++, ivv_errI.createMatlabArray()); + if (f_blocks.getStatus() != undef) + mxSetFieldByNumber(res, 0, i++, f_blocks.createMatlabArray()); + if (f_largest.getStatus() != undef) + mxSetFieldByNumber(res, 0, i++, f_largest.createMatlabArray()); + if (f_zeros.getStatus() != undef) + mxSetFieldByNumber(res, 0, i++, f_zeros.createMatlabArray()); + if (f_offdiag.getStatus() != undef) + mxSetFieldByNumber(res, 0, i++, f_offdiag.createMatlabArray()); + if (rcondA1.getStatus() != undef) + mxSetFieldByNumber(res, 0, i++, rcondA1.createMatlabArray()); + if (rcondAI.getStatus() != undef) + mxSetFieldByNumber(res, 0, i++, rcondAI.createMatlabArray()); + if (eig_min.getStatus() != undef) + mxSetFieldByNumber(res, 0, i++, eig_min.createMatlabArray()); + if (mat_err1.getStatus() != undef) + mxSetFieldByNumber(res, 0, i++, mat_err1.createMatlabArray()); + if (mat_errI.getStatus() != undef) + mxSetFieldByNumber(res, 0, i++, mat_errI.createMatlabArray()); + if (mat_errF.getStatus() != undef) + mxSetFieldByNumber(res, 0, i++, mat_errF.createMatlabArray()); + if (vec_err1.getStatus() != undef) + mxSetFieldByNumber(res, 0, i++, vec_err1.createMatlabArray()); + if (vec_errI.getStatus() != undef) + mxSetFieldByNumber(res, 0, i++, vec_errI.createMatlabArray()); + if (cpu_time.getStatus() != undef) + mxSetFieldByNumber(res, 0, i++, cpu_time.createMatlabArray()); + + return res; +} +#endif + +// Local Variables: +// mode:C++ +// End: diff --git a/dynare++/sylv/cc/SylvParams.cpp b/dynare++/sylv/cc/SylvParams.cpp deleted file mode 100644 index ee1b90e480d2ea818feeb98564519fc5091c4050..0000000000000000000000000000000000000000 --- a/dynare++/sylv/cc/SylvParams.cpp +++ /dev/null @@ -1,230 +0,0 @@ -/* $Header: /var/lib/cvs/dynare_cpp/sylv/cc/SylvParams.cpp,v 1.1.1.1 2004/06/04 13:00:52 kamenik Exp $ */ - -/* Tag $Name: $ */ - -#include "SylvParams.h" - - -void SylvParams::print(const char* prefix) const -{ - print(stdout, prefix); -} - -void SylvParams::print(FILE* fdesc, const char* prefix) const -{ - rcondA1.print(fdesc, prefix, "reci. cond1 A ", "%8.4g"); - rcondAI.print(fdesc, prefix, "reci. condInf A ", "%8.4g"); - bs_norm.print(fdesc, prefix, "log10 diag norm ", "%8.4g"); - f_err1.print(fdesc, prefix, "abs. err 1 F diag ", "%8.4g"); - f_errI.print(fdesc, prefix, "abs. err I F diag ", "%8.4g"); - viv_err1.print(fdesc, prefix, "abs. err 1 V*invV ", "%8.4g"); - viv_errI.print(fdesc, prefix, "abs. err I V*invV ", "%8.4g"); - ivv_err1.print(fdesc, prefix, "abs. err 1 invV*V ", "%8.4g"); - ivv_errI.print(fdesc, prefix, "abs. err I invV*V ", "%8.4g"); - f_blocks.print(fdesc, prefix, "num blocks in F ", "%d"); - f_largest.print(fdesc, prefix,"largest block in F ", "%d"); - f_zeros.print(fdesc, prefix, "num zeros in F ", "%d"); - f_offdiag.print(fdesc, prefix,"num offdiag in F ", "%d"); - if (*method == iter) { - converged.print(fdesc, prefix, "converged ", "%d"); - convergence_tol.print(fdesc, prefix, "convergence tol. ", "%8.4g"); - iter_last_norm.print(fdesc, prefix, "last norm ", "%8.4g"); - max_num_iter.print(fdesc, prefix, "max num iter ", "%d"); - num_iter.print(fdesc, prefix, "num iter ", "%d"); - } else { - eig_min.print(fdesc, prefix, "minimum eigenvalue ", "%8.4g"); - } - mat_err1.print(fdesc, prefix, "rel. matrix norm1 ", "%8.4g"); - mat_errI.print(fdesc, prefix, "rel. matrix normInf", "%8.4g"); - mat_errF.print(fdesc, prefix, "rel. matrix normFro", "%8.4g"); - vec_err1.print(fdesc, prefix, "rel. vector norm1 ", "%8.4g"); - vec_errI.print(fdesc, prefix, "rel. vector normInf", "%8.4g"); - cpu_time.print(fdesc, prefix, "time (CPU secs) ", "%8.4g"); -} - -void SylvParams::copy(const SylvParams& p) -{ - method = p.method; - convergence_tol = p.convergence_tol; - max_num_iter = p.max_num_iter; - bs_norm = p.bs_norm; - want_check = p.want_check; - converged = p.converged; - iter_last_norm = p.iter_last_norm; - num_iter = p.num_iter; - f_err1 = p.f_err1; - f_errI = p.f_errI; - viv_err1 = p.viv_err1; - viv_errI = p.viv_errI; - ivv_err1 = p.ivv_err1; - ivv_errI = p.ivv_errI; - f_blocks = p.f_blocks; - f_largest = p.f_largest; - f_zeros = p.f_zeros; - f_offdiag = p.f_offdiag; - rcondA1 = p.rcondA1; - rcondAI = p.rcondAI; - eig_min = p.eig_min; - mat_err1 = p.mat_err1; - mat_errI = p.mat_errI; - mat_errF = p.mat_errF; - vec_err1 = p.vec_err1; - vec_errI = p.vec_errI; - cpu_time = p.cpu_time; -} - -void SylvParams::setArrayNames(int& num, const char** names) const -{ - num = 0; - if (method.getStatus() != undef) - names[num++] = "method"; - if (convergence_tol.getStatus() != undef) - names[num++] = "convergence_tol"; - if (max_num_iter.getStatus() != undef) - names[num++] = "max_num_iter"; - if (bs_norm.getStatus() != undef) - names[num++] = "bs_norm"; - if (converged.getStatus() != undef) - names[num++] = "converged"; - if (iter_last_norm.getStatus() != undef) - names[num++] = "iter_last_norm"; - if (num_iter.getStatus() != undef) - names[num++] = "num_iter"; - if (f_err1.getStatus() != undef) - names[num++] = "f_err1"; - if (f_errI.getStatus() != undef) - names[num++] = "f_errI"; - if (viv_err1.getStatus() != undef) - names[num++] = "viv_err1"; - if (viv_errI.getStatus() != undef) - names[num++] = "viv_errI"; - if (ivv_err1.getStatus() != undef) - names[num++] = "ivv_err1"; - if (ivv_errI.getStatus() != undef) - names[num++] = "ivv_errI"; - if (f_blocks.getStatus() != undef) - names[num++] = "f_blocks"; - if (f_largest.getStatus() != undef) - names[num++] = "f_largest"; - if (f_zeros.getStatus() != undef) - names[num++] = "f_zeros"; - if (f_offdiag.getStatus() != undef) - names[num++] = "f_offdiag"; - if (rcondA1.getStatus() != undef) - names[num++] = "rcondA1"; - if (rcondAI.getStatus() != undef) - names[num++] = "rcondAI"; - if (eig_min.getStatus() != undef) - names[num++] = "eig_min"; - if (mat_err1.getStatus() != undef) - names[num++] = "mat_err1"; - if (mat_errI.getStatus() != undef) - names[num++] = "mat_errI"; - if (mat_errF.getStatus() != undef) - names[num++] = "mat_errF"; - if (vec_err1.getStatus() != undef) - names[num++] = "vec_err1"; - if (vec_errI.getStatus() != undef) - names[num++] = "vec_errI"; - if (cpu_time.getStatus() != undef) - names[num++] = "cpu_time"; -} - -#if defined(MATLAB_MEX_FILE) || defined(OCTAVE_MEX_FILE) -mxArray* SylvParams::DoubleParamItem::createMatlabArray() const -{ - return mxCreateDoubleScalar(value); -} - -mxArray* SylvParams::IntParamItem::createMatlabArray() const -{ - mxArray* res = mxCreateNumericMatrix(1, 1, mxINT32_CLASS, mxREAL); - *((int*)mxGetData(res)) = value; - return res; -} - -mxArray* SylvParams::BoolParamItem::createMatlabArray() const -{ - if (value) - return mxCreateString("true"); - else - return mxCreateString("false"); -} - -mxArray* SylvParams::MethodParamItem::createMatlabArray() const -{ - if (value == iter) - return mxCreateString("iterative"); - else - return mxCreateString("recursive"); -} - -mxArray* SylvParams::createStructArray() const -{ - const char* names[50]; - int num; - setArrayNames(num, names); - const mwSize dims[] = {1, 1}; - mxArray* const res = mxCreateStructArray(2, dims, num, names); - - int i = 0; - if (method.getStatus() != undef) - mxSetFieldByNumber(res, 0, i++, method.createMatlabArray()); - if (convergence_tol.getStatus() != undef) - mxSetFieldByNumber(res, 0, i++, convergence_tol.createMatlabArray()); - if (max_num_iter.getStatus() != undef) - mxSetFieldByNumber(res, 0, i++, max_num_iter.createMatlabArray()); - if (bs_norm.getStatus() != undef) - mxSetFieldByNumber(res, 0, i++, bs_norm.createMatlabArray()); - if (converged.getStatus() != undef) - mxSetFieldByNumber(res, 0, i++, converged.createMatlabArray()); - if (iter_last_norm.getStatus() != undef) - mxSetFieldByNumber(res, 0, i++, iter_last_norm.createMatlabArray()); - if (num_iter.getStatus() != undef) - mxSetFieldByNumber(res, 0, i++, num_iter.createMatlabArray()); - if (f_err1.getStatus() != undef) - mxSetFieldByNumber(res, 0, i++, f_err1.createMatlabArray()); - if (f_errI.getStatus() != undef) - mxSetFieldByNumber(res, 0, i++, f_errI.createMatlabArray()); - if (viv_err1.getStatus() != undef) - mxSetFieldByNumber(res, 0, i++, viv_err1.createMatlabArray()); - if (viv_errI.getStatus() != undef) - mxSetFieldByNumber(res, 0, i++, viv_errI.createMatlabArray()); - if (ivv_err1.getStatus() != undef) - mxSetFieldByNumber(res, 0, i++, ivv_err1.createMatlabArray()); - if (ivv_errI.getStatus() != undef) - mxSetFieldByNumber(res, 0, i++, ivv_errI.createMatlabArray()); - if (f_blocks.getStatus() != undef) - mxSetFieldByNumber(res, 0, i++, f_blocks.createMatlabArray()); - if (f_largest.getStatus() != undef) - mxSetFieldByNumber(res, 0, i++, f_largest.createMatlabArray()); - if (f_zeros.getStatus() != undef) - mxSetFieldByNumber(res, 0, i++, f_zeros.createMatlabArray()); - if (f_offdiag.getStatus() != undef) - mxSetFieldByNumber(res, 0, i++, f_offdiag.createMatlabArray()); - if (rcondA1.getStatus() != undef) - mxSetFieldByNumber(res, 0, i++, rcondA1.createMatlabArray()); - if (rcondAI.getStatus() != undef) - mxSetFieldByNumber(res, 0, i++, rcondAI.createMatlabArray()); - if (eig_min.getStatus() != undef) - mxSetFieldByNumber(res, 0, i++, eig_min.createMatlabArray()); - if (mat_err1.getStatus() != undef) - mxSetFieldByNumber(res, 0, i++, mat_err1.createMatlabArray()); - if (mat_errI.getStatus() != undef) - mxSetFieldByNumber(res, 0, i++, mat_errI.createMatlabArray()); - if (mat_errF.getStatus() != undef) - mxSetFieldByNumber(res, 0, i++, mat_errF.createMatlabArray()); - if (vec_err1.getStatus() != undef) - mxSetFieldByNumber(res, 0, i++, vec_err1.createMatlabArray()); - if (vec_errI.getStatus() != undef) - mxSetFieldByNumber(res, 0, i++, vec_errI.createMatlabArray()); - if (cpu_time.getStatus() != undef) - mxSetFieldByNumber(res, 0, i++, cpu_time.createMatlabArray()); - - return res; -} -#endif - -// Local Variables: -// mode:C++ -// End: diff --git a/dynare++/sylv/cc/SylvParams.h b/dynare++/sylv/cc/SylvParams.hh similarity index 100% rename from dynare++/sylv/cc/SylvParams.h rename to dynare++/sylv/cc/SylvParams.hh diff --git a/dynare++/sylv/cc/SylvesterSolver.h b/dynare++/sylv/cc/SylvesterSolver.hh similarity index 89% rename from dynare++/sylv/cc/SylvesterSolver.h rename to dynare++/sylv/cc/SylvesterSolver.hh index 344abd12740edc668aae6eb132191fe802677a0a..aa61c74244ecdcb7729737ecd4caee08bb3dec99 100644 --- a/dynare++/sylv/cc/SylvesterSolver.h +++ b/dynare++/sylv/cc/SylvesterSolver.hh @@ -5,12 +5,12 @@ #ifndef SYLVESTER_SOLVER_H #define SYLVESTER_SOLVER_H -#include "KronVector.h" -#include "QuasiTriangular.h" -#include "QuasiTriangularZero.h" -#include "SimilarityDecomp.h" -#include "SylvParams.h" -#include "SchurDecomp.h" +#include "KronVector.hh" +#include "QuasiTriangular.hh" +#include "QuasiTriangularZero.hh" +#include "SimilarityDecomp.hh" +#include "SylvParams.hh" +#include "SchurDecomp.hh" class SylvesterSolver { diff --git a/dynare++/sylv/cc/SymSchurDecomp.cc b/dynare++/sylv/cc/SymSchurDecomp.cc new file mode 100644 index 0000000000000000000000000000000000000000..d5df7efb86eb30f389df7b7a2093581337bcee93 --- /dev/null +++ b/dynare++/sylv/cc/SymSchurDecomp.cc @@ -0,0 +1,104 @@ +/* $Header$ */ + +/* Tag $Name$ */ + +#include "SymSchurDecomp.hh" +#include "SylvException.hh" + +#include <dynlapack.h> + +#include <algorithm> +#include <cmath> + +SymSchurDecomp::SymSchurDecomp(const GeneralMatrix &mata) + : lambda(mata.numRows()), q(mata.numRows()) +{ + // check mata is square + if (mata.numRows() != mata.numCols()) + throw SYLV_MES_EXCEPTION("Matrix is not square in SymSchurDecomp constructor"); + + // prepare for dsyevr + const char *jobz = "V"; + const char *range = "A"; + const char *uplo = "U"; + lapack_int n = mata.numRows(); + GeneralMatrix tmpa(mata); + double *a = tmpa.base(); + lapack_int lda = tmpa.getLD(); + double dum; + double *vl = &dum; + double *vu = &dum; + lapack_int idum; + lapack_int *il = &idum; + lapack_int *iu = &idum; + double abstol = 0.0; + lapack_int m = n; + double *w = lambda.base(); + double *z = q.base(); + lapack_int ldz = q.getLD(); + lapack_int *isuppz = new lapack_int[2*std::max(1, (int) m)]; + double tmpwork; + lapack_int lwork = -1; + lapack_int tmpiwork; + lapack_int liwork = -1; + lapack_int info; + + // query for lwork and liwork + dsyevr(jobz, range, uplo, &n, a, &lda, vl, vu, il, iu, &abstol, + &m, w, z, &ldz, isuppz, &tmpwork, &lwork, &tmpiwork, &liwork, &info); + lwork = (int) tmpwork; + liwork = tmpiwork; + // allocate work arrays + double *work = new double[lwork]; + lapack_int *iwork = new lapack_int[liwork]; + + // do the calculation + dsyevr(jobz, range, uplo, &n, a, &lda, vl, vu, il, iu, &abstol, + &m, w, z, &ldz, isuppz, work, &lwork, iwork, &liwork, &info); + + if (info < 0) + throw SYLV_MES_EXCEPTION("Internal error in SymSchurDecomp constructor"); + if (info > 0) + throw SYLV_MES_EXCEPTION("Internal LAPACK error in DSYEVR"); + + delete [] work; + delete [] iwork; + delete [] isuppz; +} + +void +SymSchurDecomp::getFactor(GeneralMatrix &f) const +{ + if (f.numRows() != q.numRows()) + throw SYLV_MES_EXCEPTION("Wrong dimension of factor matrix in SymSchurDecomp::getFactor"); + if (f.numRows() != f.numCols()) + throw SYLV_MES_EXCEPTION("Factor matrix is not square in SymSchurDecomp::getFactor"); + if (!isPositiveSemidefinite()) + throw SYLV_MES_EXCEPTION("Symmetric decomposition not positive semidefinite in SymSchurDecomp::getFactor"); + + f = q; + for (int i = 0; i < f.numCols(); i++) + { + Vector fi(f, i); + fi.mult(std::sqrt(lambda[i])); + } +} + +// LAPACK says that eigenvalues are ordered in ascending order, but we +// do not rely her on it +bool +SymSchurDecomp::isPositiveSemidefinite() const +{ + for (int i = 0; i < lambda.length(); i++) + if (lambda[i] < 0) + return false; + return true; +} + +void +SymSchurDecomp::correctDefinitness(double tol) +{ + for (int i = 0; i < lambda.length(); i++) + if (lambda[i] < 0 && lambda[i] > -tol) + lambda[i] = 0.0; +} diff --git a/dynare++/sylv/cc/SymSchurDecomp.cpp b/dynare++/sylv/cc/SymSchurDecomp.cpp deleted file mode 100644 index 1bedc3b88f4d6a44ad64a5e700db1483d6bf1a18..0000000000000000000000000000000000000000 --- a/dynare++/sylv/cc/SymSchurDecomp.cpp +++ /dev/null @@ -1,101 +0,0 @@ -/* $Header$ */ - -/* Tag $Name$ */ - -#include "SymSchurDecomp.h" -#include "SylvException.h" - -#include <dynlapack.h> - -#include <algorithm> -#include <cmath> - -SymSchurDecomp::SymSchurDecomp(const GeneralMatrix& mata) - : lambda(mata.numRows()), q(mata.numRows()) -{ - // check mata is square - if (mata.numRows() != mata.numCols()) - throw SYLV_MES_EXCEPTION("Matrix is not square in SymSchurDecomp constructor"); - - // prepare for dsyevr - const char* jobz = "V"; - const char* range = "A"; - const char* uplo = "U"; - lapack_int n = mata.numRows(); - GeneralMatrix tmpa(mata); - double* a = tmpa.base(); - lapack_int lda = tmpa.getLD(); - double dum; - double* vl = &dum; - double* vu = &dum; - lapack_int idum; - lapack_int* il = &idum; - lapack_int* iu = &idum; - double abstol = 0.0; - lapack_int m = n; - double* w = lambda.base(); - double* z = q.base(); - lapack_int ldz = q.getLD(); - lapack_int* isuppz = new lapack_int[2*std::max(1,(int) m)]; - double tmpwork; - lapack_int lwork = -1; - lapack_int tmpiwork; - lapack_int liwork = -1; - lapack_int info; - - // query for lwork and liwork - dsyevr(jobz, range, uplo, &n, a, &lda, vl, vu, il, iu, &abstol, - &m, w, z, &ldz, isuppz, &tmpwork, &lwork, &tmpiwork, &liwork, &info); - lwork = (int)tmpwork; - liwork = tmpiwork; - // allocate work arrays - double* work = new double[lwork]; - lapack_int* iwork = new lapack_int[liwork]; - - // do the calculation - dsyevr(jobz, range, uplo, &n, a, &lda, vl, vu, il, iu, &abstol, - &m, w, z, &ldz, isuppz, work, &lwork, iwork, &liwork, &info); - - if (info < 0) - throw SYLV_MES_EXCEPTION("Internal error in SymSchurDecomp constructor"); - if (info > 0) - throw SYLV_MES_EXCEPTION("Internal LAPACK error in DSYEVR"); - - delete [] work; - delete [] iwork; - delete [] isuppz; -} - -void SymSchurDecomp::getFactor(GeneralMatrix& f) const -{ - if (f.numRows() != q.numRows()) - throw SYLV_MES_EXCEPTION("Wrong dimension of factor matrix in SymSchurDecomp::getFactor"); - if (f.numRows() != f.numCols()) - throw SYLV_MES_EXCEPTION("Factor matrix is not square in SymSchurDecomp::getFactor"); - if (! isPositiveSemidefinite()) - throw SYLV_MES_EXCEPTION("Symmetric decomposition not positive semidefinite in SymSchurDecomp::getFactor"); - - f = q; - for (int i = 0; i < f.numCols(); i++) { - Vector fi(f, i); - fi.mult(std::sqrt(lambda[i])); - } -} - - -// LAPACK says that eigenvalues are ordered in ascending order, but we -// do not rely her on it -bool SymSchurDecomp::isPositiveSemidefinite() const -{ - for (int i = 0; i < lambda.length(); i++) - if (lambda[i] < 0) - return false; - return true; -} - -void SymSchurDecomp::correctDefinitness(double tol) -{ - for (int i = 0; i < lambda.length(); i++) - if (lambda[i] < 0 && lambda[i] > - tol) - lambda[i] = 0.0; -} diff --git a/dynare++/sylv/cc/SymSchurDecomp.h b/dynare++/sylv/cc/SymSchurDecomp.hh similarity index 97% rename from dynare++/sylv/cc/SymSchurDecomp.h rename to dynare++/sylv/cc/SymSchurDecomp.hh index 9b95f36bff767acc212f1a47d3cebd5e9d24488b..4ce35b4c477c695f033930471095ab26396b7726 100644 --- a/dynare++/sylv/cc/SymSchurDecomp.h +++ b/dynare++/sylv/cc/SymSchurDecomp.hh @@ -5,7 +5,7 @@ #ifndef SYM_SCHUR_DECOMP_H #define SYM_SCHUR_DECOMP_H -#include "SylvMatrix.h" +#include "SylvMatrix.hh" class SymSchurDecomp { diff --git a/dynare++/sylv/cc/TriangularSylvester.cc b/dynare++/sylv/cc/TriangularSylvester.cc new file mode 100644 index 0000000000000000000000000000000000000000..232a33976532aa43829eeb1f260865da5bbaa539 --- /dev/null +++ b/dynare++/sylv/cc/TriangularSylvester.cc @@ -0,0 +1,433 @@ +/* $Header: /var/lib/cvs/dynare_cpp/sylv/cc/TriangularSylvester.cpp,v 1.1.1.1 2004/06/04 13:00:59 kamenik Exp $ */ + +/* Tag $Name: $ */ + +#include "TriangularSylvester.hh" +#include "QuasiTriangularZero.hh" +#include "KronUtils.hh" +#include "BlockDiagonal.hh" + +#include <cstdio> +#include <cmath> + +double TriangularSylvester::diag_zero = 1.e-15; +double TriangularSylvester::diag_zero_sq = 1.e-30; + +TriangularSylvester::TriangularSylvester(const QuasiTriangular &k, + const QuasiTriangular &f) + : SylvesterSolver(k, f), + matrixKK(matrixK->clone(2, *matrixK)), + matrixFF(new QuasiTriangular(2, *matrixF)) +{ +} + +TriangularSylvester::TriangularSylvester(const SchurDecompZero &kdecomp, + const SchurDecomp &fdecomp) + : SylvesterSolver(kdecomp, fdecomp), + matrixKK(matrixK->clone(2, *matrixK)), + matrixFF(new QuasiTriangular(2, *matrixF)) +{ +} + +TriangularSylvester::TriangularSylvester(const SchurDecompZero &kdecomp, + const SimilarityDecomp &fdecomp) + : SylvesterSolver(kdecomp, fdecomp), + matrixKK(matrixK->clone(2, *matrixK)), + matrixFF(new BlockDiagonal(2, *matrixF)) +{ +} + +TriangularSylvester::~TriangularSylvester() +{ + delete matrixKK; + delete matrixFF; +} + +void +TriangularSylvester::print() const +{ + printf("matrix K (%d):\n", matrixK->getDiagonal().getSize()); + matrixK->print(); + printf("matrix F (%d):\n", matrixF->getDiagonal().getSize()); + matrixF->print(); +} + +void +TriangularSylvester::solve(SylvParams &pars, KronVector &d) const +{ + double eig_min = 1e30; + solvi(1., d, eig_min); + pars.eig_min = sqrt(eig_min); +} + +void +TriangularSylvester::solvi(double r, KronVector &d, double &eig_min) const +{ + if (d.getDepth() == 0) + { + QuasiTriangular *t = matrixK->clone(r); + t->solvePre(d, eig_min); + delete t; + } + else + { + for (const_diag_iter di = matrixF->diag_begin(); + di != matrixF->diag_end(); + ++di) + { + if ((*di).isReal()) + { + solviRealAndEliminate(r, di, d, eig_min); + } + else + { + solviComplexAndEliminate(r, di, d, eig_min); + } + } + } +} + +void +TriangularSylvester::solvii(double alpha, double beta1, double beta2, + KronVector &d1, KronVector &d2, + double &eig_min) const +{ + KronVector d1tmp(d1); + KronVector d2tmp(d2); + linEval(alpha, beta1, beta2, d1, d2, d1tmp, d2tmp); + solviip(alpha, beta1*beta2, d1, eig_min); + solviip(alpha, beta1*beta2, d2, eig_min); +} + +void +TriangularSylvester::solviip(double alpha, double betas, + KronVector &d, double &eig_min) const +{ + // quick exit to solvi if betas is small + if (betas < diag_zero_sq) + { + solvi(alpha, d, eig_min); + solvi(alpha, d, eig_min); + return; + } + + if (d.getDepth() == 0) + { + double aspbs = alpha*alpha+betas; + QuasiTriangular *t = matrixK->clone(2*alpha, aspbs, *matrixKK); + t->solvePre(d, eig_min); + delete t; + } + else + { + const_diag_iter di = matrixF->diag_begin(); + const_diag_iter dsi = matrixFF->diag_begin(); + for (; di != matrixF->diag_end(); ++di, ++dsi) + { + if ((*di).isReal()) + { + solviipRealAndEliminate(alpha, betas, di, dsi, d, eig_min); + } + else + { + solviipComplexAndEliminate(alpha, betas, di, dsi, d, eig_min); + } + } + } +} + +void +TriangularSylvester::solviRealAndEliminate(double r, const_diag_iter di, + KronVector &d, double &eig_min) const +{ + // di is real + int jbar = (*di).getIndex(); + double f = *((*di).getAlpha()); + KronVector dj(d, jbar); + // solve system + if (abs(r*f) > diag_zero) + { + solvi(r*f, dj, eig_min); + } + // calculate y + KronVector y((const KronVector &)dj); + KronUtils::multKron(*matrixF, *matrixK, y); + y.mult(r); + double divisor = 1.0; + solviEliminateReal(di, d, y, divisor); +} + +void +TriangularSylvester::solviEliminateReal(const_diag_iter di, KronVector &d, + const KronVector &y, double divisor) const +{ + for (const_row_iter ri = matrixF->row_begin(*di); + ri != matrixF->row_end(*di); + ++ri) + { + KronVector dk(d, ri.getCol()); + dk.add(-(*ri)/divisor, y); + } +} + +void +TriangularSylvester::solviComplexAndEliminate(double r, const_diag_iter di, + KronVector &d, double &eig_min) const +{ + // di is complex + int jbar = (*di).getIndex(); + // pick data + double alpha = *(*di).getAlpha(); + double beta1 = (*di).getBeta2(); + double beta2 = -(*di).getBeta1(); + double aspbs = (*di).getDeterminant(); + KronVector dj(d, jbar); + KronVector djj(d, jbar+1); + // solve + if (r*r*aspbs > diag_zero_sq) + { + solvii(r*alpha, r*beta1, r*beta2, dj, djj, eig_min); + } + KronVector y1(dj); + KronVector y2(djj); + KronUtils::multKron(*matrixF, *matrixK, y1); + KronUtils::multKron(*matrixF, *matrixK, y2); + y1.mult(r); + y2.mult(r); + double divisor = 1.0; + solviEliminateComplex(di, d, y1, y2, divisor); +} + +void +TriangularSylvester::solviEliminateComplex(const_diag_iter di, KronVector &d, + const KronVector &y1, const KronVector &y2, + double divisor) const +{ + for (const_row_iter ri = matrixF->row_begin(*di); + ri != matrixF->row_end(*di); + ++ri) + { + KronVector dk(d, ri.getCol()); + dk.add(-ri.a()/divisor, y1); + dk.add(-ri.b()/divisor, y2); + } +} + +void +TriangularSylvester::solviipRealAndEliminate(double alpha, double betas, + const_diag_iter di, const_diag_iter dsi, + KronVector &d, double &eig_min) const +{ + // di, and dsi are real + int jbar = (*di).getIndex(); + double aspbs = alpha*alpha+betas; + // pick data + double f = *((*di).getAlpha()); + double fs = f*f; + KronVector dj(d, jbar); + // solve + if (fs*aspbs > diag_zero_sq) + { + solviip(f*alpha, fs*betas, dj, eig_min); + } + KronVector y1((const KronVector &)dj); + KronVector y2((const KronVector &)dj); + KronUtils::multKron(*matrixF, *matrixK, y1); + y1.mult(2*alpha); + KronUtils::multKron(*matrixFF, *matrixKK, y2); + y2.mult(aspbs); + double divisor = 1.0; + double divisor2 = 1.0; + solviipEliminateReal(di, dsi, d, y1, y2, divisor, divisor2); +} + +void +TriangularSylvester::solviipEliminateReal(const_diag_iter di, const_diag_iter dsi, + KronVector &d, + const KronVector &y1, const KronVector &y2, + double divisor, double divisor2) const +{ + const_row_iter ri = matrixF->row_begin(*di); + const_row_iter rsi = matrixFF->row_begin(*dsi); + for (; ri != matrixF->row_end(*di); ++ri, ++rsi) + { + KronVector dk(d, ri.getCol()); + dk.add(-(*ri)/divisor, y1); + dk.add(-(*rsi)/divisor2, y2); + } +} + +void +TriangularSylvester::solviipComplexAndEliminate(double alpha, double betas, + const_diag_iter di, const_diag_iter dsi, + KronVector &d, double &eig_min) const +{ + // di, and dsi are complex + int jbar = (*di).getIndex(); + double aspbs = alpha*alpha+betas; + // pick data + double gamma = *((*di).getAlpha()); + double delta1 = (*di).getBeta2(); // swap because of transpose + double delta2 = -(*di).getBeta1(); + double gspds = (*di).getDeterminant(); + KronVector dj(d, jbar); + KronVector djj(d, jbar+1); + if (gspds*aspbs > diag_zero_sq) + { + solviipComplex(alpha, betas, gamma, delta1, delta2, dj, djj, eig_min); + } + // here dj, djj is solution, set y1, y2, y11, y22 + // y1 + KronVector y1((const KronVector &)dj); + KronUtils::multKron(*matrixF, *matrixK, y1); + y1.mult(2*alpha); + // y11 + KronVector y11((const KronVector &)djj); + KronUtils::multKron(*matrixF, *matrixK, y11); + y11.mult(2*alpha); + // y2 + KronVector y2((const KronVector &)dj); + KronUtils::multKron(*matrixFF, *matrixKK, y2); + y2.mult(aspbs); + // y22 + KronVector y22((const KronVector &)djj); + KronUtils::multKron(*matrixFF, *matrixKK, y22); + y22.mult(aspbs); + + double divisor = 1.0; + solviipEliminateComplex(di, dsi, d, y1, y11, y2, y22, divisor); +} + +void +TriangularSylvester::solviipComplex(double alpha, double betas, double gamma, + double delta1, double delta2, + KronVector &d1, KronVector &d2, + double &eig_min) const +{ + KronVector d1tmp(d1); + KronVector d2tmp(d2); + quaEval(alpha, betas, gamma, delta1, delta2, + d1, d2, d1tmp, d2tmp); + double delta = sqrt(delta1*delta2); + double beta = sqrt(betas); + double a1 = alpha*gamma - beta*delta; + double b1 = alpha*delta + gamma*beta; + double a2 = alpha*gamma + beta*delta; + double b2 = alpha*delta - gamma*beta; + solviip(a2, b2*b2, d1, eig_min); + solviip(a1, b1*b1, d1, eig_min); + solviip(a2, b2*b2, d2, eig_min); + solviip(a1, b1*b1, d2, eig_min); +} + +void +TriangularSylvester::solviipEliminateComplex(const_diag_iter di, const_diag_iter dsi, + KronVector &d, + const KronVector &y1, const KronVector &y11, + const KronVector &y2, const KronVector &y22, + double divisor) const +{ + const_row_iter ri = matrixF->row_begin(*di); + const_row_iter rsi = matrixFF->row_begin(*dsi); + for (; ri != matrixF->row_end(*di); ++ri, ++rsi) + { + KronVector dk(d, ri.getCol()); + dk.add(-ri.a()/divisor, y1); + dk.add(-ri.b()/divisor, y11); + dk.add(-rsi.a()/divisor, y2); + dk.add(-rsi.b()/divisor, y22); + } +} + +void +TriangularSylvester::linEval(double alpha, double beta1, double beta2, + KronVector &x1, KronVector &x2, + const ConstKronVector &d1, const ConstKronVector &d2) const +{ + KronVector d1tmp(d1); // make copy + KronVector d2tmp(d2); // make copy + KronUtils::multKron(*matrixF, *matrixK, d1tmp); + KronUtils::multKron(*matrixF, *matrixK, d2tmp); + x1 = d1; + x2 = d2; + Vector::mult2a(alpha, beta1, -beta2, x1, x2, d1tmp, d2tmp); +} + +void +TriangularSylvester::quaEval(double alpha, double betas, + double gamma, double delta1, double delta2, + KronVector &x1, KronVector &x2, + const ConstKronVector &d1, const ConstKronVector &d2) const +{ + KronVector d1tmp(d1); // make copy + KronVector d2tmp(d2); // make copy + KronUtils::multKron(*matrixF, *matrixK, d1tmp); + KronUtils::multKron(*matrixF, *matrixK, d2tmp); + x1 = d1; + x2 = d2; + Vector::mult2a(2*alpha*gamma, 2*alpha*delta1, -2*alpha*delta2, + x1, x2, d1tmp, d2tmp); + d1tmp = d1; // restore to d1 + d2tmp = d2; // restore to d2 + KronUtils::multKron(*matrixFF, *matrixKK, d1tmp); + KronUtils::multKron(*matrixFF, *matrixKK, d2tmp); + double aspbs = alpha*alpha + betas; + double gspds = gamma*gamma - delta1*delta2; + Vector::mult2a(aspbs*gspds, 2*aspbs*gamma*delta1, -2*aspbs*gamma*delta2, + x1, x2, d1tmp, d2tmp); +} + +double +TriangularSylvester::getEigSep(int depth) const +{ + int f_size = matrixF->getDiagonal().getSize(); + Vector feig(2*f_size); + matrixF->getDiagonal().getEigenValues(feig); + int k_size = matrixK->getDiagonal().getSize(); + Vector keig(2*k_size); + matrixK->getDiagonal().getEigenValues(keig); + + KronVector eig(f_size, 2*k_size, depth); + multEigVector(eig, feig, keig); + + double min = 1.0e20; + for (int i = 0; i < eig.length()/2; i++) + { + double alpha = eig[2*i]; + double beta = eig[2*i+1]; + double ss = (alpha+1)*(alpha+1)+beta*beta; + if (min > ss) + min = ss; + } + + return min; +} + +void +TriangularSylvester::multEigVector(KronVector &eig, const Vector &feig, + const Vector &keig) +{ + int depth = eig.getDepth(); + int m = eig.getM(); + int n = eig.getN(); + + if (depth == 0) + { + eig = keig; + } + else + { + KronVector aux(m, n, depth-1); + multEigVector(aux, feig, keig); + for (int i = 0; i < m; i++) + { + KronVector eigi(eig, i); + eigi.zeros(); + eigi.add(&feig[2*i], aux); + } + } +} + +// Local Variables: +// mode:C++ +// End: diff --git a/dynare++/sylv/cc/TriangularSylvester.cpp b/dynare++/sylv/cc/TriangularSylvester.cpp deleted file mode 100644 index baf9e45d394940165b29920a845e0968d3d17524..0000000000000000000000000000000000000000 --- a/dynare++/sylv/cc/TriangularSylvester.cpp +++ /dev/null @@ -1,392 +0,0 @@ -/* $Header: /var/lib/cvs/dynare_cpp/sylv/cc/TriangularSylvester.cpp,v 1.1.1.1 2004/06/04 13:00:59 kamenik Exp $ */ - -/* Tag $Name: $ */ - -#include "TriangularSylvester.h" -#include "QuasiTriangularZero.h" -#include "KronUtils.h" -#include "BlockDiagonal.h" - -#include <cstdio> -#include <cmath> - -double TriangularSylvester::diag_zero = 1.e-15; -double TriangularSylvester::diag_zero_sq = 1.e-30; - -TriangularSylvester::TriangularSylvester(const QuasiTriangular& k, - const QuasiTriangular& f) - : SylvesterSolver(k, f), - matrixKK(matrixK->clone(2, *matrixK)), - matrixFF(new QuasiTriangular(2, *matrixF)) -{ -} - -TriangularSylvester::TriangularSylvester(const SchurDecompZero& kdecomp, - const SchurDecomp& fdecomp) - : SylvesterSolver(kdecomp, fdecomp), - matrixKK(matrixK->clone(2, *matrixK)), - matrixFF(new QuasiTriangular(2, *matrixF)) -{ -} - -TriangularSylvester::TriangularSylvester(const SchurDecompZero& kdecomp, - const SimilarityDecomp& fdecomp) - : SylvesterSolver(kdecomp, fdecomp), - matrixKK(matrixK->clone(2, *matrixK)), - matrixFF(new BlockDiagonal(2, *matrixF)) -{ -} - -TriangularSylvester::~TriangularSylvester() -{ - delete matrixKK; - delete matrixFF; -} - -void TriangularSylvester::print() const -{ - printf("matrix K (%d):\n",matrixK->getDiagonal().getSize()); - matrixK->print(); - printf("matrix F (%d):\n",matrixF->getDiagonal().getSize()); - matrixF->print(); -} - -void TriangularSylvester::solve(SylvParams& pars, KronVector& d) const -{ - double eig_min = 1e30; - solvi(1., d, eig_min); - pars.eig_min = sqrt(eig_min); -} - -void TriangularSylvester::solvi(double r, KronVector& d, double& eig_min) const -{ - if (d.getDepth() == 0) { - QuasiTriangular* t = matrixK->clone(r); - t->solvePre(d, eig_min); - delete t; - } else { - for (const_diag_iter di = matrixF->diag_begin(); - di != matrixF->diag_end(); - ++di) { - if ((*di).isReal()) { - solviRealAndEliminate(r, di, d, eig_min); - } else { - solviComplexAndEliminate(r, di, d, eig_min); - } - } - } -} - - -void TriangularSylvester::solvii(double alpha, double beta1, double beta2, - KronVector& d1, KronVector& d2, - double& eig_min) const -{ - KronVector d1tmp(d1); - KronVector d2tmp(d2); - linEval(alpha, beta1, beta2, d1, d2, d1tmp, d2tmp); - solviip(alpha, beta1*beta2, d1, eig_min); - solviip(alpha, beta1*beta2, d2, eig_min); -} - - -void TriangularSylvester::solviip(double alpha, double betas, - KronVector& d, double& eig_min) const -{ - // quick exit to solvi if betas is small - if (betas < diag_zero_sq) { - solvi(alpha, d, eig_min); - solvi(alpha, d, eig_min); - return; - } - - if (d.getDepth() == 0) { - double aspbs = alpha*alpha+betas; - QuasiTriangular* t= matrixK->clone(2*alpha, aspbs, *matrixKK); - t->solvePre(d, eig_min); - delete t; - } else { - const_diag_iter di = matrixF->diag_begin(); - const_diag_iter dsi = matrixFF->diag_begin(); - for (; di != matrixF->diag_end(); ++di, ++dsi) { - if ((*di).isReal()) { - solviipRealAndEliminate(alpha, betas, di, dsi, d, eig_min); - } else { - solviipComplexAndEliminate(alpha, betas, di, dsi, d, eig_min); - } - } - } -} - - -void TriangularSylvester::solviRealAndEliminate(double r, const_diag_iter di, - KronVector& d, double& eig_min) const -{ - // di is real - int jbar = (*di).getIndex(); - double f = *((*di).getAlpha()); - KronVector dj(d, jbar); - // solve system - if (abs(r*f) > diag_zero) { - solvi(r*f, dj, eig_min); - } - // calculate y - KronVector y((const KronVector&)dj); - KronUtils::multKron(*matrixF, *matrixK, y); - y.mult(r); - double divisor = 1.0; - solviEliminateReal(di, d, y, divisor); -} - -void TriangularSylvester::solviEliminateReal(const_diag_iter di, KronVector& d, - const KronVector& y, double divisor) const -{ - for (const_row_iter ri = matrixF->row_begin(*di); - ri != matrixF->row_end(*di); - ++ri) { - KronVector dk(d, ri.getCol()); - dk.add(-(*ri)/divisor, y); - } -} - -void TriangularSylvester::solviComplexAndEliminate(double r, const_diag_iter di, - KronVector& d, double& eig_min) const -{ - // di is complex - int jbar = (*di).getIndex(); - // pick data - double alpha = *(*di).getAlpha(); - double beta1 = (*di).getBeta2(); - double beta2 = -(*di).getBeta1(); - double aspbs = (*di).getDeterminant(); - KronVector dj(d, jbar); - KronVector djj(d, jbar+1); - // solve - if (r*r*aspbs > diag_zero_sq) { - solvii(r*alpha, r*beta1, r*beta2, dj, djj, eig_min); - } - KronVector y1(dj); - KronVector y2(djj); - KronUtils::multKron(*matrixF, *matrixK, y1); - KronUtils::multKron(*matrixF, *matrixK, y2); - y1.mult(r); - y2.mult(r); - double divisor = 1.0; - solviEliminateComplex(di, d, y1, y2, divisor); -} - -void TriangularSylvester::solviEliminateComplex(const_diag_iter di, KronVector& d, - const KronVector& y1, const KronVector& y2, - double divisor) const -{ - for (const_row_iter ri = matrixF->row_begin(*di); - ri != matrixF->row_end(*di); - ++ri) { - KronVector dk(d, ri.getCol()); - dk.add(-ri.a()/divisor, y1); - dk.add(-ri.b()/divisor, y2); - } -} - -void TriangularSylvester::solviipRealAndEliminate(double alpha, double betas, - const_diag_iter di, const_diag_iter dsi, - KronVector& d, double& eig_min) const -{ - // di, and dsi are real - int jbar = (*di).getIndex(); - double aspbs = alpha*alpha+betas; - // pick data - double f = *((*di).getAlpha()); - double fs = f*f; - KronVector dj(d, jbar); - // solve - if (fs*aspbs > diag_zero_sq) { - solviip(f*alpha, fs*betas, dj, eig_min); - } - KronVector y1((const KronVector&)dj); - KronVector y2((const KronVector&)dj); - KronUtils::multKron(*matrixF, *matrixK, y1); - y1.mult(2*alpha); - KronUtils::multKron(*matrixFF, *matrixKK, y2); - y2.mult(aspbs); - double divisor = 1.0; - double divisor2 = 1.0; - solviipEliminateReal(di, dsi, d, y1, y2, divisor, divisor2); -} - -void TriangularSylvester::solviipEliminateReal(const_diag_iter di, const_diag_iter dsi, - KronVector& d, - const KronVector& y1, const KronVector& y2, - double divisor, double divisor2) const -{ - const_row_iter ri = matrixF->row_begin(*di); - const_row_iter rsi = matrixFF->row_begin(*dsi); - for (; ri != matrixF->row_end(*di); ++ri, ++rsi) { - KronVector dk(d, ri.getCol()); - dk.add(-(*ri)/divisor, y1); - dk.add(-(*rsi)/divisor2, y2); - } -} - -void TriangularSylvester::solviipComplexAndEliminate(double alpha, double betas, - const_diag_iter di, const_diag_iter dsi, - KronVector& d, double& eig_min) const -{ - // di, and dsi are complex - int jbar = (*di).getIndex(); - double aspbs = alpha*alpha+betas; - // pick data - double gamma = *((*di).getAlpha()); - double delta1 = (*di).getBeta2(); // swap because of transpose - double delta2 = -(*di).getBeta1(); - double gspds = (*di).getDeterminant(); - KronVector dj(d, jbar); - KronVector djj(d, jbar+1); - if (gspds*aspbs > diag_zero_sq) { - solviipComplex(alpha, betas, gamma, delta1, delta2, dj, djj, eig_min); - } - // here dj, djj is solution, set y1, y2, y11, y22 - // y1 - KronVector y1((const KronVector&) dj); - KronUtils::multKron(*matrixF, *matrixK, y1); - y1.mult(2*alpha); - // y11 - KronVector y11((const KronVector&) djj); - KronUtils::multKron(*matrixF, *matrixK, y11); - y11.mult(2*alpha); - // y2 - KronVector y2((const KronVector&) dj); - KronUtils::multKron(*matrixFF, *matrixKK, y2); - y2.mult(aspbs); - // y22 - KronVector y22((const KronVector&) djj); - KronUtils::multKron(*matrixFF, *matrixKK, y22); - y22.mult(aspbs); - - double divisor = 1.0; - solviipEliminateComplex(di, dsi, d, y1, y11, y2, y22, divisor); -} - - -void TriangularSylvester::solviipComplex(double alpha, double betas, double gamma, - double delta1, double delta2, - KronVector& d1, KronVector& d2, - double& eig_min) const -{ - KronVector d1tmp(d1); - KronVector d2tmp(d2); - quaEval(alpha, betas, gamma, delta1, delta2, - d1, d2, d1tmp, d2tmp); - double delta = sqrt(delta1*delta2); - double beta = sqrt(betas); - double a1 = alpha*gamma - beta*delta; - double b1 = alpha*delta + gamma*beta; - double a2 = alpha*gamma + beta*delta; - double b2 = alpha*delta - gamma*beta; - solviip(a2, b2*b2, d1, eig_min); - solviip(a1, b1*b1, d1, eig_min); - solviip(a2, b2*b2, d2, eig_min); - solviip(a1, b1*b1, d2, eig_min); -} - -void TriangularSylvester::solviipEliminateComplex(const_diag_iter di, const_diag_iter dsi, - KronVector& d, - const KronVector& y1, const KronVector& y11, - const KronVector& y2, const KronVector& y22, - double divisor) const -{ - const_row_iter ri = matrixF->row_begin(*di); - const_row_iter rsi = matrixFF->row_begin(*dsi); - for (; ri != matrixF->row_end(*di); ++ri, ++rsi) { - KronVector dk(d, ri.getCol()); - dk.add(-ri.a()/divisor, y1); - dk.add(-ri.b()/divisor, y11); - dk.add(-rsi.a()/divisor, y2); - dk.add(-rsi.b()/divisor, y22); - } -} - -void TriangularSylvester::linEval(double alpha, double beta1, double beta2, - KronVector& x1, KronVector& x2, - const ConstKronVector& d1, const ConstKronVector& d2) const -{ - KronVector d1tmp(d1); // make copy - KronVector d2tmp(d2); // make copy - KronUtils::multKron(*matrixF, *matrixK, d1tmp); - KronUtils::multKron(*matrixF, *matrixK, d2tmp); - x1 = d1; - x2 = d2; - Vector::mult2a(alpha, beta1, -beta2, x1, x2, d1tmp, d2tmp); -} - -void TriangularSylvester::quaEval(double alpha, double betas, - double gamma, double delta1, double delta2, - KronVector& x1, KronVector& x2, - const ConstKronVector& d1, const ConstKronVector& d2) const -{ - KronVector d1tmp(d1); // make copy - KronVector d2tmp(d2); // make copy - KronUtils::multKron(*matrixF, *matrixK, d1tmp); - KronUtils::multKron(*matrixF, *matrixK, d2tmp); - x1 = d1; - x2 = d2; - Vector::mult2a(2*alpha*gamma, 2*alpha*delta1, -2*alpha*delta2, - x1, x2, d1tmp, d2tmp); - d1tmp = d1; // restore to d1 - d2tmp = d2; // restore to d2 - KronUtils::multKron(*matrixFF, *matrixKK, d1tmp); - KronUtils::multKron(*matrixFF, *matrixKK, d2tmp); - double aspbs = alpha*alpha + betas; - double gspds = gamma*gamma - delta1*delta2; - Vector::mult2a(aspbs*gspds, 2*aspbs*gamma*delta1, -2*aspbs*gamma*delta2, - x1, x2, d1tmp, d2tmp); -} - - -double TriangularSylvester::getEigSep(int depth) const -{ - int f_size = matrixF->getDiagonal().getSize(); - Vector feig(2*f_size); - matrixF->getDiagonal().getEigenValues(feig); - int k_size = matrixK->getDiagonal().getSize(); - Vector keig(2*k_size); - matrixK->getDiagonal().getEigenValues(keig); - - KronVector eig(f_size, 2*k_size, depth); - multEigVector(eig, feig, keig); - - double min = 1.0e20; - for (int i = 0; i < eig.length()/2; i++) { - double alpha = eig[2*i]; - double beta = eig[2*i+1]; - double ss = (alpha+1)*(alpha+1)+beta*beta; - if (min > ss) - min = ss; - } - - return min; -} - -void TriangularSylvester::multEigVector(KronVector& eig, const Vector& feig, - const Vector& keig) -{ - int depth = eig.getDepth(); - int m = eig.getM(); - int n = eig.getN(); - - if (depth == 0) { - eig = keig; - } else { - KronVector aux(m, n, depth-1); - multEigVector(aux, feig, keig); - for (int i = 0; i < m; i++) { - KronVector eigi(eig, i); - eigi.zeros(); - eigi.add(&feig[2*i], aux); - } - } -} - -// Local Variables: -// mode:C++ -// End: diff --git a/dynare++/sylv/cc/TriangularSylvester.h b/dynare++/sylv/cc/TriangularSylvester.hh similarity index 97% rename from dynare++/sylv/cc/TriangularSylvester.h rename to dynare++/sylv/cc/TriangularSylvester.hh index fa652bc12f70c676e15c68ceb02a0997ee998fc9..b158bbbb3be01aeb66c49c0cc8c3df9643dc8ff6 100644 --- a/dynare++/sylv/cc/TriangularSylvester.h +++ b/dynare++/sylv/cc/TriangularSylvester.hh @@ -5,11 +5,11 @@ #ifndef TRIANGULAR_SYLVESTER_H #define TRIANGULAR_SYLVESTER_H -#include "SylvesterSolver.h" -#include "KronVector.h" -#include "QuasiTriangular.h" -#include "QuasiTriangularZero.h" -#include "SimilarityDecomp.h" +#include "SylvesterSolver.hh" +#include "KronVector.hh" +#include "QuasiTriangular.hh" +#include "QuasiTriangularZero.hh" +#include "SimilarityDecomp.hh" class TriangularSylvester : public SylvesterSolver { diff --git a/dynare++/sylv/cc/Vector.cc b/dynare++/sylv/cc/Vector.cc new file mode 100644 index 0000000000000000000000000000000000000000..d0722c5dfa74c3fb220c3aafb71ce01784312860 --- /dev/null +++ b/dynare++/sylv/cc/Vector.cc @@ -0,0 +1,418 @@ +// Copyright (C) 2004-2011, Ondra Kamenik + +#include "Vector.hh" +#include "GeneralMatrix.hh" +#include "SylvException.hh" + +#include <dynblas.h> + +#include <cstdio> +#include <cstring> +#include <cstdlib> +#include <cmath> +#include <algorithm> +#include <limits> + +using namespace std; + +ZeroPad zero_pad; + +Vector::Vector(const Vector &v) + : len(v.length()), s(1), data(new double[len]), destroy(true) +{ + copy(v.base(), v.skip()); +} + +Vector::Vector(const ConstVector &v) + : len(v.length()), s(1), data(new double[len]), destroy(true) +{ + copy(v.base(), v.skip()); +} + +const Vector & +Vector::operator=(const Vector &v) +{ + if (this == &v) + return *this; + + if (v.length() != length()) + { + throw SYLV_MES_EXCEPTION("Attempt to assign vectors with different lengths."); + } + if (s == v.s + && (data <= v.data && v.data < data+len*s + || v.data <= data && data < v.data+v.len*v.s) + && (data-v.data) % s == 0) + { + printf("this destroy=%d, v destroy=%d, data-v.data=%lu, len=%d\n", destroy, v.destroy, (unsigned long) (data-v.data), len); + throw SYLV_MES_EXCEPTION("Attempt to assign overlapping vectors."); + } + copy(v.base(), v.skip()); + return *this; +} + +const Vector & +Vector::operator=(const ConstVector &v) +{ + if (v.length() != length()) + { + throw SYLV_MES_EXCEPTION("Attempt to assign vectors with different lengths."); + } + if (v.skip() == 1 && skip() == 1 && ( + (base() < v.base() + v.length() && base() >= v.base()) + || (base() + length() < v.base() + v.length() + && base() + length() > v.base()))) + { + throw SYLV_MES_EXCEPTION("Attempt to assign overlapping vectors."); + } + copy(v.base(), v.skip()); + return *this; +} + +void +Vector::copy(const double *d, int inc) +{ + blas_int n = length(); + blas_int incy = skip(); + blas_int inc2 = inc; + dcopy(&n, d, &inc2, base(), &incy); +} + +Vector::Vector(Vector &v, int off, int l) + : len(l), s(v.skip()), data(v.base()+off*v.skip()), destroy(false) +{ + if (off < 0 || off + length() > v.length()) + throw SYLV_MES_EXCEPTION("Subvector not contained in supvector."); +} + +Vector::Vector(const Vector &v, int off, int l) + : len(l), s(1), data(new double[len]), destroy(true) +{ + if (off < 0 || off + length() > v.length()) + throw SYLV_MES_EXCEPTION("Subvector not contained in supvector."); + copy(v.base()+off*v.skip(), v.skip()); +} + +Vector::Vector(GeneralMatrix &m, int col) + : len(m.numRows()), s(1), data(&(m.get(0, col))), destroy(false) +{ +} + +Vector::Vector(int row, GeneralMatrix &m) + : len(m.numCols()), s(m.getLD()), data(&(m.get(row, 0))), destroy(false) +{ +} + +bool +Vector::operator==(const Vector &y) const +{ + return ConstVector(*this) == y; +} + +bool +Vector::operator!=(const Vector &y) const +{ + return ConstVector(*this) != y; +} + +bool +Vector::operator<(const Vector &y) const +{ + return ConstVector(*this) < y; +} + +bool +Vector::operator<=(const Vector &y) const +{ + return ConstVector(*this) <= y; +} + +bool +Vector::operator>(const Vector &y) const +{ + return ConstVector(*this) > y; +} + +bool +Vector::operator>=(const Vector &y) const +{ + return ConstVector(*this) >= y; +} + +void +Vector::zeros() +{ + if (skip() == 1) + { + double *p = base(); + for (int i = 0; i < length()/ZeroPad::length; + i++, p += ZeroPad::length) + memcpy(p, zero_pad.getBase(), sizeof(double)*ZeroPad::length); + for (; p < base()+length(); p++) + *p = 0.0; + } + else + { + for (int i = 0; i < length(); i++) + operator[](i) = 0.0; + } +} + +void +Vector::nans() +{ + for (int i = 0; i < length(); i++) + operator[](i) = std::numeric_limits<double>::quiet_NaN(); +} + +void +Vector::infs() +{ + for (int i = 0; i < length(); i++) + operator[](i) = std::numeric_limits<double>::infinity(); +} + +Vector::~Vector() +{ + if (destroy) + { + delete [] data; + } +} + +void +Vector::rotatePair(double alpha, double beta1, double beta2, int i) +{ + double tmp = alpha*operator[](i) - beta1*operator[](i+1); + operator[](i+1) = alpha*operator[](i+1) - beta2*operator[](i); + operator[](i) = tmp; +} + +void +Vector::add(double r, const Vector &v) +{ + add(r, ConstVector(v)); +} + +void +Vector::add(double r, const ConstVector &v) +{ + blas_int n = length(); + blas_int incx = v.skip(); + blas_int incy = skip(); + daxpy(&n, &r, v.base(), &incx, base(), &incy); +} + +void +Vector::add(const double *z, const Vector &v) +{ + add(z, ConstVector(v)); +} + +void +Vector::add(const double *z, const ConstVector &v) +{ + blas_int n = length()/2; + blas_int incx = v.skip(); + blas_int incy = skip(); + zaxpy(&n, z, v.base(), &incx, base(), &incy); +} + +void +Vector::mult(double r) +{ + blas_int n = length(); + blas_int incx = skip(); + dscal(&n, &r, base(), &incx); +} + +void +Vector::mult2(double alpha, double beta1, double beta2, + Vector &x1, Vector &x2, + const Vector &b1, const Vector &b2) +{ + x1.zeros(); + x2.zeros(); + mult2a(alpha, beta1, beta2, x1, x2, b1, b2); +} + +void +Vector::mult2a(double alpha, double beta1, double beta2, + Vector &x1, Vector &x2, + const Vector &b1, const Vector &b2) +{ + x1.add(alpha, b1); + x1.add(-beta1, b2); + x2.add(alpha, b2); + x2.add(-beta2, b1); +} + +double +Vector::getNorm() const +{ + ConstVector v(*this); + return v.getNorm(); +} + +double +Vector::getMax() const +{ + ConstVector v(*this); + return v.getMax(); +} + +double +Vector::getNorm1() const +{ + ConstVector v(*this); + return v.getNorm1(); +} + +double +Vector::dot(const Vector &y) const +{ + return ConstVector(*this).dot(ConstVector(y)); +} + +bool +Vector::isFinite() const +{ + return (ConstVector(*this)).isFinite(); +} + +void +Vector::print() const +{ + for (int i = 0; i < length(); i++) + { + printf("%d\t%8.4g\n", i, operator[](i)); + } +} + +ConstVector::ConstVector(const Vector &v, int off, int l) + : BaseConstVector(l, v.skip(), v.base() + v.skip()*off) +{ + if (off < 0 || off + length() > v.length()) + { + throw SYLV_MES_EXCEPTION("Subvector not contained in supvector."); + } +} + +ConstVector::ConstVector(const ConstVector &v, int off, int l) + : BaseConstVector(l, v.skip(), v.base() + v.skip()*off) +{ + if (off < 0 || off + length() > v.length()) + { + throw SYLV_MES_EXCEPTION("Subvector not contained in supvector."); + } +} + +ConstVector::ConstVector(const double *d, int skip, int l) + : BaseConstVector(l, skip, d) +{ +} + +ConstVector::ConstVector(const ConstGeneralMatrix &m, int col) + : BaseConstVector(m.numRows(), 1, &(m.get(0, col))) +{ +} + +ConstVector::ConstVector(int row, const ConstGeneralMatrix &m) + : BaseConstVector(m.numCols(), m.getLD(), &(m.get(row, 0))) +{ +} + +bool +ConstVector::operator==(const ConstVector &y) const +{ + if (length() != y.length()) + return false; + if (length() == 0) + return true; + int i = 0; + while (i < length() && operator[](i) == y[i]) + i++; + return i == length(); +} + +bool +ConstVector::operator<(const ConstVector &y) const +{ + int i = std::min(length(), y.length()); + int ii = 0; + while (ii < i && operator[](ii) == y[ii]) + ii++; + if (ii < i) + return operator[](ii) < y[ii]; + else + return length() < y.length(); +} + +double +ConstVector::getNorm() const +{ + double s = 0; + for (int i = 0; i < length(); i++) + { + s += operator[](i)*operator[](i); + } + return sqrt(s); +} + +double +ConstVector::getMax() const +{ + double r = 0; + for (int i = 0; i < length(); i++) + { + if (abs(operator[](i)) > r) + r = abs(operator[](i)); + } + return r; +} + +double +ConstVector::getNorm1() const +{ + double norm = 0.0; + for (int i = 0; i < length(); i++) + { + norm += abs(operator[](i)); + } + return norm; +} + +double +ConstVector::dot(const ConstVector &y) const +{ + if (length() != y.length()) + throw SYLV_MES_EXCEPTION("Vector has different length in ConstVector::dot."); + blas_int n = length(); + blas_int incx = skip(); + blas_int incy = y.skip(); + return ddot(&n, base(), &incx, y.base(), &incy); +} + +bool +ConstVector::isFinite() const +{ + int i = 0; + while (i < length() && isfinite(operator[](i))) + i++; + return i == length(); +} + +void +ConstVector::print() const +{ + for (int i = 0; i < length(); i++) + { + printf("%d\t%8.4g\n", i, operator[](i)); + } +} + +ZeroPad::ZeroPad() +{ + for (int i = 0; i < length; i++) + pad[i] = 0.0; +} diff --git a/dynare++/sylv/cc/Vector.cpp b/dynare++/sylv/cc/Vector.cpp deleted file mode 100644 index 929790ad8c0c68cf07e71bf62cfc8f672f33cb49..0000000000000000000000000000000000000000 --- a/dynare++/sylv/cc/Vector.cpp +++ /dev/null @@ -1,371 +0,0 @@ -// Copyright (C) 2004-2011, Ondra Kamenik - -#include "Vector.h" -#include "GeneralMatrix.h" -#include "SylvException.h" - -#include <dynblas.h> - -#include <cstdio> -#include <cstring> -#include <cstdlib> -#include <cmath> -#include <algorithm> -#include <limits> - -using namespace std; - -ZeroPad zero_pad; - -Vector::Vector(const Vector& v) - : len(v.length()), s(1), data(new double[len]), destroy(true) -{ - copy(v.base(), v.skip()); -} - -Vector::Vector(const ConstVector& v) - : len(v.length()), s(1), data(new double[len]), destroy(true) -{ - copy(v.base(), v.skip()); -} - -const Vector& Vector::operator=(const Vector& v) -{ - if (this == &v) - return *this; - - if (v.length() != length()) { - throw SYLV_MES_EXCEPTION("Attempt to assign vectors with different lengths."); - } - if (s == v.s && - (data <= v.data && v.data < data+len*s || - v.data <= data && data < v.data+v.len*v.s) && - (data-v.data) % s == 0) { - printf("this destroy=%d, v destroy=%d, data-v.data=%lu, len=%d\n", destroy, v.destroy, (unsigned long) (data-v.data), len); - throw SYLV_MES_EXCEPTION("Attempt to assign overlapping vectors."); - } - copy(v.base(), v.skip()); - return *this; -} - -const Vector& Vector::operator=(const ConstVector& v) -{ - if (v.length() != length()) { - throw SYLV_MES_EXCEPTION("Attempt to assign vectors with different lengths."); - } - if (v.skip() == 1 && skip() == 1 && ( - (base() < v.base() + v.length() && base() >= v.base()) || - (base() + length() < v.base() + v.length() && - base() + length() > v.base()))) { - throw SYLV_MES_EXCEPTION("Attempt to assign overlapping vectors."); - } - copy(v.base(), v.skip()); - return *this; -} - -void Vector::copy(const double* d, int inc) -{ - blas_int n = length(); - blas_int incy = skip(); - blas_int inc2 = inc; - dcopy(&n, d, &inc2, base(), &incy); -} - -Vector::Vector(Vector& v, int off, int l) - : len(l), s(v.skip()), data(v.base()+off*v.skip()), destroy(false) -{ - if (off < 0 || off + length() > v.length()) - throw SYLV_MES_EXCEPTION("Subvector not contained in supvector."); -} - -Vector::Vector(const Vector& v, int off, int l) - : len(l), s(1), data(new double[len]), destroy(true) -{ - if (off < 0 || off + length() > v.length()) - throw SYLV_MES_EXCEPTION("Subvector not contained in supvector."); - copy(v.base()+off*v.skip(), v.skip()); -} - -Vector::Vector(GeneralMatrix& m, int col) - : len(m.numRows()), s(1), data(&(m.get(0, col))), destroy(false) -{ -} - -Vector::Vector(int row, GeneralMatrix& m) - : len(m.numCols()), s(m.getLD()), data(&(m.get(row, 0))), destroy(false) -{ -} - -bool Vector::operator==(const Vector& y) const -{ - return ConstVector(*this) == y; -} - -bool Vector::operator!=(const Vector& y) const -{ - return ConstVector(*this) != y; -} - -bool Vector::operator<(const Vector& y) const -{ - return ConstVector(*this) < y; -} - -bool Vector::operator<=(const Vector& y) const -{ - return ConstVector(*this) <= y; -} - -bool Vector::operator>(const Vector& y) const -{ - return ConstVector(*this) > y; -} - -bool Vector::operator>=(const Vector& y) const -{ - return ConstVector(*this) >= y; -} - -void Vector::zeros() -{ - if (skip() == 1) { - double* p = base(); - for (int i = 0; i < length()/ZeroPad::length; - i++, p += ZeroPad::length) - memcpy(p, zero_pad.getBase(), sizeof(double)*ZeroPad::length); - for ( ; p < base()+length(); p++) - *p = 0.0; - } else { - for (int i = 0; i < length(); i++) - operator[](i) = 0.0; - } -} - -void Vector::nans() -{ - for (int i = 0; i < length(); i++) - operator[](i) = std::numeric_limits<double>::quiet_NaN(); -} - -void Vector::infs() -{ - for (int i = 0; i < length(); i++) - operator[](i) = std::numeric_limits<double>::infinity(); -} - -Vector::~Vector() -{ - if (destroy) { - delete [] data; - } -} - -void Vector::rotatePair(double alpha, double beta1, double beta2, int i) -{ - double tmp = alpha*operator[](i) - beta1*operator[](i+1); - operator[](i+1) = alpha*operator[](i+1) - beta2*operator[](i); - operator[](i) = tmp; -} - -void Vector::add(double r, const Vector& v) -{ - add(r, ConstVector(v)); -} - -void Vector::add(double r, const ConstVector& v) -{ - blas_int n = length(); - blas_int incx = v.skip(); - blas_int incy = skip(); - daxpy(&n, &r, v.base(), &incx, base(), &incy); -} - -void Vector::add(const double* z, const Vector& v) -{ - add(z, ConstVector(v)); -} - -void Vector::add(const double* z, const ConstVector& v) -{ - blas_int n = length()/2; - blas_int incx = v.skip(); - blas_int incy = skip(); - zaxpy(&n, z, v.base(), &incx, base(), &incy); -} - -void Vector::mult(double r) -{ - blas_int n = length(); - blas_int incx = skip(); - dscal(&n, &r, base(), &incx); -} - -void Vector::mult2(double alpha, double beta1, double beta2, - Vector& x1, Vector& x2, - const Vector& b1, const Vector& b2) -{ - x1.zeros(); - x2.zeros(); - mult2a(alpha, beta1, beta2, x1, x2, b1, b2); -} - -void Vector::mult2a(double alpha, double beta1, double beta2, - Vector& x1, Vector& x2, - const Vector& b1, const Vector& b2) -{ - x1.add(alpha, b1); - x1.add(-beta1, b2); - x2.add(alpha, b2); - x2.add(-beta2, b1); -} - -double Vector::getNorm() const -{ - ConstVector v(*this); - return v.getNorm(); -} - -double Vector::getMax() const -{ - ConstVector v(*this); - return v.getMax(); -} - -double Vector::getNorm1() const -{ - ConstVector v(*this); - return v.getNorm1(); -} - -double Vector::dot(const Vector& y) const -{ - return ConstVector(*this).dot(ConstVector(y)); -} - -bool Vector::isFinite() const -{ - return (ConstVector(*this)).isFinite(); -} - -void Vector::print() const -{ - for (int i = 0; i < length(); i++) { - printf("%d\t%8.4g\n", i, operator[](i)); - } -} - - -ConstVector::ConstVector(const Vector& v, int off, int l) - : BaseConstVector(l, v.skip(), v.base() + v.skip()*off) -{ - if (off < 0 || off + length() > v.length()) { - throw SYLV_MES_EXCEPTION("Subvector not contained in supvector."); - } -} - -ConstVector::ConstVector(const ConstVector& v, int off, int l) - : BaseConstVector(l, v.skip(), v.base() + v.skip()*off) -{ - if (off < 0 || off + length() > v.length()) { - throw SYLV_MES_EXCEPTION("Subvector not contained in supvector."); - } -} - -ConstVector::ConstVector(const double* d, int skip, int l) - : BaseConstVector(l, skip, d) -{ -} - -ConstVector::ConstVector(const ConstGeneralMatrix& m, int col) - : BaseConstVector(m.numRows(), 1, &(m.get(0, col))) -{ -} - -ConstVector::ConstVector(int row, const ConstGeneralMatrix& m) - : BaseConstVector(m.numCols(), m.getLD(), &(m.get(row, 0))) -{ -} - -bool ConstVector::operator==(const ConstVector& y) const -{ - if (length() != y.length()) - return false; - if (length() == 0) - return true; - int i = 0; - while (i < length() && operator[](i) == y[i]) - i++; - return i == length(); -} - -bool ConstVector::operator<(const ConstVector& y) const -{ - int i = std::min(length(), y.length()); - int ii = 0; - while (ii < i && operator[](ii) == y[ii]) - ii++; - if (ii < i) - return operator[](ii) < y[ii]; - else - return length() < y.length(); -} - -double ConstVector::getNorm() const -{ - double s = 0; - for (int i = 0; i < length(); i++) { - s+=operator[](i)*operator[](i); - } - return sqrt(s); -} - -double ConstVector::getMax() const -{ - double r = 0; - for (int i = 0; i < length(); i++) { - if (abs(operator[](i))>r) - r = abs(operator[](i)); - } - return r; -} - -double ConstVector::getNorm1() const -{ - double norm = 0.0; - for (int i = 0; i < length(); i++) { - norm += abs(operator[](i)); - } - return norm; -} - -double ConstVector::dot(const ConstVector& y) const -{ - if (length() != y.length()) - throw SYLV_MES_EXCEPTION("Vector has different length in ConstVector::dot."); - blas_int n = length(); - blas_int incx = skip(); - blas_int incy = y.skip(); - return ddot(&n, base(), &incx, y.base(), &incy); -} - -bool ConstVector::isFinite() const -{ - int i = 0; - while (i < length() && isfinite(operator[](i))) - i++; - return i == length(); -} - -void ConstVector::print() const -{ - for (int i = 0; i < length(); i++) { - printf("%d\t%8.4g\n", i, operator[](i)); - } -} - - -ZeroPad::ZeroPad() -{ - for (int i = 0; i < length; i++) - pad[i] = 0.0; -} diff --git a/dynare++/sylv/cc/Vector.h b/dynare++/sylv/cc/Vector.hh similarity index 100% rename from dynare++/sylv/cc/Vector.h rename to dynare++/sylv/cc/Vector.hh diff --git a/dynare++/sylv/matlab/gensylv.cc b/dynare++/sylv/matlab/gensylv.cc new file mode 100644 index 0000000000000000000000000000000000000000..14bebce58229351a5629a7c5aaf6f5f2ab0c5daa --- /dev/null +++ b/dynare++/sylv/matlab/gensylv.cc @@ -0,0 +1,94 @@ +// Copyright (C) 2005-2011, Ondra Kamenik + +#include "dynmex.h" +#include "mex.h" + +#include "GeneralSylvester.hh" +#include "SylvException.hh" + +void +gen_sylv_solve(int order, int n, int m, int zero_cols, + const double *A, const double *B, + const double *C, double *X) +{ + GeneralSylvester s(order, n, m, zero_cols, A, B, C, X, false); + s.solve(); +} + +void +gen_sylv_solve_and_check(int order, int n, int m, int zero_cols, + const double *A, const double *B, + const double *C, const double *D, + double *X, mxArray * &p) +{ + GeneralSylvester s(order, n, m, zero_cols, A, B, C, X, true); + s.solve(); + s.check(D); + p = s.getParams().createStructArray(); +} + +extern "C" { + void + mexFunction(int nlhs, mxArray *plhs[], + int nhrs, const mxArray *prhs[]) + { + if (nhrs != 5 || nlhs > 3 || nlhs < 2) + DYN_MEX_FUNC_ERR_MSG_TXT("Gensylv: Must have exactly 5 input args and either 2 or 3 output args."); + + int order = (int) mxGetScalar(prhs[0]); + const mxArray *const A = prhs[1]; + const mxArray *const B = prhs[2]; + const mxArray *const C = prhs[3]; + const mxArray *const D = prhs[4]; + const mwSize *const Adims = mxGetDimensions(A); + const mwSize *const Bdims = mxGetDimensions(B); + const mwSize *const Cdims = mxGetDimensions(C); + const mwSize *const Ddims = mxGetDimensions(D); + + if (Adims[0] != Adims[1]) + DYN_MEX_FUNC_ERR_MSG_TXT("Matrix A must be a square matrix."); + if (Adims[0] != Bdims[0]) + DYN_MEX_FUNC_ERR_MSG_TXT("Matrix A and matrix B must have the same number of rows."); + if (Adims[0] != Ddims[0]) + DYN_MEX_FUNC_ERR_MSG_TXT("Matrix A and matrix B must have the same number of rows."); + if (Cdims[0] != Cdims[1]) + DYN_MEX_FUNC_ERR_MSG_TXT("Matrix C must be square."); + if (Bdims[0] < Bdims[1]) + DYN_MEX_FUNC_ERR_MSG_TXT("Matrix B must not have more columns than rows."); + if (Ddims[1] != (mwSize) power(Cdims[0], order)) + DYN_MEX_FUNC_ERR_MSG_TXT("Matrix D has wrong number of columns."); + + int n = Adims[0]; + int m = Cdims[0]; + int zero_cols = Bdims[0] - Bdims[1]; + mxArray *X = mxCreateDoubleMatrix(Ddims[0], Ddims[1], mxREAL); + // copy D to X + Vector Xvec((double *)mxGetPr(X), power(m, order)*n); + ConstVector Dvec((double *)mxGetPr(D), power(m, order)*n); + Xvec = Dvec; + // solve (or solve and check) + try + { + if (nlhs == 2) + { + gen_sylv_solve(order, n, m, zero_cols, + mxGetPr(A), mxGetPr(B), mxGetPr(C), + mxGetPr(X)); + } + else if (nlhs == 3) + { + gen_sylv_solve_and_check(order, n, m, zero_cols, + mxGetPr(A), mxGetPr(B), mxGetPr(C), + mxGetPr(D), mxGetPr(X), plhs[2]); + } + } + catch (const SylvException &e) + { + char mes[1000]; + e.printMessage(mes, 999); + DYN_MEX_FUNC_ERR_MSG_TXT(mes); + } + plhs[1] = X; + plhs[0] = mxCreateDoubleScalar(0); + } +}; diff --git a/dynare++/sylv/matlab/gensylv.cpp b/dynare++/sylv/matlab/gensylv.cpp deleted file mode 100644 index b619afda836bbc16047b0ae221be0530e5589952..0000000000000000000000000000000000000000 --- a/dynare++/sylv/matlab/gensylv.cpp +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright (C) 2005-2011, Ondra Kamenik - -#include "dynmex.h" -#include "mex.h" - -#include "GeneralSylvester.h" -#include "SylvException.h" - - -void gen_sylv_solve(int order, int n, int m, int zero_cols, - const double* A, const double* B, - const double* C, double* X) -{ - GeneralSylvester s(order, n, m, zero_cols, A, B, C, X, false); - s.solve(); -} - -void gen_sylv_solve_and_check(int order, int n, int m, int zero_cols, - const double* A, const double* B, - const double* C, const double* D, - double* X, mxArray*& p) -{ - GeneralSylvester s(order, n, m, zero_cols, A, B, C, X, true); - s.solve(); - s.check(D); - p = s.getParams().createStructArray(); -} - -extern "C" { - void mexFunction(int nlhs, mxArray* plhs[], - int nhrs, const mxArray* prhs[]) - { - if (nhrs != 5 || nlhs > 3 || nlhs < 2 ) - DYN_MEX_FUNC_ERR_MSG_TXT("Gensylv: Must have exactly 5 input args and either 2 or 3 output args."); - - int order = (int)mxGetScalar(prhs[0]); - const mxArray* const A = prhs[1]; - const mxArray* const B = prhs[2]; - const mxArray* const C = prhs[3]; - const mxArray* const D = prhs[4]; - const mwSize* const Adims = mxGetDimensions(A); - const mwSize* const Bdims = mxGetDimensions(B); - const mwSize* const Cdims = mxGetDimensions(C); - const mwSize* const Ddims = mxGetDimensions(D); - - if (Adims[0] != Adims[1]) - DYN_MEX_FUNC_ERR_MSG_TXT("Matrix A must be a square matrix."); - if (Adims[0] != Bdims[0]) - DYN_MEX_FUNC_ERR_MSG_TXT("Matrix A and matrix B must have the same number of rows."); - if (Adims[0] != Ddims[0]) - DYN_MEX_FUNC_ERR_MSG_TXT("Matrix A and matrix B must have the same number of rows."); - if (Cdims[0] != Cdims[1]) - DYN_MEX_FUNC_ERR_MSG_TXT("Matrix C must be square."); - if (Bdims[0] < Bdims[1]) - DYN_MEX_FUNC_ERR_MSG_TXT("Matrix B must not have more columns than rows."); - if (Ddims[1] != (mwSize) power(Cdims[0], order)) - DYN_MEX_FUNC_ERR_MSG_TXT("Matrix D has wrong number of columns."); - - int n = Adims[0]; - int m = Cdims[0]; - int zero_cols = Bdims[0] - Bdims[1]; - mxArray* X = mxCreateDoubleMatrix(Ddims[0], Ddims[1], mxREAL); - // copy D to X - Vector Xvec((double*)mxGetPr(X), power(m, order)*n); - ConstVector Dvec((double*)mxGetPr(D), power(m, order)*n); - Xvec = Dvec; - // solve (or solve and check) - try - { - if (nlhs == 2) { - gen_sylv_solve(order, n, m, zero_cols, - mxGetPr(A), mxGetPr(B), mxGetPr(C), - mxGetPr(X)); - } else if (nlhs == 3) { - gen_sylv_solve_and_check(order, n, m, zero_cols, - mxGetPr(A), mxGetPr(B), mxGetPr(C), - mxGetPr(D), mxGetPr(X), plhs[2]); - } - } - catch (const SylvException& e) - { - char mes[1000]; - e.printMessage(mes, 999); - DYN_MEX_FUNC_ERR_MSG_TXT(mes); - } - plhs[1] = X; - plhs[0] = mxCreateDoubleScalar(0); - } -}; diff --git a/dynare++/sylv/testing/MMMatrix.cc b/dynare++/sylv/testing/MMMatrix.cc new file mode 100644 index 0000000000000000000000000000000000000000..099eb3a5a5ff5a94cf7f6df0b103a816d498eafc --- /dev/null +++ b/dynare++/sylv/testing/MMMatrix.cc @@ -0,0 +1,78 @@ +/* $Header: /var/lib/cvs/dynare_cpp/sylv/testing/MMMatrix.cpp,v 1.1.1.1 2004/06/04 13:01:13 kamenik Exp $ */ + +/* Tag $Name: $ */ + +#include "MMMatrix.hh" + +#include <cstdio> +#include <cstring> + +MMMatrixIn::MMMatrixIn(const char *fname) +{ + FILE *fd; + if (NULL == (fd = fopen(fname, "r"))) + throw MMException(string("Cannot open file ")+fname+" for reading\n"); + + char buffer[1000]; + // jump over initial comments + while (fgets(buffer, 1000, fd) && strncmp(buffer, "%%", 2)) + { + } + // read in number of rows and cols + if (!fgets(buffer, 1000, fd)) + throw MMException(string("Cannot read rows and cols while reading ")+fname+"\n"); + if (2 != sscanf(buffer, "%d %d", &rows, &cols)) + throw MMException("Couldn't parse rows and cols\n"); + // read in data + data = (double *) operator new[](rows*cols*sizeof(double)); + int len = rows*cols; + int i = 0; + while (fgets(buffer, 1000, fd) && i < len) + { + if (1 != sscanf(buffer, "%lf", &data[i])) + throw MMException(string("Couldn't parse float number ")+buffer+"\n"); + i++; + } + if (i < len) + { + char mes[1000]; + sprintf(mes, "Couldn't read all %d lines, read %d so far\n", len, i); + throw MMException(mes); + } + fclose(fd); +} + +MMMatrixIn::~MMMatrixIn() +{ + operator delete [](data); +} + +void +MMMatrixOut::write(const char *fname, int rows, int cols, const double *data) +{ + FILE *fd; + if (NULL == (fd = fopen(fname, "w"))) + throw MMException(string("Cannot open file ")+fname+" for writing\n"); + + if (0 > fprintf(fd, "%%%%MatrixMarket matrix array real general\n")) + throw MMException(string("Output error when writing file ")+fname); + if (0 > fprintf(fd, "%d %d\n", rows, cols)) + throw MMException(string("Output error when writing file ")+fname); + int running = 0; + for (int i = 0; i < cols; i++) + { + for (int j = 0; j < rows; j++) + { + if (0 > fprintf(fd, "%40.35g\n", data[running])) + throw MMException(string("Output error when writing file ")+fname); + running++; + } + } + fclose(fd); +} + +void +MMMatrixOut::write(const char *fname, const GeneralMatrix &m) +{ + write(fname, m.numRows(), m.numCols(), m.base()); +} diff --git a/dynare++/sylv/testing/MMMatrix.cpp b/dynare++/sylv/testing/MMMatrix.cpp deleted file mode 100644 index 9a503caab5ad2af6b8ead119521a8ec5970887c8..0000000000000000000000000000000000000000 --- a/dynare++/sylv/testing/MMMatrix.cpp +++ /dev/null @@ -1,71 +0,0 @@ -/* $Header: /var/lib/cvs/dynare_cpp/sylv/testing/MMMatrix.cpp,v 1.1.1.1 2004/06/04 13:01:13 kamenik Exp $ */ - -/* Tag $Name: $ */ - -#include "MMMatrix.h" - -#include <cstdio> -#include <cstring> - -MMMatrixIn::MMMatrixIn(const char* fname) -{ - FILE* fd; - if (NULL==(fd = fopen(fname,"r"))) - throw MMException(string("Cannot open file ")+fname+" for reading\n"); - - char buffer[1000]; - // jump over initial comments - while (fgets(buffer, 1000, fd) && strncmp(buffer, "%%", 2)) {} - // read in number of rows and cols - if (!fgets(buffer, 1000, fd)) - throw MMException(string("Cannot read rows and cols while reading ")+fname+"\n"); - if (2 != sscanf(buffer, "%d %d", &rows, &cols)) - throw MMException("Couldn't parse rows and cols\n"); - // read in data - data = (double*) operator new[](rows*cols*sizeof(double)); - int len = rows*cols; - int i = 0; - while (fgets(buffer, 1000, fd) && i < len) { - if (1 != sscanf(buffer, "%lf", &data[i])) - throw MMException(string("Couldn't parse float number ")+buffer+"\n"); - i++; - } - if (i < len) { - char mes[1000]; - sprintf(mes,"Couldn't read all %d lines, read %d so far\n",len,i); - throw MMException(mes); - } - fclose(fd); -} - -MMMatrixIn::~MMMatrixIn() -{ - operator delete [](data); -} - - -void MMMatrixOut::write(const char* fname, int rows, int cols, const double* data) -{ - FILE* fd; - if (NULL==(fd = fopen(fname,"w"))) - throw MMException(string("Cannot open file ")+fname+" for writing\n"); - - if (0 > fprintf(fd, "%%%%MatrixMarket matrix array real general\n")) - throw MMException(string("Output error when writing file ")+fname); - if (0 > fprintf(fd, "%d %d\n", rows, cols)) - throw MMException(string("Output error when writing file ")+fname); - int running = 0; - for (int i = 0; i < cols; i++) { - for (int j = 0 ; j < rows; j++) { - if (0 > fprintf(fd, "%40.35g\n", data[running])) - throw MMException(string("Output error when writing file ")+fname); - running++; - } - } - fclose(fd); -} - -void MMMatrixOut::write(const char* fname, const GeneralMatrix& m) -{ - write(fname, m.numRows(), m.numCols(), m.base()); -} diff --git a/dynare++/sylv/testing/MMMatrix.h b/dynare++/sylv/testing/MMMatrix.hh similarity index 95% rename from dynare++/sylv/testing/MMMatrix.h rename to dynare++/sylv/testing/MMMatrix.hh index f6afaa30dc2183d32908ea176cf786a8d6d341d8..3cd043804a2a479ce343fec0896430fd76e5402f 100644 --- a/dynare++/sylv/testing/MMMatrix.h +++ b/dynare++/sylv/testing/MMMatrix.hh @@ -5,8 +5,8 @@ #ifndef MM_MATRIX_H #define MM_MATRIX_H -#include "GeneralMatrix.h" -#include "SylvMemory.h" +#include "GeneralMatrix.hh" +#include "SylvMemory.hh" #include <string> diff --git a/dynare++/sylv/testing/Makefile.am b/dynare++/sylv/testing/Makefile.am index d62d0ef025f3db6fbaff987e16325f6b2790d2a0..d5b54de82e2344b27e989cebf4439dfcdd44c7f9 100644 --- a/dynare++/sylv/testing/Makefile.am +++ b/dynare++/sylv/testing/Makefile.am @@ -1,6 +1,6 @@ check_PROGRAMS = tests -tests_SOURCES = MMMatrix.cpp MMMatrix.h tests.cpp +tests_SOURCES = MMMatrix.cc MMMatrix.hh tests.cc tests_LDADD = ../cc/libsylv.a $(LAPACK_LIBS) $(BLAS_LIBS) $(LIBS) $(FLIBS) tests_CPPFLAGS = -I../cc diff --git a/dynare++/sylv/testing/tests.cc b/dynare++/sylv/testing/tests.cc new file mode 100644 index 0000000000000000000000000000000000000000..ba90ac175ae4c1b07b9cafc05b1255832d8215b7 --- /dev/null +++ b/dynare++/sylv/testing/tests.cc @@ -0,0 +1,1226 @@ +/* $Header: /var/lib/cvs/dynare_cpp/sylv/testing/tests.cpp,v 1.2 2004/07/05 19:55:48 kamenik Exp $ */ + +/* Tag $Name: $ */ + +#include "SylvException.hh" +#include "QuasiTriangular.hh" +#include "QuasiTriangularZero.hh" +#include "Vector.hh" +#include "KronVector.hh" +#include "KronUtils.hh" +#include "TriangularSylvester.hh" +#include "GeneralSylvester.hh" +#include "SylvMemory.hh" +#include "SchurDecompEig.hh" +#include "SimilarityDecomp.hh" +#include "IterativeSylvester.hh" +#include "SylvMatrix.hh" + +#include "MMMatrix.hh" + +#include <cstdio> +#include <cstring> +#include <ctime> + +#include <cmath> + +class TestRunnable : public MallocAllocator +{ + char name[100]; + static double eps_norm; +public: + TestRunnable(const char *n) + { + strncpy(name, n, 100); + } + bool test() const; + virtual bool run() const = 0; + const char * + getName() const + { + return name; + } +protected: + // declaration of auxiliary static methods + static bool quasi_solve(bool trans, const char *mname, const char *vname); + static bool mult_kron(bool trans, const char *mname, const char *vname, + const char *cname, int m, int n, int depth); + static bool level_kron(bool trans, const char *mname, const char *vname, + const char *cname, int level, int m, int n, int depth); + static bool kron_power(const char *m1name, const char *m2name, const char *vname, + const char *cname, int m, int n, int depth); + static bool lin_eval(const char *m1name, const char *m2name, const char *vname, + const char *cname, int m, int n, int depth, + double alpha, double beta1, double beta2); + static bool qua_eval(const char *m1name, const char *m2name, const char *vname, + const char *cname, int m, int n, int depth, + double alpha, double betas, double gamma, + double delta1, double delta2); + static bool tri_sylv(const char *m1name, const char *m2name, const char *vname, + int m, int n, int depth); + static bool gen_sylv(const char *aname, const char *bname, const char *cname, + const char *dname, int m, int n, int order); + static bool eig_bubble(const char *aname, int from, int to); + static bool block_diag(const char *aname, double log10norm = 3.0); + static bool iter_sylv(const char *m1name, const char *m2name, const char *vname, + int m, int n, int depth); +}; + +double TestRunnable::eps_norm = 1.0e-10; + +bool +TestRunnable::test() const +{ + printf("Running test <%s>\n", name); + clock_t start = clock(); + bool passed = run(); + clock_t end = clock(); + printf("CPU time %8.4g (CPU seconds)..................", + ((double) (end-start))/CLOCKS_PER_SEC); + if (passed) + { + printf("passed\n\n"); + return passed; + } + else + { + printf("FAILED\n\n"); + return passed; + } +} + +/**********************************************************/ +/* auxiliary methods */ +/**********************************************************/ + +bool +TestRunnable::quasi_solve(bool trans, const char *mname, const char *vname) +{ + MMMatrixIn mmt(mname); + MMMatrixIn mmv(vname); + + SylvMemoryDriver memdriver(1, mmt.row(), mmt.row(), 1); + QuasiTriangular *t; + QuasiTriangular *tsave; + if (mmt.row() == mmt.col()) + { + t = new QuasiTriangular(mmt.getData(), mmt.row()); + tsave = new QuasiTriangular(*t); + } + else if (mmt.row() > mmt.col()) + { + t = new QuasiTriangularZero(mmt.row()-mmt.col(), mmt.getData(), mmt.col()); + tsave = new QuasiTriangularZero((const QuasiTriangularZero &) *t); + } + else + { + printf(" Wrong quasi triangular dimensions, rows must be >= cols.\n"); + return false; + } + ConstVector v(mmv.getData(), mmv.row()); + Vector x(v.length()); + double eig_min = 1.0e20; + if (trans) + t->solveTrans(x, v, eig_min); + else + t->solve(x, v, eig_min); + printf("eig_min = %8.4g\n", eig_min); + Vector xx(v.length()); + if (trans) + tsave->multVecTrans(xx, ConstVector(x)); + else + tsave->multVec(xx, ConstVector(x)); + delete tsave; + delete t; + xx.add(-1.0, v); + xx.add(1.0, x); + double norm = xx.getNorm(); + printf("\terror norm = %8.4g\n", norm); + return (norm < eps_norm); +} + +bool +TestRunnable::mult_kron(bool trans, const char *mname, const char *vname, + const char *cname, int m, int n, int depth) +{ + MMMatrixIn mmt(mname); + MMMatrixIn mmv(vname); + MMMatrixIn mmc(cname); + + int length = power(m, depth)*n; + if (mmt.row() != m + || mmv.row() != length + || mmc.row() != length) + { + printf(" Incompatible sizes for krom mult action, len=%d, matrow=%d, m=%d, vrow=%d, crow=%d \n", length, mmt.row(), m, mmv.row(), mmc.row()); + return false; + } + + SylvMemoryDriver memdriver(1, m, n, depth); + QuasiTriangular t(mmt.getData(), mmt.row()); + Vector vraw(mmv.getData(), mmv.row()); + KronVector v(vraw, m, n, depth); + Vector craw(mmc.getData(), mmc.row()); + KronVector c(craw, m, n, depth); + if (trans) + t.multKronTrans(v); + else + t.multKron(v); + c.add(-1.0, v); + double norm = c.getNorm(); + printf("\terror norm = %8.4g\n", norm); + return (norm < eps_norm); +} + +bool +TestRunnable::level_kron(bool trans, const char *mname, const char *vname, + const char *cname, int level, int m, int n, int depth) +{ + MMMatrixIn mmt(mname); + MMMatrixIn mmv(vname); + MMMatrixIn mmc(cname); + + int length = power(m, depth)*n; + if (level > 0 && mmt.row() != m + || level == 0 && mmt.row() != n + || mmv.row() != length + || mmc.row() != length) + { + printf(" Incompatible sizes for krom mult action, len=%d, matrow=%d, m=%d, n=%d, vrow=%d, crow=%d \n", length, mmt.row(), m, n, mmv.row(), mmc.row()); + return false; + } + + SylvMemoryDriver memdriver(1, m, n, depth); + QuasiTriangular t(mmt.getData(), mmt.row()); + Vector vraw(mmv.getData(), mmv.row()); + ConstKronVector v(vraw, m, n, depth); + Vector craw(mmc.getData(), mmc.row()); + KronVector c(craw, m, n, depth); + KronVector x(v); + if (trans) + KronUtils::multAtLevelTrans(level, t, x); + else + KronUtils::multAtLevel(level, t, x); + x.add(-1, c); + double norm = x.getNorm(); + printf("\terror norm = %8.4g\n", norm); + return (norm < eps_norm); +} + +bool +TestRunnable::kron_power(const char *m1name, const char *m2name, const char *vname, + const char *cname, int m, int n, int depth) +{ + MMMatrixIn mmt1(m1name); + MMMatrixIn mmt2(m2name); + MMMatrixIn mmv(vname); + MMMatrixIn mmc(cname); + + int length = power(m, depth)*n; + if (mmt1.row() != m + || mmt2.row() != n + || mmv.row() != length + || mmc.row() != length) + { + printf(" Incompatible sizes for krom power mult action, len=%d, row1=%d, row2=%d, m=%d, n=%d, vrow=%d, crow=%d \n", length, mmt1.row(), mmt2.row(), m, n, mmv.row(), mmc.row()); + return false; + } + + SylvMemoryDriver memdriver(2, m, n, depth); + QuasiTriangular t1(mmt1.getData(), mmt1.row()); + QuasiTriangular t2(mmt2.getData(), mmt2.row()); + Vector vraw(mmv.getData(), mmv.row()); + ConstKronVector v(vraw, m, n, depth); + Vector craw(mmc.getData(), mmc.row()); + KronVector c(craw, m, n, depth); + KronVector x(v); + memdriver.setStackMode(true); + KronUtils::multKron(t1, t2, x); + memdriver.setStackMode(false); + x.add(-1, c); + double norm = x.getNorm(); + printf("\terror norm = %8.4g\n", norm); + return (norm < eps_norm); +} + +bool +TestRunnable::lin_eval(const char *m1name, const char *m2name, const char *vname, + const char *cname, int m, int n, int depth, + double alpha, double beta1, double beta2) +{ + MMMatrixIn mmt1(m1name); + MMMatrixIn mmt2(m2name); + MMMatrixIn mmv(vname); + MMMatrixIn mmc(cname); + + int length = power(m, depth)*n; + if (mmt1.row() != m + || mmt2.row() != n + || mmv.row() != 2*length + || mmc.row() != 2*length) + { + printf(" Incompatible sizes for lin eval action, len=%d, row1=%d, row2=%d, m=%d, n=%d, vrow=%d, crow=%d \n", length, mmt1.row(), mmt2.row(), m, n, mmv.row(), mmc.row()); + return false; + } + + SylvMemoryDriver memdriver(1, m, n, depth); + QuasiTriangular t1(mmt1.getData(), mmt1.row()); + QuasiTriangular t2(mmt2.getData(), mmt2.row()); + TriangularSylvester ts(t2, t1); + Vector vraw1(mmv.getData(), length); + ConstKronVector v1(vraw1, m, n, depth); + Vector vraw2(mmv.getData()+length, length); + ConstKronVector v2(vraw2, m, n, depth); + Vector craw1(mmc.getData(), length); + KronVector c1(craw1, m, n, depth); + Vector craw2(mmc.getData()+length, length); + KronVector c2(craw2, m, n, depth); + KronVector x1(m, n, depth); + KronVector x2(m, n, depth); + memdriver.setStackMode(true); + ts.linEval(alpha, beta1, beta2, x1, x2, v1, v2); + memdriver.setStackMode(false); + x1.add(-1, c1); + x2.add(-1, c2); + double norm1 = x1.getNorm(); + double norm2 = x2.getNorm(); + printf("\terror norm1 = %8.4g\n\terror norm2 = %8.4g\n", norm1, norm2); + return (norm1*norm1+norm2*norm2 < eps_norm*eps_norm); +} + +bool +TestRunnable::qua_eval(const char *m1name, const char *m2name, const char *vname, + const char *cname, int m, int n, int depth, + double alpha, double betas, double gamma, + double delta1, double delta2) +{ + MMMatrixIn mmt1(m1name); + MMMatrixIn mmt2(m2name); + MMMatrixIn mmv(vname); + MMMatrixIn mmc(cname); + + int length = power(m, depth)*n; + if (mmt1.row() != m + || mmt2.row() != n + || mmv.row() != 2*length + || mmc.row() != 2*length) + { + printf(" Incompatible sizes for qua eval action, len=%d, row1=%d, row2=%d, m=%d, n=%d, vrow=%d, crow=%d \n", length, mmt1.row(), mmt2.row(), m, n, mmv.row(), mmc.row()); + return false; + } + + SylvMemoryDriver memdriver(3, m, n, depth); + QuasiTriangular t1(mmt1.getData(), mmt1.row()); + QuasiTriangular t2(mmt2.getData(), mmt2.row()); + TriangularSylvester ts(t2, t1); + Vector vraw1(mmv.getData(), length); + ConstKronVector v1(vraw1, m, n, depth); + Vector vraw2(mmv.getData()+length, length); + ConstKronVector v2(vraw2, m, n, depth); + Vector craw1(mmc.getData(), length); + KronVector c1(craw1, m, n, depth); + Vector craw2(mmc.getData()+length, length); + KronVector c2(craw2, m, n, depth); + KronVector x1(m, n, depth); + KronVector x2(m, n, depth); + memdriver.setStackMode(true); + ts.quaEval(alpha, betas, gamma, delta1, delta2, x1, x2, v1, v2); + memdriver.setStackMode(false); + x1.add(-1, c1); + x2.add(-1, c2); + double norm1 = x1.getNorm(); + double norm2 = x2.getNorm(); + printf("\terror norm1 = %8.4g\n\terror norm2 = %8.4g\n", norm1, norm2); + return (norm1*norm1+norm2*norm2 < 100*eps_norm*eps_norm); // relax norm +} + +bool +TestRunnable::tri_sylv(const char *m1name, const char *m2name, const char *vname, + int m, int n, int depth) +{ + MMMatrixIn mmt1(m1name); + MMMatrixIn mmt2(m2name); + MMMatrixIn mmv(vname); + + int length = power(m, depth)*n; + if (mmt1.row() != m + || mmt2.row() != n + || mmv.row() != length) + { + printf(" Incompatible sizes for triangular sylvester action, len=%d, row1=%d, row2=%d, m=%d, n=%d, vrow=%d\n", length, mmt1.row(), mmt2.row(), m, n, mmv.row()); + return false; + } + + SylvMemoryDriver memdriver(4, m, n, depth); // need extra 2 for checks done via KronUtils::multKron + memdriver.setStackMode(true); + QuasiTriangular t1(mmt1.getData(), mmt1.row()); + QuasiTriangular t2(mmt2.getData(), mmt2.row()); + TriangularSylvester ts(t2, t1); + Vector vraw(mmv.getData(), length); + ConstKronVector v(vraw, m, n, depth); + KronVector d(v); // copy of v + SylvParams pars; + ts.solve(pars, d); + pars.print("\t"); + KronVector dcheck((const KronVector &)d); + KronUtils::multKron(t1, t2, dcheck); + dcheck.add(1.0, d); + dcheck.add(-1.0, v); + double norm = dcheck.getNorm(); + double xnorm = v.getNorm(); + printf("\trel. error norm = %8.4g\n", norm/xnorm); + double max = dcheck.getMax(); + double xmax = v.getMax(); + printf("\trel. error max = %8.4g\n", max/xmax); + memdriver.setStackMode(false); + return (norm < xnorm*eps_norm); +} + +bool +TestRunnable::gen_sylv(const char *aname, const char *bname, const char *cname, + const char *dname, int m, int n, int order) +{ + MMMatrixIn mma(aname); + MMMatrixIn mmb(bname); + MMMatrixIn mmc(cname); + MMMatrixIn mmd(dname); + + if (m != mmc.row() || m != mmc.col() + || n != mma.row() || n != mma.col() + || n != mmb.row() || n < mmb.col() + || n != mmd.row() || power(m, order) != mmd.col()) + { + printf(" Incompatible sizes for gen_sylv.\n"); + return false; + } + + SylvParams ps(true); + GeneralSylvester gs(order, n, m, n-mmb.col(), + mma.getData(), mmb.getData(), + mmc.getData(), mmd.getData(), + ps); + gs.solve(); + gs.check(mmd.getData()); + const SylvParams &pars = gs.getParams(); + pars.print("\t"); + return (*(pars.mat_err1) < eps_norm && *(pars.mat_errI) < eps_norm + && *(pars.mat_errF) < eps_norm && *(pars.vec_err1) < eps_norm + && *(pars.vec_errI) < eps_norm); +} + +bool +TestRunnable::eig_bubble(const char *aname, int from, int to) +{ + MMMatrixIn mma(aname); + + if (mma.row() != mma.col()) + { + printf(" Matrix is not square\n"); + return false; + } + + int n = mma.row(); + SylvMemoryDriver memdriver(3, n, n, 2); + QuasiTriangular orig(mma.getData(), n); + SchurDecompEig dec((const QuasiTriangular &)orig); + QuasiTriangular::diag_iter itf = dec.getT().diag_begin(); + QuasiTriangular::diag_iter itt = dec.getT().diag_begin(); + for (int i = 0; i < from; i++) + ++itf; + for (int i = 0; i < to; i++) + ++itt; + itt = dec.bubbleEigen(itf, itt); + SqSylvMatrix check(dec.getQ(), dec.getT()); + check.multRightTrans(dec.getQ()); + check.add(-1, orig); + double norm1 = check.getNorm1(); + double normInf = check.getNormInf(); + double onorm1 = orig.getNorm1(); + double onormInf = orig.getNormInf(); + printf("\tabs. error1 = %8.4g\n", norm1); + printf("\tabs. errorI = %8.4g\n", normInf); + printf("\trel. error1 = %8.4g\n", norm1/onorm1); + printf("\trel. errorI = %8.4g\n", normInf/onormInf); + return (norm1 < eps_norm*onorm1 && normInf < eps_norm*onormInf); +} + +bool +TestRunnable::block_diag(const char *aname, double log10norm) +{ + MMMatrixIn mma(aname); + + if (mma.row() != mma.col()) + { + printf(" Matrix is not square\n"); + return false; + } + + int n = mma.row(); + SylvMemoryDriver memdriver(3, n, n, 2); + SqSylvMatrix orig(mma.getData(), n); + SimilarityDecomp dec(orig.base(), orig.numRows(), log10norm); + dec.getB().printInfo(); + SqSylvMatrix check(dec.getQ(), dec.getB()); + check.multRight(dec.getInvQ()); + check.add(-1, orig); + double norm1 = check.getNorm1(); + double normInf = check.getNormInf(); + double onorm1 = orig.getNorm1(); + double onormInf = orig.getNormInf(); + printf("\terror Q*B*invQ:\n"); + printf("\tabs. error1 = %8.4g\n", norm1); + printf("\tabs. errorI = %8.4g\n", normInf); + printf("\trel. error1 = %8.4g\n", norm1/onorm1); + printf("\trel. errorI = %8.4g\n", normInf/onormInf); + SqSylvMatrix check2(dec.getQ(), dec.getInvQ()); + SqSylvMatrix in(n); + in.setUnit(); + check2.add(-1, in); + double nor1 = check2.getNorm1(); + double norInf = check2.getNormInf(); + printf("\terror Q*invQ:\n"); + printf("\tabs. error1 = %8.4g\n", nor1); + printf("\tabs. errorI = %8.4g\n", norInf); + return (norm1 < eps_norm*pow(10, log10norm)*onorm1); +} + +bool +TestRunnable::iter_sylv(const char *m1name, const char *m2name, const char *vname, + int m, int n, int depth) +{ + MMMatrixIn mmt1(m1name); + MMMatrixIn mmt2(m2name); + MMMatrixIn mmv(vname); + + int length = power(m, depth)*n; + if (mmt1.row() != m + || mmt2.row() != n + || mmv.row() != length) + { + printf(" Incompatible sizes for triangular sylvester iteration, len=%d, row1=%d, row2=%d, m=%d, n=%d, vrow=%d\n", length, mmt1.row(), mmt2.row(), m, n, mmv.row()); + return false; + } + + SylvMemoryDriver memdriver(4, m, n, depth); // need extra 2 for checks done via KronUtils::multKron + memdriver.setStackMode(true); + QuasiTriangular t1(mmt1.getData(), mmt1.row()); + QuasiTriangular t2(mmt2.getData(), mmt2.row()); + IterativeSylvester is(t2, t1); + Vector vraw(mmv.getData(), length); + ConstKronVector v(vraw, m, n, depth); + KronVector d(v); // copy of v + SylvParams pars; + pars.method = SylvParams::iter; + is.solve(pars, d); + pars.print("\t"); + KronVector dcheck((const KronVector &)d); + KronUtils::multKron(t1, t2, dcheck); + dcheck.add(1.0, d); + dcheck.add(-1.0, v); + double cnorm = dcheck.getNorm(); + double xnorm = v.getNorm(); + printf("\trel. error norm = %8.4g\n", cnorm/xnorm); + double max = dcheck.getMax(); + double xmax = v.getMax(); + printf("\trel. error max = %8.4g\n", max/xmax); + memdriver.setStackMode(false); + return (cnorm < xnorm*eps_norm); +} + +/**********************************************************/ +/* sub classes declarations */ +/**********************************************************/ + +class PureTriangTest : public TestRunnable +{ +public: + PureTriangTest() : TestRunnable("pure triangular solve (5)") + { + } + bool run() const; +}; + +class PureTriangTransTest : public TestRunnable +{ +public: + PureTriangTransTest() : TestRunnable("pure triangular solve trans (5)") + { + } + bool run() const; +}; + +class PureTrLargeTest : public TestRunnable +{ +public: + PureTrLargeTest() : TestRunnable("pure triangular large solve (300)") + { + } + bool run() const; +}; + +class PureTrLargeTransTest : public TestRunnable +{ +public: + PureTrLargeTransTest() : TestRunnable("pure triangular large solve trans (300)") + { + } + bool run() const; +}; + +class QuasiTriangTest : public TestRunnable +{ +public: + QuasiTriangTest() : TestRunnable("quasi triangular solve (7)") + { + } + bool run() const; +}; + +class QuasiTriangTransTest : public TestRunnable +{ +public: + QuasiTriangTransTest() : TestRunnable("quasi triangular solve trans (7)") + { + } + bool run() const; +}; + +class QuasiTrLargeTest : public TestRunnable +{ +public: + QuasiTrLargeTest() : TestRunnable("quasi triangular solve large (250)") + { + } + bool run() const; +}; + +class QuasiTrLargeTransTest : public TestRunnable +{ +public: + QuasiTrLargeTransTest() : TestRunnable("quasi triangular solve large trans (250)") + { + } + bool run() const; +}; + +class QuasiZeroSmallTest : public TestRunnable +{ +public: + QuasiZeroSmallTest() : TestRunnable("quasi tr. zero small test (2x1)") + { + } + bool run() const; +}; + +class MultKronSmallTest : public TestRunnable +{ +public: + MultKronSmallTest() : TestRunnable("kronecker small mult (2=2x1)") + { + } + bool run() const; +}; + +class MultKronTest : public TestRunnable +{ +public: + MultKronTest() : TestRunnable("kronecker mult (245=7x7x5)") + { + } + bool run() const; +}; + +class MultKronSmallTransTest : public TestRunnable +{ +public: + MultKronSmallTransTest() : TestRunnable("kronecker small trans mult (2=2x1)") + { + } + bool run() const; +}; + +class MultKronTransTest : public TestRunnable +{ +public: + MultKronTransTest() : TestRunnable("kronecker trans mult (245=7x7x5)") + { + } + bool run() const; +}; + +class LevelKronTest : public TestRunnable +{ +public: + LevelKronTest() : TestRunnable("kronecker level mult (1715=7x[7]x7x5)") + { + } + bool run() const; +}; + +class LevelKronTransTest : public TestRunnable +{ +public: + LevelKronTransTest() : TestRunnable("kronecker level trans mult (1715=7x[7]x7x5)") + { + } + bool run() const; +}; + +class LevelZeroKronTest : public TestRunnable +{ +public: + LevelZeroKronTest() : TestRunnable("kronecker level mult (1715=7x7x7x[5])") + { + } + bool run() const; +}; + +class LevelZeroKronTransTest : public TestRunnable +{ +public: + LevelZeroKronTransTest() : TestRunnable("kronecker level trans mult (1715=7x7x7x[5])") + { + } + bool run() const; +}; + +class KronPowerTest : public TestRunnable +{ +public: + KronPowerTest() : TestRunnable("kronecker power mult (1715=7x7x7x5)") + { + } + bool run() const; +}; + +class SmallLinEvalTest : public TestRunnable +{ +public: + SmallLinEvalTest() : TestRunnable("lin eval (24=2 x 2x2x3)") + { + } + bool run() const; +}; + +class LinEvalTest : public TestRunnable +{ +public: + LinEvalTest() : TestRunnable("lin eval (490=2 x 7x7x5)") + { + } + bool run() const; +}; + +class SmallQuaEvalTest : public TestRunnable +{ +public: + SmallQuaEvalTest() : TestRunnable("qua eval (24=2 x 2x2x3)") + { + } + bool run() const; +}; + +class QuaEvalTest : public TestRunnable +{ +public: + QuaEvalTest() : TestRunnable("qua eval (490=2 x 7x7x5)") + { + } + bool run() const; +}; + +class TriSylvSmallRealTest : public TestRunnable +{ +public: + TriSylvSmallRealTest() : TestRunnable("triangular sylvester small real solve (12=2x2x3)") + { + } + bool run() const; +}; + +class TriSylvSmallComplexTest : public TestRunnable +{ +public: + TriSylvSmallComplexTest() : TestRunnable("triangular sylvester small complx solve (12=2x2x3)") + { + } + bool run() const; +}; + +class TriSylvTest : public TestRunnable +{ +public: + TriSylvTest() : TestRunnable("triangular sylvester solve (245=7x7x5)") + { + } + bool run() const; +}; + +class TriSylvBigTest : public TestRunnable +{ +public: + TriSylvBigTest() : TestRunnable("triangular sylvester big solve (48000=40x40x30)") + { + } + bool run() const; +}; + +class TriSylvLargeTest : public TestRunnable +{ +public: + TriSylvLargeTest() : TestRunnable("triangular sylvester large solve (1920000=40x40x40x30)") + { + } + bool run() const; +}; + +class IterSylvTest : public TestRunnable +{ +public: + IterSylvTest() : TestRunnable("iterative sylvester solve (245=7x7x5)") + { + } + bool run() const; +}; + +class IterSylvLargeTest : public TestRunnable +{ +public: + IterSylvLargeTest() : TestRunnable("iterative sylvester large solve (1920000=40x40x40x30)") + { + } + bool run() const; +}; + +class GenSylvSmallTest : public TestRunnable +{ +public: + GenSylvSmallTest() : TestRunnable("general sylvester small solve (18=3x3x2)") + { + } + bool run() const; +}; + +class GenSylvTest : public TestRunnable +{ +public: + GenSylvTest() : TestRunnable("general sylvester solve (12000=20x20x30)") + { + } + bool run() const; +}; + +class GenSylvSingTest : public TestRunnable +{ +public: + GenSylvSingTest() : TestRunnable("general sylvester solve for sing. C (2500000=50x50x50x20)") + { + } + bool run() const; +}; + +class GenSylvLargeTest : public TestRunnable +{ +public: + GenSylvLargeTest() : TestRunnable("general sylvester solve (2500000=50x50x50x20)") + { + } + bool run() const; +}; + +class EigBubFrankTest : public TestRunnable +{ +public: + EigBubFrankTest() : TestRunnable("eig. bubble frank test (12x12)") + { + } + bool run() const; +}; + +class EigBubSplitTest : public TestRunnable +{ + // complex eigenvalue is split by swapping it with real +public: + EigBubSplitTest() : TestRunnable("eig. bubble complex split test (3x3)") + { + } + bool run() const; +}; + +class EigBubSameTest : public TestRunnable +{ + // complex eigenevalue bypasses the same complex eigenvalue +public: + EigBubSameTest() : TestRunnable("eig. bubble same test (5x5)") + { + } + bool run() const; +}; + +class BlockDiagSmallTest : public TestRunnable +{ +public: + BlockDiagSmallTest() : TestRunnable("block diagonalization small test (7x7)") + { + } + bool run() const; +}; + +class BlockDiagFrankTest : public TestRunnable +{ +public: + BlockDiagFrankTest() : TestRunnable("block diagonalization of frank (12x12)") + { + } + bool run() const; +}; + +class BlockDiagIllCondTest : public TestRunnable +{ +public: + BlockDiagIllCondTest() : TestRunnable("block diagonalization of ill conditioned (15x15)") + { + } + bool run() const; +}; + +class BlockDiagBigTest : public TestRunnable +{ +public: + BlockDiagBigTest() : TestRunnable("block diagonalization big test (50x50)") + { + } + bool run() const; +}; + +/**********************************************************/ +/* run methods of sub classes */ +/**********************************************************/ + +bool +PureTriangTest::run() const +{ + return quasi_solve(false, "tr5x5.mm", "v5.mm"); +} + +bool +PureTriangTransTest::run() const +{ + return quasi_solve(true, "tr5x5.mm", "v5.mm"); +} + +bool +PureTrLargeTest::run() const +{ + return quasi_solve(false, "tr300x300.mm", "v300.mm"); +} + +bool +PureTrLargeTransTest::run() const +{ + return quasi_solve(true, "tr300x300.mm", "v300.mm"); +} + +bool +QuasiTriangTest::run() const +{ + return quasi_solve(false, "qt7x7.mm", "v7.mm"); +} + +bool +QuasiTriangTransTest::run() const +{ + return quasi_solve(true, "qt7x7.mm", "v7.mm"); +} + +bool +QuasiTrLargeTest::run() const +{ + return quasi_solve(false, "qt250x250.mm", "v250.mm"); +} + +bool +QuasiTrLargeTransTest::run() const +{ + return quasi_solve(true, "qt250x250.mm", "v250.mm"); +} + +bool +QuasiZeroSmallTest::run() const +{ + return quasi_solve(false, "b2x1.mm", "v2.mm"); +} + +bool +MultKronSmallTest::run() const +{ + return mult_kron(false, "tr2x2.mm", "v2.mm", "vcheck2.mm", 2, 1, 1); +} + +bool +MultKronTest::run() const +{ + return mult_kron(false, "qt7x7.mm", "v245.mm", "vcheck245.mm", 7, 5, 2); +} + +bool +MultKronSmallTransTest::run() const +{ + return mult_kron(true, "tr2x2.mm", "v2.mm", "vcheck2a.mm", 2, 1, 1); +} + +bool +MultKronTransTest::run() const +{ + return mult_kron(true, "qt7x7.mm", "v245.mm", "vcheck245a.mm", 7, 5, 2); +} + +bool +LevelKronTest::run() const +{ + return level_kron(false, "qt7x7.mm", "v1715.mm", "vcheck1715.mm", 2, 7, 5, 3); +} + +bool +LevelKronTransTest::run() const +{ + return level_kron(true, "qt7x7.mm", "v1715.mm", "vcheck1715a.mm", 2, 7, 5, 3); +} + +bool +LevelZeroKronTest::run() const +{ + return level_kron(false, "tr5x5.mm", "v1715.mm", "vcheck1715b.mm", 0, 7, 5, 3); +} + +bool +LevelZeroKronTransTest::run() const +{ + return level_kron(true, "tr5x5.mm", "v1715.mm", "vcheck1715c.mm", 0, 7, 5, 3); +} + +bool +KronPowerTest::run() const +{ + return kron_power("qt7x7.mm", "tr5x5.mm", "v1715.mm", "vcheck1715d.mm", 7, 5, 3); +} + +bool +SmallLinEvalTest::run() const +{ + return lin_eval("qt2x2.mm", "qt3x3.mm", "v24.mm", "vcheck24.mm", 2, 3, 2, + 2, 1, 3); +} + +bool +LinEvalTest::run() const +{ + return lin_eval("qt7x7.mm", "tr5x5.mm", "v490.mm", "vcheck490.mm", 7, 5, 2, + 2, 1, 3); +} + +bool +SmallQuaEvalTest::run() const +{ + return qua_eval("qt2x2.mm", "qt3x3.mm", "v24.mm", "vcheck24q.mm", 2, 3, 2, + -0.5, 3, 2, 1, 3); +} + +bool +QuaEvalTest::run() const +{ + return qua_eval("qt7x7.mm", "tr5x5.mm", "v490.mm", "vcheck490q.mm", 7, 5, 2, + -0.5, 3, 2, 1, 3); +} + +bool +TriSylvSmallRealTest::run() const +{ + return tri_sylv("tr2x2.mm", "qt3x3.mm", "v12r.mm", 2, 3, 2); +} + +bool +TriSylvSmallComplexTest::run() const +{ + return tri_sylv("qt2x2.mm", "qt3x3.mm", "v12r.mm", 2, 3, 2); +} + +bool +TriSylvTest::run() const +{ + return tri_sylv("qt7x7eig06-09.mm", "tr5x5.mm", "v245r.mm", 7, 5, 2); +} + +bool +TriSylvBigTest::run() const +{ + return tri_sylv("qt40x40.mm", "qt30x30eig011-095.mm", "v48000.mm", 40, 30, 2); +} + +bool +TriSylvLargeTest::run() const +{ + return tri_sylv("qt40x40.mm", "qt30x30eig011-095.mm", "v1920000.mm", 40, 30, 3); +} + +bool +IterSylvTest::run() const +{ + return iter_sylv("qt7x7eig06-09.mm", "qt5x5.mm", "v245r.mm", 7, 5, 2); +} + +bool +IterSylvLargeTest::run() const +{ + return iter_sylv("qt40x40.mm", "qt30x30eig011-095.mm", "v1920000.mm", 40, 30, 3); +} + +bool +GenSylvSmallTest::run() const +{ + return gen_sylv("a2x2.mm", "b2x1.mm", "c3x3.mm", "d2x9.mm", 3, 2, 2); +} + +bool +GenSylvTest::run() const +{ + return gen_sylv("a30x30.mm", "b30x25.mm", "c20x20.mm", "d30x400.mm", 20, 30, 2); +} + +bool +GenSylvSingTest::run() const +{ + return gen_sylv("a20x20.mm", "b20x4.mm", "c50x50sing.mm", "d20x125000.mm", 50, 20, 3); +} + +bool +GenSylvLargeTest::run() const +{ + return gen_sylv("a20x20.mm", "b20x15.mm", "c50x50.mm", "d20x125000.mm", 50, 20, 3); +} + +bool +EigBubFrankTest::run() const +{ + return eig_bubble("qt_frank12x12.mm", 8, 0); +} + +bool +EigBubSplitTest::run() const +{ + return eig_bubble("qt_eps3x3.mm", 1, 0); +} + +bool +EigBubSameTest::run() const +{ + return eig_bubble("qt5x5.mm", 2, 0); +} + +bool +BlockDiagSmallTest::run() const +{ + return block_diag("qt7x7.mm", 0.1); +} + +bool +BlockDiagFrankTest::run() const +{ + return block_diag("qt_frank12x12.mm", 5); +} + +bool +BlockDiagIllCondTest::run() const +{ + return block_diag("ill_cond15x15.mm", 4.14); +} + +bool +BlockDiagBigTest::run() const +{ + return block_diag("c50x50.mm", 1.3); +} + +/**********************************************************/ +/* main */ +/**********************************************************/ + +int +main() +{ + TestRunnable *all_tests[50]; + // fill in vector of all tests + int num_tests = 0; + all_tests[num_tests++] = new PureTriangTest(); + all_tests[num_tests++] = new PureTriangTransTest(); + all_tests[num_tests++] = new PureTrLargeTest(); + all_tests[num_tests++] = new PureTrLargeTransTest(); + all_tests[num_tests++] = new QuasiTriangTest(); + all_tests[num_tests++] = new QuasiTriangTransTest(); + all_tests[num_tests++] = new QuasiTrLargeTest(); + all_tests[num_tests++] = new QuasiTrLargeTransTest(); + all_tests[num_tests++] = new QuasiZeroSmallTest(); + all_tests[num_tests++] = new MultKronSmallTest(); + all_tests[num_tests++] = new MultKronTest(); + all_tests[num_tests++] = new MultKronSmallTransTest(); + all_tests[num_tests++] = new MultKronTransTest(); + all_tests[num_tests++] = new LevelKronTest(); + all_tests[num_tests++] = new LevelKronTransTest(); + all_tests[num_tests++] = new LevelZeroKronTest(); + all_tests[num_tests++] = new LevelZeroKronTransTest(); + all_tests[num_tests++] = new KronPowerTest(); + all_tests[num_tests++] = new SmallLinEvalTest(); + all_tests[num_tests++] = new LinEvalTest(); + all_tests[num_tests++] = new SmallQuaEvalTest(); + all_tests[num_tests++] = new QuaEvalTest(); + all_tests[num_tests++] = new EigBubFrankTest(); + all_tests[num_tests++] = new EigBubSplitTest(); + all_tests[num_tests++] = new EigBubSameTest(); + all_tests[num_tests++] = new BlockDiagSmallTest(); + all_tests[num_tests++] = new BlockDiagFrankTest(); + all_tests[num_tests++] = new BlockDiagIllCondTest(); + all_tests[num_tests++] = new BlockDiagBigTest(); + all_tests[num_tests++] = new TriSylvSmallRealTest(); + all_tests[num_tests++] = new TriSylvSmallComplexTest(); + all_tests[num_tests++] = new TriSylvTest(); + all_tests[num_tests++] = new TriSylvBigTest(); + all_tests[num_tests++] = new TriSylvLargeTest(); + all_tests[num_tests++] = new IterSylvTest(); + all_tests[num_tests++] = new IterSylvLargeTest(); + all_tests[num_tests++] = new GenSylvSmallTest(); + all_tests[num_tests++] = new GenSylvTest(); + all_tests[num_tests++] = new GenSylvSingTest(); + all_tests[num_tests++] = new GenSylvLargeTest(); + + // launch the tests + int success = 0; + for (int i = 0; i < num_tests; i++) + { + try + { + if (all_tests[i]->test()) + success++; + } + catch (const MMException &e) + { + printf("Caugth MM exception in <%s>:\n%s", all_tests[i]->getName(), + e.getMessage()); + } + catch (SylvException &e) + { + printf("Caught Sylv exception in %s:\n", all_tests[i]->getName()); + e.printMessage(); + } + } + + printf("There were %d tests that failed out of %d tests run.\n", + num_tests - success, num_tests); + + // destroy + for (int i = 0; i < num_tests; i++) + { + delete all_tests[i]; + } + + return 0; +} diff --git a/dynare++/sylv/testing/tests.cpp b/dynare++/sylv/testing/tests.cpp deleted file mode 100644 index 5b1cc23389539fe3a37e2739cc3b8205fa4fc7db..0000000000000000000000000000000000000000 --- a/dynare++/sylv/testing/tests.cpp +++ /dev/null @@ -1,1022 +0,0 @@ -/* $Header: /var/lib/cvs/dynare_cpp/sylv/testing/tests.cpp,v 1.2 2004/07/05 19:55:48 kamenik Exp $ */ - -/* Tag $Name: $ */ - -#include "SylvException.h" -#include "QuasiTriangular.h" -#include "QuasiTriangularZero.h" -#include "Vector.h" -#include "KronVector.h" -#include "KronUtils.h" -#include "TriangularSylvester.h" -#include "GeneralSylvester.h" -#include "SylvMemory.h" -#include "SchurDecompEig.h" -#include "SimilarityDecomp.h" -#include "IterativeSylvester.h" -#include "SylvMatrix.h" - -#include "MMMatrix.h" - -#include <cstdio> -#include <cstring> -#include <ctime> - -#include <cmath> - -class TestRunnable : public MallocAllocator { - char name[100]; - static double eps_norm; -public: - TestRunnable(const char* n){strncpy(name, n, 100);} - bool test() const; - virtual bool run() const =0; - const char* getName() const {return name;} -protected: - // declaration of auxiliary static methods - static bool quasi_solve(bool trans, const char* mname, const char* vname); - static bool mult_kron(bool trans, const char* mname, const char* vname, - const char* cname, int m, int n, int depth); - static bool level_kron(bool trans, const char* mname, const char* vname, - const char* cname, int level, int m, int n, int depth); - static bool kron_power(const char* m1name, const char* m2name, const char* vname, - const char* cname, int m, int n, int depth); - static bool lin_eval(const char* m1name, const char* m2name, const char* vname, - const char* cname, int m, int n, int depth, - double alpha, double beta1, double beta2); - static bool qua_eval(const char* m1name, const char* m2name, const char* vname, - const char* cname, int m, int n, int depth, - double alpha, double betas, double gamma, - double delta1, double delta2); - static bool tri_sylv(const char* m1name, const char* m2name, const char* vname, - int m, int n, int depth); - static bool gen_sylv(const char* aname, const char* bname, const char* cname, - const char* dname, int m, int n, int order); - static bool eig_bubble(const char* aname, int from, int to); - static bool block_diag(const char* aname, double log10norm = 3.0); - static bool iter_sylv(const char* m1name, const char* m2name, const char* vname, - int m, int n, int depth); -}; - -double TestRunnable::eps_norm = 1.0e-10; - -bool TestRunnable::test() const -{ - printf("Running test <%s>\n",name); - clock_t start = clock(); - bool passed = run(); - clock_t end = clock(); - printf("CPU time %8.4g (CPU seconds)..................", - ((double)(end-start))/CLOCKS_PER_SEC); - if (passed) { - printf("passed\n\n"); - return passed; - } else { - printf("FAILED\n\n"); - return passed; - } -} - -/**********************************************************/ -/* auxiliary methods */ -/**********************************************************/ - -bool TestRunnable::quasi_solve(bool trans, const char* mname, const char* vname) -{ - MMMatrixIn mmt(mname); - MMMatrixIn mmv(vname); - - SylvMemoryDriver memdriver(1, mmt.row(), mmt.row(), 1); - QuasiTriangular* t; - QuasiTriangular* tsave; - if (mmt.row()==mmt.col()) { - t = new QuasiTriangular(mmt.getData(), mmt.row()); - tsave = new QuasiTriangular(*t); - } else if (mmt.row()>mmt.col()) { - t = new QuasiTriangularZero(mmt.row()-mmt.col(), mmt.getData(), mmt.col()); - tsave = new QuasiTriangularZero((const QuasiTriangularZero&)*t); - } else { - printf(" Wrong quasi triangular dimensions, rows must be >= cols.\n"); - return false; - } - ConstVector v(mmv.getData(), mmv.row()); - Vector x(v.length()); - double eig_min = 1.0e20; - if (trans) - t->solveTrans(x, v, eig_min); - else - t->solve(x, v, eig_min); - printf("eig_min = %8.4g\n", eig_min); - Vector xx(v.length()); - if (trans) - tsave->multVecTrans(xx, ConstVector(x)); - else - tsave->multVec(xx, ConstVector(x)); - delete tsave; - delete t; - xx.add(-1.0, v); - xx.add(1.0, x); - double norm = xx.getNorm(); - printf("\terror norm = %8.4g\n",norm); - return (norm < eps_norm); -} - -bool TestRunnable::mult_kron(bool trans, const char* mname, const char* vname, - const char* cname, int m, int n, int depth) -{ - MMMatrixIn mmt(mname); - MMMatrixIn mmv(vname); - MMMatrixIn mmc(cname); - - int length = power(m,depth)*n; - if (mmt.row() != m || - mmv.row() != length || - mmc.row() != length) { - printf(" Incompatible sizes for krom mult action, len=%d, matrow=%d, m=%d, vrow=%d, crow=%d \n",length,mmt.row(), m, mmv.row(), mmc.row()); - return false; - } - - SylvMemoryDriver memdriver(1, m, n, depth); - QuasiTriangular t(mmt.getData(), mmt.row()); - Vector vraw(mmv.getData(), mmv.row()); - KronVector v(vraw, m, n, depth); - Vector craw(mmc.getData(), mmc.row()); - KronVector c(craw, m, n, depth); - if (trans) - t.multKronTrans(v); - else - t.multKron(v); - c.add(-1.0, v); - double norm = c.getNorm(); - printf("\terror norm = %8.4g\n",norm); - return (norm < eps_norm); -} - -bool TestRunnable::level_kron(bool trans, const char* mname, const char* vname, - const char* cname, int level, int m, int n, int depth) -{ - MMMatrixIn mmt(mname); - MMMatrixIn mmv(vname); - MMMatrixIn mmc(cname); - - int length = power(m,depth)*n; - if (level > 0 && mmt.row() != m || - level == 0 && mmt.row() != n || - mmv.row() != length || - mmc.row() != length) { - printf(" Incompatible sizes for krom mult action, len=%d, matrow=%d, m=%d, n=%d, vrow=%d, crow=%d \n",length, mmt.row(), m, n, mmv.row(), mmc.row()); - return false; - } - - SylvMemoryDriver memdriver(1, m, n, depth); - QuasiTriangular t(mmt.getData(), mmt.row()); - Vector vraw(mmv.getData(), mmv.row()); - ConstKronVector v(vraw, m, n, depth); - Vector craw(mmc.getData(), mmc.row()); - KronVector c(craw, m, n, depth); - KronVector x(v); - if (trans) - KronUtils::multAtLevelTrans(level, t, x); - else - KronUtils::multAtLevel(level, t, x); - x.add(-1, c); - double norm = x.getNorm(); - printf("\terror norm = %8.4g\n",norm); - return (norm < eps_norm); -} - -bool TestRunnable::kron_power(const char* m1name, const char* m2name, const char* vname, - const char* cname, int m, int n, int depth) -{ - MMMatrixIn mmt1(m1name); - MMMatrixIn mmt2(m2name); - MMMatrixIn mmv(vname); - MMMatrixIn mmc(cname); - - int length = power(m,depth)*n; - if (mmt1.row() != m || - mmt2.row() != n || - mmv.row() != length || - mmc.row() != length) { - printf(" Incompatible sizes for krom power mult action, len=%d, row1=%d, row2=%d, m=%d, n=%d, vrow=%d, crow=%d \n",length,mmt1.row(), mmt2.row(), m, n, mmv.row(), mmc.row()); - return false; - } - - SylvMemoryDriver memdriver(2, m, n, depth); - QuasiTriangular t1(mmt1.getData(), mmt1.row()); - QuasiTriangular t2(mmt2.getData(), mmt2.row()); - Vector vraw(mmv.getData(), mmv.row()); - ConstKronVector v(vraw, m, n, depth); - Vector craw(mmc.getData(), mmc.row()); - KronVector c(craw, m, n, depth); - KronVector x(v); - memdriver.setStackMode(true); - KronUtils::multKron(t1, t2, x); - memdriver.setStackMode(false); - x.add(-1, c); - double norm = x.getNorm(); - printf("\terror norm = %8.4g\n",norm); - return (norm < eps_norm); -} - -bool TestRunnable::lin_eval(const char* m1name, const char* m2name, const char* vname, - const char* cname, int m, int n, int depth, - double alpha, double beta1, double beta2) -{ - MMMatrixIn mmt1(m1name); - MMMatrixIn mmt2(m2name); - MMMatrixIn mmv(vname); - MMMatrixIn mmc(cname); - - int length = power(m,depth)*n; - if (mmt1.row() != m || - mmt2.row() != n || - mmv.row() != 2*length || - mmc.row() != 2*length) { - printf(" Incompatible sizes for lin eval action, len=%d, row1=%d, row2=%d, m=%d, n=%d, vrow=%d, crow=%d \n",length,mmt1.row(), mmt2.row(), m, n, mmv.row(), mmc.row()); - return false; - } - - SylvMemoryDriver memdriver(1, m, n, depth); - QuasiTriangular t1(mmt1.getData(), mmt1.row()); - QuasiTriangular t2(mmt2.getData(), mmt2.row()); - TriangularSylvester ts(t2, t1); - Vector vraw1(mmv.getData(), length); - ConstKronVector v1(vraw1, m, n, depth); - Vector vraw2(mmv.getData()+length, length); - ConstKronVector v2(vraw2, m, n, depth); - Vector craw1(mmc.getData(), length); - KronVector c1(craw1, m, n, depth); - Vector craw2(mmc.getData()+length, length); - KronVector c2(craw2, m, n, depth); - KronVector x1(m, n, depth); - KronVector x2(m, n, depth); - memdriver.setStackMode(true); - ts.linEval(alpha, beta1, beta2, x1, x2, v1, v2); - memdriver.setStackMode(false); - x1.add(-1, c1); - x2.add(-1, c2); - double norm1 = x1.getNorm(); - double norm2 = x2.getNorm(); - printf("\terror norm1 = %8.4g\n\terror norm2 = %8.4g\n",norm1,norm2); - return (norm1*norm1+norm2*norm2 < eps_norm*eps_norm); -} - - -bool TestRunnable::qua_eval(const char* m1name, const char* m2name, const char* vname, - const char* cname, int m, int n, int depth, - double alpha, double betas, double gamma, - double delta1, double delta2) -{ - MMMatrixIn mmt1(m1name); - MMMatrixIn mmt2(m2name); - MMMatrixIn mmv(vname); - MMMatrixIn mmc(cname); - - int length = power(m,depth)*n; - if (mmt1.row() != m || - mmt2.row() != n || - mmv.row() != 2*length || - mmc.row() != 2*length) { - printf(" Incompatible sizes for qua eval action, len=%d, row1=%d, row2=%d, m=%d, n=%d, vrow=%d, crow=%d \n",length,mmt1.row(), mmt2.row(), m, n, mmv.row(), mmc.row()); - return false; - } - - SylvMemoryDriver memdriver(3, m, n, depth); - QuasiTriangular t1(mmt1.getData(), mmt1.row()); - QuasiTriangular t2(mmt2.getData(), mmt2.row()); - TriangularSylvester ts(t2, t1); - Vector vraw1(mmv.getData(), length); - ConstKronVector v1(vraw1, m, n, depth); - Vector vraw2(mmv.getData()+length, length); - ConstKronVector v2(vraw2, m, n, depth); - Vector craw1(mmc.getData(), length); - KronVector c1(craw1, m, n, depth); - Vector craw2(mmc.getData()+length, length); - KronVector c2(craw2, m, n, depth); - KronVector x1(m, n, depth); - KronVector x2(m, n, depth); - memdriver.setStackMode(true); - ts.quaEval(alpha, betas, gamma, delta1, delta2, x1, x2, v1, v2); - memdriver.setStackMode(false); - x1.add(-1, c1); - x2.add(-1, c2); - double norm1 = x1.getNorm(); - double norm2 = x2.getNorm(); - printf("\terror norm1 = %8.4g\n\terror norm2 = %8.4g\n",norm1,norm2); - return (norm1*norm1+norm2*norm2 < 100*eps_norm*eps_norm); // relax norm -} - -bool TestRunnable::tri_sylv(const char* m1name, const char* m2name, const char* vname, - int m, int n, int depth) -{ - MMMatrixIn mmt1(m1name); - MMMatrixIn mmt2(m2name); - MMMatrixIn mmv(vname); - - int length = power(m,depth)*n; - if (mmt1.row() != m || - mmt2.row() != n || - mmv.row() != length) { - printf(" Incompatible sizes for triangular sylvester action, len=%d, row1=%d, row2=%d, m=%d, n=%d, vrow=%d\n",length,mmt1.row(), mmt2.row(), m, n, mmv.row()); - return false; - } - - SylvMemoryDriver memdriver(4, m, n, depth); // need extra 2 for checks done via KronUtils::multKron - memdriver.setStackMode(true); - QuasiTriangular t1(mmt1.getData(), mmt1.row()); - QuasiTriangular t2(mmt2.getData(), mmt2.row()); - TriangularSylvester ts(t2, t1); - Vector vraw(mmv.getData(), length); - ConstKronVector v(vraw, m, n, depth); - KronVector d(v); // copy of v - SylvParams pars; - ts.solve(pars, d); - pars.print("\t"); - KronVector dcheck((const KronVector&)d); - KronUtils::multKron(t1, t2, dcheck); - dcheck.add(1.0, d); - dcheck.add(-1.0, v); - double norm = dcheck.getNorm(); - double xnorm = v.getNorm(); - printf("\trel. error norm = %8.4g\n",norm/xnorm); - double max = dcheck.getMax(); - double xmax = v.getMax(); - printf("\trel. error max = %8.4g\n", max/xmax); - memdriver.setStackMode(false); - return (norm < xnorm*eps_norm); -} - -bool TestRunnable::gen_sylv(const char* aname, const char* bname, const char* cname, - const char* dname, int m, int n, int order) -{ - MMMatrixIn mma(aname); - MMMatrixIn mmb(bname); - MMMatrixIn mmc(cname); - MMMatrixIn mmd(dname); - - if (m != mmc.row() || m != mmc.col() || - n != mma.row() || n != mma.col() || - n != mmb.row() || n < mmb.col() || - n != mmd.row() || power(m, order) != mmd.col()) { - printf(" Incompatible sizes for gen_sylv.\n"); - return false; - } - - SylvParams ps(true); - GeneralSylvester gs(order, n, m, n-mmb.col(), - mma.getData(), mmb.getData(), - mmc.getData(), mmd.getData(), - ps); - gs.solve(); - gs.check(mmd.getData()); - const SylvParams& pars = gs.getParams(); - pars.print("\t"); - return (*(pars.mat_err1) < eps_norm && *(pars.mat_errI) < eps_norm && - *(pars.mat_errF) < eps_norm && *(pars.vec_err1) < eps_norm && - *(pars.vec_errI) < eps_norm); -} - -bool TestRunnable::eig_bubble(const char* aname, int from, int to) -{ - MMMatrixIn mma(aname); - - if (mma.row() != mma.col()) { - printf(" Matrix is not square\n"); - return false; - } - - int n = mma.row(); - SylvMemoryDriver memdriver(3, n, n, 2); - QuasiTriangular orig(mma.getData(), n); - SchurDecompEig dec((const QuasiTriangular&)orig); - QuasiTriangular::diag_iter itf = dec.getT().diag_begin(); - QuasiTriangular::diag_iter itt = dec.getT().diag_begin(); - for (int i = 0; i < from; i++) - ++itf; - for (int i = 0; i < to; i++) - ++itt; - itt = dec.bubbleEigen(itf, itt); - SqSylvMatrix check(dec.getQ(), dec.getT()); - check.multRightTrans(dec.getQ()); - check.add(-1, orig); - double norm1 = check.getNorm1(); - double normInf = check.getNormInf(); - double onorm1 = orig.getNorm1(); - double onormInf = orig.getNormInf(); - printf("\tabs. error1 = %8.4g\n", norm1); - printf("\tabs. errorI = %8.4g\n", normInf); - printf("\trel. error1 = %8.4g\n", norm1/onorm1); - printf("\trel. errorI = %8.4g\n", normInf/onormInf); - return (norm1 < eps_norm*onorm1 && normInf < eps_norm*onormInf); -} - -bool TestRunnable::block_diag(const char* aname, double log10norm) -{ - MMMatrixIn mma(aname); - - if (mma.row() != mma.col()) { - printf(" Matrix is not square\n"); - return false; - } - - int n = mma.row(); - SylvMemoryDriver memdriver(3, n, n, 2); - SqSylvMatrix orig(mma.getData(), n); - SimilarityDecomp dec(orig.base(), orig.numRows(), log10norm); - dec.getB().printInfo(); - SqSylvMatrix check(dec.getQ(), dec.getB()); - check.multRight(dec.getInvQ()); - check.add(-1, orig); - double norm1 = check.getNorm1(); - double normInf = check.getNormInf(); - double onorm1 = orig.getNorm1(); - double onormInf = orig.getNormInf(); - printf("\terror Q*B*invQ:\n"); - printf("\tabs. error1 = %8.4g\n", norm1); - printf("\tabs. errorI = %8.4g\n", normInf); - printf("\trel. error1 = %8.4g\n", norm1/onorm1); - printf("\trel. errorI = %8.4g\n", normInf/onormInf); - SqSylvMatrix check2(dec.getQ(), dec.getInvQ()); - SqSylvMatrix in(n); - in.setUnit(); - check2.add(-1, in); - double nor1 = check2.getNorm1(); - double norInf = check2.getNormInf(); - printf("\terror Q*invQ:\n"); - printf("\tabs. error1 = %8.4g\n", nor1); - printf("\tabs. errorI = %8.4g\n", norInf); - return (norm1 < eps_norm*pow(10, log10norm)*onorm1); -} - -bool TestRunnable::iter_sylv(const char* m1name, const char* m2name, const char* vname, - int m, int n, int depth) -{ - MMMatrixIn mmt1(m1name); - MMMatrixIn mmt2(m2name); - MMMatrixIn mmv(vname); - - int length = power(m,depth)*n; - if (mmt1.row() != m || - mmt2.row() != n || - mmv.row() != length) { - printf(" Incompatible sizes for triangular sylvester iteration, len=%d, row1=%d, row2=%d, m=%d, n=%d, vrow=%d\n",length,mmt1.row(), mmt2.row(), m, n, mmv.row()); - return false; - } - - SylvMemoryDriver memdriver(4, m, n, depth); // need extra 2 for checks done via KronUtils::multKron - memdriver.setStackMode(true); - QuasiTriangular t1(mmt1.getData(), mmt1.row()); - QuasiTriangular t2(mmt2.getData(), mmt2.row()); - IterativeSylvester is(t2, t1); - Vector vraw(mmv.getData(), length); - ConstKronVector v(vraw, m, n, depth); - KronVector d(v); // copy of v - SylvParams pars; - pars.method = SylvParams::iter; - is.solve(pars, d); - pars.print("\t"); - KronVector dcheck((const KronVector&)d); - KronUtils::multKron(t1, t2, dcheck); - dcheck.add(1.0, d); - dcheck.add(-1.0, v); - double cnorm = dcheck.getNorm(); - double xnorm = v.getNorm(); - printf("\trel. error norm = %8.4g\n",cnorm/xnorm); - double max = dcheck.getMax(); - double xmax = v.getMax(); - printf("\trel. error max = %8.4g\n", max/xmax); - memdriver.setStackMode(false); - return (cnorm < xnorm*eps_norm); -} - -/**********************************************************/ -/* sub classes declarations */ -/**********************************************************/ - -class PureTriangTest : public TestRunnable { -public: - PureTriangTest() : TestRunnable("pure triangular solve (5)") {} - bool run() const; -}; - -class PureTriangTransTest : public TestRunnable { -public: - PureTriangTransTest() : TestRunnable("pure triangular solve trans (5)") {} - bool run() const; -}; - -class PureTrLargeTest : public TestRunnable { -public: - PureTrLargeTest() : TestRunnable("pure triangular large solve (300)") {} - bool run() const; -}; - -class PureTrLargeTransTest : public TestRunnable { -public: - PureTrLargeTransTest() : TestRunnable("pure triangular large solve trans (300)") {} - bool run() const; -}; - -class QuasiTriangTest : public TestRunnable { -public: - QuasiTriangTest() : TestRunnable("quasi triangular solve (7)") {} - bool run() const; -}; - -class QuasiTriangTransTest : public TestRunnable { -public: - QuasiTriangTransTest() : TestRunnable("quasi triangular solve trans (7)") {} - bool run() const; -}; - -class QuasiTrLargeTest : public TestRunnable { -public: - QuasiTrLargeTest() : TestRunnable("quasi triangular solve large (250)") {} - bool run() const; -}; - -class QuasiTrLargeTransTest : public TestRunnable { -public: - QuasiTrLargeTransTest() : TestRunnable("quasi triangular solve large trans (250)") {} - bool run() const; -}; - -class QuasiZeroSmallTest : public TestRunnable { -public: - QuasiZeroSmallTest() : TestRunnable("quasi tr. zero small test (2x1)") {} - bool run() const; -}; - -class MultKronSmallTest : public TestRunnable { -public: - MultKronSmallTest() : TestRunnable("kronecker small mult (2=2x1)") {} - bool run() const; -}; - -class MultKronTest : public TestRunnable { -public: - MultKronTest() : TestRunnable("kronecker mult (245=7x7x5)") {} - bool run() const; -}; - -class MultKronSmallTransTest : public TestRunnable { -public: - MultKronSmallTransTest() : TestRunnable("kronecker small trans mult (2=2x1)") {} - bool run() const; -}; - -class MultKronTransTest : public TestRunnable { -public: - MultKronTransTest() : TestRunnable("kronecker trans mult (245=7x7x5)") {} - bool run() const; -}; - -class LevelKronTest : public TestRunnable { -public: - LevelKronTest() : TestRunnable("kronecker level mult (1715=7x[7]x7x5)") {} - bool run() const; -}; - -class LevelKronTransTest : public TestRunnable { -public: - LevelKronTransTest() : TestRunnable("kronecker level trans mult (1715=7x[7]x7x5)") {} - bool run() const; -}; - -class LevelZeroKronTest : public TestRunnable { -public: - LevelZeroKronTest() : TestRunnable("kronecker level mult (1715=7x7x7x[5])") {} - bool run() const; -}; - -class LevelZeroKronTransTest : public TestRunnable { -public: - LevelZeroKronTransTest() : TestRunnable("kronecker level trans mult (1715=7x7x7x[5])") {} - bool run() const; -}; - -class KronPowerTest : public TestRunnable { -public: - KronPowerTest() : TestRunnable("kronecker power mult (1715=7x7x7x5)") {} - bool run() const; -}; - -class SmallLinEvalTest : public TestRunnable { -public: - SmallLinEvalTest() : TestRunnable("lin eval (24=2 x 2x2x3)") {} - bool run() const; -}; - -class LinEvalTest : public TestRunnable { -public: - LinEvalTest() : TestRunnable("lin eval (490=2 x 7x7x5)") {} - bool run() const; -}; - -class SmallQuaEvalTest : public TestRunnable { -public: - SmallQuaEvalTest() : TestRunnable("qua eval (24=2 x 2x2x3)") {} - bool run() const; -}; - -class QuaEvalTest : public TestRunnable { -public: - QuaEvalTest() : TestRunnable("qua eval (490=2 x 7x7x5)") {} - bool run() const; -}; - -class TriSylvSmallRealTest : public TestRunnable { -public: - TriSylvSmallRealTest() : TestRunnable("triangular sylvester small real solve (12=2x2x3)") {} - bool run() const; -}; - -class TriSylvSmallComplexTest : public TestRunnable { -public: - TriSylvSmallComplexTest() : TestRunnable("triangular sylvester small complx solve (12=2x2x3)") {} - bool run() const; -}; - -class TriSylvTest : public TestRunnable { -public: - TriSylvTest() : TestRunnable("triangular sylvester solve (245=7x7x5)") {} - bool run() const; -}; - -class TriSylvBigTest : public TestRunnable { -public: - TriSylvBigTest() : TestRunnable("triangular sylvester big solve (48000=40x40x30)") {} - bool run() const; -}; - -class TriSylvLargeTest : public TestRunnable { -public: - TriSylvLargeTest() : TestRunnable("triangular sylvester large solve (1920000=40x40x40x30)") {} - bool run() const; -}; - -class IterSylvTest : public TestRunnable { -public: - IterSylvTest() : TestRunnable("iterative sylvester solve (245=7x7x5)") {} - bool run() const; -}; - -class IterSylvLargeTest : public TestRunnable { -public: - IterSylvLargeTest() : TestRunnable("iterative sylvester large solve (1920000=40x40x40x30)") {} - bool run() const; -}; - -class GenSylvSmallTest : public TestRunnable { -public: - GenSylvSmallTest() : TestRunnable("general sylvester small solve (18=3x3x2)") {} - bool run() const; -}; - -class GenSylvTest : public TestRunnable { -public: - GenSylvTest() : TestRunnable("general sylvester solve (12000=20x20x30)") {} - bool run() const; -}; - -class GenSylvSingTest : public TestRunnable { -public: - GenSylvSingTest() : TestRunnable("general sylvester solve for sing. C (2500000=50x50x50x20)") {} - bool run() const; -}; - -class GenSylvLargeTest : public TestRunnable { -public: - GenSylvLargeTest() : TestRunnable("general sylvester solve (2500000=50x50x50x20)") {} - bool run() const; -}; - -class EigBubFrankTest : public TestRunnable { -public: - EigBubFrankTest() : TestRunnable("eig. bubble frank test (12x12)") {} - bool run() const; -}; - -class EigBubSplitTest : public TestRunnable { -// complex eigenvalue is split by swapping it with real -public: - EigBubSplitTest() : TestRunnable("eig. bubble complex split test (3x3)") {} - bool run() const; -}; - -class EigBubSameTest : public TestRunnable { -// complex eigenevalue bypasses the same complex eigenvalue -public: - EigBubSameTest() : TestRunnable("eig. bubble same test (5x5)") {} - bool run() const; -}; - -class BlockDiagSmallTest : public TestRunnable { -public: - BlockDiagSmallTest() : TestRunnable("block diagonalization small test (7x7)") {} - bool run() const; -}; - -class BlockDiagFrankTest : public TestRunnable { -public: - BlockDiagFrankTest() : TestRunnable("block diagonalization of frank (12x12)") {} - bool run() const; -}; - -class BlockDiagIllCondTest : public TestRunnable { -public: - BlockDiagIllCondTest() : TestRunnable("block diagonalization of ill conditioned (15x15)") {} - bool run() const; -}; - -class BlockDiagBigTest : public TestRunnable { -public: - BlockDiagBigTest() : TestRunnable("block diagonalization big test (50x50)") {} - bool run() const; -}; - -/**********************************************************/ -/* run methods of sub classes */ -/**********************************************************/ - -bool PureTriangTest::run() const -{ - return quasi_solve(false, "tr5x5.mm", "v5.mm"); -} - -bool PureTriangTransTest::run() const -{ - return quasi_solve(true, "tr5x5.mm", "v5.mm"); -} - -bool PureTrLargeTest::run() const -{ - return quasi_solve(false, "tr300x300.mm", "v300.mm"); -} - -bool PureTrLargeTransTest::run() const -{ - return quasi_solve(true, "tr300x300.mm", "v300.mm"); -} - -bool QuasiTriangTest::run() const -{ - return quasi_solve(false, "qt7x7.mm", "v7.mm"); -} - -bool QuasiTriangTransTest::run() const -{ - return quasi_solve(true, "qt7x7.mm", "v7.mm"); -} - -bool QuasiTrLargeTest::run() const -{ - return quasi_solve(false, "qt250x250.mm", "v250.mm"); -} - -bool QuasiTrLargeTransTest::run() const -{ - return quasi_solve(true, "qt250x250.mm", "v250.mm"); -} - -bool QuasiZeroSmallTest::run() const -{ - return quasi_solve(false, "b2x1.mm", "v2.mm"); -} - -bool MultKronSmallTest::run() const -{ - return mult_kron(false, "tr2x2.mm", "v2.mm", "vcheck2.mm", 2, 1, 1); -} - -bool MultKronTest::run() const -{ - return mult_kron(false, "qt7x7.mm", "v245.mm", "vcheck245.mm", 7, 5, 2); -} - -bool MultKronSmallTransTest::run() const -{ - return mult_kron(true, "tr2x2.mm", "v2.mm", "vcheck2a.mm", 2, 1, 1); -} - -bool MultKronTransTest::run() const -{ - return mult_kron(true, "qt7x7.mm", "v245.mm", "vcheck245a.mm", 7, 5, 2); -} - -bool LevelKronTest::run() const -{ - return level_kron(false, "qt7x7.mm", "v1715.mm", "vcheck1715.mm", 2, 7, 5, 3); -} - -bool LevelKronTransTest::run() const -{ - return level_kron(true, "qt7x7.mm", "v1715.mm", "vcheck1715a.mm", 2, 7, 5, 3); -} - -bool LevelZeroKronTest::run() const -{ - return level_kron(false, "tr5x5.mm", "v1715.mm", "vcheck1715b.mm", 0, 7, 5, 3); -} - -bool LevelZeroKronTransTest::run() const -{ - return level_kron(true, "tr5x5.mm", "v1715.mm", "vcheck1715c.mm", 0, 7, 5, 3); -} - -bool KronPowerTest::run() const -{ - return kron_power("qt7x7.mm", "tr5x5.mm", "v1715.mm", "vcheck1715d.mm", 7, 5, 3); -} - -bool SmallLinEvalTest::run() const -{ - return lin_eval("qt2x2.mm", "qt3x3.mm", "v24.mm", "vcheck24.mm", 2, 3, 2, - 2, 1, 3); -} - -bool LinEvalTest::run() const -{ - return lin_eval("qt7x7.mm", "tr5x5.mm", "v490.mm", "vcheck490.mm", 7, 5, 2, - 2, 1, 3); -} - -bool SmallQuaEvalTest::run() const -{ - return qua_eval("qt2x2.mm", "qt3x3.mm", "v24.mm", "vcheck24q.mm", 2, 3, 2, - -0.5, 3, 2, 1, 3); -} - -bool QuaEvalTest::run() const -{ - return qua_eval("qt7x7.mm", "tr5x5.mm", "v490.mm", "vcheck490q.mm", 7, 5, 2, - -0.5, 3, 2, 1, 3); -} - -bool TriSylvSmallRealTest::run() const -{ - return tri_sylv("tr2x2.mm", "qt3x3.mm", "v12r.mm", 2, 3, 2); -} - -bool TriSylvSmallComplexTest::run() const -{ - return tri_sylv("qt2x2.mm", "qt3x3.mm", "v12r.mm", 2, 3, 2); -} - -bool TriSylvTest::run() const -{ - return tri_sylv("qt7x7eig06-09.mm", "tr5x5.mm", "v245r.mm", 7, 5, 2); -} - -bool TriSylvBigTest::run() const -{ - return tri_sylv("qt40x40.mm", "qt30x30eig011-095.mm", "v48000.mm", 40, 30, 2); -} - -bool TriSylvLargeTest::run() const -{ - return tri_sylv("qt40x40.mm", "qt30x30eig011-095.mm", "v1920000.mm", 40, 30, 3); -} - -bool IterSylvTest::run() const -{ - return iter_sylv("qt7x7eig06-09.mm", "qt5x5.mm", "v245r.mm", 7, 5, 2); -} - -bool IterSylvLargeTest::run() const -{ - return iter_sylv("qt40x40.mm", "qt30x30eig011-095.mm", "v1920000.mm", 40, 30, 3); -} - -bool GenSylvSmallTest::run() const -{ - return gen_sylv("a2x2.mm", "b2x1.mm", "c3x3.mm", "d2x9.mm", 3, 2, 2); -} - -bool GenSylvTest::run() const -{ - return gen_sylv("a30x30.mm", "b30x25.mm", "c20x20.mm", "d30x400.mm", 20, 30, 2); -} - -bool GenSylvSingTest::run() const -{ - return gen_sylv("a20x20.mm", "b20x4.mm", "c50x50sing.mm", "d20x125000.mm", 50, 20, 3); -} - -bool GenSylvLargeTest::run() const -{ - return gen_sylv("a20x20.mm", "b20x15.mm", "c50x50.mm", "d20x125000.mm", 50, 20, 3); -} - -bool EigBubFrankTest::run() const -{ - return eig_bubble("qt_frank12x12.mm", 8, 0); -} - -bool EigBubSplitTest::run() const -{ - return eig_bubble("qt_eps3x3.mm",1,0); -} - -bool EigBubSameTest::run() const -{ - return eig_bubble("qt5x5.mm",2,0); -} - -bool BlockDiagSmallTest::run() const -{ - return block_diag("qt7x7.mm", 0.1); -} - -bool BlockDiagFrankTest::run() const -{ - return block_diag("qt_frank12x12.mm", 5); -} - -bool BlockDiagIllCondTest::run() const -{ - return block_diag("ill_cond15x15.mm", 4.14); -} - -bool BlockDiagBigTest::run() const -{ - return block_diag("c50x50.mm", 1.3); -} - -/**********************************************************/ -/* main */ -/**********************************************************/ - -int main() -{ - TestRunnable* all_tests[50]; - // fill in vector of all tests - int num_tests = 0; - all_tests[num_tests++] = new PureTriangTest(); - all_tests[num_tests++] = new PureTriangTransTest(); - all_tests[num_tests++] = new PureTrLargeTest(); - all_tests[num_tests++] = new PureTrLargeTransTest(); - all_tests[num_tests++] = new QuasiTriangTest(); - all_tests[num_tests++] = new QuasiTriangTransTest(); - all_tests[num_tests++] = new QuasiTrLargeTest(); - all_tests[num_tests++] = new QuasiTrLargeTransTest(); - all_tests[num_tests++] = new QuasiZeroSmallTest(); - all_tests[num_tests++] = new MultKronSmallTest(); - all_tests[num_tests++] = new MultKronTest(); - all_tests[num_tests++] = new MultKronSmallTransTest(); - all_tests[num_tests++] = new MultKronTransTest(); - all_tests[num_tests++] = new LevelKronTest(); - all_tests[num_tests++] = new LevelKronTransTest(); - all_tests[num_tests++] = new LevelZeroKronTest(); - all_tests[num_tests++] = new LevelZeroKronTransTest(); - all_tests[num_tests++] = new KronPowerTest(); - all_tests[num_tests++] = new SmallLinEvalTest(); - all_tests[num_tests++] = new LinEvalTest(); - all_tests[num_tests++] = new SmallQuaEvalTest(); - all_tests[num_tests++] = new QuaEvalTest(); - all_tests[num_tests++] = new EigBubFrankTest(); - all_tests[num_tests++] = new EigBubSplitTest(); - all_tests[num_tests++] = new EigBubSameTest(); - all_tests[num_tests++] = new BlockDiagSmallTest(); - all_tests[num_tests++] = new BlockDiagFrankTest(); - all_tests[num_tests++] = new BlockDiagIllCondTest(); - all_tests[num_tests++] = new BlockDiagBigTest(); - all_tests[num_tests++] = new TriSylvSmallRealTest(); - all_tests[num_tests++] = new TriSylvSmallComplexTest(); - all_tests[num_tests++] = new TriSylvTest(); - all_tests[num_tests++] = new TriSylvBigTest(); - all_tests[num_tests++] = new TriSylvLargeTest(); - all_tests[num_tests++] = new IterSylvTest(); - all_tests[num_tests++] = new IterSylvLargeTest(); - all_tests[num_tests++] = new GenSylvSmallTest(); - all_tests[num_tests++] = new GenSylvTest(); - all_tests[num_tests++] = new GenSylvSingTest(); - all_tests[num_tests++] = new GenSylvLargeTest(); - - // launch the tests - int success = 0; - for (int i = 0; i < num_tests; i++) { - try { - if (all_tests[i]->test()) - success++; - } catch (const MMException& e) { - printf("Caugth MM exception in <%s>:\n%s", all_tests[i]->getName(), - e.getMessage()); - } catch (SylvException& e) { - printf("Caught Sylv exception in %s:\n", all_tests[i]->getName()); - e.printMessage(); - } - } - - printf("There were %d tests that failed out of %d tests run.\n", - num_tests - success, num_tests); - - // destroy - for (int i = 0; i < num_tests; i++) { - delete all_tests[i]; - } - - return 0; -} - diff --git a/dynare++/tl/cc/pyramid_prod2.hh b/dynare++/tl/cc/pyramid_prod2.hh index 5594cf063227ab01aabc568a612be5d378cf2327..2dce7e1c5ead50f6a882770033c1f4f924f8210a 100644 --- a/dynare++/tl/cc/pyramid_prod2.hh +++ b/dynare++/tl/cc/pyramid_prod2.hh @@ -74,7 +74,7 @@ #include "rfs_tensor.hh" #include "stack_container.hh" -#include "Vector.h" +#include "Vector.hh" /* First we declare a helper class for the tensor. Its purpose is to gather the columns which are going to be Kronecker multiplied. The diff --git a/dynare++/tl/cc/sparse_tensor.hh b/dynare++/tl/cc/sparse_tensor.hh index 1b61d7ef856283ab6db2e198d8c7e8ec72762092..deceaace354c26b77ca400e080efc7baa9a172a9 100644 --- a/dynare++/tl/cc/sparse_tensor.hh +++ b/dynare++/tl/cc/sparse_tensor.hh @@ -27,7 +27,7 @@ #include "symmetry.hh" #include "tensor.hh" #include "gs_tensor.hh" -#include "Vector.h" +#include "Vector.hh" #include <map> diff --git a/dynare++/tl/cc/t_container.hh b/dynare++/tl/cc/t_container.hh index 07c6e7b98a92cb74ddca36fbd3b784d5b324655c..96aa76194a1d69f9bcacad1d164c4eadc4da93ed 100644 --- a/dynare++/tl/cc/t_container.hh +++ b/dynare++/tl/cc/t_container.hh @@ -54,7 +54,7 @@ #include "sparse_tensor.hh" #include "equivalence.hh" #include "rfs_tensor.hh" -#include "Vector.h" +#include "Vector.hh" #include <map> #include <string> diff --git a/dynare++/tl/cc/twod_matrix.hh b/dynare++/tl/cc/twod_matrix.hh index 90d9591d77f6a6fcfb99ebd6cec97fcc63ee5b5c..03b5b659b2751bf33c13d25c0c6490afd27b9e77 100644 --- a/dynare++/tl/cc/twod_matrix.hh +++ b/dynare++/tl/cc/twod_matrix.hh @@ -15,7 +15,7 @@ #ifndef TWOD_MATRIX_H #define TWOD_MATRIX_H -#include "GeneralMatrix.h" +#include "GeneralMatrix.hh" #include <cstdio> #include <matio.h> diff --git a/dynare++/tl/testing/monoms.hh b/dynare++/tl/testing/monoms.hh index 86707e3bd47d261a4c081ad5d97afdc0acc10711..684c9d4f6e54f0d38a9d51a44148f85c91ee460e 100644 --- a/dynare++/tl/testing/monoms.hh +++ b/dynare++/tl/testing/monoms.hh @@ -8,7 +8,7 @@ #include "gs_tensor.hh" #include "t_container.hh" #include "sparse_tensor.hh" -#include "Vector.h" +#include "Vector.hh" class IntGenerator { diff --git a/dynare++/tl/testing/tests.cc b/dynare++/tl/testing/tests.cc index d989481cb135681833bbe747a0ea1975132ce8ca..9f751ecef84da807c0cbb9f3f62477bc30adee3a 100644 --- a/dynare++/tl/testing/tests.cc +++ b/dynare++/tl/testing/tests.cc @@ -1,7 +1,7 @@ /* $Id: tests.cpp 148 2005-04-19 15:12:26Z kamenik $ */ /* Copyright 2004, Ondra Kamenik */ -#include "SylvException.h" +#include "SylvException.hh" #include "tl_exception.hh" #include "gs_tensor.hh" #include "factory.hh" diff --git a/dynare++/utils/cc/Makefile.am b/dynare++/utils/cc/Makefile.am index 91c1a091db60599e713514eaee70e2eb2e97af87..220db615c8b8cb5aeaec624f3853f256460b0d6c 100644 --- a/dynare++/utils/cc/Makefile.am +++ b/dynare++/utils/cc/Makefile.am @@ -1,8 +1,8 @@ noinst_LIBRARIES = libutils.a libutils_a_SOURCES = \ - exception.h \ - memory_file.cpp \ - memory_file.h \ - pascal_triangle.cpp \ - pascal_triangle.h + exception.hh \ + memory_file.cc \ + memory_file.hh \ + pascal_triangle.cc \ + pascal_triangle.hh diff --git a/dynare++/utils/cc/exception.h b/dynare++/utils/cc/exception.hh similarity index 100% rename from dynare++/utils/cc/exception.h rename to dynare++/utils/cc/exception.hh diff --git a/dynare++/utils/cc/memory_file.cc b/dynare++/utils/cc/memory_file.cc new file mode 100644 index 0000000000000000000000000000000000000000..9c8967ffe71953b685cde0a76967ee27f00f3112 --- /dev/null +++ b/dynare++/utils/cc/memory_file.cc @@ -0,0 +1,71 @@ +// Copyright (C) 2005, Ondra Kamenik + +// $Id: memory_file.cpp 987 2006-10-17 14:39:19Z kamenik $ + +#include "memory_file.hh" + +#include <cstdio> + +using namespace ogu; + +int +ogu::calc_pos_offset(int length, const char *str, int line, int col) +{ + int i = 0; + int il = 1; + int ic = 1; + while (i < length && il <= line && ic <= col) + { + if (str[i] == '\n') + { + il++; + ic = 1; + } + else + { + ic++; + } + } + return i; +} + +void +ogu::calc_pos_line_and_col(int length, const char *str, int offset, + int &line, int &col) +{ + line = 1; + col = 0; + int i = 0; + while (i < length && i < offset) + { + if (str[i] == '\n') + { + line++; + col = 0; + } + i++; + col++; + } +} + +MemoryFile::MemoryFile(const char *fname) + : len(-1), data(NULL) +{ + FILE *fd = fopen(fname, "rb"); + if (fd) + { + // get the file size + fseek(fd, 0, SEEK_END); + len = ftell(fd); + // allocate space for the file plus ending '\0' character + data = new char[len+1]; + // read file and set data + fseek(fd, 0, SEEK_SET); + int i = 0; + int c; + while (EOF != (c = fgetc(fd))) + data[i++] = (unsigned char) c; + data[len] = '\0'; + fclose(fd); + } +} diff --git a/dynare++/utils/cc/memory_file.cpp b/dynare++/utils/cc/memory_file.cpp deleted file mode 100644 index 5e147af56fda05dc8ff8dd9f33bdc8b59db7da41..0000000000000000000000000000000000000000 --- a/dynare++/utils/cc/memory_file.cpp +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright (C) 2005, Ondra Kamenik - -// $Id: memory_file.cpp 987 2006-10-17 14:39:19Z kamenik $ - -#include "memory_file.h" - -#include <cstdio> - -using namespace ogu; - -int ogu::calc_pos_offset(int length, const char* str, int line, int col) -{ - int i = 0; - int il = 1; - int ic = 1; - while (i < length && il <= line && ic <= col) { - if (str[i] == '\n') { - il++; - ic = 1; - } else { - ic++; - } - } - return i; -} - -void ogu::calc_pos_line_and_col(int length, const char* str, int offset, - int& line, int& col) -{ - line = 1; - col = 0; - int i = 0; - while (i < length && i < offset) { - if (str[i] == '\n') { - line++; - col = 0; - } - i++; - col++; - } -} - -MemoryFile::MemoryFile(const char* fname) - : len(-1), data(NULL) -{ - FILE* fd = fopen(fname, "rb"); - if (fd) { - // get the file size - fseek(fd, 0, SEEK_END); - len = ftell(fd); - // allocate space for the file plus ending '\0' character - data = new char[len+1]; - // read file and set data - fseek(fd, 0, SEEK_SET); - int i = 0; - int c; - while (EOF != (c = fgetc(fd))) - data[i++] = (unsigned char)c; - data[len] = '\0'; - fclose(fd); - } -} diff --git a/dynare++/utils/cc/memory_file.h b/dynare++/utils/cc/memory_file.hh similarity index 100% rename from dynare++/utils/cc/memory_file.h rename to dynare++/utils/cc/memory_file.hh diff --git a/dynare++/utils/cc/pascal_triangle.cc b/dynare++/utils/cc/pascal_triangle.cc new file mode 100644 index 0000000000000000000000000000000000000000..c64db047da9ed700ced276e30c67fea310f722ce --- /dev/null +++ b/dynare++/utils/cc/pascal_triangle.cc @@ -0,0 +1,101 @@ +#include "pascal_triangle.hh" +#include <cstdio> + +using namespace ogu; + +PascalTriangle ptriang; + +void +PascalRow::setFromPrevious(const PascalRow &prev) +{ + k = prev.k + 1; + clear(); + prolong(prev); +} + +/** This prolongs the PascalRow. If it is empty, we set the first item + * to k+1, which is noverk(k+1,k) which is the second item in the real + * pascal row, which starts from noverk(k,k)=1. Then we calculate + * other items from the provided row which must be the one with k-1.*/ +void +PascalRow::prolong(const PascalRow &prev) +{ + if (size() == 0) + push_back(k+1); + int last = back(); + for (unsigned int i = size(); i < prev.size(); i++) + { + last += prev[i]; + push_back(last); + } +} + +void +PascalRow::prolongFirst(int n) +{ + // todo: check n = 1; + for (int i = (int) size()+2; i <= n; i++) + push_back(i); +} + +void +PascalRow::print() const +{ + printf("k=%d\n", k); + for (unsigned int i = 0; i < size(); i++) + printf("%d ", operator[](i)); + printf("\n"); +} + +int +PascalTriangle::max_n() const +{ + return (int) (tr[0].size()+1); +} + +int +PascalTriangle::max_k() const +{ + return (int) tr.size(); +} + +void +PascalTriangle::ensure(int n, int k) +{ + // add along n + if (n > max_n()) + { + tr[0].prolongFirst(n); + for (int i = 2; i <= max_k(); i++) + tr[i-1].prolong(tr[i-2]); + } + + if (k > max_k()) + { + for (int i = max_k()+1; i <= k; i++) + { + PascalRow r; + tr.push_back(r); + tr.back().setFromPrevious(tr[i-2]); + } + } +} + +int +PascalTriangle::noverk(int n, int k) +{ + // todo: rais if out of bounds + if (n-k < k) + k = n-k; + if (k == 0) + return 1; + ensure(n, k); + return (tr[k-1])[n-1-k]; +} + +void +PascalTriangle::print() const +{ + for (unsigned int i = 0; i < tr.size(); i++) + tr[i].print(); +} diff --git a/dynare++/utils/cc/pascal_triangle.cpp b/dynare++/utils/cc/pascal_triangle.cpp deleted file mode 100644 index 1dc4c09d65fa98f1d699e789129360e76f6b8b01..0000000000000000000000000000000000000000 --- a/dynare++/utils/cc/pascal_triangle.cpp +++ /dev/null @@ -1,88 +0,0 @@ -#include "pascal_triangle.h" -#include <cstdio> - -using namespace ogu; - -PascalTriangle ptriang; - -void PascalRow::setFromPrevious(const PascalRow& prev) -{ - k = prev.k + 1; - clear(); - prolong(prev); -} - -/** This prolongs the PascalRow. If it is empty, we set the first item - * to k+1, which is noverk(k+1,k) which is the second item in the real - * pascal row, which starts from noverk(k,k)=1. Then we calculate - * other items from the provided row which must be the one with k-1.*/ -void PascalRow::prolong(const PascalRow& prev) -{ - if (size() == 0) - push_back(k+1); - int last = back(); - for (unsigned int i = size(); i < prev.size(); i++) { - last += prev[i]; - push_back(last); - } -} - -void PascalRow::prolongFirst(int n) -{ - // todo: check n = 1; - for (int i = (int)size()+2; i <= n; i++) - push_back(i); -} - -void PascalRow::print() const -{ - printf("k=%d\n",k); - for (unsigned int i = 0; i < size(); i++) - printf("%d ",operator[](i)); - printf("\n"); -} - -int PascalTriangle::max_n() const -{ - return (int)(tr[0].size()+1); -} - -int PascalTriangle::max_k() const -{ - return (int)tr.size(); -} - -void PascalTriangle::ensure(int n, int k) -{ - // add along n - if (n > max_n()) { - tr[0].prolongFirst(n); - for (int i = 2; i <= max_k(); i++) - tr[i-1].prolong(tr[i-2]); - } - - if (k > max_k()) { - for (int i = max_k()+1; i <= k; i++) { - PascalRow r; - tr.push_back(r); - tr.back().setFromPrevious(tr[i-2]); - } - } -} - -int PascalTriangle::noverk(int n, int k) -{ - // todo: rais if out of bounds - if (n-k < k) - k = n-k; - if (k == 0) - return 1; - ensure(n, k); - return (tr[k-1])[n-1-k]; -} - -void PascalTriangle::print() const -{ - for (unsigned int i = 0; i < tr.size(); i++) - tr[i].print(); -} diff --git a/dynare++/utils/cc/pascal_triangle.h b/dynare++/utils/cc/pascal_triangle.hh similarity index 100% rename from dynare++/utils/cc/pascal_triangle.h rename to dynare++/utils/cc/pascal_triangle.hh diff --git a/mex/build/dynare_simul_.am b/mex/build/dynare_simul_.am index 3d64b6bc4e5679d5a0d123fdbf3bbcb572f1b4d8..05716b9a26fb10cc80565668beecdbc92740fb36 100644 --- a/mex/build/dynare_simul_.am +++ b/mex/build/dynare_simul_.am @@ -8,4 +8,4 @@ dynare_simul__CXXFLAGS = $(AM_CXXFLAGS) $(PTHREAD_CFLAGS) dynare_simul__LDFLAGS = $(AM_LDFLAGS) $(LDFLAGS_MATIO) dynare_simul__LDADD = ../libdynare++/libdynare++.a $(PTHREAD_LIBS) $(LIBADD_MATIO) -nodist_dynare_simul__SOURCES = $(top_srcdir)/../../../dynare++/extern/matlab/dynare_simul.cpp +nodist_dynare_simul__SOURCES = $(top_srcdir)/../../../dynare++/extern/matlab/dynare_simul.cc diff --git a/mex/build/gensylv.am b/mex/build/gensylv.am index 0c20ea7e5ae3dd44414b3d0b4f8fa2be7c7f05d9..ee45a519b3cac51716448bd6a16d12c0a3eeb444 100644 --- a/mex/build/gensylv.am +++ b/mex/build/gensylv.am @@ -4,4 +4,4 @@ gensylv_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/../../../dynare++/sylv/cc -I$( gensylv_LDADD = ../libdynare++/libdynare++.a -nodist_gensylv_SOURCES = $(top_srcdir)/../../../dynare++/sylv/matlab/gensylv.cpp +nodist_gensylv_SOURCES = $(top_srcdir)/../../../dynare++/sylv/matlab/gensylv.cc diff --git a/mex/build/libdynare++.am b/mex/build/libdynare++.am index 0ee183beb1f88df85546bb29af1f5e4dc4f7369f..8c9f87fc5c1c1a5057d139481f56239eb48b66af 100644 --- a/mex/build/libdynare++.am +++ b/mex/build/libdynare++.am @@ -33,24 +33,43 @@ KORD_SRCS = \ $(TOPDIR)/kord/random.hh SYLV_SRCS = \ - $(TOPDIR)/sylv/cc/IterativeSylvester.cpp \ - $(TOPDIR)/sylv/cc/QuasiTriangular.cpp \ - $(TOPDIR)/sylv/cc/QuasiTriangularZero.cpp \ - $(TOPDIR)/sylv/cc/GeneralMatrix.cpp \ - $(TOPDIR)/sylv/cc/GeneralSylvester.cpp \ - $(TOPDIR)/sylv/cc/SimilarityDecomp.cpp \ - $(TOPDIR)/sylv/cc/SylvException.cpp \ - $(TOPDIR)/sylv/cc/SchurDecompEig.cpp \ - $(TOPDIR)/sylv/cc/Vector.cpp \ - $(TOPDIR)/sylv/cc/TriangularSylvester.cpp \ - $(TOPDIR)/sylv/cc/SylvParams.cpp \ - $(TOPDIR)/sylv/cc/BlockDiagonal.cpp \ - $(TOPDIR)/sylv/cc/KronVector.cpp \ - $(TOPDIR)/sylv/cc/SylvMemory.cpp \ - $(TOPDIR)/sylv/cc/SymSchurDecomp.cpp \ - $(TOPDIR)/sylv/cc/SylvMatrix.cpp \ - $(TOPDIR)/sylv/cc/SchurDecomp.cpp \ - $(TOPDIR)/sylv/cc/KronUtils.cpp + $(TOPDIR)/sylv/cc/BlockDiagonal.cc \ + $(TOPDIR)/sylv/cc/BlockDiagonal.hh \ + $(TOPDIR)/sylv/cc/GeneralMatrix.cc \ + $(TOPDIR)/sylv/cc/GeneralMatrix.hh \ + $(TOPDIR)/sylv/cc/GeneralSylvester.cc \ + $(TOPDIR)/sylv/cc/GeneralSylvester.hh \ + $(TOPDIR)/sylv/cc/IterativeSylvester.cc \ + $(TOPDIR)/sylv/cc/IterativeSylvester.hh \ + $(TOPDIR)/sylv/cc/KronUtils.cc \ + $(TOPDIR)/sylv/cc/KronUtils.hh \ + $(TOPDIR)/sylv/cc/KronVector.cc \ + $(TOPDIR)/sylv/cc/KronVector.hh \ + $(TOPDIR)/sylv/cc/QuasiTriangular.cc \ + $(TOPDIR)/sylv/cc/QuasiTriangular.hh \ + $(TOPDIR)/sylv/cc/QuasiTriangularZero.cc \ + $(TOPDIR)/sylv/cc/QuasiTriangularZero.hh \ + $(TOPDIR)/sylv/cc/SchurDecomp.cc \ + $(TOPDIR)/sylv/cc/SchurDecomp.hh \ + $(TOPDIR)/sylv/cc/SchurDecompEig.cc \ + $(TOPDIR)/sylv/cc/SchurDecompEig.hh \ + $(TOPDIR)/sylv/cc/SimilarityDecomp.cc \ + $(TOPDIR)/sylv/cc/SimilarityDecomp.hh \ + $(TOPDIR)/sylv/cc/SylvException.cc \ + $(TOPDIR)/sylv/cc/SylvException.hh \ + $(TOPDIR)/sylv/cc/SylvMatrix.cc \ + $(TOPDIR)/sylv/cc/SylvMatrix.hh \ + $(TOPDIR)/sylv/cc/SylvMemory.cc \ + $(TOPDIR)/sylv/cc/SylvMemory.hh \ + $(TOPDIR)/sylv/cc/SylvParams.cc \ + $(TOPDIR)/sylv/cc/SylvParams.hh \ + $(TOPDIR)/sylv/cc/SylvesterSolver.hh \ + $(TOPDIR)/sylv/cc/SymSchurDecomp.cc \ + $(TOPDIR)/sylv/cc/SymSchurDecomp.hh \ + $(TOPDIR)/sylv/cc/TriangularSylvester.cc \ + $(TOPDIR)/sylv/cc/TriangularSylvester.hh \ + $(TOPDIR)/sylv/cc/Vector.cc \ + $(TOPDIR)/sylv/cc/Vector.hh TL_SRCS = \ $(TOPDIR)/tl/cc/equivalence.cc \ @@ -114,4 +133,5 @@ nodist_libdynare___a_SOURCES = \ $(TL_SRCS) \ $(SYLV_SRCS) \ $(INTEG_SRCS) \ - $(TOPDIR)/src/nlsolve.cpp + $(TOPDIR)/src/nlsolve.cc \ + $(TOPDIR)/src/nlsolve.hh diff --git a/mex/sources/k_order_perturbation/dynamic_dll.hh b/mex/sources/k_order_perturbation/dynamic_dll.hh index aef34c8872a2a99f25d9fa91092955833565b495..f79aae54cd8305b68725106b38431310817cf69c 100644 --- a/mex/sources/k_order_perturbation/dynamic_dll.hh +++ b/mex/sources/k_order_perturbation/dynamic_dll.hh @@ -32,7 +32,7 @@ #include <string> #include "dynamic_abstract_class.hh" -#include "dynare_exception.h" +#include "dynare_exception.hh" using dynamic_tt_fct = void (*)(const double *y, const double *x, int nb_row_x, const double *params, const double *steady_state, int it_, double *T); using dynamic_resid_fct = void (*) (const double *y, const double *x, int nb_row_x, const double *params, const double *steady_state, int it_, const double *T, double *residual); diff --git a/mex/sources/k_order_perturbation/k_ord_dynare.cc b/mex/sources/k_order_perturbation/k_ord_dynare.cc index ab81818e7a2c166dd58e5b994dde7892b4ed2bfe..fa45e8bbfa3b465d4a7f3b5cf850ea5d8348297b 100644 --- a/mex/sources/k_order_perturbation/k_ord_dynare.cc +++ b/mex/sources/k_order_perturbation/k_ord_dynare.cc @@ -26,7 +26,7 @@ #include <cmath> #include <sstream> -#include "memory_file.h" +#include "memory_file.hh" #include <iostream> #include <fstream> diff --git a/mex/sources/k_order_perturbation/k_ord_dynare.hh b/mex/sources/k_order_perturbation/k_ord_dynare.hh index 45c94582288504fd4729f42c89520bc4a1601e04..93b1d90b78a6b56ff74d21fe3e37096298aa3ce9 100644 --- a/mex/sources/k_order_perturbation/k_ord_dynare.hh +++ b/mex/sources/k_order_perturbation/k_ord_dynare.hh @@ -26,13 +26,13 @@ #include "decision_rule.hh" #include "dynamic_model.hh" -#include "exception.h" -#include "dynare_exception.h" +#include "exception.hh" +#include "dynare_exception.hh" #include "fs_tensor.hh" -#include "SylvException.h" +#include "SylvException.hh" #include "tl_exception.hh" #include "kord_exception.hh" -#include "nlsolve.h" +#include "nlsolve.hh" #include "approximation.hh" class KordpDynare;