K-Order Perturbation: Adding the Core subset of Dynare++ deemed needed for k-ord perturb. and the bare bones of the new interface (not compilable yet)

git-svn-id: https://www.dynare.org/svn/dynare/dynare_v4@2136 ac1d8469-bf42-47a9-8791-bf33cf982152
time-shift
george 2008-10-06 10:25:09 +00:00
parent f51ba0bd93
commit f70374eb19
149 changed files with 30247 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,178 @@
/*
* Module: sched.h
*
* Purpose:
* Provides an implementation of POSIX realtime extensions
* as defined in
*
* POSIX 1003.1b-1993 (POSIX.1b)
*
* --------------------------------------------------------------------------
*
* Pthreads-win32 - POSIX Threads Library for Win32
* Copyright(C) 1998 John E. Bossom
* Copyright(C) 1999,2005 Pthreads-win32 contributors
*
* Contact Email: rpj@callisto.canberra.edu.au
*
* The current list of contributors is contained
* in the file CONTRIBUTORS included with the source
* code distribution. The list can also be seen at the
* following World Wide Web location:
* http://sources.redhat.com/pthreads-win32/contributors.html
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library in the file COPYING.LIB;
* if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifndef _SCHED_H
#define _SCHED_H
#undef PTW32_LEVEL
#if defined(_POSIX_SOURCE)
#define PTW32_LEVEL 0
/* Early POSIX */
#endif
#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309
#undef PTW32_LEVEL
#define PTW32_LEVEL 1
/* Include 1b, 1c and 1d */
#endif
#if defined(INCLUDE_NP)
#undef PTW32_LEVEL
#define PTW32_LEVEL 2
/* Include Non-Portable extensions */
#endif
#define PTW32_LEVEL_MAX 3
#if !defined(PTW32_LEVEL)
#define PTW32_LEVEL PTW32_LEVEL_MAX
/* Include everything */
#endif
#if __GNUC__ && ! defined (__declspec)
# error Please upgrade your GNU compiler to one that supports __declspec.
#endif
/*
* When building the DLL code, you should define PTW32_BUILD so that
* the variables/functions are exported correctly. When using the DLL,
* do NOT define PTW32_BUILD, and then the variables/functions will
* be imported correctly.
*/
#ifndef PTW32_STATIC_LIB
# ifdef PTW32_BUILD
# define PTW32_DLLPORT __declspec (dllexport)
# else
# define PTW32_DLLPORT __declspec (dllimport)
# endif
#else
# define PTW32_DLLPORT
#endif
/*
* This is a duplicate of what is in the autoconf config.h,
* which is only used when building the pthread-win32 libraries.
*/
#ifndef PTW32_CONFIG_H
# if defined(WINCE)
# define NEED_ERRNO
# define NEED_SEM
# endif
# if defined(_UWIN) || defined(__MINGW32__)
# define HAVE_MODE_T
# endif
#endif
/*
*
*/
#if PTW32_LEVEL >= PTW32_LEVEL_MAX
#ifdef NEED_ERRNO
#include "need_errno.h"
#else
#include <errno.h>
#endif
#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */
#if defined(__MINGW32__) || defined(_UWIN)
#if PTW32_LEVEL >= PTW32_LEVEL_MAX
/* For pid_t */
# include <sys/types.h>
/* Required by Unix 98 */
# include <time.h>
#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */
#else
typedef int pid_t;
#endif
/* Thread scheduling policies */
enum {
SCHED_OTHER = 0,
SCHED_FIFO,
SCHED_RR,
SCHED_MIN = SCHED_OTHER,
SCHED_MAX = SCHED_RR
};
struct sched_param {
int sched_priority;
};
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
PTW32_DLLPORT int __cdecl sched_yield (void);
PTW32_DLLPORT int __cdecl sched_get_priority_min (int policy);
PTW32_DLLPORT int __cdecl sched_get_priority_max (int policy);
PTW32_DLLPORT int __cdecl sched_setscheduler (pid_t pid, int policy);
PTW32_DLLPORT int __cdecl sched_getscheduler (pid_t pid);
/*
* Note that this macro returns ENOTSUP rather than
* ENOSYS as might be expected. However, returning ENOSYS
* should mean that sched_get_priority_{min,max} are
* not implemented as well as sched_rr_get_interval.
* This is not the case, since we just don't support
* round-robin scheduling. Therefore I have chosen to
* return the same value as sched_setscheduler when
* SCHED_RR is passed to it.
*/
#define sched_rr_get_interval(_pid, _interval) \
( errno = ENOTSUP, (int) -1 )
#ifdef __cplusplus
} /* End of extern "C" */
#endif /* __cplusplus */
#undef PTW32_LEVEL
#undef PTW32_LEVEL_MAX
#endif /* !_SCHED_H */

View File

@ -0,0 +1,166 @@
/*
* Module: semaphore.h
*
* Purpose:
* Semaphores aren't actually part of the PThreads standard.
* They are defined by the POSIX Standard:
*
* POSIX 1003.1b-1993 (POSIX.1b)
*
* --------------------------------------------------------------------------
*
* Pthreads-win32 - POSIX Threads Library for Win32
* Copyright(C) 1998 John E. Bossom
* Copyright(C) 1999,2005 Pthreads-win32 contributors
*
* Contact Email: rpj@callisto.canberra.edu.au
*
* The current list of contributors is contained
* in the file CONTRIBUTORS included with the source
* code distribution. The list can also be seen at the
* following World Wide Web location:
* http://sources.redhat.com/pthreads-win32/contributors.html
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library in the file COPYING.LIB;
* if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined( SEMAPHORE_H )
#define SEMAPHORE_H
#undef PTW32_LEVEL
#if defined(_POSIX_SOURCE)
#define PTW32_LEVEL 0
/* Early POSIX */
#endif
#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309
#undef PTW32_LEVEL
#define PTW32_LEVEL 1
/* Include 1b, 1c and 1d */
#endif
#if defined(INCLUDE_NP)
#undef PTW32_LEVEL
#define PTW32_LEVEL 2
/* Include Non-Portable extensions */
#endif
#define PTW32_LEVEL_MAX 3
#if !defined(PTW32_LEVEL)
#define PTW32_LEVEL PTW32_LEVEL_MAX
/* Include everything */
#endif
#if __GNUC__ && ! defined (__declspec)
# error Please upgrade your GNU compiler to one that supports __declspec.
#endif
/*
* When building the DLL code, you should define PTW32_BUILD so that
* the variables/functions are exported correctly. When using the DLL,
* do NOT define PTW32_BUILD, and then the variables/functions will
* be imported correctly.
*/
#ifndef PTW32_STATIC_LIB
# ifdef PTW32_BUILD
# define PTW32_DLLPORT __declspec (dllexport)
# else
# define PTW32_DLLPORT __declspec (dllimport)
# endif
#else
# define PTW32_DLLPORT
#endif
/*
* This is a duplicate of what is in the autoconf config.h,
* which is only used when building the pthread-win32 libraries.
*/
#ifndef PTW32_CONFIG_H
# if defined(WINCE)
# define NEED_ERRNO
# define NEED_SEM
# endif
# if defined(_UWIN) || defined(__MINGW32__)
# define HAVE_MODE_T
# endif
#endif
/*
*
*/
#if PTW32_LEVEL >= PTW32_LEVEL_MAX
#ifdef NEED_ERRNO
#include "need_errno.h"
#else
#include <errno.h>
#endif
#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */
#define _POSIX_SEMAPHORES
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
#ifndef HAVE_MODE_T
typedef unsigned int mode_t;
#endif
typedef struct sem_t_ * sem_t;
PTW32_DLLPORT int __cdecl sem_init (sem_t * sem,
int pshared,
unsigned int value);
PTW32_DLLPORT int __cdecl sem_destroy (sem_t * sem);
PTW32_DLLPORT int __cdecl sem_trywait (sem_t * sem);
PTW32_DLLPORT int __cdecl sem_wait (sem_t * sem);
PTW32_DLLPORT int __cdecl sem_timedwait (sem_t * sem,
const struct timespec * abstime);
PTW32_DLLPORT int __cdecl sem_post (sem_t * sem);
PTW32_DLLPORT int __cdecl sem_post_multiple (sem_t * sem,
int count);
PTW32_DLLPORT int __cdecl sem_open (const char * name,
int oflag,
mode_t mode,
unsigned int value);
PTW32_DLLPORT int __cdecl sem_close (sem_t * sem);
PTW32_DLLPORT int __cdecl sem_unlink (const char * name);
PTW32_DLLPORT int __cdecl sem_getvalue (sem_t * sem,
int * sval);
#ifdef __cplusplus
} /* End of extern "C" */
#endif /* __cplusplus */
#undef PTW32_LEVEL
#undef PTW32_LEVEL_MAX
#endif /* !SEMAPHORE_H */

View File

@ -0,0 +1,129 @@
CC = gcc
CC_FLAGS = -Wall -I../../sylv/cc -I../../tl/cc -I../../kord -I../../integ/cc \
$(CC_INCLUDE_PATH)
LDFLAGS = -llapack -lcblas -lf77blas -latlas -lg2c -lstdc++
ifeq ($(DEBUG),yes)
CC_FLAGS := $(CC_FLAGS) -g -DTL_DEBUG=2
else
CC_FLAGS := $(CC_FLAGS) -O3 -DPOSIX_THREADS
endif
ifeq ($(OS),Windows_NT)
CC_FLAGS := -mno-cygwin -mthreads $(CC_FLAGS)
LDFLAGS := -mno-cygwin -mthreads $(LDFLAGS) -lpthreadGC2
ARCH := w32
MEX_SUFFIX = dll
else
LDFLAGS := $(LDFLAGS) -lpthread
ARCH := linux
MEX_SUFFIX = mexglx
endif
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))
cppsource := $(wildcard *.cpp)
mexobjects := $(patsubst %.cpp,%_.$(MEX_SUFFIX),$(cppsource))
all: $(mexobjects)
../../tl/cc/dummy.ch:
make -C ../../tl/cc dummy.ch
../../tl/cc/%.cpp: ../../tl/cc/%.cweb ../../tl/cc/dummy.ch
make -C ../../tl/cc $*.cpp
../../tl/cc/%.h: ../../tl/cc/%.hweb ../../tl/cc/dummy.ch
make -C ../../tl/cc $*.h
../../tl/cc/%.o: ../../tl/cc/%.cpp $(tlhsource)
make -C ../../tl/cc $*.o
../../integ/cc/dummy.ch:
make -C ../../integ/cc dummy.ch
../../integ/cc/%.cpp: ../../integ/cc/%.cweb ../../integ/cc/dummy.ch
make -C ../../integ/cc $*.cpp
../../integ/cc/%.h: ../../integ/cc/%.hweb ../../integ/cc/dummy.ch
make -C ../../integ/cc $*.h
../../integ/cc/%.o: ../../integ/cc/%.cpp $(integhsource) $(tlhsource)
make -C ../../integ/cc $*.o
../../sylv/cc/%.o: ../../sylv/cc/%.cpp $(sylvhsource)
make -C ../../sylv/cc $*.o
../../kord/dummy.ch:
make -C ../../kord dummy.ch
../../kord/%.cpp: ../../kord/%.cweb ../../kord/dummy.ch
make -C ../../kord $*.cpp
../../kord/%.h: ../../kord/%.hweb ../../kord/dummy.ch
make -C ../../kord $*.h
../../kord/%.o: ../../kord/%.cpp $(tlhsource) $(kordhsource) $(integhsource)
make -C ../../kord $*.o
dynarelib.a: $(tlhwebsource) $(tlcwebsoure) $(tlhsource) $(tlcppsource) \
$(integhwebsource) $(integcwebsoure) $(integhsource) $(integcppsource) \
$(kordhwebsource) $(kordcwebsoure) $(kordhsource) $(kordcppsource) \
$(sylvhsource) $(sylvcppsource) \
$(kordobjects) $(tlobjects) $(integobjects) $(sylvobjects)
ar cr dynarelib.a $(kordobjects) $(tlobjects) $(integobjects) $(sylvobjects)
ranlib dynarelib.a
# to compile mex objects for Windows do:
# 1. install gnumex
# 2. create mexopts.bat via gnumex in this directory, specify MinGW compilation, and dll output
# 3. change -Ic:/MATLAB71/extern/include according your Matlab setup
# 4. pray it works
# OR: just use the mexopt.bat from the repository and check MATLAB root directory
%_.$(MEX_SUFFIX): %.cpp $(tlhwebsource) $(tlcwebsoure) $(tlhsource) $(tlcppsource) \
$(integhwebsource) $(integcwebsoure) $(integhsource) $(integcppsource) \
$(kordhwebsource) $(kordcwebsoure) $(kordhsource) $(kordcppsource) \
$(sylvhsource) $(sylvcppsource) \
dynarelib.a
ifeq ($(OS),Windows_NT)
mex.bat -I../../sylv/cc -I../../tl/cc -I../../kord -I../../integ/cc COMPFLAGS\#"-c -DMATLAB_MEX_FILE -DPOSIX_THREADS" OPTIMFLAGS\#"-O3 -fexceptions -Ic:/MATLAB71/extern/include" GM_ADD_LIBS\#"$(LDFLAGS)" $*.cpp dynarelib.a
else
mex -I../../sylv/cc/ -I../../tl/cc -I../../kord -I../../integ/cc $*.cpp CFLAGS='$$CFLAGS -fexceptions' dynarelib.a
endif
mv $*.$(MEX_SUFFIX) $*_.$(MEX_SUFFIX)
clear:
rm -f dynarelib.a
rm -f *.mexglx
rm -f *.dll
make -C ../../tl/testing clear
make -C ../../tl/cc clear
make -C ../../integ/testing clear
make -C ../../integ/cc clear
make -C ../../sylv/testing clear
make -C ../../sylv/cc clear
make -C ../../kord clear

View File

@ -0,0 +1,133 @@
// $Id: dynare_simul.cpp 1488 2007-12-19 14:16:30Z kamenik $
// Copyright 2005, 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 "mex.h"
#include "decision_rule.h"
#include "fs_tensor.h"
#include "SylvException.h"
extern "C" {
void mexFunction(int nhls, mxArray* plhs[],
int nhrs, const mxArray* prhs[])
{
if (nhrs < 12)
mexErrMsgTxt("Must have at least 12 input parameters.\n");
if (nhls != 1)
mexErrMsgTxt("Must have exactly 1 output parameter.\n");
int order = (int)mxGetScalar(prhs[0]);
if (nhrs != 12 + order) {
mexErrMsgTxt("Must have exactly 11+order input parameters.\n");
return;
}
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 int* const ystart_dim = mxGetDimensions(ystart);
const int* const shocks_dim = mxGetDimensions(shocks);
const int* const vcov_dim = mxGetDimensions(vcov);
const int* const ysteady_dim = mxGetDimensions(ysteady);
int ny = nstat + npred + nboth + nforw;
if (ny != ystart_dim[0])
mexErrMsgTxt("ystart has wrong number of rows.\n");
if (1 != ystart_dim[1])
mexErrMsgTxt("ystart has wrong number of cols.\n");
int nper = shocks_dim[1];
if (nexog != shocks_dim[0])
mexErrMsgTxt("shocks has a wrong number of rows.\n");
if (nexog != vcov_dim[0])
mexErrMsgTxt("vcov has a wrong number of rows.\n");
if (nexog != vcov_dim[1])
mexErrMsgTxt("vcov has a wrong number of cols.\n");
if (ny != ysteady_dim[0])
mexErrMsgTxt("ysteady has wrong number of rows.\n");
if (1 != ysteady_dim[1])
mexErrMsgTxt("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 int* const gk_dim = mxGetDimensions(gk);
FFSTensor ft(ny, npred+nboth+nexog, dim);
if (ft.ncols() != gk_dim[1]) {
char buf[1000];
sprintf(buf, "Wrong number of columns for folded tensor: got %d but I want %d\n",
gk_dim[1], ft.ncols());
mexErrMsgTxt(buf);
}
if (ft.nrows() != gk_dim[0]) {
char buf[1000];
sprintf(buf, "Wrong number of rows for folded tensor: got %d but I want %d\n",
gk_dim[0], ft.nrows());
mexErrMsgTxt(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[0] = res;
} catch (const KordException& e) {
mexErrMsgTxt("Caugth Kord exception.");
} catch (const TLException& e) {
mexErrMsgTxt("Caugth TL exception.");
} catch (SylvException& e) {
mexErrMsgTxt("Caught Sylv exception.");
}
}
};

View File

@ -0,0 +1,160 @@
%
% SYNOPSIS
%
% r = dynare_simul(name, shocks)
% r = dynare_simul(name, prefix, shocks)
% r = dynare_simul(name, shocks, start)
% r = dynare_simul(name, prefix, shocks, start)
%
% name name of MAT-file produced by dynare++
% prefix prefix of variables in the MAT-file
% shocks matrix of shocks
% start zero period value
%
% SEMANTICS
%
% The command reads a decision rule from the MAT-file having the given
% prefix. Then it starts simulating the decision rule with zero time value
% equal to the given start. It uses the given shocks for the simulation. If
% the start is not given, the state about which the decision rule is
% centralized is taken (called fix point, or stochastic steady state, take
% your pick).
%
% prefix Use the prefix with which you called dynare++, the default
% prefix in dynare++ is 'dyn'.
% shocks Number of rows must be a number of exogenous shocks,
% number of columns gives the number of simulated
% periods. NaNs and Infs in the matrix are substitued by
% draws from the normal distribution using the covariance
% matrix given in the model file.
% start Vector of endogenous variables in the ordering given by
% <prefix>_vars.
%
% Seed for random generator is derived from calling rand(1,1). Therefore,
% seeding can be controlled with rand('state') and rand('state',some_seed).
%
% EXAMPLES
%
% All examples suppose that the prefix is 'dyn' and that your_model.mat
% has been loaded into Matlab.
%
% 1. response to permanent negative shock to the third exo var EPS3 for
% 100 periods
%
% shocks = zeros(4,100); % 4 exogenous variables in the model
% shocks(dyn_i_EPS3,:) = -0.1; % the permanent shock to EPS3
% r = dynare_simul('your_model.mat',shocks);
%
% 2. one stochastic simulation for 100 periods
%
% shocks = zeros(4,100)./0; % put NaNs everywhere
% r = dynare_simul('your_model.mat',shocks);
%
% 3. one stochastic simulation starting at 75% undercapitalized economy
%
% shocks = zeros(4,100)./0; % put NaNs everywhere
% ystart = dyn_ss; % get copy of DR fix point
% ystart(dyn_i_K) = 0.75*dyn_ss(dyn_i_K); % scale down the capital
% r = dynare_simul('your_model.mat',shocks,ystart);
%
%
% SEE ALSO
%
% "DSGE Models with Dynare++. A Tutorial.", Ondra Kamenik, 2005
function r = dynare_simul(varargin)
% get the file name and load data
fname = varargin{1};
eval(['load ' fname]);
% set prefix, shocks, ystart
if ischar(varargin{2})
prefix = varargin{2};
if length(varargin) == 3
shocks = varargin{3};
ystart = NaN;
elseif length(varargin) == 4
shocks = varargin{3};
ystart = varargin{4};
else
error('Wrong number of parameters.');
end
else
prefix = 'dyn';
if length(varargin) == 2
shocks = varargin{2};
ystart = NaN;
elseif length(varargin) == 3
shocks = varargin{2};
ystart = varargin{3};
else
error('Wrong number of parameters.');
end
end
% load all needed variables but prefix_g_*
if (exist([prefix '_nstat']))
nstat = eval([prefix '_nstat']);
else
error(['Could not find variable ' prefix '_nstat in workspace']);
end
if (exist([prefix '_npred']))
npred = eval([prefix '_npred']);
else
error(['Could not find variable ' prefix '_npred in workspace']);
end
if (exist([prefix '_nboth']))
nboth = eval([prefix '_nboth']);
else
error(['Could not find variable ' prefix '_nboth in workspace']);
end
if (exist([prefix '_nforw']))
nforw = eval([prefix '_nforw']);
else
error(['Could not find variable ' prefix '_nforw in workspace']);
end
if (exist([prefix '_ss']))
ss = eval([prefix '_ss']);
else
error(['Could not find variable ' prefix '_ss in workspace']);
end
if (exist([prefix '_vcov_exo']))
vcov_exo = eval([prefix '_vcov_exo']);
else
error(['Could not find variable ' prefix '_vcov_exo in workspace']);
end
nexog = size(vcov_exo,1);
if isnan(ystart)
ystart = ss;
end
% newer version of dynare++ doesn't return prefix_g_0, we make it here if
% it does not exist in workspace
g_zero = [prefix '_g_0'];
if (~ exist(g_zero))
eval([ g_zero '= zeros(nstat+npred+nboth+nforw,1);']);
end
% make derstr a string of comma seperated existing prefix_g_*
derstr = [',' g_zero];
order = 1;
cont = 1;
while cont == 1
g_ord = [prefix '_g_' num2str(order)];
if (exist(g_ord))
derstr = [derstr ',' g_ord];
order = order + 1;
else
cont = 0;
end
end
% set seed
seed = ceil(10000*rand(1,1));
% call dynare_simul_
command = ['r=dynare_simul_(' num2str(order-1) ',nstat,npred,nboth,nforw,' ...
'nexog,ystart,shocks,vcov_exo,seed,ss' derstr ');'];
eval(command);

Binary file not shown.

View File

@ -0,0 +1,58 @@
@echo off
rem C:\ondra\tmp\dynare++\extern\matlab\mexopts.bat
rem Generated by gnumex.m script in c:\fs\gnumex-1.11
rem gnumex version: 1.11
rem Compile and link options used for building MEX etc files with
rem the Mingw/Cygwin tools. Options here are:
rem Mingw linking
rem Mex (*.dll) creation
rem Safe linking to temporary libraries
rem Language: C / C++
rem Compiling for pentium and above
rem Matlab version 7
rem
set MATLAB=C:\MATLAB71
set GM_PERLPATH=C:\MATLAB71\sys\perl\win32\bin\perl.exe
set GM_UTIL_PATH=c:\fs\gnumex-1.11
set PATH=c:\fs\mingw\bin;%PATH%
rem
rem Added libraries for linking
set GM_ADD_LIBS=
rem
rem Type of file to compile (mex or engine)
set GM_MEXTYPE=mex
rem
rem Language for compilation
set GM_MEXLANG=c
rem
rem def files to be converted to libs
set GM_DEFS2LINK=libmx.def;libmex.def;libmat.def;
rem
rem dlltool command line
set GM_DLLTOOL=dlltool
rem
rem compiler options; add compiler flags to compflags as desired
set NAME_OBJECT=-o
set COMPILER=gcc
set COMPFLAGS=-c -DMATLAB_MEX_FILE
set OPTIMFLAGS=-O3 -malign-double -fno-exceptions -mcpu=pentium
set DEBUGFLAGS=-g
set CPPCOMPFLAGS=%COMPFLAGS% -x c++
set CPPOPTIMFLAGS=%OPTIMFLAGS%
set CPPDEBUGFLAGS=%DEBUGFLAGS%
rem
rem NB Library creation commands occur in linker scripts
rem
rem Linker parameters
set LINKER=%GM_PERLPATH% %GM_UTIL_PATH%\linkmex.pl
set LINKFLAGS=
set CPPLINKFLAGS=GM_ISCPP
set LINKOPTIMFLAGS=-s
set LINKDEBUGFLAGS=-g -Wl,--image-base,0x28000000\n
set LINK_FILE=
set LINK_LIB=
set NAME_OUTPUT=-o %OUTDIR%%MEX_NAME%.dll
rem
rem Resource compiler parameters
set RC_COMPILER=%GM_PERLPATH% %GM_UTIL_PATH%\rccompile.pl -o %OUTDIR%mexversion.res
set RC_LINKER=

View File

@ -0,0 +1,360 @@
#define _W32_FT_OFFSET (116444736000000000LL)
/*1:*/
#line 6 "./journal.cweb"
#include "journal.h"
#include "kord_exception.h"
#ifndef __MINGW32__
# include <sys/resource.h>
# include <sys/utsname.h>
#endif
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
SystemResources _sysres;
#ifdef __MINGW32__
/*16:*/
#line 249 "./journal.cweb"
typedef struct _filetime{
unsigned long dwLowDateTime;
unsigned long dwHighDateTime;
}filetime;
extern"C"{
void __stdcall GetSystemTimeAsFileTime(filetime*);
};
typedef union{
long long ns100;
filetime ft;
}w32_ftv;
void gettimeofday(struct timeval*p,struct timezone*tz)
{
w32_ftv _now;
GetSystemTimeAsFileTime(&(_now.ft));
p->tv_usec= (long)((_now.ns100/10LL)%1000000LL);
p->tv_sec= (long)((_now.ns100-_W32_FT_OFFSET)/10000000LL);
return;
}
/*:16*/
#line 20 "./journal.cweb"
;
/*17:*/
#line 282 "./journal.cweb"
#define _SC_PAGESIZE 1
#define _SC_PHYS_PAGES 2
#define _SC_AVPHYS_PAGES 3
#define _SC_NPROCESSORS_ONLN 4
struct Win32MemoryStatus{
unsigned long dwLength;
unsigned long dwMemoryLoad;
unsigned int dwTotalPhys;
unsigned int dwAvailPhys;
unsigned int dwTotalPageFile;
unsigned int dwAvailPageFile;
unsigned int dwTotalVirtual;
unsigned int dwAvailVirtual;
Win32MemoryStatus();
};
extern"C"{
void __stdcall GlobalMemoryStatus(Win32MemoryStatus*);
};
Win32MemoryStatus::Win32MemoryStatus()
{
dwLength= sizeof(Win32MemoryStatus);
GlobalMemoryStatus(this);
}
long sysconf(int name)
{
switch(name){
case _SC_PAGESIZE:
return 1024;
case _SC_PHYS_PAGES:
{
Win32MemoryStatus memstat;
return memstat.dwTotalPhys/1024;
}
case _SC_AVPHYS_PAGES:
{
Win32MemoryStatus memstat;
return memstat.dwAvailPhys/1024;
}
case _SC_NPROCESSORS_ONLN:
return-1;
default:
KORD_RAISE("Not implemented in Win32 sysconf.");
return-1;
}
}
/*:17*/
#line 21 "./journal.cweb"
;
#endif
/*2:*/
#line 40 "./journal.cweb"
SystemResources::SystemResources()
{
gettimeofday(&start,NULL);
}
/*:2*/
#line 24 "./journal.cweb"
;
/*3:*/
#line 48 "./journal.cweb"
long int SystemResources::pageSize()
{
return sysconf(_SC_PAGESIZE);
}
/*:3*/
#line 25 "./journal.cweb"
;
/*4:*/
#line 55 "./journal.cweb"
long int SystemResources::physicalPages()
{
return sysconf(_SC_PHYS_PAGES);
}
/*:4*/
#line 26 "./journal.cweb"
;
/*5:*/
#line 62 "./journal.cweb"
long int SystemResources::onlineProcessors()
{
return sysconf(_SC_NPROCESSORS_ONLN);
}
/*:5*/
#line 27 "./journal.cweb"
;
/*6:*/
#line 69 "./journal.cweb"
long int SystemResources::availableMemory()
{
return pageSize()*sysconf(_SC_AVPHYS_PAGES);
}
/*:6*/
#line 28 "./journal.cweb"
;
/*7:*/
#line 78 "./journal.cweb"
void SystemResources::getRUS(double&load_avg,long int&pg_avail,
double&utime,double&stime,double&elapsed,
long int&idrss,long int&majflt)
{
struct timeval now;
gettimeofday(&now,NULL);
elapsed= now.tv_sec-start.tv_sec+(now.tv_usec-start.tv_usec)*1.0e-6;
#ifndef __MINGW32__
struct rusage rus;
getrusage(RUSAGE_SELF,&rus);
utime= rus.ru_utime.tv_sec+rus.ru_utime.tv_usec*1.0e-6;
stime= rus.ru_stime.tv_sec+rus.ru_stime.tv_usec*1.0e-6;
idrss= rus.ru_idrss;
majflt= rus.ru_majflt;
getloadavg(&load_avg,1);
#else
utime= -1.0;
stime= -1.0;
idrss= -1;
majflt= -1;
load_avg= -1.0;
#endif
pg_avail= sysconf(_SC_AVPHYS_PAGES);
}
/*:7*/
#line 29 "./journal.cweb"
;
/*8:*/
#line 107 "./journal.cweb"
SystemResourcesFlash::SystemResourcesFlash()
{
_sysres.getRUS(load_avg,pg_avail,utime,stime,
elapsed,idrss,majflt);
}
/*:8*/
#line 30 "./journal.cweb"
;
/*9:*/
#line 115 "./journal.cweb"
void SystemResourcesFlash::diff(const SystemResourcesFlash&pre)
{
utime-= pre.utime;
stime-= pre.stime;
elapsed-= pre.elapsed;
idrss-= pre.idrss;
majflt-= pre.majflt;
}
/*:9*/
#line 31 "./journal.cweb"
;
/*10:*/
#line 126 "./journal.cweb"
JournalRecord&JournalRecord::operator<<(const IntSequence&s)
{
operator<<("[");
for(int i= 0;i<s.size();i++){
operator<<(s[i]);
if(i<s.size()-1)
operator<<(",");
}
operator<<("]");
return*this;
}
/*:10*/
#line 32 "./journal.cweb"
;
/*11:*/
#line 140 "./journal.cweb"
void JournalRecord::writePrefix(const SystemResourcesFlash&f)
{
for(int i= 0;i<MAXLEN;i++)
prefix[i]= ' ';
double mb= 1024*1024;
sprintf(prefix,"%07.6g",f.elapsed);
sprintf(prefix+7,":%c%05d",recChar,ord);
sprintf(prefix+14,":%1.1f",f.load_avg);
sprintf(prefix+18,":%05.4g",f.pg_avail*_sysres.pageSize()/mb);
sprintf(prefix+24,"%s",": : ");
for(int i= 0;i<2*journal.getDepth();i++)
prefix[i+33]= ' ';
prefix[2*journal.getDepth()+33]= '\0';
}
/*:11*/
#line 33 "./journal.cweb"
;
/*12:*/
#line 157 "./journal.cweb"
void JournalRecordPair::writePrefixForEnd(const SystemResourcesFlash&f)
{
for(int i= 0;i<MAXLEN;i++)
prefix_end[i]= ' ';
double mb= 1024*1024;
SystemResourcesFlash difnow;
difnow.diff(f);
sprintf(prefix_end,"%07.6g",f.elapsed+difnow.elapsed);
sprintf(prefix_end+7,":E%05d",ord);
sprintf(prefix_end+14,":%1.1f",difnow.load_avg);
sprintf(prefix_end+18,":%05.4g",difnow.pg_avail*_sysres.pageSize()/mb);
sprintf(prefix_end+24,":%06.5g",difnow.majflt*_sysres.pageSize()/mb);
sprintf(prefix_end+31,"%s",": ");
for(int i= 0;i<2*journal.getDepth();i++)
prefix_end[i+33]= ' ';
prefix_end[2*journal.getDepth()+33]= '\0';
}
/*:12*/
#line 34 "./journal.cweb"
;
/*13:*/
#line 177 "./journal.cweb"
JournalRecordPair::~JournalRecordPair()
{
journal.decrementDepth();
writePrefixForEnd(flash);
journal<<prefix_end;
journal<<mes;
journal<<endl;
journal.flush();
}
/*:13*/
#line 35 "./journal.cweb"
;
/*14:*/
#line 189 "./journal.cweb"
JournalRecord&endrec(JournalRecord&rec)
{
rec.journal<<rec.prefix;
rec.journal<<rec.mes;
rec.journal<<endl;
rec.journal.flush();
rec.journal.incrementOrd();
return rec;
}
/*:14*/
#line 36 "./journal.cweb"
;
/*15:*/
#line 201 "./journal.cweb"
void Journal::printHeader()
{
(*this)<<"This is Dynare++, Copyright (C) 2004,2005 Michel Juillard, Ondra Kamenik\n";
(*this)<<"Dynare++ comes with ABSOLUTELY NO WARRANTY and is distributed under\n";
(*this)<<"General Public License, see http://www.gnu.org/license/gpl.html\n";
(*this)<<"\n\n";
#ifndef __MINGW32__
utsname info;
uname(&info);
(*this)<<"System info: ";
(*this)<<info.sysname<<" "<<info.release<<" "<<info.version<<" ";
(*this)<<info.machine<<", processors online: "<<_sysres.onlineProcessors();
(*this)<<"\n\nStart time: ";
char ts[100];
time_t curtime= time(NULL);
tm loctime;
localtime_r(&curtime,&loctime);
asctime_r(&loctime,ts);
(*this)<<ts<<"\n";
#else
(*this)<<"System info: (not implemented for MINGW)\n";
(*this)<<"Start time: (not implemented for MINGW)\n\n";
#endif
(*this)<<" ------ elapsed time (seconds) \n";
(*this)<<" | ------ record unique identifier \n";
(*this)<<" | | ------ load average \n";
(*this)<<" | | | ------ available memory (MB) \n";
(*this)<<" | | | | ------ major faults (MB)\n";
(*this)<<" | | | | | \n";
(*this)<<" V V V V V \n";
(*this)<<"\n";
}
/*:15*/
#line 37 "./journal.cweb"
;
/*:1*/

View File

@ -0,0 +1,96 @@
# $Id: Makefile 843 2006-07-28 08:54:19Z tamas $
# Copyright 2004, Ondra Kamenik
LD_LIBS := -llapack -lcblas -lf77blas -latlas -lg2c
CC_FLAGS := -Wall -I../tl/cc -I../sylv/cc -I../integ/cc \
$(CC_INCLUDE_PATH)
# -I/cygdrive/f/MinGW/include \
# -I/usr/local/atlas/include -I/usr/local/atlas/include/atlas \
# -I/cygdrive/f/Pthreads/Pre-built.2/include
ifeq ($(DEBUG),yes)
CC_FLAGS := $(CC_FLAGS) -g -DTL_DEBUG=2
else
CC_FLAGS := $(CC_FLAGS) -O2 -DPOSIX_THREADS
endif
ifeq ($(OS),Windows_NT)
CC_FLAGS := -mno-cygwin -mthreads $(CC_FLAGS)
LD_LIBS := -mno-cygwin -mthreads $(LD_LIBS) -lpthreadGC1
else
LD_LIBS := $(LD_LIBS) -lpthread
endif
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))
integhwebsource := $(wildcard ../integ/cc/*.hweb)
integhsource := $(patsubst %.hweb,%.h,$(integhwebsource))
cwebsource := $(wildcard *.cweb)
cppsource := $(patsubst %.cweb,%.cpp,$(cwebsource))
objects := $(patsubst %.cweb,%.o,$(cwebsource))
hwebsource := $(wildcard *.hweb)
hsource := $(patsubst %.hweb,%.h,$(hwebsource))
../integ/cc/dummy.ch:
make -C ../integ/cc dummy.ch
../tl/cc/dummy.ch:
make -C ../tl/cc dummy.ch
../tl/cc/%.cpp: ../tl/cc/%.cweb ../tl/cc/dummy.ch
make -C ../tl/cc $*.cpp
../tl/cc/%.h: ../tl/cc/%.hweb ../tl/cc/dummy.ch
make -C ../tl/cc $*.h
../integ/cc/%.h: ../integ/cc/%.hweb ../integ/cc/dummy.ch
make -C ../integ/cc $*.h
../tl/cc/%.o: ../tl/cc/%.cpp $(tlhsource)
make -C ../tl/cc $*.o
../sylv/cc/%.o: ../sylv/cc/%.cpp $(sylvhsource)
make -C ../sylv/cc $*.o
dummy.ch:
touch dummy.ch
%.cpp: %.cweb dummy.ch
ctangle -bhp $*.cweb dummy.ch $*.cpp
%.h: %.hweb dummy.ch
ctangle -bhp $*.hweb dummy.ch $*.h
%.o: %.cpp $(hwebsource) $(hsource) $(tlhwebsource) $(tlhsource) \
$(integhwebsource) $(integhsource)
$(CC) $(CC_FLAGS) -c $*.cpp
tests: $(hwebsource) $(cwebsoure) $(hsource) $(cppsource) \
$(tlhwebsource) $(tlcwebsoure) $(tlhsource) $(tlcppsource) \
$(sylvhsource) $(sylvcppsource) \
tests.o $(objects) $(tlobjects) $(sylvobjects)
$(CC) $(CC_FLAGS) $(objects) $(tlobjects) $(sylvobjects) tests.o -o tests $(LD_LIBS)
kord.pdf: doc
doc: main.web $(hwebsource) $(cwebsource)
cweave -bhp main.web
pdftex main
mv main.pdf kord.pdf
clear:
rm -f $(hsource)
rm -f $(cppsource)
rm -f *.o
rm -f tests
make -C ../tl/cc clear
make -C ../sylv/cc clear
rm -f main.{idx,dvi,pdf,scn,log,tex,toc}

View File

@ -0,0 +1,394 @@
/*1:*/
#line 6 "./approximation.cweb"
#include "kord_exception.h"
#include "approximation.h"
#include "first_order.h"
#include "korder_stoch.h"
/*2:*/
#line 26 "./approximation.cweb"
ZAuxContainer::ZAuxContainer(const _Ctype*gss,int ngss,int ng,int ny,int nu)
:StackContainer<FGSTensor> (4,1)
{
stack_sizes[0]= ngss;stack_sizes[1]= ng;
stack_sizes[2]= ny;stack_sizes[3]= nu;
conts[0]= gss;
calculateOffsets();
}
/*:2*/
#line 12 "./approximation.cweb"
;
/*3:*/
#line 41 "./approximation.cweb"
ZAuxContainer::itype ZAuxContainer::getType(int i,const Symmetry&s)const
{
if(i==0)
if(s[2]> 0)
return zero;
else
return matrix;
return zero;
}
/*:3*/
#line 13 "./approximation.cweb"
;
/*4:*/
#line 54 "./approximation.cweb"
Approximation::Approximation(DynamicModel&m,Journal&j,int ns)
:model(m),journal(j),rule_ders(NULL),rule_ders_ss(NULL),fdr(NULL),udr(NULL),
ypart(model.nstat(),model.npred(),model.nboth(),model.nforw()),
mom(UNormalMoments(model.order(),model.getVcov())),nvs(4),steps(ns),
ss(ypart.ny(),steps+1)
{
nvs[0]= ypart.nys();nvs[1]= model.nexog();
nvs[2]= model.nexog();nvs[3]= 1;
ss.nans();
}
/*:4*/
#line 14 "./approximation.cweb"
;
/*5:*/
#line 68 "./approximation.cweb"
Approximation::~Approximation()
{
if(rule_ders_ss)delete rule_ders_ss;
if(rule_ders)delete rule_ders;
if(fdr)delete fdr;
if(udr)delete udr;
}
/*:5*/
#line 15 "./approximation.cweb"
;
/*6:*/
#line 78 "./approximation.cweb"
const FoldDecisionRule&Approximation::getFoldDecisionRule()const
{
KORD_RAISE_IF(fdr==NULL,
"Folded decision rule has not been created in Approximation::getFoldDecisionRule");
return*fdr;
}
/*:6*/
#line 16 "./approximation.cweb"
;
/*7:*/
#line 88 "./approximation.cweb"
const UnfoldDecisionRule&Approximation::getUnfoldDecisionRule()const
{
KORD_RAISE_IF(udr==NULL,
"Unfolded decision rule has not been created in Approximation::getUnfoldDecisionRule");
return*udr;
}
/*:7*/
#line 17 "./approximation.cweb"
;
/*8:*/
#line 102 "./approximation.cweb"
void Approximation::approxAtSteady()
{
model.calcDerivativesAtSteady();
FirstOrder fo(model.nstat(),model.npred(),model.nboth(),model.nforw(),
model.nexog(),*(model.getModelDerivatives().get(Symmetry(1))),
journal);
KORD_RAISE_IF_X(!fo.isStable(),
"The model is not Blanchard-Kahn stable",
KORD_MD_NOT_STABLE);
if(model.order()>=2){
KOrder korder(model.nstat(),model.npred(),model.nboth(),model.nforw(),
model.getModelDerivatives(),fo.getGy(),fo.getGu(),
model.getVcov(),journal);
korder.switchToFolded();
for(int k= 2;k<=model.order();k++)
korder.performStep<KOrder::fold> (k);
saveRuleDerivs(korder.getFoldDers());
}else{
FirstOrderDerivs<KOrder::fold> fo_ders(fo);
saveRuleDerivs(fo_ders);
}
check(0.0);
}
/*:8*/
#line 18 "./approximation.cweb"
;
/*9:*/
#line 159 "./approximation.cweb"
void Approximation::walkStochSteady()
{
/*10:*/
#line 186 "./approximation.cweb"
model.solveDeterministicSteady();
approxAtSteady();
Vector steady0(ss,0);
steady0= (const Vector&)model.getSteady();
/*:10*/
#line 162 "./approximation.cweb"
;
double sigma_so_far= 0.0;
double dsigma= (steps==0)?0.0:1.0/steps;
for(int i= 1;i<=steps;i++){
JournalRecordPair pa(journal);
pa<<"Approximation about stochastic steady for sigma="<<sigma_so_far+dsigma<<endrec;
Vector last_steady((const Vector&)model.getSteady());
/*11:*/
#line 196 "./approximation.cweb"
DRFixPoint<KOrder::fold> fp(*rule_ders,ypart,model.getSteady(),dsigma);
bool converged= fp.calcFixPoint(DecisionRule::horner,model.getSteady());
JournalRecord rec(journal);
rec<<"Fix point calcs: iter="<<fp.getNumIter()<<", newton_iter="
<<fp.getNewtonTotalIter()<<", last_newton_iter="<<fp.getNewtonLastIter()<<".";
if(converged)
rec<<" Converged."<<endrec;
else{
rec<<" Not converged!!"<<endrec;
KORD_RAISE_X("Fix point calculation not converged",KORD_FP_NOT_CONV);
}
Vector steadyi(ss,i);
steadyi= (const Vector&)model.getSteady();
/*:11*/
#line 171 "./approximation.cweb"
;
/*12:*/
#line 216 "./approximation.cweb"
Vector dy((const Vector&)model.getSteady());
dy.add(-1.0,last_steady);
StochForwardDerivs<KOrder::fold> hh(ypart,model.nexog(),*rule_ders_ss,mom,dy,
dsigma,sigma_so_far);
JournalRecord rec1(journal);
rec1<<"Calculation of g** expectations done"<<endrec;
/*:12*/
#line 172 "./approximation.cweb"
;
/*13:*/
#line 229 "./approximation.cweb"
model.calcDerivativesAtSteady();
KOrderStoch korder_stoch(ypart,model.nexog(),model.getModelDerivatives(),
hh,journal);
for(int d= 1;d<=model.order();d++){
korder_stoch.performStep<KOrder::fold> (d);
}
saveRuleDerivs(korder_stoch.getFoldDers());
/*:13*/
#line 173 "./approximation.cweb"
;
check(sigma_so_far+dsigma);
sigma_so_far+= dsigma;
}
/*14:*/
#line 240 "./approximation.cweb"
if(fdr){
delete fdr;
fdr= NULL;
}
if(udr){
delete udr;
udr= NULL;
}
fdr= new FoldDecisionRule(*rule_ders,ypart,model.nexog(),
model.getSteady(),1.0-sigma_so_far);
if(steps==0){
/*15:*/
#line 258 "./approximation.cweb"
DRFixPoint<KOrder::fold> fp(*rule_ders,ypart,model.getSteady(),1.0);
bool converged= fp.calcFixPoint(DecisionRule::horner,model.getSteady());
JournalRecord rec(journal);
rec<<"Fix point calcs: iter="<<fp.getNumIter()<<", newton_iter="
<<fp.getNewtonTotalIter()<<", last_newton_iter="<<fp.getNewtonLastIter()<<".";
if(converged)
rec<<" Converged."<<endrec;
else{
rec<<" Not converged!!"<<endrec;
KORD_RAISE_X("Fix point calculation not converged",KORD_FP_NOT_CONV);
}
{
JournalRecordPair recp(journal);
recp<<"Centralizing about fix-point."<<endrec;
FoldDecisionRule*dr_backup= fdr;
fdr= new FoldDecisionRule(*dr_backup,model.getSteady());
delete dr_backup;
}
/*:15*/
#line 253 "./approximation.cweb"
;
}
/*:14*/
#line 179 "./approximation.cweb"
;
}
/*:9*/
#line 19 "./approximation.cweb"
;
/*16:*/
#line 285 "./approximation.cweb"
void Approximation::saveRuleDerivs(const FGSContainer&g)
{
if(rule_ders){
delete rule_ders;
delete rule_ders_ss;
}
rule_ders= new FGSContainer(g);
rule_ders_ss= new FGSContainer(4);
for(FGSContainer::iterator run= (*rule_ders).begin();run!=(*rule_ders).end();++run){
FGSTensor*ten= new FGSTensor(ypart.nstat+ypart.npred,ypart.nyss(),*((*run).second));
rule_ders_ss->insert(ten);
}
}
/*:16*/
#line 20 "./approximation.cweb"
;
/*17:*/
#line 312 "./approximation.cweb"
void Approximation::calcStochShift(Vector&out,double at_sigma)const
{
KORD_RAISE_IF(out.length()!=ypart.ny(),
"Wrong length of output vector for Approximation::calcStochShift");
out.zeros();
ZAuxContainer zaux(rule_ders_ss,ypart.nyss(),ypart.ny(),
ypart.nys(),model.nexog());
int dfac= 1;
for(int d= 1;d<=rule_ders->getMaxDim();d++,dfac*= d){
if(KOrder::is_even(d)){
Symmetry sym(0,d,0,0);
/*18:*/
#line 333 "./approximation.cweb"
FGSTensor*ten= new FGSTensor(ypart.ny(),TensorDimens(sym,nvs));
ten->zeros();
for(int l= 1;l<=d;l++){
const FSSparseTensor*f= model.getModelDerivatives().get(Symmetry(l));
zaux.multAndAdd(*f,*ten);
}
/*:18*/
#line 326 "./approximation.cweb"
;
/*19:*/
#line 342 "./approximation.cweb"
FGSTensor*tmp= new FGSTensor(ypart.ny(),TensorDimens(Symmetry(0,0,0,0),nvs));
tmp->zeros();
ten->contractAndAdd(1,*tmp,*(mom.get(Symmetry(d))));
out.add(pow(at_sigma,d)/dfac,tmp->getData());
delete ten;
delete tmp;
/*:19*/
#line 327 "./approximation.cweb"
;
}
}
}
/*:17*/
#line 21 "./approximation.cweb"
;
/*20:*/
#line 359 "./approximation.cweb"
void Approximation::check(double at_sigma)const
{
Vector stoch_shift(ypart.ny());
Vector system_resid(ypart.ny());
Vector xx(model.nexog());
xx.zeros();
model.evaluateSystem(system_resid,model.getSteady(),xx);
calcStochShift(stoch_shift,at_sigma);
stoch_shift.add(1.0,system_resid);
JournalRecord rec1(journal);
rec1<<"Error of current approximation for shocks at sigma "<<at_sigma
<<" is "<<stoch_shift.getMax()<<endrec;
calcStochShift(stoch_shift,1.0);
stoch_shift.add(1.0,system_resid);
JournalRecord rec2(journal);
rec2<<"Error of current approximation for full shocks is "<<stoch_shift.getMax()<<endrec;
}
/*:20*/
#line 22 "./approximation.cweb"
;
/*21:*/
#line 394 "./approximation.cweb"
TwoDMatrix*Approximation::calcYCov()const
{
const TwoDMatrix&gy= *(rule_ders->get(Symmetry(1,0,0,0)));
const TwoDMatrix&gu= *(rule_ders->get(Symmetry(0,1,0,0)));
TwoDMatrix G(model.numeq(),model.numeq());
G.zeros();
G.place(gy,0,model.nstat());
TwoDMatrix B((const TwoDMatrix&)G);
B.mult(-1.0);
TwoDMatrix C(G,"transpose");
TwoDMatrix A(model.numeq(),model.numeq());
A.zeros();
for(int i= 0;i<model.numeq();i++)
A.get(i,i)= 1.0;
TwoDMatrix guSigma(gu,model.getVcov());
TwoDMatrix guTrans(gu,"transpose");
TwoDMatrix*X= new TwoDMatrix(guSigma,guTrans);
GeneralSylvester gs(1,model.numeq(),model.numeq(),0,
A.base(),B.base(),C.base(),X->base());
gs.solve();
return X;
}
/*:21*/
#line 23 "./approximation.cweb"
;
/*:1*/

View File

@ -0,0 +1,71 @@
/*1:*/
#line 53 "./approximation.hweb"
#ifndef APPROXIMATION_H
#define APPROXIMATION_H
#include "dynamic_model.h"
#include "decision_rule.h"
#include "korder.h"
#include "journal.h"
/*2:*/
#line 80 "./approximation.hweb"
class ZAuxContainer:public StackContainer<FGSTensor> ,public FoldedStackContainer{
public:
typedef StackContainer<FGSTensor> ::_Ctype _Ctype;
typedef StackContainer<FGSTensor> ::itype itype;
ZAuxContainer(const _Ctype*gss,int ngss,int ng,int ny,int nu);
itype getType(int i,const Symmetry&s)const;
};
/*:2*/
#line 62 "./approximation.hweb"
;
/*3:*/
#line 115 "./approximation.hweb"
class Approximation{
DynamicModel&model;
Journal&journal;
FGSContainer*rule_ders;
FGSContainer*rule_ders_ss;
FoldDecisionRule*fdr;
UnfoldDecisionRule*udr;
const PartitionY ypart;
const FNormalMoments mom;
IntSequence nvs;
int steps;
TwoDMatrix ss;
public:
Approximation(DynamicModel&m,Journal&j,int ns);
virtual~Approximation();
const FoldDecisionRule&getFoldDecisionRule()const;
const UnfoldDecisionRule&getUnfoldDecisionRule()const;
const TwoDMatrix&getSS()const
{return ss;}
const DynamicModel&getModel()const
{return model;}
void walkStochSteady();
TwoDMatrix*calcYCov()const;
protected:
void approxAtSteady();
void calcStochShift(Vector&out,double at_sigma)const;
void saveRuleDerivs(const FGSContainer&g);
void check(double at_sigma)const;
};
/*:3*/
#line 63 "./approximation.hweb"
;
#endif
/*:1*/

View File

@ -0,0 +1,793 @@
/*1:*/
#line 5 "./decision_rule.cweb"
#include "kord_exception.h"
#include "decision_rule.h"
#include "dynamic_model.h"
#include "SymSchurDecomp.h"
#include "cpplapack.h"
#include <limits>
template<>
int DRFixPoint<KOrder::fold> ::max_iter= 10000;
template<>
int DRFixPoint<KOrder::unfold> ::max_iter= 10000;
template<>
double DRFixPoint<KOrder::fold> ::tol= 1.e-10;
template<>
double DRFixPoint<KOrder::unfold> ::tol= 1.e-10;
template<>
int DRFixPoint<KOrder::fold> ::max_newton_iter= 50;
template<>
int DRFixPoint<KOrder::unfold> ::max_newton_iter= 50;
template<>
int DRFixPoint<KOrder::fold> ::newton_pause= 100;
template<>
int DRFixPoint<KOrder::unfold> ::newton_pause= 100;
/*2:*/
#line 72 "./decision_rule.cweb"
FoldDecisionRule::FoldDecisionRule(const UnfoldDecisionRule&udr)
:DecisionRuleImpl<KOrder::fold> (ctraits<KOrder::fold> ::Tpol(udr.nrows(),udr.nvars()),
udr.ypart,udr.nu,udr.ysteady)
{
for(ctraits<KOrder::unfold> ::Tpol::const_iterator it= udr.begin();
it!=udr.end();++it){
insert(new ctraits<KOrder::fold> ::Ttensym(*((*it).second)));
}
}
/*:2*/
#line 33 "./decision_rule.cweb"
;
/*3:*/
#line 84 "./decision_rule.cweb"
UnfoldDecisionRule::UnfoldDecisionRule(const FoldDecisionRule&fdr)
:DecisionRuleImpl<KOrder::unfold> (ctraits<KOrder::unfold> ::Tpol(fdr.nrows(),fdr.nvars()),
fdr.ypart,fdr.nu,fdr.ysteady)
{
for(ctraits<KOrder::fold> ::Tpol::const_iterator it= fdr.begin();
it!=fdr.end();++it){
insert(new ctraits<KOrder::unfold> ::Ttensym(*((*it).second)));
}
}
/*:3*/
#line 34 "./decision_rule.cweb"
;
/*4:*/
#line 96 "./decision_rule.cweb"
SimResults::~SimResults()
{
for(int i= 0;i<getNumSets();i++){
delete data[i];
delete shocks[i];
}
}
/*:4*/
#line 35 "./decision_rule.cweb"
;
/*5:*/
#line 108 "./decision_rule.cweb"
void SimResults::simulate(int num_sim,const DecisionRule&dr,const Vector&start,
const TwoDMatrix&vcov,Journal&journal)
{
JournalRecordPair paa(journal);
paa<<"Performing "<<num_sim<<" stochastic simulations for "
<<num_per<<" periods"<<endrec;
simulate(num_sim,dr,start,vcov);
int thrown= num_sim-data.size();
if(thrown> 0){
JournalRecord rec(journal);
rec<<"I had to throw "<<thrown<<" simulations away due to Nan or Inf"<<endrec;
}
}
/*:5*/
#line 36 "./decision_rule.cweb"
;
/*6:*/
#line 127 "./decision_rule.cweb"
void SimResults::simulate(int num_sim,const DecisionRule&dr,const Vector&start,
const TwoDMatrix&vcov)
{
std::vector<RandomShockRealization> rsrs;
rsrs.reserve(num_sim);
THREAD_GROUP gr;
for(int i= 0;i<num_sim;i++){
RandomShockRealization sr(vcov,system_random_generator.int_uniform());
rsrs.push_back(sr);
THREAD*worker= new
SimulationWorker(*this,dr,DecisionRule::horner,
num_per,start,rsrs.back());
gr.insert(worker);
}
gr.run();
}
/*:6*/
#line 37 "./decision_rule.cweb"
;
/*7:*/
#line 149 "./decision_rule.cweb"
bool SimResults::addDataSet(TwoDMatrix*d,ExplicitShockRealization*sr)
{
KORD_RAISE_IF(d->nrows()!=num_y,
"Incompatible number of rows for SimResults::addDataSets");
KORD_RAISE_IF(d->ncols()!=num_per,
"Incompatible number of cols for SimResults::addDataSets");
if(d->isFinite()){
data.push_back(d);
shocks.push_back(sr);
return true;
}else{
delete d;
delete sr;
return false;
}
}
/*:7*/
#line 38 "./decision_rule.cweb"
;
/*8:*/
#line 168 "./decision_rule.cweb"
void SimResults::writeMat4(const char*base,const char*lname)const
{
char matfile_name[100];
sprintf(matfile_name,"%s.mat",base);
FILE*out;
if(NULL!=(out= fopen(matfile_name,"wb"))){
writeMat4(out,lname);
fclose(out);
}
}
/*:8*/
#line 39 "./decision_rule.cweb"
;
/*9:*/
#line 183 "./decision_rule.cweb"
void SimResults::writeMat4(FILE*fd,const char*lname)const
{
char tmp[100];
for(int i= 0;i<getNumSets();i++){
if(getNumSets()> 1)
sprintf(tmp,"%s_data%d",lname,i+1);
else
sprintf(tmp,"%s_data",lname);
ConstTwoDMatrix m(*(data[i]));
m.writeMat4(fd,tmp);
}
}
/*:9*/
#line 40 "./decision_rule.cweb"
;
/*10:*/
#line 198 "./decision_rule.cweb"
void SimResultsStats::simulate(int num_sim,const DecisionRule&dr,
const Vector&start,
const TwoDMatrix&vcov,Journal&journal)
{
SimResults::simulate(num_sim,dr,start,vcov,journal);
{
JournalRecordPair paa(journal);
paa<<"Calculating means from the simulations."<<endrec;
calcMean();
}
{
JournalRecordPair paa(journal);
paa<<"Calculating covariances from the simulations."<<endrec;
calcVcov();
}
}
/*:10*/
#line 41 "./decision_rule.cweb"
;
/*11:*/
#line 218 "./decision_rule.cweb"
void SimResultsStats::writeMat4(FILE*fd,const char*lname)const
{
char tmp[100];
sprintf(tmp,"%s_mean",lname);
ConstTwoDMatrix m(num_y,1,mean.base());
m.writeMat4(fd,tmp);
sprintf(tmp,"%s_vcov",lname);
ConstTwoDMatrix(vcov).writeMat4(fd,tmp);
}
/*:11*/
#line 42 "./decision_rule.cweb"
;
/*12:*/
#line 230 "./decision_rule.cweb"
void SimResultsStats::calcMean()
{
mean.zeros();
if(data.size()*num_per> 0){
double mult= 1.0/data.size()/num_per;
for(unsigned int i= 0;i<data.size();i++){
for(int j= 0;j<num_per;j++){
ConstVector col(*data[i],j);
mean.add(mult,col);
}
}
}
}
/*:12*/
#line 43 "./decision_rule.cweb"
;
/*13:*/
#line 246 "./decision_rule.cweb"
void SimResultsStats::calcVcov()
{
if(data.size()*num_per> 1){
vcov.zeros();
double mult= 1.0/(data.size()*num_per-1);
for(unsigned int i= 0;i<data.size();i++){
const TwoDMatrix&d= *(data[i]);
for(int j= 0;j<num_per;j++){
for(int m= 0;m<num_y;m++){
for(int n= m;n<num_y;n++){
double s= (d.get(m,j)-mean[m])*(d.get(n,j)-mean[n]);
vcov.get(m,n)+= mult*s;
if(m!=n)
vcov.get(n,m)+= mult*s;
}
}
}
}
}else{
vcov.infs();
}
}
/*:13*/
#line 44 "./decision_rule.cweb"
;
/*14:*/
#line 271 "./decision_rule.cweb"
void SimResultsDynamicStats::simulate(int num_sim,const DecisionRule&dr,
const Vector&start,
const TwoDMatrix&vcov,Journal&journal)
{
SimResults::simulate(num_sim,dr,start,vcov,journal);
{
JournalRecordPair paa(journal);
paa<<"Calculating means of the conditional simulations."<<endrec;
calcMean();
}
{
JournalRecordPair paa(journal);
paa<<"Calculating variances of the conditional simulations."<<endrec;
calcVariance();
}
}
/*:14*/
#line 45 "./decision_rule.cweb"
;
/*15:*/
#line 290 "./decision_rule.cweb"
void SimResultsDynamicStats::writeMat4(FILE*fd,const char*lname)const
{
char tmp[100];
sprintf(tmp,"%s_cond_mean",lname);
ConstTwoDMatrix(mean).writeMat4(fd,tmp);
sprintf(tmp,"%s_cond_variance",lname);
ConstTwoDMatrix(variance).writeMat4(fd,tmp);
}
/*:15*/
#line 46 "./decision_rule.cweb"
;
/*16:*/
#line 301 "./decision_rule.cweb"
void SimResultsDynamicStats::calcMean()
{
mean.zeros();
if(data.size()> 0){
double mult= 1.0/data.size();
for(int j= 0;j<num_per;j++){
Vector meanj(mean,j);
for(unsigned int i= 0;i<data.size();i++){
ConstVector col(*data[i],j);
meanj.add(mult,col);
}
}
}
}
/*:16*/
#line 47 "./decision_rule.cweb"
;
/*17:*/
#line 318 "./decision_rule.cweb"
void SimResultsDynamicStats::calcVariance()
{
if(data.size()> 1){
variance.zeros();
double mult= 1.0/(data.size()-1);
for(int j= 0;j<num_per;j++){
ConstVector meanj(mean,j);
Vector varj(variance,j);
for(int i= 0;i<(int)data.size();i++){
Vector col(ConstVector((*data[i]),j));
col.add(-1.0,meanj);
for(int k= 0;k<col.length();k++)
col[k]= col[k]*col[k];
varj.add(mult,col);
}
}
}else{
variance.infs();
}
}
/*:17*/
#line 48 "./decision_rule.cweb"
;
/*18:*/
#line 342 "./decision_rule.cweb"
void SimResultsIRF::simulate(const DecisionRule&dr,const Vector&start,
Journal&journal)
{
JournalRecordPair paa(journal);
paa<<"Performing "<<control.getNumSets()<<" IRF simulations for "
<<num_per<<" periods; shock="<<ishock<<", impulse="<<imp<<endrec;
simulate(dr,start);
int thrown= control.getNumSets()-data.size();
if(thrown> 0){
JournalRecord rec(journal);
rec<<"I had to throw "<<thrown
<<" simulations away due to Nan or Inf"<<endrec;
}
calcMeans();
calcVariances();
}
/*:18*/
#line 49 "./decision_rule.cweb"
;
/*19:*/
#line 361 "./decision_rule.cweb"
void SimResultsIRF::simulate(const DecisionRule&dr,const Vector&start)
{
THREAD_GROUP gr;
for(int idata= 0;idata<control.getNumSets();idata++){
THREAD*worker= new
SimulationIRFWorker(*this,dr,DecisionRule::horner,
num_per,start,idata,ishock,imp);
gr.insert(worker);
}
gr.run();
}
/*:19*/
#line 50 "./decision_rule.cweb"
;
/*20:*/
#line 375 "./decision_rule.cweb"
void SimResultsIRF::calcMeans()
{
means.zeros();
if(data.size()> 0){
for(unsigned int i= 0;i<data.size();i++)
means.add(1.0,*(data[i]));
means.mult(1.0/data.size());
}
}
/*:20*/
#line 51 "./decision_rule.cweb"
;
/*21:*/
#line 387 "./decision_rule.cweb"
void SimResultsIRF::calcVariances()
{
if(data.size()> 1){
variances.zeros();
for(unsigned int i= 0;i<data.size();i++){
TwoDMatrix d((const TwoDMatrix&)(*(data[i])));
d.add(-1.0,means);
for(int j= 0;j<d.nrows();j++)
for(int k= 0;k<d.ncols();k++)
variances.get(j,k)+= d.get(j,k)*d.get(j,k);
d.mult(1.0/(data.size()-1));
}
}else{
variances.infs();
}
}
/*:21*/
#line 52 "./decision_rule.cweb"
;
/*22:*/
#line 406 "./decision_rule.cweb"
void SimResultsIRF::writeMat4(FILE*fd,const char*lname)const
{
char tmp[100];
sprintf(tmp,"%s_mean",lname);
means.writeMat4(fd,tmp);
sprintf(tmp,"%s_var",lname);
variances.writeMat4(fd,tmp);
}
/*:22*/
#line 53 "./decision_rule.cweb"
;
/*23:*/
#line 417 "./decision_rule.cweb"
void RTSimResultsStats::simulate(int num_sim,const DecisionRule&dr,const Vector&start,
const TwoDMatrix&v,Journal&journal)
{
JournalRecordPair paa(journal);
paa<<"Performing "<<num_sim<<" real-time stochastic simulations for "
<<num_per<<" periods"<<endrec;
simulate(num_sim,dr,start,v);
mean= nc.getMean();
mean.add(1.0,dr.getSteady());
nc.getVariance(vcov);
if(thrown_periods> 0){
JournalRecord rec(journal);
rec<<"I had to throw "<<thrown_periods<<" periods away due to Nan or Inf"<<endrec;
JournalRecord rec1(journal);
rec1<<"This affected "<<incomplete_simulations<<" out of "
<<num_sim<<" simulations"<<endrec;
}
}
/*:23*/
#line 54 "./decision_rule.cweb"
;
/*24:*/
#line 438 "./decision_rule.cweb"
void RTSimResultsStats::simulate(int num_sim,const DecisionRule&dr,const Vector&start,
const TwoDMatrix&vcov)
{
std::vector<RandomShockRealization> rsrs;
rsrs.reserve(num_sim);
THREAD_GROUP gr;
for(int i= 0;i<num_sim;i++){
RandomShockRealization sr(vcov,system_random_generator.int_uniform());
rsrs.push_back(sr);
THREAD*worker= new
RTSimulationWorker(*this,dr,DecisionRule::horner,
num_per,start,rsrs.back());
gr.insert(worker);
}
gr.run();
}
/*:24*/
#line 55 "./decision_rule.cweb"
;
/*25:*/
#line 458 "./decision_rule.cweb"
void RTSimResultsStats::writeMat4(FILE*fd,const char*lname)
{
char tmp[100];
sprintf(tmp,"%s_rt_mean",lname);
ConstTwoDMatrix m(nc.getDim(),1,mean.base());
m.writeMat4(fd,tmp);
sprintf(tmp,"%s_rt_vcov",lname);
ConstTwoDMatrix(vcov).writeMat4(fd,tmp);
}
/*:25*/
#line 56 "./decision_rule.cweb"
;
/*26:*/
#line 470 "./decision_rule.cweb"
IRFResults::IRFResults(const DynamicModel&mod,const DecisionRule&dr,
const SimResults&control,const vector<int> &ili,
Journal&journal)
:model(mod),irf_list_ind(ili)
{
int num_per= control.getNumPer();
JournalRecordPair pa(journal);
pa<<"Calculating IRFs against control for "<<(int)irf_list_ind.size()<<" shocks and for "
<<num_per<<" periods"<<endrec;
const TwoDMatrix&vcov= mod.getVcov();
for(unsigned int ii= 0;ii<irf_list_ind.size();ii++){
int ishock= irf_list_ind[ii];
double stderror= sqrt(vcov.get(ishock,ishock));
irf_res.push_back(new SimResultsIRF(control,model.numeq(),num_per,
ishock,stderror));
irf_res.push_back(new SimResultsIRF(control,model.numeq(),num_per,
ishock,-stderror));
}
for(unsigned int ii= 0;ii<irf_list_ind.size();ii++){
irf_res[2*ii]->simulate(dr,model.getSteady(),journal);
irf_res[2*ii+1]->simulate(dr,model.getSteady(),journal);
}
}
/*:26*/
#line 57 "./decision_rule.cweb"
;
/*27:*/
#line 497 "./decision_rule.cweb"
IRFResults::~IRFResults()
{
for(unsigned int i= 0;i<irf_res.size();i++)
delete irf_res[i];
}
/*:27*/
#line 58 "./decision_rule.cweb"
;
/*28:*/
#line 505 "./decision_rule.cweb"
void IRFResults::writeMat4(FILE*fd,const char*prefix)const
{
for(unsigned int i= 0;i<irf_list_ind.size();i++){
char tmp[100];
int ishock= irf_list_ind[i];
const char*shockname= model.getExogNames().getName(ishock);
sprintf(tmp,"%s_irfp_%s",prefix,shockname);
irf_res[2*i]->writeMat4(fd,tmp);
sprintf(tmp,"%s_irfm_%s",prefix,shockname);
irf_res[2*i+1]->writeMat4(fd,tmp);
}
}
/*:28*/
#line 59 "./decision_rule.cweb"
;
/*29:*/
#line 520 "./decision_rule.cweb"
void SimulationWorker::operator()()
{
ExplicitShockRealization*esr= new ExplicitShockRealization(sr,np);
TwoDMatrix*m= dr.simulate(em,np,st,*esr);
{
SYNCHRO syn(&res,"simulation");
res.addDataSet(m,esr);
}
}
/*:29*/
#line 60 "./decision_rule.cweb"
;
/*30:*/
#line 534 "./decision_rule.cweb"
void SimulationIRFWorker::operator()()
{
ExplicitShockRealization*esr=
new ExplicitShockRealization(res.control.getShocks(idata));
esr->addToShock(ishock,0,imp);
TwoDMatrix*m= dr.simulate(em,np,st,*esr);
m->add(-1.0,res.control.getData(idata));
{
SYNCHRO syn(&res,"simulation");
res.addDataSet(m,esr);
}
}
/*:30*/
#line 61 "./decision_rule.cweb"
;
/*31:*/
#line 549 "./decision_rule.cweb"
void RTSimulationWorker::operator()()
{
NormalConj nc(res.nc.getDim());
const PartitionY&ypart= dr.getYPart();
int nu= dr.nexog();
const Vector&ysteady= dr.getSteady();
/*32:*/
#line 571 "./decision_rule.cweb"
Vector dyu(ypart.nys()+nu);
ConstVector ystart_pred(ystart,ypart.nstat,ypart.nys());
ConstVector ysteady_pred(ysteady,ypart.nstat,ypart.nys());
Vector dy(dyu,0,ypart.nys());
Vector u(dyu,ypart.nys(),nu);
Vector y(nc.getDim());
ConstVector ypred(y,ypart.nstat,ypart.nys());
/*:32*/
#line 557 "./decision_rule.cweb"
;
/*33:*/
#line 581 "./decision_rule.cweb"
int ip= 0;
dy= ystart_pred;
dy.add(-1.0,ysteady_pred);
sr.get(ip,u);
dr.eval(em,y,dyu);
nc.update(y);
/*:33*/
#line 558 "./decision_rule.cweb"
;
/*34:*/
#line 590 "./decision_rule.cweb"
while(y.isFinite()&&ip<res.num_per){
ip++;
dy= ypred;
sr.get(ip,u);
dr.eval(em,y,dyu);
nc.update(y);
}
/*:34*/
#line 559 "./decision_rule.cweb"
;
{
SYNCHRO syn(&res,"rtsimulation");
res.nc.update(nc);
if(res.num_per-ip> 0){
res.incomplete_simulations++;
res.thrown_periods+= res.num_per-ip;
}
}
}
/*:31*/
#line 62 "./decision_rule.cweb"
;
/*35:*/
#line 602 "./decision_rule.cweb"
void RandomShockRealization::choleskyFactor(const TwoDMatrix&v)
{
factor= v;
int rows= factor.nrows();
for(int i= 0;i<rows;i++)
for(int j= i+1;j<rows;j++)
factor.get(i,j)= 0.0;
int info;
LAPACK_dpotrf("L",&rows,factor.base(),&rows,&info);
KORD_RAISE_IF(info!=0,
"Info!=0 in RandomShockRealization::choleskyFactor");
}
/*:35*/
#line 63 "./decision_rule.cweb"
;
/*36:*/
#line 620 "./decision_rule.cweb"
void RandomShockRealization::schurFactor(const TwoDMatrix&v)
{
SymSchurDecomp ssd(v);
ssd.getFactor(factor);
}
/*:36*/
#line 64 "./decision_rule.cweb"
;
/*37:*/
#line 628 "./decision_rule.cweb"
void RandomShockRealization::get(int n,Vector&out)
{
KORD_RAISE_IF(out.length()!=numShocks(),
"Wrong length of out vector in RandomShockRealization::get");
Vector d(out.length());
for(int i= 0;i<d.length();i++){
d[i]= mtwister.normal();
}
out.zeros();
factor.multaVec(out,ConstVector(d));
}
/*:37*/
#line 65 "./decision_rule.cweb"
;
/*38:*/
#line 642 "./decision_rule.cweb"
ExplicitShockRealization::ExplicitShockRealization(ShockRealization&sr,
int num_per)
:shocks(sr.numShocks(),num_per)
{
for(int j= 0;j<num_per;j++){
Vector jcol(shocks,j);
sr.get(j,jcol);
}
}
/*:38*/
#line 66 "./decision_rule.cweb"
;
/*39:*/
#line 654 "./decision_rule.cweb"
void ExplicitShockRealization::get(int n,Vector&out)
{
KORD_RAISE_IF(out.length()!=numShocks(),
"Wrong length of out vector in ExplicitShockRealization::get");
int i= n%shocks.ncols();
ConstVector icol(shocks,i);
out= icol;
}
/*:39*/
#line 67 "./decision_rule.cweb"
;
/*40:*/
#line 665 "./decision_rule.cweb"
void ExplicitShockRealization::addToShock(int ishock,int iper,double val)
{
KORD_RAISE_IF(ishock<0||ishock> numShocks(),
"Wrong index of shock in ExplicitShockRealization::addToShock");
int j= iper%shocks.ncols();
shocks.get(ishock,j)+= val;
}
/*:40*/
#line 68 "./decision_rule.cweb"
;
/*41:*/
#line 676 "./decision_rule.cweb"
void GenShockRealization::get(int n,Vector&out)
{
KORD_RAISE_IF(out.length()!=numShocks(),
"Wrong length of out vector in GenShockRealization::get");
ExplicitShockRealization::get(n,out);
Vector r(numShocks());
RandomShockRealization::get(n,r);
for(int j= 0;j<numShocks();j++)
if(!isfinite(out[j]))
out[j]= r[j];
}
/*:41*/
#line 69 "./decision_rule.cweb"
;
/*:1*/

View File

@ -0,0 +1,828 @@
/*1:*/
#line 38 "./decision_rule.hweb"
#ifndef DECISION_RULE_H
#define DECISION_RULE_H
#include "kord_exception.h"
#include "korder.h"
#include "normal_conjugate.h"
#include "mersenne_twister.h"
/*2:*/
#line 73 "./decision_rule.hweb"
class ShockRealization{
public:
virtual~ShockRealization(){}
virtual void get(int n,Vector&out)= 0;
virtual int numShocks()const= 0;
};
/*:2*/
#line 47 "./decision_rule.hweb"
;
/*3:*/
#line 94 "./decision_rule.hweb"
class DecisionRule{
public:
enum emethod{horner,trad};
virtual~DecisionRule(){}
virtual TwoDMatrix*simulate(emethod em,int np,const Vector&ystart,
ShockRealization&sr)const= 0;
virtual void eval(emethod em,Vector&out,const ConstVector&v)const= 0;
virtual void evaluate(emethod em,Vector&out,const ConstVector&ys,
const ConstVector&u)const= 0;
virtual void writeMat4(FILE*fd,const char*prefix)const= 0;
virtual DecisionRule*centralizedClone(const Vector&fixpoint)const= 0;
virtual const Vector&getSteady()const= 0;
virtual int nexog()const= 0;
virtual const PartitionY&getYPart()const= 0;
};
/*:3*/
#line 48 "./decision_rule.hweb"
;
/*4:*/
#line 134 "./decision_rule.hweb"
template<int t>
class DecisionRuleImpl:public ctraits<t> ::Tpol,public DecisionRule{
protected:
typedef typename ctraits<t> ::Tpol _Tparent;
const Vector ysteady;
const PartitionY ypart;
const int nu;
public:
DecisionRuleImpl(const _Tparent&pol,const PartitionY&yp,int nuu,
const Vector&ys)
:ctraits<t> ::Tpol(pol),ysteady(ys),ypart(yp),nu(nuu){}
DecisionRuleImpl(_Tparent&pol,const PartitionY&yp,int nuu,
const Vector&ys)
:ctraits<t> ::Tpol(0,yp.ny(),pol),ysteady(ys),ypart(yp),
nu(nuu){}
DecisionRuleImpl(const _Tg&g,const PartitionY&yp,int nuu,
const Vector&ys,double sigma)
:ctraits<t> ::Tpol(yp.ny(),yp.nys()+nuu),ysteady(ys),ypart(yp),nu(nuu)
{fillTensors(g,sigma);}
DecisionRuleImpl(const DecisionRuleImpl<t> &dr,const ConstVector&fixpoint)
:ctraits<t> ::Tpol(dr.ypart.ny(),dr.ypart.nys()+dr.nu),
ysteady(fixpoint),ypart(dr.ypart),nu(dr.nu)
{centralize(dr);}
const Vector&getSteady()const
{return ysteady;}
/*8:*/
#line 290 "./decision_rule.hweb"
TwoDMatrix*simulate(emethod em,int np,const Vector&ystart,
ShockRealization&sr)const
{
KORD_RAISE_IF(ysteady.length()!=ystart.length(),
"Start and steady lengths differ in DecisionRuleImpl::simulate");
TwoDMatrix*res= new TwoDMatrix(ypart.ny(),np);
/*9:*/
#line 309 "./decision_rule.hweb"
Vector dyu(ypart.nys()+nu);
ConstVector ystart_pred(ystart,ypart.nstat,ypart.nys());
ConstVector ysteady_pred(ysteady,ypart.nstat,ypart.nys());
Vector dy(dyu,0,ypart.nys());
Vector u(dyu,ypart.nys(),nu);
/*:9*/
#line 298 "./decision_rule.hweb"
;
/*10:*/
#line 320 "./decision_rule.hweb"
dy= ystart_pred;
dy.add(-1.0,ysteady_pred);
sr.get(0,u);
Vector out(*res,0);
eval(em,out,dyu);
/*:10*/
#line 299 "./decision_rule.hweb"
;
/*11:*/
#line 330 "./decision_rule.hweb"
for(int i= 1;i<np;i++){
ConstVector ym(*res,i-1);
ConstVector dym(ym,ypart.nstat,ypart.nys());
dy= dym;
sr.get(i,u);
Vector out(*res,i);
eval(em,out,dyu);
if(!out.isFinite()){
if(i+1<np){
TwoDMatrix rest(*res,i+1,np-i-1);
rest.zeros();
}
return res;
}
}
/*:11*/
#line 300 "./decision_rule.hweb"
;
/*12:*/
#line 348 "./decision_rule.hweb"
for(int i= 0;i<res->ncols();i++){
Vector col(*res,i);
col.add(1.0,ysteady);
}
/*:12*/
#line 301 "./decision_rule.hweb"
;
return res;
}
/*:8*/
#line 160 "./decision_rule.hweb"
;
/*13:*/
#line 360 "./decision_rule.hweb"
void evaluate(emethod em,Vector&out,const ConstVector&ys,
const ConstVector&u)const
{
KORD_RAISE_IF(ys.length()!=ypart.nys()||u.length()!=nu,
"Wrong dimensions of input vectors in DecisionRuleImpl::evaluate");
KORD_RAISE_IF(out.length()!=ypart.ny(),
"Wrong dimension of output vector in DecisionRuleImpl::evaluate");
ConstVector ysteady_pred(ysteady,ypart.nstat,ypart.nys());
Vector ys_u(ypart.nys()+nu);
Vector ys_u1(ys_u,0,ypart.nys());
ys_u1= ys;
ys_u1.add(-1.0,ysteady_pred);
Vector ys_u2(ys_u,ypart.nys(),nu);
ys_u2= u;
eval(em,out,ys_u);
out.add(1.0,ysteady);
}
/*:13*/
#line 161 "./decision_rule.hweb"
;
/*14:*/
#line 382 "./decision_rule.hweb"
DecisionRule*centralizedClone(const Vector&fixpoint)const
{
return new DecisionRuleImpl<t> (*this,fixpoint);
}
/*:14*/
#line 162 "./decision_rule.hweb"
;
/*16:*/
#line 401 "./decision_rule.hweb"
void writeMat4(FILE*fd,const char*prefix)const
{
ctraits<t> ::Tpol::writeMat4(fd,prefix);
TwoDMatrix dum(ysteady.length(),1);
dum.getData()= ysteady;
char tmp[100];
sprintf(tmp,"%s_ss",prefix);
ConstTwoDMatrix(dum).writeMat4(fd,tmp);
}
/*:16*/
#line 163 "./decision_rule.hweb"
;
int nexog()const
{return nu;}
const PartitionY&getYPart()const
{return ypart;}
protected:
/*5:*/
#line 210 "./decision_rule.hweb"
void fillTensors(const _Tg&g,double sigma)
{
IntSequence tns(2);
tns[0]= ypart.nys();tns[1]= nu;
int dfact= 1;
for(int d= 0;d<=g.getMaxDim();d++,dfact*= d){
_Ttensym*g_yud= new _Ttensym(ypart.ny(),ypart.nys()+nu,d);
g_yud->zeros();
/*6:*/
#line 234 "./decision_rule.hweb"
for(int i= 0;i<=d;i++){
int j= d-i;
int kfact= 1;
_Ttensor tmp(ypart.ny(),
TensorDimens(Symmetry(i,j),tns));
tmp.zeros();
for(int k= 0;k+d<=g.getMaxDim();k++,kfact*= k){
Symmetry sym(i,j,0,k);
if(g.check(sym)){
double mult= pow(sigma,k)/dfact/kfact;
tmp.add(mult,*(g.get(sym)));
}
}
g_yud->addSubTensor(tmp);
}
/*:6*/
#line 219 "./decision_rule.hweb"
;
insert(g_yud);
}
}
/*:5*/
#line 169 "./decision_rule.hweb"
;
/*7:*/
#line 260 "./decision_rule.hweb"
void centralize(const DecisionRuleImpl&dr)
{
Vector dstate(ypart.nys()+nu);
dstate.zeros();
Vector dstate_star(dstate,0,ypart.nys());
ConstVector newsteady_star(ysteady,ypart.nstat,ypart.nys());
ConstVector oldsteady_star(dr.ysteady,ypart.nstat,ypart.nys());
dstate_star.add(1.0,newsteady_star);
dstate_star.add(-1.0,oldsteady_star);
_Tpol pol(dr);
for(int d= 1;d<=dr.getMaxDim();d++){
pol.derivative(d-1);
_Ttensym*der= pol.evalPartially(d,dstate);
insert(der);
}
}
/*:7*/
#line 170 "./decision_rule.hweb"
;
/*15:*/
#line 391 "./decision_rule.hweb"
void eval(emethod em,Vector&out,const ConstVector&v)const
{
if(em==DecisionRule::horner)
_Tparent::evalHorner(out,v);
else
_Tparent::evalTrad(out,v);
}
/*:15*/
#line 171 "./decision_rule.hweb"
;
};
/*:4*/
#line 49 "./decision_rule.hweb"
;
/*17:*/
#line 417 "./decision_rule.hweb"
class UnfoldDecisionRule;
class FoldDecisionRule:public DecisionRuleImpl<KOrder::fold> {
friend class UnfoldDecisionRule;
public:
FoldDecisionRule(const ctraits<KOrder::fold> ::Tpol&pol,const PartitionY&yp,int nuu,
const Vector&ys)
:DecisionRuleImpl<KOrder::fold> (pol,yp,nuu,ys){}
FoldDecisionRule(ctraits<KOrder::fold> ::Tpol&pol,const PartitionY&yp,int nuu,
const Vector&ys)
:DecisionRuleImpl<KOrder::fold> (pol,yp,nuu,ys){}
FoldDecisionRule(const ctraits<KOrder::fold> ::Tg&g,const PartitionY&yp,int nuu,
const Vector&ys,double sigma)
:DecisionRuleImpl<KOrder::fold> (g,yp,nuu,ys,sigma){}
FoldDecisionRule(const DecisionRuleImpl<KOrder::fold> &dr,const ConstVector&fixpoint)
:DecisionRuleImpl<KOrder::fold> (dr,fixpoint){}
FoldDecisionRule(const UnfoldDecisionRule&udr);
};
/*:17*/
#line 50 "./decision_rule.hweb"
;
/*18:*/
#line 440 "./decision_rule.hweb"
class UnfoldDecisionRule:public DecisionRuleImpl<KOrder::unfold> {
friend class FoldDecisionRule;
public:
UnfoldDecisionRule(const ctraits<KOrder::unfold> ::Tpol&pol,const PartitionY&yp,int nuu,
const Vector&ys)
:DecisionRuleImpl<KOrder::unfold> (pol,yp,nuu,ys){}
UnfoldDecisionRule(ctraits<KOrder::unfold> ::Tpol&pol,const PartitionY&yp,int nuu,
const Vector&ys)
:DecisionRuleImpl<KOrder::unfold> (pol,yp,nuu,ys){}
UnfoldDecisionRule(const ctraits<KOrder::unfold> ::Tg&g,const PartitionY&yp,int nuu,
const Vector&ys,double sigma)
:DecisionRuleImpl<KOrder::unfold> (g,yp,nuu,ys,sigma){}
UnfoldDecisionRule(const DecisionRuleImpl<KOrder::unfold> &dr,const ConstVector&fixpoint)
:DecisionRuleImpl<KOrder::unfold> (dr,fixpoint){}
UnfoldDecisionRule(const FoldDecisionRule&udr);
};
/*:18*/
#line 51 "./decision_rule.hweb"
;
/*19:*/
#line 472 "./decision_rule.hweb"
template<int t>
class DRFixPoint:public ctraits<t> ::Tpol{
typedef typename ctraits<t> ::Tpol _Tparent;
static int max_iter;
static int max_newton_iter;
static int newton_pause;
static double tol;
const Vector ysteady;
const PartitionY ypart;
_Tparent*bigf;
_Tparent*bigfder;
public:
typedef typename DecisionRule::emethod emethod;
/*20:*/
#line 511 "./decision_rule.hweb"
DRFixPoint(const _Tg&g,const PartitionY&yp,
const Vector&ys,double sigma)
:ctraits<t> ::Tpol(yp.ny(),yp.nys()),
ysteady(ys),ypart(yp),bigf(NULL),bigfder(NULL)
{
fillTensors(g,sigma);
_Tparent yspol(ypart.nstat,ypart.nys(),*this);
bigf= new _Tparent((const _Tparent&)yspol);
_Ttensym*frst= bigf->get(Symmetry(1));
for(int i= 0;i<ypart.nys();i++)
frst->get(i,i)= frst->get(i,i)-1;
bigfder= new _Tparent(*bigf,0);
}
/*:20*/
#line 486 "./decision_rule.hweb"
;
/*21:*/
#line 527 "./decision_rule.hweb"
virtual~DRFixPoint()
{
if(bigf)
delete bigf;
if(bigfder)
delete bigfder;
}
/*:21*/
#line 487 "./decision_rule.hweb"
;
/*25:*/
#line 650 "./decision_rule.hweb"
bool calcFixPoint(emethod em,Vector&out)
{
KORD_RAISE_IF(out.length()!=ypart.ny(),
"Wrong length of out in DRFixPoint::calcFixPoint");
Vector delta(ypart.nys());
Vector ystar(ypart.nys());
ystar.zeros();
iter= 0;
newton_iter_last= 0;
newton_iter_total= 0;
bool converged= false;
do{
if((iter/newton_pause)*newton_pause==iter)
converged= solveNewton(ystar);
if(!converged){
bigf->evalHorner(delta,ystar);
KORD_RAISE_IF_X(!delta.isFinite(),
"NaN or Inf asserted in DRFixPoint::calcFixPoint",
KORD_FP_NOT_FINITE);
ystar.add(1.0,delta);
converged= delta.getNorm()<tol;
}
iter++;
}while(iter<max_iter&&!converged);
if(converged){
_Tparent::evalHorner(out,ystar);
out.add(1.0,ysteady);
}
return converged;
}
/*:25*/
#line 488 "./decision_rule.hweb"
;
int getNumIter()const
{return iter;}
int getNewtonLastIter()const
{return newton_iter_last;}
int getNewtonTotalIter()const
{return newton_iter_total;}
protected:
/*22:*/
#line 542 "./decision_rule.hweb"
void fillTensors(const _Tg&g,double sigma)
{
int dfact= 1;
for(int d= 0;d<=g.getMaxDim();d++,dfact*= d){
_Ttensym*g_yd= new _Ttensym(ypart.ny(),ypart.nys(),d);
g_yd->zeros();
int kfact= 1;
for(int k= 0;d+k<=g.getMaxDim();k++,kfact*= k){
if(g.check(Symmetry(d,0,0,k))){
const _Ttensor*ten= g.get(Symmetry(d,0,0,k));
double mult= pow(sigma,k)/dfact/kfact;
g_yd->add(mult,*ten);
}
}
insert(g_yd);
}
}
/*:22*/
#line 496 "./decision_rule.hweb"
;
/*23:*/
#line 575 "./decision_rule.hweb"
bool solveNewton(Vector&y)
{
const double urelax_threshold= 1.e-5;
Vector sol((const Vector&)y);
Vector delta(y.length());
newton_iter_last= 0;
bool delta_finite= true;
double flastnorm= 0.0;
double fnorm= 0.0;
bool converged= false;
double urelax= 1.0;
do{
_Ttensym*jacob= bigfder->evalPartially(1,sol);
bigf->evalHorner(delta,sol);
if(newton_iter_last==0)
flastnorm= delta.getNorm();
delta_finite= delta.isFinite();
if(delta_finite){
ConstTwoDMatrix(*jacob).multInvLeft(delta);
/*24:*/
#line 620 "./decision_rule.hweb"
bool urelax_found= false;
urelax= 1.0;
while(!urelax_found&&urelax> urelax_threshold){
Vector soltmp((const Vector&)sol);
soltmp.add(-urelax,delta);
Vector f(sol.length());
bigf->evalHorner(f,soltmp);
fnorm= f.getNorm();
if(fnorm<=flastnorm)
urelax_found= true;
else
urelax*= std::min(0.5,flastnorm/fnorm);
}
/*:24*/
#line 596 "./decision_rule.hweb"
;
sol.add(-urelax,delta);
delta_finite= delta.isFinite();
}
delete jacob;
newton_iter_last++;
converged= delta_finite&&fnorm<tol;
flastnorm= fnorm;
}while(!converged&&newton_iter_last<max_newton_iter
&&urelax> urelax_threshold);
newton_iter_total+= newton_iter_last;
if(!converged)
newton_iter_last= 0;
y= (const Vector&)sol;
return converged;
}
/*:23*/
#line 497 "./decision_rule.hweb"
;
private:
int iter;
int newton_iter_last;
int newton_iter_total;
};
/*:19*/
#line 52 "./decision_rule.hweb"
;
/*26:*/
#line 691 "./decision_rule.hweb"
class ExplicitShockRealization;
class SimResults{
protected:
int num_y;
int num_per;
vector<TwoDMatrix*> data;
vector<ExplicitShockRealization*> shocks;
public:
SimResults(int ny,int nper)
:num_y(ny),num_per(nper){}
virtual~SimResults();
void simulate(int num_sim,const DecisionRule&dr,const Vector&start,
const TwoDMatrix&vcov,Journal&journal);
void simulate(int num_sim,const DecisionRule&dr,const Vector&start,
const TwoDMatrix&vcov);
int getNumPer()const
{return num_per;}
int getNumSets()const
{return(int)data.size();}
const TwoDMatrix&getData(int i)const
{return*(data[i]);}
const ExplicitShockRealization&getShocks(int i)const
{return*(shocks[i]);}
bool addDataSet(TwoDMatrix*d,ExplicitShockRealization*sr);
void writeMat4(const char*base,const char*lname)const;
void writeMat4(FILE*fd,const char*lname)const;
};
/*:26*/
#line 53 "./decision_rule.hweb"
;
/*27:*/
#line 723 "./decision_rule.hweb"
class SimResultsStats:public SimResults{
protected:
Vector mean;
TwoDMatrix vcov;
public:
SimResultsStats(int ny,int nper)
:SimResults(ny,nper),mean(ny),vcov(ny,ny){}
void simulate(int num_sim,const DecisionRule&dr,const Vector&start,
const TwoDMatrix&vcov,Journal&journal);
void writeMat4(FILE*fd,const char*lname)const;
protected:
void calcMean();
void calcVcov();
};
/*:27*/
#line 54 "./decision_rule.hweb"
;
/*28:*/
#line 743 "./decision_rule.hweb"
class SimResultsDynamicStats:public SimResults{
protected:
TwoDMatrix mean;
TwoDMatrix variance;
public:
SimResultsDynamicStats(int ny,int nper)
:SimResults(ny,nper),mean(ny,nper),variance(ny,nper){}
void simulate(int num_sim,const DecisionRule&dr,const Vector&start,
const TwoDMatrix&vcov,Journal&journal);
void writeMat4(FILE*fd,const char*lname)const;
protected:
void calcMean();
void calcVariance();
};
/*:28*/
#line 55 "./decision_rule.hweb"
;
/*29:*/
#line 767 "./decision_rule.hweb"
class SimulationIRFWorker;
class SimResultsIRF:public SimResults{
friend class SimulationIRFWorker;
protected:
const SimResults&control;
int ishock;
double imp;
TwoDMatrix means;
TwoDMatrix variances;
public:
SimResultsIRF(const SimResults&cntl,int ny,int nper,int i,double impulse)
:SimResults(ny,nper),control(cntl),
ishock(i),imp(impulse),
means(ny,nper),variances(ny,nper){}
void simulate(const DecisionRule&dr,const Vector&start,
Journal&journal);
void simulate(const DecisionRule&dr,const Vector&start);
void writeMat4(FILE*fd,const char*lname)const;
protected:
void calcMeans();
void calcVariances();
};
/*:29*/
#line 56 "./decision_rule.hweb"
;
/*30:*/
#line 797 "./decision_rule.hweb"
class RTSimulationWorker;
class RTSimResultsStats{
friend class RTSimulationWorker;
protected:
Vector mean;
TwoDMatrix vcov;
int num_per;
NormalConj nc;
int incomplete_simulations;
int thrown_periods;
public:
RTSimResultsStats(int ny,int nper)
:mean(ny),vcov(ny,ny),
num_per(nper),nc(ny),
incomplete_simulations(0),thrown_periods(0){}
void simulate(int num_sim,const DecisionRule&dr,const Vector&start,
const TwoDMatrix&vcov,Journal&journal);
void simulate(int num_sim,const DecisionRule&dr,const Vector&start,
const TwoDMatrix&vcov);
void writeMat4(FILE*fd,const char*lname);
};
/*:30*/
#line 57 "./decision_rule.hweb"
;
/*31:*/
#line 834 "./decision_rule.hweb"
class DynamicModel;
class IRFResults{
vector<SimResultsIRF*> irf_res;
const DynamicModel&model;
vector<int> irf_list_ind;
public:
IRFResults(const DynamicModel&mod,const DecisionRule&dr,
const SimResults&control,const vector<int> &ili,
Journal&journal);
~IRFResults();
void writeMat4(FILE*fd,const char*prefix)const;
};
/*:31*/
#line 58 "./decision_rule.hweb"
;
/*32:*/
#line 851 "./decision_rule.hweb"
class SimulationWorker:public THREAD{
protected:
SimResults&res;
const DecisionRule&dr;
DecisionRule::emethod em;
int np;
const Vector&st;
ShockRealization&sr;
public:
SimulationWorker(SimResults&sim_res,
const DecisionRule&dec_rule,
DecisionRule::emethod emet,int num_per,
const Vector&start,ShockRealization&shock_r)
:res(sim_res),dr(dec_rule),em(emet),np(num_per),st(start),sr(shock_r){}
void operator()();
};
/*:32*/
#line 59 "./decision_rule.hweb"
;
/*33:*/
#line 874 "./decision_rule.hweb"
class SimulationIRFWorker:public THREAD{
SimResultsIRF&res;
const DecisionRule&dr;
DecisionRule::emethod em;
int np;
const Vector&st;
int idata;
int ishock;
double imp;
public:
SimulationIRFWorker(SimResultsIRF&sim_res,
const DecisionRule&dec_rule,
DecisionRule::emethod emet,int num_per,
const Vector&start,int id,
int ishck,double impulse)
:res(sim_res),dr(dec_rule),em(emet),np(num_per),st(start),
idata(id),ishock(ishck),imp(impulse){}
void operator()();
};
/*:33*/
#line 60 "./decision_rule.hweb"
;
/*34:*/
#line 901 "./decision_rule.hweb"
class RTSimulationWorker:public THREAD{
protected:
RTSimResultsStats&res;
const DecisionRule&dr;
DecisionRule::emethod em;
int np;
const Vector&ystart;
ShockRealization&sr;
public:
RTSimulationWorker(RTSimResultsStats&sim_res,
const DecisionRule&dec_rule,
DecisionRule::emethod emet,int num_per,
const Vector&start,ShockRealization&shock_r)
:res(sim_res),dr(dec_rule),em(emet),np(num_per),ystart(start),sr(shock_r){}
void operator()();
};
/*:34*/
#line 61 "./decision_rule.hweb"
;
/*35:*/
#line 923 "./decision_rule.hweb"
class RandomShockRealization:virtual public ShockRealization{
protected:
MersenneTwister mtwister;
TwoDMatrix factor;
public:
RandomShockRealization(const TwoDMatrix&v,unsigned int iseed)
:mtwister(iseed),factor(v.nrows(),v.nrows())
{schurFactor(v);}
RandomShockRealization(const RandomShockRealization&sr)
:mtwister(sr.mtwister),factor(sr.factor){}
virtual~RandomShockRealization(){}
void get(int n,Vector&out);
int numShocks()const
{return factor.nrows();}
protected:
void choleskyFactor(const TwoDMatrix&v);
void schurFactor(const TwoDMatrix&v);
};
/*:35*/
#line 62 "./decision_rule.hweb"
;
/*36:*/
#line 946 "./decision_rule.hweb"
class ExplicitShockRealization:virtual public ShockRealization{
TwoDMatrix shocks;
public:
ExplicitShockRealization(const TwoDMatrix&sh)
:shocks(sh){}
ExplicitShockRealization(const ExplicitShockRealization&sr)
:shocks(sr.shocks){}
ExplicitShockRealization(ShockRealization&sr,int num_per);
void get(int n,Vector&out);
int numShocks()const
{return shocks.nrows();}
void addToShock(int ishock,int iper,double val);
void print()const
{shocks.print();}
};
/*:36*/
#line 63 "./decision_rule.hweb"
;
/*37:*/
#line 972 "./decision_rule.hweb"
class GenShockRealization:public RandomShockRealization,public ExplicitShockRealization{
public:
GenShockRealization(const TwoDMatrix&v,const TwoDMatrix&sh,int seed)
:RandomShockRealization(v,seed),ExplicitShockRealization(sh)
{
KORD_RAISE_IF(sh.nrows()!=v.nrows()||v.nrows()!=v.ncols(),
"Wrong dimension of input matrix in GenShockRealization constructor");
}
void get(int n,Vector&out);
int numShocks()const
{return RandomShockRealization::numShocks();}
};
/*:37*/
#line 64 "./decision_rule.hweb"
;
#endif
/*:1*/

View File

@ -0,0 +1,65 @@
/*1:*/
#line 6 "./dynamic_model.cweb"
#include "dynamic_model.h"
/*2:*/
#line 14 "./dynamic_model.cweb"
void NameList::print()const
{
for(int i= 0;i<getNum();i++)
printf("%s\n",getName(i));
}
/*:2*/
#line 9 "./dynamic_model.cweb"
;
/*3:*/
#line 22 "./dynamic_model.cweb"
void NameList::writeMat4(FILE*fd,const char*vname)const
{
int maxlen= 0;
for(int i= 0;i<getNum();i++)
if(maxlen<(int)strlen(getName(i)))
maxlen= (int)strlen(getName(i));
if(maxlen==0)
return;
TwoDMatrix m(getNum(),maxlen);
for(int i= 0;i<getNum();i++)
for(int j= 0;j<maxlen;j++)
if(j<(int)strlen(getName(i)))
m.get(i,j)= (double)(getName(i)[j]);
else
m.get(i,j)= (double)(' ');
Mat4Header header(m,vname,"text matrix");
header.write(fd);
fwrite(m.getData().base(),sizeof(double),m.nrows()*m.ncols(),fd);
}
/*:3*/
#line 10 "./dynamic_model.cweb"
;
/*4:*/
#line 47 "./dynamic_model.cweb"
void NameList::writeMat4Indices(FILE*fd,const char*prefix)const
{
char tmp[100];
TwoDMatrix aux(1,1);
for(int i= 0;i<getNum();i++){
sprintf(tmp,"%s_i_%s",prefix,getName(i));
aux.get(0,0)= i+1;
aux.writeMat4(fd,tmp);
}
}
/*:4*/
#line 11 "./dynamic_model.cweb"
;
/*:1*/

View File

@ -0,0 +1,67 @@
/*1:*/
#line 13 "./dynamic_model.hweb"
#ifndef DYNAMIC_MODEL_H
#define DYNAMIC_MODEL_H
#include "t_container.h"
#include "sparse_tensor.h"
#include "Vector.h"
/*2:*/
#line 29 "./dynamic_model.hweb"
class NameList{
public:
virtual~NameList(){}
virtual int getNum()const= 0;
virtual const char*getName(int i)const= 0;
void print()const;
void writeMat4(FILE*fd,const char*vname)const;
void writeMat4Indices(FILE*fd,const char*prefix)const;
};
/*:2*/
#line 22 "./dynamic_model.hweb"
;
/*3:*/
#line 89 "./dynamic_model.hweb"
class DynamicModel{
public:
virtual DynamicModel*clone()const= 0;
virtual~DynamicModel(){}
virtual int nstat()const= 0;
virtual int nboth()const= 0;
virtual int npred()const= 0;
virtual int nforw()const= 0;
virtual int nexog()const= 0;
virtual int order()const= 0;
int numeq()const
{return nstat()+nboth()+npred()+nforw();}
virtual const NameList&getAllEndoNames()const= 0;
virtual const NameList&getStateNames()const= 0;
virtual const NameList&getExogNames()const= 0;
virtual const TwoDMatrix&getVcov()const= 0;
virtual const TensorContainer<FSSparseTensor> &getModelDerivatives()const= 0;
virtual const Vector&getSteady()const= 0;
virtual Vector&getSteady()= 0;
virtual void solveDeterministicSteady()= 0;
virtual void evaluateSystem(Vector&out,const Vector&yy,const Vector&xx)= 0;
virtual void evaluateSystem(Vector&out,const Vector&yym,const Vector&yy,
const Vector&yyp,const Vector&xx)= 0;
virtual void calcDerivativesAtSteady()= 0;
};
/*:3*/
#line 23 "./dynamic_model.hweb"
;
#endif
/*:1*/

View File

@ -0,0 +1,130 @@
/*1:*/
#line 9 "./faa_di_bruno.cweb"
#include "faa_di_bruno.h"
#include "fine_container.h"
#include <math.h>
double FaaDiBruno::magic_mult= 1.5;
/*2:*/
#line 25 "./faa_di_bruno.cweb"
void FaaDiBruno::calculate(const StackContainer<FGSTensor> &cont,
const TensorContainer<FSSparseTensor> &f,
FGSTensor&out)
{
out.zeros();
for(int l= 1;l<=out.dimen();l++){
int mem_mb,p_size_mb;
int max= estimRefinment(out.getDims(),out.nrows(),l,mem_mb,p_size_mb);
FoldedFineContainer fine_cont(cont,max);
fine_cont.multAndAdd(l,f,out);
JournalRecord recc(journal);
recc<<"dim="<<l<<" avmem="<<mem_mb<<" tmpmem="<<p_size_mb<<" max="<<max
<<" stacks="<<cont.numStacks()<<"->"<<fine_cont.numStacks()<<endrec;
}
}
/*:2*/
#line 16 "./faa_di_bruno.cweb"
;
/*3:*/
#line 45 "./faa_di_bruno.cweb"
void FaaDiBruno::calculate(const FoldedStackContainer&cont,const FGSContainer&g,
FGSTensor&out)
{
out.zeros();
for(int l= 1;l<=out.dimen();l++){
long int mem= SystemResources::availableMemory();
cont.multAndAdd(l,g,out);
JournalRecord rec(journal);
int mem_mb= mem/1024/1024;
rec<<"dim="<<l<<" avmem="<<mem_mb<<endrec;
}
}
/*:3*/
#line 17 "./faa_di_bruno.cweb"
;
/*4:*/
#line 63 "./faa_di_bruno.cweb"
void FaaDiBruno::calculate(const StackContainer<UGSTensor> &cont,
const TensorContainer<FSSparseTensor> &f,
UGSTensor&out)
{
out.zeros();
for(int l= 1;l<=out.dimen();l++){
int mem_mb,p_size_mb;
int max= estimRefinment(out.getDims(),out.nrows(),l,mem_mb,p_size_mb);
UnfoldedFineContainer fine_cont(cont,max);
fine_cont.multAndAdd(l,f,out);
JournalRecord recc(journal);
recc<<"dim="<<l<<" avmem="<<mem_mb<<" tmpmem="<<p_size_mb<<" max="<<max
<<" stacks="<<cont.numStacks()<<"->"<<fine_cont.numStacks()<<endrec;
}
}
/*:4*/
#line 18 "./faa_di_bruno.cweb"
;
/*5:*/
#line 81 "./faa_di_bruno.cweb"
void FaaDiBruno::calculate(const UnfoldedStackContainer&cont,const UGSContainer&g,
UGSTensor&out)
{
out.zeros();
for(int l= 1;l<=out.dimen();l++){
long int mem= SystemResources::availableMemory();
cont.multAndAdd(l,g,out);
JournalRecord rec(journal);
int mem_mb= mem/1024/1024;
rec<<"dim="<<l<<" avmem="<<mem_mb<<endrec;
}
}
/*:5*/
#line 19 "./faa_di_bruno.cweb"
;
/*6:*/
#line 126 "./faa_di_bruno.cweb"
int FaaDiBruno::estimRefinment(const TensorDimens&tdims,int nr,int l,
int&avmem_mb,int&tmpmem_mb)
{
int nthreads= THREAD_GROUP::max_parallel_threads;
long int per_size1= tdims.calcUnfoldMaxOffset();
long int per_size2= (long int)pow((double)tdims.getNVS().getMax(),l);
double lambda= 0.0;
long int per_size= sizeof(double)*nr
*(long int)(lambda*per_size1+(1-lambda)*per_size2);
long int mem= SystemResources::availableMemory();
int max= 0;
double num_cols= ((double)(mem-magic_mult*nthreads*per_size))
/nthreads/sizeof(double)/nr;
if(num_cols> 0){
double maxd= pow(num_cols,((double)1)/l);
max= (int)floor(maxd);
}
if(max==0){
max= 10;
JournalRecord rec(journal);
rec<<"dim="<<l<<" run out of memory, imposing max="<<max;
if(nthreads> 1)
rec<<" (decrease number of threads)";
rec<<endrec;
}
avmem_mb= mem/1024/1024;
tmpmem_mb= (nthreads*per_size)/1024/1024;
return max;
}
/*:6*/
#line 20 "./faa_di_bruno.cweb"
;
/*:1*/

View File

@ -0,0 +1,40 @@
/*1:*/
#line 13 "./faa_di_bruno.hweb"
#ifndef FAA_DI_BRUNO_H
#define FAA_DI_BRUNO_H
#include "journal.h"
#include "stack_container.h"
#include "t_container.h"
#include "sparse_tensor.h"
#include "gs_tensor.h"
/*2:*/
#line 30 "./faa_di_bruno.hweb"
class FaaDiBruno{
Journal&journal;
public:
FaaDiBruno(Journal&jr)
:journal(jr){}
void calculate(const StackContainer<FGSTensor> &cont,const TensorContainer<FSSparseTensor> &f,
FGSTensor&out);
void calculate(const FoldedStackContainer&cont,const FGSContainer&g,
FGSTensor&out);
void calculate(const StackContainer<UGSTensor> &cont,const TensorContainer<FSSparseTensor> &f,
UGSTensor&out);
void calculate(const UnfoldedStackContainer&cont,const UGSContainer&g,
UGSTensor&out);
protected:
int estimRefinment(const TensorDimens&tdims,int nr,int l,int&avmem_mb,int&tmpmem_mb);
static double magic_mult;
};
/*:2*/
#line 23 "./faa_di_bruno.hweb"
;
#endif
/*:1*/

View File

@ -0,0 +1,233 @@
/*1:*/
#line 6 "./first_order.cweb"
#include "kord_exception.h"
#include "first_order.h"
#include "cpplapack.h"
/*2:*/
#line 20 "./first_order.cweb"
int order_eigs(const double*alphar,const double*alphai,const double*beta)
{
return(*alphar**alphar+*alphai**alphai<*beta**beta);
}
/*:2*/
#line 12 "./first_order.cweb"
;
/*3:*/
#line 40 "./first_order.cweb"
void FirstOrder::solve(const TwoDMatrix&fd)
{
JournalRecordPair pa(journal);
pa<<"Recovering first order derivatives "<<endrec;
/*4:*/
#line 132 "./first_order.cweb"
/*5:*/
#line 145 "./first_order.cweb"
int off= 0;
ConstTwoDMatrix fyplus(fd,off,ypart.nyss());
off+= ypart.nyss();
ConstTwoDMatrix fyszero(fd,off,ypart.nstat);
off+= ypart.nstat;
ConstTwoDMatrix fypzero(fd,off,ypart.npred);
off+= ypart.npred;
ConstTwoDMatrix fybzero(fd,off,ypart.nboth);
off+= ypart.nboth;
ConstTwoDMatrix fyfzero(fd,off,ypart.nforw);
off+= ypart.nforw;
ConstTwoDMatrix fymins(fd,off,ypart.nys());
off+= ypart.nys();
ConstTwoDMatrix fuzero(fd,off,nu);
off+= nu;
/*:5*/
#line 133 "./first_order.cweb"
;
/*6:*/
#line 163 "./first_order.cweb"
int n= ypart.ny()+ypart.nboth;
TwoDMatrix matD(n,n);
matD.zeros();
matD.place(fypzero,0,0);
matD.place(fybzero,0,ypart.npred);
matD.place(fyplus,0,ypart.nys()+ypart.nstat);
for(int i= 0;i<ypart.nboth;i++)
matD.get(ypart.ny()+i,ypart.npred+i)= 1.0;
/*:6*/
#line 134 "./first_order.cweb"
;
/*7:*/
#line 175 "./first_order.cweb"
TwoDMatrix matE(n,n);
matE.zeros();
matE.place(fymins,0,0);
matE.place(fyszero,0,ypart.nys());
matE.place(fyfzero,0,ypart.nys()+ypart.nstat+ypart.nboth);
for(int i= 0;i<ypart.nboth;i++)
matE.get(ypart.ny()+i,ypart.nys()+ypart.nstat+i)= -1.0;
matE.mult(-1.0);
/*:7*/
#line 135 "./first_order.cweb"
;
/*8:*/
#line 186 "./first_order.cweb"
TwoDMatrix vsl(n,n);
TwoDMatrix vsr(n,n);
int lwork= 100*n+16;
Vector work(lwork);
IntSequence bwork(n);
int info;
LAPACK_dgges("N","V","S",order_eigs,&n,matE.getData().base(),&n,
matD.getData().base(),&n,&sdim,alphar.base(),alphai.base(),
beta.base(),vsl.getData().base(),&n,vsr.getData().base(),&n,
work.base(),&lwork,&(bwork[0]),&info);
bk_cond= (sdim==ypart.nys());
/*:8*/
#line 136 "./first_order.cweb"
;
/*9:*/
#line 201 "./first_order.cweb"
ConstGeneralMatrix z11(vsr,0,0,ypart.nys(),ypart.nys());
ConstGeneralMatrix z12(vsr,0,ypart.nys(),ypart.nys(),n-ypart.nys());
ConstGeneralMatrix z21(vsr,ypart.nys(),0,n-ypart.nys(),ypart.nys());
ConstGeneralMatrix z22(vsr,ypart.nys(),ypart.nys(),n-ypart.nys(),n-ypart.nys());
/*:9*/
#line 137 "./first_order.cweb"
;
/*10:*/
#line 208 "./first_order.cweb"
GeneralMatrix sfder(z12,"transpose");
z22.multInvLeftTrans(sfder);
sfder.mult(-1);
/*:10*/
#line 138 "./first_order.cweb"
;
/*11:*/
#line 217 "./first_order.cweb"
ConstGeneralMatrix s11(matE,0,0,ypart.nys(),ypart.nys());
ConstGeneralMatrix t11(matD,0,0,ypart.nys(),ypart.nys());
GeneralMatrix dumm(s11,"transpose");
z11.multInvLeftTrans(dumm);
GeneralMatrix preder(dumm,"transpose");
t11.multInvLeft(preder);
preder.multLeft(z11);
/*:11*/
#line 139 "./first_order.cweb"
;
/*12:*/
#line 227 "./first_order.cweb"
gy.place(preder,ypart.nstat,0);
GeneralMatrix sder(sfder,0,0,ypart.nstat,ypart.nys());
gy.place(sder,0,0);
GeneralMatrix fder(sfder,ypart.nstat+ypart.nboth,0,ypart.nforw,ypart.nys());
gy.place(fder,ypart.nstat+ypart.nys(),0);
/*:12*/
#line 140 "./first_order.cweb"
;
/*13:*/
#line 235 "./first_order.cweb"
GeneralMatrix bder((const GeneralMatrix&)sfder,ypart.nstat,0,ypart.nboth,ypart.nys());
GeneralMatrix bder2(preder,ypart.npred,0,ypart.nboth,ypart.nys());
bder.add(-1,bder2);
b_error= bder.getData().getMax();
/*:13*/
#line 141 "./first_order.cweb"
;
/*:4*/
#line 46 "./first_order.cweb"
;
/*14:*/
#line 255 "./first_order.cweb"
GeneralMatrix matA(ypart.ny(),ypart.ny());
matA.zeros();
ConstGeneralMatrix gss(gy,ypart.nstat+ypart.npred,0,ypart.nyss(),ypart.nys());
GeneralMatrix aux(fyplus,gss);
matA.place(aux,0,ypart.nstat);
ConstGeneralMatrix fyzero(fd,0,ypart.nyss(),ypart.ny(),ypart.ny());
matA.add(1.0,fyzero);
gu.zeros();
gu.add(-1.0,fuzero);
ConstGeneralMatrix(matA).multInvLeft(gu);
/*:14*/
#line 47 "./first_order.cweb"
;
journalEigs();
if(!gy.isFinite()||!gu.isFinite()){
throw KordException(__FILE__,__LINE__,
"NaN or Inf asserted in first order derivatives in FirstOrder::solve");
}
}
/*:3*/
#line 13 "./first_order.cweb"
;
/*15:*/
#line 268 "./first_order.cweb"
void FirstOrder::journalEigs()
{
if(bk_cond){
JournalRecord jr(journal);
jr<<"Blanchard-Kahn conditition satisfied, model stable"<<endrec;
}else{
JournalRecord jr(journal);
jr<<"Blanchard-Kahn condition not satisfied, model not stable: sdim="<<sdim
<<" "<<"npred="<<ypart.nys()<<endrec;
}
if(!bk_cond){
for(int i= 0;i<alphar.length();i++){
if(i==sdim||i==ypart.nys()){
JournalRecord jr(journal);
jr<<"---------------------------------------------------- ";
if(i==sdim)
jr<<"sdim";
else
jr<<"npred";
jr<<endrec;
}
JournalRecord jr(journal);
double mod= sqrt(alphar[i]*alphar[i]+alphai[i]*alphai[i]);
mod= mod/round(100000*std::abs(beta[i]))*100000;
jr<<i<<"\t("<<alphar[i]<<","<<alphai[i]<<") / "<<beta[i]
<<" \t"<<mod<<endrec;
}
}
}
/*:15*/
#line 14 "./first_order.cweb"
;
/*:1*/

View File

@ -0,0 +1,80 @@
/*1:*/
#line 10 "./first_order.hweb"
#ifndef FIRST_ORDER_H
#define FIRST_ORDER_H
#include "korder.h"
/*2:*/
#line 23 "./first_order.hweb"
template<int> class FirstOrderDerivs;
class FirstOrder{
template<int> friend class FirstOrderDerivs;
PartitionY ypart;
int nu;
TwoDMatrix gy;
TwoDMatrix gu;
bool bk_cond;
double b_error;
int sdim;
Vector alphar;
Vector alphai;
Vector beta;
Journal&journal;
public:
FirstOrder(int num_stat,int num_pred,int num_both,int num_forw,
int num_u,const FSSparseTensor&f,Journal&jr)
:ypart(num_stat,num_pred,num_both,num_forw),
nu(num_u),
gy(ypart.ny(),ypart.nys()),
gu(ypart.ny(),nu),
alphar(ypart.ny()+ypart.nboth),
alphai(ypart.ny()+ypart.nboth),
beta(ypart.ny()+ypart.nboth),
journal(jr)
{solve(FFSTensor(f));}
bool isStable()const
{return bk_cond;}
const TwoDMatrix&getGy()const
{return gy;}
const TwoDMatrix&getGu()const
{return gu;}
protected:
void solve(const TwoDMatrix&f);
void journalEigs();
};
/*:2*/
#line 17 "./first_order.hweb"
;
/*3:*/
#line 64 "./first_order.hweb"
template<int t>
class FirstOrderDerivs:public ctraits<t> ::Tg{
public:
FirstOrderDerivs(const FirstOrder&fo)
:ctraits<t> ::Tg(4)
{
IntSequence nvs(4);
nvs[0]= fo.ypart.nys();nvs[1]= fo.nu;nvs[2]= fo.nu;nvs[3]= 1;
_Ttensor*ten= new _Ttensor(fo.ypart.ny(),TensorDimens(Symmetry(1,0,0,0),nvs));
ten->zeros();ten->add(1.0,fo.gy);
insert(ten);
ten= new _Ttensor(fo.ypart.ny(),TensorDimens(Symmetry(0,1,0,0),nvs));
ten->zeros();ten->add(1.0,fo.gu);
insert(ten);
}
};
/*:3*/
#line 18 "./first_order.hweb"
;
#endif
/*:1*/

View File

@ -0,0 +1,469 @@
/*1:*/
#line 6 "./global_check.cweb"
#include "SymSchurDecomp.h"
#include "global_check.h"
#include "smolyak.h"
#include "product.h"
#include "quasi_mcarlo.h"
#include "cpplapack.h"
/*2:*/
#line 31 "./global_check.cweb"
ResidFunction::ResidFunction(const Approximation&app)
:VectorFunction(app.getModel().nexog(),app.getModel().numeq()),approx(app),
model(app.getModel().clone()),
yplus(NULL),ystar(NULL),u(NULL),hss(NULL)
{
}
/*:2*/
#line 17 "./global_check.cweb"
;
/*3:*/
#line 40 "./global_check.cweb"
ResidFunction::ResidFunction(const ResidFunction&rf)
:VectorFunction(rf),approx(rf.approx),model(rf.model->clone()),
yplus(NULL),ystar(NULL),u(NULL),hss(NULL)
{
if(rf.yplus)
yplus= new Vector(*(rf.yplus));
if(rf.ystar)
ystar= new Vector(*(rf.ystar));
if(rf.u)
u= new Vector(*(rf.u));
if(rf.hss)
hss= new FTensorPolynomial(*(rf.hss));
}
/*:3*/
#line 18 "./global_check.cweb"
;
/*4:*/
#line 57 "./global_check.cweb"
ResidFunction::~ResidFunction()
{
delete model;
/*5:*/
#line 65 "./global_check.cweb"
if(yplus)
delete yplus;
if(ystar)
delete ystar;
if(u)
delete u;
if(hss)
delete hss;
/*:5*/
#line 61 "./global_check.cweb"
;
}
/*:4*/
#line 19 "./global_check.cweb"
;
/*6:*/
#line 79 "./global_check.cweb"
void ResidFunction::setYU(const Vector&ys,const Vector&xx)
{
/*5:*/
#line 65 "./global_check.cweb"
if(yplus)
delete yplus;
if(ystar)
delete ystar;
if(u)
delete u;
if(hss)
delete hss;
/*:5*/
#line 82 "./global_check.cweb"
;
ystar= new Vector(ys);
u= new Vector(xx);
yplus= new Vector(model->numeq());
approx.getFoldDecisionRule().evaluate(DecisionRule::horner,
*yplus,*ystar,*u);
/*7:*/
#line 103 "./global_check.cweb"
union{const FoldDecisionRule*c;FoldDecisionRule*n;}dr;
dr.c= &(approx.getFoldDecisionRule());
FTensorPolynomial dr_ss(model->nstat()+model->npred(),model->nboth()+model->nforw(),
*(dr.n));
/*:7*/
#line 90 "./global_check.cweb"
;
/*8:*/
#line 110 "./global_check.cweb"
Vector ytmp_star(ConstVector(*yplus,model->nstat(),model->npred()+model->nboth()));
ConstVector ysteady_star(dr.c->getSteady(),model->nstat(),
model->npred()+model->nboth());
ytmp_star.add(-1.0,ysteady_star);
/*:8*/
#line 91 "./global_check.cweb"
;
/*9:*/
#line 117 "./global_check.cweb"
hss= new FTensorPolynomial(dr_ss,ytmp_star);
ConstVector ysteady_ss(dr.c->getSteady(),model->nstat()+model->npred(),
model->nboth()+model->nforw());
if(hss->check(Symmetry(0))){
hss->get(Symmetry(0))->getData().add(1.0,ysteady_ss);
}else{
FFSTensor*ten= new FFSTensor(hss->nrows(),hss->nvars(),0);
ten->getData()= ysteady_ss;
hss->insert(ten);
}
/*:9*/
#line 92 "./global_check.cweb"
;
}
/*:6*/
#line 20 "./global_check.cweb"
;
/*10:*/
#line 132 "./global_check.cweb"
void ResidFunction::eval(const Vector&point,const ParameterSignal&sig,Vector&out)
{
KORD_RAISE_IF(point.length()!=hss->nvars(),
"Wrong dimension of input vector in ResidFunction::eval");
KORD_RAISE_IF(out.length()!=model->numeq(),
"Wrong dimension of output vector in ResidFunction::eval");
Vector yss(hss->nrows());
hss->evalHorner(yss,point);
model->evaluateSystem(out,*ystar,*yplus,yss,*u);
}
/*:10*/
#line 21 "./global_check.cweb"
;
/*11:*/
#line 148 "./global_check.cweb"
void GlobalChecker::check(const Quadrature&quad,int level,
const ConstVector&ys,const ConstVector&x,Vector&out)
{
for(int ifunc= 0;ifunc<vfs.getNum();ifunc++)
((GResidFunction&)(vfs.getFunc(ifunc))).setYU(ys,x);
quad.integrate(vfs,level,out);
}
/*:11*/
#line 22 "./global_check.cweb"
;
/*12:*/
#line 165 "./global_check.cweb"
void GlobalChecker::check(int max_evals,const ConstTwoDMatrix&y,
const ConstTwoDMatrix&x,TwoDMatrix&out)
{
JournalRecordPair pa(journal);
pa<<"Checking approximation error for "<<y.ncols()
<<" states with at most "<<max_evals<<" evaluations"<<endrec;
/*13:*/
#line 182 "./global_check.cweb"
GaussHermite gh;
SmolyakQuadrature dummy_sq(model.nexog(),1,gh);
int smol_evals;
int smol_level;
dummy_sq.designLevelForEvals(max_evals,smol_level,smol_evals);
ProductQuadrature dummy_pq(model.nexog(),gh);
int prod_evals;
int prod_level;
dummy_pq.designLevelForEvals(max_evals,prod_level,prod_evals);
bool take_smolyak= (smol_evals<prod_evals)&&(smol_level>=prod_level-1);
/*:13*/
#line 173 "./global_check.cweb"
;
Quadrature*quad;
int lev;
/*14:*/
#line 198 "./global_check.cweb"
if(take_smolyak){
quad= new SmolyakQuadrature(model.nexog(),smol_level,gh);
lev= smol_level;
JournalRecord rec(journal);
rec<<"Selected Smolyak (level,evals)=("<<smol_level<<","
<<smol_evals<<") over product ("<<prod_level<<","
<<prod_evals<<")"<<endrec;
}else{
quad= new ProductQuadrature(model.nexog(),gh);
lev= prod_level;
JournalRecord rec(journal);
rec<<"Selected product (level,evals)=("<<prod_level<<","
<<prod_evals<<") over Smolyak ("<<smol_level<<","
<<smol_evals<<")"<<endrec;
}
/*:14*/
#line 176 "./global_check.cweb"
;
/*15:*/
#line 216 "./global_check.cweb"
int first_row= (y.nrows()==model.numeq())?model.nstat():0;
ConstTwoDMatrix ysmat(y,first_row,0,model.npred()+model.nboth(),y.ncols());
for(int j= 0;j<y.ncols();j++){
ConstVector yj(ysmat,j);
ConstVector xj(x,j);
Vector outj(out,j);
check(*quad,lev,yj,xj,outj);
}
/*:15*/
#line 177 "./global_check.cweb"
;
delete quad;
}
/*:12*/
#line 23 "./global_check.cweb"
;
/*16:*/
#line 233 "./global_check.cweb"
void GlobalChecker::checkAlongShocksAndSave(FILE*fd,const char*prefix,
int m,double mult,int max_evals)
{
JournalRecordPair pa(journal);
pa<<"Calculating errors along shocks +/- "
<<mult<<" std errors, granularity "<<m<<endrec;
/*17:*/
#line 250 "./global_check.cweb"
TwoDMatrix y_mat(model.numeq(),2*m*model.nexog()+1);
for(int j= 0;j<2*m*model.nexog()+1;j++){
Vector yj(y_mat,j);
yj= (const Vector&)model.getSteady();
}
/*:17*/
#line 240 "./global_check.cweb"
;
/*18:*/
#line 258 "./global_check.cweb"
TwoDMatrix exo_mat(model.nexog(),2*m*model.nexog()+1);
exo_mat.zeros();
for(int ishock= 0;ishock<model.nexog();ishock++){
double max_sigma= sqrt(model.getVcov().get(ishock,ishock));
for(int j= 0;j<2*m;j++){
int jmult= (j<m)?j-m:j-m+1;
exo_mat.get(ishock,1+2*m*ishock+j)=
mult*jmult*max_sigma/m;
}
}
/*:18*/
#line 241 "./global_check.cweb"
;
TwoDMatrix errors(model.numeq(),2*m*model.nexog()+1);
check(max_evals,y_mat,exo_mat,errors);
/*19:*/
#line 271 "./global_check.cweb"
TwoDMatrix res(model.nexog(),2*m+1);
JournalRecord rec(journal);
rec<<"Shock value error"<<endrec;
ConstVector err0(errors,0);
char shock[9];
char erbuf[17];
for(int ishock= 0;ishock<model.nexog();ishock++){
TwoDMatrix err_out(model.numeq(),2*m+1);
sprintf(shock,"%-8s",model.getExogNames().getName(ishock));
for(int j= 0;j<2*m+1;j++){
int jj;
Vector error(err_out,j);
if(j!=m){
if(j<m)
jj= 1+2*m*ishock+j;
else
jj= 1+2*m*ishock+j-1;
ConstVector coljj(errors,jj);
error= coljj;
}else{
jj= 0;
error= err0;
}
JournalRecord rec1(journal);
sprintf(erbuf,"%12.7g ",error.getMax());
rec1<<shock<<" "<<exo_mat.get(ishock,jj)
<<"\t"<<erbuf<<endrec;
}
char tmp[100];
sprintf(tmp,"%s_shock_%s_errors",prefix,model.getExogNames().getName(ishock));
err_out.writeMat4(fd,tmp);
}
/*:19*/
#line 246 "./global_check.cweb"
;
}
/*:16*/
#line 24 "./global_check.cweb"
;
/*20:*/
#line 320 "./global_check.cweb"
void GlobalChecker::checkOnEllipseAndSave(FILE*fd,const char*prefix,
int m,double mult,int max_evals)
{
JournalRecordPair pa(journal);
pa<<"Calculating errors at "<<m
<<" ellipse points scaled by "<<mult<<endrec;
/*21:*/
#line 338 "./global_check.cweb"
TwoDMatrix*ycov= approx.calcYCov();
TwoDMatrix ycovpred((const TwoDMatrix&)*ycov,model.nstat(),model.nstat(),
model.npred()+model.nboth(),model.npred()+model.nboth());
delete ycov;
SymSchurDecomp ssd(ycovpred);
ssd.correctDefinitness(1.e-05);
TwoDMatrix ycovfac(ycovpred.nrows(),ycovpred.ncols());
KORD_RAISE_IF(!ssd.isPositiveSemidefinite(),
"Covariance matrix of the states not positive \
semidefinite in GlobalChecker::checkOnEllipseAndSave");
ssd.getFactor(ycovfac);
/*:21*/
#line 327 "./global_check.cweb"
;
/*22:*/
#line 363 "./global_check.cweb"
int d= model.npred()+model.nboth()-1;
TwoDMatrix ymat(model.npred()+model.nboth(),(d==0)?2:m);
if(d==0){
ymat.get(0,0)= 1;
ymat.get(0,1)= -1;
}else{
int icol= 0;
ReversePerScheme ps;
QMCarloCubeQuadrature qmc(d,m,ps);
qmcpit beg= qmc.start(m);
qmcpit end= qmc.end(m);
for(qmcpit run= beg;run!=end;++run,icol++){
Vector ycol(ymat,icol);
Vector x(run.point());
x.mult(2*M_PI);
ycol[0]= 1;
for(int i= 0;i<d;i++){
Vector subsphere(ycol,0,i+1);
subsphere.mult(cos(x[i]));
ycol[i+1]= sin(x[i]);
}
}
}
/*:22*/
#line 328 "./global_check.cweb"
;
/*23:*/
#line 392 "./global_check.cweb"
TwoDMatrix umat(model.nexog(),ymat.ncols());
umat.zeros();
ymat.mult(mult);
ymat.multLeft(ycovfac);
ConstVector ys(model.getSteady(),model.nstat(),
model.npred()+model.nboth());
for(int icol= 0;icol<ymat.ncols();icol++){
Vector ycol(ymat,icol);
ycol.add(1.0,ys);
}
/*:23*/
#line 329 "./global_check.cweb"
;
/*24:*/
#line 405 "./global_check.cweb"
TwoDMatrix out(model.numeq(),ymat.ncols());
check(max_evals,ymat,umat,out);
char tmp[100];
sprintf(tmp,"%s_ellipse_points",prefix);
ymat.writeMat4(fd,tmp);
sprintf(tmp,"%s_ellipse_errors",prefix);
out.writeMat4(fd,tmp);
/*:24*/
#line 330 "./global_check.cweb"
;
}
/*:20*/
#line 25 "./global_check.cweb"
;
/*25:*/
#line 418 "./global_check.cweb"
void GlobalChecker::checkAlongSimulationAndSave(FILE*fd,const char*prefix,
int m,int max_evals)
{
JournalRecordPair pa(journal);
pa<<"Calculating errors at "<<m
<<" simulated points"<<endrec;
RandomShockRealization sr(model.getVcov(),system_random_generator.int_uniform());
TwoDMatrix*y= approx.getFoldDecisionRule().simulate(DecisionRule::horner,
m,model.getSteady(),sr);
TwoDMatrix x(model.nexog(),m);
x.zeros();
TwoDMatrix out(model.numeq(),m);
check(max_evals,*y,x,out);
char tmp[100];
sprintf(tmp,"%s_simul_points",prefix);
y->writeMat4(fd,tmp);
sprintf(tmp,"%s_simul_errors",prefix);
out.writeMat4(fd,tmp);
delete y;
}
/*:25*/
#line 26 "./global_check.cweb"
;
/*:1*/

View File

@ -0,0 +1,104 @@
/*1:*/
#line 49 "./global_check.hweb"
#ifndef GLOBAL_CHECK_H
#define GLOBAL_CHECK_H
#include "vector_function.h"
#include "quadrature.h"
#include "dynamic_model.h"
#include "journal.h"
#include "approximation.h"
/*2:*/
#line 85 "./global_check.hweb"
class ResidFunction:public VectorFunction{
protected:
const Approximation&approx;
DynamicModel*model;
Vector*yplus;
Vector*ystar;
Vector*u;
FTensorPolynomial*hss;
public:
ResidFunction(const Approximation&app);
ResidFunction(const ResidFunction&rf);
virtual~ResidFunction();
virtual VectorFunction*clone()const
{return new ResidFunction(*this);}
virtual void eval(const Vector&point,const ParameterSignal&sig,Vector&out);
void setYU(const Vector&ys,const Vector&xx);
};
/*:2*/
#line 60 "./global_check.hweb"
;
/*3:*/
#line 106 "./global_check.hweb"
class GResidFunction:public GaussConverterFunction{
public:
GResidFunction(const Approximation&app)
:GaussConverterFunction(new ResidFunction(app),app.getModel().getVcov()){}
GResidFunction(const GResidFunction&rf)
:GaussConverterFunction(rf){}
virtual~GResidFunction(){}
virtual VectorFunction*clone()const
{return new GResidFunction(*this);}
void setYU(const Vector&ys,const Vector&xx)
{((ResidFunction*)func)->setYU(ys,xx);}
};
/*:3*/
#line 61 "./global_check.hweb"
;
/*4:*/
#line 133 "./global_check.hweb"
class GlobalChecker{
const Approximation&approx;
const DynamicModel&model;
Journal&journal;
GResidFunction rf;
VectorFunctionSet vfs;
public:
GlobalChecker(const Approximation&app,int n,Journal&jr)
:approx(app),model(approx.getModel()),journal(jr),
rf(approx),vfs(rf,n){}
void check(int max_evals,const ConstTwoDMatrix&y,
const ConstTwoDMatrix&x,TwoDMatrix&out);
void checkAlongShocksAndSave(FILE*fd,const char*prefix,
int m,double mult,int max_evals);
void checkOnEllipseAndSave(FILE*fd,const char*prefix,
int m,double mult,int max_evals);
void checkAlongSimulationAndSave(FILE*fd,const char*prefix,
int m,int max_evals);
void checkUnconditionalAndSave(FILE*fd,const char*prefix,
int m,int max_evals);
protected:
void check(const Quadrature&quad,int level,
const ConstVector&y,const ConstVector&x,Vector&out);
};
/*:4*/
#line 62 "./global_check.hweb"
;
/*5:*/
#line 161 "./global_check.hweb"
class ResidFunctionSig:public ResidFunction{
public:
ResidFunctionSig(const Approximation&app,const Vector&ys,const Vector&xx);
};
/*:5*/
#line 63 "./global_check.hweb"
;
#endif
/*:1*/

View File

@ -0,0 +1,360 @@
#define _W32_FT_OFFSET (116444736000000000LL)
/*1:*/
#line 6 "./journal.cweb"
#include "journal.h"
#include "kord_exception.h"
#ifndef __MINGW32__
# include <sys/resource.h>
# include <sys/utsname.h>
#endif
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
SystemResources _sysres;
#ifdef __MINGW32__
/*16:*/
#line 249 "./journal.cweb"
typedef struct _filetime{
unsigned long dwLowDateTime;
unsigned long dwHighDateTime;
}filetime;
extern"C"{
void __stdcall GetSystemTimeAsFileTime(filetime*);
};
typedef union{
long long ns100;
filetime ft;
}w32_ftv;
void D_gettimeofday(struct timeval*p,struct timezone*tz)
{
w32_ftv _now;
GetSystemTimeAsFileTime(&(_now.ft));
p->tv_usec= (long)((_now.ns100/10LL)%1000000LL);
p->tv_sec= (long)((_now.ns100-_W32_FT_OFFSET)/10000000LL);
return;
}
/*:16*/
#line 20 "./journal.cweb"
;
/*17:*/
#line 282 "./journal.cweb"
#define _SC_PAGESIZE 1
#define _SC_PHYS_PAGES 2
#define _SC_AVPHYS_PAGES 3
#define _SC_NPROCESSORS_ONLN 4
struct Win32MemoryStatus{
unsigned long dwLength;
unsigned long dwMemoryLoad;
unsigned int dwTotalPhys;
unsigned int dwAvailPhys;
unsigned int dwTotalPageFile;
unsigned int dwAvailPageFile;
unsigned int dwTotalVirtual;
unsigned int dwAvailVirtual;
Win32MemoryStatus();
};
extern"C"{
void __stdcall GlobalMemoryStatus(Win32MemoryStatus*);
};
Win32MemoryStatus::Win32MemoryStatus()
{
dwLength= sizeof(Win32MemoryStatus);
GlobalMemoryStatus(this);
}
long sysconf(int name)
{
switch(name){
case _SC_PAGESIZE:
return 1024;
case _SC_PHYS_PAGES:
{
Win32MemoryStatus memstat;
return memstat.dwTotalPhys/1024;
}
case _SC_AVPHYS_PAGES:
{
Win32MemoryStatus memstat;
return memstat.dwAvailPhys/1024;
}
case _SC_NPROCESSORS_ONLN:
return-1;
default:
KORD_RAISE("Not implemented in Win32 sysconf.");
return-1;
}
}
/*:17*/
#line 21 "./journal.cweb"
;
#endif
/*2:*/
#line 40 "./journal.cweb"
SystemResources::SystemResources()
{
D_gettimeofday(&start,NULL);
}
/*:2*/
#line 24 "./journal.cweb"
;
/*3:*/
#line 48 "./journal.cweb"
long int SystemResources::pageSize()
{
return sysconf(_SC_PAGESIZE);
}
/*:3*/
#line 25 "./journal.cweb"
;
/*4:*/
#line 55 "./journal.cweb"
long int SystemResources::physicalPages()
{
return sysconf(_SC_PHYS_PAGES);
}
/*:4*/
#line 26 "./journal.cweb"
;
/*5:*/
#line 62 "./journal.cweb"
long int SystemResources::onlineProcessors()
{
return sysconf(_SC_NPROCESSORS_ONLN);
}
/*:5*/
#line 27 "./journal.cweb"
;
/*6:*/
#line 69 "./journal.cweb"
long int SystemResources::availableMemory()
{
return pageSize()*sysconf(_SC_AVPHYS_PAGES);
}
/*:6*/
#line 28 "./journal.cweb"
;
/*7:*/
#line 78 "./journal.cweb"
void SystemResources::getRUS(double&load_avg,long int&pg_avail,
double&utime,double&stime,double&elapsed,
long int&idrss,long int&majflt)
{
struct timeval now;
D_gettimeofday(&now,NULL);
elapsed= now.tv_sec-start.tv_sec+(now.tv_usec-start.tv_usec)*1.0e-6;
#ifndef __MINGW32__
struct rusage rus;
getrusage(RUSAGE_SELF,&rus);
utime= rus.ru_utime.tv_sec+rus.ru_utime.tv_usec*1.0e-6;
stime= rus.ru_stime.tv_sec+rus.ru_stime.tv_usec*1.0e-6;
idrss= rus.ru_idrss;
majflt= rus.ru_majflt;
getloadavg(&load_avg,1);
#else
utime= -1.0;
stime= -1.0;
idrss= -1;
majflt= -1;
load_avg= -1.0;
#endif
pg_avail= sysconf(_SC_AVPHYS_PAGES);
}
/*:7*/
#line 29 "./journal.cweb"
;
/*8:*/
#line 107 "./journal.cweb"
SystemResourcesFlash::SystemResourcesFlash()
{
_sysres.getRUS(load_avg,pg_avail,utime,stime,
elapsed,idrss,majflt);
}
/*:8*/
#line 30 "./journal.cweb"
;
/*9:*/
#line 115 "./journal.cweb"
void SystemResourcesFlash::diff(const SystemResourcesFlash&pre)
{
utime-= pre.utime;
stime-= pre.stime;
elapsed-= pre.elapsed;
idrss-= pre.idrss;
majflt-= pre.majflt;
}
/*:9*/
#line 31 "./journal.cweb"
;
/*10:*/
#line 126 "./journal.cweb"
JournalRecord&JournalRecord::operator<<(const IntSequence&s)
{
operator<<("[");
for(int i= 0;i<s.size();i++){
operator<<(s[i]);
if(i<s.size()-1)
operator<<(",");
}
operator<<("]");
return*this;
}
/*:10*/
#line 32 "./journal.cweb"
;
/*11:*/
#line 140 "./journal.cweb"
void JournalRecord::writePrefix(const SystemResourcesFlash&f)
{
for(int i= 0;i<MAXLEN;i++)
prefix[i]= ' ';
double mb= 1024*1024;
sprintf(prefix,"%07.6g",f.elapsed);
sprintf(prefix+7,":%c%05d",recChar,ord);
sprintf(prefix+14,":%1.1f",f.load_avg);
sprintf(prefix+18,":%05.4g",f.pg_avail*_sysres.pageSize()/mb);
sprintf(prefix+24,"%s",": : ");
for(int i= 0;i<2*journal.getDepth();i++)
prefix[i+33]= ' ';
prefix[2*journal.getDepth()+33]= '\0';
}
/*:11*/
#line 33 "./journal.cweb"
;
/*12:*/
#line 157 "./journal.cweb"
void JournalRecordPair::writePrefixForEnd(const SystemResourcesFlash&f)
{
for(int i= 0;i<MAXLEN;i++)
prefix_end[i]= ' ';
double mb= 1024*1024;
SystemResourcesFlash difnow;
difnow.diff(f);
sprintf(prefix_end,"%07.6g",f.elapsed+difnow.elapsed);
sprintf(prefix_end+7,":E%05d",ord);
sprintf(prefix_end+14,":%1.1f",difnow.load_avg);
sprintf(prefix_end+18,":%05.4g",difnow.pg_avail*_sysres.pageSize()/mb);
sprintf(prefix_end+24,":%06.5g",difnow.majflt*_sysres.pageSize()/mb);
sprintf(prefix_end+31,"%s",": ");
for(int i= 0;i<2*journal.getDepth();i++)
prefix_end[i+33]= ' ';
prefix_end[2*journal.getDepth()+33]= '\0';
}
/*:12*/
#line 34 "./journal.cweb"
;
/*13:*/
#line 177 "./journal.cweb"
JournalRecordPair::~JournalRecordPair()
{
journal.decrementDepth();
writePrefixForEnd(flash);
journal<<prefix_end;
journal<<mes;
journal<<endl;
journal.flush();
}
/*:13*/
#line 35 "./journal.cweb"
;
/*14:*/
#line 189 "./journal.cweb"
JournalRecord&endrec(JournalRecord&rec)
{
rec.journal<<rec.prefix;
rec.journal<<rec.mes;
rec.journal<<endl;
rec.journal.flush();
rec.journal.incrementOrd();
return rec;
}
/*:14*/
#line 36 "./journal.cweb"
;
/*15:*/
#line 201 "./journal.cweb"
void Journal::printHeader()
{
(*this)<<"This is Dynare++, Copyright (C) 2004,2005 Michel Juillard, Ondra Kamenik\n";
(*this)<<"Dynare++ comes with ABSOLUTELY NO WARRANTY and is distributed under\n";
(*this)<<"General Public License, see http://www.gnu.org/license/gpl.html\n";
(*this)<<"\n\n";
#ifndef __MINGW32__
utsname info;
uname(&info);
(*this)<<"System info: ";
(*this)<<info.sysname<<" "<<info.release<<" "<<info.version<<" ";
(*this)<<info.machine<<", processors online: "<<_sysres.onlineProcessors();
(*this)<<"\n\nStart time: ";
char ts[100];
time_t curtime= time(NULL);
tm loctime;
localtime_r(&curtime,&loctime);
asctime_r(&loctime,ts);
(*this)<<ts<<"\n";
#else
(*this)<<"System info: (not implemented for MINGW)\n";
(*this)<<"Start time: (not implemented for MINGW)\n\n";
#endif
(*this)<<" ------ elapsed time (seconds) \n";
(*this)<<" | ------ record unique identifier \n";
(*this)<<" | | ------ load average \n";
(*this)<<" | | | ------ available memory (MB) \n";
(*this)<<" | | | | ------ major faults (MB)\n";
(*this)<<" | | | | | \n";
(*this)<<" V V V V V \n";
(*this)<<"\n";
}
/*:15*/
#line 37 "./journal.cweb"
;
/*:1*/

View File

@ -0,0 +1,140 @@
#define MAXLEN 1000 \
/*1:*/
#line 14 "./journal.hweb"
#ifndef JOURNAL_H
#define JOURNAL_H
#include "int_sequence.h"
#include <sys/time.h>
#include <stdio.h>
#include <iostream>
#include <fstream>
/*2:*/
#line 34 "./journal.hweb"
class SystemResources{
timeval start;
public:
SystemResources();
static long int pageSize();
static long int physicalPages();
static long int onlineProcessors();
static long int availableMemory();
void getRUS(double&load_avg,long int&pg_avail,double&utime,
double&stime,double&elapsed,long int&idrss,
long int&majflt);
};
/*:2*/
#line 25 "./journal.hweb"
;
/*3:*/
#line 49 "./journal.hweb"
struct SystemResourcesFlash{
double load_avg;
long int pg_avail;
double utime;
double stime;
double elapsed;
long int idrss;
long int majflt;
SystemResourcesFlash();
void diff(const SystemResourcesFlash&pre);
};
/*:3*/
#line 26 "./journal.hweb"
;
/*6:*/
#line 113 "./journal.hweb"
class Journal:public ofstream{
int ord;
int depth;
public:
Journal(const char*fname)
:ofstream(fname),ord(0),depth(0)
{printHeader();}
~Journal()
{flush();}
void printHeader();
void incrementOrd()
{ord++;}
int getOrd()const
{return ord;}
void incrementDepth()
{depth++;}
void decrementDepth()
{depth--;}
int getDepth()const
{return depth;}
};
/*:6*/
#line 27 "./journal.hweb"
;
/*4:*/
#line 67 "./journal.hweb"
class JournalRecord;
JournalRecord&endrec(JournalRecord&);
class JournalRecord{
protected:
char recChar;
int ord;
public:
Journal&journal;
char prefix[MAXLEN];
char mes[MAXLEN];
SystemResourcesFlash flash;
typedef JournalRecord&(*_Tfunc)(JournalRecord&);
JournalRecord(Journal&jr,char rc= 'M')
:recChar(rc),ord(jr.getOrd()),journal(jr)
{prefix[0]= '\0';mes[0]= '\0';writePrefix(flash);}
virtual~JournalRecord(){}
JournalRecord&operator<<(const IntSequence&s);
JournalRecord&operator<<(_Tfunc f)
{(*f)(*this);return*this;}
JournalRecord&operator<<(const char*s)
{strcat(mes,s);return*this;}
JournalRecord&operator<<(int i)
{sprintf(mes+strlen(mes),"%d",i);return*this;}
JournalRecord&operator<<(double d)
{sprintf(mes+strlen(mes),"%f",d);return*this;}
protected:
void writePrefix(const SystemResourcesFlash&f);
};
/*:4*/
#line 28 "./journal.hweb"
;
/*5:*/
#line 100 "./journal.hweb"
class JournalRecordPair:public JournalRecord{
char prefix_end[MAXLEN];
public:
JournalRecordPair(Journal&jr)
:JournalRecord(jr,'S')
{prefix_end[0]= '\0';journal.incrementDepth();}
~JournalRecordPair();
private:
void writePrefixForEnd(const SystemResourcesFlash&f);
};
/*:5*/
#line 29 "./journal.hweb"
;
#endif
/*:1*/

View File

@ -0,0 +1,64 @@
/*1:*/
#line 9 "./kord_exception.hweb"
#ifndef KORD_EXCEPTION_H
#define KORD_EXCEPTION_H
#include <string.h>
#include <stdio.h>
#define KORD_RAISE(mes) \
throw KordException(__FILE__, __LINE__, mes);
#define KORD_RAISE_IF(expr, mes) \
if (expr) throw KordException(__FILE__, __LINE__, mes);
#define KORD_RAISE_X(mes, c) \
throw KordException(__FILE__, __LINE__, mes, c);
#define KORD_RAISE_IF_X(expr, mes, c) \
if (expr) throw KordException(__FILE__, __LINE__, mes, c);
/*2:*/
#line 34 "./kord_exception.hweb"
class KordException{
protected:
char fname[50];
int lnum;
char message[500];
int cd;
public:
KordException(const char*f,int l,const char*mes,int c= 255)
{
strncpy(fname,f,50);fname[49]= '\0';
strncpy(message,mes,500);message[499]= '\0';
lnum= l;
cd= c;
}
virtual~KordException(){}
virtual void print()const
{printf("At %s:%d:(%d):%s\n",fname,lnum,cd,message);}
virtual int code()const
{return cd;}
const char*get_message()const
{return message;}
};
/*:2*/
#line 28 "./kord_exception.hweb"
;
/*3:*/
#line 59 "./kord_exception.hweb"
#define KORD_FP_NOT_CONV 254
#define KORD_FP_NOT_FINITE 253
#define KORD_MD_NOT_STABLE 252
/*:3*/
#line 29 "./kord_exception.hweb"
;
#endif
/*:1*/

View File

@ -0,0 +1,326 @@
/*1:*/
#line 6 "./korder.cweb"
#include "kord_exception.h"
#include "korder.h"
#include "cpplapack.h"
/*2:*/
#line 25 "./korder.cweb"
PLUMatrix::PLUMatrix(const PLUMatrix&plu)
:TwoDMatrix(plu),inv(plu.inv),ipiv(new int[nrows()])
{
memcpy(ipiv,plu.ipiv,nrows()*sizeof(int));
}
/*:2*/
#line 13 "./korder.cweb"
;
/*3:*/
#line 37 "./korder.cweb"
void PLUMatrix::calcPLU()
{
int info;
int rows= nrows();
inv= (const Vector&)getData();
LAPACK_dgetrf(&rows,&rows,inv.base(),&rows,ipiv,&info);
}
/*:3*/
#line 14 "./korder.cweb"
;
/*4:*/
#line 48 "./korder.cweb"
void PLUMatrix::multInv(TwoDMatrix&m)const
{
KORD_RAISE_IF(m.nrows()!=ncols(),
"The matrix is not square in PLUMatrix::multInv");
int info;
int mcols= m.ncols();
int mrows= m.nrows();
double*mbase= m.getData().base();
LAPACK_dgetrs("N",&mrows,&mcols,inv.base(),&mrows,ipiv,
mbase,&mrows,&info);
KORD_RAISE_IF(info!=0,
"Info!=0 in PLUMatrix::multInv");
}
/*:4*/
#line 15 "./korder.cweb"
;
/*5:*/
#line 69 "./korder.cweb"
MatrixA::MatrixA(const FSSparseTensor&f,const IntSequence&ss,
const TwoDMatrix&gy,const PartitionY&ypart)
:PLUMatrix(ypart.ny())
{
zeros();
IntSequence c(1);c[0]= 1;
FGSTensor f_y(f,ss,c,TensorDimens(ss,c));
add(1.0,f_y);
ConstTwoDMatrix gss_ys(ypart.nstat+ypart.npred,ypart.nyss(),gy);
c[0]= 0;
FGSTensor f_yss(f,ss,c,TensorDimens(ss,c));
TwoDMatrix sub(*this,ypart.nstat,ypart.nys());
sub.multAndAdd(ConstTwoDMatrix(f_yss),gss_ys);
calcPLU();
}
/*:5*/
#line 16 "./korder.cweb"
;
/*6:*/
#line 97 "./korder.cweb"
MatrixS::MatrixS(const FSSparseTensor&f,const IntSequence&ss,
const TwoDMatrix&gy,const PartitionY&ypart)
:PLUMatrix(ypart.ny())
{
zeros();
IntSequence c(1);c[0]= 1;
FGSTensor f_y(f,ss,c,TensorDimens(ss,c));
add(1.0,f_y);
ConstTwoDMatrix gss_ys(ypart.nstat+ypart.npred,ypart.nyss(),gy);
c[0]= 0;
FGSTensor f_yss(f,ss,c,TensorDimens(ss,c));
TwoDMatrix sub(*this,ypart.nstat,ypart.nys());
sub.multAndAdd(ConstTwoDMatrix(f_yss),gss_ys);
TwoDMatrix sub2(*this,ypart.nstat+ypart.npred,ypart.nyss());
sub2.add(1.0,f_yss);
calcPLU();
}
/*:6*/
#line 17 "./korder.cweb"
;
/*13:*/
#line 281 "./korder.cweb"
template<> ctraits<KOrder::unfold> ::Tg&KOrder::g<KOrder::unfold> ()
{return _ug;}
template<> const ctraits<KOrder::unfold> ::Tg&KOrder::g<KOrder::unfold> ()const
{return _ug;}
template<> ctraits<KOrder::fold> ::Tg&KOrder::g<KOrder::fold> ()
{return _fg;}
template<> const ctraits<KOrder::fold> ::Tg&KOrder::g<KOrder::fold> ()const
{return _fg;}
template<> ctraits<KOrder::unfold> ::Tgs&KOrder::gs<KOrder::unfold> ()
{return _ugs;}
template<> const ctraits<KOrder::unfold> ::Tgs&KOrder::gs<KOrder::unfold> ()const
{return _ugs;}
template<> ctraits<KOrder::fold> ::Tgs&KOrder::gs<KOrder::fold> ()
{return _fgs;}
template<> const ctraits<KOrder::fold> ::Tgs&KOrder::gs<KOrder::fold> ()const
{return _fgs;}
template<> ctraits<KOrder::unfold> ::Tgss&KOrder::gss<KOrder::unfold> ()
{return _ugss;}
template<> const ctraits<KOrder::unfold> ::Tgss&KOrder::gss<KOrder::unfold> ()const
{return _ugss;}
template<> ctraits<KOrder::fold> ::Tgss&KOrder::gss<KOrder::fold> ()
{return _fgss;}
template<> const ctraits<KOrder::fold> ::Tgss&KOrder::gss<KOrder::fold> ()const
{return _fgss;}
template<> ctraits<KOrder::unfold> ::TG&KOrder::G<KOrder::unfold> ()
{return _uG;}
template<> const ctraits<KOrder::unfold> ::TG&KOrder::G<KOrder::unfold> ()const
{return _uG;}
template<> ctraits<KOrder::fold> ::TG&KOrder::G<KOrder::fold> ()
{return _fG;}
template<> const ctraits<KOrder::fold> ::TG&KOrder::G<KOrder::fold> ()const
{return _fG;}
template<> ctraits<KOrder::unfold> ::TZstack&KOrder::Zstack<KOrder::unfold> ()
{return _uZstack;}
template<> const ctraits<KOrder::unfold> ::TZstack&KOrder::Zstack<KOrder::unfold> ()const
{return _uZstack;}
template<> ctraits<KOrder::fold> ::TZstack&KOrder::Zstack<KOrder::fold> ()
{return _fZstack;}
template<> const ctraits<KOrder::fold> ::TZstack&KOrder::Zstack<KOrder::fold> ()const
{return _fZstack;}
template<> ctraits<KOrder::unfold> ::TGstack&KOrder::Gstack<KOrder::unfold> ()
{return _uGstack;}
template<> const ctraits<KOrder::unfold> ::TGstack&KOrder::Gstack<KOrder::unfold> ()const
{return _uGstack;}
template<> ctraits<KOrder::fold> ::TGstack&KOrder::Gstack<KOrder::fold> ()
{return _fGstack;}
template<> const ctraits<KOrder::fold> ::TGstack&KOrder::Gstack<KOrder::fold> ()const
{return _fGstack;}
template<> ctraits<KOrder::unfold> ::Tm&KOrder::m<KOrder::unfold> ()
{return _um;}
template<> const ctraits<KOrder::unfold> ::Tm&KOrder::m<KOrder::unfold> ()const
{return _um;}
template<> ctraits<KOrder::fold> ::Tm&KOrder::m<KOrder::fold> ()
{return _fm;}
template<> const ctraits<KOrder::fold> ::Tm&KOrder::m<KOrder::fold> ()const
{return _fm;}
/*:13*/
#line 18 "./korder.cweb"
;
/*10:*/
#line 211 "./korder.cweb"
template<>
void KOrder::sylvesterSolve<KOrder::unfold> (ctraits<unfold> ::Ttensor&der)const
{
JournalRecordPair pa(journal);
pa<<"Sylvester equation for dimension = "<<der.getSym()[0]<<endrec;
if(ypart.nys()> 0&&ypart.nyss()> 0){
KORD_RAISE_IF(!der.isFinite(),
"RHS of Sylverster is not finite");
TwoDMatrix gs_y(*(gs<unfold> ().get(Symmetry(1,0,0,0))));
GeneralSylvester sylv(der.getSym()[0],ny,ypart.nys(),
ypart.nstat+ypart.npred,
matA.getData().base(),matB.getData().base(),
gs_y.getData().base(),der.getData().base());
sylv.solve();
}else if(ypart.nys()> 0&&ypart.nyss()==0){
matA.multInv(der);
}
}
/*:10*/
#line 19 "./korder.cweb"
;
/*11:*/
#line 235 "./korder.cweb"
template<>
void KOrder::sylvesterSolve<KOrder::fold> (ctraits<fold> ::Ttensor&der)const
{
ctraits<unfold> ::Ttensor tmp(der);
sylvesterSolve<unfold> (tmp);
ctraits<fold> ::Ttensor ftmp(tmp);
der.getData()= (const Vector&)(ftmp.getData());
}
/*:11*/
#line 20 "./korder.cweb"
;
/*12:*/
#line 246 "./korder.cweb"
void KOrder::switchToFolded()
{
JournalRecordPair pa(journal);
pa<<"Switching from unfolded to folded"<<endrec;
int maxdim= g<unfold> ().getMaxDim();
for(int dim= 1;dim<=maxdim;dim++){
SymmetrySet ss(dim,4);
for(symiterator si(ss);!si.isEnd();++si){
if((*si)[2]==0&&g<unfold> ().check(*si)){
FGSTensor*ft= new FGSTensor(*(g<unfold> ().get(*si)));
insertDerivative<fold> (ft);
if(dim> 1){
gss<unfold> ().remove(*si);
gs<unfold> ().remove(*si);
g<unfold> ().remove(*si);
}
}
if(G<unfold> ().check(*si)){
FGSTensor*ft= new FGSTensor(*(G<unfold> ().get(*si)));
G<fold> ().insert(ft);
if(dim> 1){
G<fold> ().remove(*si);
}
}
}
}
}
/*:12*/
#line 21 "./korder.cweb"
;
/*7:*/
#line 133 "./korder.cweb"
KOrder::KOrder(int num_stat,int num_pred,int num_both,int num_forw,
const TensorContainer<FSSparseTensor> &fcont,
const TwoDMatrix&gy,const TwoDMatrix&gu,const TwoDMatrix&v,
Journal&jr)
:ypart(num_stat,num_pred,num_both,num_forw),
ny(ypart.ny()),nu(gu.ncols()),maxk(fcont.getMaxDim()),
nvs(4),
_ug(4),_fg(4),_ugs(4),_fgs(4),_ugss(4),_fgss(4),
_uG(4),_fG(4),
_uZstack(&_uG,ypart.nyss(),&_ug,ny,ypart.nys(),nu),
_fZstack(&_fG,ypart.nyss(),&_fg,ny,ypart.nys(),nu),
_uGstack(&_ugs,ypart.nys(),nu),
_fGstack(&_fgs,ypart.nys(),nu),
_um(maxk,v),_fm(_um),f(fcont),
matA(*(f.get(Symmetry(1))),_uZstack.getStackSizes(),gy,ypart),
matS(*(f.get(Symmetry(1))),_uZstack.getStackSizes(),gy,ypart),
matB(*(f.get(Symmetry(1))),_uZstack.getStackSizes()),
journal(jr)
{
KORD_RAISE_IF(gy.ncols()!=ypart.nys(),
"Wrong number of columns in gy in KOrder constructor");
KORD_RAISE_IF(v.ncols()!=nu,
"Wrong number of columns of Vcov in KOrder constructor");
KORD_RAISE_IF(nu!=v.nrows(),
"Wrong number of rows of Vcov in KOrder constructor");
KORD_RAISE_IF(maxk<2,
"Order of approximation must be at least 2 in KOrder constructor");
KORD_RAISE_IF(gy.nrows()!=ypart.ny(),
"Wrong number of rows in gy in KOrder constructor");
KORD_RAISE_IF(gu.nrows()!=ypart.ny(),
"Wrong number of rows in gu in KOrder constuctor");
KORD_RAISE_IF(gu.ncols()!=nu,
"Wrong number of columns in gu in KOrder constuctor");
nvs[0]= ypart.nys();nvs[1]= nu;nvs[2]= nu;nvs[3]= 1;
/*8:*/
#line 178 "./korder.cweb"
UGSTensor*tgy= new UGSTensor(ny,TensorDimens(Symmetry(1,0,0,0),nvs));
tgy->getData()= gy.getData();
insertDerivative<unfold> (tgy);
UGSTensor*tgu= new UGSTensor(ny,TensorDimens(Symmetry(0,1,0,0),nvs));
tgu->getData()= gu.getData();
insertDerivative<unfold> (tgu);
/*:8*/
#line 171 "./korder.cweb"
;
/*9:*/
#line 187 "./korder.cweb"
UGSTensor*tGy= faaDiBrunoG<unfold> (Symmetry(1,0,0,0));
G<unfold> ().insert(tGy);
UGSTensor*tGu= faaDiBrunoG<unfold> (Symmetry(0,1,0,0));
G<unfold> ().insert(tGu);
UGSTensor*tGup= faaDiBrunoG<unfold> (Symmetry(0,0,1,0));
G<unfold> ().insert(tGup);
/*:9*/
#line 172 "./korder.cweb"
;
}
/*:7*/
#line 22 "./korder.cweb"
;
/*:1*/

View File

@ -0,0 +1,736 @@
#define _Ttensor TYPENAME ctraits<t> ::Ttensor
#define _Ttensym TYPENAME ctraits<t> ::Ttensym
#define _Tg TYPENAME ctraits<t> ::Tg
#define _Tgs TYPENAME ctraits<t> ::Tgs
#define _Tgss TYPENAME ctraits<t> ::Tgss
#define _TG TYPENAME ctraits<t> ::TG
#define _TZstack TYPENAME ctraits<t> ::TZstack
#define _TGstack TYPENAME ctraits<t> ::TGstack
#define _TZXstack TYPENAME ctraits<t> ::TZXstack
#define _TGXstack TYPENAME ctraits<t> ::TGXstack
#define _Tm TYPENAME ctraits<t> ::Tm
#define _Tpol TYPENAME ctraits<t> ::Tpol \
\
/*1:*/
#line 62 "./korder.hweb"
#ifndef KORDER_H
#define KORDER_H
#include "int_sequence.h"
#include "fs_tensor.h"
#include "gs_tensor.h"
#include "t_container.h"
#include "stack_container.h"
#include "normal_moments.h"
#include "t_polynomial.h"
#include "faa_di_bruno.h"
#include "journal.h"
#include "kord_exception.h"
#include "GeneralSylvester.h"
#include <cmath>
#define TYPENAME typename
/*2:*/
#line 106 "./korder.hweb"
class FoldedZXContainer;
class UnfoldedZXContainer;
class FoldedGXContainer;
class UnfoldedGXContainer;
template<bool condition,class Then,class Else>
struct IF{
typedef Then RET;
};
template<class Then,class Else>
struct IF<false,Then,Else> {
typedef Else RET;
};
template<int type>
class ctraits{
public:
enum{fold,unfold};
typedef TYPENAME IF<type==fold,FGSTensor,UGSTensor> ::RET Ttensor;
typedef TYPENAME IF<type==fold,FFSTensor,UFSTensor> ::RET Ttensym;
typedef TYPENAME IF<type==fold,FGSContainer,UGSContainer> ::RET Tg;
typedef TYPENAME IF<type==fold,FGSContainer,UGSContainer> ::RET Tgs;
typedef TYPENAME IF<type==fold,FGSContainer,UGSContainer> ::RET Tgss;
typedef TYPENAME IF<type==fold,FGSContainer,UGSContainer> ::RET TG;
typedef TYPENAME IF<type==fold,FoldedZContainer,UnfoldedZContainer> ::RET TZstack;
typedef TYPENAME IF<type==fold,FoldedGContainer,UnfoldedGContainer> ::RET TGstack;
typedef TYPENAME IF<type==fold,FNormalMoments,UNormalMoments> ::RET Tm;
typedef TYPENAME IF<type==fold,FTensorPolynomial,UTensorPolynomial> ::RET Tpol;
typedef TYPENAME IF<type==fold,FoldedZXContainer,UnfoldedZXContainer> ::RET TZXstack;
typedef TYPENAME IF<type==fold,FoldedGXContainer,UnfoldedGXContainer> ::RET TGXstack;
};
/*:2*/
#line 83 "./korder.hweb"
;
/*3:*/
#line 156 "./korder.hweb"
struct PartitionY{
const int nstat;
const int npred;
const int nboth;
const int nforw;
PartitionY(int num_stat,int num_pred,
int num_both,int num_forw)
:nstat(num_stat),npred(num_pred),
nboth(num_both),nforw(num_forw)
{}
int ny()const
{return nstat+npred+nboth+nforw;}
int nys()const
{return npred+nboth;}
int nyss()const
{return nboth+nforw;}
};
/*:3*/
#line 84 "./korder.hweb"
;
/*4:*/
#line 183 "./korder.hweb"
class PLUMatrix:public TwoDMatrix{
public:
PLUMatrix(int n)
:TwoDMatrix(n,n),
inv(nrows()*ncols()),
ipiv(new int[nrows()]){}
PLUMatrix(const PLUMatrix&plu);
virtual~PLUMatrix()
{delete[]ipiv;}
void multInv(TwoDMatrix&m)const;
private:
Vector inv;
int*ipiv;
protected:
void calcPLU();
};
/*:4*/
#line 85 "./korder.hweb"
;
/*5:*/
#line 205 "./korder.hweb"
class MatrixA:public PLUMatrix{
public:
MatrixA(const FSSparseTensor&f,const IntSequence&ss,
const TwoDMatrix&gy,const PartitionY&ypart);
};
/*:5*/
#line 86 "./korder.hweb"
;
/*6:*/
#line 218 "./korder.hweb"
class MatrixS:public PLUMatrix{
public:
MatrixS(const FSSparseTensor&f,const IntSequence&ss,
const TwoDMatrix&gy,const PartitionY&ypart);
};
/*:6*/
#line 87 "./korder.hweb"
;
/*7:*/
#line 229 "./korder.hweb"
class MatrixB:public TwoDMatrix{
public:
MatrixB(const FSSparseTensor&f,const IntSequence&ss)
:TwoDMatrix(FGSTensor(f,ss,IntSequence(1,0),
TensorDimens(ss,IntSequence(1,0))))
{}
};
/*:7*/
#line 88 "./korder.hweb"
;
/*8:*/
#line 325 "./korder.hweb"
class KOrder{
protected:
const PartitionY ypart;
const int ny;
const int nu;
const int maxk;
IntSequence nvs;
/*30:*/
#line 919 "./korder.hweb"
UGSContainer _ug;
FGSContainer _fg;
UGSContainer _ugs;
FGSContainer _fgs;
UGSContainer _ugss;
FGSContainer _fgss;
UGSContainer _uG;
FGSContainer _fG;
UnfoldedZContainer _uZstack;
FoldedZContainer _fZstack;
UnfoldedGContainer _uGstack;
FoldedGContainer _fGstack;
UNormalMoments _um;
FNormalMoments _fm;
const TensorContainer<FSSparseTensor> &f;
/*:30*/
#line 333 "./korder.hweb"
;
const MatrixA matA;
const MatrixS matS;
const MatrixB matB;
/*31:*/
#line 939 "./korder.hweb"
template<int t> _Tg&g();
template<int t> const _Tg&g()const;
template<int t> _Tgs&gs();
template<int t> const _Tgs&gs()const;
template<int t> _Tgss&gss();
template<int t> const _Tgss&gss()const;
template<int t> _TG&G();
template<int t> const _TG&G()const;
template<int t> _TZstack&Zstack();
template<int t> const _TZstack&Zstack()const;
template<int t> _TGstack&Gstack();
template<int t> const _TGstack&Gstack()const;
template<int t> _Tm&m();
template<int t> const _Tm&m()const;
/*:31*/
#line 337 "./korder.hweb"
;
Journal&journal;
public:
KOrder(int num_stat,int num_pred,int num_both,int num_forw,
const TensorContainer<FSSparseTensor> &fcont,
const TwoDMatrix&gy,const TwoDMatrix&gu,const TwoDMatrix&v,
Journal&jr);
enum{fold,unfold};
/*24:*/
#line 796 "./korder.hweb"
template<int t>
void performStep(int order)
{
KORD_RAISE_IF(order-1!=g<t> ().getMaxDim(),
"Wrong order for KOrder::performStep");
JournalRecordPair pa(journal);
pa<<"Performing step for order = "<<order<<endrec;
recover_y<t> (order);
for(int i= 0;i<order;i++){
recover_yu<t> (i,order-i);
}
for(int j= 1;j<order;j++){
for(int i= j-1;i>=1;i--){
recover_yus<t> (order-j,i,j-i);
}
recover_ys<t> (order-j,j);
}
for(int i= order-1;i>=1;i--){
recover_yus<t> (0,i,order-i);
}
recover_s<t> (order);
}
/*:24*/
#line 345 "./korder.hweb"
;
/*25:*/
#line 828 "./korder.hweb"
template<int t>
double check(int dim)const
{
KORD_RAISE_IF(dim> g<t> ().getMaxDim(),
"Wrong dimension for KOrder::check");
JournalRecordPair pa(journal);
pa<<"Checking residuals for order = "<<dim<<endrec;
double maxerror= 0.0;
/*26:*/
#line 848 "./korder.hweb"
for(int i= 0;i<=dim;i++){
Symmetry sym(dim-i,i,0,0);
_Ttensor*r= faaDiBrunoZ<t> (sym);
double err= r->getData().getMax();
JournalRecord(journal)<<"\terror for symmetry "<<sym<<"\tis "<<err<<endrec;
if(err> maxerror)
maxerror= err;
delete r;
}
/*:26*/
#line 839 "./korder.hweb"
;
/*27:*/
#line 860 "./korder.hweb"
SymmetrySet ss(dim,3);
for(symiterator si(ss);!si.isEnd();++si){
int i= (*si)[0];
int j= (*si)[1];
int k= (*si)[2];
if(i+j> 0&&k> 0){
Symmetry sym(i,j,0,k);
_Ttensor*r= faaDiBrunoZ<t> (sym);
_Ttensor*D_ijk= calcD_ijk<t> (i,j,k);
r->add(1.0,*D_ijk);
delete D_ijk;
_Ttensor*E_ijk= calcE_ijk<t> (i,j,k);
r->add(1.0,*E_ijk);
delete E_ijk;
double err= r->getData().getMax();
JournalRecord(journal)<<"\terror for symmetry "<<sym<<"\tis "<<err<<endrec;
delete r;
}
}
/*:27*/
#line 840 "./korder.hweb"
;
/*28:*/
#line 883 "./korder.hweb"
_Ttensor*r= faaDiBrunoZ<t> (Symmetry(0,0,0,dim));
_Ttensor*D_k= calcD_k<t> (dim);
r->add(1.0,*D_k);
delete D_k;
_Ttensor*E_k= calcE_k<t> (dim);
r->add(1.0,*E_k);
delete E_k;
double err= r->getData().getMax();
Symmetry sym(0,0,0,dim);
JournalRecord(journal)<<"\terror for symmetry "<<sym<<"\tis "<<err<<endrec;
if(err> maxerror)
maxerror= err;
delete r;
/*:28*/
#line 841 "./korder.hweb"
;
return maxerror;
}
/*:25*/
#line 346 "./korder.hweb"
;
/*29:*/
#line 899 "./korder.hweb"
template<int t>
Vector*calcStochShift(int order,double sigma)const
{
Vector*res= new Vector(ny);
res->zeros();
int jfac= 1;
for(int j= 1;j<=order;j++,jfac*= j)
if(is_even(j)){
_Ttensor*ten= calcD_k<t> (j);
res->add(std::pow(sigma,j)/jfac,ten->getData());
delete ten;
}
return res;
}
/*:29*/
#line 347 "./korder.hweb"
;
void switchToFolded();
const PartitionY&getPartY()const
{return ypart;}
const FGSContainer&getFoldDers()const
{return _fg;}
const UGSContainer&getUnfoldDers()const
{return _ug;}
static bool is_even(int i)
{return(i/2)*2==i;}
protected:
/*9:*/
#line 386 "./korder.hweb"
template<int t>
void insertDerivative(_Ttensor*der)
{
g<t> ().insert(der);
gs<t> ().insert(new _Ttensor(ypart.nstat,ypart.nys(),*der));
gss<t> ().insert(new _Ttensor(ypart.nstat+ypart.npred,
ypart.nyss(),*der));
}
/*:9*/
#line 358 "./korder.hweb"
;
template<int t>
void sylvesterSolve(_Ttensor&der)const;
/*10:*/
#line 404 "./korder.hweb"
template<int t>
_Ttensor*faaDiBrunoZ(const Symmetry&sym)const
{
JournalRecordPair pa(journal);
pa<<"Faa Di Bruno Z container for "<<sym<<endrec;
_Ttensor*res= new _Ttensor(ny,TensorDimens(sym,nvs));
FaaDiBruno bruno(journal);
bruno.calculate(Zstack<t> (),f,*res);
return res;
}
/*:10*/
#line 362 "./korder.hweb"
;
/*11:*/
#line 419 "./korder.hweb"
template<int t>
_Ttensor*faaDiBrunoG(const Symmetry&sym)const
{
JournalRecordPair pa(journal);
pa<<"Faa Di Bruno G container for "<<sym<<endrec;
TensorDimens tdims(sym,nvs);
_Ttensor*res= new _Ttensor(ypart.nyss(),tdims);
FaaDiBruno bruno(journal);
bruno.calculate(Gstack<t> (),gss<t> (),*res);
return res;
}
/*:11*/
#line 363 "./korder.hweb"
;
/*12:*/
#line 444 "./korder.hweb"
template<int t>
void recover_y(int i)
{
Symmetry sym(i,0,0,0);
JournalRecordPair pa(journal);
pa<<"Recovering symmetry "<<sym<<endrec;
_Ttensor*G_yi= faaDiBrunoG<t> (sym);
G<t> ().insert(G_yi);
_Ttensor*g_yi= faaDiBrunoZ<t> (sym);
g_yi->mult(-1.0);
sylvesterSolve<t> (*g_yi);
insertDerivative<t> (g_yi);
_Ttensor*gss_y= gss<t> ().get(Symmetry(1,0,0,0));
gs<t> ().multAndAdd(*gss_y,*G_yi);
_Ttensor*gss_yi= gss<t> ().get(sym);
gs<t> ().multAndAdd(*gss_yi,*G_yi);
}
/*:12*/
#line 365 "./korder.hweb"
;
/*13:*/
#line 480 "./korder.hweb"
template<int t>
void recover_yu(int i,int j)
{
Symmetry sym(i,j,0,0);
JournalRecordPair pa(journal);
pa<<"Recovering symmetry "<<sym<<endrec;
_Ttensor*G_yiuj= faaDiBrunoG<t> (sym);
G<t> ().insert(G_yiuj);
_Ttensor*g_yiuj= faaDiBrunoZ<t> (sym);
g_yiuj->mult(-1.0);
matA.multInv(*g_yiuj);
insertDerivative<t> (g_yiuj);
gs<t> ().multAndAdd(*(gss<t> ().get(Symmetry(1,0,0,0))),*G_yiuj);
}
/*:13*/
#line 366 "./korder.hweb"
;
/*14:*/
#line 519 "./korder.hweb"
template<int t>
void recover_ys(int i,int j)
{
Symmetry sym(i,0,0,j);
JournalRecordPair pa(journal);
pa<<"Recovering symmetry "<<sym<<endrec;
fillG<t> (i,0,j);
if(is_even(j)){
_Ttensor*G_yisj= faaDiBrunoG<t> (sym);
G<t> ().insert(G_yisj);
_Ttensor*g_yisj= faaDiBrunoZ<t> (sym);
{
_Ttensor*D_ij= calcD_ik<t> (i,j);
g_yisj->add(1.0,*D_ij);
delete D_ij;
}
if(j>=3){
_Ttensor*E_ij= calcE_ik<t> (i,j);
g_yisj->add(1.0,*E_ij);
delete E_ij;
}
g_yisj->mult(-1.0);
sylvesterSolve<t> (*g_yisj);
insertDerivative<t> (g_yisj);
Gstack<t> ().multAndAdd(1,gss<t> (),*G_yisj);
Gstack<t> ().multAndAdd(i+j,gss<t> (),*G_yisj);
}
}
/*:14*/
#line 367 "./korder.hweb"
;
/*15:*/
#line 577 "./korder.hweb"
template<int t>
void recover_yus(int i,int j,int k)
{
Symmetry sym(i,j,0,k);
JournalRecordPair pa(journal);
pa<<"Recovering symmetry "<<sym<<endrec;
fillG<t> (i,j,k);
if(is_even(k)){
_Ttensor*G_yiujsk= faaDiBrunoG<t> (sym);
G<t> ().insert(G_yiujsk);
_Ttensor*g_yiujsk= faaDiBrunoZ<t> (sym);
{
_Ttensor*D_ijk= calcD_ijk<t> (i,j,k);
g_yiujsk->add(1.0,*D_ijk);
delete D_ijk;
}
if(k>=3){
_Ttensor*E_ijk= calcE_ijk<t> (i,j,k);
g_yiujsk->add(1.0,*E_ijk);
delete E_ijk;
}
g_yiujsk->mult(-1.0);
matA.multInv(*g_yiujsk);
insertDerivative<t> (g_yiujsk);
Gstack<t> ().multAndAdd(1,gss<t> (),*G_yiujsk);
}
}
/*:15*/
#line 368 "./korder.hweb"
;
/*16:*/
#line 642 "./korder.hweb"
template<int t>
void recover_s(int i)
{
Symmetry sym(0,0,0,i);
JournalRecordPair pa(journal);
pa<<"Recovering symmetry "<<sym<<endrec;
fillG<t> (0,0,i);
if(is_even(i)){
_Ttensor*G_si= faaDiBrunoG<t> (sym);
G<t> ().insert(G_si);
_Ttensor*g_si= faaDiBrunoZ<t> (sym);
{
_Ttensor*D_i= calcD_k<t> (i);
g_si->add(1.0,*D_i);
delete D_i;
}
if(i>=3){
_Ttensor*E_i= calcE_k<t> (i);
g_si->add(1.0,*E_i);
delete E_i;
}
g_si->mult(-1.0);
matS.multInv(*g_si);
insertDerivative<t> (g_si);
Gstack<t> ().multAndAdd(1,gss<t> (),*G_si);
Gstack<t> ().multAndAdd(i,gss<t> (),*G_si);
}
}
/*:16*/
#line 369 "./korder.hweb"
;
/*17:*/
#line 685 "./korder.hweb"
template<int t>
void fillG(int i,int j,int k)
{
for(int m= 1;m<=k;m++){
if(is_even(k-m)){
_Ttensor*G_yiujupms= faaDiBrunoG<t> (Symmetry(i,j,m,k-m));
G<t> ().insert(G_yiujupms);
}
}
}
/*:17*/
#line 370 "./korder.hweb"
;
/*18:*/
#line 705 "./korder.hweb"
template<int t>
_Ttensor*calcD_ijk(int i,int j,int k)const
{
_Ttensor*res= new _Ttensor(ny,TensorDimens(Symmetry(i,j,0,0),nvs));
res->zeros();
if(is_even(k)){
_Ttensor*tmp= faaDiBrunoZ<t> (Symmetry(i,j,k,0));
tmp->contractAndAdd(2,*res,*(m<t> ().get(Symmetry(k))));
delete tmp;
}
return res;
}
/*:18*/
#line 372 "./korder.hweb"
;
/*20:*/
#line 743 "./korder.hweb"
template<int t>
_Ttensor*calcD_ik(int i,int k)const
{
return calcD_ijk<t> (i,0,k);
}
/*:20*/
#line 373 "./korder.hweb"
;
/*21:*/
#line 751 "./korder.hweb"
template<int t>
_Ttensor*calcD_k(int k)const
{
return calcD_ijk<t> (0,0,k);
}
/*:21*/
#line 374 "./korder.hweb"
;
/*19:*/
#line 727 "./korder.hweb"
template<int t>
_Ttensor*calcE_ijk(int i,int j,int k)const
{
_Ttensor*res= new _Ttensor(ny,TensorDimens(Symmetry(i,j,0,0),nvs));
res->zeros();
for(int n= 2;n<=k-1;n+= 2){
_Ttensor*tmp= faaDiBrunoZ<t> (Symmetry(i,j,n,k-n));
tmp->mult((double)(Tensor::noverk(k,n)));
tmp->contractAndAdd(2,*res,*(m<t> ().get(Symmetry(n))));
delete tmp;
}
return res;
}
/*:19*/
#line 376 "./korder.hweb"
;
/*22:*/
#line 759 "./korder.hweb"
template<int t>
_Ttensor*calcE_ik(int i,int k)const
{
return calcE_ijk<t> (i,0,k);
}
/*:22*/
#line 377 "./korder.hweb"
;
/*23:*/
#line 767 "./korder.hweb"
template<int t>
_Ttensor*calcE_k(int k)const
{
return calcE_ijk<t> (0,0,k);
}
/*:23*/
#line 378 "./korder.hweb"
;
};
/*:8*/
#line 89 "./korder.hweb"
;
#endif
/*:1*/

View File

@ -0,0 +1,137 @@
/*1:*/
#line 5 "./korder_stoch.cweb"
#include "korder_stoch.h"
/*2:*/
#line 14 "./korder_stoch.cweb"
MatrixAA::MatrixAA(const FSSparseTensor&f,const IntSequence&ss,
const TwoDMatrix&gss_ys,const PartitionY&ypart)
:PLUMatrix(ypart.ny())
{
zeros();
IntSequence c(1);c[0]= 1;
FGSTensor f_y(f,ss,c,TensorDimens(ss,c));
add(1.0,f_y);
c[0]= 0;
FGSTensor f_yss(f,ss,c,TensorDimens(ss,c));
TwoDMatrix sub(*this,ypart.nstat,ypart.nys());
sub.multAndAdd(f_yss,gss_ys);
calcPLU();
}
/*:2*/
#line 8 "./korder_stoch.cweb"
;
/*3:*/
#line 35 "./korder_stoch.cweb"
KOrderStoch::KOrderStoch(const PartitionY&yp,int nu,
const TensorContainer<FSSparseTensor> &fcont,
const FGSContainer&hh,Journal&jr)
:nvs(4),ypart(yp),journal(jr),
_ug(4),_fg(4),_ugs(4),_fgs(4),_uG(4),_fG(4),
_uh(NULL),_fh(&hh),
_uZstack(&_uG,ypart.nyss(),&_ug,ypart.ny(),ypart.nys(),nu),
_fZstack(&_fG,ypart.nyss(),&_fg,ypart.ny(),ypart.nys(),nu),
_uGstack(&_ugs,ypart.nys(),nu),
_fGstack(&_fgs,ypart.nys(),nu),
f(fcont),
matA(*(fcont.get(Symmetry(1))),_uZstack.getStackSizes(),*(hh.get(Symmetry(1,0,0,0))),
ypart)
{
nvs[0]= ypart.nys();
nvs[1]= nu;
nvs[2]= nu;
nvs[3]= 1;
}
/*:3*/
#line 9 "./korder_stoch.cweb"
;
/*4:*/
#line 57 "./korder_stoch.cweb"
KOrderStoch::KOrderStoch(const PartitionY&yp,int nu,
const TensorContainer<FSSparseTensor> &fcont,
const UGSContainer&hh,Journal&jr)
:nvs(4),ypart(yp),journal(jr),
_ug(4),_fg(4),_ugs(4),_fgs(4),_uG(4),_fG(4),
_uh(&hh),_fh(NULL),
_uZstack(&_uG,ypart.nyss(),&_ug,ypart.ny(),ypart.nys(),nu),
_fZstack(&_fG,ypart.nyss(),&_fg,ypart.ny(),ypart.nys(),nu),
_uGstack(&_ugs,ypart.nys(),nu),
_fGstack(&_fgs,ypart.nys(),nu),
f(fcont),
matA(*(fcont.get(Symmetry(1))),_uZstack.getStackSizes(),*(hh.get(Symmetry(1,0,0,0))),
ypart)
{
nvs[0]= ypart.nys();
nvs[1]= nu;
nvs[2]= nu;
nvs[3]= 1;
}
/*:4*/
#line 10 "./korder_stoch.cweb"
;
/*5:*/
#line 80 "./korder_stoch.cweb"
template<> ctraits<KOrder::unfold> ::Tg&KOrderStoch::g<KOrder::unfold> ()
{return _ug;}
template<> const ctraits<KOrder::unfold> ::Tg&KOrderStoch::g<KOrder::unfold> ()const
{return _ug;}
template<> ctraits<KOrder::fold> ::Tg&KOrderStoch::g<KOrder::fold> ()
{return _fg;}
template<> const ctraits<KOrder::fold> ::Tg&KOrderStoch::g<KOrder::fold> ()const
{return _fg;}
template<> ctraits<KOrder::unfold> ::Tgs&KOrderStoch::gs<KOrder::unfold> ()
{return _ugs;}
template<> const ctraits<KOrder::unfold> ::Tgs&KOrderStoch::gs<KOrder::unfold> ()const
{return _ugs;}
template<> ctraits<KOrder::fold> ::Tgs&KOrderStoch::gs<KOrder::fold> ()
{return _fgs;}
template<> const ctraits<KOrder::fold> ::Tgs&KOrderStoch::gs<KOrder::fold> ()const
{return _fgs;}
template<> const ctraits<KOrder::unfold> ::Tgss&KOrderStoch::h<KOrder::unfold> ()const
{return*_uh;}
template<> const ctraits<KOrder::fold> ::Tgss&KOrderStoch::h<KOrder::fold> ()const
{return*_fh;}
template<> ctraits<KOrder::unfold> ::TG&KOrderStoch::G<KOrder::unfold> ()
{return _uG;}
template<> const ctraits<KOrder::unfold> ::TG&KOrderStoch::G<KOrder::unfold> ()const
{return _uG;}
template<> ctraits<KOrder::fold> ::TG&KOrderStoch::G<KOrder::fold> ()
{return _fG;}
template<> const ctraits<KOrder::fold> ::TG&KOrderStoch::G<KOrder::fold> ()const
{return _fG;}
template<> ctraits<KOrder::unfold> ::TZXstack&KOrderStoch::Zstack<KOrder::unfold> ()
{return _uZstack;}
template<> const ctraits<KOrder::unfold> ::TZXstack&KOrderStoch::Zstack<KOrder::unfold> ()const
{return _uZstack;}
template<> ctraits<KOrder::fold> ::TZXstack&KOrderStoch::Zstack<KOrder::fold> ()
{return _fZstack;}
template<> const ctraits<KOrder::fold> ::TZXstack&KOrderStoch::Zstack<KOrder::fold> ()const
{return _fZstack;}
template<> ctraits<KOrder::unfold> ::TGXstack&KOrderStoch::Gstack<KOrder::unfold> ()
{return _uGstack;}
template<> const ctraits<KOrder::unfold> ::TGXstack&KOrderStoch::Gstack<KOrder::unfold> ()const
{return _uGstack;}
template<> ctraits<KOrder::fold> ::TGXstack&KOrderStoch::Gstack<KOrder::fold> ()
{return _fGstack;}
template<> const ctraits<KOrder::fold> ::TGXstack&KOrderStoch::Gstack<KOrder::fold> ()const
{return _fGstack;}
/*:5*/
#line 11 "./korder_stoch.cweb"
;
/*:1*/

View File

@ -0,0 +1,444 @@
/*1:*/
#line 40 "./korder_stoch.hweb"
#include "korder.h"
#include "faa_di_bruno.h"
#include "journal.h"
/*2:*/
#line 60 "./korder_stoch.hweb"
template<int t>
class IntegDerivs:public ctraits<t> ::Tgss{
public:
/*3:*/
#line 106 "./korder_stoch.hweb"
IntegDerivs(int r,const IntSequence&nvs,const _Tgss&g,const _Tm&mom,
double at_sigma)
:ctraits<t> ::Tgss(4)
{
int maxd= g.getMaxDim();
for(int d= 1;d<=maxd;d++){
for(int i= 0;i<=d;i++){
int p= d-i;
Symmetry sym(i,0,0,p);
_Ttensor*ten= new _Ttensor(r,TensorDimens(sym,nvs));
/*4:*/
#line 129 "./korder_stoch.hweb"
ten->zeros();
for(int n= 0;n<=p;n++){
int k= p-n;
int povern= Tensor::noverk(p,n);
int mfac= 1;
for(int m= 0;i+m+n+k<=maxd;m++,mfac*= m){
double mult= (pow(at_sigma,m)*povern)/mfac;
Symmetry sym_mn(i,m+n,0,k);
if(m+n==0&&g.check(sym_mn))
ten->add(mult,*(g.get(sym_mn)));
if(m+n> 0&&KOrder::is_even(m+n)&&g.check(sym_mn)){
_Ttensor gtmp(*(g.get(sym_mn)));
gtmp.mult(mult);
gtmp.contractAndAdd(1,*ten,*(mom.get(Symmetry(m+n))));
}
}
}
/*:4*/
#line 117 "./korder_stoch.hweb"
;
insert(ten);
}
}
}
/*:3*/
#line 64 "./korder_stoch.hweb"
;
};
/*:2*/
#line 46 "./korder_stoch.hweb"
;
/*5:*/
#line 156 "./korder_stoch.hweb"
template<int t>
class StochForwardDerivs:public ctraits<t> ::Tgss{
public:
/*6:*/
#line 180 "./korder_stoch.hweb"
StochForwardDerivs(const PartitionY&ypart,int nu,
const _Tgss&g,const _Tm&m,
const Vector&ydelta,double sdelta,
double at_sigma)
:ctraits<t> ::Tgss(4)
{
int maxd= g.getMaxDim();
int r= ypart.nyss();
/*7:*/
#line 201 "./korder_stoch.hweb"
IntSequence nvs(4);
nvs[0]= ypart.nys();nvs[1]= 0;nvs[2]= 0;nvs[3]= 1;
IntegDerivs<t> g_int(r,nvs,g,m,at_sigma);
/*:7*/
#line 190 "./korder_stoch.hweb"
;
/*8:*/
#line 209 "./korder_stoch.hweb"
_Tpol g_int_sym(r,ypart.nys()+1);
for(int d= 1;d<=maxd;d++){
_Ttensym*ten= new _Ttensym(r,ypart.nys()+1,d);
ten->zeros();
for(int i= 0;i<=d;i++){
int k= d-i;
if(g_int.check(Symmetry(i,0,0,k)))
ten->addSubTensor(*(g_int.get(Symmetry(i,0,0,k))));
}
g_int_sym.insert(ten);
}
/*:8*/
#line 191 "./korder_stoch.hweb"
;
/*9:*/
#line 229 "./korder_stoch.hweb"
Vector delta(ypart.nys()+1);
Vector dy(delta,0,ypart.nys());
ConstVector dy_in(ydelta,ypart.nstat,ypart.nys());
dy= dy_in;
delta[ypart.nys()]= sdelta;
_Tpol g_int_cent(r,ypart.nys()+1);
for(int d= 1;d<=maxd;d++){
g_int_sym.derivative(d-1);
_Ttensym*der= g_int_sym.evalPartially(d,delta);
g_int_cent.insert(der);
}
/*:9*/
#line 192 "./korder_stoch.hweb"
;
/*10:*/
#line 245 "./korder_stoch.hweb"
IntSequence ss(4);
ss[0]= ypart.nys();ss[1]= 0;ss[2]= 0;ss[3]= 1;
IntSequence pp(4);
pp[0]= 0;pp[1]= 1;pp[2]= 2;pp[3]= 3;
IntSequence true_nvs(nvs);
true_nvs[1]= nu;true_nvs[2]= nu;
for(int d= 1;d<=maxd;d++){
if(g_int_cent.check(Symmetry(d))){
for(int i= 0;i<=d;i++){
Symmetry sym(i,0,0,d-i);
IntSequence coor(sym,pp);
_Ttensor*ten= new _Ttensor(*(g_int_cent.get(Symmetry(d))),ss,coor,
TensorDimens(sym,true_nvs));
insert(ten);
}
}
}
/*:10*/
#line 193 "./korder_stoch.hweb"
;
}
/*:6*/
#line 160 "./korder_stoch.hweb"
;
};
/*:5*/
#line 47 "./korder_stoch.hweb"
;
/*11:*/
#line 270 "./korder_stoch.hweb"
template<class _Ttype>
class GXContainer:public GContainer<_Ttype> {
public:
typedef StackContainerInterface<_Ttype> _Stype;
typedef typename StackContainer<_Ttype> ::_Ctype _Ctype;
typedef typename StackContainer<_Ttype> ::itype itype;
GXContainer(const _Ctype*gs,int ngs,int nu)
:GContainer<_Ttype> (gs,ngs,nu){}
/*12:*/
#line 285 "./korder_stoch.hweb"
itype getType(int i,const Symmetry&s)const
{
if(i==0)
if(s[2]> 0)
return _Stype::zero;
else
return _Stype::matrix;
if(i==1)
return _Stype::zero;
if(i==2)
return _Stype::zero;
if(i==3)
if(s==Symmetry(0,0,0,1))
return _Stype::unit;
else
return _Stype::zero;
KORD_RAISE("Wrong stack index in GXContainer::getType");
}
/*:12*/
#line 279 "./korder_stoch.hweb"
;
};
/*:11*/
#line 48 "./korder_stoch.hweb"
;
/*13:*/
#line 312 "./korder_stoch.hweb"
template<class _Ttype>
class ZXContainer:public ZContainer<_Ttype> {
public:
typedef StackContainerInterface<_Ttype> _Stype;
typedef typename StackContainer<_Ttype> ::_Ctype _Ctype;
typedef typename StackContainer<_Ttype> ::itype itype;
ZXContainer(const _Ctype*gss,int ngss,const _Ctype*g,int ng,int ny,int nu)
:ZContainer<_Ttype> (gss,ngss,g,ng,ny,nu){}
/*14:*/
#line 327 "./korder_stoch.hweb"
itype getType(int i,const Symmetry&s)const
{
if(i==0)
if(s[2]> 0)
return _Stype::zero;
else
return _Stype::matrix;
if(i==1)
if(s[2]> 0)
return _Stype::zero;
else
return _Stype::matrix;
if(i==2)
if(s==Symmetry(1,0,0,0))
return _Stype::unit;
else
return _Stype::zero;
if(i==3)
if(s==Symmetry(0,1,0,0))
return _Stype::unit;
else
return _Stype::zero;
KORD_RAISE("Wrong stack index in ZXContainer::getType");
}
/*:14*/
#line 321 "./korder_stoch.hweb"
;
};
/*:13*/
#line 49 "./korder_stoch.hweb"
;
/*15:*/
#line 355 "./korder_stoch.hweb"
class UnfoldedGXContainer:public GXContainer<UGSTensor> ,public UnfoldedStackContainer{
public:
typedef TensorContainer<UGSTensor> _Ctype;
UnfoldedGXContainer(const _Ctype*gs,int ngs,int nu)
:GXContainer<UGSTensor> (gs,ngs,nu){}
};
/*:15*/
#line 50 "./korder_stoch.hweb"
;
/*16:*/
#line 364 "./korder_stoch.hweb"
class FoldedGXContainer:public GXContainer<FGSTensor> ,public FoldedStackContainer{
public:
typedef TensorContainer<FGSTensor> _Ctype;
FoldedGXContainer(const _Ctype*gs,int ngs,int nu)
:GXContainer<FGSTensor> (gs,ngs,nu){}
};
/*:16*/
#line 51 "./korder_stoch.hweb"
;
/*17:*/
#line 373 "./korder_stoch.hweb"
class UnfoldedZXContainer:public ZXContainer<UGSTensor> ,public UnfoldedStackContainer{
public:
typedef TensorContainer<UGSTensor> _Ctype;
UnfoldedZXContainer(const _Ctype*gss,int ngss,const _Ctype*g,int ng,int ny,int nu)
:ZXContainer<UGSTensor> (gss,ngss,g,ng,ny,nu){}
};
/*:17*/
#line 52 "./korder_stoch.hweb"
;
/*18:*/
#line 382 "./korder_stoch.hweb"
class FoldedZXContainer:public ZXContainer<FGSTensor> ,public FoldedStackContainer{
public:
typedef TensorContainer<FGSTensor> _Ctype;
FoldedZXContainer(const _Ctype*gss,int ngss,const _Ctype*g,int ng,int ny,int nu)
:ZXContainer<FGSTensor> (gss,ngss,g,ng,ny,nu){}
};
/*:18*/
#line 53 "./korder_stoch.hweb"
;
/*19:*/
#line 397 "./korder_stoch.hweb"
class MatrixAA:public PLUMatrix{
public:
MatrixAA(const FSSparseTensor&f,const IntSequence&ss,
const TwoDMatrix&gyss,const PartitionY&ypart);
};
/*:19*/
#line 54 "./korder_stoch.hweb"
;
/*20:*/
#line 418 "./korder_stoch.hweb"
class KOrderStoch{
protected:
IntSequence nvs;
PartitionY ypart;
Journal&journal;
UGSContainer _ug;
FGSContainer _fg;
UGSContainer _ugs;
FGSContainer _fgs;
UGSContainer _uG;
FGSContainer _fG;
const UGSContainer*_uh;
const FGSContainer*_fh;
UnfoldedZXContainer _uZstack;
FoldedZXContainer _fZstack;
UnfoldedGXContainer _uGstack;
FoldedGXContainer _fGstack;
const TensorContainer<FSSparseTensor> &f;
MatrixAA matA;
public:
KOrderStoch(const PartitionY&ypart,int nu,const TensorContainer<FSSparseTensor> &fcont,
const FGSContainer&hh,Journal&jr);
KOrderStoch(const PartitionY&ypart,int nu,const TensorContainer<FSSparseTensor> &fcont,
const UGSContainer&hh,Journal&jr);
/*23:*/
#line 496 "./korder_stoch.hweb"
template<int t>
void performStep(int order)
{
int maxd= g<t> ().getMaxDim();
KORD_RAISE_IF(order-1!=maxd&&(order!=1||maxd!=-1),
"Wrong order for KOrderStoch::performStep");
SymmetrySet ss(order,4);
for(symiterator si(ss);!si.isEnd();++si){
if((*si)[2]==0){
JournalRecordPair pa(journal);
pa<<"Recovering symmetry "<<*si<<endrec;
_Ttensor*G_sym= faaDiBrunoG<t> (*si);
G<t> ().insert(G_sym);
_Ttensor*g_sym= faaDiBrunoZ<t> (*si);
g_sym->mult(-1.0);
matA.multInv(*g_sym);
g<t> ().insert(g_sym);
gs<t> ().insert(new _Ttensor(ypart.nstat,ypart.nys(),*g_sym));
Gstack<t> ().multAndAdd(1,h<t> (),*G_sym);
}
}
}
/*:23*/
#line 443 "./korder_stoch.hweb"
;
const FGSContainer&getFoldDers()const
{return _fg;}
const UGSContainer&getUnfoldDers()const
{return _ug;}
protected:
/*21:*/
#line 457 "./korder_stoch.hweb"
template<int t>
_Ttensor*faaDiBrunoZ(const Symmetry&sym)const
{
JournalRecordPair pa(journal);
pa<<"Faa Di Bruno ZX container for "<<sym<<endrec;
_Ttensor*res= new _Ttensor(ypart.ny(),TensorDimens(sym,nvs));
FaaDiBruno bruno(journal);
bruno.calculate(Zstack<t> (),f,*res);
return res;
}
/*:21*/
#line 449 "./korder_stoch.hweb"
;
/*22:*/
#line 472 "./korder_stoch.hweb"
template<int t>
_Ttensor*faaDiBrunoG(const Symmetry&sym)const
{
JournalRecordPair pa(journal);
pa<<"Faa Di Bruno GX container for "<<sym<<endrec;
TensorDimens tdims(sym,nvs);
_Ttensor*res= new _Ttensor(ypart.nyss(),tdims);
FaaDiBruno bruno(journal);
bruno.calculate(Gstack<t> (),h<t> (),*res);
return res;
}
/*:22*/
#line 450 "./korder_stoch.hweb"
;
/*24:*/
#line 524 "./korder_stoch.hweb"
template<int t> _Tg&g();
template<int t> const _Tg&g()const;
template<int t> _Tgs&gs();
template<int t> const _Tgs&gs()const;
template<int t> const _Tgss&h()const;
template<int t> _TG&G();
template<int t> const _TG&G()const;
template<int t> _TZXstack&Zstack();
template<int t> const _TZXstack&Zstack()const;
template<int t> _TGXstack&Gstack();
template<int t> const _TGXstack&Gstack()const;
/*:24*/
#line 451 "./korder_stoch.hweb"
;
};
/*:20*/
#line 55 "./korder_stoch.hweb"
;
/*:1*/

View File

@ -0,0 +1,157 @@
/*1:*/
#line 14 "./mersenne_twister.hweb"
#ifndef MERSENNE_TWISTER_H
#define MERSENNE_TWISTER_H
#include "random.h"
#include <string.h>
/*2:*/
#line 27 "./mersenne_twister.hweb"
class MersenneTwister:public RandomGenerator{
protected:
typedef unsigned int uint32;
enum{STATE_SIZE= 624};
enum{RECUR_OFFSET= 397};
uint32 statevec[STATE_SIZE];
int stateptr;
public:
MersenneTwister(uint32 iseed);
MersenneTwister(const MersenneTwister&mt);
virtual~MersenneTwister(){}
uint32 lrand();
double drand();
double uniform()
{return drand();}
protected:
void seed(uint32 iseed);
void refresh();
private:
/*3:*/
#line 51 "./mersenne_twister.hweb"
static uint32 hibit(uint32 u)
{return u&0x80000000UL;}
static uint32 lobit(uint32 u)
{return u&0x00000001UL;}
static uint32 lobits(uint32 u)
{return u&0x7fffffffUL;}
static uint32 mixbits(uint32 u,uint32 v)
{return hibit(u)|lobits(v);}
static uint32 twist(uint32 m,uint32 s0,uint32 s1)
{return m^(mixbits(s0,s1)>>1)^(-lobit(s1)&0x9908b0dfUL);}
/*:3*/
#line 47 "./mersenne_twister.hweb"
;
};
/*:2*/
#line 21 "./mersenne_twister.hweb"
;
/*4:*/
#line 65 "./mersenne_twister.hweb"
/*5:*/
#line 74 "./mersenne_twister.hweb"
inline MersenneTwister::MersenneTwister(uint32 iseed)
{
seed(iseed);
}
/*:5*/
#line 66 "./mersenne_twister.hweb"
;
/*6:*/
#line 81 "./mersenne_twister.hweb"
inline MersenneTwister::MersenneTwister(const MersenneTwister&mt)
:stateptr(mt.stateptr)
{
memcpy(statevec,mt.statevec,sizeof(uint32)*STATE_SIZE);
}
/*:6*/
#line 67 "./mersenne_twister.hweb"
;
/*7:*/
#line 89 "./mersenne_twister.hweb"
inline MersenneTwister::uint32 MersenneTwister::lrand()
{
if(stateptr>=STATE_SIZE)
refresh();
register uint32 v= statevec[stateptr++];
v^= v>>11;
v^= (v<<7)&0x9d2c5680;
v^= (v<<15)&0xefc60000;
return(v^(v>>18));
}
/*:7*/
#line 68 "./mersenne_twister.hweb"
;
/*8:*/
#line 103 "./mersenne_twister.hweb"
inline double MersenneTwister::drand()
{
uint32 a= lrand()>>5;
uint32 b= lrand()>>6;
return(a*67108864.0+b)*(1.0/9007199254740992.0);
}
/*:8*/
#line 69 "./mersenne_twister.hweb"
;
/*9:*/
#line 112 "./mersenne_twister.hweb"
inline void MersenneTwister::seed(uint32 iseed)
{
statevec[0]= iseed&0xffffffffUL;
for(int i= 1;i<STATE_SIZE;i++){
register uint32 val= statevec[i-1]>>30;
val^= statevec[i-1];
val*= 1812433253ul;
val+= i;
statevec[i]= val&0xffffffffUL;
}
refresh();
}
/*:9*/
#line 70 "./mersenne_twister.hweb"
;
/*10:*/
#line 128 "./mersenne_twister.hweb"
inline void MersenneTwister::refresh()
{
register uint32*p= statevec;
for(int i= STATE_SIZE-RECUR_OFFSET;i--;++p)
*p= twist(p[RECUR_OFFSET],p[0],p[1]);
for(int i= RECUR_OFFSET;--i;++p)
*p= twist(p[RECUR_OFFSET-STATE_SIZE],p[0],p[1]);
*p= twist(p[RECUR_OFFSET-STATE_SIZE],p[0],statevec[0]);
stateptr= 0;
}
/*:10*/
#line 71 "./mersenne_twister.hweb"
;
/*:4*/
#line 22 "./mersenne_twister.hweb"
;
#endif
/*:1*/

View File

@ -0,0 +1,130 @@
/*1:*/
#line 6 "./normal_conjugate.cweb"
#include "normal_conjugate.h"
#include "kord_exception.h"
/*2:*/
#line 20 "./normal_conjugate.cweb"
NormalConj::NormalConj(int d)
:mu(d),kappa(0),nu(-1),lambda(d,d)
{
mu.zeros();
lambda.zeros();
}
/*:2*/
#line 11 "./normal_conjugate.cweb"
;
/*3:*/
#line 29 "./normal_conjugate.cweb"
NormalConj::NormalConj(const ConstTwoDMatrix&ydata)
:mu(ydata.numRows()),kappa(ydata.numCols()),nu(ydata.numCols()-1),
lambda(ydata.numRows(),ydata.numRows())
{
mu.zeros();
for(int i= 0;i<ydata.numCols();i++)
mu.add(1.0/ydata.numCols(),ConstVector(ydata,i));
lambda.zeros();
for(int i= 0;i<ydata.numCols();i++){
Vector diff(ConstVector(ydata,i));
diff.add(-1,mu);
lambda.addOuter(diff);
}
}
/*:3*/
#line 12 "./normal_conjugate.cweb"
;
/*4:*/
#line 47 "./normal_conjugate.cweb"
NormalConj::NormalConj(const NormalConj&nc)
:mu(nc.mu),kappa(nc.kappa),nu(nc.nu),lambda(nc.lambda)
{
}
/*:4*/
#line 13 "./normal_conjugate.cweb"
;
/*5:*/
#line 61 "./normal_conjugate.cweb"
void NormalConj::update(const ConstVector&y)
{
KORD_RAISE_IF(y.length()!=mu.length(),
"Wrong length of a vector in NormalConj::update");
mu.mult(kappa/(1.0+kappa));
mu.add(1.0/(1.0+kappa),y);
Vector diff(y);
diff.add(-1,mu);
lambda.addOuter(diff,kappa/(1.0+kappa));
kappa++;
nu++;
}
/*:5*/
#line 14 "./normal_conjugate.cweb"
;
/*6:*/
#line 80 "./normal_conjugate.cweb"
void NormalConj::update(const ConstTwoDMatrix&ydata)
{
NormalConj nc(ydata);
update(nc);
}
/*:6*/
#line 15 "./normal_conjugate.cweb"
;
/*7:*/
#line 89 "./normal_conjugate.cweb"
void NormalConj::update(const NormalConj&nc)
{
double wold= ((double)kappa)/(kappa+nc.kappa);
double wnew= 1-wold;
mu.mult(wold);
mu.add(wnew,nc.mu);
Vector diff(nc.mu);
diff.add(-1,mu);
lambda.add(1.0,nc.lambda);
lambda.addOuter(diff);
kappa= kappa+nc.kappa;
nu= nu+nc.kappa;
}
/*:7*/
#line 16 "./normal_conjugate.cweb"
;
/*8:*/
#line 112 "./normal_conjugate.cweb"
void NormalConj::getVariance(TwoDMatrix&v)const
{
if(nu> getDim()+1){
v= (const TwoDMatrix&)lambda;
v.mult(1.0/(nu-getDim()-1));
}else
v.nans();
}
/*:8*/
#line 17 "./normal_conjugate.cweb"
;
/*:1*/

View File

@ -0,0 +1,47 @@
/*1:*/
#line 37 "./normal_conjugate.hweb"
#ifndef NORMAL_CONJUGATE_H
#define NORMAL_CONJUGATE_H
#include "twod_matrix.h"
/*2:*/
#line 49 "./normal_conjugate.hweb"
class NormalConj{
protected:
Vector mu;
int kappa;
int nu;
TwoDMatrix lambda;
public:
/*3:*/
#line 76 "./normal_conjugate.hweb"
NormalConj(int d);
NormalConj(const ConstTwoDMatrix&ydata);
NormalConj(const NormalConj&nc);
/*:3*/
#line 57 "./normal_conjugate.hweb"
;
virtual~NormalConj(){}
void update(const ConstVector&y);
void update(const ConstTwoDMatrix&ydata);
void update(const NormalConj&nc);
int getDim()const
{return mu.length();}
const Vector&getMean()const
{return mu;}
void getVariance(TwoDMatrix&v)const;
};
/*:2*/
#line 43 "./normal_conjugate.hweb"
;
#endif
/*:1*/

View File

@ -0,0 +1,73 @@
/*1:*/
#line 5 "./random.cweb"
#include "random.h"
#include <stdlib.h>
#include <limits>
#include <cmath>
/*2:*/
#line 20 "./random.cweb"
int RandomGenerator::int_uniform()
{
double s= std::numeric_limits<int> ::max()*uniform();
return(int)s;
}
/*:2*/
#line 13 "./random.cweb"
;
/*3:*/
#line 28 "./random.cweb"
double RandomGenerator::normal()
{
double x1,x2;
double w;
do{
x1= 2*uniform()-1;
x2= 2*uniform()-1;
w= x1*x1+x2*x2;
}while(w>=1.0||w<1.0e-30);
return x1*std::sqrt((-2.0*std::log(w))/w);
}
/*:3*/
#line 14 "./random.cweb"
;
SystemRandomGenerator system_random_generator;
/*4:*/
#line 42 "./random.cweb"
double SystemRandomGenerator::uniform()
{
#ifndef __MINGW32__
return drand48();
#else
return((double)rand())/RAND_MAX;
#endif
}
/*:4*/
#line 16 "./random.cweb"
;
/*5:*/
#line 53 "./random.cweb"
void SystemRandomGenerator::initSeed(int seed)
{
#ifndef __MINGW32__
srand48(seed);
#else
srand(seed);
#endif
}
/*:5*/
#line 17 "./random.cweb"
;
/*:1*/

View File

@ -0,0 +1,36 @@
/*1:*/
#line 9 "./random.hweb"
#ifndef RANDOM_H
#define RANDOM_H
/*2:*/
#line 22 "./random.hweb"
class RandomGenerator{
public:
virtual double uniform()= 0;
int int_uniform();
double normal();
};
/*:2*/
#line 13 "./random.hweb"
;
/*3:*/
#line 32 "./random.hweb"
class SystemRandomGenerator:public RandomGenerator{
public:
double uniform();
void initSeed(int seed);
};
/*:3*/
#line 14 "./random.hweb"
;
extern SystemRandomGenerator system_random_generator;
#endif
/*:1*/

View File

@ -0,0 +1,413 @@
/* $Id: tests.cpp 148 2005-04-19 15:12:26Z kamenik $ */
/* Copyright 2004, Ondra Kamenik */
#include "korder.h"
#include "SylvException.h"
struct Rand {
static void init(int n1, int n2, int n3, int n4, int n5);
static double get(double m);
static int get(int m);
static bool discrete(double prob); // answers true with given probability
};
void Rand::init(int n1, int n2, int n3, int n4, int n5)
{
long int seed = n1;
seed = 256*seed+n2;
seed = 256*seed+n3;
seed = 256*seed+n4;
seed = 256*seed+n5;
srand48(seed);
}
double Rand::get(double m)
{
return 2*m*(drand48()-0.5);
}
int Rand::get(int m)
{
return (int)(Rand::get(0.9999*m));
}
bool Rand::discrete(double prob)
{
return drand48() < prob;
}
struct SparseGenerator {
static FSSparseTensor* makeTensor(int dim, int nv, int r,
double fill, double m);
static void fillContainer(TensorContainer<FSSparseTensor>& c,
int maxdim, int nv, int r, double m);
};
FSSparseTensor* SparseGenerator::makeTensor(int dim, int nv, int r,
double fill, double m)
{
FSSparseTensor* res = new FSSparseTensor(dim, nv, r);
FFSTensor dummy(0, nv, dim);
for (Tensor::index fi = dummy.begin(); fi != dummy.end(); ++fi) {
for (int i = 0; i < r; i++) {
if (Rand::discrete(fill)) {
double x = Rand::get(m);
res->insert(fi.getCoor(), i, x);
}
}
}
return res;
}
void SparseGenerator::fillContainer(TensorContainer<FSSparseTensor>& c,
int maxdim, int nv, int r,
double m)
{
Rand::init(maxdim, nv, r, (int)(5*m), 0);
double fill = 0.5;
for (int d = 1; d <= maxdim; d++) {
c.insert(makeTensor(d,nv,r,fill,m));
fill *= 0.3;
}
}
const double vdata [] = { // 3x3
0.1307870268, 0.1241940078, 0.1356703123,
0.1241940078, 0.1986920419, 0.2010160581,
0.1356703123, 0.2010160581, 0.2160336975
};
const double gy_data [] = { // 8x4
0.3985178619, -0.5688233582, 0.9572900437, -0.6606847776, 0.1453004017,
0.3025310675, -0.8627437750, -0.6903410191, 0.4751910580, -0.7270018589,
-0.0939612498, -0.1463831989, 0.6742110220, 0.6046671043, 0.5215893126,
-1.0412969986, -0.3524898417, -1.0986703430, 0.8006531522, 0.8879776376,
-0.1037608317, -0.5587378073, -0.1010366945, 0.9462411248, -0.2439199881,
1.3420621236, -0.7820285935, 0.3205293447, 0.3606124791, 0.2975422208,
-0.5452861965, 1.6320340279
};
const double gu_data [] = { // just some numbers, no structure
1.8415286914, -0.2638743845, 1.7690713274, 0.9668585956, 0.2303143646,
-0.2229624279, -0.4381991822, 1.0082401405, -0.3186555860, -0.0624691529,
-0.5189085756, 1.4269672156, 0.1163282969, 1.4020183445, -0.0952660426,
0.2099097124, 0.6912400502, -0.5180935114, 0.5288316624, 0.2188053448,
0.5715516767, 0.7813893410, -0.6385073106, 0.8335131513, 0.3605202168,
-1.1167944865, -1.2263750934, 0.6113636081, 0.6964915482, -0.6451217688,
0.4062810500, -2.0552251116, -1.6383406284, 0.0198915095, 0.0111014458,
-1.2421792262, -1.0724161722, -0.4276904972, 0.1801494950, -2.0716473264
};
const double vdata2 [] = { // 10x10 positive definite
0.79666, -0.15536, 0.05667, -0.21026, 0.20262, 0.28505, 0.60341, -0.09703, 0.32363, 0.13299,
-0.15536, 0.64380, -0.01131, 0.00980, 0.03755, 0.43791, 0.21784, -0.31755, -0.55911, -0.29655,
0.05667, -0.01131, 0.56165, -0.34357, -0.40584, 0.20990, 0.28348, 0.20398, -0.19856, 0.35820,
-0.21026, 0.00980, -0.34357, 0.56147, 0.10972, -0.34146, -0.49906, -0.19685, 0.21088, -0.31560,
0.20262, 0.03755, -0.40584, 0.10972, 0.72278, 0.02155, 0.04089, -0.19696, 0.03446, -0.12919,
0.28505, 0.43791, 0.20990, -0.34146, 0.02155, 0.75867, 0.77699, -0.31125, -0.55141, -0.02155,
0.60341, 0.21784, 0.28348, -0.49906, 0.04089, 0.77699, 1.34553, -0.18613, -0.25811, -0.19016,
-0.09703, -0.31755, 0.20398, -0.19685, -0.19696, -0.31125, -0.18613, 0.59470, 0.08386, 0.41750,
0.32363, -0.55911, -0.19856, 0.21088, 0.03446, -0.55141, -0.25811, 0.08386, 0.98917, -0.12992,
0.13299, -0.29655, 0.35820, -0.31560, -0.12919, -0.02155, -0.19016, 0.41750, -0.12992, 0.89608
};
const double gy_data2 [] = { // 600 items make gy 30x20, whose gy(6:25,:) has spectrum within unit
0.39414, -0.29766, 0.08948, -0.19204, -0.00750, 0.21159, 0.05494, 0.06225, 0.01771, 0.21913,
-0.01373, 0.20086, -0.06086, -0.10955, 0.14424, -0.08390, 0.03948, -0.14713, 0.11674, 0.05091,
0.24039, 0.28307, -0.11835, 0.13030, 0.11682, -0.27444, -0.19311, -0.16654, 0.12867, 0.25116,
-0.19781, 0.45242, -0.15862, 0.24428, -0.11966, 0.11483, -0.32279, 0.29727, 0.20934, -0.18190,
-0.15080, -0.09477, -0.30551, -0.02672, -0.26919, 0.11165, -0.06390, 0.03449, -0.26622, 0.22197,
0.45141, -0.41683, 0.09760, 0.31094, -0.01652, 0.05809, -0.04514, -0.05645, 0.00554, 0.47980,
0.11726, 0.42459, -0.13136, -0.30902, -0.14648, 0.11455, 0.02947, -0.03835, -0.04044, 0.03559,
-0.26575, -0.01783, 0.31243, -0.14412, -0.13218, -0.05080, 0.18576, 0.13840, -0.05560, 0.35530,
-0.25573, -0.11560, 0.15187, -0.18431, 0.08193, -0.32278, 0.17560, -0.05529, -0.10020, -0.23088,
-0.20979, -0.49245, 0.09915, -0.16909, -0.03443, 0.19497, 0.18473, 0.25662, 0.29605, -0.20531,
-0.39244, -0.43369, 0.05588, 0.24823, -0.14236, -0.08311, 0.16371, -0.19975, 0.30605, -0.17087,
-0.01270, 0.00123, -0.22426, -0.13810, 0.05079, 0.06971, 0.01922, -0.09952, -0.23177, -0.41962,
-0.41991, 0.41430, -0.04247, -0.13706, -0.12048, -0.28906, -0.22813, -0.25057, -0.18579, -0.20642,
-0.47976, 0.25490, -0.05138, -0.30794, 0.31651, 0.02034, 0.12954, -0.20110, 0.13336, -0.40775,
-0.30195, -0.13704, 0.12396, 0.28152, 0.02986, 0.27669, 0.24623, 0.08635, -0.11956, -0.02949,
0.37401, 0.20838, 0.24801, -0.26872, 0.11195, 0.00315, -0.19069, 0.12839, -0.23036, -0.48228,
0.08434, -0.39872, -0.28896, -0.28754, 0.24668, 0.23285, 0.25437, 0.10456, -0.14124, 0.20483,
-0.19117, -0.33836, -0.24875, 0.08207, -0.03930, 0.20364, 0.15384, -0.15270, 0.24372, -0.11199,
-0.46591, 0.30319, 0.05745, 0.09084, 0.06058, 0.31884, 0.05071, -0.28899, -0.30793, -0.03566,
0.02286, 0.28178, 0.00736, -0.31378, -0.18144, -0.22346, -0.27239, 0.31043, -0.26228, 0.22181,
-0.15096, -0.36953, -0.06032, 0.21496, 0.29545, -0.13112, 0.16420, -0.07573, -0.43111, -0.43057,
0.26716, -0.31209, -0.05866, -0.29101, -0.27437, -0.18727, 0.28732, -0.19014, 0.08837, 0.30405,
0.06103, -0.35612, 0.00173, 0.25134, -0.08987, -0.22766, -0.03254, -0.18662, -0.08491, 0.49401,
-0.12145, -0.02961, -0.03668, -0.30043, -0.08555, 0.01701, -0.12544, 0.10969, -0.48202, 0.07245,
0.20673, 0.11408, 0.04343, -0.01815, -0.31594, -0.23632, -0.06258, -0.27474, 0.12180, 0.16613,
-0.37931, 0.30219, 0.15765, 0.25489, 0.17529, -0.17020, -0.30060, 0.22058, -0.02450, -0.42143,
0.49642, 0.46899, -0.28552, -0.22549, -0.01333, 0.21567, 0.22251, 0.21639, -0.19194, -0.19140,
-0.24106, 0.10952, -0.11019, 0.29763, -0.02039, -0.25748, 0.23169, 0.01357, 0.09802, -0.19022,
0.37604, -0.40777, 0.18131, -0.10258, 0.29573, -0.31773, 0.09069, -0.02198, -0.26594, 0.48302,
-0.10041, 0.20210, -0.05609, -0.01169, -0.17339, 0.17862, -0.22502, 0.29009, -0.45160, 0.19771,
0.27634, 0.31695, -0.09993, 0.17167, 0.12394, 0.28088, -0.12502, -0.16967, -0.06296, -0.17036,
0.27320, 0.01595, 0.16955, 0.30146, -0.15173, -0.29807, 0.08178, -0.06811, 0.21655, 0.26348,
0.06316, 0.45661, -0.29756, -0.05742, -0.14715, -0.03037, -0.16656, -0.08768, 0.38078, 0.40679,
-0.32779, -0.09106, 0.16107, -0.07301, 0.07700, -0.22694, -0.15692, -0.02548, 0.38749, -0.12203,
-0.02980, -0.22067, 0.00680, -0.23058, -0.29112, 0.23032, -0.16026, 0.23392, -0.09990, 0.03628,
-0.42592, -0.33474, -0.09499, -0.17442, -0.20110, 0.24618, -0.06418, -0.06715, 0.40754, 0.29377,
0.29543, -0.16832, -0.08468, 0.06491, -0.01410, 0.19988, 0.24950, 0.14626, -0.27851, 0.06079,
0.48134, -0.13475, 0.25398, 0.11738, 0.23369, -0.00661, -0.16811, -0.04557, -0.12030, -0.39527,
-0.35760, 0.01840, -0.15941, 0.03290, 0.09988, -0.08307, 0.06644, -0.24637, 0.34112, -0.08026,
0.00951, 0.27656, 0.16247, 0.28217, 0.17198, -0.16389, -0.03835, -0.02675, -0.08032, -0.21045,
-0.38946, 0.23207, 0.10987, -0.31674, -0.28653, -0.27430, -0.29109, -0.00648, 0.38431, -0.38478,
-0.41195, -0.19364, -0.20977, -0.05524, 0.05558, -0.20109, 0.11803, -0.19884, 0.43318, -0.39255,
0.26612, -0.21771, 0.12471, 0.12856, -0.15104, -0.11676, 0.17582, -0.25330, 0.00298, -0.31712,
0.21532, -0.20319, 0.14507, -0.04588, -0.22995, -0.06470, 0.18849, -0.13444, 0.37107, 0.07387,
-0.14008, 0.09896, 0.13727, -0.28417, -0.09461, -0.18703, 0.04080, 0.02343, -0.49988, 0.17993,
0.23189, -0.30581, -0.18334, -0.09667, -0.27699, -0.05998, 0.09118, -0.32453, 0.46251, 0.41500,
-0.45314, -0.00544, 0.08529, 0.29099, -0.00937, -0.31650, 0.26163, 0.14506, 0.37498, -0.16454,
0.35215, 0.31642, -0.09161, -0.31452, -0.04792, -0.04677, -0.19523, 0.27998, 0.05491, 0.44461,
-0.01258, -0.27887, 0.18361, -0.04539, -0.02977, 0.30821, 0.29454, -0.17932, 0.16193, 0.23934,
0.47923, 0.25373, 0.23258, 0.31484, -0.17958, -0.01136, 0.17681, 0.12869, 0.03235, 0.43762,
0.13734, -0.09433, -0.03735, 0.17949, 0.14122, -0.17814, 0.06359, 0.16044, 0.12249, -0.22314,
0.40775, 0.05147, 0.12389, 0.04290, -0.01642, 0.00082, -0.18056, 0.02875, 0.32690, 0.17712,
0.34001, -0.21581, -0.01086, -0.18180, 0.17480, -0.17774, -0.07503, 0.28438, -0.19747, 0.29595,
-0.28002, -0.02073, -0.16522, -0.18234, -0.20565, 0.29620, 0.07502, 0.01429, -0.31418, 0.43693,
-0.12212, 0.11178, -0.28503, 0.04683, 0.00072, 0.05566, 0.18857, 0.26101, -0.38891, -0.21216,
-0.21850, -0.15147, -0.30749, -0.23762, 0.14984, 0.03535, -0.02862, -0.00105, -0.39907, -0.06909,
-0.36094, 0.21717, 0.15930, -0.18924, 0.13741, 0.01039, 0.13613, 0.00659, 0.07676, -0.13711,
0.24285, -0.07564, -0.28349, -0.15658, 0.03135, -0.30909, -0.22534, 0.17363, -0.19376, 0.26038,
0.05546, -0.22607, 0.32420, -0.02552, -0.05400, 0.13388, 0.04643, -0.31535, -0.06181, 0.30237,
-0.04680, -0.29441, 0.12231, 0.03960, -0.01188, 0.01406, 0.25402, 0.03315, 0.25026, -0.10922
};
const double gu_data2 [] = { // raw data 300 items
0.26599, 0.41329, 0.31846, 0.92590, 0.43050, 0.17466, 0.02322, 0.72621, 0.37921, 0.70597,
0.97098, 0.14023, 0.57619, 0.09938, 0.02281, 0.92341, 0.72654, 0.71000, 0.76687, 0.70182,
0.88752, 0.49524, 0.42549, 0.42806, 0.57615, 0.76051, 0.15341, 0.47457, 0.60066, 0.40880,
0.20668, 0.41949, 0.97620, 0.94318, 0.71491, 0.56402, 0.23553, 0.94387, 0.78567, 0.06362,
0.85252, 0.86262, 0.25190, 0.03274, 0.93216, 0.37971, 0.08797, 0.14596, 0.73871, 0.06574,
0.67447, 0.28575, 0.43911, 0.92133, 0.12327, 0.87762, 0.71060, 0.07141, 0.55443, 0.53310,
0.91529, 0.25121, 0.07593, 0.94490, 0.28656, 0.82174, 0.68887, 0.67337, 0.99291, 0.03316,
0.02849, 0.33891, 0.25594, 0.90071, 0.01248, 0.67871, 0.65953, 0.65369, 0.97574, 0.31578,
0.23678, 0.39220, 0.06706, 0.80943, 0.57694, 0.08220, 0.18151, 0.19969, 0.37096, 0.37858,
0.70153, 0.46816, 0.76511, 0.02520, 0.39387, 0.25527, 0.39050, 0.60141, 0.30322, 0.46195,
0.12025, 0.33616, 0.04174, 0.00196, 0.68886, 0.74445, 0.15869, 0.18994, 0.95195, 0.62874,
0.82874, 0.53369, 0.34383, 0.50752, 0.97023, 0.22695, 0.62407, 0.25840, 0.71279, 0.28785,
0.31611, 0.20391, 0.19702, 0.40760, 0.85158, 0.68369, 0.63760, 0.09879, 0.11924, 0.32920,
0.53052, 0.15900, 0.21229, 0.84080, 0.33933, 0.93651, 0.42705, 0.06199, 0.50092, 0.47192,
0.57152, 0.01818, 0.31404, 0.50173, 0.87725, 0.50530, 0.10717, 0.04035, 0.32901, 0.33538,
0.04780, 0.40984, 0.78216, 0.91288, 0.11314, 0.25248, 0.23823, 0.74001, 0.48089, 0.55531,
0.82486, 0.01058, 0.05409, 0.44357, 0.52641, 0.68188, 0.94629, 0.61627, 0.33037, 0.11961,
0.57988, 0.19653, 0.91902, 0.59838, 0.52974, 0.28364, 0.45767, 0.65836, 0.63045, 0.76140,
0.27918, 0.27256, 0.46035, 0.77418, 0.92918, 0.14095, 0.89645, 0.25146, 0.21172, 0.47910,
0.95451, 0.34377, 0.29927, 0.79220, 0.97654, 0.67591, 0.44385, 0.38434, 0.44860, 0.28170,
0.90712, 0.20337, 0.00292, 0.55046, 0.62255, 0.45127, 0.80896, 0.43965, 0.59145, 0.23801,
0.33601, 0.30119, 0.89935, 0.40850, 0.98226, 0.75430, 0.68318, 0.65407, 0.68067, 0.32942,
0.11756, 0.27626, 0.83879, 0.72174, 0.75430, 0.13702, 0.03402, 0.58781, 0.07393, 0.23067,
0.92537, 0.29445, 0.43437, 0.47685, 0.54548, 0.66082, 0.23805, 0.60208, 0.94337, 0.21363,
0.72637, 0.57181, 0.77679, 0.63931, 0.72860, 0.38901, 0.94920, 0.04535, 0.12863, 0.40550,
0.90095, 0.21418, 0.13953, 0.99639, 0.02526, 0.70018, 0.21828, 0.20294, 0.20191, 0.30954,
0.39490, 0.68955, 0.11506, 0.15748, 0.40252, 0.91680, 0.61547, 0.78443, 0.19693, 0.67630,
0.56552, 0.58556, 0.53554, 0.53507, 0.09831, 0.21229, 0.83135, 0.26375, 0.89287, 0.97069,
0.70615, 0.42041, 0.43117, 0.21291, 0.26086, 0.26978, 0.77340, 0.43833, 0.46179, 0.54418,
0.67878, 0.42776, 0.61454, 0.55915, 0.36363, 0.31999, 0.42442, 0.86649, 0.62513, 0.02047
};
class TestRunnable {
char name[100];
public:
int dim; // dimension of the solved problem
int nvar; // number of variable of the solved problem
TestRunnable(const char* n, int d, int nv)
: dim(d), nvar(nv)
{strncpy(name, n, 100);}
bool test() const;
virtual bool run() const =0;
const char* getName() const
{return name;}
protected:
static double korder_unfold_fold(int maxdim, int unfold_dim,
int nstat, int npred, int nboth, int forw,
const TwoDMatrix& gy, const TwoDMatrix& gu,
const TwoDMatrix& v);
};
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;
}
}
double TestRunnable::korder_unfold_fold(int maxdim, int unfold_dim,
int nstat, int npred, int nboth, int nforw,
const TwoDMatrix& gy, const TwoDMatrix& gu,
const TwoDMatrix& v)
{
TensorContainer<FSSparseTensor> c(1);
int ny = nstat+npred+nboth+nforw;
int nu = v.nrows();
int nz = nboth+nforw+ny+nboth+npred+nu;
SparseGenerator::fillContainer(c, maxdim, nz, ny, 5.0);
for (int d = 1; d <= maxdim; d++) {
printf("\ttensor fill for dim=%d is: %3.2f %%\n",
d, c.get(Symmetry(d))->getFillFactor()*100.0);
}
Journal jr("out.txt");
KOrder kord(nstat, npred, nboth, nforw, c, gy, gu, v, jr);
// perform unfolded steps until unfold_dim
double maxerror = 0.0;
for (int d = 2; d <= unfold_dim; d++) {
clock_t pertime = clock();
kord.performStep<KOrder::unfold>(d);
pertime = clock()-pertime;
printf("\ttime for unfolded step dim=%d: %8.4g\n",
d, ((double)(pertime))/CLOCKS_PER_SEC);
clock_t checktime = clock();
double err = kord.check<KOrder::unfold>(d);
checktime = clock()-checktime;
printf("\ttime for step check dim=%d: %8.4g\n",
d, ((double)(checktime))/CLOCKS_PER_SEC);
printf("\tmax error in step dim=%d: %10.6g\n",
d, err);
if (maxerror < err)
maxerror = err;
}
// perform folded steps until maxdim
if (unfold_dim < maxdim) {
clock_t swtime = clock();
kord.switchToFolded();
swtime = clock()-swtime;
printf("\ttime for switching dim=%d: %8.4g\n",
unfold_dim, ((double)(swtime))/CLOCKS_PER_SEC);
for (int d = unfold_dim+1; d <= maxdim; d++) {
clock_t pertime = clock();
kord.performStep<KOrder::fold>(d);
pertime = clock()-pertime;
printf("\ttime for folded step dim=%d: %8.4g\n",
d, ((double)(pertime))/CLOCKS_PER_SEC);
clock_t checktime = clock();
double err = kord.check<KOrder::fold>(d);
checktime = clock()-checktime;
printf("\ttime for step check dim=%d: %8.4g\n",
d, ((double)(checktime))/CLOCKS_PER_SEC);
printf("\tmax error in step dim=%d: %10.6g\n",
d, err);
if (maxerror < err)
maxerror = err;
}
}
return maxerror;
}
class UnfoldKOrderSmall : public TestRunnable {
public:
UnfoldKOrderSmall()
: TestRunnable("unfold-3 fold-4 korder (stat=2,pred=3,both=1,forw=2,u=3,dim=4)",
4, 18) {}
bool run() const
{
TwoDMatrix gy(8, 4, gy_data);
TwoDMatrix gu(8, 3, gu_data);
TwoDMatrix v(3, 3, vdata);
double err = korder_unfold_fold(4, 3, 2, 3, 1, 2,
gy, gu, v);
return err < 0.08;
}
};
// same dimension as Smets & Wouters
class UnfoldKOrderSW : public TestRunnable {
public:
UnfoldKOrderSW()
: TestRunnable("unfold S&W korder (stat=5,pred=12,both=8,forw=5,u=10,dim=4)",
4, 73) {}
bool run() const
{
TwoDMatrix gy(30, 20, gy_data2);
TwoDMatrix gu(30, 10, gu_data2);
TwoDMatrix v(10, 10, vdata2);
v.mult(0.001);
gu.mult(.01);
double err = korder_unfold_fold(4, 4, 5, 12, 8, 5,
gy, gu, v);
return err < 0.08;
}
};
class UnfoldFoldKOrderSW : public TestRunnable {
public:
UnfoldFoldKOrderSW()
: TestRunnable("unfold-2 fold-3 S&W korder (stat=5,pred=12,both=8,forw=5,u=10,dim=3)",
4, 73) {}
bool run() const
{
TwoDMatrix gy(30, 20, gy_data2);
TwoDMatrix gu(30, 10, gu_data2);
TwoDMatrix v(10, 10, vdata2);
v.mult(0.001);
gu.mult(.01);
double err = korder_unfold_fold(4, 3, 5, 12, 8, 5,
gy, gu, v);
return err < 0.08;
}
};
int main()
{
TestRunnable* all_tests[50];
// fill in vector of all tests
int num_tests = 0;
all_tests[num_tests++] = new UnfoldKOrderSmall();
all_tests[num_tests++] = new UnfoldKOrderSW();
all_tests[num_tests++] = new UnfoldFoldKOrderSW();
// find maximum dimension and maximum nvar
int dmax=0;
int nvmax = 0;
for (int i = 0; i < num_tests; i++) {
if (dmax < all_tests[i]->dim)
dmax = all_tests[i]->dim;
if (nvmax < all_tests[i]->nvar)
nvmax = all_tests[i]->nvar;
}
tls.init(dmax, nvmax); // initialize library
// launch the tests
int success = 0;
for (int i = 0; i < num_tests; i++) {
try {
if (all_tests[i]->test())
success++;
} catch (const TLException& e) {
printf("Caugth TL exception in <%s>:\n", all_tests[i]->getName());
e.print();
} 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;
}

View File

@ -0,0 +1,216 @@
CC_FLAGS = -Wall -I../sylv/cc -I../tl/cc -I../kord -I../integ/cc -I.. \
$(CC_INCLUDE_PATH)
LDFLAGS = -llapack -lcblas -lf77blas -latlas -lg2c -lstdc++ -lcygwin
DYNVERSION = 1.3.7
tmpdir = /tmp/aaabbb123321
pthreadGC2 = `which pthreadGC2.dll`
mingwm10 = `which mingwm10.dll`
ifeq ($(CC),)
CC := gcc
endif
ifneq ($(LD_LIBRARY_PATH),) # use LD_LIBRARY_PATH from environment
# LDFLAGS := -Wl,--library-path $(LD_LIBRARY_PATH) $(LDFLAGS)
LDFLAGS := -Wl,--library-path $(LD_LIBRARY_LIST) $(LDFLAGS)
# LDFLAGS := $(LD_LIBRARY_LIST) $(LDFLAGS)
endif
ifeq ($(DEBUG),yes)
CC_FLAGS := $(CC_FLAGS) -g -DTL_DEBUG=2
else
CC_FLAGS := $(CC_FLAGS) -O3 -DPOSIX_THREADS
endif
ifeq ($(OS),Windows_NT)
CC_FLAGS := -mno-cygwin -mthreads $(CC_FLAGS)
LDFLAGS := -mno-cygwin -mthreads $(LDFLAGS) -lpthreadGC2
ARCH := w32
MEX_SUFFIX = dll
else
LDFLAGS := $(LDFLAGS) -lpthread
ARCH := linux
MEX_SUFFIX = mexglx
endif
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)
cppsource := $(wildcard *.cpp) $(patsubst %.y,%_ll.cc,$(wildcard *.y)) $(patsubst %.lex,%_tab.cc,$(wildcard *.lex))
hsource := $(wildcard *.h) $(patsubst %.lex,%_tab.hh,$(wildcard *.lex))
objects := $(patsubst %.cpp,%.o,$(wildcard *.cpp)) $(patsubst %.y,%_ll.o,$(wildcard *.y)) $(patsubst %.lex,%_tab.o,$(wildcard *.lex))
all: dynare++
../tl/cc/dummy.ch:
make -C ../tl/cc dummy.ch
../tl/cc/%.cpp: ../tl/cc/%.cweb ../tl/cc/dummy.ch
make -C ../tl/cc $*.cpp
../tl/cc/%.h: ../tl/cc/%.hweb ../tl/cc/dummy.ch
make -C ../tl/cc $*.h
../tl/cc/%.o: ../tl/cc/%.cpp $(tlhsource)
make -C ../tl/cc $*.o
../integ/cc/dummy.ch:
make -C ../integ/cc dummy.ch
../integ/cc/%.cpp: ../integ/cc/%.cweb ../integ/cc/dummy.ch
make -C ../integ/cc $*.cpp
../integ/cc/%.h: ../integ/cc/%.hweb ../integ/cc/dummy.ch
make -C ../integ/cc $*.h
../integ/cc/%.o: ../integ/cc/%.cpp $(integhsource) $(tlhsource)
make -C ../integ/cc $*.o
../sylv/cc/%.o: ../sylv/cc/%.cpp $(sylvhsource)
make -C ../sylv/cc $*.o
../kord/dummy.ch:
make -C ../kord dummy.ch
../kord/%.cpp: ../kord/%.cweb ../kord/dummy.ch
make -C ../kord $*.cpp
../kord/%.h: ../kord/%.hweb ../kord/dummy.ch
make -C ../kord $*.h
../kord/%.o: ../kord/%.cpp $(tlhsource) $(kordhsource) $(integhsource)
make -C ../kord $*.o
# for some reason, the pattern rules didn't work here, so the rules
# are expanded:
dynglob_tab.cc: dynglob.y dynare_atoms.h dynare_model.h
bison -d -t --verbose -odynglob_tab.cc dynglob.y
dynglob_tab.hh: dynglob.y dynare_atoms.h dynare_model.h
bison -d -t --verbose -odynglob_tab.cc dynglob.y
dynglob_ll.cc: dynglob.lex dynglob_tab.hh
flex -i -odynglob_ll.cc dynglob.lex
dynglob_ll.o: dynglob_ll.cc $(hsource)
$(CC) -I.. -I../sylv/cc -I../tl/cc -O3 -c dynglob_ll.cc
dynglob_tab.o: dynglob_tab.cc $(hsource)
$(CC) -I.. -I../sylv/cc -I../tl/cc -O3 -c dynglob_tab.cc
%.o: %.cpp $(hsource) $(kordhsource) $(tlhsource) $(sylvhsource) $(parserhsource)
$(CC) $(CC_FLAGS) -DDYNVERSION=\"$(DYNVERSION)\" -o $*.o -c $*.cpp
../parser/cc/parser.a: $(parserhsource) $(parsercppsource)
make -C ../parser/cc parser.a
../utils/cc/utils.a: $(utilshsource) $(utilscppsource)
make -C ../utils/cc utils.a
dynare++: $(tlhwebsource) $(tlcwebsoure) $(tlhsource) $(tlcppsource) \
$(integhwebsource) $(integcwebsoure) $(integhsource) $(integcppsource) \
$(kordhwebsource) $(kordcwebsoure) $(kordhsource) $(kordcppsource) \
$(sylvhsource) $(sylvcppsource) \
$(kordobjects) $(tlobjects) $(integobjects) $(sylvobjects) $(objects) \
../parser/cc/parser.a ../utils/cc/utils.a
$(CC) -g -o dynare++ $(objects) $(kordobjects) $(integobjects) $(tlobjects) ../parser/cc/parser.a ../utils/cc/utils.a $(sylvobjects) $(LDFLAGS)
../extern/matlab/dynare_simul_.$(MEX_SUFFIX):
make -C ../extern/matlab all
srcball:
rm -rf $(tmpdir)
mkdir -p $(tmpdir)/dynare++-$(DYNVERSION)/tests
cp ../tests/*.mod ../tests/*.dyn $(tmpdir)/dynare++-$(DYNVERSION)/tests
mkdir -p $(tmpdir)/dynare++-$(DYNVERSION)/src
cp *.h *.cpp *.y *.lex Makefile $(tmpdir)/dynare++-$(DYNVERSION)/src
mkdir -p $(tmpdir)/dynare++-$(DYNVERSION)/tl/cc
cp ../tl/cc/*web ../tl/cc/Makefile $(tmpdir)/dynare++-$(DYNVERSION)/tl/cc
mkdir -p $(tmpdir)/dynare++-$(DYNVERSION)/tl/testing
cp ../tl/testing/*.cpp ../tl/testing/*.h ../tl/testing/Makefile $(tmpdir)/dynare++-$(DYNVERSION)/tl/testing
mkdir -p $(tmpdir)/dynare++-$(DYNVERSION)/integ/cc
cp ../integ/cc/*web ../integ/cc/Makefile ../integ/cc/*.dat $(tmpdir)/dynare++-$(DYNVERSION)/integ/cc
mkdir -p $(tmpdir)/dynare++-$(DYNVERSION)/integ/testing
cp ../integ/testing/*.cpp ../integ/testing/Makefile $(tmpdir)/dynare++-$(DYNVERSION)/integ/testing
mkdir -p $(tmpdir)/dynare++-$(DYNVERSION)/sylv/cc
cp ../sylv/cc/*.cpp ../sylv/cc/*.h ../sylv/cc/Makefile $(tmpdir)/dynare++-$(DYNVERSION)/sylv/cc
mkdir -p $(tmpdir)/dynare++-$(DYNVERSION)/sylv/testing
cp ../sylv/testing/*.cpp ../sylv/testing/*.h ../sylv/testing/Makefile $(tmpdir)/dynare++-$(DYNVERSION)/sylv/testing
mkdir -p $(tmpdir)/dynare++-$(DYNVERSION)/kord
cp ../kord/*web ../kord/Makefile ../kord/tests.cpp $(tmpdir)/dynare++-$(DYNVERSION)/kord
mkdir -p $(tmpdir)/dynare++-$(DYNVERSION)/parser/cc
cp ../parser/cc/*.cpp ../parser/cc/*.h ../parser/cc/*.lex ../parser/cc/*.y ../parser/cc/Makefile $(tmpdir)/dynare++-$(DYNVERSION)/parser/cc
mkdir -p $(tmpdir)/dynare++-$(DYNVERSION)/utils/cc
cp ../utils/cc/*.cpp ../utils/cc/*.h ../utils/cc/Makefile $(tmpdir)/dynare++-$(DYNVERSION)/utils/cc
mkdir -p $(tmpdir)/dynare++-$(DYNVERSION)/extern/matlab
cp ../extern/matlab/*.cpp ../extern/matlab/*.m ../extern/matlab/Makefile ../extern/matlab/*.bat $(tmpdir)/dynare++-$(DYNVERSION)/extern/matlab
mkdir -p $(tmpdir)/dynare++-$(DYNVERSION)/doc
cp ../doc/*.tex $(tmpdir)/dynare++-$(DYNVERSION)/doc
cp ../change_log.html $(tmpdir)/dynare++-$(DYNVERSION)/
cd $(tmpdir); tar czf dynare++-$(DYNVERSION).src.tgz dynare++-$(DYNVERSION)/*
mv $(tmpdir)/dynare++-$(DYNVERSION).src.tgz ..
rm -rf $(tmpdir)
binball: dynare++ ../extern/matlab/dynare_simul_.$(MEX_SUFFIX)
rm -rf $(tmpdir)
mkdir -p $(tmpdir)/dynare++-$(DYNVERSION)/tests
cp ../tests/*.mod ../tests/*.dyn $(tmpdir)/dynare++-$(DYNVERSION)/tests
mkdir -p $(tmpdir)/dynare++-$(DYNVERSION)/doc
cp ../doc/*.pdf $(tmpdir)/dynare++-$(DYNVERSION)/doc
cp dynare++* $(tmpdir)/dynare++-$(DYNVERSION)
cp ../extern/matlab/*.m $(tmpdir)/dynare++-$(DYNVERSION)
cp ../extern/matlab/dynare_simul_.$(MEX_SUFFIX) $(tmpdir)/dynare++-$(DYNVERSION)
cp ../change_log.html $(tmpdir)/dynare++-$(DYNVERSION)
ifeq ($(OS),Windows_NT)
cp $(pthreadGC2) $(tmpdir)/dynare++-$(DYNVERSION)
cp $(mingwm10) $(tmpdir)/dynare++-$(DYNVERSION)
cd $(tmpdir); zip -r dynare++-$(DYNVERSION)-$(ARCH).ix86.zip dynare++-$(DYNVERSION)/*
mv $(tmpdir)/dynare++-$(DYNVERSION)-$(ARCH).ix86.zip ..
else
cd $(tmpdir); tar czf dynare++-$(DYNVERSION)-$(ARCH).ix86.tgz dynare++-$(DYNVERSION)/*
mv $(tmpdir)/dynare++-$(DYNVERSION)-$(ARCH).ix86.tgz ..
endif
rm -rf $(tmpdir)
clear:
rm -f *.o
rm -f dynare++*
rm -f *_ll.cc *_tab.hh *_tab.cc *.output
make -C ../tl/testing clear
make -C ../tl/cc clear
make -C ../integ/testing clear
make -C ../integ/cc clear
make -C ../sylv/testing clear
make -C ../sylv/cc clear
make -C ../kord clear
make -C ../parser/cc clear
make -C ../utils/cc clear

View File

@ -0,0 +1,41 @@
// Copyright (C) 2006, Ondra Kamenik
// $Id: dynare_exception.h 853 2006-08-01 08:42:42Z kamenik $
#ifndef DYNARE_EXCEPTION_H
#define DYNARE_EXCEPTION_H
#include <string>
class DynareException {
char* mes;
public:
DynareException(const char* m, const char* fname, int line, int col)
{
mes = new char[strlen(m) + strlen(fname) + 100];
sprintf(mes, "Parse error at %s, line %d, column %d: %s", fname, line, col, m);
}
DynareException(const char* fname, int line, const std::string& m)
{
mes = new char[m.size() + strlen(fname) + 50];
sprintf(mes, "%s:%d: %s", fname, line, m.c_str());
}
DynareException(const char* m, int offset)
{
mes = new char[strlen(m) + 100];
sprintf(mes, "Parse error in provided string at offset %d: %s", offset, m);
}
DynareException(const DynareException& e)
: mes(new char[strlen(e.mes)+1])
{strcpy(mes, e.mes);}
virtual ~DynareException()
{delete [] mes;}
const char* message() const
{return mes;}
};
#endif
// Local Variables:
// mode:C++
// End:

View File

@ -0,0 +1,245 @@
// $Id: dynare_params.cpp 1520 2008-01-02 14:46:44Z kamenik $
//Copyright 2004, Ondra Kamenik
#include "dynare_params.h"
#include <getopt.h>
#include <stdio.h>
#include <string.h>
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 [100]\n"
" --sim <num> number of simulations [80]\n"
" --rtper <num> number of RT periods simulated [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"
" --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"
"\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_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), 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},
{"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},
{"no-irfs", no_argument, NULL, opt_noirfs},
{"irfs", no_argument, NULL, opt_irfs},
{"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_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_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:

View File

@ -0,0 +1,71 @@
// $Id: dynare_params.h 1520 2008-01-02 14:46:44Z kamenik $
// Copyright 2004, Ondra Kamenik
/*
along shocks: m mult max_evals
ellipse: m mult max_evals (10*m) (0.5*mult)
simul: m max_evals (10*m)
--check-scale 2.0 --check-evals 1000 --check-num 10 --check PES
*/
#include <vector>
#include <string>
struct DynareParams {
const char* modname;
std::string basename;
int num_per;
int num_sim;
int num_rtper;
int num_rtsim;
int num_condper;
int num_condsim;
int num_threads;
int num_steps;
const char* prefix;
int seed;
int order;
/** Tolerance used for steady state calcs. */
double ss_tol;
bool check_along_path;
bool check_along_shocks;
bool check_on_ellipse;
int check_evals;
int check_num;
double check_scale;
/** Flag for doing IRFs even if the irf_list is empty. */
bool do_irfs_all;
/** List of shocks for which IRF will be calculated. */
std::vector<const char*> irf_list;
bool help;
bool version;
DynareParams(int argc, char** argv);
void printHelp() const;
int getCheckShockPoints() const
{return check_num;}
double getCheckShockScale() const
{return check_scale;}
int getCheckEllipsePoints() const
{return 10*check_num;}
double getCheckEllipseScale() const
{return 0.5*check_scale;}
int getCheckPathPoints() const
{return 10*check_num;}
private:
enum {opt_per, opt_sim, opt_rtper, opt_rtsim, opt_condper, opt_condsim, opt_prefix, opt_threads,
opt_steps, opt_seed, opt_order, opt_ss_tol, opt_check,
opt_check_along_path, opt_check_along_shocks, opt_check_on_ellipse,
opt_check_evals, opt_check_scale, opt_check_num, opt_noirfs, opt_irfs,
opt_help, opt_version};
void processCheckFlags(const char* flags);
/** This gathers strings from argv[optind] and on not starting
* with '-' to the irf_list. It stops one item before the end,
* since this is the model file. */
void processIRFList(int argc, char** argv);
};
// Local Variables:
// mode:C++
// End:

View File

@ -0,0 +1,122 @@
// Copyright (C) 2006, Ondra Kamenik
// $Id$
#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
hash_set<int> nlt = model.get_nonlinear_subterms(ft);
int j = 0; // indexes subterms
// and make substitutions for all these non-linear subterms
for (hash_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;
model.variable_shift_map(model.eqs.nulary_of_term(t), 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 AUXLEAD_*_*{mlead-1}(+1) for t
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));
}
}

View File

@ -0,0 +1,83 @@
// Copyright (C) 2006, Ondra Kamenik
// $Id$
#ifndef FORW_SUBST_BUILDER_H
#define FORW_SUBST_BUILDER_H
#include "dynare_model.h"
namespace ogdyn {
/** This struct encapsulates information about the process of
* forward substitutions. */
struct ForwSubstInfo {
int num_affected_equations;
int num_subst_terms;
int num_aux_variables;
int num_new_terms;
ForwSubstInfo()
: num_affected_equations(0),
num_subst_terms(0),
num_aux_variables(0),
num_new_terms(0) {}
};
class ForwSubstBuilder {
typedef map<int, const char*> Ttermauxmap;
protected:
/** Reference to the model, to which we will add equations and
* change some equations. */
DynareModel& model;
/** A map mapping new auxiliary variables to the terms in the
* tree in the DynareModel. */
Tsubstmap aux_map;
/** Information about the substitutions. */
ForwSubstInfo info;
public:
/** Do all the jobs needed. This scans all equations in the
* model, and for equations containing forward looking
* variables greater than 1 lead, it makes corresponding
* substitutions. Basically, it breaks each equation to its
* non-linear components and creates substitutions for these
* components, not for whole equation. This is because the
* expectation operator can go through the linear part of the
* function. This will save us many occurrences of other
* variables involved in the equation. */
ForwSubstBuilder(DynareModel& m);
/** Copy constructor with a new instance of the model. */
ForwSubstBuilder(const ForwSubstBuilder& b, DynareModel& m);
/** Return the auxiliary variable mapping. */
const Tsubstmap& get_aux_map() const
{return aux_map;}
/** Return the information. */
const ForwSubstInfo& get_info() const
{return info;}
private:
ForwSubstBuilder(const ForwSubstBuilder& b);
/** This method takes a nonlinear term t, and if it has leads
* of greater than 1, then it substitutes the term for the new
* variable (or string of variables). Note that the
* substitution is done by DynamicAtoms::assign_variable. This
* means that the substitution is made for all other
* ocurrences of t in the model. So there is no need of
* tracking already substituted terms. The other two
* parameters are just for identification of the new auxiliary
* variables. When called from the constructor, i is an
* equation number, j is an order of the non-linear term in
* the equation. */
void substitute_for_term(int t, int i, int j);
/** This is called just at the end of the job. It unassigns
* all nulary terms with a lead greater than 1. */
void unassign_gt_1_leads();
/** This unassigns all leads greater than 1 of the given name. */
void unassign_gt_1_leads(const char* name);
};
};
#endif
// Local Variables:
// mode:C++
// End:

View File

@ -0,0 +1,230 @@
// 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);
double f2 = 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]
f2 = 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]
f2 = 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;
}

View File

@ -0,0 +1,94 @@
// Copyright (C) 2006, Ondra Kamenik
// $Id: nlsolve.h 762 2006-05-22 13:00:07Z kamenik $
#ifndef OGU_NLSOLVE_H
#define OGU_NLSOLVE_H
#include "twod_matrix.h"
#include "journal.h"
namespace ogu {
class OneDFunction {
public:
virtual ~OneDFunction() {}
virtual double eval(double) = 0;
};
class GoldenSectionSearch {
protected:
static double tol;
static double golden;
public:
static double search(OneDFunction& f, double x1, double x2);
protected:
/** This initializes a bracket by moving x2 and b (as a golden
* section of x1,x2) so that f(x1)>f(b) && f(b)<f(x2). The point
* x1 is not moved, since it is considered as reliable and f(x1)
* is supposed to be finite. If initialization of a bracket
* succeeded, then [x1, b, x2] is the bracket and true is
* returned. Otherwise, b is the minimum found and false is
* returned. */
static bool init_bracket(OneDFunction& f, double x1, double& x2, double& b);
/** This supposes that f(x1) is finite and it moves x2 toward x1
* until x2 and b (as a golden section of x1,x2) are finite. If
* succeeded, the routine returns true and x2, and b. Otherwise,
* it returns false. */
static bool search_for_finite(OneDFunction& f, double x1, double& x2, double& b);
};
class VectorFunction {
public:
VectorFunction() {}
virtual ~VectorFunction() {}
virtual int inDim() const = 0;
virtual int outDim() const = 0;
/** Check dimensions of eval parameters. */
void check_for_eval(const ConstVector& in, Vector& out) const;
/** Evaluate the vector function. */
virtual void eval(const ConstVector& in, Vector& out) = 0;
};
class Jacobian : public TwoDMatrix {
public:
Jacobian(int n)
: TwoDMatrix(n,n) {}
virtual ~Jacobian() {}
virtual void eval(const Vector& in) = 0;
};
class NLSolver : public OneDFunction {
protected:
Journal& journal;
VectorFunction& func;
Jacobian& jacob;
const int max_iter;
const double tol;
private:
Vector xnewton;
Vector xcauchy;
Vector x;
public:
NLSolver(VectorFunction& f, Jacobian& j, int maxit, double tl, Journal& jr)
: journal(jr), func(f), jacob(j), max_iter(maxit), tol(tl),
xnewton(f.inDim()), xcauchy(f.inDim()), x(f.inDim())
{xnewton.zeros(); xcauchy.zeros(); x.zeros();}
virtual ~NLSolver() {}
/** Returns true if the problem has converged. xx as input is the
* starting value, as output it is a solution. */
bool solve(Vector& xx, int& iter);
/** To implement OneDFunction interface. It returns
* func(xx)^T*func(xx), where
* xx=x+lambda*xcauchy+(1-lambda)*xnewton. It is non-const only
* because it calls func, x, xnewton, xcauchy is not changed. */
double eval(double lambda);
};
};
#endif
// Local Variables:
// mode:C++
// End:

View File

@ -0,0 +1,321 @@
/* $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 <stdio.h>
#include <string.h>
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:

View File

@ -0,0 +1,53 @@
/* $Header: /var/lib/cvs/dynare_cpp/sylv/cc/BlockDiagonal.h,v 1.1.1.1 2004/06/04 13:00:20 kamenik Exp $ */
/* Tag $Name: $ */
#ifndef BLOCK_DIAGONAL_H
#define BLOCK_DIAGONAL_H
#include "QuasiTriangular.h"
class BlockDiagonal : public QuasiTriangular {
int* const row_len;
int* const col_len;
public:
BlockDiagonal(const double* d, int d_size);
BlockDiagonal(int p, const BlockDiagonal& b);
BlockDiagonal(const BlockDiagonal& b);
BlockDiagonal(const QuasiTriangular& t);
const BlockDiagonal& operator=(const QuasiTriangular& t)
{GeneralMatrix::operator=(t); return *this;}
const BlockDiagonal& operator=(const BlockDiagonal& b);
~BlockDiagonal() {delete [] row_len; delete [] col_len;}
void setZeroBlockEdge(diag_iter edge);
int getNumZeros() const;
int getNumBlocks() const;
int getLargestBlock() const;
void printInfo() const;
void multKron(KronVector& x) const;
void multKronTrans(KronVector& x) const;
const_col_iter col_begin(const DiagonalBlock& b) const;
col_iter col_begin(const DiagonalBlock& b);
const_row_iter row_end(const DiagonalBlock& b) const;
row_iter row_end(const DiagonalBlock& b);
QuasiTriangular* clone() const
{return new BlockDiagonal(*this);}
private:
void setZerosToRU(diag_iter edge);
const_diag_iter findBlockStart(const_diag_iter from) const;
static void savePartOfX(int si, int ei, const KronVector& x, Vector& work);
void multKronBlock(const_diag_iter start, const_diag_iter end,
KronVector& x, Vector& work) const;
void multKronBlockTrans(const_diag_iter start, const_diag_iter end,
KronVector& x, Vector& work) const;
};
#endif /* BLOCK_DIAGONAL_H */
// Local Variables:
// mode:C++
// End:

View File

@ -0,0 +1,482 @@
/* $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 "cppblas.h"
#include "cpplapack.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#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.");
}
int m = opa_rows;
int n = opb_cols;
int k = opa_cols;
int lda = a.ld;
int ldb = b.ld;
int ldc = ld;
if (lda > 0 && ldb > 0 && ldc > 0) {
BLAS_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) {
int mm = rows;
int nn = cols;
double alpha = b;
int lda = ld;
int incx = d.skip();
double beta = a;
int incy = x.skip();
BLAS_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) {
int mm = rows;
int nn = cols;
double alpha = b;
int lda = rows;
int incx = d.skip();
double beta = a;
int incy = x.skip();
BLAS_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);
int* ipiv = new int[rows];
int info;
LAPACK_dgetrf(&rows, &rows, inv.getData().base(), &rows, ipiv, &info);
LAPACK_dgetrs(trans, &rows, &mcols, inv.base(), &rows, ipiv, d,
&mld, &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");
}
}

View File

@ -0,0 +1,284 @@
/* $Header: /var/lib/cvs/dynare_cpp/sylv/cc/GeneralMatrix.h,v 1.3 2004/11/24 20:41:59 kamenik Exp $ */
/* Tag $Name: $ */
#ifndef GENERAL_MATRIX_H
#define GENERAL_MATRIX_H
#include "Vector.h"
class GeneralMatrix;
class ConstGeneralMatrix {
friend class GeneralMatrix;
protected:
ConstVector data;
int rows;
int cols;
int ld;
public:
ConstGeneralMatrix(const double* d, int m, int n)
: data(d, m*n), rows(m), cols(n), ld(m) {}
ConstGeneralMatrix(const GeneralMatrix& m);
ConstGeneralMatrix(const GeneralMatrix& m, int i, int j, int nrows, int ncols);
ConstGeneralMatrix(const ConstGeneralMatrix& m, int i, int j, int nrows, int ncols);
virtual ~ConstGeneralMatrix() {}
const double& get(int i, int j) const
{return data[j*ld+i];}
int numRows() const {return rows;}
int numCols() const {return cols;}
int getLD() const {return ld;}
const double* base() const {return data.base();}
const ConstVector& getData() const {return data;}
double getNormInf() const;
double getNorm1() const;
/* x = scalar(a)*x + scalar(b)*this*d */
void multVec(double a, Vector& x, double b, const ConstVector& d) const;
/* x = scalar(a)*x + scalar(b)*this'*d */
void multVecTrans(double a, Vector& x, double b, const ConstVector& d) const;
/* x = x + this*d */
void multaVec(Vector& x, const ConstVector& d) const
{multVec(1.0, x, 1.0, d);}
/* x = x + this'*d */
void multaVecTrans(Vector& x, const ConstVector& d) const
{multVecTrans(1.0, x, 1.0, d);}
/* x = x - this*d */
void multsVec(Vector& x, const ConstVector& d) const
{multVec(1.0, x, -1.0, d);}
/* x = x - this'*d */
void multsVecTrans(Vector& x, const ConstVector& d) const
{multVecTrans(1.0, x, -1.0, d);}
/* m = inv(this)*m */
void multInvLeft(GeneralMatrix& m) const;
/* m = inv(this')*m */
void multInvLeftTrans(GeneralMatrix& m) const;
/* d = inv(this)*d */
void multInvLeft(Vector& d) const;
/* d = inv(this')*d */
void multInvLeftTrans(Vector& d) const;
bool isFinite() const;
/** Returns true of the matrix is exactly zero. */
bool isZero() const;
virtual void print() const;
protected:
void multInvLeft(const char* trans, int mrows, int mcols, int mld, double* d) const;
};
class GeneralMatrix {
friend class ConstGeneralMatrix;
protected:
Vector data;
int rows;
int cols;
int ld;
public:
GeneralMatrix(int m, int n)
: data(m*n), rows(m), cols(n), ld(m) {}
GeneralMatrix(const double* d, int m, int n)
: data(d, m*n), rows(m), cols(n), ld(m) {}
GeneralMatrix(double* d, int m, int n)
: data(d, m*n), rows(m), cols(n), ld(m) {}
GeneralMatrix(const GeneralMatrix& m);
GeneralMatrix(const ConstGeneralMatrix& m);
GeneralMatrix(const GeneralMatrix&m, const char* dummy); // transpose
GeneralMatrix(const ConstGeneralMatrix&m, const char* dummy); // transpose
GeneralMatrix(const GeneralMatrix& m, int i, int j, int nrows, int ncols);
GeneralMatrix(GeneralMatrix& m, int i, int j, int nrows, int ncols);
/* this = a*b */
GeneralMatrix(const GeneralMatrix& a, const GeneralMatrix& b);
/* this = a*b' */
GeneralMatrix(const GeneralMatrix& a, const GeneralMatrix& b, const char* dum);
/* this = a'*b */
GeneralMatrix(const GeneralMatrix& a, const char* dum, const GeneralMatrix& b);
/* this = a'*b */
GeneralMatrix(const GeneralMatrix& a, const char* dum1,
const GeneralMatrix& b, const char* dum2);
virtual ~GeneralMatrix();
const GeneralMatrix& operator=(const GeneralMatrix& m)
{data=m.data; rows=m.rows; cols=m.cols; ld=m.ld; return *this;}
const double& get(int i, int j) const
{return data[j*ld+i];}
double& get(int i, int j)
{return data[j*ld+i];}
int numRows() const {return rows;}
int numCols() const {return cols;}
int getLD() const {return ld;}
double* base() {return data.base();}
const double* base() const {return data.base();}
Vector& getData() {return data;}
const Vector& getData() const {return data;}
double getNormInf() const
{return ConstGeneralMatrix(*this).getNormInf();}
double getNorm1() const
{return ConstGeneralMatrix(*this).getNorm1();}
/* place matrix m to the position (i,j) */
void place(const ConstGeneralMatrix& m, int i, int j);
void place(const GeneralMatrix& m, int i, int j)
{place(ConstGeneralMatrix(m), i, j);}
/* this = a*b */
void mult(const ConstGeneralMatrix& a, const ConstGeneralMatrix& b);
void mult(const GeneralMatrix& a, const GeneralMatrix& b)
{mult(ConstGeneralMatrix(a), ConstGeneralMatrix(b));}
/* this = this + scalar*a*b */
void multAndAdd(const ConstGeneralMatrix& a, const ConstGeneralMatrix& b,
double mult=1.0);
void multAndAdd(const GeneralMatrix& a, const GeneralMatrix& b,
double mult=1.0)
{multAndAdd(ConstGeneralMatrix(a), ConstGeneralMatrix(b), mult);}
/* this = this + scalar*a*b' */
void multAndAdd(const ConstGeneralMatrix& a, const ConstGeneralMatrix& b,
const char* dum, double mult=1.0);
void multAndAdd(const GeneralMatrix& a, const GeneralMatrix& b,
const char* dum, double mult=1.0)
{multAndAdd(ConstGeneralMatrix(a), ConstGeneralMatrix(b), dum, mult);}
/* this = this + scalar*a'*b */
void multAndAdd(const ConstGeneralMatrix& a, const char* dum, const ConstGeneralMatrix& b,
double mult=1.0);
void multAndAdd(const GeneralMatrix& a, const char* dum, const GeneralMatrix& b,
double mult=1.0)
{multAndAdd(ConstGeneralMatrix(a), dum, ConstGeneralMatrix(b), mult);}
/* this = this + scalar*a'*b' */
void multAndAdd(const ConstGeneralMatrix& a, const char* dum1,
const ConstGeneralMatrix& b, const char* dum2, double mult=1.0);
void multAndAdd(const GeneralMatrix& a, const char* dum1,
const GeneralMatrix& b, const char* dum2, double mult=1.0)
{multAndAdd(ConstGeneralMatrix(a), dum1, ConstGeneralMatrix(b),dum2, mult);}
/* this = this + scalar*a*a' */
void addOuter(const ConstVector& a, double mult=1.0);
void addOuter(const Vector& a, double mult=1.0)
{addOuter(ConstVector(a), mult);}
/* this = this * m */
void multRight(const ConstGeneralMatrix& m);
void multRight(const GeneralMatrix& m)
{multRight(ConstGeneralMatrix(m));}
/* this = m * this */
void multLeft(const ConstGeneralMatrix& m);
void multLeft(const GeneralMatrix& m)
{multLeft(ConstGeneralMatrix(m));}
/* this = this * m' */
void multRightTrans(const ConstGeneralMatrix& m);
void multRightTrans(const GeneralMatrix& m)
{multRightTrans(ConstGeneralMatrix(m));}
/* this = m' * this */
void multLeftTrans(const ConstGeneralMatrix& m);
void multLeftTrans(const GeneralMatrix& m)
{multLeftTrans(ConstGeneralMatrix(m));}
/* x = scalar(a)*x + scalar(b)*this*d */
void multVec(double a, Vector& x, double b, const ConstVector& d) const
{ConstGeneralMatrix(*this).multVec(a, x, b, d);}
/* x = scalar(a)*x + scalar(b)*this'*d */
void multVecTrans(double a, Vector& x, double b, const ConstVector& d) const
{ConstGeneralMatrix(*this).multVecTrans(a, x, b, d);}
/* x = x + this*d */
void multaVec(Vector& x, const ConstVector& d) const
{ConstGeneralMatrix(*this).multaVec(x, d);}
/* x = x + this'*d */
void multaVecTrans(Vector& x, const ConstVector& d) const
{ConstGeneralMatrix(*this).multaVecTrans(x, d);}
/* x = x - this*d */
void multsVec(Vector& x, const ConstVector& d) const
{ConstGeneralMatrix(*this).multsVec(x, d);}
/* x = x - this'*d */
void multsVecTrans(Vector& x, const ConstVector& d) const
{ConstGeneralMatrix(*this).multsVecTrans(x, d);}
/* this = zero */
void zeros();
/** this = unit (on main diagonal) */
void unit();
/* this = NaN */
void nans();
/* this = Inf */
void infs();
/* this = scalar*this */
void mult(double a);
/* this = this + scalar*m */
void add(double a, const ConstGeneralMatrix& m);
void add(double a, const GeneralMatrix& m)
{add(a, ConstGeneralMatrix(m));}
/* this = this + scalar*m' */
void add(double a, const ConstGeneralMatrix& m, const char* dum);
void add(double a, const GeneralMatrix& m, const char* dum)
{add(a, ConstGeneralMatrix(m), dum);}
bool isFinite() const
{return (ConstGeneralMatrix(*this)).isFinite();}
bool isZero() const
{return (ConstGeneralMatrix(*this)).isZero();}
virtual void print() const
{ConstGeneralMatrix(*this).print();}
private:
void copy(const ConstGeneralMatrix& m, int ioff = 0, int joff = 0);
void copy(const GeneralMatrix& m, int ioff = 0, int joff = 0)
{copy(ConstGeneralMatrix(m), ioff, joff);}
void gemm(const char* transa, const ConstGeneralMatrix& a,
const char* transb, const ConstGeneralMatrix& b,
double alpha, double beta);
void gemm(const char* transa, const GeneralMatrix& a,
const char* transb, const GeneralMatrix& b,
double alpha, double beta)
{gemm(transa, ConstGeneralMatrix(a), transb, ConstGeneralMatrix(b),
alpha, beta);}
/* this = this * op(m) (without whole copy of this) */
void gemm_partial_right(const char* trans, const ConstGeneralMatrix& m,
double alpha, double beta);
void gemm_partial_right(const char* trans, const GeneralMatrix& m,
double alpha, double beta)
{gemm_partial_right(trans, ConstGeneralMatrix(m), alpha, beta);}
/* this = op(m) *this (without whole copy of this) */
void gemm_partial_left(const char* trans, const ConstGeneralMatrix& m,
double alpha, double beta);
void gemm_partial_left(const char* trans, const GeneralMatrix& m,
double alpha, double beta)
{gemm_partial_left(trans, ConstGeneralMatrix(m), alpha, beta);}
/* number of rows/columns for copy used in gemm_partial_* */
static int md_length;
};
#endif /* GENERAL_MATRIX_H */
// Local Variables:
// mode:C++
// End:

View File

@ -0,0 +1,138 @@
/* $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 <time.h>
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:

View File

@ -0,0 +1,61 @@
/* $Header: /var/lib/cvs/dynare_cpp/sylv/cc/GeneralSylvester.h,v 1.1.1.1 2004/06/04 13:00:20 kamenik Exp $ */
/* Tag $Name: $ */
#ifndef GENERAL_SYLVESTER_H
#define GENERAL_SYLVESTER_H
#include "SylvMatrix.h"
#include "SylvMemory.h"
#include "SimilarityDecomp.h"
#include "SylvesterSolver.h"
class GeneralSylvester {
SylvParams pars;
SylvMemoryDriver mem_driver;
int order;
const SqSylvMatrix a;
const SylvMatrix b;
const SqSylvMatrix c;
SylvMatrix d;
bool solved;
SchurDecompZero* bdecomp;
SimilarityDecomp* cdecomp;
SylvesterSolver* sylv;
public:
/* construct with my copy of d*/
GeneralSylvester(int ord, int n, int m, int zero_cols,
const double* da, const double* db,
const double* dc, const double* dd,
const SylvParams& ps);
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 = false);
/* construct with provided storage for d */
GeneralSylvester(int ord, int n, int m, int zero_cols,
const double* da, const double* db,
const double* dc, double* dd,
bool alloc_for_check = false);
GeneralSylvester(int ord, int n, int m, int zero_cols,
const double* da, const double* db,
const double* dc, double* dd,
const SylvParams& ps);
virtual ~GeneralSylvester();
int getM() const {return c.numRows();}
int getN() const {return a.numRows();}
const double* getResult() const {return d.base();}
const SylvParams& getParams() const {return pars;}
SylvParams& getParams() {return pars;}
void solve();
void check(const double* ds);
private:
void init();
};
#endif /* GENERAL_SYLVESTER_H */
// Local Variables:
// mode:C++
// End:

View File

@ -0,0 +1,53 @@
/* $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:

View File

@ -0,0 +1,33 @@
/* $Header: /var/lib/cvs/dynare_cpp/sylv/cc/IterativeSylvester.h,v 1.1.1.1 2004/06/04 13:00:20 kamenik Exp $ */
/* Tag $Name: $ */
#ifndef ITERATIVE_SYLVESTER_H
#define ITERATIVE_SYLVESTER_H
#include "SylvesterSolver.h"
#include "KronVector.h"
#include "QuasiTriangular.h"
#include "SimilarityDecomp.h"
class IterativeSylvester : public SylvesterSolver {
public:
IterativeSylvester(const QuasiTriangular& k, const QuasiTriangular& f)
: SylvesterSolver(k, f) {}
IterativeSylvester(const SchurDecompZero& kdecomp, const SchurDecomp& fdecomp)
: SylvesterSolver(kdecomp, fdecomp) {}
IterativeSylvester(const SchurDecompZero& kdecomp, const SimilarityDecomp& fdecomp)
: SylvesterSolver(kdecomp, fdecomp) {}
void solve(SylvParams& pars, KronVector& x) const;
private:
double performFirstStep(KronVector& x) const;
static double performStep(const QuasiTriangular& k, const QuasiTriangular& f,
KronVector& x);
};
#endif /* ITERATIVE_SYLVESTER_H */
// Local Variables:
// mode:C++
// End:

View File

@ -0,0 +1,53 @@
/* $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);
}
}

View File

@ -0,0 +1,32 @@
/* $Header: /var/lib/cvs/dynare_cpp/sylv/cc/KronUtils.h,v 1.1.1.1 2004/06/04 13:00:31 kamenik Exp $ */
/* Tag $Name: $ */
#ifndef KRON_UTILS_H
#define KRON_UTILS_H
#include "KronVector.h"
#include "QuasiTriangular.h"
class KronUtils {
public:
/* multiplies I_m\otimes..\I_m\otimes T\otimes I_m...I_m\otimes I_n
with given b and returns x. T must be (m,m), number of
\otimes is b.getDepth(), level is a number of I_m's between T
and I_n plus 1. If level=0, then we multiply
\I_m\otimes ..\otimes I_m\otimes T, T is (n,n) */
static void multAtLevel(int level, const QuasiTriangular& t,
KronVector& x);
static void multAtLevelTrans(int level, const QuasiTriangular& t,
KronVector& x);
/* multiplies x=(F'\otimes F'\otimes..\otimes K)x */
static void multKron(const QuasiTriangular& f, const QuasiTriangular& k,
KronVector& x);
};
#endif /* KRON_UTILS_H */
// Local Variables:
// mode:C++
// End:

View File

@ -0,0 +1,109 @@
/* $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.");
}
}

View File

@ -0,0 +1,58 @@
/* $Header: /var/lib/cvs/dynare_cpp/sylv/cc/KronVector.h,v 1.1.1.1 2004/06/04 13:00:31 kamenik Exp $ */
/* Tag $Name: $ */
#ifndef KRON_VECTOR_H
#define KRON_VECTOR_H
#include "Vector.h"
class ConstKronVector;
class KronVector : public Vector {
protected:
int m;
int n;
int depth;
public:
KronVector() : Vector((double*)0, 0), m(0), n(0), depth(0) {}
KronVector(int mm, int nn, int dp); // new instance
KronVector(Vector& v, int mm, int nn, int dp); // conversion
KronVector(KronVector&, int i); // picks i-th subvector
KronVector(const ConstKronVector& v); // new instance and copy
const KronVector& operator=(KronVector& v)
{Vector::operator=(v); m=v.m; n=v.n; depth = v.depth; return *this;}
const KronVector& operator=(const KronVector& v)
{Vector::operator=(v); m=v.m; n=v.n; depth = v.depth; return *this;}
const KronVector& operator=(const ConstKronVector& v);
const KronVector& operator=(const Vector& v);
int getM() const {return m;}
int getN() const {return n;}
int getDepth() const {return depth;}
};
class ConstKronVector : public ConstVector
{
protected:
int m;
int n;
int depth;
public:
ConstKronVector(const KronVector& v);
ConstKronVector(const ConstKronVector& v);
ConstKronVector(const Vector& v, int mm, int nn, int dp);
ConstKronVector(const ConstVector& v, int mm, int nn, int dp);
ConstKronVector(const KronVector& v, int i);
ConstKronVector(const ConstKronVector& v, int i);
int getM() const {return m;}
int getN() const {return n;}
int getDepth() const {return depth;}
};
int power(int m, int depth);
#endif /* KRON_VECTOR */
// Local Variables:
// mode:C++
// End:

View File

@ -0,0 +1,34 @@
# $Header: /var/lib/cvs/dynare_cpp/sylv/cc/Makefile,v 1.4 2005/01/18 21:28:26 kamenik Exp $
# Tag $Name: $
CC_FLAGS := -Wall -I../testing -I../cc \
$(CC_INCLUDE_PATH)
ifeq ($(DEBUG),yes)
CC_FLAGS := $(CC_FLAGS) -g
else
CC_FLAGS := $(CC_FLAGS) -O2
endif
ifeq ($(OS),Windows_NT)
CC_FLAGS := -mno-cygwin -mthreads $(CC_FLAGS)
endif
objects := $(patsubst %.cpp,%.o,$(wildcard *.cpp))
headers := $(wildcard *.h)
all: $(objects)
sylvester.a: $(objects)
ar cr sylvester.a $(objects)
ranlib sylvester.a
clear:
rm -f *.o
rm -f sylvester.a
%.o : %.cpp $(headers)
$(CC) $(CC_FLAGS) $(EXTERN_DEFS) -c $*.cpp

View File

@ -0,0 +1,682 @@
/* $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 "cppblas.h"
#include <stdio.h>
#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());
int d_size = diagonal.getSize();
double alpha = 1.0;
double beta = 0.0;
BLAS_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;
}
int nn = diagonal.getSize();
int lda = diagonal.getSize();
int incx = x.skip();
BLAS_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;
}
int nn = diagonal.getSize();
int lda = diagonal.getSize();
int incx = x.skip();
BLAS_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;
int nn = diagonal.getSize();
int lda = diagonal.getSize();
int incx = x.skip();
BLAS_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;
int nn = diagonal.getSize();
int lda = diagonal.getSize();
int incx = x.skip();
BLAS_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();
}

View File

@ -0,0 +1,339 @@
/* $Header: /var/lib/cvs/dynare_cpp/sylv/cc/QuasiTriangular.h,v 1.1.1.1 2004/06/04 13:00:44 kamenik Exp $ */
/* Tag $Name: $ */
#ifndef QUASI_TRIANGULAR_H
#define QUASI_TRIANGULAR_H
#include "Vector.h"
#include "KronVector.h"
#include "SylvMatrix.h"
#include <list>
using namespace std;
class DiagonalBlock;
class Diagonal;
class DiagPair {
private:
double* a1;
double* a2;
public:
DiagPair() {}
DiagPair(double* aa1, double* aa2) {a1 = aa1; a2 = aa2;}
DiagPair(const DiagPair& p) {a1 = p.a1; a2 = p.a2;}
const DiagPair& operator=(const DiagPair& p) {a1 = p.a1; a2 = p.a2; return *this;}
const DiagPair& operator=(double v) {*a1 = v; *a2 = v; return *this;}
const double& operator*() const {return *a1;}
/** here we must not define double& operator*(), since it wouldn't
rewrite both values, we use operator= for this */
friend class Diagonal;
friend class DiagonalBlock;
};
class DiagonalBlock {
private:
int jbar;
bool real;
DiagPair alpha;
double* beta1;
double* beta2;
void copy(const DiagonalBlock& b) {
jbar = b.jbar;
real = b.real;
alpha = b.alpha;
beta1 = b.beta1;
beta2 = b.beta2;
}
public:
DiagonalBlock() {}
DiagonalBlock(int jb, bool r, double* a1, double* a2,
double* b1, double* b2)
: alpha(a1, a2)
{
jbar = jb;
real = r;
beta1 = b1;
beta2 = b2;
}
// construct complex block
DiagonalBlock(int jb, double* a1, double* a2)
: alpha(a1, a2)
{
jbar = jb;
real = false;
beta1 = a2 - 1;
beta2 = a1 + 1;
}
// construct real block
DiagonalBlock(int jb, double* a1)
: alpha(a1, a1)
{
jbar = jb;
real = true;
beta1 = 0;
beta2 = 0;
}
DiagonalBlock(const DiagonalBlock& b)
{copy(b);}
const DiagonalBlock& operator=(const DiagonalBlock& b)
{copy(b); return *this;}
int getIndex() const
{return jbar;}
bool isReal() const
{return real;}
const DiagPair& getAlpha() const
{return alpha;}
DiagPair& getAlpha()
{return alpha;}
double& getBeta1() const
{return *beta1;}
double& getBeta2() const
{return *beta2;}
double getDeterminant() const;
double getSBeta() const;
double getSize() const;
void setReal();
// for debugging
void checkBlock(const double* d, int d_size);
friend class Diagonal;
};
template <class _Tdiag, class _Tblock, class _Titer>
struct _diag_iter {
typedef _diag_iter<_Tdiag, _Tblock, _Titer> _Self;
_Tdiag diag;
_Titer it;
public:
_diag_iter(_Tdiag d, _Titer iter) : diag(d), it(iter) {}
_Tblock operator*() const {return *it;}
_Self& operator++() {++it; return *this;}
_Self& operator--() {--it; return *this;}
bool operator==(const _Self& x) const {return x.it == it;}
bool operator!=(const _Self& x) const {return x.it != it;}
const _Self& operator=(const _Self& x) {it = x.it; return *this;}
_Titer iter() const {return it;}
};
class Diagonal {
public:
typedef _diag_iter<const Diagonal&, const DiagonalBlock&, list<DiagonalBlock>::const_iterator> const_diag_iter;
typedef _diag_iter<Diagonal&, DiagonalBlock&, list<DiagonalBlock>::iterator> diag_iter;
private:
int num_all;
list<DiagonalBlock> blocks;
int num_real;
void copy(const Diagonal&);
public:
Diagonal() : num_all(0), num_real(0) {}
Diagonal(double* data, int d_size);
Diagonal(double* data, const Diagonal& d);
Diagonal(const Diagonal& d) {copy(d);}
const Diagonal& operator =(const Diagonal& d) {copy(d); return *this;}
virtual ~Diagonal() {}
int getNumComplex() const {return num_all - num_real;}
int getNumReal() const {return num_real;}
int getSize() const {return getNumReal() + 2*getNumComplex();}
int getNumBlocks() const {return num_all;}
void getEigenValues(Vector& eig) const;
void swapLogically(diag_iter it);
void checkConsistency(diag_iter it);
double getAverageSize(diag_iter start, diag_iter end);
diag_iter findClosestBlock(diag_iter start, diag_iter end, double a);
diag_iter findNextLargerBlock(diag_iter start, diag_iter end, double a);
void print() const;
diag_iter begin()
{return diag_iter(*this, blocks.begin());}
const_diag_iter begin() const
{return const_diag_iter(*this, blocks.begin());}
diag_iter end()
{return diag_iter(*this, blocks.end());}
const_diag_iter end() const
{return const_diag_iter(*this, blocks.end());}
/* redefine pointers as data start at p */
void changeBase(double* p);
private:
static double EPS;
static int getNumComplex(const double* data, int d_size);
static bool isZero(double p);
};
template <class _TRef, class _TPtr>
struct _matrix_iter {
typedef _matrix_iter<_TRef, _TPtr> _Self;
int d_size;
bool real;
_TPtr ptr;
public:
_matrix_iter(_TPtr base, int ds, bool r)
{ptr = base; d_size = ds; real = r;}
virtual ~_matrix_iter() {}
const _Self& operator=(const _Self& it)
{ptr = it.ptr; d_size = it.d_size; real = it.real; return *this;}
bool operator==(const _Self& it) const
{return ptr == it.ptr;}
bool operator!=(const _Self& it) const
{return ptr != it.ptr;}
_TRef operator*() const
{return *ptr;}
_TRef a() const
{return *ptr;}
virtual _Self& operator++() =0;
};
template <class _TRef, class _TPtr>
class _column_iter : public _matrix_iter<_TRef, _TPtr> {
typedef _matrix_iter<_TRef, _TPtr> _Tparent;
typedef _column_iter<_TRef, _TPtr> _Self;
int row;
public:
_column_iter(_TPtr base, int ds, bool r, int rw)
: _matrix_iter<_TRef, _TPtr>(base, ds, r), row(rw) {};
_Self& operator++()
{_Tparent::ptr++; row++; return *this;}
_TRef b() const
{
if (_Tparent::real) {
return *(_Tparent::ptr);
} else {
return *(_Tparent::ptr+_Tparent::d_size);
}
}
int getRow() const {return row;}
};
template <class _TRef, class _TPtr>
class _row_iter : public _matrix_iter<_TRef, _TPtr> {
typedef _matrix_iter<_TRef, _TPtr> _Tparent;
typedef _row_iter<_TRef, _TPtr> _Self;
int col;
public:
_row_iter(_TPtr base, int ds, bool r, int cl)
: _matrix_iter<_TRef, _TPtr>(base, ds, r), col(cl) {};
_Self& operator++()
{_Tparent::ptr += _Tparent::d_size; col++; return *this;}
virtual _TRef b() const
{
if (_Tparent::real) {
return *(_Tparent::ptr);
}else {
return *(_Tparent::ptr+1);
}
}
int getCol() const {return col;}
};
class SchurDecomp;
class SchurDecompZero;
class QuasiTriangular : public SqSylvMatrix {
public:
typedef _column_iter<const double&, const double*> const_col_iter;
typedef _column_iter<double&, double*> col_iter;
typedef _row_iter<const double&, const double*> const_row_iter;
typedef _row_iter<double&, double*> row_iter;
typedef Diagonal::const_diag_iter const_diag_iter;
typedef Diagonal::diag_iter diag_iter;
protected:
Diagonal diagonal;
public:
QuasiTriangular(const double* d, int d_size);
QuasiTriangular(double r, const QuasiTriangular& t);
QuasiTriangular(double r, const QuasiTriangular& t,
double rr, const QuasiTriangular& tt);
QuasiTriangular(int p, const QuasiTriangular& t);
QuasiTriangular(const SchurDecomp& decomp);
QuasiTriangular(const SchurDecompZero& decomp);
QuasiTriangular(const QuasiTriangular& t);
virtual ~QuasiTriangular();
const Diagonal& getDiagonal() const {return diagonal;}
int getNumOffdiagonal() const;
void swapDiagLogically(diag_iter it);
void checkDiagConsistency(diag_iter it);
double getAverageDiagSize(diag_iter start, diag_iter end);
diag_iter findClosestDiagBlock(diag_iter start, diag_iter end, double a);
diag_iter findNextLargerBlock(diag_iter start, diag_iter end, double a);
/* (I+T)y = x, y-->x */
virtual void solvePre(Vector& x, double& eig_min);
/* (I+T')y = x, y-->x */
virtual void solvePreTrans(Vector& x, double& eig_min);
/* (I+T)x = b */
virtual void solve(Vector& x, const ConstVector& b, double& eig_min);
/* (I+T')x = b */
virtual void solveTrans(Vector& x, const ConstVector& b, double& eig_min);
/* x = Tb */
virtual void multVec(Vector& x, const ConstVector& b) const;
/* x = T'b */
virtual void multVecTrans(Vector& x, const ConstVector& b) const;
/* x = x + Tb */
virtual void multaVec(Vector& x, const ConstVector& b) const;
/* x = x + T'b */
virtual void multaVecTrans(Vector& x, const ConstVector& b) const;
/* x = (T\otimes I)x */
virtual void multKron(KronVector& x) const;
/* x = (T'\otimes I)x */
virtual void multKronTrans(KronVector& x) const;
/* A = T*A */
virtual void multLeftOther(GeneralMatrix& a) const;
/* A = T'*A */
virtual void multLeftOtherTrans(GeneralMatrix& a) const;
const_diag_iter diag_begin() const
{return diagonal.begin();}
diag_iter diag_begin()
{return diagonal.begin();}
const_diag_iter diag_end() const
{return diagonal.end();}
diag_iter diag_end()
{return diagonal.end();}
/* iterators for off diagonal elements */
virtual const_col_iter col_begin(const DiagonalBlock& b) const;
virtual col_iter col_begin(const DiagonalBlock& b);
virtual const_row_iter row_begin(const DiagonalBlock& b) const;
virtual row_iter row_begin(const DiagonalBlock& b);
virtual const_col_iter col_end(const DiagonalBlock& b) const;
virtual col_iter col_end(const DiagonalBlock& b);
virtual const_row_iter row_end(const DiagonalBlock& b) const;
virtual row_iter row_end(const DiagonalBlock& b);
/* clone */
virtual QuasiTriangular* clone() const
{return new QuasiTriangular(*this);}
virtual QuasiTriangular* clone(int p, const QuasiTriangular& t) const
{return new QuasiTriangular(p, t);}
virtual QuasiTriangular* clone(double r) const
{return new QuasiTriangular(r, *this);}
virtual QuasiTriangular* clone(double r, double rr, const QuasiTriangular& tt) const
{return new QuasiTriangular(r, *this, rr, tt);}
protected:
void setMatrix(double r, const QuasiTriangular& t);
void addMatrix(double r, const QuasiTriangular& t);
private:
void addUnit();
/* x = x + (T\otimes I)b */
void multaKron(KronVector& x, const ConstKronVector& b) const;
/* x = x + (T'\otimes I)b */
void multaKronTrans(KronVector& x, const ConstKronVector& b) const;
/* implementation via iterators, useful for large matrices */
void setMatrixViaIter(double r, const QuasiTriangular& t);
void addMatrixViaIter(double r, const QuasiTriangular& t);
/* hide noneffective implementations of parents */
void multsVec(Vector& x, const ConstVector& d) const;
void multsVecTrans(Vector& x, const ConstVector& d) const;
};
#endif /* QUASI_TRIANGULAR_H */
// Local Variables:
// mode:C++
// End:

View File

@ -0,0 +1,148 @@
/* $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 <stdio.h>
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.");
}

View File

@ -0,0 +1,48 @@
/* $Header: /var/lib/cvs/dynare_cpp/sylv/cc/QuasiTriangularZero.h,v 1.1.1.1 2004/06/04 13:00:44 kamenik Exp $ */
/* Tag $Name: $ */
#ifndef QUASI_TRIANGULAR_ZERO_H
#define QUASI_TRIANGULAR_ZERO_H
#include "QuasiTriangular.h"
#include "GeneralMatrix.h"
class QuasiTriangularZero : public QuasiTriangular {
int nz; // number of zero columns
GeneralMatrix ru; // data in right upper part (nz,d_size)
public:
QuasiTriangularZero(int num_zeros, const double* d, int d_size);
QuasiTriangularZero(double r, const QuasiTriangularZero& t);
QuasiTriangularZero(double r, const QuasiTriangularZero& t,
double rr, const QuasiTriangularZero& tt);
QuasiTriangularZero(int p, const QuasiTriangularZero& t);
QuasiTriangularZero(const QuasiTriangular& t);
QuasiTriangularZero(const SchurDecompZero& decomp);
~QuasiTriangularZero();
void solvePre(Vector& x, double& eig_min);
void solvePreTrans(Vector& x, double& eig_min);
void multVec(Vector& x, const ConstVector& b) const;
void multVecTrans(Vector& x, const ConstVector& b) const;
void multaVec(Vector& x, const ConstVector& b) const;
void multaVecTrans(Vector& x, const ConstVector& b) const;
void multKron(KronVector& x) const;
void multKronTrans(KronVector& x) const;
void multLeftOther(GeneralMatrix& a) const;
/* clone */
virtual QuasiTriangular* clone() const
{return new QuasiTriangularZero(*this);}
virtual QuasiTriangular* clone(int p, const QuasiTriangular& t) const
{return new QuasiTriangularZero(p, (const QuasiTriangularZero&)t);}
virtual QuasiTriangular* clone(double r) const
{return new QuasiTriangularZero(r, *this);}
virtual QuasiTriangular* clone(double r, double rr, const QuasiTriangular& tt) const
{return new QuasiTriangularZero(r, *this, rr, (const QuasiTriangularZero&)tt);}
void print() const;
};
#endif /* QUASI_TRIANGULAR_ZERO_H */
// Local Variables:
// mode:C++
// End:

View File

@ -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.h"
#include "cpplapack.h"
SchurDecomp::SchurDecomp(const SqSylvMatrix& m)
: q_destroy(true), t_destroy(true)
{
int rows = m.numRows();
q = new SqSylvMatrix(rows);
SqSylvMatrix auxt(m);
int sdim;
double* const wr = new double[rows];
double* const wi = new double[rows];
int lwork = 6*rows;
double* const work = new double[lwork];
int info;
LAPACK_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();
}

View File

@ -0,0 +1,43 @@
/* $Header: /var/lib/cvs/dynare_cpp/sylv/cc/SchurDecomp.h,v 1.1.1.1 2004/06/04 13:00:44 kamenik Exp $ */
/* Tag $Name: $ */
#ifndef SCHUR_DECOMP_H
#define SCHUR_DECOMP_H
#include "SylvMatrix.h"
#include "QuasiTriangular.h"
class QuasiTriangular;
class SchurDecomp {
bool q_destroy;
SqSylvMatrix* q;
bool t_destroy;
QuasiTriangular* t;
public:
SchurDecomp(const SqSylvMatrix& m);
SchurDecomp(const QuasiTriangular& tr);
SchurDecomp(QuasiTriangular& tr);
const SqSylvMatrix& getQ() const {return *q;}
const QuasiTriangular& getT() const {return *t;}
SqSylvMatrix& getQ() {return *q;}
QuasiTriangular& getT() {return *t;}
virtual int getDim() const;
virtual ~SchurDecomp();
};
class SchurDecompZero : public SchurDecomp {
GeneralMatrix ru; /* right upper matrix */
public:
SchurDecompZero(const GeneralMatrix& m);
const GeneralMatrix& getRU() const {return ru;}
int getDim() const;
int getZeroCols() const {return ru.numRows();}
};
#endif /* SCHUR_DECOMP_H */
// Local Variables:
// mode:C++
// End:

View File

@ -0,0 +1,91 @@
#include "SchurDecompEig.h"
#include "SylvException.h"
#include "cpplapack.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;
int n = getDim();
int ifst = (*it).getIndex() + 1;
int ilst = (*itadd).getIndex() + 1;
double* work = new double[n];
int info;
LAPACK_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 LAPACK_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;
}
}

View File

@ -0,0 +1,31 @@
/* $Header: /var/lib/cvs/dynare_cpp/sylv/cc/SchurDecompEig.h,v 1.1.1.1 2004/06/04 13:00:44 kamenik Exp $ */
/* Tag $Name: $ */
// contains algorithms for eigenvalue reordering
#ifndef SCHUR_DECOMP_EIG_H
#define SCHUR_DECOMP_EIG_H
#include "SchurDecomp.h"
#include "QuasiTriangular.h"
class SchurDecompEig : public SchurDecomp {
public:
typedef QuasiTriangular::diag_iter diag_iter;
SchurDecompEig(const SqSylvMatrix& m) : SchurDecomp(m) {}
SchurDecompEig(const QuasiTriangular& tr) : SchurDecomp(tr) {};
SchurDecompEig(QuasiTriangular& tr) : SchurDecomp(tr) {}
diag_iter bubbleEigen(diag_iter from, diag_iter to);
void orderEigen();
protected:
bool tryToSwap(diag_iter& it, diag_iter& itadd);
};
#endif /* SCHUR_DECOMP_EIG_H */
// Local Variables:
// mode:C++
// End:

View File

@ -0,0 +1,160 @@
/* $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 "cpplapack.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());
int isgn = -1;
int m = A.numRows();
int n = B.numRows();
double scale;
int info;
LAPACK_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:

View File

@ -0,0 +1,41 @@
/* $Header: /var/lib/cvs/dynare_cpp/sylv/cc/SimilarityDecomp.h,v 1.1.1.1 2004/06/04 13:00:44 kamenik Exp $ */
/* Tag $Name: $ */
#ifndef SIMILARITY_DECOMP_H
#define SIMILARITY_DECOMP_H
#include "SylvMatrix.h"
#include "BlockDiagonal.h"
#include "SylvParams.h"
class SimilarityDecomp {
SqSylvMatrix* q;
BlockDiagonal* b;
SqSylvMatrix* invq;
typedef BlockDiagonal::diag_iter diag_iter;
public:
SimilarityDecomp(const double* d, int d_size, double log10norm = 3.0);
virtual ~SimilarityDecomp();
const SqSylvMatrix& getQ() const
{return *q;}
const SqSylvMatrix& getInvQ() const
{return *invq;}
const BlockDiagonal& getB() const
{return *b;}
void check(SylvParams& pars, const GeneralMatrix& m) const;
void infoToPars(SylvParams& pars) const;
protected:
void getXDim(diag_iter start, diag_iter end, int& rows, int& cols) const;
bool solveX(diag_iter start, diag_iter end, GeneralMatrix& X, double norm) const;
void updateTransform(diag_iter start, diag_iter end, GeneralMatrix& X);
void bringGuiltyBlock(diag_iter start, diag_iter& end);
void diagonalize(double norm);
};
#endif /* SIMILARITY_DECOMP_H */
// Local Variables:
// mode:C++
// End:

View File

@ -0,0 +1,69 @@
/* $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 <string.h>
#include <stdio.h>
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);
printf(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;
}

View File

@ -0,0 +1,39 @@
/* $Header: /var/lib/cvs/dynare_cpp/sylv/cc/SylvException.h,v 1.1.1.1 2004/06/04 13:00:44 kamenik Exp $ */
/* Tag $Name: $ */
#ifndef SYLV_EXCEPTION_H
#define SYLV_EXCEPTION_H
#include "SylvMemory.h"
class SylvException : public MallocAllocator {
protected:
char file[50];
int line;
const SylvException* source;
public:
SylvException(const char* f, int l, const SylvException* s);
virtual ~SylvException();
virtual int printMessage(char* str, int maxlen) const;
void printMessage() const;
};
class SylvExceptionMessage : public SylvException {
char message[500];
public:
SylvExceptionMessage(const char* f, int l, const char* mes);
virtual int printMessage(char* str, int maxlen) const;
};
// define macros:
#define SYLV_EXCEPTION(exc) (SylvException(__FILE__, __LINE__, exc))
#define SYLV_MES_EXCEPTION(mes) (SylvExceptionMessage(__FILE__, __LINE__, mes))
#endif /* SYLV_EXCEPTION_H */
// Local Variables:
// mode:C++
// End:

View File

@ -0,0 +1,251 @@
/* $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 "cppblas.h"
#include "cpplapack.h"
#include <stdio.h>
#include <string.h>
#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) {
int mm = a.numRows();
int nn = cols;
int kk = a.numCols();
double alpha = 1.0;
int lda = a.getLD();
int ldb = ld;
double beta = 0.0;
int ldc = ld;
BLAS_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);
int * const ipiv = new int[rows];
int info;
LAPACK_dgetrf(&rows, &rows, inv.base(), &rows, ipiv, &info);
// solve a
int acols = a.numCols();
double* abase = a.base();
LAPACK_dgetrs("N", &rows, &acols, inv.base(), &rows, ipiv,
abase, &rows, &info);
// solve b
int bcols = b.numCols();
double* bbase = b.base();
LAPACK_dgetrs("N", &rows, &bcols, inv.base(), &rows, ipiv,
bbase, &rows, &info);
delete [] ipiv;
// condition numbers
double* const work = new double[4*rows];
int* const iwork = new int[rows];
double norm1 = getNorm1();
LAPACK_dgecon("1", &rows, inv.base(), &rows, &norm1, &rcond1,
work, iwork, &info);
double norminf = getNormInf();
LAPACK_dgecon("I", &rows, inv.base(), &rows, &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:

View File

@ -0,0 +1,81 @@
/* $Header: /var/lib/cvs/dynare_cpp/sylv/cc/SylvMatrix.h,v 1.1.1.1 2004/06/04 13:00:44 kamenik Exp $ */
/* Tag $Name: $ */
#ifndef SYLV_MATRIX_H
#define SYLV_MATRIX_H
#include "GeneralMatrix.h"
#include "KronVector.h"
class SqSylvMatrix;
class SylvMatrix : public GeneralMatrix {
public:
SylvMatrix(int m, int n)
: GeneralMatrix(m,n) {}
SylvMatrix(const double* d, int m, int n)
: GeneralMatrix(d, m, n) {}
SylvMatrix(double* d, int m, int n)
: GeneralMatrix(d, m, n) {}
SylvMatrix(const GeneralMatrix& m)
: GeneralMatrix(m) {}
SylvMatrix(const GeneralMatrix& m, int i, int j, int nrows, int ncols)
: GeneralMatrix(m, i, j, nrows, ncols) {}
SylvMatrix(GeneralMatrix& m, int i, int j, int nrows, int ncols)
: GeneralMatrix(m, i, j, nrows, ncols) {}
SylvMatrix(const GeneralMatrix& a, const GeneralMatrix& b)
: GeneralMatrix(a, b) {}
/* this = |I 0|* this
|0 m| */
void multLeftI(const SqSylvMatrix& m);
/* this = |I 0|* this
|0 m'| */
void multLeftITrans(const SqSylvMatrix& m);
/* this = |0 a|*b, so that |0 a| is square */
void multLeft(int zero_cols, const GeneralMatrix& a, const GeneralMatrix& b);
/* this = this * (m\otimes m..\otimes m) */
void multRightKron(const SqSylvMatrix& m, int order);
/* this = this * (m'\otimes m'..\otimes m') */
void multRightKronTrans(const SqSylvMatrix& m, int order);
/* this = P*this, x = P*x, where P is gauss transformation setting
* a given element to zero */
void eliminateLeft(int row, int col, Vector& x);
/* this = this*P, x = P'*x, where P is gauss transformation setting
* a given element to zero */
void eliminateRight(int row, int col, Vector& x);
};
class SqSylvMatrix : public SylvMatrix {
public:
SqSylvMatrix(int m) : SylvMatrix(m, m) {}
SqSylvMatrix(const double* d, int m) : SylvMatrix(d, m, m) {}
SqSylvMatrix(double* d, int m) : SylvMatrix(d, m, m) {}
SqSylvMatrix(const SqSylvMatrix& m) : SylvMatrix(m) {}
SqSylvMatrix(const GeneralMatrix& m, int i, int j, int nrows)
: SylvMatrix(m, i, j, nrows, nrows) {}
SqSylvMatrix(GeneralMatrix& m, int i, int j, int nrows)
: SylvMatrix(m, i, j, nrows, nrows) {}
SqSylvMatrix(const GeneralMatrix& a, const GeneralMatrix& b);
const SqSylvMatrix& operator=(const SqSylvMatrix& m)
{GeneralMatrix::operator=(m); return *this;}
/* x = (this \otimes this..\otimes this)*d */
void multVecKron(KronVector& x, const KronVector& d) const;
/* x = (this' \otimes this'..\otimes this')*d */
void multVecKronTrans(KronVector& x, const KronVector& d) const;
/* a = inv(this)*a, b=inv(this)*b */
void multInvLeft2(GeneralMatrix& a, GeneralMatrix& b,
double& rcond1, double& rcondinf) const;
/* this = I */
void setUnit();
};
#endif /* SYLV_MATRIX_H */
// Local Variables:
// mode:C++
// End:

View File

@ -0,0 +1,221 @@
/* $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"
#ifdef MATLAB
#include "mex.h"
#endif
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
/**********************************************************/
/* 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;
#ifdef MATLAB
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()
{
#ifndef MATLAB
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)
{
#ifdef MATLAB
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)
{
#ifdef MATLAB
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)
{
#ifdef MATLAB
throw SYLV_MES_EXCEPTION("Attempt to call wrong memory destructor.");
#else
free(p);
#endif
}
void MallocAllocator::operator delete[](void* p)
{
#ifdef MATLAB
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);
}

View File

@ -0,0 +1,63 @@
/* $Header: /var/lib/cvs/dynare_cpp/sylv/cc/SylvMemory.h,v 1.1.1.1 2004/06/04 13:00:49 kamenik Exp $ */
/* Tag $Name: $ */
#ifndef SYLV_MEMORY_H
#define SYLV_MEMORY_H
#include "SylvParams.h"
#include <new>
class MallocAllocator {
#ifdef USE_MEMORY_POOL
public:
void* operator new(size_t size);
void* operator new[](size_t size);
void operator delete(void* p);
void operator delete[](void* p);
#endif
};
#ifdef USE_MEMORY_POOL
void* operator new(size_t size);
void* operator new[](size_t size);
void operator delete(void* p);
void operator delete[](void* p);
#endif
class SylvMemoryPool {
char* base;
size_t length;
size_t allocated;
bool stack_mode;
SylvMemoryPool(const SylvMemoryPool&);
const SylvMemoryPool& operator=(const SylvMemoryPool&);
public:
SylvMemoryPool();
~SylvMemoryPool();
void init(size_t size);
void* allocate(size_t size);
void free(void* p);
void reset();
void setStackMode(bool);
};
class SylvMemoryDriver {
SylvMemoryDriver(const SylvMemoryDriver&);
const SylvMemoryDriver& operator=(const SylvMemoryDriver&);
public:
SylvMemoryDriver(int num_d, int m, int n, int order);
SylvMemoryDriver(const SylvParams& pars, int num_d, int m, int n, int order);
static void setStackMode(bool);
~SylvMemoryDriver();
protected:
void allocate(int num_d, int m, int n, int order);
};
#endif /* SYLV_MEMORY_H */
// Local Variables:
// mode:C++
// End:

View File

@ -0,0 +1,230 @@
/* $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";
}
#ifdef MATLAB
mxArray* SylvParams::DoubleParamItem::createMatlabArray() const
{
return mxCreateScalarDouble(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 int 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:

View File

@ -0,0 +1,162 @@
/* $Header: /var/lib/cvs/dynare_cpp/sylv/cc/SylvParams.h,v 1.1.1.1 2004/06/04 13:00:54 kamenik Exp $ */
/* Tag $Name: $ */
#ifndef SYLV_PARAMS_H
#define SYLV_PARAMS_H
#include <stdio.h>
#include <string.h>
#ifdef MATLAB
#include "mex.h"
#endif
typedef enum {def, changed, undef} status;
template <class _Type>
struct ParamItem {
protected:
typedef ParamItem<_Type> _Self;
status s;
_Type value;
public:
ParamItem()
{s = undef;}
ParamItem(_Type val)
{value = val; s = def;}
ParamItem(const _Self& item)
{value = item.value; s = item.s;}
const _Self& operator=(const _Self& item)
{value = item.value; s = item.s; return *this;}
const _Self& operator=(const _Type& val)
{value = val; s = changed; return *this;}
_Type operator*() const
{return value;}
status getStatus() const
{return s;}
void print(FILE* f, const char* prefix, const char* str, const char* fmt) const
{
if (s == undef)
return;
char out[1000];
strcpy(out, prefix);
strcat(out, str);
strcat(out, "= ");
strcat(out, fmt);
if (s == def)
strcat(out, " <default>");
strcat(out,"\n");
fprintf(f, out, value);
}
};
class SylvParams {
public:
typedef enum {iter, recurse} solve_method;
protected:
class DoubleParamItem : public ParamItem<double> {
public:
DoubleParamItem() : ParamItem<double>() {}
DoubleParamItem(double val) : ParamItem<double>(val) {}
DoubleParamItem(const DoubleParamItem& item) : ParamItem<double>(item) {}
const DoubleParamItem& operator=(const double& val)
{ParamItem<double>::operator=(val); return *this;}
#ifdef MATLAB
mxArray* createMatlabArray() const;
#endif
};
class IntParamItem : public ParamItem<int> {
public:
IntParamItem() : ParamItem<int>() {}
IntParamItem(int val) : ParamItem<int>(val) {}
IntParamItem(const IntParamItem& item) : ParamItem<int>(item) {}
const IntParamItem& operator=(const int& val)
{ParamItem<int>::operator=(val); return *this;}
#ifdef MATLAB
mxArray* createMatlabArray() const;
#endif
};
class BoolParamItem : public ParamItem<bool> {
public:
BoolParamItem() : ParamItem<bool>() {}
BoolParamItem(bool val) : ParamItem<bool>(val) {}
BoolParamItem(const BoolParamItem& item) : ParamItem<bool>(item) {}
const BoolParamItem& operator=(const bool& val)
{ParamItem<bool>::operator=(val); return *this;}
#ifdef MATLAB
mxArray* createMatlabArray() const;
#endif
};
class MethodParamItem : public ParamItem<solve_method> {
public:
MethodParamItem() : ParamItem<solve_method>() {}
MethodParamItem(solve_method val) : ParamItem<solve_method>(val) {}
MethodParamItem(const MethodParamItem& item) : ParamItem<solve_method>(item) {}
const MethodParamItem operator=(const solve_method& val)
{ParamItem<solve_method>::operator=(val); return *this;}
#ifdef MATLAB
mxArray* createMatlabArray() const;
#endif
};
public:
// input parameters
MethodParamItem method; // method of solution: iter/recurse
DoubleParamItem convergence_tol; // norm for what we consider converged
IntParamItem max_num_iter; // max number of iterations
DoubleParamItem bs_norm; // Bavely Stewart log10 of norm for diagonalization
BoolParamItem want_check; // true => allocate extra space for checks
// output parameters
BoolParamItem converged; // true if converged
DoubleParamItem iter_last_norm; // norm of the last iteration
IntParamItem num_iter; // number of iterations
DoubleParamItem f_err1; // norm 1 of diagonalization abs. error C-V*F*inv(V)
DoubleParamItem f_errI; // norm Inf of diagonalization abs. error C-V*F*inv(V)
DoubleParamItem viv_err1; // norm 1 of error I-V*inv(V)
DoubleParamItem viv_errI; // norm Inf of error I-V*inv(V)
DoubleParamItem ivv_err1; // norm 1 of error I-inv(V)*V
DoubleParamItem ivv_errI; // norm Inf of error I-inv(V)*V
IntParamItem f_blocks; // number of diagonal blocks of F
IntParamItem f_largest; // size of largest diagonal block in F
IntParamItem f_zeros; // number of off diagonal zeros in F
IntParamItem f_offdiag; // number of all off diagonal elements in F
DoubleParamItem rcondA1; // reciprocal cond 1 number of A
DoubleParamItem rcondAI; // reciprocal cond Inf number of A
DoubleParamItem eig_min; // minimum eigenvalue of the solved system
DoubleParamItem mat_err1; // rel. matrix 1 norm of A*X-B*X*kron(C,..,C)-D
DoubleParamItem mat_errI; // rel. matrix Inf norm of A*X-B*X*kron(C,..,C)-D
DoubleParamItem mat_errF; // rel. matrix Frob. norm of A*X-B*X*kron(C,..,C)-D
DoubleParamItem vec_err1; // rel. vector 1 norm of A*X-B*X*kron(C,..,C)-D
DoubleParamItem vec_errI; // rel. vector Inf norm of A*X-B*X*kron(C,..,C)-D
DoubleParamItem cpu_time; // time of the job in CPU seconds
// note: remember to change copy() if adding/removing member
SylvParams(bool wc = false)
: method(recurse), convergence_tol(1.e-30), max_num_iter(15),
bs_norm(1.3), want_check(wc) {}
SylvParams(const SylvParams& p)
{copy(p);}
const SylvParams& operator=(const SylvParams& p)
{copy(p); return *this;}
~SylvParams() {}
void print(const char* prefix) const;
void print(FILE* fdesc, const char* prefix) const;
void setArrayNames(int& num, const char** names) const;
#ifdef MATLAB
mxArray* createStructArray() const;
#endif
private:
void copy(const SylvParams& p);
};
#endif /* SYLV_PARAMS_H */
// Local Variables:
// mode:C++
// End:

View File

@ -0,0 +1,51 @@
/* $Header: /var/lib/cvs/dynare_cpp/sylv/cc/SylvesterSolver.h,v 1.1.1.1 2004/06/04 13:00:54 kamenik Exp $ */
/* Tag $Name: $ */
#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"
class SylvesterSolver {
protected:
const QuasiTriangular* const matrixK;
const QuasiTriangular* const matrixF;
private:
/* return true when it is more efficient to use QuasiTriangular
* than QuasiTriangularZero */
static bool zeroPad(const SchurDecompZero& kdecomp) {
return ((kdecomp.getZeroCols()*3 < kdecomp.getDim()*2) ||
(kdecomp.getZeroCols() < 10));
}
public:
SylvesterSolver(const QuasiTriangular& k, const QuasiTriangular& f)
: matrixK(new QuasiTriangular(k)),
matrixF(new QuasiTriangular(f))
{}
SylvesterSolver(const SchurDecompZero& kdecomp, const SchurDecomp& fdecomp)
: matrixK((zeroPad(kdecomp)) ?
new QuasiTriangular(kdecomp) : new QuasiTriangularZero(kdecomp)),
matrixF(new QuasiTriangular(fdecomp))
{}
SylvesterSolver(const SchurDecompZero& kdecomp, const SimilarityDecomp& fdecomp)
: matrixK((zeroPad(kdecomp)) ?
new QuasiTriangular(kdecomp) : new QuasiTriangularZero(kdecomp)),
matrixF(new BlockDiagonal(fdecomp.getB()))
{}
virtual ~SylvesterSolver()
{delete matrixK; delete matrixF;}
virtual void solve(SylvParams& pars, KronVector& x) const = 0;
};
#endif /* SYLVESTER_SOLVER_H */
// Local Variables:
// mode:C++
// End:

View File

@ -0,0 +1,101 @@
/* $Header$ */
/* Tag $Name$ */
#include "SymSchurDecomp.h"
#include "SylvException.h"
#include "cpplapack.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";
int n = mata.numRows();
GeneralMatrix tmpa(mata);
double* a = tmpa.base();
int lda = tmpa.getLD();
double dum;
double* vl = &dum;
double* vu = &dum;
int idum;
int* il = &idum;
int* iu = &idum;
double abstol = 0.0;
int m = n;
double* w = lambda.base();
double* z = q.base();
int ldz = q.getLD();
int* isuppz = new int[2*std::max(1,m)];
double tmpwork;
int lwork = -1;
int tmpiwork;
int liwork = -1;
int info;
// query for lwork and liwork
LAPACK_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];
int* iwork = new int[liwork];
// do the calculation
LAPACK_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;
}

View File

@ -0,0 +1,41 @@
/* $Header: /var/lib/cvs/dynare_cpp/sylv/cc/SchurDecomp.h,v 1.1.1.1 2004/06/04 13:00:44 kamenik Exp $ */
/* Tag $Name: $ */
#ifndef SYM_SCHUR_DECOMP_H
#define SYM_SCHUR_DECOMP_H
#include "SylvMatrix.h"
class SymSchurDecomp {
protected:
Vector lambda;
SqSylvMatrix q;
public:
/** Calculates A = Q*Lambda*Q^T, where A is assummed to be
* symmetric and Lambda real diagonal, hence a vector. */
SymSchurDecomp(const GeneralMatrix& a);
SymSchurDecomp(const SymSchurDecomp& ssd)
: lambda(ssd.lambda), q(ssd.q) {}
virtual ~SymSchurDecomp() {}
const Vector& getLambda() const
{return lambda;}
const SqSylvMatrix& getQ() const
{return q;}
/** Return factor F*F^T = A, raises and exception if A is not
* positive semidefinite, F must be square. */
void getFactor(GeneralMatrix& f) const;
/** Returns true if A is positive semidefinite. */
bool isPositiveSemidefinite() const;
/** Correct definitness. This sets all eigenvalues between minus
* tolerance and zero to zero. */
void correctDefinitness(double tol);
};
#endif
// Local Variables:
// mode:C++
// End:

View File

@ -0,0 +1,392 @@
/* $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 <stdio.h>
#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:

View File

@ -0,0 +1,115 @@
/* $Header: /var/lib/cvs/dynare_cpp/sylv/cc/TriangularSylvester.h,v 1.1.1.1 2004/06/04 13:01:03 kamenik Exp $ */
/* Tag $Name: $ */
#ifndef TRIANGULAR_SYLVESTER_H
#define TRIANGULAR_SYLVESTER_H
#include "SylvesterSolver.h"
#include "KronVector.h"
#include "QuasiTriangular.h"
#include "QuasiTriangularZero.h"
#include "SimilarityDecomp.h"
class TriangularSylvester : public SylvesterSolver {
const QuasiTriangular* const matrixKK;
const QuasiTriangular* const matrixFF;
public:
TriangularSylvester(const QuasiTriangular& k, const QuasiTriangular& f);
TriangularSylvester(const SchurDecompZero& kdecomp, const SchurDecomp& fdecomp);
TriangularSylvester(const SchurDecompZero& kdecomp, const SimilarityDecomp& fdecomp);
virtual ~TriangularSylvester();
void print() const;
void solve(SylvParams& pars, KronVector& d) const;
void solvi(double r, KronVector& d, double& eig_min) const;
void solvii(double alpha, double beta1, double beta2,
KronVector& d1, KronVector& d2,
double& eig_min) const;
void solviip(double alpha, double betas,
KronVector& d, double& eig_min) const;
/* evaluates:
|x1| |d1| |alpha -beta1| |d1|
| | = | |+| |\otimes F'...\otimes K | |
|x2| |d2| |beta2 alpha| |d2|
*/
void linEval(double alpha, double beta1, double beta2,
KronVector& x1, KronVector& x2,
const ConstKronVector& d1, const ConstKronVector& d2) const;
void linEval(double alpha, double beta1, double beta2,
KronVector& x1, KronVector& x2,
const KronVector& d1, const KronVector& d2) const
{linEval(alpha, beta1, beta2, x1, x2,
ConstKronVector(d1), ConstKronVector(d2));}
/* evaluates:
|x1| |d1| |gamma -delta1| |d1|
| | = | | + 2alpha*| |\otimes F'...\otimes K | | +
|x2| |d2| |delta2 gamma| |d2|
|gamma -delta1|^2 |d1|
+ (alpha^2+betas)*| |\otimes F'2...\otimes K2 | |
|delta2 gamma| |d2|
*/
void quaEval(double alpha, double betas,
double gamma, double delta1, double delta2,
KronVector& x1, KronVector& x2,
const ConstKronVector& d1, const ConstKronVector& d2) const;
void quaEval(double alpha, double betas,
double gamma, double delta1, double delta2,
KronVector& x1, KronVector& x2,
const KronVector& d1, const KronVector& d2) const
{quaEval(alpha, betas, gamma, delta1, delta2, x1, x2,
ConstKronVector(d1), ConstKronVector(d2));}
private:
/* returns square of size of minimal eigenvalue of the system solved,
now obsolete */
double getEigSep(int depth) const;
/* recursivelly calculates kronecker product of complex vectors (used in getEigSep) */
static void multEigVector(KronVector& eig, const Vector& feig, const Vector& keig);
/* auxiliary typedefs */
typedef QuasiTriangular::const_diag_iter const_diag_iter;
typedef QuasiTriangular::const_row_iter const_row_iter;
/* called from solvi */
void solviRealAndEliminate(double r, const_diag_iter di,
KronVector& d, double& eig_min) const;
void solviComplexAndEliminate(double r, const_diag_iter di,
KronVector& d, double& eig_min) const;
/* called from solviip */
void solviipRealAndEliminate(double alpha, double betas,
const_diag_iter di, const_diag_iter dsi,
KronVector& d, double& eig_min) const;
void solviipComplexAndEliminate(double alpha, double betas,
const_diag_iter di, const_diag_iter dsi,
KronVector& d, double& eig_min) const;
/* eliminations */
void solviEliminateReal(const_diag_iter di, KronVector& d,
const KronVector& y, double divisor) const;
void solviEliminateComplex(const_diag_iter di, KronVector& d,
const KronVector& y1, const KronVector& y2,
double divisor) const;
void solviipEliminateReal(const_diag_iter di, const_diag_iter dsi,
KronVector& d,
const KronVector& y1, const KronVector& y2,
double divisor, double divisor2) const;
void 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;
/* Lemma 2 */
void solviipComplex(double alpha, double betas, double gamma,
double delta1, double delta2,
KronVector& d1, KronVector& d2,
double& eig_min) const;
/* norms for what we consider zero on diagonal of F */
static double diag_zero;
static double diag_zero_sq; // square of diag_zero
};
#endif /* TRIANGULAR_SYLVESTER_H */
// Local Variables:
// mode:C++
// End:

View File

@ -0,0 +1,366 @@
/* $Header: /var/lib/cvs/dynare_cpp/sylv/cc/Vector.cpp,v 1.1.1.1 2004/06/04 13:01:13 kamenik Exp $ */
/* Tag $Name: $ */
#include "Vector.h"
#include "GeneralMatrix.h"
#include "SylvException.h"
#include "cppblas.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <cmath>
#include <algorithm>
#include <limits>
using namespace std;
ZeroPad zero_pad;
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=%d, len=%d\n", destroy, v.destroy, 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)
{
int n = length();
int incy = skip();
BLAS_dcopy(&n, d, &inc, 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)
{
int n = length();
int incx = v.skip();
int incy = skip();
BLAS_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)
{
int n = length()/2;
int incx = v.skip();
int incy = skip();
BLAS_zaxpy(&n, z, v.base(), &incx, base(), &incy);
}
void Vector::mult(double r)
{
int n = length();
int incx = skip();
BLAS_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.");
int n = length();
int incx = skip();
int incy = y.skip();
return BLAS_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;
}

View File

@ -0,0 +1,178 @@
/* $Header: /var/lib/cvs/dynare_cpp/sylv/cc/Vector.h,v 1.1.1.1 2004/06/04 13:01:13 kamenik Exp $ */
/* Tag $Name: $ */
#ifndef VECTOR_H
#define VECTOR_H
/* NOTE! Vector and ConstVector have not common super class in order
* to avoid running virtual method invokation mechanism. Some
* members, and methods are thus duplicated */
#include <stdio.h>
class GeneralMatrix;
class ConstVector;
class Vector {
protected:
int len;
int s;
double* data;
bool destroy;
public:
Vector() : len(0), s(1), data(0), destroy(false) {}
Vector(int l) : len(l), s(1), data(new double[l]), destroy(true) {}
Vector(Vector& v) : len(v.length()), s(v.skip()), data(v.base()), destroy(false) {}
Vector(const Vector& v)
: len(v.length()), s(1), data(new double[len]), destroy(true)
{copy(v.base(), v.skip());}
Vector(const ConstVector& v);
Vector(const double* d, int l)
: len(l), s(1), data(new double[len]), destroy(true)
{copy(d, 1);}
Vector(double* d, int l)
: len(l), s(1), data(d), destroy(false) {}
Vector(double* d, int skip, int l)
: len(l), s(skip), data(d), destroy(false) {}
Vector(Vector& v, int off, int l);
Vector(const Vector& v, int off, int l);
Vector(GeneralMatrix& m, int col);
Vector(int row, GeneralMatrix& m);
const Vector& operator=(const Vector& v);
const Vector& operator=(const ConstVector& v);
double& operator[](int i)
{return data[s*i];}
const double& operator[](int i) const
{return data[s*i];}
const double* base() const
{return data;}
double* base()
{return data;}
int length() const
{return len;}
int skip() const
{return s;}
/** Exact equality. */
bool operator==(const Vector& y) const;
bool operator!=(const Vector& y) const;
/** Lexicographic ordering. */
bool operator<(const Vector& y) const;
bool operator<=(const Vector& y) const;
bool operator>(const Vector& y) const;
bool operator>=(const Vector& y) const;
virtual ~Vector();
void zeros();
void nans();
void infs();
bool toBeDestroyed() const {return destroy;}
void rotatePair(double alpha, double beta1, double beta2, int i);
void add(double r, const Vector& v);
void add(double r, const ConstVector& v);
void add(const double* z, const Vector& v);
void add(const double* z, const ConstVector& v);
void mult(double r);
double getNorm() const;
double getMax() const;
double getNorm1() const;
double dot(const Vector& y) const;
bool isFinite() const;
void print() const;
/* multiplies | alpha -beta1| |b1| |x1|
| |\otimes I .| | = | |
| -beta2 alpha| |b2| |x2|
*/
static void mult2(double alpha, double beta1, double beta2,
Vector& x1, Vector& x2,
const Vector& b1, const Vector& b2);
/* same, but adds instead of set */
static void mult2a(double alpha, double beta1, double beta2,
Vector& x1, Vector& x2,
const Vector& b1, const Vector& b2);
/* same, but subtracts instead of add */
static void mult2s(double alpha, double beta1, double beta2,
Vector& x1, Vector& x2,
const Vector& b1, const Vector& b2)
{mult2a(-alpha, -beta1, -beta2, x1, x2, b1, b2);}
private:
void copy(const double* d, int inc);
const Vector& operator=(int); // must not be used (not implemented)
const Vector& operator=(double); // must not be used (not implemented)
};
class BaseConstVector {
protected:
int len;
int s;
const double* data;
public:
BaseConstVector(int l, int si, const double* d) : len(l), s(si), data(d) {}
BaseConstVector(const BaseConstVector& v) : len(v.len), s(v.s), data(v.data) {}
const BaseConstVector& operator=(const BaseConstVector& v)
{len = v.len; s = v.s; data = v.data; return *this;}
const double& operator[](int i) const
{return data[s*i];}
const double* base() const
{return data;}
int length() const
{return len;}
int skip() const
{return s;}
};
class ConstGeneralMatrix;
class ConstVector : public BaseConstVector {
public:
ConstVector(const Vector& v) : BaseConstVector(v.length(), v.skip(), v.base()) {}
ConstVector(const ConstVector& v) : BaseConstVector(v) {}
ConstVector(const double* d, int l) : BaseConstVector(l, 1, d) {}
ConstVector(const Vector& v, int off, int l);
ConstVector(const ConstVector& v, int off, int l);
ConstVector(const double* d, int skip, int l);
ConstVector(const ConstGeneralMatrix& m, int col);
ConstVector(int row, const ConstGeneralMatrix& m);
virtual ~ConstVector() {}
/** Exact equality. */
bool operator==(const ConstVector& y) const;
bool operator!=(const ConstVector& y) const
{return ! operator==(y);}
/** Lexicographic ordering. */
bool operator<(const ConstVector& y) const;
bool operator<=(const ConstVector& y) const
{return operator<(y) || operator==(y);}
bool operator>(const ConstVector& y) const
{return ! operator<=(y);}
bool operator>=(const ConstVector& y) const
{return ! operator<(y);}
double getNorm() const;
double getMax() const;
double getNorm1() const;
double dot(const ConstVector& y) const;
bool isFinite() const;
void print() const;
};
class ZeroPad {
public:
//static const int length = 16;
enum { length = 16};
private:
double pad[16];
public:
ZeroPad();
const double* getBase() const {return pad;}
};
#endif /* VECTOR_H */
// Local Variables:
// mode:C++
// End:

View File

@ -0,0 +1,68 @@
/* $Header: /var/lib/cvs/dynare_cpp/sylv/cc/cppblas.h,v 1.2 2004/11/24 20:42:52 kamenik Exp $ */
/* Tag $Name: $ */
#ifndef CPPBLAS_H
#define CPPBLAS_H
#if defined(MATLAB) && !defined(__linux__)
#define BLAS_dgemm dgemm
#define BLAS_dgemv dgemv
#define BLAS_dtrsv dtrsv
#define BLAS_dtrmv dtrmv
#define BLAS_daxpy daxpy
#define BLAS_dcopy dcopy
#define BLAS_zaxpy zaxpy
#define BLAS_dscal dscal
#define BLAS_dtrsm dtrsm
#define BLAS_ddot ddot
#else /* defined(MATLAB) && !defined(__linux__) */
#define BLAS_dgemm dgemm_
#define BLAS_dgemv dgemv_
#define BLAS_dtrsv dtrsv_
#define BLAS_dtrmv dtrmv_
#define BLAS_daxpy daxpy_
#define BLAS_dcopy dcopy_
#define BLAS_zaxpy zaxpy_
#define BLAS_dscal dscal_
#define BLAS_dtrsm dtrsm_
#define BLAS_ddot ddot_
#endif /* defined(MATLAB) && !defined(__linux__) */
#define BLCHAR const char*
#define CONST_BLINT const int*
#define CONST_BLDOU const double*
#define BLDOU double*
extern "C" {
void BLAS_dgemm(BLCHAR transa, BLCHAR transb, CONST_BLINT m, CONST_BLINT n,
CONST_BLINT k, CONST_BLDOU alpha, CONST_BLDOU a, CONST_BLINT lda,
CONST_BLDOU b, CONST_BLINT ldb, CONST_BLDOU beta,
BLDOU c, CONST_BLINT ldc);
void BLAS_dgemv(BLCHAR trans, CONST_BLINT m, CONST_BLINT n, CONST_BLDOU alpha,
CONST_BLDOU a, CONST_BLINT lda, CONST_BLDOU x, CONST_BLINT incx,
CONST_BLDOU beta, BLDOU y, CONST_BLINT incy);
void BLAS_dtrsv(BLCHAR uplo, BLCHAR trans, BLCHAR diag, CONST_BLINT n,
CONST_BLDOU a, CONST_BLINT lda, BLDOU x, CONST_BLINT incx);
void BLAS_dtrmv(BLCHAR uplo, BLCHAR trans, BLCHAR diag, CONST_BLINT n,
CONST_BLDOU a, CONST_BLINT lda, BLDOU x, CONST_BLINT incx);
void BLAS_daxpy(CONST_BLINT n, CONST_BLDOU a, CONST_BLDOU x, CONST_BLINT incx,
BLDOU y, CONST_BLINT incy);
void BLAS_dcopy(CONST_BLINT n, CONST_BLDOU x, CONST_BLINT incx,
BLDOU y, CONST_BLINT incy);
void BLAS_zaxpy(CONST_BLINT n, CONST_BLDOU a, CONST_BLDOU x, CONST_BLINT incx,
BLDOU y, CONST_BLINT incy);
void BLAS_dscal(CONST_BLINT n, CONST_BLDOU a, BLDOU x, CONST_BLINT incx);
void BLAS_dtrsm(BLCHAR side, BLCHAR uplo, BLCHAR transa, BLCHAR diag, CONST_BLINT m,
CONST_BLINT n, CONST_BLDOU alpha, CONST_BLDOU a, CONST_BLINT lda,
BLDOU b, CONST_BLINT ldb);
double BLAS_ddot(CONST_BLINT n, CONST_BLDOU x, CONST_BLINT incx, CONST_BLDOU y,
CONST_BLINT incy);
};
#endif /* CPPBLAS_H */
// Local Variables:
// mode:C++
// End:

View File

@ -0,0 +1,82 @@
/* $Header: /var/lib/cvs/dynare_cpp/sylv/cc/cpplapack.h,v 1.3 2004/11/24 20:43:10 kamenik Exp $ */
/* Tag $Name: $ */
#ifndef CPPLAPACK_H
#define CPPLAPACK_H
#if defined(MATLAB) && !defined(__linux__)
#define LAPACK_dgetrs dgetrs
#define LAPACK_dgetrf dgetrf
#define LAPACK_dgees dgees
#define LAPACK_dgecon dgecon
#define LAPACK_dtrexc dtrexc
#define LAPACK_dtrsyl dtrsyl
#define LAPACK_dpotrf dpotrf
#define LAPACK_dgges dgges
#define LAPACK_dsyev dsyev
#define LAPACK_dsyevr dsyevr
#else /* MATLAB */
#define LAPACK_dgetrs dgetrs_
#define LAPACK_dgetrf dgetrf_
#define LAPACK_dgees dgees_
#define LAPACK_dgecon dgecon_
#define LAPACK_dtrexc dtrexc_
#define LAPACK_dtrsyl dtrsyl_
#define LAPACK_dpotrf dpotrf_
#define LAPACK_dgges dgges_
#define LAPACK_dsyev dsyev_
#define LAPACK_dsyevr dsyevr_
#endif /* MATLAB */
#define LACHAR const char*
#define CONST_LAINT const int*
#define LAINT int*
#define CONST_LADOU const double*
#define LADOU double*
typedef int (*DGGESCRIT)(const double*, const double*, const double*);
extern "C" {
void LAPACK_dgetrs(LACHAR trans, CONST_LAINT n, CONST_LAINT nrhs,
CONST_LADOU a, CONST_LAINT lda, CONST_LAINT ipiv,
LADOU b, CONST_LAINT ldb, LAINT info);
void LAPACK_dgetrf(CONST_LAINT m, CONST_LAINT n, LADOU a,
CONST_LAINT lda, LAINT ipiv, LAINT info);
void LAPACK_dgees(LACHAR jobvs, LACHAR sort, const void* select,
CONST_LAINT n, LADOU a, CONST_LAINT lda, LAINT sdim,
LADOU wr, LADOU wi, LADOU vs, CONST_LAINT ldvs,
LADOU work, CONST_LAINT lwork, const void* bwork, LAINT info);
void LAPACK_dgecon(LACHAR norm, CONST_LAINT n, CONST_LADOU a, CONST_LAINT lda,
CONST_LADOU anorm, LADOU rnorm, LADOU work, LAINT iwork,
LAINT info);
void LAPACK_dtrexc(LACHAR compq, CONST_LAINT n, LADOU t, CONST_LAINT ldt,
LADOU q, CONST_LAINT ldq, LAINT ifst, LAINT ilst, LADOU work,
LAINT info);
void LAPACK_dtrsyl(LACHAR trana, LACHAR tranb, CONST_LAINT isgn, CONST_LAINT m,
CONST_LAINT n, CONST_LADOU a, CONST_LAINT lda, CONST_LADOU b,
CONST_LAINT ldb, LADOU c, CONST_LAINT ldc, LADOU scale,
LAINT info);
void LAPACK_dpotrf(LACHAR uplo, CONST_LAINT n, LADOU a, CONST_LAINT lda,
LAINT info);
void LAPACK_dgges(LACHAR jobvsl, LACHAR jobvsr, LACHAR sort, DGGESCRIT delztg,
CONST_LAINT n, LADOU a, CONST_LAINT lda, LADOU b, CONST_LAINT ldb,
LAINT sdim, LADOU alphar, LADOU alphai, LADOU beta,
LADOU vsl, CONST_LAINT ldvsl, LADOU vsr, CONST_LAINT ldvsr,
LADOU work, CONST_LAINT lwork, LAINT bwork, LAINT info);
void LAPACK_dsyev(LACHAR jobz, LACHAR uplo, CONST_LAINT n, LADOU a, CONST_LAINT lda,
LADOU w, LADOU work, CONST_LAINT lwork, LAINT info);
void LAPACK_dsyevr(LACHAR jobz, LACHAR range, LACHAR uplo, CONST_LAINT n, LADOU a,
CONST_LAINT lda, LADOU lv, LADOU vu, CONST_LAINT il, CONST_LAINT iu,
CONST_LADOU abstol, LAINT m, LADOU w, LADOU z, CONST_LAINT ldz,
LAINT isuppz, LADOU work, CONST_LAINT lwork, LAINT iwork, CONST_LAINT liwork,
LAINT info);
};
#endif /* CPPLAPACK_H */
// Local Variables:
// mode:C++
// End:

View File

@ -0,0 +1,140 @@
<HTML>
<!-- $Header: /var/lib/cvs/dynare_cpp/sylv/change_log.html,v 1.1.1.1 2004/06/04 13:00:05 kamenik Exp $ -->
<!-- Tag $Name: $ -->
<TITLE>
Sylvester Solver Change Log
</TITLE>
<BODY>
<TABLE CELLSPACING=2 ALIGN="CENTER" BORDER=1>
<TR>
<TD BGCOLOR="#d0d0d0" WIDTH="85"> Tag </TD>
<TD BGCOLOR="#d0d0d0" WIDTH="80"> Date </TD>
<TD BGCOLOR="#d0d0d0" WIDTH="600"> Description/Changes</TD>
</TR>
<TR>
<TD></TD>
<TD>2003/09/10</TD>
<TD>Initial version solving triangular system put to repository</TD>
</TR>
<TR>
<TD></TD>
<TD></TD>
<TD>Implemented solution of general case.</TD>
</TR>
<TR>
<TD></TD>
<TD></TD>
<TD>Implemented a memory pool (Paris).</TD>
</TR>
<TR>
<TD></TD>
<TD></TD>
<TD>Implemented MEX interface to the routine (Paris).</TD>
</TR>
<TR>
<TD></TD>
<TD></TD>
<TD>Implemented QuasiTriangularZero (Paris) (not fully used yet).</TD>
</TR>
<TR>
<TD>rel-1</TD>
<TD>2003/10-02</TD>
<TD>Version sent to Michel.</TD>
</TR>
<TR>
<TD></TD>
<TD></TD>
<TD>Inheritance streamlined, QuasiTriangular inherits from GeneralMatrix.</TD>
</TR>
<TR>
<TD></TD>
<TD></TD>
<TD>Implemented block diagonalization algorithm.</TD>
</TR>
<TR>
<TD></TD>
<TD></TD>
<TD>Solution routines rewritten so that the output rewrites input,
considerable memory improvement.</TD>
</TR>
<TR>
<TD></TD>
<TD></TD>
<TD>MEX interface now links with LAPACK library from Matlab.</TD>
</TR>
<TR>
<TD></TD>
<TD></TD>
<TD>Added a hack to MEX library loading in order to avoid Matlab crash in Wins.</TD>
</TR>
<TR>
<TD>rel-2</TD>
<TD>2003/10/15</TD>
<TD>Version sent to Michel.</TD>
</TR>
<TR>
<TD></TD>
<TD></TD>
<TD>KronUtils now rewrite input by output using less memory.</TD>
</TR>
<TR>
<TD></TD>
<TD></TD>
<TD>Added iterative solution algorithm (doubling).</TD>
</TR>
<TR>
<TD></TD>
<TD></TD>
<TD>Introduced abstraction for set of parameters (SylvParams).</TD>
</TR>
<TR>
<TD></TD>
<TD></TD>
<TD>Algorithm enabled to solve problems with singular C.</TD>
</TR>
<TR>
<TD></TD>
<TD></TD>
<TD>Implemented a class chooser chossing between QuasiTriangularZero,
and QuasiTriangular (padded with zero) depending on size of the
problem. Full use of QuasiTriangularZero.</TD>
</TR>
<TR>
<TD></TD>
<TD></TD>
<TD>Reimplemented QuasiTriangular::solve, offdiagonal elements are
eleiminated by gauss with partial pivoting, not by transformation of
complex eigenvalues. More stable for ill conditioned eigenvalues.</TD>
</TR>
<TR>
<TD></TD>
<TD></TD>
<TD>Reimplemented calculation of eliminating vectors, much more
numerically stable now.</TD>
</TR>
<TR>
<TD></TD>
<TD></TD>
<TD>Implemented algorithm for ordering of eigenvalues (not used now,
no numerical improvements).</TD>
</TR>
<TR>
<TD>rel-3</TD>
<TD>2003/12/4</TD>
<TD>Version sent to Michel.</TD>
</TR>
<TR>
<TD></TD>
<TD></TD>
<TD>GeneralMatrix separated for use outside, in sylv module we use
its subclass SylvMatrix. Implemented ConstGeneralMatrix (useful outside).
</TD>
</TR>
<TR>
<TD>rel-4</TD>
<TD>2004/6/4</TD>
<TD>Version, which was moved to pythie.cepremap.cnrs.fr repository.</TD>
</TR>
</TABLE>
</BODY>
</HTML>

View File

@ -0,0 +1,35 @@
# $Header: /var/lib/cvs/dynare_cpp/sylv/matlab/Makefile,v 1.1.1.1 2004/06/04 13:01:13 kamenik Exp $
# Tag $Name: $
# set directory to sylvester code
sylv=../cc
LD_LIBS := -llapack -lcblas -lblas -latlas
CC_FLAGS := -Wall -I../cc
CC_DEFS := -I/usr/local/matlab73/extern/include -DMATLAB #-DUSE_MEMORY_POOL
MEX := mex.bat
objects := $(patsubst %.cpp,%.o,$(wildcard ../cc/*.cpp))
headers := $(wildcard ../cc/*.h)
# set mex file suffix
mex_suffix=dll
ifeq ($(OSTYPE),linux-gnu)
mex_suffix=mexglx
endif
aa_gensylv.$(mex_suffix): gensylv.cpp ../cc/sylvester.a
$(MEX) -I../cc -DMATLAB gensylv.cpp ../cc/sylvester.a c:/matlab6p5/extern/lib/win32/microsoft/msvc60/libmwlapack.lib
mv gensylv.$(mex_suffix) aa_gensylv.$(mex_suffix)
../cc/sylvester.a : $(objects)
make -C ../cc sylvester.a
../cc/%.o: ../cc/%.cpp $(headers)
make EXTERN_DEFS="$(CC_DEFS)" -C ../cc $*.o
clear:
make -C ../cc clear
rm -f *.dll
rm -f *.mexglx

View File

@ -0,0 +1,3 @@
/* this is only dummy header file to be able to loadlibrary to MATLAB */
void mexFunction(int nhls, mxArray* plhs[],
int nhrs, const mxArray* prhs[]);

View File

@ -0,0 +1,100 @@
/* $Header: /var/lib/cvs/dynare_cpp/sylv/matlab/gensylv.cpp,v 1.1.1.1 2004/06/04 13:01:13 kamenik Exp $ */
/* Tag $Name: $ */
#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)
{
try {
GeneralSylvester s(order, n, m, zero_cols, A, B, C, X, false);
s.solve();
} catch (const SylvException& e) {
char mes[1000];
e.printMessage(mes, 999);
mexErrMsgTxt(mes);
}
}
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)
{
try {
GeneralSylvester s(order, n, m, zero_cols, A, B, C, X, true);
s.solve();
s.check(D);
p = s.getParams().createStructArray();
} catch (const SylvException& e) {
char mes[1000];
e.printMessage(mes, 999);
mexErrMsgTxt(mes);
}
}
void checkDimensions(const mwSize* const Adims, const mwSize* const Bdims,
const mwSize* const Cdims, const mwSize* const Ddims,
int order)
{
if (Adims[0] != Adims[1])
mexErrMsgTxt("Matrix A must be a square matrix.");
if (Adims[0] != Bdims[0])
mexErrMsgTxt("Matrix A and matrix B must have the same number of rows.");
if (Adims[0] != Ddims[0])
mexErrMsgTxt("Matrix A and matrix B must have the same number of rows.");
if (Cdims[0] != Cdims[1])
mexErrMsgTxt("Matrix C must be square.");
if (Bdims[0] < Bdims[1])
mexErrMsgTxt("Matrix B must not have more columns than rows.");
if (Ddims[1] != power(Cdims[0], order))
mexErrMsgTxt("Matrix D has wrong number of columns.");
}
extern "C" {
void mexFunction(int nhls, mxArray* plhs[],
int nhrs, const mxArray* prhs[])
{
if (nhrs != 5)
mexErrMsgTxt("Must have exactly 5 input args.");
if (nhls !=1 && nhls != 2)
mexErrMsgTxt("Must have 1 or 2 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);
checkDimensions(Adims, Bdims, Cdims, Ddims, order);
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)
if (nhls == 1) {
gen_sylv_solve(order, n, m, zero_cols,
mxGetPr(A), mxGetPr(B), mxGetPr(C),
mxGetPr(X));
} else if (nhls == 2) {
gen_sylv_solve_and_check(order, n, m, zero_cols,
mxGetPr(A), mxGetPr(B), mxGetPr(C),
mxGetPr(D), mxGetPr(X), plhs[1]);
}
plhs[0] = X;
}
};

View File

@ -0,0 +1,74 @@
%
% GENSYLV solves the following matrix equation:
% A*X + [0 B]*X*kron(C,..,C) = D,
% where
% A ...... regular (n,n) matrix,
% [0 B] .. (n,n) matrix with a few first
% columns equal to zeros
% B ...... rectangular (n, nz) matrix with nz<=n
% C ...... regular (m,m) matrix, whose spectrum is
% within (-1, 1)
% kron(C,..,C)
% ...... Kronecker power of C of order 'order'
% D ..... rectangular (n, m^order) matrix.
%
% X = gensylv(order, A, B, C, D)
% returns X as the solution, doesn't perform any checks
%
% [X, par] = gensylv(order, A, B, C, D)
% solves the system, and performs checks. 'par' is struct
% containing information about solution and error norms
% returned by the check. This is a list of the struct
% members, some of them may be missing in actual returned
% value:
% method = method used for solution recursive/iterative
% convergence_tol = convergence tolerance for iter. method
% max_num_iter = max number of steps for iter. method
% bs_norm = Bavely Stewart log10 norm for diagonalization
% converged = convergence status for iterative method
% iter_last_norm = residual norm of the last step of iterations
% num_iter = number of iterations performed
% f_err1 = norm 1 of abs. error C-V*F*inv(V)
% f_errI = norm Inf of abs. error C-V*F*inv(V)
% viv_err1 = norm 1 of abs. error I-V*inv(V)
% viv_errI = norm Inf of abs. error I-V*inv(V)
% ivv_err1 = norm 1 of abs. error I-inv(V)*V
% ivv_errI = norm Inf of abs. error I-inv(V)*V
% f_blocks = number of diagonal blocks of F
% f_largest = size of largest diagonal block in F
% f_zeros = number of off diagonal zeros in F
% f_offdiag = number of all offdiagonal elements in F
% rcondA1 = reciprocal cond 1 number of A
% rcondAI = reciprocal cond Inf number of A
% eig_min = minimum eigenvalue of vectorized system
% mat_err1 = rel. matrix 1 norm of A*X-[0 B]*X*kron(C,..,C)-D
% mat_errI = rel. matrix Inf norm of --"--
% mat_errF = rel. matrix Frobenius norm of --"--
% vec_err1 = rel. vector 1 norm of --"--
% vec_errI = rel. vector Inf norm of --"--
% cpu_time = CPU time needed for solution in CPU seconds
%
% $Header: /var/lib/cvs/dynare_cpp/sylv/matlab/gensylv.m,v 1.1.1.1 2004/06/04 13:01:13 kamenik Exp $
% Tag $Name: $
function [X, varargout] = gensylv(order, A, B, C, D)
% in Windows, ensure that aa_gensylv.dll is loaded, this prevents
% clearing the function and a successive Matlab crash
if strcmp('PCWIN', computer)
if ~ libisloaded('aa_gensylv')
loadlibrary('aa_gensylv', 'dummy');
end
end
% launch aa_gensylv
if nargout == 1
X = aa_gensylv(order, A, B, C, D);
elseif nargout == 2
[X, par] = aa_gensylv(order, A, B, C, D);
varargout(1) = {par};
else
error('Must have 1 or 2 output arguments.');
end

View File

@ -0,0 +1,59 @@
@echo off
rem $Header: /var/lib/cvs/dynare_cpp/sylv/matlab/mexopts.bat,v 1.1.1.1 2004/06/04 13:01:13 kamenik Exp $
rem Tag $Name: $
rem c:\ondra\wk\sylv\matlab\mexopts.bat
rem Generated by gnumex.m script in c:\fs\gnumex
rem gnumex version: 1.08
rem Compile and link options used for building MEX etc files with
rem the Mingw/Cygwin tools. Options here are:
rem Cygwin (cygwin*.dll) linking
rem Mex file creation
rem Standard (safe) linking to temporary libraries
rem Language C / C++
rem Matlab version 6.5
rem
set MATLAB=C:\MATLAB~2
set GM_PERLPATH=C:\MATLAB~2\sys\perl\win32\bin\perl.exe
set GM_UTIL_PATH=c:\fs\gnumex
set PATH=C:\fs\cygwin\bin;%PATH%
rem
rem Added libraries for linking
set GM_ADD_LIBS=
rem
rem Type of file to compile (mex or engine)
set GM_MEXTYPE=mex
rem
rem Language for compilation
set GM_MEXLANG=c
rem
rem def files to be converted to libs
set GM_DEFS2LINK=libmx.def;libmex.def;libmat.def;_libmatlbmx.def;
rem
rem dlltool command line
set GM_DLLTOOL=c:\fs\gnumex\mexdlltool -E --as C:\fs\cygwin\bin\as.exe
rem
rem compiler options; add compiler flags to compflags as desired
set NAME_OBJECT=-o
set COMPILER=gcc
set COMPFLAGS=-c -DMATLAB_MEX_FILE
set OPTIMFLAGS=-O3 -mcpu=pentium -malign-double
set DEBUGFLAGS=-g
set CPPCOMPFLAGS=%COMPFLAGS% -x c++
set CPPOPTIMFLAGS=%OPTIMFLAGS%
set CPPDEBUGFLAGS=%DEBUGFLAGS%
rem
rem NB Library creation commands occur in linker scripts
rem
rem Linker parameters
set LINKER=%GM_PERLPATH% %GM_UTIL_PATH%\linkmex.pl
set LINKFLAGS=
set CPPLINKFLAGS= --driver-name c++
set LINKOPTIMFLAGS=-s
set LINKDEBUGFLAGS=-g
set LINK_FILE=
set LINK_LIB=
set NAME_OUTPUT=-o %OUTDIR%%MEX_NAME%.dll
rem
rem Resource compiler parameters
set RC_COMPILER=%GM_PERLPATH% %GM_UTIL_PATH%\rccompile.pl --unix -o %OUTDIR%mexversion.res
set RC_LINKER=

View File

@ -0,0 +1,541 @@
\input amstex
\documentstyle{amsppt}
\def\vec{\mathop{\hbox{vec}}}
\def\otimesi{\mathop{\overset{\ssize i}\to{\otimes}}}
\def\iF{\,^i\!F}
\def\imF{\,^{i-1}\!F}
\def\solvi{\bold{solv1}}
\def\solvii{\bold{solv2}}
\def\solviip{\bold{solv2p}}
\topmatter
\title Solution of Specialized Sylvester Equation\endtitle
\author Ondra Kamenik\endauthor
\email ondrej.kamenik@cnb.cz\endemail
\endtopmatter
\document
Given the following matrix equation
$$AX+BX\left(\otimesi C\right)=D,$$ where $A$ is regular $n\times n$
matrix, $X$ is $n\times m^i$ matrix of unknowns, $B$ is singular
$n\times n$ matrix, $C$ is $m\times m$ regular matrix with
$|\beta(C)|<1$ (i.e. modulus of largest eigenvalue is less than one),
$i$ is an order of Kronecker product, and finally $D$ is $n\times m^i$
matrix.
First we multiply the equation from the left by $A^{-1}$ to obtain:
$$X+A^{-1}BX\left(\otimesi C\right)=A^{-1}D$$
Then we find real Schur decomposition $K=UA^{-1}BU^T$, and
$F=VCV^T$. The equation can be written as
$$UX\left(\otimesi V^T\right) +
KUX\left(\otimesi V^T\right)\left(\otimesi F\right) =
UA^{-1}D\left(\otimesi V^T\right)$$
This can be rewritten as
$$Y + KY\left(\otimesi F\right)=\widehat{D},$$
and vectorized
$$\left(I+\otimesi F^T\otimes K\right)\vec(Y)=\vec(\widehat{D})$$
Let $\iF$ denote $\otimesi F^T$ for the rest of the text.
\proclaim{Lemma 1}
For any $n\times n$ matrix $A$ and $\beta_1\beta_2>0$, if there is
exactly one solution of
$$\left(I_2\otimes I_n +
\pmatrix\alpha&\beta_1\cr-\beta_2&\alpha\endpmatrix
\otimes A\right)\pmatrix x_1\cr x_2\endpmatrix =
\pmatrix d_1\cr d_2\endpmatrix,$$
then it can be obtained as solution of
$$\align
\left(I_n + 2\alpha A+(\alpha^2+\beta^2)A^2\right)x_1 & =
\widehat{d_1}\\
\left(I_n + 2\alpha A+(\alpha^2+\beta^2)A^2\right)x_2 & =
\widehat{d_2}
\endalign$$
where $\beta=\sqrt{\beta1\beta2}$, and
$$
\pmatrix \widehat{d_1}\cr\widehat{d_2}\endpmatrix =
\left(I_2\otimes I_n +
\pmatrix\alpha&-\beta_1\cr\beta_2&\alpha\endpmatrix
\otimes A\right)\pmatrix d_1\cr d_2\endpmatrix$$
\endproclaim
\demo{Proof} Since
$$
\pmatrix \alpha&\beta_1\cr-\beta_2&\alpha\endpmatrix
\pmatrix \alpha&-\beta_1\cr\beta_2&\alpha\endpmatrix
=
\pmatrix \alpha&-\beta_1\cr\beta_2&\alpha\endpmatrix
\pmatrix \alpha&\beta_1\cr-\beta_2&\alpha\endpmatrix
=
\pmatrix \alpha^2+\beta^2&0\cr 0&\alpha^2+\beta^2\endpmatrix,
$$
it is easy to see that if the equation is multiplied by
$$I_2\otimes I_n +
\pmatrix\alpha&-\beta_1\cr\beta_2&\alpha\endpmatrix
\otimes A$$
we obtain the result. We only need to prove that the matrix is
regular. But this is clear because matrix
$$\pmatrix \alpha&-\beta_1\cr\beta_2&\alpha\endpmatrix$$
collapses an eigenvalue of $A$ to $-1$ iff the matrix
$$\pmatrix \alpha&\beta_1\cr-\beta_2&\alpha\endpmatrix$$
does.\qed
\enddemo
\proclaim{Lemma 2}
For any $n\times n$ matrix $A$ and $\delta_1\delta_2>0$, if there is
exactly one solution of
$$\left(I_2\otimes I_n +
2\alpha\pmatrix\gamma&\delta_1\cr-\delta_2&\gamma\endpmatrix\otimes A
+(\alpha^2+\beta^2)
\pmatrix\gamma&\delta_1\cr-\delta_2&\gamma\endpmatrix^2\otimes A^2\right)
\pmatrix x_1\cr x_2\endpmatrix=
\pmatrix d_1\cr d_2\endpmatrix
$$
it can be obtained as
$$
\align
\left(I_n+2a_1A+(a_1^2+b_1^2)A^2\right)\left(I_n+2a_2A+(a_2^2+b_2^2)A^2\right)
x_1 & =\widehat{d_1}\\
\left(I_n+2a_1A+(a_1^2+b_1^2)A^2\right)\left(I_n+2a_2A+(a_2^2+b_2^2)A^2\right)
x_2 & =\widehat{d_2}
\endalign$$
where
$$
\pmatrix \widehat{d_1}\cr\widehat{d_2}\endpmatrix =
\left(I_2\otimes I_n +
2\alpha\pmatrix\gamma&-\delta_1\cr\delta_2&\gamma\endpmatrix\otimes A
+(\alpha^2+\beta^2)
\pmatrix\gamma&-\delta_1\cr\delta_2&\gamma\endpmatrix^2\otimes A^2\right)
\pmatrix d_1\cr d_2\endpmatrix
$$
and
$$
\align
a_1 & = \alpha\gamma - \beta\delta\\
b_1 & = \alpha\delta + \gamma\beta\\
a_2 & = \alpha\gamma + \beta\delta\\
b_2 & = \alpha\delta - \gamma\beta\\
\delta & = \sqrt{\delta_1\delta_2}
\endalign$$
\endproclaim
\demo{Proof}
The matrix can be written as
$$\left(I_2\otimes I_n+(\alpha+\roman i\beta)
\pmatrix\gamma&\delta_1\cr-\delta_2&\gamma\endpmatrix\otimes A\right)
\left(I_2\otimes I_n +(\alpha-\roman i\beta)
\pmatrix\gamma&\delta_1\cr-\delta_2&\gamma\endpmatrix\otimes A\right).
$$
Note that the both matrices are regular since their product is
regular. For the same reason as in the previous proof, the following
matrix is also regular
$$\left(I_2\otimes I_n+(\alpha+\roman i\beta)
\pmatrix\gamma&-\delta_1\cr\delta_2&\gamma\endpmatrix\otimes A\right)
\left(I_2\otimes I_n +(\alpha-\roman i\beta)
\pmatrix\gamma&-\delta_1\cr\delta_2&\gamma\endpmatrix\otimes A\right),
$$
and we may multiply the equation by this matrix obtaining
$\widehat{d_1}$ and $\widehat{d_2}$. Note that the four matrices
commute, that is why we can write the whole product as
$$
\align
\left(I_2\otimes I_n + (\alpha+\roman i\beta)
\pmatrix\gamma&\delta_1\cr-\delta_2&\gamma\endpmatrix\otimes A\right)\cdot
\left(I_2\otimes I_n + (\alpha+\roman i\beta)
\pmatrix\gamma&-\delta_1\cr\delta_2&\gamma\endpmatrix\otimes A\right)&\cdot\\
\left(I_2\otimes I_n + (\alpha-\roman i\beta)
\pmatrix\gamma&\delta_1\cr-\delta_2&\gamma\endpmatrix\otimes A\right)\cdot
\left(I_2\otimes I_n + (\alpha-\roman i\beta)
\pmatrix\gamma&-\delta_1\cr\delta_2&\gamma\endpmatrix\otimes A\right)&=\\
\left(I_2\otimes I_n + 2(\alpha + \roman i\beta)
\pmatrix\gamma&0\cr 0&\gamma\endpmatrix\otimes A +
(\alpha + \roman i\beta)^2
\pmatrix\gamma^2+\delta^2&0\cr 0&\gamma^2+\delta^2\endpmatrix\otimes A^2
\right)&\cdot\\
\left(I_2\otimes I_n + 2(\alpha - \roman i\beta)
\pmatrix\gamma&0\cr 0&\gamma\endpmatrix\otimes A +
(\alpha - \roman i\beta)^2
\pmatrix\gamma^2+\delta^2&0\cr 0&\gamma^2+\delta^2\endpmatrix\otimes A^2
\right)&
\endalign
$$
The product is a diagonal consiting of two $n\times n$ blocks, which are the
same. The block can be rewritten as product:
$$
\align
(I_n+(\alpha+\roman i\beta)(\gamma+\roman i\delta)A)\cdot
(I_n+(\alpha+\roman i\beta)(\gamma-\roman i\delta)A)&\cdot\\
(I_n+(\alpha-\roman i\beta)(\gamma+\roman i\delta)A)\cdot
(I_n+(\alpha-\roman i\beta)(\gamma-\roman i\delta)A)&
\endalign
$$
and after reordering
$$
\align
(I_n+(\alpha+\roman i\beta)(\gamma+\roman i\delta)A)\cdot
(I_n+(\alpha-\roman i\beta)(\gamma-\roman i\delta)A)&\cdot\\
(I_n+(\alpha+\roman i\beta)(\gamma-\roman i\delta)A)\cdot
(I_n+(\alpha-\roman i\beta)(\gamma+\roman i\delta)A)&=\\
(I_n+2(\alpha\gamma-\beta\delta)A+
(\alpha^2+\beta^2)(\gamma^2+\delta^2)A^2)&\cdot\\
(I_n+2(\alpha\gamma+\beta\delta)A+
(\alpha^2+\beta^2)(\gamma^2+\delta^2)A^2)&
\endalign
$$
Now it suffices to compare $a_1=\alpha\gamma-\beta\delta$ and verify
that
$$
\align
b_1^2 & = (\alpha^2+\beta^2)(\gamma^2+\delta^2)-a_1^2 =\cr
& = \alpha^2\gamma^2+\beta^2\gamma^2+\alpha^2\beta^2+\beta^2\delta^2-
(\alpha\gamma)^2+2\alpha\beta\gamma\delta-(\beta\delta)^2=\cr
& = (\beta\gamma)^2 + (\alpha\beta)^2 + 2\alpha\beta\gamma\delta=\cr
& = (\beta\gamma +\alpha\beta)^2
\endalign
$$
For $b_2$ it is done in the same way.
\qed
\enddemo
\head The Algorithm\endhead
Below we define three functions of which
$\vec(Y)=\solvi(1,\vec(\widehat{D}),i)$ provides the solution $Y$. $X$
is then obtained as $X=U^TY\left(\otimesi V\right)$.
\subhead Synopsis\endsubhead
$F^T$ is $m\times m$ lower quasi-triangular matrix. Let $m_r$ be a
number of real eigenvalues, $m_c$ number of complex pairs. Thus
$m=m_r+2m_c$. Let $F_j$ denote
$j$-th diagonal block of $F^T$ ($1\times 1$ or $2\times 2$ matrix) for
$j=1,\ldots, m_r+m_c$. For a fixed $j$, let $\bar j$ denote index of the
first column of $F_j$ in $F^T$. Whenever we write something like
$(I_{m^i}\otimes I_n+r\iF\otimes K)x = d$, $x$ and $d$ denote column
vectors of appropriate dimensions, and $x_{\bar j}$ is $\bar j$-th
partition of $x$, and $x_j=(x_{\bar j}\quad x_{\bar j+1})^T$ if $j$-th
eigenvalue is complex, and $x_j=x_{\bar j}$ if $j$-th eigenvalue is real.
\subhead Function $\solvi$\endsubhead
The function $x=\solvi(r,d,i)$ solves equation
$$\left(I_{m^i}\otimes I_n+r\iF\otimes K\right)x = d.$$
The function proceedes as follows:
If $i=0$, the equation is solved directly, $K$ is upper
quasi-triangular matrix, so this is easy.
If $i>0$, then we go through diagonal blocks $F_j$ for
$j=1,\ldots, m_r+m_c$ and perform:
\roster
\item if $F_j=(f_{\bar j\bar j}) = (f)$, then we return
$x_j=\solvi(rf,d_{\bar j}, i-1)$. Then precalculate $y=d_j-x_j$, and
eliminate guys below $F_j$. This is, for each $k=\bar j+1,\ldots, m$, we
put
$$d_k = d_k-rf_{\bar jk}\left(\imF\otimes K\right)x_{\bar j}=
d_k - \frac{f_{\bar jk}}{f}y$$
\item if $F_j=\pmatrix\alpha&\beta_1\cr -\beta_2&\alpha\endpmatrix$,
we return $x_j=\solvii(r\alpha, r\beta_1, r\beta_2, d_j, i-1)$. Then
we precalculate
$$y=\left(\pmatrix\alpha&-\beta_1\cr \beta_2&\alpha\endpmatrix
\otimes I_{m^{i-1}}\otimes I_n\right)
\pmatrix d_{\bar j} - x_{\bar j}\cr
d_{\bar j+1} - x_{\bar j+1}
\endpmatrix$$
and eliminate guys below $F_j$. This is, for each $k=\bar j+2,\ldots, n$
we put
$$
\align
d_k &= d_k - r(f_{{\bar j}k}\quad f_{{\bar j}+1 k})
\otimes\left(\imF\otimes K\right)x_j\\
&= d_k - \frac{1}{\alpha^2+\beta_1\beta_2}
\left((f_{{\bar j}k}\quad f_{{\bar j}+1 k})
\otimes I_{m^{i-1}}\otimes I_n\right)y
\endalign
$$
\endroster
\subhead Function $\solvii$\endsubhead
The function $x=\solvii(\alpha, \beta_1, \beta_2, d, i)$ solves
equation
$$
\left(I_2\otimes I_{m^i}\otimes I_n +
\pmatrix\alpha&\beta_1\cr-\beta_2&\alpha\endpmatrix
\otimes\iF\otimes K\right)x=d
$$
According to {\bf Lemma 1} the function returns
$$
x=\pmatrix\solviip(\alpha,\beta_1\beta_2,\widehat{d_1},i)\cr
\solviip(\alpha,\beta_1\beta_2,\widehat{d_2},i)\endpmatrix,
$$
where $\widehat{d_1}$, and $\widehat{d_2}$ are partitions of
$\widehat{d}$ from the lemma.
\subhead Function $\solviip$\endsubhead
The function $x=\solviip(\alpha,\beta^2,d,i)$ solves equation
$$
\left(I_{m^i}\otimes I_n + 2\alpha\iF\otimes K +
(\alpha^2+\beta^2)\iF^2\otimes K^2\right)x = d
$$
The function proceedes as follows:
If $i=0$, the matrix $I_n+2\alpha K+(\alpha^2+\beta^2)K^2$ is
calculated and the solution is obtained directly.
Now note that diagonal blocks of $F^{2T}$ are of the form $F_j^2$,
since if the $F^T$ is block partitioned according to diagonal blocks,
then it is lower triangular.
If $i>0$, then we go through diagonal blocks $F_j$ for $j=1,\ldots, m_r+m_c$
and perform:
\roster
\item if $F_j=(f_{\bar j\bar j})=(f)$ then $j$-th diagonal block of
$$
I_{m^i}\otimes I_n + 2\alpha\iF\otimes K +
(\alpha^2+\beta^2)\iF^2\otimes K^2
$$
takes the form
$$
I_{m^{i-1}}\otimes I_n +2\alpha f\imF\otimes K +
(\alpha^2+\beta^2)f^2\imF^2\otimes K^2
$$
and we can put $x_j = \solviip(f\alpha,f^2\beta^2,d_j,i-1)$.
Then we need to eliminate guys below $F_j$. Note that $|f^2|<|f|$,
therefore we precalculate $y_2=(\alpha^2+\beta^2)f^2(\imF^2\otimes K^2)x_j$,
and then precalculate
$$y_1 = 2\alpha f(\imF\otimes K)x_j = d_j-x_j-y_2.$$
Let $g_{pq}$ denote element of $F^{2T}$ at position $(q,p)$.
The elimination is done by going through $k=\bar j+1,\ldots, m$ and
putting
$$
\align
d_k &= d_k - \left(2\alpha f_{\bar j k}\imF\otimes K +
(\alpha^2+\beta^2)g_{\bar j k}\imF^2\otimes K^2\right)x_j\\
&= d_k - \frac{f_{\bar j k}}{f}y_1 -
\frac{g_{\bar j k}}{f^2}y_2
\endalign
$$
\item if $F_j=\pmatrix\gamma&\delta_1\cr -\delta_2&\gamma\endpmatrix$,
then $j$-th diagonal block of
$$
I_{m^i}\otimes I_n + 2\alpha\iF\otimes K +
(\alpha^2+\beta^2)\iF^2\otimes K^2
$$
takes the form
$$
I_{m^{i-1}}\otimes I_n +2\alpha
\pmatrix\gamma&\delta_1\cr -\delta_2&\gamma\endpmatrix\imF\otimes K
+(\alpha^2+\beta^2)
\pmatrix\gamma&\delta_1\cr -\delta_2&\gamma\endpmatrix^2\imF^2\otimes K^2
$$
According to {\bf Lemma 2}, we need to calculate
$\widehat{d}_{\bar j}$, and $\widehat{d}_{\bar j+1}$, and $a_1$,
$b_1$, $a_2$, $b_2$. Then we obtain
$$
\align
x_{\bar j}&=
\solviip(a_1,b_1^2,\solviip(a_2,b_2^2,\widehat{d}_{\bar j},i-1),i-1)\\
x_{\bar j+1}&=
\solviip(a_1,b_1^2,\solviip(a_2,b_2^2,\widehat{d}_{\bar j+1},i-1),i-1)
\endalign
$$
Now we need to eliminate guys below $F_j$. Since $\Vert F^2_j\Vert <
\Vert F_j\Vert$, we precalculate
$$
\align
y_2&=(\alpha^2+\beta^2)(\gamma^2+\delta^2)
\left(I_2\otimes\imF^2\otimes K^2\right)x_j\\
y_1&=2\alpha(\gamma^2+\delta^2)\left(I_2\otimes\imF\otimes
K\right)x_j\\
&=(\gamma^2+\delta^2)
\left(F_j^{-1}
\otimes I_{m^{i-1}n}\right)
\left(d_j-x_j-\frac{1}{(\gamma^2+\delta^2)}
\left(
F_j^2
\otimes I_{m^{i-1}n}\right)y_2\right)\\
&=\left(\pmatrix\gamma&-\delta_1\cr\delta_2&\gamma\endpmatrix
\otimes I_{m^{i-1}n}\right)(d_j-x_j)
-\left(\pmatrix\gamma&\delta_1\cr-\delta_2&\gamma\endpmatrix
\otimes I_{m^{i-1}n}\right)y_2
\endalign
$$
Then we go through all $k=\bar j+2,\ldots, m$. For clearer formulas, let
$\bold f_k$ denote pair of $F^T$ elements in $k$-th line below $F_j$,
this is $\bold f_k=(f_{\bar jk}\quad f_{\bar j+1k})$. And let $\bold g_k$
denote the same for $F^{2T}$, this is $\bold g_k=(g_{\bar jk}\quad
g_{\bar j+1k})$. For each $k$ we put
$$
\align
d_k &= d_k - \left(2\alpha\bold f_k\otimes
\imF\otimes K +
(\alpha^2+\beta^2)\bold g_k\otimes
\imF^2\otimes K^2\right)x_j\\
&= d_k - \frac{1}{\gamma^2+\delta^2}
\left(\bold f_k\otimes
I_{m^{i-1}n}\right)y_1
- \frac{1}{\gamma^2+\delta^2}
\left(\bold g_k\otimes
I_{m^{i-1}n}\right)y_2
\endalign
$$
\endroster
\head Final Notes\endhead
\subhead Numerical Issues of $A^{-1}B$\endsubhead
We began the solution of the Sylvester equation with multiplication by
$A^{-1}$. This can introduce numerical errors, and we need more
numerically stable supplement. Its aim is to make $A$ and $B$
commutative, this is we need to find a regular matrix $P$, such that
$(PA)(PB)=(PB)(PA)$. Recall that this is neccessary in solution of
$$
(I_2\otimes I_{m^i}\otimes (PA)+(D+C)\otimes\,\iF\otimes (PB))x=d,
$$
since this equation is
multiplied by $I_2\otimes I_{m^i}\otimes (PA)+(D-C)\otimes\,\iF\otimes PB$,
and the diagonal
result
$$
I_2\otimes I_{m^i}\otimes (PAPA) + 2D\otimes\,\iF\otimes (PAPB) +
(D^2-C^2)\otimes\,\iF^2\otimes (PBPB)
$$
is obtained only if
$(PA)(PB)=(PB)(PA)$.
Finding regular solution of $(PA)(PB)=(PB)(PA)$ is equivalent to
finding regular solution of $APB-BPA=0$. Numerical error of the former
equation is $P$-times greater than the numerical error of the latter
equation. And the numerical error of the latter equation also grows
with the size of $P$. On the other hand, truncation error in $P$
multiplication decreases with growing the size of $P$. By intuition,
stability analysis will show that the best choice is some orthonormal
$P$.
Obviously, since $A$ is regular, the equation $APB-BPA=0$ has solution
of the form $P=\alpha A^{-1}$, where $\alpha\neq 0$. There is a vector
space of all solutions $P$ (including singular ones). In precise
arithmetics, its dimension is $\sum n^2_i$, where $n_i$ is number of
repetitions of $i$-th eigenvalue of $A^{-1}B$ which is similar to
$BA^{-1}$. In floating point arithmetics, without any further
knowledge about $A$, and $B$, we are only sure about dimension $n$
which is implied by similarity of $A^{-1}B$ and $BA^{-1}$. Now we try
to find the base of the vector space of solutions.
Let $L$ denote the following linear operator:
$$L(X)=(AXB-BXA)^T.$$
Let $\vec(X)$ denote a vector made by stacking all the
columns of $X$. Let $T_n$ denote $n^2\times n^2$ matrix representing
operator $\vec(X)\mapsto \vec(X^T)$. And
finally let $M$ denote $n^2\times n^2$ matrix represening the operator
$L$. It is not difficult to verify that:
$$M=T_n(B^T\otimes A - A^T\otimes B)$$
Now we show that $M$ is skew symmetric. Recall that $T_n(X\otimes
Y)=(Y\otimes X)T_n$, we have:
$$M^T=(B^T\otimes A - A^T\otimes B)^TT_n=(B\otimes A^T - A\otimes B^T)T_n=
T_n(A^T\otimes B - B^T\otimes A) = -M$$
We try to solve $M\vec(X) = T_n(0) = 0$. Since $M$ is
skew symmetric, there is real orthonormal matrix $Q$, such that
$M=Q\widehat{M}Q^T$, and $\widehat{M}$ is block diagonal matrix
consisting of $2\times 2$ blocks of the form
$$\left(\matrix 0&\alpha_i\cr-\alpha_i&0\endmatrix\right),$$
and of additional zero, if $n^2$ is odd.
Now we solve equation $\widehat{M}y=0$, where $y=Q^T\vec(X)$. Now
there are $n$ zero rows in $\widehat{M}$ coming from similarity of
$A^{-1}B$ and $BA^{-1}$ (structural zeros). Note that the additional
zero for odd $n^2$ is already included in that number, since for odd
$n^2$ is $n^2-n$ even. Besides those, there are also zeros (esp. in
floating point arithmetics), coming from repetitive (or close)
eigenvalues of $A^{-1}B$. If we are able to select the rows with the
structural zeros, a solution is obtained by picking arbitrary numbers
for the same positions in $y$, and put $\vec(X)=Qy$.
The following questions need to be answered:
\roster
\item How to recognize the structural rows?
\item Is $A^{-1}$ generated by a $y$, which has non-zero elements only
on structural rows? Note that $A$ can have repetitive eigenvalues. The
positive answer to the question implies that in each $n$-partition of
$y$ there is exactly one structural row.
\item And very difficult one: How to pick $y$ so that $X$ would be
regular, or even close to orthonormal (pure orthonormality
overdeterminates $y$)?
\endroster
\subhead Making Zeros in $F$\endsubhead
It is clear that the numerical complexity of the proposed algorithm
strongly depends on a number of non-zero elements in the Schur factor
$F$. If we were able to find $P$, such that $PFP^{-1}$ has
substantially less zeros than $F$, then the computation would be
substantially faster. However, it seems that we have to pay price for
any additional zero in terms of less numerical stability of $PFP^{-1}$
multiplication. Consider $P$, and $F$ in form
$$P=\pmatrix I &X\cr 0&I\endpmatrix,
\qquad F=\pmatrix A&C\cr 0&B\endpmatrix$$
we obtain
$$PFP^{-1}=\pmatrix A& C + XB - AX\cr 0&B \endpmatrix$$
Thus, we need to solve $C = AX - XB$. Its clear that numerical
stability of operator $Y\mapsto PYP^{-1}$ and its inverse $Y\mapsto
P^{-1}YP$ is worse with growing norm $\Vert X\Vert$. The norm can be
as large as $\Vert F\Vert/\delta$, where $\delta$ is a distance of
eigenspectra of $A$ and $B$. Also, a numerical error of the solution is
proportional to $\Vert C\Vert/\delta$.
Although, these difficulties cannot be overcome completely, we may
introduce an algorithm, which works on $F$ with ordered eigenvalues on
diagonal, and seeks such partitioning to maximize $\delta$ and
minimize $C$. If the partitioning is found, the algorithm finds $P$
and then is run for $A$ and $B$ blocks. It stops when further
partitioning is not possible without breaking some user given limit
for numerical errors. We have to keep in mind that the numerical
errors are accumulated in product of all $P$'s of every step.
\subhead Exploiting constant rows in $F$\endsubhead
If some of $F$'s rows consists of the same numbers, or a number of
distict values within a row is small, then this structure can be
easily exploited in the algorithm. Recall, that in both functions
$\solvi$, and $\solviip$, we eliminate guys below diagonal element (or
block) (of $F^T$), by multiplying solution of the diagonal and
cancelling it from right side. If the elements below the diagonal
block are the same, we save one vector multiplication. Note that in
$\solviip$ we still need to multiply by elements below diagonal of the
matrix $F^{T2}$, which obviously has not the property. However, the
heaviest elimination is done at the very top level, in the first call
to $\solvi$.
Another way of exploitation the property is to proceed all
calculations in complex numbers. In that case, only $\solvi$ is run.
How the structure can be introduced into the matrix? Following the
same notation as in previous section, we solve $C = AX - XB$ in order
to obtain zeros at place of $C$. If it is not possible, we may relax
the equation by solving $C - R = AX - XB$, where $R$ is suitable
matrix with constant rows. The matrix $R$ minimizes $\Vert C-R\Vert$
in order to minimize $\Vert X\Vert$ if $A$, and $B$ are given. Now, in
the next step we need to introduce zeros (or constant rows) to matrix
$A$, so we seek for regular matrix $P$, doing the
job. If found, the product looks like:
$$\pmatrix P&0\cr 0&I\endpmatrix\pmatrix A&R\cr 0&B\endpmatrix
\pmatrix P^{-1}&0\cr 0&I\endpmatrix=
\pmatrix PAP^{-1}&PR\cr 0&B\endpmatrix$$
Now note, that matrix $PR$ has also constant rows. Thus,
preconditioning of the matrix in upper left corner doesn't affect the
property. However, a preconditioning of the matrix in lower right
corner breaks the property, since we would obtain $RP^{-1}$.
\enddocument

View File

@ -0,0 +1,71 @@
/* $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 <stdio.h>
#include <string.h>
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());
}

View File

@ -0,0 +1,46 @@
/* $Header: /var/lib/cvs/dynare_cpp/sylv/testing/MMMatrix.h,v 1.1.1.1 2004/06/04 13:01:13 kamenik Exp $ */
/* Tag $Name: $ */
#ifndef MM_MATRIX_H
#define MM_MATRIX_H
#include "GeneralMatrix.h"
#include "SylvMemory.h"
#include <string>
using namespace std;
class MMException : public MallocAllocator {
string message;
public:
MMException(string mes) : message(mes) {}
MMException(const char* mes) : message(mes) {}
const char* getMessage() const {return message.data();}
};
class MMMatrixIn : public MallocAllocator {
double* data;
int rows;
int cols;
public:
MMMatrixIn(const char* fname);
~MMMatrixIn();
const double* getData() const {return data;}
int size() const {return rows*cols;}
int row() const {return rows;}
int col() const {return cols;}
};
class MMMatrixOut : public MallocAllocator {
public:
static void write(const char* fname, int rows, int cols, const double* data);
static void write(const char* fname, const GeneralMatrix& m);
};
#endif /* MM_MATRIX_H */
// Local Variables:
// mode:C++
// End:

View File

@ -0,0 +1,36 @@
# $Header: /var/lib/cvs/dynare_cpp/sylv/testing/Makefile,v 1.2 2004/09/28 16:16:43 kamenik Exp $
# Tag $Name: $
LD_LIBS := -llapack -lcblas -lf77blas -latlas -lg2c
CC_FLAGS := -Wall -I../cc $(CC_INCLUDE_PATH)
CC_DEFS := #-DUSE_MEMORY_POOL
ifeq ($(DEBUG),yes)
CC_FLAGS := $(CC_FLAGS) -g
CC_DEFS := $(CC_DEFS) -DDEBUG
else
CC_FLAGS := $(CC_FLAGS) -O2
endif
objects := $(patsubst %.cpp,%.o,$(wildcard ../cc/*.cpp))
headers := $(wildcard ../cc/*.h)
clear:
make -C ../cc clear
rm -f tests.exe
rm -f tests
rm -f *.o
../cc/%.o : ../cc/%.cpp $(headers)
make EXTERN_DEFS="$(CC_DEFS)" -C ../cc $*.o
%.o : %.cpp $(headers)
$(CC) $(CC_FLAGS) $(CC_DEFS) -c $*.cpp
# untar testing data
tdata.done : tdata.tgz
tar -xzf tdata.tgz
touch tdata.done
test: $(objects) tests.o MMMatrix.o tdata.done
$(CC) $(CC_FLAGS) -o test $(objects) tests.o MMMatrix.o $(LD_LIBS)

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,59 @@
# $Id: Makefile 886 2006-09-01 11:56:07Z kamenik $
# Copyright 2004, Ondra Kamenik
LD_LIBS := -llapack -lcblas -lf77blas -latlas -lg2c
CC_FLAGS := -Wall -I../../sylv/cc \
$(CC_INCLUDE_PATH)
ifeq ($(DEBUG),yes)
CC_FLAGS := $(CC_FLAGS) -g -DTL_DEBUG=2
else
CC_FLAGS := $(CC_FLAGS) -O2 -DPOSIX_THREADS
endif
ifeq ($(OS),Windows_NT)
CC_FLAGS := -mno-cygwin -mthreads $(CC_FLAGS)
LD_LIBS := -mno-cygwin -mthreads $(LD_LIBS) -lpthreadGC1
else
LD_LIBS := $(LD_LIBS) -lpthread
endif
matrix_interface := GeneralMatrix Vector SylvException
matobjs := $(patsubst %, ../../sylv/cc/%.o, $(matrix_interface))
cwebsource := $(wildcard *.cweb)
cppsource := $(patsubst %.cweb,%.cpp,$(cwebsource))
objects := $(patsubst %.cweb,%.o,$(cwebsource))
hwebsource := $(wildcard *.hweb)
hsource := $(patsubst %.hweb,%.h,$(hwebsource))
dummy.ch:
touch dummy.ch
%.cpp: %.cweb dummy.ch
ctangle -bhp $*.cweb dummy.ch $*.cpp
%.h: %.hweb dummy.ch
ctangle -bhp $*.hweb dummy.ch $*.h
%.o : %.cpp $(hsource)
$(CC) $(CC_FLAGS) $(EXTERN_DEFS) -c $*.cpp
all: $(objects) $(cppsource) $(hsource)
tl.pdf: doc
doc: main.web $(hwebsource) $(cwebsource)
cweave -bhp main.web
pdftex main
mv main.pdf tl.pdf
clear:
rm -f $(cppsource)
rm -f $(hsource)
rm -f *.o
rm -f main.{dvi,idx,log,pdf,scn,tex,toc}
rm -f dummy.ch
rm -f *~

View File

@ -0,0 +1,513 @@
/*1:*/
#line 6 "./equivalence.cweb"
#include "equivalence.h"
#include "permutation.h"
#include "tl_exception.h"
#include <string.h>
/*2:*/
#line 19 "./equivalence.cweb"
/*6:*/
#line 57 "./equivalence.cweb"
int OrdSequence::operator[](int i)const
{
TL_RAISE_IF((i<0||i>=length()),
"Index out of range in OrdSequence::operator[]");
return data[i];
}
/*:6*/
#line 20 "./equivalence.cweb"
;
/*7:*/
#line 69 "./equivalence.cweb"
bool OrdSequence::operator<(const OrdSequence&s)const
{
double ta= average();
double sa= s.average();
return(ta<sa||((ta==sa)&&(operator[](0)> s[0])));
}
/*:7*/
#line 21 "./equivalence.cweb"
;
/*8:*/
#line 78 "./equivalence.cweb"
bool OrdSequence::operator==(const OrdSequence&s)const
{
if(length()!=s.length())
return false;
int i= 0;
while(i<length()&&operator[](i)==s[i])
i++;
return(i==length());
}
/*:8*/
#line 22 "./equivalence.cweb"
;
/*9:*/
#line 96 "./equivalence.cweb"
void OrdSequence::add(int i)
{
vector<int> ::iterator vit= data.begin();
while(vit!=data.end()&&*vit<i)
++vit;
if(vit!=data.end()&&*vit==i)
return;
data.insert(vit,i);
}
void OrdSequence::add(const OrdSequence&s)
{
vector<int> ::const_iterator vit= s.data.begin();
while(vit!=s.data.end()){
add(*vit);
++vit;
}
}
/*:9*/
#line 23 "./equivalence.cweb"
;
/*10:*/
#line 117 "./equivalence.cweb"
bool OrdSequence::has(int i)const
{
vector<int> ::const_iterator vit= data.begin();
while(vit!=data.end()){
if(*vit==i)
return true;
++vit;
}
return false;
}
/*:10*/
#line 24 "./equivalence.cweb"
;
/*11:*/
#line 130 "./equivalence.cweb"
double OrdSequence::average()const
{
double res= 0;
for(unsigned int i= 0;i<data.size();i++)
res+= data[i];
TL_RAISE_IF(data.size()==0,
"Attempt to take average of empty class in OrdSequence::average");
return res/data.size();
}
/*:11*/
#line 25 "./equivalence.cweb"
;
/*12:*/
#line 142 "./equivalence.cweb"
void OrdSequence::print(const char*prefix)const
{
printf("%s",prefix);
for(unsigned int i= 0;i<data.size();i++)
printf("%d ",data[i]);
printf("\n");
}
/*:12*/
#line 26 "./equivalence.cweb"
;
/*:2*/
#line 13 "./equivalence.cweb"
;
/*3:*/
#line 29 "./equivalence.cweb"
/*13:*/
#line 152 "./equivalence.cweb"
Equivalence::Equivalence(int num)
:n(num)
{
for(int i= 0;i<num;i++){
OrdSequence s;
s.add(i);
classes.push_back(s);
}
}
Equivalence::Equivalence(int num,const char*dummy)
:n(num)
{
OrdSequence s;
for(int i= 0;i<num;i++)
s.add(i);
classes.push_back(s);
}
/*:13*/
#line 30 "./equivalence.cweb"
;
/*14:*/
#line 173 "./equivalence.cweb"
Equivalence::Equivalence(const Equivalence&e)
:n(e.n),
classes(e.classes)
{
}
Equivalence::Equivalence(const Equivalence&e,int i1,int i2)
:n(e.n),
classes(e.classes)
{
seqit s1= find(i1);
seqit s2= find(i2);
if(s1!=s2){
OrdSequence ns(*s1);
ns.add(*s2);
classes.erase(s1);
classes.erase(s2);
insert(ns);
}
}
/*:14*/
#line 31 "./equivalence.cweb"
;
/*17:*/
#line 220 "./equivalence.cweb"
Equivalence::const_seqit Equivalence::findHaving(int i)const
{
const_seqit si= classes.begin();
while(si!=classes.end()){
if((*si).has(i))
return si;
++si;
}
TL_RAISE_IF(si==classes.end(),
"Couldn't find equivalence class in Equivalence::findHaving");
return si;
}
Equivalence::seqit Equivalence::findHaving(int i)
{
seqit si= classes.begin();
while(si!=classes.end()){
if((*si).has(i))
return si;
++si;
}
TL_RAISE_IF(si==classes.end(),
"Couldn't find equivalence class in Equivalence::findHaving");
return si;
}
/*:17*/
#line 32 "./equivalence.cweb"
;
/*18:*/
#line 249 "./equivalence.cweb"
Equivalence::const_seqit Equivalence::find(int j)const
{
const_seqit si= classes.begin();
int i= 0;
while(si!=classes.end()&&i<j){
++si;
i++;
}
TL_RAISE_IF(si==classes.end(),
"Couldn't find equivalence class in Equivalence::find");
return si;
}
Equivalence::seqit Equivalence::find(int j)
{
seqit si= classes.begin();
int i= 0;
while(si!=classes.end()&&i<j){
++si;
i++;
}
TL_RAISE_IF(si==classes.end(),
"Couldn't find equivalence class in Equivalence::find");
return si;
}
/*:18*/
#line 33 "./equivalence.cweb"
;
/*19:*/
#line 278 "./equivalence.cweb"
void Equivalence::insert(const OrdSequence&s)
{
seqit si= classes.begin();
while(si!=classes.end()&&*si<s)
++si;
classes.insert(si,s);
}
/*:19*/
#line 34 "./equivalence.cweb"
;
/*15:*/
#line 196 "./equivalence.cweb"
const Equivalence&Equivalence::operator= (const Equivalence&e)
{
classes.clear();
n= e.n;
classes= e.classes;
return*this;
}
/*:15*/
#line 35 "./equivalence.cweb"
;
/*16:*/
#line 206 "./equivalence.cweb"
bool Equivalence::operator==(const Equivalence&e)const
{
if(!std::operator==(classes,e.classes))
return false;
if(n!=e.n)
return false;
return true;
}
/*:16*/
#line 36 "./equivalence.cweb"
;
/*20:*/
#line 293 "./equivalence.cweb"
void Equivalence::trace(IntSequence&out,int num)const
{
int i= 0;
int nc= 0;
for(const_seqit it= begin();it!=end()&&nc<num;++it,++nc)
for(int j= 0;j<(*it).length();j++,i++){
TL_RAISE_IF(i>=out.size(),
"Wrong size of output sequence in Equivalence::trace");
out[i]= (*it)[j];
}
}
/*:20*/
#line 37 "./equivalence.cweb"
;
/*21:*/
#line 307 "./equivalence.cweb"
void Equivalence::trace(IntSequence&out,const Permutation&per)const
{
TL_RAISE_IF(out.size()!=n,
"Wrong size of output sequence in Equivalence::trace");
TL_RAISE_IF(per.size()!=numClasses(),
"Wrong permutation for permuted Equivalence::trace");
int i= 0;
for(int iclass= 0;iclass<numClasses();iclass++){
const_seqit itper= find(per.getMap()[iclass]);
for(int j= 0;j<(*itper).length();j++,i++)
out[i]= (*itper)[j];
}
}
/*:21*/
#line 38 "./equivalence.cweb"
;
/*22:*/
#line 324 "./equivalence.cweb"
void Equivalence::print(const char*prefix)const
{
int i= 0;
for(const_seqit it= classes.begin();
it!=classes.end();
++it,i++){
printf("%sclass %d: ",prefix,i);
(*it).print("");
}
}
/*:22*/
#line 39 "./equivalence.cweb"
;
/*:3*/
#line 14 "./equivalence.cweb"
;
/*4:*/
#line 42 "./equivalence.cweb"
/*23:*/
#line 357 "./equivalence.cweb"
EquivalenceSet::EquivalenceSet(int num)
:n(num),
equis()
{
list<Equivalence> added;
Equivalence first(n);
equis.push_back(first);
addParents(first,added);
while(!added.empty()){
addParents(added.front(),added);
added.pop_front();
}
if(n> 1){
Equivalence last(n,"");
equis.push_back(last);
}
}
/*:23*/
#line 43 "./equivalence.cweb"
;
/*24:*/
#line 386 "./equivalence.cweb"
bool EquivalenceSet::has(const Equivalence&e)const
{
list<Equivalence> ::const_reverse_iterator rit= equis.rbegin();
while(rit!=equis.rend()&&*rit!=e)
++rit;
if(rit!=equis.rend())
return true;
return false;
}
/*:24*/
#line 44 "./equivalence.cweb"
;
/*25:*/
#line 404 "./equivalence.cweb"
void EquivalenceSet::addParents(const Equivalence&e,
list<Equivalence> &added)
{
if(e.numClasses()==2||e.numClasses()==1)
return;
for(int i1= 0;i1<e.numClasses();i1++)
for(int i2= i1+1;i2<e.numClasses();i2++){
Equivalence ns(e,i1,i2);
if(!has(ns)){
added.push_back(ns);
equis.push_back(ns);
}
}
}
/*:25*/
#line 45 "./equivalence.cweb"
;
/*26:*/
#line 422 "./equivalence.cweb"
void EquivalenceSet::print(const char*prefix)const
{
char tmp[100];
strcpy(tmp,prefix);
strcat(tmp," ");
int i= 0;
for(list<Equivalence> ::const_iterator it= equis.begin();
it!=equis.end();
++it,i++){
printf("%sequivalence %d:(classes %d)\n",prefix,i,(*it).numClasses());
(*it).print(tmp);
}
}
/*:26*/
#line 46 "./equivalence.cweb"
;
/*:4*/
#line 15 "./equivalence.cweb"
;
/*5:*/
#line 49 "./equivalence.cweb"
/*27:*/
#line 438 "./equivalence.cweb"
EquivalenceBundle::EquivalenceBundle(int nmax)
{
nmax= max(nmax,1);
generateUpTo(nmax);
}
/*:27*/
#line 50 "./equivalence.cweb"
;
/*28:*/
#line 446 "./equivalence.cweb"
EquivalenceBundle::~EquivalenceBundle()
{
for(unsigned int i= 0;i<bundle.size();i++)
delete bundle[i];
}
/*:28*/
#line 51 "./equivalence.cweb"
;
/*29:*/
#line 454 "./equivalence.cweb"
const EquivalenceSet&EquivalenceBundle::get(int n)const
{
if(n> (int)(bundle.size())||n<1){
TL_RAISE("Equivalence set not found in EquivalenceBundle::get");
return*(bundle[0]);
}else{
return*(bundle[n-1]);
}
}
/*:29*/
#line 52 "./equivalence.cweb"
;
/*30:*/
#line 468 "./equivalence.cweb"
void EquivalenceBundle::generateUpTo(int nmax)
{
int curmax= bundle.size();
for(int i= curmax+1;i<=nmax;i++)
bundle.push_back(new EquivalenceSet(i));
}
/*:30*/
#line 53 "./equivalence.cweb"
;
/*:5*/
#line 16 "./equivalence.cweb"
;
/*:1*/

View File

@ -0,0 +1,146 @@
/*1:*/
#line 46 "./equivalence.hweb"
#ifndef EQUIVALENCE_H
#define EQUIVALENCE_H
#include "int_sequence.h"
#include <vector>
#include <list>
using namespace std;
/*2:*/
#line 72 "./equivalence.hweb"
class OrdSequence{
vector<int> data;
public:
OrdSequence():data(){}
OrdSequence(const OrdSequence&s):data(s.data){}
const OrdSequence&operator= (const OrdSequence&s)
{data= s.data;return*this;}
bool operator==(const OrdSequence&s)const;
int operator[](int i)const;
bool operator<(const OrdSequence&s)const;
const vector<int> &getData()const
{return data;}
int length()const{return data.size();}
void add(int i);
void add(const OrdSequence&s);
bool has(int i)const;
void print(const char*prefix)const;
private:
double average()const;
};
/*:2*/
#line 57 "./equivalence.hweb"
;
/*3:*/
#line 101 "./equivalence.hweb"
class Permutation;
class Equivalence{
private:
int n;
list<OrdSequence> classes;
public:
typedef list<OrdSequence> ::const_iterator const_seqit;
typedef list<OrdSequence> ::iterator seqit;
/*6:*/
#line 178 "./equivalence.hweb"
Equivalence(int num);
Equivalence(int num,const char*dummy);
Equivalence(const Equivalence&e);
Equivalence(const Equivalence&e,int i1,int i2);
/*:6*/
#line 111 "./equivalence.hweb"
;
const Equivalence&operator= (const Equivalence&e);
bool operator==(const Equivalence&e)const;
bool operator!=(const Equivalence&e)const
{return!operator==(e);}
int getN()const{return n;}
int numClasses()const{return classes.size();}
void trace(IntSequence&out,int n)const;
void trace(IntSequence&out)const
{trace(out,numClasses());}
void trace(IntSequence&out,const Permutation&per)const;
void print(const char*prefix)const;
/*7:*/
#line 185 "./equivalence.hweb"
seqit begin(){return classes.begin();}
const_seqit begin()const{return classes.begin();}
seqit end(){return classes.end();}
const_seqit end()const{return classes.end();}
/*:7*/
#line 123 "./equivalence.hweb"
;
const_seqit find(int i)const;
seqit find(int i);
protected:
/*8:*/
#line 198 "./equivalence.hweb"
const_seqit findHaving(int i)const;
seqit findHaving(int i);
void insert(const OrdSequence&s);
/*:8*/
#line 127 "./equivalence.hweb"
;
};
/*:3*/
#line 58 "./equivalence.hweb"
;
/*4:*/
#line 137 "./equivalence.hweb"
class EquivalenceSet{
int n;
list<Equivalence> equis;
public:
typedef list<Equivalence> ::const_iterator const_iterator;
EquivalenceSet(int num);
void print(const char*prefix)const;
const_iterator begin()const
{return equis.begin();}
const_iterator end()const
{return equis.end();}
private:
bool has(const Equivalence&e)const;
void addParents(const Equivalence&e,list<Equivalence> &added);
};
/*:4*/
#line 59 "./equivalence.hweb"
;
/*5:*/
#line 161 "./equivalence.hweb"
class EquivalenceBundle{
vector<EquivalenceSet*> bundle;
public:
EquivalenceBundle(int nmax);
~EquivalenceBundle();
const EquivalenceSet&get(int n)const;
void generateUpTo(int nmax);
};
/*:5*/
#line 60 "./equivalence.hweb"
;
#endif
/*:1*/

View File

@ -0,0 +1,39 @@
/*1:*/
#line 6 "./fine_container.cweb"
#include "fine_container.h"
#include <math.h>
/*2:*/
#line 16 "./fine_container.cweb"
SizeRefinement::SizeRefinement(const IntSequence&s,int nc,int max)
{
new_nc= 0;
for(int i= 0;i<nc;i++){
int nr= s[i]/max;
if(s[i]%max!=0)
nr++;
int ss= (nr> 0)?(int)round(((double)s[i])/nr):0;
for(int j= 0;j<nr-1;j++){
rsizes.push_back(ss);
ind_map.push_back(i);
new_nc++;
}
rsizes.push_back(s[i]-(nr-1)*ss);
ind_map.push_back(i);
new_nc++;
}
for(int i= nc;i<s.size();i++){
rsizes.push_back(s[i]);
ind_map.push_back(i);
}
}
/*:2*/
#line 11 "./fine_container.cweb"
;
/*:1*/

View File

@ -0,0 +1,130 @@
/*1:*/
#line 33 "./fine_container.hweb"
#ifndef FINE_CONTAINER_H
#define FINE_CONTAINER_H
#include "stack_container.h"
#include <vector>
/*2:*/
#line 54 "./fine_container.hweb"
class SizeRefinement{
vector<int> rsizes;
vector<int> ind_map;
int new_nc;
public:
SizeRefinement(const IntSequence&s,int nc,int max);
int getRefSize(int i)const
{return rsizes[i];}
int numRefinements()const
{return rsizes.size();}
int getOldIndex(int i)const
{return ind_map[i];}
int getNC()const
{return new_nc;}
};
/*:2*/
#line 41 "./fine_container.hweb"
;
/*3:*/
#line 77 "./fine_container.hweb"
template<class _Ttype>
class FineContainer:public SizeRefinement,public StackContainer<_Ttype> {
protected:
typedef StackContainer<_Ttype> _Stype;
typedef typename StackContainerInterface<_Ttype> ::_Ctype _Ctype;
typedef typename StackContainerInterface<_Ttype> ::itype itype;
_Ctype**const ref_conts;
const _Stype&stack_cont;
public:
/*4:*/
#line 109 "./fine_container.hweb"
FineContainer(const _Stype&sc,int max)
:SizeRefinement(sc.getStackSizes(),sc.numConts(),max),
StackContainer<_Ttype> (numRefinements(),getNC()),
ref_conts(new _Ctype*[getNC()]),
stack_cont(sc)
{
for(int i= 0;i<numRefinements();i++)
_Stype::stack_sizes[i]= getRefSize(i);
_Stype::calculateOffsets();
int last_cont= -1;
int last_row= 0;
for(int i= 0;i<getNC();i++){
if(getOldIndex(i)!=last_cont){
last_cont= getOldIndex(i);
last_row= 0;
}
union{const _Ctype*c;_Ctype*n;}convert;
convert.c= stack_cont.getCont(last_cont);
ref_conts[i]= new _Ctype(last_row,_Stype::stack_sizes[i],
*(convert.n));
_Stype::conts[i]= ref_conts[i];
last_row+= _Stype::stack_sizes[i];
}
}
/*:4*/
#line 87 "./fine_container.hweb"
;
/*5:*/
#line 137 "./fine_container.hweb"
virtual~FineContainer()
{
for(int i= 0;i<_Stype::numConts();i++)
delete ref_conts[i];
delete[]ref_conts;
}
/*:5*/
#line 88 "./fine_container.hweb"
;
itype getType(int i,const Symmetry&s)const
{return stack_cont.getType(getOldIndex(i),s);}
};
/*:3*/
#line 42 "./fine_container.hweb"
;
/*6:*/
#line 148 "./fine_container.hweb"
class FoldedFineContainer:public FineContainer<FGSTensor> ,public FoldedStackContainer{
public:
FoldedFineContainer(const StackContainer<FGSTensor> &sc,int max)
:FineContainer<FGSTensor> (sc,max){}
};
/*:6*/
#line 43 "./fine_container.hweb"
;
/*7:*/
#line 156 "./fine_container.hweb"
class UnfoldedFineContainer:public FineContainer<UGSTensor> ,public UnfoldedStackContainer{
public:
UnfoldedFineContainer(const StackContainer<UGSTensor> &sc,int max)
:FineContainer<UGSTensor> (sc,max){}
};
/*:7*/
#line 44 "./fine_container.hweb"
;
#endif
/*:1*/

Some files were not shown because too many files have changed in this diff Show More