MEX files: reformat C++ source code using clang-format 15
parent
ca16f7f848
commit
ed332e3ba1
|
@ -21,10 +21,9 @@
|
|||
|
||||
#include "dynmex.h"
|
||||
|
||||
BasicSymbolTable::BasicSymbolTable(const mxArray *M_)
|
||||
BasicSymbolTable::BasicSymbolTable(const mxArray* M_)
|
||||
{
|
||||
auto get_field_names = [&](const char *field_name, SymbolType type)
|
||||
{
|
||||
auto get_field_names = [&](const char* field_name, SymbolType type) {
|
||||
vector<string> r;
|
||||
if (mxGetFieldNumber(M_, field_name) != -1)
|
||||
{
|
||||
|
@ -33,16 +32,17 @@ BasicSymbolTable::BasicSymbolTable(const mxArray *M_)
|
|||
mexErrMsgTxt(("M_."s + field_name + " is not a cell array").c_str());
|
||||
for (size_t i {0}; i < mxGetNumberOfElements(M_field); i++)
|
||||
{
|
||||
const mxArray *cell_mx = mxGetCell(M_field, i);
|
||||
const mxArray* cell_mx = mxGetCell(M_field, i);
|
||||
if (!(cell_mx && mxIsChar(cell_mx)))
|
||||
mexErrMsgTxt(("M_."s + field_name + " contains a cell which is not a character array").c_str());
|
||||
mexErrMsgTxt(("M_."s + field_name + " contains a cell which is not a character array")
|
||||
.c_str());
|
||||
r.emplace_back(mxArrayToString(cell_mx));
|
||||
}
|
||||
}
|
||||
|
||||
// Fill the reverse map
|
||||
for (size_t i {0}; i < r.size(); i++)
|
||||
name_to_id_and_type.emplace(r[i], pair{type, i});
|
||||
name_to_id_and_type.emplace(r[i], pair {type, i});
|
||||
|
||||
return r;
|
||||
};
|
||||
|
@ -71,21 +71,23 @@ BasicSymbolTable::getName(SymbolType type, int tsid) const
|
|||
mexErrMsgTxt(("Unsupported symbol type: " + to_string(static_cast<int>(type))).c_str());
|
||||
}
|
||||
}
|
||||
catch (out_of_range &)
|
||||
catch (out_of_range&)
|
||||
{
|
||||
mexErrMsgTxt(("Unknown symbol with ID " + to_string(tsid) + " and type " + to_string(static_cast<int>(type))).c_str());
|
||||
mexErrMsgTxt(("Unknown symbol with ID " + to_string(tsid) + " and type "
|
||||
+ to_string(static_cast<int>(type)))
|
||||
.c_str());
|
||||
}
|
||||
__builtin_unreachable(); // Silence GCC warning
|
||||
}
|
||||
|
||||
pair<SymbolType, int>
|
||||
BasicSymbolTable::getIDAndType(const string &name) const
|
||||
BasicSymbolTable::getIDAndType(const string& name) const
|
||||
{
|
||||
try
|
||||
{
|
||||
return name_to_id_and_type.at(name);
|
||||
}
|
||||
catch (out_of_range &)
|
||||
catch (out_of_range&)
|
||||
{
|
||||
mexErrMsgTxt(("Unknown symbol: " + name).c_str());
|
||||
}
|
||||
|
@ -96,7 +98,7 @@ size_t
|
|||
BasicSymbolTable::maxEndoNameLength() const
|
||||
{
|
||||
size_t r {0};
|
||||
for (const auto &n : endo_names)
|
||||
for (const auto& n : endo_names)
|
||||
r = max(r, n.size());
|
||||
return r;
|
||||
}
|
||||
|
|
|
@ -20,10 +20,10 @@
|
|||
#ifndef _BASIC_SYMBOL_TABLE_HH
|
||||
#define _BASIC_SYMBOL_TABLE_HH
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "dynmex.h"
|
||||
|
||||
|
@ -34,10 +34,11 @@ using namespace std;
|
|||
class BasicSymbolTable
|
||||
{
|
||||
public:
|
||||
BasicSymbolTable(const mxArray *M_);
|
||||
BasicSymbolTable(const mxArray* M_);
|
||||
string getName(SymbolType type, int tsid) const;
|
||||
pair<SymbolType, int> getIDAndType(const string &name) const;
|
||||
pair<SymbolType, int> getIDAndType(const string& name) const;
|
||||
size_t maxEndoNameLength() const;
|
||||
|
||||
private:
|
||||
vector<string> endo_names, param_names, exo_names, exo_det_names;
|
||||
map<string, pair<SymbolType, int>> name_to_id_and_type;
|
||||
|
|
|
@ -20,9 +20,9 @@
|
|||
#ifndef _ERROR_HANDLING_HH
|
||||
#define _ERROR_HANDLING_HH
|
||||
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <cmath>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
@ -34,23 +34,22 @@ struct GeneralException
|
|||
struct FloatingPointException : public GeneralException
|
||||
{
|
||||
const string location;
|
||||
FloatingPointException(const string &details, string location_arg) :
|
||||
GeneralException {"Floating point error: " + details},
|
||||
location {move(location_arg)}
|
||||
FloatingPointException(const string& details, string location_arg) :
|
||||
GeneralException {"Floating point error: " + details}, location {move(location_arg)}
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct UnaryOpException : public FloatingPointException
|
||||
{
|
||||
UnaryOpException(const string &op, double value, string location_arg) :
|
||||
FloatingPointException { [=]
|
||||
{
|
||||
// We don’t use std::to_string(), because it uses fixed formatting
|
||||
ostringstream s;
|
||||
s << op << "(X) with X=" << defaultfloat << value;
|
||||
return s.str();
|
||||
}(), move(location_arg) }
|
||||
UnaryOpException(const string& op, double value, string location_arg) :
|
||||
FloatingPointException {[=] {
|
||||
// We don’t use std::to_string(), because it uses fixed formatting
|
||||
ostringstream s;
|
||||
s << op << "(X) with X=" << defaultfloat << value;
|
||||
return s.str();
|
||||
}(),
|
||||
move(location_arg)}
|
||||
{
|
||||
}
|
||||
};
|
||||
|
@ -58,13 +57,13 @@ struct UnaryOpException : public FloatingPointException
|
|||
struct DivideException : public FloatingPointException
|
||||
{
|
||||
DivideException(double v1, double v2, string location_arg) :
|
||||
FloatingPointException { [=]
|
||||
{
|
||||
// We don’t use std::to_string(), because it uses fixed formatting
|
||||
ostringstream s;
|
||||
s << "a/X with a=" << defaultfloat << v1 << " and X= " << v2;
|
||||
return s.str();
|
||||
}(), move(location_arg) }
|
||||
FloatingPointException {[=] {
|
||||
// We don’t use std::to_string(), because it uses fixed formatting
|
||||
ostringstream s;
|
||||
s << "a/X with a=" << defaultfloat << v1 << " and X= " << v2;
|
||||
return s.str();
|
||||
}(),
|
||||
move(location_arg)}
|
||||
{
|
||||
}
|
||||
};
|
||||
|
@ -72,15 +71,15 @@ struct DivideException : public FloatingPointException
|
|||
struct PowException : public FloatingPointException
|
||||
{
|
||||
PowException(double base, double exponent, string location_arg) :
|
||||
FloatingPointException { [=]
|
||||
{
|
||||
// We don’t use std::to_string(), because it uses fixed formatting
|
||||
ostringstream s;
|
||||
s << "X^a with X=" << defaultfloat << base;
|
||||
if (fabs(base) <= 1e-10)
|
||||
s << " and a=" << exponent;
|
||||
return s.str();
|
||||
}(), move(location_arg) }
|
||||
FloatingPointException {[=] {
|
||||
// We don’t use std::to_string(), because it uses fixed formatting
|
||||
ostringstream s;
|
||||
s << "X^a with X=" << defaultfloat << base;
|
||||
if (fabs(base) <= 1e-10)
|
||||
s << " and a=" << exponent;
|
||||
return s.str();
|
||||
}(),
|
||||
move(location_arg)}
|
||||
{
|
||||
}
|
||||
};
|
||||
|
@ -94,17 +93,18 @@ struct UserException : public GeneralException
|
|||
|
||||
struct FatalException : public GeneralException
|
||||
{
|
||||
FatalException(const string &details) :
|
||||
GeneralException {"Fatal error: " + details}
|
||||
FatalException(const string& details) : GeneralException {"Fatal error: " + details}
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
inline void
|
||||
test_mxMalloc(void *z, int line, const string &file, const string &func, int amount)
|
||||
test_mxMalloc(void* z, int line, const string& file, const string& func, int amount)
|
||||
{
|
||||
if (!z && amount > 0)
|
||||
throw FatalException{"mxMalloc: out of memory " + to_string(amount) + " bytes required at line " + to_string(line) + " in function " + func + " (file " + file};
|
||||
throw FatalException {"mxMalloc: out of memory " + to_string(amount)
|
||||
+ " bytes required at line " + to_string(line) + " in function " + func
|
||||
+ " (file " + file};
|
||||
}
|
||||
|
||||
#ifdef MATLAB_MEX_FILE
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -20,24 +20,24 @@
|
|||
#ifndef _EVALUATE_HH
|
||||
#define _EVALUATE_HH
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <optional>
|
||||
#include <memory>
|
||||
#include <filesystem>
|
||||
#include <deque>
|
||||
#include <filesystem>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "Bytecode.hh"
|
||||
#include "BasicSymbolTable.hh"
|
||||
#include "Bytecode.hh"
|
||||
|
||||
class Evaluate
|
||||
{
|
||||
private:
|
||||
using instructions_list_t = vector<BytecodeInstruction *>;
|
||||
using instructions_list_t = vector<BytecodeInstruction*>;
|
||||
using it_code_type = instructions_list_t::const_iterator;
|
||||
|
||||
const BasicSymbolTable &symbol_table;
|
||||
const BasicSymbolTable& symbol_table;
|
||||
const bool steady_state; // Whether this is a static or dynamic .cod file
|
||||
|
||||
// Memory copy of the contents of the .cod file
|
||||
|
@ -55,14 +55,14 @@ private:
|
|||
Those are either pointers inside “raw_bytecode” or “deserialized_{fbeginblock,fcall}” */
|
||||
instructions_list_t instructions_list;
|
||||
|
||||
// Number of blocks in the model
|
||||
// Number of blocks in the model
|
||||
int nb_blocks {0};
|
||||
|
||||
// Index of beginnings of blocks within instructions_list
|
||||
vector<size_t> begin_block;
|
||||
|
||||
int block_num; // Index of the current block
|
||||
int size; // Size of the current block
|
||||
int size; // Size of the current block
|
||||
|
||||
ExpressionType EQN_type;
|
||||
int EQN_equation, EQN_dvar1;
|
||||
|
@ -75,12 +75,14 @@ private:
|
|||
the expression that created a floating point exception, in which case the
|
||||
corresponding mathematical operator will be printed within braces.
|
||||
The second output argument points to the tag past the expression. */
|
||||
pair<string, it_code_type> print_expression(const it_code_type &expr_begin, const optional<it_code_type> &faulty_op = nullopt) const;
|
||||
pair<string, it_code_type> print_expression(const it_code_type& expr_begin,
|
||||
const optional<it_code_type>& faulty_op
|
||||
= nullopt) const;
|
||||
|
||||
FBEGINBLOCK_ *
|
||||
FBEGINBLOCK_*
|
||||
currentBlockTag() const
|
||||
{
|
||||
return reinterpret_cast<FBEGINBLOCK_ *>(instructions_list[begin_block[block_num]]);
|
||||
return reinterpret_cast<FBEGINBLOCK_*>(instructions_list[begin_block[block_num]]);
|
||||
}
|
||||
|
||||
// Returns iterator to first instruction in the current block (after FBEGINBLOCK)
|
||||
|
@ -91,9 +93,17 @@ private:
|
|||
}
|
||||
|
||||
public:
|
||||
Evaluate(const filesystem::path &codfile, bool steady_state_arg, const BasicSymbolTable &symbol_table_arg);
|
||||
Evaluate(const filesystem::path& codfile, bool steady_state_arg,
|
||||
const BasicSymbolTable& symbol_table_arg);
|
||||
|
||||
void evaluateBlock(int it_, int y_kmin, double *__restrict__ y, int y_size, double *__restrict__ x, int nb_row_x, double *__restrict__ params, const double *__restrict__ steady_y, double *__restrict__ u, int Per_u_, double *__restrict__ T, int T_nrows, map<int, double> &TEF, map<pair<int, int>, double> &TEFD, map<tuple<int, int, int>, double> &TEFDD, double *__restrict__ r, double *__restrict__ g1, double *__restrict__ jacob, double *__restrict__ jacob_exo, double *__restrict__ jacob_exo_det, bool evaluate, bool no_derivatives);
|
||||
void evaluateBlock(int it_, int y_kmin, double* __restrict__ y, int y_size,
|
||||
double* __restrict__ x, int nb_row_x, double* __restrict__ params,
|
||||
const double* __restrict__ steady_y, double* __restrict__ u, int Per_u_,
|
||||
double* __restrict__ T, int T_nrows, map<int, double>& TEF,
|
||||
map<pair<int, int>, double>& TEFD, map<tuple<int, int, int>, double>& TEFDD,
|
||||
double* __restrict__ r, double* __restrict__ g1, double* __restrict__ jacob,
|
||||
double* __restrict__ jacob_exo, double* __restrict__ jacob_exo_det,
|
||||
bool evaluate, bool no_derivatives);
|
||||
|
||||
// Prints current block
|
||||
void printCurrentBlock();
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -20,21 +20,21 @@
|
|||
#ifndef _INTERPRETER_HH
|
||||
#define _INTERPRETER_HH
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <cstddef>
|
||||
#include <utility>
|
||||
#include <map>
|
||||
#include <tuple>
|
||||
#include <stack>
|
||||
#include <fstream>
|
||||
#include <map>
|
||||
#include <stack>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "dynumfpack.h"
|
||||
#include "dynmex.h"
|
||||
#include "dynumfpack.h"
|
||||
|
||||
#include "ErrorHandling.hh"
|
||||
#include "Mem_Mngr.hh"
|
||||
#include "Evaluate.hh"
|
||||
#include "Mem_Mngr.hh"
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
@ -61,7 +61,8 @@ struct table_conditional_local_type
|
|||
using vector_table_conditional_local_type = vector<table_conditional_local_type>;
|
||||
using table_conditional_global_type = map<int, vector_table_conditional_local_type>;
|
||||
|
||||
constexpr int IFLD = 0, IFDIV = 1, IFLESS = 2, IFSUB = 3, IFLDZ = 4, IFMUL = 5, IFSTP = 6, IFADD = 7;
|
||||
constexpr int IFLD = 0, IFDIV = 1, IFLESS = 2, IFSUB = 3, IFLDZ = 4, IFMUL = 5, IFSTP = 6,
|
||||
IFADD = 7;
|
||||
constexpr double eps = 1e-15, very_big = 1e24;
|
||||
constexpr int alt_symbolic_count_max = 1;
|
||||
constexpr double mem_increasing_factor = 1.1;
|
||||
|
@ -76,13 +77,13 @@ private:
|
|||
|
||||
void *Symbolic {nullptr}, *Numeric {nullptr};
|
||||
|
||||
const BasicSymbolTable &symbol_table;
|
||||
const BasicSymbolTable& symbol_table;
|
||||
const bool steady_state; // Whether this is a static or dynamic model
|
||||
|
||||
// Whether to use the block-decomposed version of the bytecode file
|
||||
bool block_decomposed;
|
||||
|
||||
Evaluate &evaluator;
|
||||
Evaluate& evaluator;
|
||||
|
||||
fstream SaveCode;
|
||||
|
||||
|
@ -94,8 +95,8 @@ private:
|
|||
|
||||
int *pivot, *pivotk, *pivot_save;
|
||||
double *pivotv, *pivotva;
|
||||
int *b;
|
||||
bool *line_done;
|
||||
int* b;
|
||||
bool* line_done;
|
||||
bool symbolic, alt_symbolic;
|
||||
int alt_symbolic_count;
|
||||
double markowitz_c_s;
|
||||
|
@ -104,7 +105,7 @@ private:
|
|||
map<tuple<int, int, int>, int> IM_i;
|
||||
int u_count_alloc, u_count_alloc_save;
|
||||
double slowc, slowc_save, prev_slowc_save, markowitz_c;
|
||||
int *index_equa; // Actually unused
|
||||
int* index_equa; // Actually unused
|
||||
int u_count, tbreak_g;
|
||||
int iter;
|
||||
int start_compare;
|
||||
|
@ -118,24 +119,24 @@ private:
|
|||
int minimal_solving_periods;
|
||||
int Per_u_, Per_y_;
|
||||
int maxit_;
|
||||
double *direction;
|
||||
double* direction;
|
||||
double solve_tolf;
|
||||
// 1-norm error, square of 2-norm error, ∞-norm error
|
||||
double res1, res2, max_res;
|
||||
int max_res_idx;
|
||||
int *index_vara;
|
||||
int* index_vara;
|
||||
|
||||
double *y, *ya;
|
||||
int y_size;
|
||||
double *T;
|
||||
double* T;
|
||||
int nb_row_x;
|
||||
int y_kmin, y_kmax, periods;
|
||||
double *x, *params;
|
||||
double *u;
|
||||
double *steady_y;
|
||||
double* u;
|
||||
double* steady_y;
|
||||
double *g1, *r, *res;
|
||||
vector<mxArray *> jacobian_block, jacobian_exo_block, jacobian_det_exo_block;
|
||||
mxArray *GlobalTemporaryTerms;
|
||||
vector<mxArray*> jacobian_block, jacobian_exo_block, jacobian_det_exo_block;
|
||||
mxArray* GlobalTemporaryTerms;
|
||||
int it_;
|
||||
map<int, double> TEF;
|
||||
map<pair<int, int>, double> TEFD;
|
||||
|
@ -143,7 +144,7 @@ private:
|
|||
|
||||
// Information about the current block
|
||||
int block_num; // Index of the current block
|
||||
int size; // Size of the current block
|
||||
int size; // Size of the current block
|
||||
BlockSimulationType type;
|
||||
bool is_linear;
|
||||
int u_count_int;
|
||||
|
@ -160,47 +161,61 @@ private:
|
|||
void solve_simple_one_periods();
|
||||
void solve_simple_over_periods(bool forward);
|
||||
void compute_complete_2b();
|
||||
void evaluate_a_block(bool initialization, bool single_block, const string &bin_base_name);
|
||||
int simulate_a_block(const vector_table_conditional_local_type &vector_table_conditional_local, bool single_block, const string &bin_base_name);
|
||||
void evaluate_a_block(bool initialization, bool single_block, const string& bin_base_name);
|
||||
int simulate_a_block(const vector_table_conditional_local_type& vector_table_conditional_local,
|
||||
bool single_block, const string& bin_base_name);
|
||||
static string elastic(string str, unsigned int len, bool left);
|
||||
void check_for_controlled_exo_validity(const vector<s_plan> &sconstrained_extended_path);
|
||||
pair<bool, vector<int>> MainLoop(const string &bin_basename, bool evaluate, int block, bool constrained, const vector<s_plan> &sconstrained_extended_path, const vector_table_conditional_local_type &vector_table_conditional_local);
|
||||
void Simulate_Newton_Two_Boundaries(bool cvg, const vector_table_conditional_local_type &vector_table_conditional_local);
|
||||
void check_for_controlled_exo_validity(const vector<s_plan>& sconstrained_extended_path);
|
||||
pair<bool, vector<int>>
|
||||
MainLoop(const string& bin_basename, bool evaluate, int block, bool constrained,
|
||||
const vector<s_plan>& sconstrained_extended_path,
|
||||
const vector_table_conditional_local_type& vector_table_conditional_local);
|
||||
void Simulate_Newton_Two_Boundaries(
|
||||
bool cvg, const vector_table_conditional_local_type& vector_table_conditional_local);
|
||||
void Simulate_Newton_One_Boundary(bool forward);
|
||||
void fixe_u();
|
||||
void Read_SparseMatrix(const string &file_name, bool two_boundaries);
|
||||
void Read_SparseMatrix(const string& file_name, bool two_boundaries);
|
||||
void Singular_display();
|
||||
void End_Solver();
|
||||
static int find_exo_num(const vector<s_plan> &sconstrained_extended_path, int value);
|
||||
static int find_int_date(const vector<pair<int, double>> &per_value, int value);
|
||||
static int find_exo_num(const vector<s_plan>& sconstrained_extended_path, int value);
|
||||
static int find_int_date(const vector<pair<int, double>>& per_value, int value);
|
||||
void Init_Gaussian_Elimination();
|
||||
void Init_Matlab_Sparse_Two_Boundaries(const mxArray *A_m, const mxArray *b_m, const mxArray *x0_m) const;
|
||||
tuple<SuiteSparse_long *, SuiteSparse_long *, double *, double *> Init_UMFPACK_Sparse_Two_Boundaries(const mxArray *x0_m, const vector_table_conditional_local_type &vector_table_conditional_local) const;
|
||||
bool Init_Matlab_Sparse_One_Boundary(const mxArray *A_m, const mxArray *b_m, const mxArray *x0_m) const;
|
||||
tuple<bool, SuiteSparse_long *, SuiteSparse_long *, double *, double *> Init_UMFPACK_Sparse_One_Boundary(const mxArray *x0_m) const;
|
||||
void Init_Matlab_Sparse_Two_Boundaries(const mxArray* A_m, const mxArray* b_m,
|
||||
const mxArray* x0_m) const;
|
||||
tuple<SuiteSparse_long*, SuiteSparse_long*, double*, double*> Init_UMFPACK_Sparse_Two_Boundaries(
|
||||
const mxArray* x0_m,
|
||||
const vector_table_conditional_local_type& vector_table_conditional_local) const;
|
||||
bool Init_Matlab_Sparse_One_Boundary(const mxArray* A_m, const mxArray* b_m,
|
||||
const mxArray* x0_m) const;
|
||||
tuple<bool, SuiteSparse_long*, SuiteSparse_long*, double*, double*>
|
||||
Init_UMFPACK_Sparse_One_Boundary(const mxArray* x0_m) const;
|
||||
bool Simple_Init();
|
||||
void End_Gaussian_Elimination();
|
||||
tuple<bool, double, double, double, double> mnbrak(double &ax, double &bx);
|
||||
tuple<bool, double, double, double, double> mnbrak(double& ax, double& bx);
|
||||
pair<bool, double> golden(double ax, double bx, double cx, double tol);
|
||||
void Solve_ByteCode_Symbolic_Sparse_GaussianElimination(bool symbolic);
|
||||
bool Solve_ByteCode_Sparse_GaussianElimination();
|
||||
void Solve_LU_UMFPack_Two_Boundaries(SuiteSparse_long *Ap, SuiteSparse_long *Ai, double *Ax, double *b, const vector_table_conditional_local_type &vector_table_conditional_local);
|
||||
void Solve_LU_UMFPack_One_Boundary(SuiteSparse_long *Ap, SuiteSparse_long *Ai, double *Ax, double *b);
|
||||
void Solve_LU_UMFPack_Two_Boundaries(
|
||||
SuiteSparse_long* Ap, SuiteSparse_long* Ai, double* Ax, double* b,
|
||||
const vector_table_conditional_local_type& vector_table_conditional_local);
|
||||
void Solve_LU_UMFPack_One_Boundary(SuiteSparse_long* Ap, SuiteSparse_long* Ai, double* Ax,
|
||||
double* b);
|
||||
|
||||
void Solve_Matlab_GMRES(mxArray *A_m, mxArray *b_m, bool is_two_boundaries, mxArray *x0_m);
|
||||
void Solve_Matlab_BiCGStab(mxArray *A_m, mxArray *b_m, bool is_two_boundaries, mxArray *x0_m, int precond);
|
||||
void Solve_Matlab_GMRES(mxArray* A_m, mxArray* b_m, bool is_two_boundaries, mxArray* x0_m);
|
||||
void Solve_Matlab_BiCGStab(mxArray* A_m, mxArray* b_m, bool is_two_boundaries, mxArray* x0_m,
|
||||
int precond);
|
||||
void Check_and_Correct_Previous_Iteration();
|
||||
bool Simulate_One_Boundary();
|
||||
bool solve_linear(bool do_check_and_correct);
|
||||
void solve_non_linear();
|
||||
string preconditioner_print_out(string s, int preconditioner, bool ss);
|
||||
bool compare(int *save_op, int *save_opa, int *save_opaa, int beg_t, long nop4);
|
||||
bool compare(int* save_op, int* save_opa, int* save_opaa, int beg_t, long nop4);
|
||||
void Insert(int r, int c, int u_index, int lag_index);
|
||||
void Delete(int r, int c);
|
||||
pair<int, NonZeroElem *> At_Row(int r) const;
|
||||
NonZeroElem *At_Pos(int r, int c) const;
|
||||
pair<int, NonZeroElem *> At_Col(int c) const;
|
||||
pair<int, NonZeroElem *> At_Col(int c, int lag) const;
|
||||
pair<int, NonZeroElem*> At_Row(int r) const;
|
||||
NonZeroElem* At_Pos(int r, int c) const;
|
||||
pair<int, NonZeroElem*> At_Col(int c) const;
|
||||
pair<int, NonZeroElem*> At_Col(int c, int lag) const;
|
||||
int NRow(int r) const;
|
||||
int NCol(int c) const;
|
||||
int Get_u();
|
||||
|
@ -211,17 +226,17 @@ private:
|
|||
void bksub(int tbreak, int last_period);
|
||||
void simple_bksub();
|
||||
// Computes Aᵀ where A is are sparse. The result is sparse.
|
||||
static mxArray *Sparse_transpose(const mxArray *A_m);
|
||||
static mxArray* Sparse_transpose(const mxArray* A_m);
|
||||
// Computes Aᵀ·B where A and B are sparse. The result is sparse.
|
||||
static mxArray *Sparse_mult_SAT_SB(const mxArray *A_m, const mxArray *B_m);
|
||||
static mxArray* Sparse_mult_SAT_SB(const mxArray* A_m, const mxArray* B_m);
|
||||
// Computes Aᵀ·B where A is sparse and B is dense. The result is sparse.
|
||||
static mxArray *Sparse_mult_SAT_B(const mxArray *A_m, const mxArray *B_m);
|
||||
static mxArray* Sparse_mult_SAT_B(const mxArray* A_m, const mxArray* B_m);
|
||||
// Computes Aᵀ·B where A is sparse and B is dense. The result is dense.
|
||||
static mxArray *mult_SAT_B(const mxArray *A_m, const mxArray *B_m);
|
||||
static mxArray* mult_SAT_B(const mxArray* A_m, const mxArray* B_m);
|
||||
// Computes A−B where A and B are sparse. The result is sparse.
|
||||
static mxArray *Sparse_subtract_SA_SB(const mxArray *A_m, const mxArray *B_m);
|
||||
static mxArray* Sparse_subtract_SA_SB(const mxArray* A_m, const mxArray* B_m);
|
||||
// Computes A−B where A and B are dense. The result is dense.
|
||||
static mxArray *subtract_A_B(const mxArray *A_m, const mxArray *B_m);
|
||||
static mxArray* subtract_A_B(const mxArray* A_m, const mxArray* B_m);
|
||||
|
||||
void compute_block_time(int my_Per_u_, bool evaluate, bool no_derivatives);
|
||||
bool compute_complete(bool no_derivatives);
|
||||
|
@ -229,28 +244,33 @@ private:
|
|||
pair<bool, double> compute_complete(double lambda);
|
||||
|
||||
public:
|
||||
Interpreter(Evaluate &evaluator_arg, double *params_arg, double *y_arg, double *ya_arg, double *x_arg, double *steady_y_arg,
|
||||
double *direction_arg, int y_size_arg,
|
||||
int nb_row_x_arg, int periods_arg, int y_kmin_arg, int y_kmax_arg,
|
||||
int maxit_arg_, double solve_tolf_arg, double markowitz_c_arg,
|
||||
int minimal_solving_periods_arg, int stack_solve_algo_arg, int solve_algo_arg,
|
||||
bool print_arg, const mxArray *GlobalTemporaryTerms_arg,
|
||||
bool steady_state_arg, bool block_decomposed_arg, int col_x_arg, int col_y_arg, const BasicSymbolTable &symbol_table_arg, int verbosity_arg);
|
||||
pair<bool, vector<int>> extended_path(const string &file_name, bool evaluate, int block, int nb_periods, const vector<s_plan> &sextended_path, const vector<s_plan> &sconstrained_extended_path, const vector<string> &dates, const table_conditional_global_type &table_conditional_global);
|
||||
pair<bool, vector<int>> compute_blocks(const string &file_name, bool evaluate, int block);
|
||||
Interpreter(Evaluate& evaluator_arg, double* params_arg, double* y_arg, double* ya_arg,
|
||||
double* x_arg, double* steady_y_arg, double* direction_arg, int y_size_arg,
|
||||
int nb_row_x_arg, int periods_arg, int y_kmin_arg, int y_kmax_arg, int maxit_arg_,
|
||||
double solve_tolf_arg, double markowitz_c_arg, int minimal_solving_periods_arg,
|
||||
int stack_solve_algo_arg, int solve_algo_arg, bool print_arg,
|
||||
const mxArray* GlobalTemporaryTerms_arg, bool steady_state_arg,
|
||||
bool block_decomposed_arg, int col_x_arg, int col_y_arg,
|
||||
const BasicSymbolTable& symbol_table_arg, int verbosity_arg);
|
||||
pair<bool, vector<int>>
|
||||
extended_path(const string& file_name, bool evaluate, int block, int nb_periods,
|
||||
const vector<s_plan>& sextended_path,
|
||||
const vector<s_plan>& sconstrained_extended_path, const vector<string>& dates,
|
||||
const table_conditional_global_type& table_conditional_global);
|
||||
pair<bool, vector<int>> compute_blocks(const string& file_name, bool evaluate, int block);
|
||||
void Close_SaveCode();
|
||||
|
||||
inline mxArray *
|
||||
inline mxArray*
|
||||
get_jacob(int block_num) const
|
||||
{
|
||||
return jacobian_block[block_num];
|
||||
}
|
||||
inline mxArray *
|
||||
inline mxArray*
|
||||
get_jacob_exo(int block_num) const
|
||||
{
|
||||
return jacobian_exo_block[block_num];
|
||||
}
|
||||
inline mxArray *
|
||||
inline mxArray*
|
||||
get_jacob_exo_det(int block_num) const
|
||||
{
|
||||
return jacobian_det_exo_block[block_num];
|
||||
|
@ -260,7 +280,7 @@ public:
|
|||
{
|
||||
return residual;
|
||||
}
|
||||
inline mxArray *
|
||||
inline mxArray*
|
||||
get_Temporary_Terms() const
|
||||
{
|
||||
return GlobalTemporaryTerms;
|
||||
|
|
|
@ -51,17 +51,18 @@ Mem_Mngr::init_CHUNK_BLCK_SIZE(int u_count)
|
|||
CHUNK_BLCK_SIZE = u_count;
|
||||
}
|
||||
|
||||
NonZeroElem *
|
||||
NonZeroElem*
|
||||
Mem_Mngr::mxMalloc_NZE()
|
||||
{
|
||||
long unsigned int i;
|
||||
if (!Chunk_Stack.empty()) /*An unused block of memory available inside the heap*/
|
||||
{
|
||||
NonZeroElem *p1 = Chunk_Stack.back();
|
||||
NonZeroElem* p1 = Chunk_Stack.back();
|
||||
Chunk_Stack.pop_back();
|
||||
return p1;
|
||||
}
|
||||
else if (CHUNK_heap_pos < CHUNK_SIZE) /*there is enough allocated memory space available we keep it at the top of the heap*/
|
||||
else if (CHUNK_heap_pos < CHUNK_SIZE) /*there is enough allocated memory space available we keep
|
||||
it at the top of the heap*/
|
||||
{
|
||||
i = CHUNK_heap_pos++;
|
||||
return NZE_Mem_add[i];
|
||||
|
@ -70,43 +71,54 @@ Mem_Mngr::mxMalloc_NZE()
|
|||
{
|
||||
CHUNK_SIZE += CHUNK_BLCK_SIZE;
|
||||
Nb_CHUNK++;
|
||||
NZE_Mem = static_cast<NonZeroElem *>(mxMalloc(CHUNK_BLCK_SIZE*sizeof(NonZeroElem))); /*The block of memory allocated*/
|
||||
test_mxMalloc(NZE_Mem, __LINE__, __FILE__, __func__, CHUNK_BLCK_SIZE*sizeof(NonZeroElem));
|
||||
NZE_Mem = static_cast<NonZeroElem*>(
|
||||
mxMalloc(CHUNK_BLCK_SIZE * sizeof(NonZeroElem))); /*The block of memory allocated*/
|
||||
test_mxMalloc(NZE_Mem, __LINE__, __FILE__, __func__, CHUNK_BLCK_SIZE * sizeof(NonZeroElem));
|
||||
NZE_Mem_Allocated.push_back(NZE_Mem);
|
||||
if (!NZE_Mem)
|
||||
mexPrintf("Not enough memory available\n");
|
||||
if (NZE_Mem_add)
|
||||
{
|
||||
NZE_Mem_add = static_cast<NonZeroElem **>(mxRealloc(NZE_Mem_add, CHUNK_SIZE*sizeof(NonZeroElem *))); /*We have to redefine the size of pointer on the memory*/
|
||||
test_mxMalloc(NZE_Mem_add, __LINE__, __FILE__, __func__, CHUNK_SIZE*sizeof(NonZeroElem *));
|
||||
NZE_Mem_add = static_cast<NonZeroElem**>(mxRealloc(
|
||||
NZE_Mem_add,
|
||||
CHUNK_SIZE
|
||||
* sizeof(
|
||||
NonZeroElem*))); /*We have to redefine the size of pointer on the memory*/
|
||||
test_mxMalloc(NZE_Mem_add, __LINE__, __FILE__, __func__,
|
||||
CHUNK_SIZE * sizeof(NonZeroElem*));
|
||||
}
|
||||
else
|
||||
{
|
||||
NZE_Mem_add = static_cast<NonZeroElem **>(mxMalloc(CHUNK_SIZE*sizeof(NonZeroElem *))); /*We have to define the size of pointer on the memory*/
|
||||
test_mxMalloc(NZE_Mem_add, __LINE__, __FILE__, __func__, CHUNK_SIZE*sizeof(NonZeroElem *));
|
||||
NZE_Mem_add = static_cast<NonZeroElem**>(mxMalloc(
|
||||
CHUNK_SIZE
|
||||
* sizeof(NonZeroElem*))); /*We have to define the size of pointer on the memory*/
|
||||
test_mxMalloc(NZE_Mem_add, __LINE__, __FILE__, __func__,
|
||||
CHUNK_SIZE * sizeof(NonZeroElem*));
|
||||
}
|
||||
|
||||
if (!NZE_Mem_add)
|
||||
mexPrintf("Not enough memory available\n");
|
||||
for (i = CHUNK_heap_pos; i < CHUNK_SIZE; i++)
|
||||
NZE_Mem_add[i] = const_cast<NonZeroElem *>(NZE_Mem+(i-CHUNK_heap_pos));
|
||||
NZE_Mem_add[i] = const_cast<NonZeroElem*>(NZE_Mem + (i - CHUNK_heap_pos));
|
||||
i = CHUNK_heap_pos++;
|
||||
return NZE_Mem_add[i];
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Mem_Mngr::mxFree_NZE(void *pos)
|
||||
Mem_Mngr::mxFree_NZE(void* pos)
|
||||
{
|
||||
unsigned int i;
|
||||
ptrdiff_t gap;
|
||||
for (i = 0; i < Nb_CHUNK; i++)
|
||||
{
|
||||
gap = (reinterpret_cast<ptrdiff_t>(pos)-reinterpret_cast<ptrdiff_t>(NZE_Mem_add[i*CHUNK_BLCK_SIZE]))/sizeof(NonZeroElem);
|
||||
gap = (reinterpret_cast<ptrdiff_t>(pos)
|
||||
- reinterpret_cast<ptrdiff_t>(NZE_Mem_add[i * CHUNK_BLCK_SIZE]))
|
||||
/ sizeof(NonZeroElem);
|
||||
if (gap < CHUNK_BLCK_SIZE && gap >= 0)
|
||||
break;
|
||||
}
|
||||
Chunk_Stack.push_back(static_cast<NonZeroElem *>(pos));
|
||||
Chunk_Stack.push_back(static_cast<NonZeroElem*>(pos));
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -20,9 +20,9 @@
|
|||
#ifndef _MEM_MNGR_HH
|
||||
#define _MEM_MNGR_HH
|
||||
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <fstream>
|
||||
|
||||
#include "ErrorHandling.hh"
|
||||
|
||||
|
@ -35,26 +35,27 @@ struct NonZeroElem
|
|||
NonZeroElem *NZE_R_N, *NZE_C_N;
|
||||
};
|
||||
|
||||
using v_NonZeroElem = vector<NonZeroElem *>;
|
||||
using v_NonZeroElem = vector<NonZeroElem*>;
|
||||
|
||||
class Mem_Mngr
|
||||
{
|
||||
public:
|
||||
void init_Mem();
|
||||
void mxFree_NZE(void *pos);
|
||||
NonZeroElem *mxMalloc_NZE();
|
||||
void mxFree_NZE(void* pos);
|
||||
NonZeroElem* mxMalloc_NZE();
|
||||
void init_CHUNK_BLCK_SIZE(int u_count);
|
||||
void Free_All();
|
||||
Mem_Mngr();
|
||||
void fixe_file_name(string filename_arg);
|
||||
bool swp_f;
|
||||
|
||||
private:
|
||||
v_NonZeroElem Chunk_Stack;
|
||||
unsigned int CHUNK_SIZE, CHUNK_BLCK_SIZE, Nb_CHUNK;
|
||||
unsigned int CHUNK_heap_pos;
|
||||
NonZeroElem **NZE_Mem_add;
|
||||
NonZeroElem *NZE_Mem;
|
||||
vector<NonZeroElem *> NZE_Mem_Allocated;
|
||||
NonZeroElem** NZE_Mem_add;
|
||||
NonZeroElem* NZE_Mem;
|
||||
vector<NonZeroElem*> NZE_Mem_Allocated;
|
||||
int swp_f_b;
|
||||
fstream SaveCode_swp;
|
||||
string filename_mem;
|
||||
|
|
|
@ -17,20 +17,20 @@
|
|||
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <type_traits>
|
||||
#include <algorithm>
|
||||
|
||||
#include "Interpreter.hh"
|
||||
#include "ErrorHandling.hh"
|
||||
#include "Interpreter.hh"
|
||||
|
||||
string
|
||||
Get_Argument(const mxArray *prhs)
|
||||
Get_Argument(const mxArray* prhs)
|
||||
{
|
||||
const mxArray *mxa = prhs;
|
||||
const mxArray* mxa = prhs;
|
||||
auto buflen = mwSize(mxGetM(mxa) * mxGetN(mxa) + 1);
|
||||
char *first_argument;
|
||||
first_argument = static_cast<char *>(mxCalloc(buflen, sizeof(char)));
|
||||
char* first_argument;
|
||||
first_argument = static_cast<char*>(mxCalloc(buflen, sizeof(char)));
|
||||
size_t status = mxGetString(mxa, first_argument, buflen);
|
||||
if (status != 0)
|
||||
mexWarnMsgTxt("Not enough space. The first argument is truncated.");
|
||||
|
@ -49,20 +49,14 @@ deblank(string x)
|
|||
}
|
||||
|
||||
void
|
||||
Get_Arguments_and_global_variables(int nrhs,
|
||||
const mxArray *prhs[],
|
||||
double *yd[], size_t &row_y, size_t &col_y,
|
||||
double *xd[], size_t &row_x, size_t &col_x,
|
||||
double *params[],
|
||||
double *steady_yd[], size_t &steady_row_y, size_t &steady_col_y,
|
||||
int &periods,
|
||||
mxArray **block_structur,
|
||||
bool &steady_state, bool &block_decomposed,
|
||||
bool &evaluate, int &block,
|
||||
const mxArray **M_, const mxArray **options_,
|
||||
bool &print,
|
||||
const mxArray **GlobalTemporaryTerms,
|
||||
bool *extended_path, mxArray **ep_struct)
|
||||
Get_Arguments_and_global_variables(int nrhs, const mxArray* prhs[], double* yd[], size_t& row_y,
|
||||
size_t& col_y, double* xd[], size_t& row_x, size_t& col_x,
|
||||
double* params[], double* steady_yd[], size_t& steady_row_y,
|
||||
size_t& steady_col_y, int& periods, mxArray** block_structur,
|
||||
bool& steady_state, bool& block_decomposed, bool& evaluate,
|
||||
int& block, const mxArray** M_, const mxArray** options_,
|
||||
bool& print, const mxArray** GlobalTemporaryTerms,
|
||||
bool* extended_path, mxArray** ep_struct)
|
||||
{
|
||||
int count_array_argument {0};
|
||||
*extended_path = false;
|
||||
|
@ -115,82 +109,83 @@ Get_Arguments_and_global_variables(int nrhs,
|
|||
}
|
||||
count_array_argument++;
|
||||
}
|
||||
else if (Get_Argument(prhs[i]) == "static")
|
||||
steady_state = true;
|
||||
else if (Get_Argument(prhs[i]) == "dynamic")
|
||||
steady_state = false;
|
||||
else if (Get_Argument(prhs[i]) == "block_decomposed")
|
||||
block_decomposed = true;
|
||||
else if (Get_Argument(prhs[i]) == "evaluate")
|
||||
evaluate = true;
|
||||
else if (Get_Argument(prhs[i]) == "print")
|
||||
print = true;
|
||||
else
|
||||
if (Get_Argument(prhs[i]) == "static")
|
||||
steady_state = true;
|
||||
else if (Get_Argument(prhs[i]) == "dynamic")
|
||||
steady_state = false;
|
||||
else if (Get_Argument(prhs[i]) == "block_decomposed")
|
||||
block_decomposed = true;
|
||||
else if (Get_Argument(prhs[i]) == "evaluate")
|
||||
evaluate = true;
|
||||
else if (Get_Argument(prhs[i]) == "print")
|
||||
print = true;
|
||||
else
|
||||
{
|
||||
if (Get_Argument(prhs[i]).substr(0, 6) == "block=")
|
||||
{
|
||||
try
|
||||
{
|
||||
block = stoi(Get_Argument(prhs[i]).substr(6))-1;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
throw FatalException{"ERROR: incorrect syntax for the 'block=' option"};
|
||||
}
|
||||
}
|
||||
else if (Get_Argument(prhs[i]).substr(0, 13) == "extended_path")
|
||||
{
|
||||
*extended_path = true;
|
||||
if ((i+1) >= nrhs)
|
||||
*ep_struct = nullptr;
|
||||
else
|
||||
{
|
||||
*ep_struct = mxDuplicateArray(prhs[i + 1]);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
else
|
||||
throw FatalException{"In main, unknown argument : " + Get_Argument(prhs[i])};
|
||||
}
|
||||
{
|
||||
if (Get_Argument(prhs[i]).substr(0, 6) == "block=")
|
||||
{
|
||||
try
|
||||
{
|
||||
block = stoi(Get_Argument(prhs[i]).substr(6)) - 1;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
throw FatalException {"ERROR: incorrect syntax for the 'block=' option"};
|
||||
}
|
||||
}
|
||||
else if (Get_Argument(prhs[i]).substr(0, 13) == "extended_path")
|
||||
{
|
||||
*extended_path = true;
|
||||
if ((i + 1) >= nrhs)
|
||||
*ep_struct = nullptr;
|
||||
else
|
||||
{
|
||||
*ep_struct = mxDuplicateArray(prhs[i + 1]);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
else
|
||||
throw FatalException {"In main, unknown argument : " + Get_Argument(prhs[i])};
|
||||
}
|
||||
}
|
||||
if (steady_state)
|
||||
{
|
||||
if (count_array_argument < 5)
|
||||
throw FatalException{"In a static context, the following arguments have to be indicated: M_, options_, y, x, params"};
|
||||
throw FatalException {"In a static context, the following arguments have to be indicated: "
|
||||
"M_, options_, y, x, params"};
|
||||
if (count_array_argument < 7)
|
||||
periods = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (count_array_argument < 7)
|
||||
throw FatalException{"In a dynamic context, the following arguments have to be indicated: M_, options_, y, x, params, steady_state, periods"};
|
||||
throw FatalException {"In a dynamic context, the following arguments have to be indicated: "
|
||||
"M_, options_, y, x, params, steady_state, periods"};
|
||||
}
|
||||
}
|
||||
|
||||
/* The gateway routine */
|
||||
void
|
||||
mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
||||
mexFunction(int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[])
|
||||
{
|
||||
const mxArray *M_, *options_;
|
||||
const mxArray *GlobalTemporaryTerms {nullptr};
|
||||
mxArray *block_structur = nullptr;
|
||||
const mxArray* GlobalTemporaryTerms {nullptr};
|
||||
mxArray* block_structur = nullptr;
|
||||
size_t i, row_y = 0, col_y = 0, row_x = 0, col_x = 0;
|
||||
size_t steady_row_y, steady_col_y;
|
||||
int y_kmin = 0, y_kmax = 0;
|
||||
int periods {1};
|
||||
double *direction;
|
||||
double* direction;
|
||||
bool steady_state = false;
|
||||
bool block_decomposed {false};
|
||||
bool evaluate = false;
|
||||
int block = -1;
|
||||
double *params = nullptr;
|
||||
double* params = nullptr;
|
||||
double *yd = nullptr, *xd = nullptr;
|
||||
bool print = false; // Whether the “print” command is requested
|
||||
int verbosity {1}; // Corresponds to options_.verbosity
|
||||
double *steady_yd = nullptr;
|
||||
int verbosity {1}; // Corresponds to options_.verbosity
|
||||
double* steady_yd = nullptr;
|
||||
bool extended_path;
|
||||
mxArray *extended_path_struct;
|
||||
mxArray* extended_path_struct;
|
||||
|
||||
table_conditional_local_type conditional_local;
|
||||
vector<s_plan> sextended_path, sconditional_extended_path;
|
||||
|
@ -206,19 +201,12 @@ mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
|||
|
||||
try
|
||||
{
|
||||
Get_Arguments_and_global_variables(nrhs, prhs,
|
||||
&yd, row_y, col_y,
|
||||
&xd, row_x, col_x,
|
||||
¶ms,
|
||||
&steady_yd, steady_row_y, steady_col_y,
|
||||
periods,
|
||||
&block_structur,
|
||||
steady_state, block_decomposed, evaluate, block,
|
||||
&M_, &options_,
|
||||
print, &GlobalTemporaryTerms,
|
||||
&extended_path, &extended_path_struct);
|
||||
Get_Arguments_and_global_variables(
|
||||
nrhs, prhs, &yd, row_y, col_y, &xd, row_x, col_x, ¶ms, &steady_yd, steady_row_y,
|
||||
steady_col_y, periods, &block_structur, steady_state, block_decomposed, evaluate, block,
|
||||
&M_, &options_, print, &GlobalTemporaryTerms, &extended_path, &extended_path_struct);
|
||||
}
|
||||
catch (GeneralException &feh)
|
||||
catch (GeneralException& feh)
|
||||
{
|
||||
mexErrMsgTxt(feh.message.c_str());
|
||||
}
|
||||
|
@ -226,57 +214,68 @@ mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
|||
mexPrintf("**************************************\n");
|
||||
#endif
|
||||
|
||||
BasicSymbolTable symbol_table{M_};
|
||||
BasicSymbolTable symbol_table {M_};
|
||||
vector<string> dates;
|
||||
|
||||
if (extended_path)
|
||||
{
|
||||
if (!extended_path_struct)
|
||||
mexErrMsgTxt("The 'extended_path' option must be followed by the extended_path descriptor");
|
||||
mxArray *date_str = mxGetField(extended_path_struct, 0, "date_str");
|
||||
mxArray* date_str = mxGetField(extended_path_struct, 0, "date_str");
|
||||
if (!date_str)
|
||||
mexErrMsgTxt("The extended_path description structure does not contain the member: date_str");
|
||||
mexErrMsgTxt(
|
||||
"The extended_path description structure does not contain the member: date_str");
|
||||
int nb_periods = mxGetM(date_str) * mxGetN(date_str);
|
||||
|
||||
mxArray *constrained_vars_ = mxGetField(extended_path_struct, 0, "constrained_vars_");
|
||||
mxArray* constrained_vars_ = mxGetField(extended_path_struct, 0, "constrained_vars_");
|
||||
if (!constrained_vars_)
|
||||
mexErrMsgTxt("The extended_path description structure does not contain the member: constrained_vars_");
|
||||
mxArray *constrained_paths_ = mxGetField(extended_path_struct, 0, "constrained_paths_");
|
||||
mexErrMsgTxt("The extended_path description structure does not contain the member: "
|
||||
"constrained_vars_");
|
||||
mxArray* constrained_paths_ = mxGetField(extended_path_struct, 0, "constrained_paths_");
|
||||
if (!constrained_paths_)
|
||||
mexErrMsgTxt("The extended_path description structure does not contain the member: constrained_paths_");
|
||||
mxArray *constrained_int_date_ = mxGetField(extended_path_struct, 0, "constrained_int_date_");
|
||||
mexErrMsgTxt("The extended_path description structure does not contain the member: "
|
||||
"constrained_paths_");
|
||||
mxArray* constrained_int_date_ = mxGetField(extended_path_struct, 0, "constrained_int_date_");
|
||||
if (!constrained_int_date_)
|
||||
mexErrMsgTxt("The extended_path description structure does not contain the member: constrained_int_date_");
|
||||
mxArray *constrained_perfect_foresight_ = mxGetField(extended_path_struct, 0, "constrained_perfect_foresight_");
|
||||
mexErrMsgTxt("The extended_path description structure does not contain the member: "
|
||||
"constrained_int_date_");
|
||||
mxArray* constrained_perfect_foresight_
|
||||
= mxGetField(extended_path_struct, 0, "constrained_perfect_foresight_");
|
||||
if (!constrained_perfect_foresight_)
|
||||
mexErrMsgTxt("The extended_path description structure does not contain the member: constrained_perfect_foresight_");
|
||||
mxArray *shock_var_ = mxGetField(extended_path_struct, 0, "shock_vars_");
|
||||
mexErrMsgTxt("The extended_path description structure does not contain the member: "
|
||||
"constrained_perfect_foresight_");
|
||||
mxArray* shock_var_ = mxGetField(extended_path_struct, 0, "shock_vars_");
|
||||
if (!shock_var_)
|
||||
mexErrMsgTxt("The extended_path description structure does not contain the member: shock_vars_");
|
||||
mxArray *shock_paths_ = mxGetField(extended_path_struct, 0, "shock_paths_");
|
||||
mexErrMsgTxt(
|
||||
"The extended_path description structure does not contain the member: shock_vars_");
|
||||
mxArray* shock_paths_ = mxGetField(extended_path_struct, 0, "shock_paths_");
|
||||
if (!shock_paths_)
|
||||
mexErrMsgTxt("The extended_path description structure does not contain the member: shock_paths_");
|
||||
mxArray *shock_int_date_ = mxGetField(extended_path_struct, 0, "shock_int_date_");
|
||||
mexErrMsgTxt(
|
||||
"The extended_path description structure does not contain the member: shock_paths_");
|
||||
mxArray* shock_int_date_ = mxGetField(extended_path_struct, 0, "shock_int_date_");
|
||||
if (!shock_int_date_)
|
||||
mexErrMsgTxt("The extended_path description structure does not contain the member: shock_int_date_");
|
||||
mxArray *shock_str_date_ = mxGetField(extended_path_struct, 0, "shock_str_date_");
|
||||
mexErrMsgTxt(
|
||||
"The extended_path description structure does not contain the member: shock_int_date_");
|
||||
mxArray* shock_str_date_ = mxGetField(extended_path_struct, 0, "shock_str_date_");
|
||||
if (!shock_str_date_)
|
||||
mexErrMsgTxt("The extended_path description structure does not contain the member: shock_str_date_");
|
||||
mexErrMsgTxt(
|
||||
"The extended_path description structure does not contain the member: shock_str_date_");
|
||||
int nb_constrained = mxGetM(constrained_vars_) * mxGetN(constrained_vars_);
|
||||
int nb_controlled = 0;
|
||||
mxArray *options_cond_fcst_ = mxGetField(extended_path_struct, 0, "options_cond_fcst_");
|
||||
mxArray *controlled_varexo = nullptr;
|
||||
mxArray* options_cond_fcst_ = mxGetField(extended_path_struct, 0, "options_cond_fcst_");
|
||||
mxArray* controlled_varexo = nullptr;
|
||||
if (options_cond_fcst_)
|
||||
{
|
||||
controlled_varexo = mxGetField(options_cond_fcst_, 0, "controlled_varexo");
|
||||
nb_controlled = mxGetM(controlled_varexo) * mxGetN(controlled_varexo);
|
||||
if (nb_controlled != nb_constrained)
|
||||
mexErrMsgTxt("The number of exogenized variables and the number of exogenous controlled variables should be equal.");
|
||||
mexErrMsgTxt("The number of exogenized variables and the number of exogenous "
|
||||
"controlled variables should be equal.");
|
||||
}
|
||||
double *controlled_varexo_value = nullptr;
|
||||
double* controlled_varexo_value = nullptr;
|
||||
if (controlled_varexo)
|
||||
controlled_varexo_value = mxGetPr(controlled_varexo);
|
||||
double *constrained_var_value = mxGetPr(constrained_vars_);
|
||||
double* constrained_var_value = mxGetPr(constrained_vars_);
|
||||
sconditional_extended_path.resize(nb_constrained);
|
||||
max_periods = 0;
|
||||
if (nb_constrained)
|
||||
|
@ -302,16 +301,19 @@ mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
|||
{
|
||||
sconditional_extended_path[i].exo_num = ceil(constrained_var_value[i]);
|
||||
sconditional_extended_path[i].var_num = ceil(controlled_varexo_value[i]);
|
||||
mxArray *Array_constrained_paths_ = mxGetCell(constrained_paths_, i);
|
||||
double *specific_constrained_paths_ = mxGetPr(Array_constrained_paths_);
|
||||
double *specific_constrained_int_date_ = mxGetPr(mxGetCell(constrained_int_date_, i));
|
||||
int nb_local_periods = mxGetM(Array_constrained_paths_) * mxGetN(Array_constrained_paths_);
|
||||
int *constrained_int_date = static_cast<int *>(mxMalloc(nb_local_periods * sizeof(int)));
|
||||
test_mxMalloc(constrained_int_date, __LINE__, __FILE__, __func__, nb_local_periods * sizeof(int));
|
||||
mxArray* Array_constrained_paths_ = mxGetCell(constrained_paths_, i);
|
||||
double* specific_constrained_paths_ = mxGetPr(Array_constrained_paths_);
|
||||
double* specific_constrained_int_date_ = mxGetPr(mxGetCell(constrained_int_date_, i));
|
||||
int nb_local_periods
|
||||
= mxGetM(Array_constrained_paths_) * mxGetN(Array_constrained_paths_);
|
||||
int* constrained_int_date = static_cast<int*>(mxMalloc(nb_local_periods * sizeof(int)));
|
||||
test_mxMalloc(constrained_int_date, __LINE__, __FILE__, __func__,
|
||||
nb_local_periods * sizeof(int));
|
||||
if (nb_periods < nb_local_periods)
|
||||
mexErrMsgTxt(("The total number of simulation periods (" + to_string(nb_periods)
|
||||
+ ") is lesser than the number of periods in the shock definitions ("
|
||||
+ to_string(nb_local_periods)).c_str());
|
||||
+ to_string(nb_local_periods))
|
||||
.c_str());
|
||||
|
||||
sconditional_extended_path[i].per_value.resize(nb_local_periods);
|
||||
sconditional_extended_path[i].value.resize(nb_periods);
|
||||
|
@ -324,47 +326,55 @@ mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
|||
conditional_local.var_exo = sconditional_extended_path[i].var_num - 1;
|
||||
conditional_local.var_endo = sconditional_extended_path[i].exo_num - 1;
|
||||
conditional_local.constrained_value = specific_constrained_paths_[j];
|
||||
table_conditional_global[constrained_int_date[j]][sconditional_extended_path[i].exo_num - 1] = conditional_local;
|
||||
sconditional_extended_path[i].per_value[j] = { constrained_int_date[j], specific_constrained_paths_[j] };
|
||||
sconditional_extended_path[i].value[constrained_int_date[j]] = specific_constrained_paths_[j];
|
||||
table_conditional_global[constrained_int_date[j]]
|
||||
[sconditional_extended_path[i].exo_num - 1]
|
||||
= conditional_local;
|
||||
sconditional_extended_path[i].per_value[j]
|
||||
= {constrained_int_date[j], specific_constrained_paths_[j]};
|
||||
sconditional_extended_path[i].value[constrained_int_date[j]]
|
||||
= specific_constrained_paths_[j];
|
||||
max_periods = max(max_periods, constrained_int_date[j] + 1);
|
||||
}
|
||||
mxFree(constrained_int_date);
|
||||
}
|
||||
vector_table_conditional_local_type vv = table_conditional_global[0];
|
||||
double *shock_var_value = mxGetPr(shock_var_);
|
||||
double* shock_var_value = mxGetPr(shock_var_);
|
||||
int nb_shocks = mxGetM(shock_var_) * mxGetN(shock_var_);
|
||||
sextended_path.resize(nb_shocks);
|
||||
for (int i = 0; i < nb_shocks; i++)
|
||||
{
|
||||
sextended_path[i].exo_num = ceil(shock_var_value[i]);
|
||||
mxArray *Array_shock_paths_ = mxGetCell(shock_paths_, i);
|
||||
double *specific_shock_paths_ = mxGetPr(Array_shock_paths_);
|
||||
double *specific_shock_int_date_ = mxGetPr(mxGetCell(shock_int_date_, i));
|
||||
mxArray* Array_shock_paths_ = mxGetCell(shock_paths_, i);
|
||||
double* specific_shock_paths_ = mxGetPr(Array_shock_paths_);
|
||||
double* specific_shock_int_date_ = mxGetPr(mxGetCell(shock_int_date_, i));
|
||||
int nb_local_periods = mxGetM(Array_shock_paths_) * mxGetN(Array_shock_paths_);
|
||||
if (nb_periods < nb_local_periods)
|
||||
mexErrMsgTxt(("The total number of simulation periods (" + to_string(nb_periods)
|
||||
+ ") is lesser than the number of periods in the shock definitions ("
|
||||
+ to_string(nb_local_periods)).c_str());
|
||||
+ to_string(nb_local_periods))
|
||||
.c_str());
|
||||
sextended_path[i].per_value.resize(nb_local_periods);
|
||||
sextended_path[i].value.resize(nb_periods);
|
||||
for (int j = 0; j < nb_periods; j++)
|
||||
sextended_path[i].value[j] = 0;
|
||||
for (int j = 0; j < nb_local_periods; j++)
|
||||
{
|
||||
sextended_path[i].per_value[j] = { static_cast<int>(specific_shock_int_date_[j]), specific_shock_paths_[j] };
|
||||
sextended_path[i].value[static_cast<int>(specific_shock_int_date_[j]-1)] = specific_shock_paths_[j];
|
||||
sextended_path[i].per_value[j]
|
||||
= {static_cast<int>(specific_shock_int_date_[j]), specific_shock_paths_[j]};
|
||||
sextended_path[i].value[static_cast<int>(specific_shock_int_date_[j] - 1)]
|
||||
= specific_shock_paths_[j];
|
||||
max_periods = max(max_periods, static_cast<int>(specific_shock_int_date_[j]));
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < nb_periods; i++)
|
||||
{
|
||||
int buflen = mxGetNumberOfElements(mxGetCell(date_str, i)) + 1;
|
||||
char *buf = static_cast<char *>(mxCalloc(buflen, sizeof(char)));
|
||||
char* buf = static_cast<char*>(mxCalloc(buflen, sizeof(char)));
|
||||
int info = mxGetString(mxGetCell(date_str, i), buf, buflen);
|
||||
if (info)
|
||||
mexErrMsgTxt("Can not allocated memory to store the date_str in the extended path descriptor");
|
||||
dates.emplace_back(buf); //string(Dates[i]);
|
||||
mexErrMsgTxt(
|
||||
"Can not allocated memory to store the date_str in the extended path descriptor");
|
||||
dates.emplace_back(buf); // string(Dates[i]);
|
||||
mxFree(buf);
|
||||
}
|
||||
}
|
||||
|
@ -401,7 +411,7 @@ mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
|||
if (field < 0)
|
||||
mexErrMsgTxt("steady is not a field of options_");
|
||||
}
|
||||
mxArray *temporarystruct {mxGetFieldByNumber(options_, 0, field)};
|
||||
mxArray* temporarystruct {mxGetFieldByNumber(options_, 0, field)};
|
||||
|
||||
field = mxGetFieldNumber(temporarystruct, "maxit");
|
||||
if (field < 0)
|
||||
|
@ -433,8 +443,7 @@ mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
|||
|
||||
/* Solver tolerance with respect to the residual. Equals options_.solve_tolf
|
||||
in the static case, or options_.dynatol.f in the dynamic case */
|
||||
double solve_tolf { [options_, steady_state]
|
||||
{
|
||||
double solve_tolf {[options_, steady_state] {
|
||||
if (steady_state)
|
||||
{
|
||||
int field {mxGetFieldNumber(options_, "solve_tolf")};
|
||||
|
@ -447,21 +456,21 @@ mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
|||
int field {mxGetFieldNumber(options_, "dynatol")};
|
||||
if (field < 0)
|
||||
mexErrMsgTxt("dynatol is not a field of options_");
|
||||
mxArray *dynatol {mxGetFieldByNumber(options_, 0, field)};
|
||||
mxArray* dynatol {mxGetFieldByNumber(options_, 0, field)};
|
||||
field = mxGetFieldNumber(dynatol, "f");
|
||||
if (field < 0)
|
||||
mexErrMsgTxt("f is not a field of options_.dynatol");
|
||||
return *mxGetPr(mxGetFieldByNumber(dynatol, 0, field));
|
||||
}
|
||||
}() };
|
||||
}()};
|
||||
|
||||
field = mxGetFieldNumber(M_, "fname");
|
||||
if (field < 0)
|
||||
mexErrMsgTxt("fname is not a field of M_");
|
||||
mxArray *mxa {mxGetFieldByNumber(M_, 0, field)};
|
||||
mxArray* mxa {mxGetFieldByNumber(M_, 0, field)};
|
||||
|
||||
size_t buflen = mxGetM(mxa) * mxGetN(mxa) + 1;
|
||||
char *fname = static_cast<char *>(mxCalloc(buflen+1, sizeof(char)));
|
||||
char* fname = static_cast<char*>(mxCalloc(buflen + 1, sizeof(char)));
|
||||
size_t status = mxGetString(mxa, fname, static_cast<int>(buflen));
|
||||
fname[buflen] = ' ';
|
||||
if (status != 0)
|
||||
|
@ -476,43 +485,68 @@ mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
|||
mexErrMsgTxt("Bytecode: Can't use option stack_solve_algo=1 or 6");
|
||||
|
||||
if (steady_state && !evaluate && !print && (solve_algo < 5 || solve_algo > 8))
|
||||
mexErrMsgTxt("Bytecode: solve_algo must be between 5 and 8 when using the internal steady state solver");
|
||||
mexErrMsgTxt(
|
||||
"Bytecode: solve_algo must be between 5 and 8 when using the internal steady state solver");
|
||||
|
||||
size_t size_of_direction = col_y*row_y*sizeof(double);
|
||||
auto *y = static_cast<double *>(mxMalloc(size_of_direction));
|
||||
size_t size_of_direction = col_y * row_y * sizeof(double);
|
||||
auto* y = static_cast<double*>(mxMalloc(size_of_direction));
|
||||
test_mxMalloc(y, __LINE__, __FILE__, __func__, size_of_direction);
|
||||
auto *ya = static_cast<double *>(mxMalloc(size_of_direction));
|
||||
auto* ya = static_cast<double*>(mxMalloc(size_of_direction));
|
||||
test_mxMalloc(ya, __LINE__, __FILE__, __func__, size_of_direction);
|
||||
direction = static_cast<double *>(mxMalloc(size_of_direction));
|
||||
direction = static_cast<double*>(mxMalloc(size_of_direction));
|
||||
test_mxMalloc(direction, __LINE__, __FILE__, __func__, size_of_direction);
|
||||
auto *x = static_cast<double *>(mxMalloc(col_x*row_x*sizeof(double)));
|
||||
test_mxMalloc(x, __LINE__, __FILE__, __func__, col_x*row_x*sizeof(double));
|
||||
auto* x = static_cast<double*>(mxMalloc(col_x * row_x * sizeof(double)));
|
||||
test_mxMalloc(x, __LINE__, __FILE__, __func__, col_x * row_x * sizeof(double));
|
||||
|
||||
fill_n(direction, row_y*col_y, 0);
|
||||
copy_n(xd, row_x*col_x, x);
|
||||
copy_n(yd, row_y*col_y, y);
|
||||
copy_n(yd, row_y*col_y, ya);
|
||||
fill_n(direction, row_y * col_y, 0);
|
||||
copy_n(xd, row_x * col_x, x);
|
||||
copy_n(yd, row_y * col_y, y);
|
||||
copy_n(yd, row_y * col_y, ya);
|
||||
|
||||
const filesystem::path codfile {file_name + "/model/bytecode/" + (block_decomposed ? "block/" : "")
|
||||
+ (steady_state ? "static" : "dynamic") + ".cod"};
|
||||
const filesystem::path codfile {file_name + "/model/bytecode/"
|
||||
+ (block_decomposed ? "block/" : "")
|
||||
+ (steady_state ? "static" : "dynamic") + ".cod"};
|
||||
Evaluate evaluator {codfile, steady_state, symbol_table};
|
||||
|
||||
Interpreter interprete {evaluator, params, y, ya, x, steady_yd, direction, static_cast<int>(row_y), static_cast<int>(row_x),
|
||||
periods, y_kmin, y_kmax, maxit_, solve_tolf,
|
||||
markowitz_c, minimal_solving_periods, stack_solve_algo,
|
||||
solve_algo, print, GlobalTemporaryTerms,
|
||||
steady_state, block_decomposed, static_cast<int>(col_x), static_cast<int>(col_y), symbol_table, verbosity};
|
||||
Interpreter interprete {evaluator,
|
||||
params,
|
||||
y,
|
||||
ya,
|
||||
x,
|
||||
steady_yd,
|
||||
direction,
|
||||
static_cast<int>(row_y),
|
||||
static_cast<int>(row_x),
|
||||
periods,
|
||||
y_kmin,
|
||||
y_kmax,
|
||||
maxit_,
|
||||
solve_tolf,
|
||||
markowitz_c,
|
||||
minimal_solving_periods,
|
||||
stack_solve_algo,
|
||||
solve_algo,
|
||||
print,
|
||||
GlobalTemporaryTerms,
|
||||
steady_state,
|
||||
block_decomposed,
|
||||
static_cast<int>(col_x),
|
||||
static_cast<int>(col_y),
|
||||
symbol_table,
|
||||
verbosity};
|
||||
bool r;
|
||||
vector<int> blocks;
|
||||
|
||||
try
|
||||
{
|
||||
if (extended_path)
|
||||
tie(r, blocks) = interprete.extended_path(file_name, evaluate, block, max_periods, sextended_path, sconditional_extended_path, dates, table_conditional_global);
|
||||
tie(r, blocks)
|
||||
= interprete.extended_path(file_name, evaluate, block, max_periods, sextended_path,
|
||||
sconditional_extended_path, dates, table_conditional_global);
|
||||
else
|
||||
tie(r, blocks) = interprete.compute_blocks(file_name, evaluate, block);
|
||||
}
|
||||
catch (GeneralException &feh)
|
||||
catch (GeneralException& feh)
|
||||
{
|
||||
// Release the lock on dynamic.bin for MATLAB+Windows, see #1815
|
||||
interprete.Close_SaveCode();
|
||||
|
@ -524,30 +558,31 @@ mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
|||
if (evaluate)
|
||||
{
|
||||
vector<double> residual = interprete.get_residual();
|
||||
plhs[0] = mxCreateDoubleMatrix(residual.size()/periods, periods, mxREAL);
|
||||
plhs[0] = mxCreateDoubleMatrix(residual.size() / periods, periods, mxREAL);
|
||||
std::copy(residual.begin(), residual.end(), mxGetPr(plhs[0]));
|
||||
}
|
||||
else
|
||||
{
|
||||
int out_periods = extended_path ? max_periods + y_kmin : col_y;
|
||||
plhs[0] = mxCreateDoubleMatrix(row_y, out_periods, mxREAL);
|
||||
std::copy_n(y, row_y*out_periods, mxGetPr(plhs[0]));
|
||||
std::copy_n(y, row_y * out_periods, mxGetPr(plhs[0]));
|
||||
}
|
||||
if (nlhs > 1)
|
||||
{
|
||||
if (evaluate)
|
||||
{
|
||||
int jacob_field_number = 0, jacob_exo_field_number = 0,
|
||||
jacob_exo_det_field_number = 0;
|
||||
jacob_exo_det_field_number = 0;
|
||||
bool dont_store_a_structure {false};
|
||||
if (!block_structur)
|
||||
{
|
||||
const char *field_names[] = {"g1", "g1_x", "g1_xd"};
|
||||
const char* field_names[] = {"g1", "g1_x", "g1_xd"};
|
||||
jacob_field_number = 0;
|
||||
jacob_exo_field_number = 1;
|
||||
jacob_exo_det_field_number = 2;
|
||||
mwSize dims[1] = { static_cast<mwSize>(blocks.size()) };
|
||||
plhs[1] = mxCreateStructArray(1, dims, std::extent_v<decltype(field_names)>, field_names);
|
||||
mwSize dims[1] = {static_cast<mwSize>(blocks.size())};
|
||||
plhs[1] = mxCreateStructArray(1, dims, std::extent_v<decltype(field_names)>,
|
||||
field_names);
|
||||
}
|
||||
else if (!mxIsStruct(block_structur))
|
||||
{
|
||||
|
@ -559,42 +594,47 @@ mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
|||
plhs[1] = block_structur;
|
||||
jacob_field_number = mxAddField(plhs[1], "g1");
|
||||
if (jacob_field_number == -1)
|
||||
mexErrMsgTxt("Fatal error in bytecode: in main, cannot add extra field jacob to the structArray");
|
||||
mexErrMsgTxt("Fatal error in bytecode: in main, cannot add extra field jacob "
|
||||
"to the structArray");
|
||||
jacob_exo_field_number = mxAddField(plhs[1], "g1_x");
|
||||
if (jacob_exo_field_number == -1)
|
||||
mexErrMsgTxt("Fatal error in bytecode: in main, cannot add extra field jacob_exo to the structArray");
|
||||
mexErrMsgTxt("Fatal error in bytecode: in main, cannot add extra field "
|
||||
"jacob_exo to the structArray");
|
||||
jacob_exo_det_field_number = mxAddField(plhs[1], "g1_xd");
|
||||
if (jacob_exo_det_field_number == -1)
|
||||
mexErrMsgTxt("Fatal error in bytecode: in main, cannot add extra field jacob_exo_det to the structArray");
|
||||
mexErrMsgTxt("Fatal error in bytecode: in main, cannot add extra field "
|
||||
"jacob_exo_det to the structArray");
|
||||
}
|
||||
if (!dont_store_a_structure)
|
||||
for (size_t i {0}; i < blocks.size(); i++)
|
||||
{
|
||||
mxSetFieldByNumber(plhs[1], i, jacob_field_number, interprete.get_jacob(blocks[i]));
|
||||
mxSetFieldByNumber(plhs[1], i, jacob_field_number,
|
||||
interprete.get_jacob(blocks[i]));
|
||||
if (!steady_state)
|
||||
{
|
||||
mxSetFieldByNumber(plhs[1], i, jacob_exo_field_number, interprete.get_jacob_exo(blocks[i]));
|
||||
mxSetFieldByNumber(plhs[1], i, jacob_exo_det_field_number, interprete.get_jacob_exo_det(blocks[i]));
|
||||
mxSetFieldByNumber(plhs[1], i, jacob_exo_field_number,
|
||||
interprete.get_jacob_exo(blocks[i]));
|
||||
mxSetFieldByNumber(plhs[1], i, jacob_exo_det_field_number,
|
||||
interprete.get_jacob_exo_det(blocks[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
plhs[1] = mxCreateDoubleMatrix(row_x, col_x, mxREAL);
|
||||
double *pind = mxGetPr(plhs[1]);
|
||||
for (i = 0; i < row_x*col_x; i++)
|
||||
double* pind = mxGetPr(plhs[1]);
|
||||
for (i = 0; i < row_x * col_x; i++)
|
||||
pind[i] = x[i];
|
||||
}
|
||||
if (nlhs > 2)
|
||||
{
|
||||
plhs[2] = mxCreateDoubleMatrix(row_y, col_y, mxREAL);
|
||||
double *pind = mxGetPr(plhs[2]);
|
||||
for (i = 0; i < row_y*col_y; i++)
|
||||
double* pind = mxGetPr(plhs[2]);
|
||||
for (i = 0; i < row_y * col_y; i++)
|
||||
pind[i] = y[i];
|
||||
if (nlhs > 3)
|
||||
plhs[3] = interprete.get_Temporary_Terms();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
if (x)
|
||||
|
|
|
@ -43,71 +43,67 @@ typedef int blas_int;
|
|||
#if defined(MATLAB_MEX_FILE) && defined(_WIN32)
|
||||
# define FORTRAN_WRAPPER(x) x
|
||||
#else
|
||||
# define FORTRAN_WRAPPER(x) x ## _
|
||||
# define FORTRAN_WRAPPER(x) x##_
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
typedef const char *BLCHAR;
|
||||
typedef const blas_int *CONST_BLINT;
|
||||
typedef const double *CONST_BLDOU;
|
||||
typedef const float *CONST_BLFLT;
|
||||
typedef double *BLDOU;
|
||||
typedef float *BLFLT;
|
||||
typedef const char* BLCHAR;
|
||||
typedef const blas_int* CONST_BLINT;
|
||||
typedef const double* CONST_BLDOU;
|
||||
typedef const float* CONST_BLFLT;
|
||||
typedef double* BLDOU;
|
||||
typedef float* BLFLT;
|
||||
|
||||
#define dgemm FORTRAN_WRAPPER(dgemm)
|
||||
void 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 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);
|
||||
|
||||
#define sgemm FORTRAN_WRAPPER(sgemm)
|
||||
void sgemm(BLCHAR transa, BLCHAR transb, CONST_BLINT m, CONST_BLINT n,
|
||||
CONST_BLINT k, CONST_BLFLT alpha, CONST_BLFLT a, CONST_BLINT lda,
|
||||
CONST_BLFLT b, CONST_BLINT ldb, CONST_BLFLT beta,
|
||||
BLFLT c, CONST_BLINT ldc);
|
||||
void sgemm(BLCHAR transa, BLCHAR transb, CONST_BLINT m, CONST_BLINT n, CONST_BLINT k,
|
||||
CONST_BLFLT alpha, CONST_BLFLT a, CONST_BLINT lda, CONST_BLFLT b, CONST_BLINT ldb,
|
||||
CONST_BLFLT beta, BLFLT c, CONST_BLINT ldc);
|
||||
|
||||
#define dsymm FORTRAN_WRAPPER(dsymm)
|
||||
void dsymm(BLCHAR side, BLCHAR uplo, CONST_BLINT m, CONST_BLINT n,
|
||||
CONST_BLDOU alpha, CONST_BLDOU a, CONST_BLINT lda,
|
||||
CONST_BLDOU b, CONST_BLINT ldb, CONST_BLDOU beta,
|
||||
void dsymm(BLCHAR side, BLCHAR uplo, CONST_BLINT m, CONST_BLINT n, CONST_BLDOU alpha,
|
||||
CONST_BLDOU a, CONST_BLINT lda, CONST_BLDOU b, CONST_BLINT ldb, CONST_BLDOU beta,
|
||||
BLDOU c, CONST_BLINT ldc);
|
||||
|
||||
#define dgemv FORTRAN_WRAPPER(dgemv)
|
||||
void 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 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);
|
||||
|
||||
#define dsymv FORTRAN_WRAPPER(dsymv)
|
||||
void dsymv(BLCHAR uplo, CONST_BLINT m, CONST_BLDOU alpha, CONST_BLDOU a,
|
||||
CONST_BLINT lda, CONST_BLDOU b, CONST_BLINT ldb, CONST_BLDOU beta,
|
||||
BLDOU c, CONST_BLINT ldc);
|
||||
void dsymv(BLCHAR uplo, CONST_BLINT m, CONST_BLDOU alpha, CONST_BLDOU a, CONST_BLINT lda,
|
||||
CONST_BLDOU b, CONST_BLINT ldb, CONST_BLDOU beta, BLDOU c, CONST_BLINT ldc);
|
||||
|
||||
#define dtrsv FORTRAN_WRAPPER(dtrsv)
|
||||
void dtrsv(BLCHAR uplo, BLCHAR trans, BLCHAR diag, CONST_BLINT n,
|
||||
CONST_BLDOU a, CONST_BLINT lda, BLDOU x, CONST_BLINT incx);
|
||||
void dtrsv(BLCHAR uplo, BLCHAR trans, BLCHAR diag, CONST_BLINT n, CONST_BLDOU a, CONST_BLINT lda,
|
||||
BLDOU x, CONST_BLINT incx);
|
||||
|
||||
#define dtrmv FORTRAN_WRAPPER(dtrmv)
|
||||
void dtrmv(BLCHAR uplo, BLCHAR trans, BLCHAR diag, CONST_BLINT n,
|
||||
CONST_BLDOU a, CONST_BLINT lda, BLDOU x, CONST_BLINT incx);
|
||||
void dtrmv(BLCHAR uplo, BLCHAR trans, BLCHAR diag, CONST_BLINT n, CONST_BLDOU a, CONST_BLINT lda,
|
||||
BLDOU x, CONST_BLINT incx);
|
||||
|
||||
#define daxpy FORTRAN_WRAPPER(daxpy)
|
||||
void daxpy(CONST_BLINT n, CONST_BLDOU a, CONST_BLDOU x, CONST_BLINT incx,
|
||||
BLDOU y, CONST_BLINT incy);
|
||||
void daxpy(CONST_BLINT n, CONST_BLDOU a, CONST_BLDOU x, CONST_BLINT incx, BLDOU y,
|
||||
CONST_BLINT incy);
|
||||
|
||||
#define saxpy FORTRAN_WRAPPER(saxpy)
|
||||
void saxpy(CONST_BLINT n, CONST_BLFLT a, CONST_BLFLT x, CONST_BLINT incx,
|
||||
BLFLT y, CONST_BLINT incy);
|
||||
void saxpy(CONST_BLINT n, CONST_BLFLT a, CONST_BLFLT x, CONST_BLINT incx, BLFLT y,
|
||||
CONST_BLINT incy);
|
||||
|
||||
#define dcopy FORTRAN_WRAPPER(dcopy)
|
||||
void dcopy(CONST_BLINT n, CONST_BLDOU x, CONST_BLINT incx,
|
||||
BLDOU y, CONST_BLINT incy);
|
||||
void dcopy(CONST_BLINT n, CONST_BLDOU x, CONST_BLINT incx, BLDOU y, CONST_BLINT incy);
|
||||
|
||||
#define zaxpy FORTRAN_WRAPPER(zaxpy)
|
||||
void zaxpy(CONST_BLINT n, CONST_BLDOU a, CONST_BLDOU x, CONST_BLINT incx,
|
||||
BLDOU y, CONST_BLINT incy);
|
||||
void zaxpy(CONST_BLINT n, CONST_BLDOU a, CONST_BLDOU x, CONST_BLINT incx, BLDOU y,
|
||||
CONST_BLINT incy);
|
||||
|
||||
#define dscal FORTRAN_WRAPPER(dscal)
|
||||
void dscal(CONST_BLINT n, CONST_BLDOU a, BLDOU x, CONST_BLINT incx);
|
||||
|
@ -116,27 +112,23 @@ extern "C" {
|
|||
void sscal(CONST_BLINT n, CONST_BLDOU a, BLFLT x, CONST_BLINT incx);
|
||||
|
||||
#define dtrsm FORTRAN_WRAPPER(dtrsm)
|
||||
void 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);
|
||||
void 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);
|
||||
|
||||
#define ddot FORTRAN_WRAPPER(ddot)
|
||||
double ddot(CONST_BLINT n, CONST_BLDOU x, CONST_BLINT incx, CONST_BLDOU y,
|
||||
CONST_BLINT incy);
|
||||
double ddot(CONST_BLINT n, CONST_BLDOU x, CONST_BLINT incx, CONST_BLDOU y, CONST_BLINT incy);
|
||||
|
||||
#define dsyr FORTRAN_WRAPPER(dsyr)
|
||||
void dsyr(BLCHAR uplo, CONST_BLINT n, CONST_BLDOU alpha, CONST_BLDOU x,
|
||||
CONST_BLINT incx, BLDOU a, CONST_BLINT lda);
|
||||
void dsyr(BLCHAR uplo, CONST_BLINT n, CONST_BLDOU alpha, CONST_BLDOU x, CONST_BLINT incx, BLDOU a,
|
||||
CONST_BLINT lda);
|
||||
|
||||
#define dtrmm FORTRAN_WRAPPER(dtrmm)
|
||||
void dtrmm(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);
|
||||
void dtrmm(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);
|
||||
|
||||
#define strmm FORTRAN_WRAPPER(strmm)
|
||||
void strmm(BLCHAR side, BLCHAR uplo, BLCHAR transa, BLCHAR diag, CONST_BLINT m,
|
||||
CONST_BLINT n, CONST_BLFLT alpha, CONST_BLFLT a, CONST_BLINT lda,
|
||||
BLFLT b, CONST_BLINT ldb);
|
||||
void strmm(BLCHAR side, BLCHAR uplo, BLCHAR transa, BLCHAR diag, CONST_BLINT m, CONST_BLINT n,
|
||||
CONST_BLFLT alpha, CONST_BLFLT a, CONST_BLINT lda, BLFLT b, CONST_BLINT ldb);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
|
|
|
@ -43,115 +43,104 @@ typedef int lapack_int;
|
|||
#if defined(MATLAB_MEX_FILE) && defined(_WIN32)
|
||||
# define FORTRAN_WRAPPER(x) x
|
||||
#else
|
||||
# define FORTRAN_WRAPPER(x) x ## _
|
||||
# define FORTRAN_WRAPPER(x) x##_
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
typedef const char *LACHAR;
|
||||
typedef const lapack_int *CONST_LAINT;
|
||||
typedef lapack_int *LAINT;
|
||||
typedef const double *CONST_LADOU;
|
||||
typedef double *LADOU;
|
||||
typedef lapack_int (*DGGESCRIT)(const double *, const double *, const double *);
|
||||
typedef lapack_int (*SGGESCRIT)(const float *, const float *, const float *);
|
||||
typedef float *LAFLT;
|
||||
typedef const float *CONST_LAFLT;
|
||||
typedef lapack_int *CONST_LALOG; /*logical*/
|
||||
typedef const char* LACHAR;
|
||||
typedef const lapack_int* CONST_LAINT;
|
||||
typedef lapack_int* LAINT;
|
||||
typedef const double* CONST_LADOU;
|
||||
typedef double* LADOU;
|
||||
typedef lapack_int (*DGGESCRIT)(const double*, const double*, const double*);
|
||||
typedef lapack_int (*SGGESCRIT)(const float*, const float*, const float*);
|
||||
typedef float* LAFLT;
|
||||
typedef const float* CONST_LAFLT;
|
||||
typedef lapack_int* CONST_LALOG; /*logical*/
|
||||
|
||||
#define dgetrs FORTRAN_WRAPPER(dgetrs)
|
||||
void 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 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);
|
||||
|
||||
#define dgetrf FORTRAN_WRAPPER(dgetrf)
|
||||
void dgetrf(CONST_LAINT m, CONST_LAINT n, LADOU a,
|
||||
CONST_LAINT lda, LAINT ipiv, LAINT info);
|
||||
void dgetrf(CONST_LAINT m, CONST_LAINT n, LADOU a, CONST_LAINT lda, LAINT ipiv, LAINT info);
|
||||
|
||||
#define dgetri FORTRAN_WRAPPER(dgetri)
|
||||
void dgetri(CONST_LAINT n, LADOU a, CONST_LAINT lda, CONST_LAINT ipiv, LADOU work,
|
||||
CONST_LAINT lwork, LAINT info);
|
||||
|
||||
#define sgetrf FORTRAN_WRAPPER(sgetrf)
|
||||
void sgetrf(CONST_LAINT m, CONST_LAINT n, LAFLT a,
|
||||
CONST_LAINT lda, LAINT ipiv, LAINT info);
|
||||
void sgetrf(CONST_LAINT m, CONST_LAINT n, LAFLT a, CONST_LAINT lda, LAINT ipiv, LAINT info);
|
||||
|
||||
#define dgees FORTRAN_WRAPPER(dgees)
|
||||
void 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, LAINT bwork, LAINT info);
|
||||
void 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, LAINT bwork, LAINT info);
|
||||
|
||||
#define dgecon FORTRAN_WRAPPER(dgecon)
|
||||
void dgecon(LACHAR norm, CONST_LAINT n, CONST_LADOU a, CONST_LAINT lda,
|
||||
CONST_LADOU anorm, LADOU rnorm, LADOU work, LAINT iwork,
|
||||
LAINT info);
|
||||
void dgecon(LACHAR norm, CONST_LAINT n, CONST_LADOU a, CONST_LAINT lda, CONST_LADOU anorm,
|
||||
LADOU rnorm, LADOU work, LAINT iwork, LAINT info);
|
||||
|
||||
#define dtrexc FORTRAN_WRAPPER(dtrexc)
|
||||
void 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 dtrexc(LACHAR compq, CONST_LAINT n, LADOU t, CONST_LAINT ldt, LADOU q, CONST_LAINT ldq,
|
||||
LAINT ifst, LAINT ilst, LADOU work, LAINT info);
|
||||
|
||||
#define dtrsyl FORTRAN_WRAPPER(dtrsyl)
|
||||
void 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 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);
|
||||
|
||||
#define dpotrf FORTRAN_WRAPPER(dpotrf)
|
||||
void dpotrf(LACHAR uplo, CONST_LAINT n, LADOU a, CONST_LAINT lda,
|
||||
LAINT info);
|
||||
void dpotrf(LACHAR uplo, CONST_LAINT n, LADOU a, CONST_LAINT lda, LAINT info);
|
||||
|
||||
#define dppsv FORTRAN_WRAPPER(dppsv)
|
||||
void dppsv(LACHAR uplo, CONST_LAINT n, CONST_LAINT m, LADOU a, LADOU b, CONST_LAINT ldb,
|
||||
LAINT info);
|
||||
|
||||
#define dpotri FORTRAN_WRAPPER(dpotri)
|
||||
void dpotri(LACHAR uplo, CONST_LAINT n, LADOU a, CONST_LAINT lda,
|
||||
LAINT info);
|
||||
void dpotri(LACHAR uplo, CONST_LAINT n, LADOU a, CONST_LAINT lda, LAINT info);
|
||||
|
||||
#define dtrtri FORTRAN_WRAPPER(dtrtri)
|
||||
void dtrtri(LACHAR uplo, LACHAR diag, CONST_LAINT n, LADOU a, CONST_LAINT lda,
|
||||
LAINT info);
|
||||
void dtrtri(LACHAR uplo, LACHAR diag, CONST_LAINT n, LADOU a, CONST_LAINT lda, LAINT info);
|
||||
|
||||
#define dgges FORTRAN_WRAPPER(dgges)
|
||||
void 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 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);
|
||||
|
||||
#define sgges FORTRAN_WRAPPER(sgges)
|
||||
void sgges(LACHAR jobvsl, LACHAR jobvsr, LACHAR sort, SGGESCRIT delztg,
|
||||
CONST_LAINT n, LAFLT a, CONST_LAINT lda, LAFLT b, CONST_LAINT ldb,
|
||||
LAINT sdim, LAFLT alphar, LAFLT alphai, LAFLT beta,
|
||||
LAFLT vsl, CONST_LAINT ldvsl, LAFLT vsr, CONST_LAINT ldvsr,
|
||||
LAFLT work, CONST_LAINT lwork, LAINT bwork, LAINT info);
|
||||
void sgges(LACHAR jobvsl, LACHAR jobvsr, LACHAR sort, SGGESCRIT delztg, CONST_LAINT n, LAFLT a,
|
||||
CONST_LAINT lda, LAFLT b, CONST_LAINT ldb, LAINT sdim, LAFLT alphar, LAFLT alphai,
|
||||
LAFLT beta, LAFLT vsl, CONST_LAINT ldvsl, LAFLT vsr, CONST_LAINT ldvsr, LAFLT work,
|
||||
CONST_LAINT lwork, LAINT bwork, LAINT info);
|
||||
|
||||
#define dsyev FORTRAN_WRAPPER(dsyev)
|
||||
void dsyev(LACHAR jobz, LACHAR uplo, CONST_LAINT n, LADOU a, CONST_LAINT lda,
|
||||
LADOU w, LADOU work, CONST_LAINT lwork, LAINT info);
|
||||
void dsyev(LACHAR jobz, LACHAR uplo, CONST_LAINT n, LADOU a, CONST_LAINT lda, LADOU w, LADOU work,
|
||||
CONST_LAINT lwork, LAINT info);
|
||||
|
||||
#define dsyevr FORTRAN_WRAPPER(dsyevr)
|
||||
void 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);
|
||||
void 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);
|
||||
|
||||
#define dgeqrf FORTRAN_WRAPPER(dgeqrf)
|
||||
void dgeqrf(CONST_LAINT m, CONST_LAINT n, LADOU a, CONST_LAINT lda,
|
||||
LADOU tau, LADOU work, CONST_LAINT lwork, LAINT info);
|
||||
void dgeqrf(CONST_LAINT m, CONST_LAINT n, LADOU a, CONST_LAINT lda, LADOU tau, LADOU work,
|
||||
CONST_LAINT lwork, LAINT info);
|
||||
|
||||
#define sgeqrf FORTRAN_WRAPPER(sgeqrf)
|
||||
void sgeqrf(CONST_LAINT m, CONST_LAINT n, LAFLT a, CONST_LAINT lda,
|
||||
LAFLT tau, LAFLT work, CONST_LAINT lwork, LAINT info);
|
||||
void sgeqrf(CONST_LAINT m, CONST_LAINT n, LAFLT a, CONST_LAINT lda, LAFLT tau, LAFLT work,
|
||||
CONST_LAINT lwork, LAINT info);
|
||||
|
||||
#define dormqr FORTRAN_WRAPPER(dormqr)
|
||||
void dormqr(LACHAR side, LACHAR trans, CONST_LAINT m, CONST_LAINT n, CONST_LAINT k,
|
||||
CONST_LADOU a, CONST_LAINT lda, CONST_LADOU tau, LADOU c, CONST_LAINT ldc,
|
||||
LADOU work, CONST_LAINT lwork, LAINT info);
|
||||
void dormqr(LACHAR side, LACHAR trans, CONST_LAINT m, CONST_LAINT n, CONST_LAINT k, CONST_LADOU a,
|
||||
CONST_LAINT lda, CONST_LADOU tau, LADOU c, CONST_LAINT ldc, LADOU work,
|
||||
CONST_LAINT lwork, LAINT info);
|
||||
|
||||
#define dorgqr FORTRAN_WRAPPER(dorgqr)
|
||||
void dorgqr(CONST_LAINT m, CONST_LAINT n, CONST_LAINT k, LADOU a, CONST_LAINT lda,
|
||||
|
@ -162,12 +151,12 @@ extern "C" {
|
|||
CONST_LAFLT tau, LAFLT work, CONST_LAINT lwork, LAINT info);
|
||||
|
||||
#define dgelqf FORTRAN_WRAPPER(dgelqf)
|
||||
void dgelqf(CONST_LAINT m, CONST_LAINT n, LADOU a, CONST_LAINT lda, LADOU tau,
|
||||
LADOU work, CONST_LAINT lwork, LAINT info);
|
||||
void dgelqf(CONST_LAINT m, CONST_LAINT n, LADOU a, CONST_LAINT lda, LADOU tau, LADOU work,
|
||||
CONST_LAINT lwork, LAINT info);
|
||||
|
||||
#define sgelqf FORTRAN_WRAPPER(sgelqf)
|
||||
void sgelqf(CONST_LAINT m, CONST_LAINT n, LAFLT a, CONST_LAINT lda, LAFLT tau,
|
||||
LAFLT work, CONST_LAINT lwork, LAINT info);
|
||||
void sgelqf(CONST_LAINT m, CONST_LAINT n, LAFLT a, CONST_LAINT lda, LAFLT tau, LAFLT work,
|
||||
CONST_LAINT lwork, LAINT info);
|
||||
|
||||
#define dorglq FORTRAN_WRAPPER(dorglq)
|
||||
void dorglq(CONST_LAINT m, CONST_LAINT n, CONST_LAINT k, LADOU a, CONST_LAINT lda,
|
||||
|
@ -178,8 +167,8 @@ extern "C" {
|
|||
CONST_LAFLT tau, LAFLT work, CONST_LAINT lwork, LAINT info);
|
||||
|
||||
#define dgesv FORTRAN_WRAPPER(dgesv)
|
||||
void dgesv(CONST_LAINT n, CONST_LAINT nrhs, LADOU a, CONST_LAINT lda, LAINT ipiv,
|
||||
LADOU b, CONST_LAINT ldb, LAINT info);
|
||||
void dgesv(CONST_LAINT n, CONST_LAINT nrhs, LADOU a, CONST_LAINT lda, LAINT ipiv, LADOU b,
|
||||
CONST_LAINT ldb, LAINT info);
|
||||
|
||||
#define dgesvd FORTRAN_WRAPPER(dgesvd)
|
||||
void dgesvd(LACHAR jobu, LACHAR jobvt, CONST_LAINT m, CONST_LAINT n, LADOU a, CONST_LAINT lda,
|
||||
|
@ -193,17 +182,17 @@ extern "C" {
|
|||
|
||||
#define dtgsen FORTRAN_WRAPPER(dtgsen)
|
||||
void dtgsen(CONST_LAINT ijob, CONST_LALOG wantq, CONST_LALOG wantz, CONST_LALOG select,
|
||||
CONST_LAINT n, LADOU a, CONST_LAINT lda, LADOU b, CONST_LAINT ldb,
|
||||
LADOU alphar, LADOU alphai, LADOU beta, LADOU q, CONST_LAINT ldq,
|
||||
LADOU z, CONST_LAINT ldz, LAINT m, LADOU pl, LADOU pr, LADOU dif, LADOU work,
|
||||
CONST_LAINT lwork, LAINT iwork, CONST_LAINT liwork, LAINT info);
|
||||
CONST_LAINT n, LADOU a, CONST_LAINT lda, LADOU b, CONST_LAINT ldb, LADOU alphar,
|
||||
LADOU alphai, LADOU beta, LADOU q, CONST_LAINT ldq, LADOU z, CONST_LAINT ldz, LAINT m,
|
||||
LADOU pl, LADOU pr, LADOU dif, LADOU work, CONST_LAINT lwork, LAINT iwork,
|
||||
CONST_LAINT liwork, LAINT info);
|
||||
|
||||
#define stgsen FORTRAN_WRAPPER(stgsen)
|
||||
void stgsen(CONST_LAINT ijob, CONST_LALOG wantq, CONST_LALOG wantz, CONST_LALOG select,
|
||||
CONST_LAINT n, LAFLT a, CONST_LAINT lda, LAFLT b, CONST_LAINT ldb,
|
||||
LAFLT alphar, LAFLT alphai, LAFLT beta, LAFLT q, CONST_LAINT ldq,
|
||||
LAFLT z, CONST_LAINT ldz, LAINT m, LAFLT pl, LAFLT pr, LAFLT dif, LAFLT work,
|
||||
CONST_LAINT lwork, LAINT iwork, CONST_LAINT liwork, LAINT info);
|
||||
CONST_LAINT n, LAFLT a, CONST_LAINT lda, LAFLT b, CONST_LAINT ldb, LAFLT alphar,
|
||||
LAFLT alphai, LAFLT beta, LAFLT q, CONST_LAINT ldq, LAFLT z, CONST_LAINT ldz, LAINT m,
|
||||
LAFLT pl, LAFLT pr, LAFLT dif, LAFLT work, CONST_LAINT lwork, LAINT iwork,
|
||||
CONST_LAINT liwork, LAINT info);
|
||||
|
||||
#define dtgexc FORTRAN_WRAPPER(dtgexc)
|
||||
void dtgexc(CONST_LALOG wantq, CONST_LALOG wantz, CONST_LAINT n, LADOU a, CONST_LAINT lda,
|
||||
|
@ -216,19 +205,19 @@ extern "C" {
|
|||
LAINT ifst, LAINT ilst, LAFLT work, CONST_LAINT lwork, LAINT info);
|
||||
|
||||
#define dgesdd FORTRAN_WRAPPER(dgesdd)
|
||||
void dgesdd(LACHAR jobz, CONST_LAINT m, CONST_LAINT n, LADOU a, CONST_LAINT lda,
|
||||
LADOU s, LADOU u, CONST_LAINT ldu, LADOU vt, CONST_LAINT ldvt, LADOU work,
|
||||
CONST_LAINT lwork, LAINT iwork, LAINT info);
|
||||
void dgesdd(LACHAR jobz, CONST_LAINT m, CONST_LAINT n, LADOU a, CONST_LAINT lda, LADOU s, LADOU u,
|
||||
CONST_LAINT ldu, LADOU vt, CONST_LAINT ldvt, LADOU work, CONST_LAINT lwork,
|
||||
LAINT iwork, LAINT info);
|
||||
|
||||
#define sgesdd FORTRAN_WRAPPER(sgesdd)
|
||||
void sgesdd(LACHAR jobz, CONST_LAINT m, CONST_LAINT n, LAFLT a, CONST_LAINT lda,
|
||||
LAFLT s, LAFLT u, CONST_LAINT ldu, LAFLT vt, CONST_LAINT ldvt, LAFLT work,
|
||||
CONST_LAINT lwork, LAINT iwork, LAINT info);
|
||||
void sgesdd(LACHAR jobz, CONST_LAINT m, CONST_LAINT n, LAFLT a, CONST_LAINT lda, LAFLT s, LAFLT u,
|
||||
CONST_LAINT ldu, LAFLT vt, CONST_LAINT ldvt, LAFLT work, CONST_LAINT lwork,
|
||||
LAINT iwork, LAINT info);
|
||||
|
||||
#define dgeev FORTRAN_WRAPPER(dgeev)
|
||||
void dgeev(LACHAR jobvl, LACHAR jobvr, CONST_LAINT n, LADOU a, CONST_LAINT lda,
|
||||
LADOU wr, LADOU wi, LADOU vl, CONST_LAINT ldvl, LADOU vr, CONST_LAINT ldvr,
|
||||
LADOU work, CONST_LAINT lwork, LAINT info);
|
||||
void dgeev(LACHAR jobvl, LACHAR jobvr, CONST_LAINT n, LADOU a, CONST_LAINT lda, LADOU wr,
|
||||
LADOU wi, LADOU vl, CONST_LAINT ldvl, LADOU vr, CONST_LAINT ldvr, LADOU work,
|
||||
CONST_LAINT lwork, LAINT info);
|
||||
|
||||
#define dgeqp3 FORTRAN_WRAPPER(dgeqp3)
|
||||
void dgeqp3(CONST_LAINT m, CONST_LAINT n, LADOU a, CONST_LAINT lda, LAINT jpvt, LADOU tau,
|
||||
|
|
|
@ -37,7 +37,8 @@
|
|||
libmwumfpack, since there is no associated header */
|
||||
|
||||
# ifdef __cplusplus
|
||||
extern "C" {
|
||||
extern "C"
|
||||
{
|
||||
# endif
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
@ -50,10 +51,10 @@ extern "C" {
|
|||
# define UMFPACK_INFO 90
|
||||
# define UMFPACK_CONTROL 20
|
||||
/* used in all UMFPACK_report_* routines: */
|
||||
# define UMFPACK_PRL 0 /* print level */
|
||||
# define UMFPACK_PRL 0 /* print level */
|
||||
/* returned by all routines that use Info: */
|
||||
# define UMFPACK_OK (0)
|
||||
# define UMFPACK_STATUS 0 /* UMFPACK_OK, or other result */
|
||||
# define UMFPACK_STATUS 0 /* UMFPACK_OK, or other result */
|
||||
|
||||
# ifdef _WIN64
|
||||
# ifdef __cplusplus
|
||||
|
@ -63,42 +64,44 @@ extern "C" {
|
|||
# endif
|
||||
typedef int64_t SuiteSparse_long;
|
||||
# else
|
||||
typedef long SuiteSparse_long;
|
||||
typedef long SuiteSparse_long;
|
||||
# endif
|
||||
|
||||
void umfpack_dl_defaults(double Control[UMFPACK_CONTROL]);
|
||||
|
||||
SuiteSparse_long umfpack_dl_symbolic(SuiteSparse_long n_row, SuiteSparse_long n_col,
|
||||
const SuiteSparse_long Ap [], const SuiteSparse_long Ai [],
|
||||
const double Ax [], void **Symbolic,
|
||||
const double Control [UMFPACK_CONTROL], double Info [UMFPACK_INFO]);
|
||||
const SuiteSparse_long Ap[], const SuiteSparse_long Ai[],
|
||||
const double Ax[], void** Symbolic,
|
||||
const double Control[UMFPACK_CONTROL],
|
||||
double Info[UMFPACK_INFO]);
|
||||
|
||||
SuiteSparse_long umfpack_dl_numeric(const SuiteSparse_long Ap [], const SuiteSparse_long Ai [],
|
||||
const double Ax [], void *Symbolic, void **Numeric,
|
||||
const double Control [UMFPACK_CONTROL], double Info [UMFPACK_INFO]);
|
||||
SuiteSparse_long umfpack_dl_numeric(const SuiteSparse_long Ap[], const SuiteSparse_long Ai[],
|
||||
const double Ax[], void* Symbolic, void** Numeric,
|
||||
const double Control[UMFPACK_CONTROL],
|
||||
double Info[UMFPACK_INFO]);
|
||||
|
||||
SuiteSparse_long umfpack_dl_solve(SuiteSparse_long sys, const SuiteSparse_long Ap [],
|
||||
const SuiteSparse_long Ai [], const double Ax [],
|
||||
double X [], const double B [], void *Numeric,
|
||||
const double Control [UMFPACK_CONTROL], double Info [UMFPACK_INFO]);
|
||||
SuiteSparse_long umfpack_dl_solve(SuiteSparse_long sys, const SuiteSparse_long Ap[],
|
||||
const SuiteSparse_long Ai[], const double Ax[], double X[],
|
||||
const double B[], void* Numeric,
|
||||
const double Control[UMFPACK_CONTROL],
|
||||
double Info[UMFPACK_INFO]);
|
||||
|
||||
void umfpack_dl_report_info(const double Control [UMFPACK_CONTROL],
|
||||
const double Info [UMFPACK_INFO]);
|
||||
void umfpack_dl_report_info(const double Control[UMFPACK_CONTROL],
|
||||
const double Info[UMFPACK_INFO]);
|
||||
|
||||
void umfpack_dl_report_status(const double Control [UMFPACK_CONTROL],
|
||||
SuiteSparse_long status);
|
||||
void umfpack_dl_report_status(const double Control[UMFPACK_CONTROL], SuiteSparse_long status);
|
||||
|
||||
void umfpack_dl_free_symbolic(void **Symbolic);
|
||||
void umfpack_dl_free_symbolic(void** Symbolic);
|
||||
|
||||
void umfpack_dl_free_numeric(void **Numeric);
|
||||
void umfpack_dl_free_numeric(void** Numeric);
|
||||
|
||||
SuiteSparse_long umfpack_dl_load_symbolic(void **Symbolic, char *filename);
|
||||
SuiteSparse_long umfpack_dl_load_symbolic(void** Symbolic, char* filename);
|
||||
|
||||
SuiteSparse_long umfpack_dl_load_numeric(void **Numeric, char *filename);
|
||||
SuiteSparse_long umfpack_dl_load_numeric(void** Numeric, char* filename);
|
||||
|
||||
SuiteSparse_long umfpack_dl_save_symbolic(void *Symbolic, char *filename);
|
||||
SuiteSparse_long umfpack_dl_save_symbolic(void* Symbolic, char* filename);
|
||||
|
||||
SuiteSparse_long umfpack_dl_save_numeric(void *Numeric, char *filename);
|
||||
SuiteSparse_long umfpack_dl_save_numeric(void* Numeric, char* filename);
|
||||
|
||||
# ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
|
|
|
@ -26,19 +26,17 @@
|
|||
#include "int_power.hh"
|
||||
|
||||
void
|
||||
gen_sylv_solve(int order, int n, int m, int zero_cols,
|
||||
const ConstVector &A, const ConstVector &B,
|
||||
const ConstVector &C, Vector &X)
|
||||
gen_sylv_solve(int order, int n, int m, int zero_cols, const ConstVector& A, const ConstVector& B,
|
||||
const ConstVector& C, Vector& X)
|
||||
{
|
||||
GeneralSylvester s(order, n, m, zero_cols, A, B, C, X, false);
|
||||
s.solve();
|
||||
}
|
||||
|
||||
mxArray *
|
||||
gen_sylv_solve_and_check(int order, int n, int m, int zero_cols,
|
||||
const ConstVector &A, const ConstVector &B,
|
||||
const ConstVector &C, const ConstVector &D,
|
||||
Vector &X)
|
||||
mxArray*
|
||||
gen_sylv_solve_and_check(int order, int n, int m, int zero_cols, const ConstVector& A,
|
||||
const ConstVector& B, const ConstVector& C, const ConstVector& D,
|
||||
Vector& X)
|
||||
{
|
||||
GeneralSylvester s(order, n, m, zero_cols, A, B, C, X, true);
|
||||
s.solve();
|
||||
|
@ -46,10 +44,10 @@ gen_sylv_solve_and_check(int order, int n, int m, int zero_cols,
|
|||
return s.getParams().createStructArray();
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
extern "C"
|
||||
{
|
||||
void
|
||||
mexFunction(int nlhs, mxArray *plhs[],
|
||||
int nhrs, const mxArray *prhs[])
|
||||
mexFunction(int nlhs, mxArray* plhs[], int nhrs, const mxArray* prhs[])
|
||||
{
|
||||
if (nhrs != 5 || nlhs > 2 || nlhs < 1)
|
||||
mexErrMsgTxt("Gensylv: Must have exactly 5 input args and either 1 or 2 output args.");
|
||||
|
@ -58,10 +56,10 @@ extern "C" {
|
|||
mexErrMsgTxt("First argument should be a numeric scalar");
|
||||
|
||||
auto order = static_cast<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 mxArray* const A = prhs[1];
|
||||
const mxArray* const B = prhs[2];
|
||||
const mxArray* const C = prhs[3];
|
||||
const mxArray* const D = prhs[4];
|
||||
|
||||
if (!mxIsDouble(A) || mxIsComplex(A) || mxIsSparse(A))
|
||||
mexErrMsgTxt("Matrix A must be a real dense matrix.");
|
||||
|
@ -72,10 +70,10 @@ extern "C" {
|
|||
if (!mxIsDouble(D) || mxIsComplex(D) || mxIsSparse(D))
|
||||
mexErrMsgTxt("Matrix D must be a real dense matrix.");
|
||||
|
||||
const mwSize *const Adims = mxGetDimensions(A);
|
||||
const mwSize *const Bdims = mxGetDimensions(B);
|
||||
const mwSize *const Cdims = mxGetDimensions(C);
|
||||
const mwSize *const Ddims = mxGetDimensions(D);
|
||||
const mwSize* const Adims = mxGetDimensions(A);
|
||||
const mwSize* const Bdims = mxGetDimensions(B);
|
||||
const mwSize* const Cdims = mxGetDimensions(C);
|
||||
const mwSize* const Ddims = mxGetDimensions(D);
|
||||
|
||||
if (Adims[0] != Adims[1])
|
||||
mexErrMsgTxt("Matrix A must be a square matrix.");
|
||||
|
@ -93,10 +91,10 @@ extern "C" {
|
|||
auto n = static_cast<int>(Adims[0]);
|
||||
auto m = static_cast<int>(Cdims[0]);
|
||||
auto zero_cols = static_cast<int>(Bdims[0] - Bdims[1]);
|
||||
mxArray *X = mxCreateDoubleMatrix(Ddims[0], Ddims[1], mxREAL);
|
||||
mxArray* X = mxCreateDoubleMatrix(Ddims[0], Ddims[1], mxREAL);
|
||||
// copy D to X
|
||||
ConstVector Avec{A}, Bvec{B}, Cvec{C}, Dvec{D};
|
||||
Vector Xvec{X};
|
||||
ConstVector Avec {A}, Bvec {B}, Cvec {C}, Dvec {D};
|
||||
Vector Xvec {X};
|
||||
Xvec = Dvec;
|
||||
// solve (or solve and check)
|
||||
try
|
||||
|
@ -106,7 +104,7 @@ extern "C" {
|
|||
else if (nlhs == 2)
|
||||
plhs[1] = gen_sylv_solve_and_check(order, n, m, zero_cols, Avec, Bvec, Cvec, Dvec, Xvec);
|
||||
}
|
||||
catch (const SylvException &e)
|
||||
catch (const SylvException& e)
|
||||
{
|
||||
mexErrMsgTxt(e.getMessage().c_str());
|
||||
}
|
||||
|
|
|
@ -23,16 +23,16 @@
|
|||
outputs.
|
||||
*/
|
||||
|
||||
#include "dynamic_m.hh"
|
||||
#include "dynamic_dll.hh"
|
||||
#include "dynamic_m.hh"
|
||||
#include "k_ord_dynare.hh"
|
||||
|
||||
#include "SylvException.hh"
|
||||
#include "approximation.hh"
|
||||
#include "exception.hh"
|
||||
#include "dynare_exception.hh"
|
||||
#include "exception.hh"
|
||||
#include "kord_exception.hh"
|
||||
#include "tl_exception.hh"
|
||||
#include "SylvException.hh"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
|
@ -49,13 +49,13 @@ std::vector<std::string> g_fieldnames;
|
|||
/* Convert MATLAB Dynare endo and exo names cell array to a vector<string> array of
|
||||
string pointers. */
|
||||
std::vector<std::string>
|
||||
DynareMxArrayToString(const mxArray *mxFldp)
|
||||
DynareMxArrayToString(const mxArray* mxFldp)
|
||||
{
|
||||
assert(mxIsCell(mxFldp));
|
||||
std::vector<std::string> r;
|
||||
for (size_t i = 0; i < mxGetNumberOfElements(mxFldp); i++)
|
||||
{
|
||||
const mxArray *cell_mx = mxGetCell(mxFldp, i);
|
||||
const mxArray* cell_mx = mxGetCell(mxFldp, i);
|
||||
if (!(cell_mx && mxIsChar(cell_mx)))
|
||||
mexErrMsgTxt("Cell is not a character array");
|
||||
r.emplace_back(mxArrayToString(cell_mx));
|
||||
|
@ -65,90 +65,90 @@ DynareMxArrayToString(const mxArray *mxFldp)
|
|||
}
|
||||
|
||||
void
|
||||
copy_derivatives(mxArray *destin, const Symmetry &sym, const FGSContainer &derivs, const char *fieldname)
|
||||
copy_derivatives(mxArray* destin, const Symmetry& sym, const FGSContainer& derivs,
|
||||
const char* fieldname)
|
||||
{
|
||||
const FGSTensor &x = derivs.get(sym);
|
||||
const FGSTensor& x = derivs.get(sym);
|
||||
auto x_unfolded = x.unfold();
|
||||
int n = x_unfolded->nrows();
|
||||
int m = x_unfolded->ncols();
|
||||
mxArray *tmp = mxCreateDoubleMatrix(n, m, mxREAL);
|
||||
std::copy_n(x_unfolded->getData().base(), n*m, mxGetPr(tmp));
|
||||
mxArray* tmp = mxCreateDoubleMatrix(n, m, mxREAL);
|
||||
std::copy_n(x_unfolded->getData().base(), n * m, mxGetPr(tmp));
|
||||
mxSetField(destin, 0, fieldname, tmp);
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
extern "C"
|
||||
{
|
||||
|
||||
void
|
||||
mexFunction(int nlhs, mxArray *plhs[],
|
||||
int nrhs, const mxArray *prhs[])
|
||||
mexFunction(int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[])
|
||||
{
|
||||
if (nrhs != 3 || nlhs < 1 || nlhs > 2)
|
||||
mexErrMsgTxt("Must have exactly 3 input parameters and takes 1 or 2 output parameters.");
|
||||
|
||||
// Give explicit names to input arguments
|
||||
const mxArray *dr_mx = prhs[0];
|
||||
const mxArray *M_mx = prhs[1];
|
||||
const mxArray *options_mx = prhs[2];
|
||||
const mxArray* dr_mx = prhs[0];
|
||||
const mxArray* M_mx = prhs[1];
|
||||
const mxArray* options_mx = prhs[2];
|
||||
|
||||
auto get_int_field = [](const mxArray *struct_mx, const std::string &fieldname)
|
||||
{
|
||||
mxArray *field_mx = mxGetField(struct_mx, 0, fieldname.c_str());
|
||||
if (!(field_mx && mxIsScalar(field_mx) && mxIsNumeric(field_mx)))
|
||||
mexErrMsgTxt(("Field `" + fieldname + "' should be a numeric scalar").c_str());
|
||||
return static_cast<int>(mxGetScalar(field_mx));
|
||||
};
|
||||
auto get_int_field = [](const mxArray* struct_mx, const std::string& fieldname) {
|
||||
mxArray* field_mx = mxGetField(struct_mx, 0, fieldname.c_str());
|
||||
if (!(field_mx && mxIsScalar(field_mx) && mxIsNumeric(field_mx)))
|
||||
mexErrMsgTxt(("Field `" + fieldname + "' should be a numeric scalar").c_str());
|
||||
return static_cast<int>(mxGetScalar(field_mx));
|
||||
};
|
||||
|
||||
// Extract various fields from options_
|
||||
const int kOrder = get_int_field(options_mx, "order");
|
||||
if (kOrder < 1)
|
||||
mexErrMsgTxt("options_.order must be at least 1");
|
||||
|
||||
const mxArray *use_dll_mx = mxGetField(options_mx, 0, "use_dll");
|
||||
const mxArray* use_dll_mx = mxGetField(options_mx, 0, "use_dll");
|
||||
if (!(use_dll_mx && mxIsLogicalScalar(use_dll_mx)))
|
||||
mexErrMsgTxt("options_.use_dll should be a logical scalar");
|
||||
bool use_dll = static_cast<bool>(mxGetScalar(use_dll_mx));
|
||||
|
||||
double qz_criterium = 1+1e-6;
|
||||
const mxArray *qz_criterium_mx = mxGetField(options_mx, 0, "qz_criterium");
|
||||
double qz_criterium = 1 + 1e-6;
|
||||
const mxArray* qz_criterium_mx = mxGetField(options_mx, 0, "qz_criterium");
|
||||
if (qz_criterium_mx && mxIsScalar(qz_criterium_mx) && mxIsNumeric(qz_criterium_mx))
|
||||
qz_criterium = mxGetScalar(qz_criterium_mx);
|
||||
|
||||
const mxArray *threads_mx = mxGetField(options_mx, 0, "threads");
|
||||
const mxArray* threads_mx = mxGetField(options_mx, 0, "threads");
|
||||
if (!threads_mx)
|
||||
mexErrMsgTxt("Can't find field options_.threads");
|
||||
const mxArray *num_threads_mx = mxGetField(threads_mx, 0, "k_order_perturbation");
|
||||
const mxArray* num_threads_mx = mxGetField(threads_mx, 0, "k_order_perturbation");
|
||||
if (!(num_threads_mx && mxIsScalar(num_threads_mx) && mxIsNumeric(num_threads_mx)))
|
||||
mexErrMsgTxt("options_.threads.k_order_perturbation be a numeric scalar");
|
||||
int num_threads = static_cast<int>(mxGetScalar(num_threads_mx));
|
||||
|
||||
const mxArray *debug_mx = mxGetField(options_mx, 0, "debug");
|
||||
const mxArray* debug_mx = mxGetField(options_mx, 0, "debug");
|
||||
if (!(debug_mx && mxIsLogicalScalar(debug_mx)))
|
||||
mexErrMsgTxt("options_.debug should be a logical scalar");
|
||||
bool debug = static_cast<bool>(mxGetScalar(debug_mx));
|
||||
|
||||
const mxArray *pruning_mx = mxGetField(options_mx, 0, "pruning");
|
||||
const mxArray* pruning_mx = mxGetField(options_mx, 0, "pruning");
|
||||
if (!(pruning_mx && mxIsLogicalScalar(pruning_mx)))
|
||||
mexErrMsgTxt("options_.pruning should be a logical scalar");
|
||||
bool pruning = static_cast<bool>(mxGetScalar(pruning_mx));
|
||||
|
||||
// Extract various fields from M_
|
||||
const mxArray *fname_mx = mxGetField(M_mx, 0, "fname");
|
||||
const mxArray* fname_mx = mxGetField(M_mx, 0, "fname");
|
||||
if (!(fname_mx && mxIsChar(fname_mx) && mxGetM(fname_mx) == 1))
|
||||
mexErrMsgTxt("M_.fname should be a character string");
|
||||
std::string fname{mxArrayToString(fname_mx)};
|
||||
std::string fname {mxArrayToString(fname_mx)};
|
||||
|
||||
const mxArray *params_mx = mxGetField(M_mx, 0, "params");
|
||||
const mxArray* params_mx = mxGetField(M_mx, 0, "params");
|
||||
if (!(params_mx && mxIsDouble(params_mx) && !mxIsComplex(params_mx) && !mxIsSparse(params_mx)))
|
||||
mexErrMsgTxt("M_.params should be a real dense array");
|
||||
Vector modParams{ConstVector{params_mx}};
|
||||
Vector modParams {ConstVector {params_mx}};
|
||||
if (!modParams.isFinite())
|
||||
mexErrMsgTxt("M_.params contains NaN or Inf");
|
||||
|
||||
const mxArray *sigma_e_mx = mxGetField(M_mx, 0, "Sigma_e");
|
||||
if (!(sigma_e_mx && mxIsDouble(sigma_e_mx) && !mxIsComplex(sigma_e_mx) && !mxIsSparse(sigma_e_mx)
|
||||
&& mxGetM(sigma_e_mx) == mxGetN(sigma_e_mx)))
|
||||
const mxArray* sigma_e_mx = mxGetField(M_mx, 0, "Sigma_e");
|
||||
if (!(sigma_e_mx && mxIsDouble(sigma_e_mx) && !mxIsComplex(sigma_e_mx)
|
||||
&& !mxIsSparse(sigma_e_mx) && mxGetM(sigma_e_mx) == mxGetN(sigma_e_mx)))
|
||||
mexErrMsgTxt("M_.Sigma_e should be a real dense square matrix");
|
||||
TwoDMatrix vCov{ConstTwoDMatrix{sigma_e_mx}};
|
||||
TwoDMatrix vCov {ConstTwoDMatrix {sigma_e_mx}};
|
||||
if (!vCov.isFinite())
|
||||
mexErrMsgTxt("M_.Sigma_e contains NaN or Inf");
|
||||
|
||||
|
@ -161,63 +161,71 @@ extern "C" {
|
|||
const int nEndo = get_int_field(M_mx, "endo_nbr");
|
||||
const int nPar = get_int_field(M_mx, "param_nbr");
|
||||
|
||||
const mxArray *lead_lag_incidence_mx = mxGetField(M_mx, 0, "lead_lag_incidence");
|
||||
const mxArray* lead_lag_incidence_mx = mxGetField(M_mx, 0, "lead_lag_incidence");
|
||||
if (!(lead_lag_incidence_mx && mxIsDouble(lead_lag_incidence_mx)
|
||||
&& !mxIsComplex(lead_lag_incidence_mx) && !mxIsSparse(lead_lag_incidence_mx)
|
||||
&& mxGetM(lead_lag_incidence_mx) == 3
|
||||
&& mxGetN(lead_lag_incidence_mx) == static_cast<size_t>(nEndo)))
|
||||
mexErrMsgTxt("M_.lead_lag_incidence should be a real dense matrix with 3 rows and M_.endo_nbr columns");
|
||||
ConstTwoDMatrix llincidence{lead_lag_incidence_mx};
|
||||
mexErrMsgTxt("M_.lead_lag_incidence should be a real dense matrix with 3 rows and "
|
||||
"M_.endo_nbr columns");
|
||||
ConstTwoDMatrix llincidence {lead_lag_incidence_mx};
|
||||
|
||||
const mxArray *nnzderivatives_mx = mxGetField(M_mx, 0, "NNZDerivatives");
|
||||
const mxArray* nnzderivatives_mx = mxGetField(M_mx, 0, "NNZDerivatives");
|
||||
if (!(nnzderivatives_mx && mxIsDouble(nnzderivatives_mx) && !mxIsComplex(nnzderivatives_mx)
|
||||
&& !mxIsSparse(nnzderivatives_mx)))
|
||||
mexErrMsgTxt("M_.NNZDerivatives should be a double precision array");
|
||||
ConstVector NNZD{nnzderivatives_mx};
|
||||
if (NNZD.length() < kOrder || NNZD[kOrder-1] == -1)
|
||||
mexErrMsgTxt("The derivatives were not computed for the required order. Make sure that you used the right order option inside the `stoch_simul' command");
|
||||
ConstVector NNZD {nnzderivatives_mx};
|
||||
if (NNZD.length() < kOrder || NNZD[kOrder - 1] == -1)
|
||||
mexErrMsgTxt("The derivatives were not computed for the required order. Make sure that you "
|
||||
"used the right order option inside the `stoch_simul' command");
|
||||
|
||||
const mxArray *endo_names_mx = mxGetField(M_mx, 0, "endo_names");
|
||||
if (!(endo_names_mx && mxIsCell(endo_names_mx) && mxGetNumberOfElements(endo_names_mx) == static_cast<size_t>(nEndo)))
|
||||
const mxArray* endo_names_mx = mxGetField(M_mx, 0, "endo_names");
|
||||
if (!(endo_names_mx && mxIsCell(endo_names_mx)
|
||||
&& mxGetNumberOfElements(endo_names_mx) == static_cast<size_t>(nEndo)))
|
||||
mexErrMsgTxt("M_.endo_names should be a cell array of M_.endo_nbr elements");
|
||||
std::vector<std::string> endoNames = DynareMxArrayToString(endo_names_mx);
|
||||
|
||||
const mxArray *exo_names_mx = mxGetField(M_mx, 0, "exo_names");
|
||||
if (!(exo_names_mx && mxIsCell(exo_names_mx) && mxGetNumberOfElements(exo_names_mx) == static_cast<size_t>(nExog)))
|
||||
const mxArray* exo_names_mx = mxGetField(M_mx, 0, "exo_names");
|
||||
if (!(exo_names_mx && mxIsCell(exo_names_mx)
|
||||
&& mxGetNumberOfElements(exo_names_mx) == static_cast<size_t>(nExog)))
|
||||
mexErrMsgTxt("M_.exo_names should be a cell array of M_.exo_nbr elements");
|
||||
std::vector<std::string> exoNames = DynareMxArrayToString(exo_names_mx);
|
||||
|
||||
const mxArray *dynamic_tmp_nbr_mx = mxGetField(M_mx, 0, "dynamic_tmp_nbr");
|
||||
const mxArray* dynamic_tmp_nbr_mx = mxGetField(M_mx, 0, "dynamic_tmp_nbr");
|
||||
if (!(dynamic_tmp_nbr_mx && mxIsDouble(dynamic_tmp_nbr_mx) && !mxIsComplex(dynamic_tmp_nbr_mx)
|
||||
&& !mxIsSparse(dynamic_tmp_nbr_mx)
|
||||
&& mxGetNumberOfElements(dynamic_tmp_nbr_mx) >= static_cast<size_t>(kOrder+1)))
|
||||
mexErrMsgTxt("M_.dynamic_tmp_nbr should be a real dense array with strictly more elements than the order of derivation");
|
||||
int ntt = std::accumulate(mxGetPr(dynamic_tmp_nbr_mx), mxGetPr(dynamic_tmp_nbr_mx)+kOrder+1, 0);
|
||||
&& mxGetNumberOfElements(dynamic_tmp_nbr_mx) >= static_cast<size_t>(kOrder + 1)))
|
||||
mexErrMsgTxt("M_.dynamic_tmp_nbr should be a real dense array with strictly more elements "
|
||||
"than the order of derivation");
|
||||
int ntt
|
||||
= std::accumulate(mxGetPr(dynamic_tmp_nbr_mx), mxGetPr(dynamic_tmp_nbr_mx) + kOrder + 1, 0);
|
||||
|
||||
// Extract various fields from dr
|
||||
const mxArray *ys_mx = mxGetField(dr_mx, 0, "ys"); // and not in order of dr.order_var
|
||||
const mxArray* ys_mx = mxGetField(dr_mx, 0, "ys"); // and not in order of dr.order_var
|
||||
if (!(ys_mx && mxIsDouble(ys_mx) && !mxIsComplex(ys_mx) && !mxIsSparse(ys_mx)))
|
||||
mexErrMsgTxt("dr.ys should be a real dense array");
|
||||
Vector ySteady{ConstVector{ys_mx}};
|
||||
Vector ySteady {ConstVector {ys_mx}};
|
||||
if (!ySteady.isFinite())
|
||||
mexErrMsgTxt("dr.ys contains NaN or Inf");
|
||||
|
||||
const mxArray *order_var_mx = mxGetField(dr_mx, 0, "order_var");
|
||||
if (!(order_var_mx && mxIsDouble(order_var_mx) && !mxIsComplex(order_var_mx) && !mxIsSparse(order_var_mx)
|
||||
const mxArray* order_var_mx = mxGetField(dr_mx, 0, "order_var");
|
||||
if (!(order_var_mx && mxIsDouble(order_var_mx) && !mxIsComplex(order_var_mx)
|
||||
&& !mxIsSparse(order_var_mx)
|
||||
&& mxGetNumberOfElements(order_var_mx) == static_cast<size_t>(nEndo)))
|
||||
mexErrMsgTxt("dr.order_var should be a real dense array of M_.endo_nbr elements");
|
||||
std::vector<int> dr_order(nEndo);
|
||||
std::transform(mxGetPr(order_var_mx), mxGetPr(order_var_mx)+nEndo, dr_order.begin(),
|
||||
[](double x) { return static_cast<int>(x)-1; });
|
||||
std::transform(mxGetPr(order_var_mx), mxGetPr(order_var_mx) + nEndo, dr_order.begin(),
|
||||
[](double x) { return static_cast<int>(x) - 1; });
|
||||
|
||||
const int nSteps = 0; // Dynare++ solving steps, for time being default to 0 = deterministic steady state
|
||||
const int nSteps
|
||||
= 0; // Dynare++ solving steps, for time being default to 0 = deterministic steady state
|
||||
|
||||
try
|
||||
{
|
||||
// Journal is not written on-disk, unless options_.debug = true (see #1735)
|
||||
Journal journal;
|
||||
if (debug)
|
||||
journal = Journal{fname + ".jnl"};
|
||||
journal = Journal {fname + ".jnl"};
|
||||
|
||||
std::unique_ptr<DynamicModelAC> dynamicModelFile;
|
||||
if (use_dll)
|
||||
|
@ -226,15 +234,14 @@ extern "C" {
|
|||
dynamicModelFile = std::make_unique<DynamicModelMFile>(fname, ntt);
|
||||
|
||||
// intiate tensor library
|
||||
TLStatic::init(kOrder, nStat+2*nPred+3*nBoth+2*nForw+nExog);
|
||||
TLStatic::init(kOrder, nStat + 2 * nPred + 3 * nBoth + 2 * nForw + nExog);
|
||||
|
||||
// Set number of parallel threads
|
||||
sthread::detach_thread_group::max_parallel_threads = num_threads;
|
||||
|
||||
// make KordpDynare object
|
||||
KordpDynare dynare(endoNames, exoNames, nExog, nPar,
|
||||
ySteady, vCov, modParams, nStat, nPred, nForw, nBoth,
|
||||
NNZD, nSteps, kOrder, journal, std::move(dynamicModelFile),
|
||||
KordpDynare dynare(endoNames, exoNames, nExog, nPar, ySteady, vCov, modParams, nStat, nPred,
|
||||
nForw, nBoth, NNZD, nSteps, kOrder, journal, std::move(dynamicModelFile),
|
||||
dr_order, llincidence);
|
||||
|
||||
// construct main K-order approximation class
|
||||
|
@ -242,53 +249,53 @@ extern "C" {
|
|||
// run stochastic steady
|
||||
app.walkStochSteady();
|
||||
|
||||
const FoldDecisionRule &fdr = app.getFoldDecisionRule();
|
||||
const FoldDecisionRule& fdr = app.getFoldDecisionRule();
|
||||
|
||||
// Add possibly missing field names
|
||||
for (int i = static_cast<int>(g_fieldnames.size()); i <= kOrder; i++)
|
||||
g_fieldnames.emplace_back("g_" + std::to_string(i));
|
||||
// Create structure for storing derivatives in Dynare++ format
|
||||
const char *g_fieldnames_c[kOrder+1];
|
||||
const char* g_fieldnames_c[kOrder + 1];
|
||||
for (int i = 0; i <= kOrder; i++)
|
||||
g_fieldnames_c[i] = g_fieldnames[i].c_str();
|
||||
|
||||
|
||||
if (pruning)
|
||||
{
|
||||
std::vector<std::string> g_fieldnames_pruning(g_fieldnames);
|
||||
std::vector<std::string> g_fieldnames_pruning(g_fieldnames);
|
||||
g_fieldnames_pruning.emplace_back("pruning");
|
||||
const char *g_fieldnames_pruning_c[kOrder+2];
|
||||
std::copy_n(g_fieldnames_c, kOrder+1, g_fieldnames_pruning_c);
|
||||
g_fieldnames_pruning_c[kOrder+1] = g_fieldnames_pruning.back().c_str();
|
||||
plhs[0] = mxCreateStructMatrix(1, 1, kOrder+2, g_fieldnames_pruning_c);
|
||||
const char* g_fieldnames_pruning_c[kOrder + 2];
|
||||
std::copy_n(g_fieldnames_c, kOrder + 1, g_fieldnames_pruning_c);
|
||||
g_fieldnames_pruning_c[kOrder + 1] = g_fieldnames_pruning.back().c_str();
|
||||
plhs[0] = mxCreateStructMatrix(1, 1, kOrder + 2, g_fieldnames_pruning_c);
|
||||
}
|
||||
else
|
||||
plhs[0] = mxCreateStructMatrix(1, 1, kOrder+1, g_fieldnames_c);
|
||||
plhs[0] = mxCreateStructMatrix(1, 1, kOrder + 1, g_fieldnames_c);
|
||||
|
||||
// Fill that structure
|
||||
for (int i = 0; i <= kOrder; i++)
|
||||
{
|
||||
const FFSTensor &t = fdr.get(Symmetry{i});
|
||||
mxArray *tmp = mxCreateDoubleMatrix(t.nrows(), t.ncols(), mxREAL);
|
||||
const ConstVector &vec = t.getData();
|
||||
const FFSTensor& t = fdr.get(Symmetry {i});
|
||||
mxArray* tmp = mxCreateDoubleMatrix(t.nrows(), t.ncols(), mxREAL);
|
||||
const ConstVector& vec = t.getData();
|
||||
assert(vec.skip() == 1);
|
||||
std::copy_n(vec.base(), vec.length(), mxGetPr(tmp));
|
||||
mxSetField(plhs[0], 0, g_fieldnames_c[i], tmp);
|
||||
}
|
||||
|
||||
// Filling the output elements for pruning
|
||||
// Filling the output elements for pruning
|
||||
if (pruning)
|
||||
{
|
||||
const UnfoldDecisionRule &udr_pruning = app.getUnfoldDecisionRulePruning();
|
||||
const UnfoldDecisionRule& udr_pruning = app.getUnfoldDecisionRulePruning();
|
||||
|
||||
mxArray *dr_pruning = mxCreateStructMatrix(1, 1, kOrder+1, g_fieldnames_c);
|
||||
mxArray* dr_pruning = mxCreateStructMatrix(1, 1, kOrder + 1, g_fieldnames_c);
|
||||
mxSetField(plhs[0], 0, "pruning", dr_pruning);
|
||||
|
||||
// Fill that structure
|
||||
for (int i = 0; i <= kOrder; i++)
|
||||
{
|
||||
const UFSTensor &t = udr_pruning.get(Symmetry{i});
|
||||
mxArray *tmp = mxCreateDoubleMatrix(t.nrows(), t.ncols(), mxREAL);
|
||||
const ConstVector &vec = t.getData();
|
||||
const UFSTensor& t = udr_pruning.get(Symmetry {i});
|
||||
mxArray* tmp = mxCreateDoubleMatrix(t.nrows(), t.ncols(), mxREAL);
|
||||
const ConstVector& vec = t.getData();
|
||||
assert(vec.skip() == 1);
|
||||
std::copy_n(vec.base(), vec.length(), mxGetPr(tmp));
|
||||
mxSetField(dr_pruning, 0, g_fieldnames_c[i], tmp);
|
||||
|
@ -300,55 +307,58 @@ extern "C" {
|
|||
/* Return as 3rd argument a struct containing derivatives in Dynare
|
||||
format (unfolded matrices, without Taylor coefficient) up to 3rd
|
||||
order */
|
||||
const FGSContainer &derivs = app.get_rule_ders();
|
||||
const FGSContainer& derivs = app.get_rule_ders();
|
||||
|
||||
size_t nfields = (kOrder == 1 ? 2 : (kOrder == 2 ? 6 : 12));
|
||||
const char *c_fieldnames[] = { "gy", "gu", "gyy", "gyu", "guu", "gss",
|
||||
"gyyy", "gyyu", "gyuu", "guuu", "gyss", "guss" };
|
||||
const char* c_fieldnames[] = {"gy", "gu", "gyy", "gyu", "guu", "gss",
|
||||
"gyyy", "gyyu", "gyuu", "guuu", "gyss", "guss"};
|
||||
plhs[1] = mxCreateStructMatrix(1, 1, nfields, c_fieldnames);
|
||||
|
||||
copy_derivatives(plhs[1], Symmetry{1, 0, 0, 0}, derivs, "gy");
|
||||
copy_derivatives(plhs[1], Symmetry{0, 1, 0, 0}, derivs, "gu");
|
||||
copy_derivatives(plhs[1], Symmetry {1, 0, 0, 0}, derivs, "gy");
|
||||
copy_derivatives(plhs[1], Symmetry {0, 1, 0, 0}, derivs, "gu");
|
||||
if (kOrder >= 2)
|
||||
{
|
||||
copy_derivatives(plhs[1], Symmetry{2, 0, 0, 0}, derivs, "gyy");
|
||||
copy_derivatives(plhs[1], Symmetry{0, 2, 0, 0}, derivs, "guu");
|
||||
copy_derivatives(plhs[1], Symmetry{1, 1, 0, 0}, derivs, "gyu");
|
||||
copy_derivatives(plhs[1], Symmetry{0, 0, 0, 2}, derivs, "gss");
|
||||
copy_derivatives(plhs[1], Symmetry {2, 0, 0, 0}, derivs, "gyy");
|
||||
copy_derivatives(plhs[1], Symmetry {0, 2, 0, 0}, derivs, "guu");
|
||||
copy_derivatives(plhs[1], Symmetry {1, 1, 0, 0}, derivs, "gyu");
|
||||
copy_derivatives(plhs[1], Symmetry {0, 0, 0, 2}, derivs, "gss");
|
||||
}
|
||||
if (kOrder >= 3)
|
||||
{
|
||||
copy_derivatives(plhs[1], Symmetry{3, 0, 0, 0}, derivs, "gyyy");
|
||||
copy_derivatives(plhs[1], Symmetry{0, 3, 0, 0}, derivs, "guuu");
|
||||
copy_derivatives(plhs[1], Symmetry{2, 1, 0, 0}, derivs, "gyyu");
|
||||
copy_derivatives(plhs[1], Symmetry{1, 2, 0, 0}, derivs, "gyuu");
|
||||
copy_derivatives(plhs[1], Symmetry{1, 0, 0, 2}, derivs, "gyss");
|
||||
copy_derivatives(plhs[1], Symmetry{0, 1, 0, 2}, derivs, "guss");
|
||||
copy_derivatives(plhs[1], Symmetry {3, 0, 0, 0}, derivs, "gyyy");
|
||||
copy_derivatives(plhs[1], Symmetry {0, 3, 0, 0}, derivs, "guuu");
|
||||
copy_derivatives(plhs[1], Symmetry {2, 1, 0, 0}, derivs, "gyyu");
|
||||
copy_derivatives(plhs[1], Symmetry {1, 2, 0, 0}, derivs, "gyuu");
|
||||
copy_derivatives(plhs[1], Symmetry {1, 0, 0, 2}, derivs, "gyss");
|
||||
copy_derivatives(plhs[1], Symmetry {0, 1, 0, 2}, derivs, "guss");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (const KordException &e)
|
||||
catch (const KordException& e)
|
||||
{
|
||||
e.print();
|
||||
mexErrMsgTxt(("dynare:k_order_perturbation: Caught Kord exception: " + e.get_message()).c_str());
|
||||
mexErrMsgTxt(
|
||||
("dynare:k_order_perturbation: Caught Kord exception: " + e.get_message()).c_str());
|
||||
}
|
||||
catch (const TLException &e)
|
||||
catch (const TLException& e)
|
||||
{
|
||||
e.print();
|
||||
mexErrMsgTxt("dynare:k_order_perturbation: Caught TL exception");
|
||||
}
|
||||
catch (SylvException &e)
|
||||
catch (SylvException& e)
|
||||
{
|
||||
e.printMessage();
|
||||
mexErrMsgTxt("dynare:k_order_perturbation: Caught Sylv exception");
|
||||
}
|
||||
catch (const DynareException &e)
|
||||
catch (const DynareException& e)
|
||||
{
|
||||
mexErrMsgTxt(("dynare:k_order_perturbation: Caught KordDynare exception: " + e.message()).c_str());
|
||||
mexErrMsgTxt(
|
||||
("dynare:k_order_perturbation: Caught KordDynare exception: " + e.message()).c_str());
|
||||
}
|
||||
catch (const ogu::Exception &e)
|
||||
catch (const ogu::Exception& e)
|
||||
{
|
||||
mexErrMsgTxt(("dynare:k_order_perturbation: Caught general exception: " + e.message()).c_str());
|
||||
mexErrMsgTxt(
|
||||
("dynare:k_order_perturbation: Caught general exception: " + e.message()).c_str());
|
||||
}
|
||||
} // end of mexFunction()
|
||||
} // end of extern C
|
||||
|
|
|
@ -24,38 +24,32 @@
|
|||
* The main has been derived from mxFunction used for K-Order DLL
|
||||
***************************************/
|
||||
|
||||
//#include "stdafx.h"
|
||||
#include "k_ord_dynare.h"
|
||||
// #include "stdafx.h"
|
||||
#include "dynamic_dll.h"
|
||||
#include "k_ord_dynare.h"
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
|
||||
double qz_criterium = 1+1e-6;
|
||||
double qz_criterium = 1 + 1e-6;
|
||||
const int check_flag = 0;
|
||||
const char *fName = "./fs2000k"; //mxArrayToString(mFname);
|
||||
const char *dfExt = ".mexa64"; //Dynamic file extension, e.g.".dll";
|
||||
const char* fName = "./fs2000k"; // mxArrayToString(mFname);
|
||||
const char* dfExt = ".mexa64"; // Dynamic file extension, e.g.".dll";
|
||||
|
||||
#ifdef DEBUG
|
||||
mexPrintf("k_order_perturbation: check_flag = %d , fName = %s .\n", check_flag, fName);
|
||||
#endif
|
||||
int kOrder = 2;
|
||||
int npar = 7; //(int)mxGetM(mxFldp);
|
||||
double dparams[7] = { 0.3300,
|
||||
0.9900,
|
||||
0.0030,
|
||||
1.0110,
|
||||
0.7000,
|
||||
0.7870,
|
||||
0.0200};
|
||||
Vector *modParams = new Vector(dparams, npar);
|
||||
double dparams[7] = {0.3300, 0.9900, 0.0030, 1.0110, 0.7000, 0.7870, 0.0200};
|
||||
Vector* modParams = new Vector(dparams, npar);
|
||||
|
||||
#ifdef DEBUG
|
||||
mexPrintf("k_ord_perturbation: nParams=%d .\n", npar);
|
||||
for (int i = 0; i < npar; i++)
|
||||
{
|
||||
mexPrintf("k_ord_perturbation: dParams[%d]= %g.\n", i, dparams+i*(sizeof(double)));
|
||||
mexPrintf("k_ord_perturbation: dParams[%d]= %g.\n", i, dparams + i * (sizeof(double)));
|
||||
}
|
||||
for (int i = 0; i < npar; i++)
|
||||
{
|
||||
|
@ -64,102 +58,86 @@ main(int argc, char *argv[])
|
|||
|
||||
#endif
|
||||
|
||||
double d2Dparams[4] = { //(double *) mxGetData(mxFldp);
|
||||
0.1960e-3, 0.0,
|
||||
0.0, 0.0250e-3
|
||||
};
|
||||
double d2Dparams[4] = {//(double *) mxGetData(mxFldp);
|
||||
0.1960e-3, 0.0, 0.0, 0.0250e-3};
|
||||
npar = 2; //(int)mxGetN(mxFldp);
|
||||
TwoDMatrix *vCov = new TwoDMatrix(npar, npar, (d2Dparams));
|
||||
double dYSparams[16] = { // 27 mxGetData(mxFldp);
|
||||
// 1.0110, 2.2582, 5.8012, 0.5808,
|
||||
1.0110, 2.2582, 0.4477, 1.0000,
|
||||
4.5959, 1.0212, 5.8012, 0.8494,
|
||||
0.1872, 0.8604, 1.0030, 1.0080,
|
||||
0.5808, 1.0030, 2.2582, 0.4477
|
||||
//, 1.0110, 2.2582, 0.4477, 1.0000, 0.1872, 2.2582, 0.4477
|
||||
TwoDMatrix* vCov = new TwoDMatrix(npar, npar, (d2Dparams));
|
||||
double dYSparams[16] = {
|
||||
// 27 mxGetData(mxFldp);
|
||||
// 1.0110, 2.2582, 5.8012, 0.5808,
|
||||
1.0110, 2.2582, 0.4477, 1.0000, 4.5959, 1.0212, 5.8012, 0.8494, 0.1872,
|
||||
0.8604, 1.0030, 1.0080, 0.5808, 1.0030, 2.2582, 0.4477
|
||||
//, 1.0110, 2.2582, 0.4477, 1.0000, 0.1872, 2.2582, 0.4477
|
||||
};
|
||||
const int nSteady = 16; //27 //31;//29, 16 (int)mxGetM(mxFldp);
|
||||
Vector *ySteady = new Vector(dYSparams, nSteady);
|
||||
const int nSteady = 16; // 27 //31;//29, 16 (int)mxGetM(mxFldp);
|
||||
Vector* ySteady = new Vector(dYSparams, nSteady);
|
||||
|
||||
double nnzd[3] = { 77, 217, 0};
|
||||
const Vector *NNZD = new Vector(nnzd, 3);
|
||||
double nnzd[3] = {77, 217, 0};
|
||||
const Vector* NNZD = new Vector(nnzd, 3);
|
||||
|
||||
//mxFldp = mxGetField(dr, 0,"nstatic" );
|
||||
// mxFldp = mxGetField(dr, 0,"nstatic" );
|
||||
const int nStat = 7; //(int)mxGetScalar(mxFldp);
|
||||
// mxFldp = mxGetField(dr, 0,"npred" );
|
||||
const int nPred = 2; //6 - nBoth (int)mxGetScalar(mxFldp);
|
||||
//mxFldp = mxGetField(dr, 0,"nspred" );
|
||||
const int nPred = 2; // 6 - nBoth (int)mxGetScalar(mxFldp);
|
||||
// mxFldp = mxGetField(dr, 0,"nspred" );
|
||||
const int nsPred = 4; //(int)mxGetScalar(mxFldp);
|
||||
//mxFldp = mxGetField(dr, 0,"nboth" );
|
||||
// mxFldp = mxGetField(dr, 0,"nboth" );
|
||||
const int nBoth = 2; // (int)mxGetScalar(mxFldp);
|
||||
//mxFldp = mxGetField(dr, 0,"nfwrd" );
|
||||
// mxFldp = mxGetField(dr, 0,"nfwrd" );
|
||||
const int nForw = 5; // 3 (int)mxGetScalar(mxFldp);
|
||||
//mxFldp = mxGetField(dr, 0,"nsfwrd" );
|
||||
// mxFldp = mxGetField(dr, 0,"nsfwrd" );
|
||||
const int nsForw = 7; //(int)mxGetScalar(mxFldp);
|
||||
|
||||
//mxFldp = mxGetField(M_, 0,"exo_nbr" );
|
||||
// mxFldp = mxGetField(M_, 0,"exo_nbr" );
|
||||
const int nExog = 2; // (int)mxGetScalar(mxFldp);
|
||||
//mxFldp = mxGetField(M_, 0,"endo_nbr" );
|
||||
const int nEndo = 16; //16(int)mxGetScalar(mxFldp);
|
||||
//mxFldp = mxGetField(M_, 0,"param_nbr" );
|
||||
// mxFldp = mxGetField(M_, 0,"endo_nbr" );
|
||||
const int nEndo = 16; // 16(int)mxGetScalar(mxFldp);
|
||||
// mxFldp = mxGetField(M_, 0,"param_nbr" );
|
||||
const int nPar = 7; //(int)mxGetScalar(mxFldp);
|
||||
// it_ should be set to M_.maximum_lag
|
||||
//mxFldp = mxGetField(M_, 0,"maximum_lag" );
|
||||
// mxFldp = mxGetField(M_, 0,"maximum_lag" );
|
||||
const int nMax_lag = 1; //(int)mxGetScalar(mxFldp);
|
||||
|
||||
int var_order[] //[18]
|
||||
= {
|
||||
5, 6, 8, 10, 11, 12, 14, 7, 13, 1, 2, 3, 4, 9, 15, 16
|
||||
// 5, 6, 8, 10, 11, 12, 16, 7, 13, 14, 15, 1, 2, 3, 4, 9, 17, 18
|
||||
};
|
||||
//Vector * varOrder = new Vector(var_order, nEndo);
|
||||
vector<int> *var_order_vp = new vector<int>(nEndo); //nEndo));
|
||||
= {
|
||||
5, 6, 8, 10, 11, 12, 14, 7, 13,
|
||||
1, 2, 3, 4, 9, 15, 16
|
||||
// 5, 6, 8, 10, 11, 12, 16, 7, 13, 14, 15, 1, 2, 3, 4, 9, 17,
|
||||
// 18
|
||||
};
|
||||
// Vector * varOrder = new Vector(var_order, nEndo);
|
||||
vector<int>* var_order_vp = new vector<int>(nEndo); // nEndo));
|
||||
for (int v = 0; v < nEndo; v++)
|
||||
(*var_order_vp)[v] = var_order[v];
|
||||
|
||||
const double ll_incidence[] //[3][18]
|
||||
= {
|
||||
1, 5, 21,
|
||||
2, 6, 22,
|
||||
0, 7, 23,
|
||||
0, 8, 24,
|
||||
0, 9, 0,
|
||||
0, 10, 0,
|
||||
3, 11, 0,
|
||||
0, 12, 0,
|
||||
0, 13, 25,
|
||||
0, 14, 0,
|
||||
0, 15, 0,
|
||||
0, 16, 0,
|
||||
4, 17, 0,
|
||||
0, 18, 0,
|
||||
0, 19, 26,
|
||||
0, 20, 27
|
||||
};
|
||||
TwoDMatrix *llincidence = new TwoDMatrix(3, nEndo, ll_incidence);
|
||||
= {1, 5, 21, 2, 6, 22, 0, 7, 23, 0, 8, 24, 0, 9, 0, 0, 10, 0, 3, 11, 0, 0, 12, 0,
|
||||
0, 13, 25, 0, 14, 0, 0, 15, 0, 0, 16, 0, 4, 17, 0, 0, 18, 0, 0, 19, 26, 0, 20, 27};
|
||||
TwoDMatrix* llincidence = new TwoDMatrix(3, nEndo, ll_incidence);
|
||||
|
||||
const int jcols = nExog+nEndo+nsPred+nsForw; // Num of Jacobian columns
|
||||
const int jcols = nExog + nEndo + nsPred + nsForw; // Num of Jacobian columns
|
||||
#ifdef DEBUG
|
||||
mexPrintf("k_order_perturbation: jcols= %d .\n", jcols);
|
||||
#endif
|
||||
//mxFldp= mxGetField(M_, 0,"endo_names" );
|
||||
const int nendo = 16; //16(int)mxGetM(mxFldp);
|
||||
// mxFldp= mxGetField(M_, 0,"endo_names" );
|
||||
const int nendo = 16; // 16(int)mxGetM(mxFldp);
|
||||
const int widthEndo = 6; // (int)mxGetN(mxFldp);
|
||||
const char *cNamesCharStr = "mPceWRkdnlggydPc yp A22 __ oo bb ss ";
|
||||
const char* cNamesCharStr = "mPceWRkdnlggydPc yp A22 __ oo "
|
||||
" bb ss ";
|
||||
// const char** endoNamesMX= DynareMxArrayToString( mxFldp,nendo,widthEndo);
|
||||
const char **endoNamesMX = DynareMxArrayToString(cNamesCharStr, nendo, widthEndo);
|
||||
const char** endoNamesMX = DynareMxArrayToString(cNamesCharStr, nendo, widthEndo);
|
||||
#ifdef DEBUG
|
||||
for (int i = 0; i < nEndo; i++)
|
||||
{
|
||||
mexPrintf("k_ord_perturbation: EndoNameList[%d][0]= %s.\n", i, endoNamesMX[i]);
|
||||
}
|
||||
#endif
|
||||
//mxFldp = mxGetField(M_, 0,"exo_names" );
|
||||
const int nexo = 2; //(int)mxGetM(mxFldp);
|
||||
// mxFldp = mxGetField(M_, 0,"exo_names" );
|
||||
const int nexo = 2; //(int)mxGetM(mxFldp);
|
||||
const int widthExog = 3; //(int)mxGetN(mxFldp);
|
||||
// const char** exoNamesMX= DynareMxArrayToString( mxFldp,nexo,widthExog);
|
||||
const char *cExoNamesCharStr = "ee__am";
|
||||
const char **exoNamesMX = DynareMxArrayToString(cExoNamesCharStr, nexo, widthExog);
|
||||
const char* cExoNamesCharStr = "ee__am";
|
||||
const char** exoNamesMX = DynareMxArrayToString(cExoNamesCharStr, nexo, widthExog);
|
||||
#ifdef DEBUG
|
||||
for (int i = 0; i < nexo; i++)
|
||||
{
|
||||
|
@ -193,15 +171,16 @@ main(int argc, char *argv[])
|
|||
/* Fetch time index */
|
||||
// int it_ = (int) mxGetScalar(prhs[3]) - 1;
|
||||
|
||||
const int nSteps = 0; // Dynare++ solving steps, for time being default to 0 = deterministic steady state
|
||||
const double sstol = 1.e-13; //NL solver tolerance from
|
||||
const int nSteps
|
||||
= 0; // Dynare++ solving steps, for time being default to 0 = deterministic steady state
|
||||
const double sstol = 1.e-13; // NL solver tolerance from
|
||||
|
||||
THREAD_GROUP::max_parallel_threads = 1; //2 params.num_threads;
|
||||
THREAD_GROUP::max_parallel_threads = 1; // 2 params.num_threads;
|
||||
|
||||
try
|
||||
{
|
||||
// make journal name and journal
|
||||
std::string jName(fName); //params.basename);
|
||||
std::string jName(fName); // params.basename);
|
||||
jName += ".jnl";
|
||||
Journal journal(jName.c_str());
|
||||
|
||||
|
@ -209,7 +188,7 @@ main(int argc, char *argv[])
|
|||
mexPrintf("k_order_perturbation: Call tls init\n");
|
||||
#endif
|
||||
|
||||
tls.init(kOrder, (nStat+2*nPred+3*nBoth+2*nForw+nExog));
|
||||
tls.init(kOrder, (nStat + 2 * nPred + 3 * nBoth + 2 * nForw + nExog));
|
||||
|
||||
#ifdef DEBUG
|
||||
mexPrintf("k_order_perturbation: Calling dynamicDLL constructor.\n");
|
||||
|
@ -221,8 +200,8 @@ main(int argc, char *argv[])
|
|||
#endif
|
||||
// make KordpDynare object
|
||||
KordpDynare dynare(endoNamesMX, nEndo, exoNamesMX, nExog, nPar, // paramNames,
|
||||
ySteady, vCov, modParams, nStat, nPred, nForw, nBoth,
|
||||
jcols, NNZD, nSteps, kOrder, journal, dynamicDLL, sstol, var_order_vp, //var_order
|
||||
ySteady, vCov, modParams, nStat, nPred, nForw, nBoth, jcols, NNZD, nSteps,
|
||||
kOrder, journal, dynamicDLL, sstol, var_order_vp, // var_order
|
||||
llincidence, qz_criterium);
|
||||
#ifdef DEBUG
|
||||
mexPrintf("k_order_perturbation: Call Approximation constructor \n");
|
||||
|
@ -237,7 +216,7 @@ main(int argc, char *argv[])
|
|||
// open mat file
|
||||
std::string matfile(fName); //(params.basename);
|
||||
matfile += ".mat";
|
||||
FILE *matfd = NULL;
|
||||
FILE* matfd = NULL;
|
||||
if (NULL == (matfd = fopen(matfile.c_str(), "wb")))
|
||||
{
|
||||
fprintf(stderr, "Couldn't open %s for writing.\n", matfile.c_str());
|
||||
|
@ -247,12 +226,12 @@ main(int argc, char *argv[])
|
|||
#ifdef DEBUG
|
||||
mexPrintf("k_order_perturbation: Filling Mat file outputs.\n");
|
||||
#endif
|
||||
std::string ss_matrix_name(fName); //params.prefix);
|
||||
std::string ss_matrix_name(fName); // params.prefix);
|
||||
ss_matrix_name += "_steady_states";
|
||||
ConstTwoDMatrix(app.getSS()).writeMat4(matfd, ss_matrix_name.c_str());
|
||||
|
||||
// write the folded decision rule to the Mat-4 file
|
||||
app.getFoldDecisionRule().writeMat4(matfd, fName); //params.prefix);
|
||||
app.getFoldDecisionRule().writeMat4(matfd, fName); // params.prefix);
|
||||
|
||||
fclose(matfd);
|
||||
|
||||
|
@ -261,8 +240,7 @@ main(int argc, char *argv[])
|
|||
#ifdef DEBUG
|
||||
app.getFoldDecisionRule().print();
|
||||
mexPrintf("k_order_perturbation: Map print: \n");
|
||||
for (map<string, ConstTwoDMatrix>::const_iterator cit = mm.begin();
|
||||
cit != mm.end(); ++cit)
|
||||
for (map<string, ConstTwoDMatrix>::const_iterator cit = mm.begin(); cit != mm.end(); ++cit)
|
||||
{
|
||||
mexPrintf("k_order_perturbation: Map print: string: %s , g:\n", (*cit).first.c_str());
|
||||
(*cit).second.print();
|
||||
|
@ -270,33 +248,33 @@ main(int argc, char *argv[])
|
|||
#endif
|
||||
|
||||
// get latest ysteady
|
||||
double *dYsteady = (dynare.getSteady().base());
|
||||
ySteady = (Vector *) (&dynare.getSteady());
|
||||
double* dYsteady = (dynare.getSteady().base());
|
||||
ySteady = (Vector*)(&dynare.getSteady());
|
||||
}
|
||||
catch (const KordException &e)
|
||||
catch (const KordException& e)
|
||||
{
|
||||
printf("Caugth Kord exception: ");
|
||||
e.print();
|
||||
return 1; // e.code();
|
||||
}
|
||||
catch (const TLException &e)
|
||||
catch (const TLException& e)
|
||||
{
|
||||
printf("Caugth TL exception: ");
|
||||
e.print();
|
||||
return 2; // 255;
|
||||
}
|
||||
catch (SylvException &e)
|
||||
catch (SylvException& e)
|
||||
{
|
||||
printf("Caught Sylv exception: ");
|
||||
e.printMessage();
|
||||
return 3; // 255;
|
||||
}
|
||||
catch (const DynareException &e)
|
||||
catch (const DynareException& e)
|
||||
{
|
||||
printf("Caught KordpDynare exception: %s\n", e.message());
|
||||
return 4; // 255;
|
||||
}
|
||||
catch (const ogu::Exception &e)
|
||||
catch (const ogu::Exception& e)
|
||||
{
|
||||
printf("Caught ogu::Exception: ");
|
||||
e.print();
|
||||
|
@ -307,8 +285,8 @@ main(int argc, char *argv[])
|
|||
const int nrhs = 5;
|
||||
const int nlhs = 2;
|
||||
|
||||
mxArray *prhs[nrhs];
|
||||
mxArray *plhs[nlhs];
|
||||
mxArray* prhs[nrhs];
|
||||
mxArray* plhs[nlhs];
|
||||
|
||||
#ifdef DEBUG
|
||||
mexPrintf("k_order_perturbation: Filling MATLAB outputs.\n");
|
||||
|
|
|
@ -20,11 +20,16 @@
|
|||
|
||||
#include <utility>
|
||||
|
||||
#include "kord_exception.hh"
|
||||
#include "approximation_welfare.hh"
|
||||
#include "kord_exception.hh"
|
||||
|
||||
ApproximationWelfare::ApproximationWelfare(KordwDynare &w, double discount_factor_arg, const FGSContainer &rule_ders_arg, const FGSContainer &rule_ders_s_arg, Journal &j)
|
||||
: welfare{w}, discount_factor(discount_factor_arg), nvs{welfare.getModel().nys(), welfare.getModel().nexog(), welfare.getModel().nexog(), 1}, journal{j}
|
||||
ApproximationWelfare::ApproximationWelfare(KordwDynare& w, double discount_factor_arg,
|
||||
const FGSContainer& rule_ders_arg,
|
||||
const FGSContainer& rule_ders_s_arg, Journal& j) :
|
||||
welfare {w},
|
||||
discount_factor(discount_factor_arg), nvs {welfare.getModel().nys(), welfare.getModel().nexog(),
|
||||
welfare.getModel().nexog(), 1},
|
||||
journal {j}
|
||||
{
|
||||
rule_ders = std::make_unique<FGSContainer>(rule_ders_arg);
|
||||
rule_ders_s = std::make_unique<FGSContainer>(rule_ders_s_arg);
|
||||
|
@ -38,25 +43,32 @@ void
|
|||
ApproximationWelfare::approxAtSteady()
|
||||
{
|
||||
welfare.calcDerivativesAtSteady();
|
||||
KOrderWelfare korderwel(welfare.getModel().nstat(), welfare.getModel().npred(), welfare.getModel().nboth(), welfare.getModel().nforw(), welfare.getModel().nexog(), welfare.getModel().order(), discount_factor, welfare.getPlannerObjDerivatives(), get_rule_ders(), get_rule_ders_s(), welfare.getModel().getVcov(), journal);
|
||||
KOrderWelfare korderwel(welfare.getModel().nstat(), welfare.getModel().npred(),
|
||||
welfare.getModel().nboth(), welfare.getModel().nforw(),
|
||||
welfare.getModel().nexog(), welfare.getModel().order(), discount_factor,
|
||||
welfare.getPlannerObjDerivatives(), get_rule_ders(), get_rule_ders_s(),
|
||||
welfare.getModel().getVcov(), journal);
|
||||
for (int k = 1; k <= welfare.getModel().order(); k++)
|
||||
korderwel.performStep<Storage::fold>(k);
|
||||
saveRuleDerivs(korderwel.getFoldW());
|
||||
|
||||
// construct the resulting decision rule
|
||||
cond_fdr = std::make_unique<FoldDecisionRule>(*cond_ders, welfare.getModel().nys(), welfare.getModel().nexog(), welfare.getModel().getSteady());
|
||||
cond_fdr = std::make_unique<FoldDecisionRule>(*cond_ders, welfare.getModel().nys(),
|
||||
welfare.getModel().nexog(),
|
||||
welfare.getModel().getSteady());
|
||||
}
|
||||
|
||||
const FoldDecisionRule &
|
||||
const FoldDecisionRule&
|
||||
ApproximationWelfare::getFoldCondWel() const
|
||||
{
|
||||
KORD_RAISE_IF(!cond_fdr,
|
||||
"Folded decision rule has not been created in ApproximationWelfare::getFoldCondWel");
|
||||
KORD_RAISE_IF(
|
||||
!cond_fdr,
|
||||
"Folded decision rule has not been created in ApproximationWelfare::getFoldCondWel");
|
||||
return *cond_fdr;
|
||||
}
|
||||
|
||||
void
|
||||
ApproximationWelfare::saveRuleDerivs(const FGSContainer &W)
|
||||
ApproximationWelfare::saveRuleDerivs(const FGSContainer& W)
|
||||
{
|
||||
cond_ders = std::make_unique<FGSContainer>(W);
|
||||
}
|
|
@ -20,50 +20,52 @@
|
|||
#ifndef APPROXIMATION_WELFARE_H
|
||||
#define APPROXIMATION_WELFARE_H
|
||||
|
||||
#include "k_ord_objective.hh"
|
||||
#include "journal.hh"
|
||||
#include "k_ord_objective.hh"
|
||||
|
||||
#include <memory>
|
||||
|
||||
class ApproximationWelfare
|
||||
{
|
||||
KordwDynare &welfare;
|
||||
KordwDynare& welfare;
|
||||
double discount_factor;
|
||||
std::unique_ptr<FGSContainer> rule_ders;
|
||||
std::unique_ptr<FGSContainer> rule_ders_s;
|
||||
std::unique_ptr<FGSContainer> cond_ders;
|
||||
std::unique_ptr<FoldDecisionRule> cond_fdr;
|
||||
IntSequence nvs;
|
||||
Journal &journal;
|
||||
public:
|
||||
ApproximationWelfare(KordwDynare &w, double discount_factor, const FGSContainer &rule_ders, const FGSContainer &rule_ders_s, Journal &j);
|
||||
Journal& journal;
|
||||
|
||||
const KordwDynare &
|
||||
public:
|
||||
ApproximationWelfare(KordwDynare& w, double discount_factor, const FGSContainer& rule_ders,
|
||||
const FGSContainer& rule_ders_s, Journal& j);
|
||||
|
||||
const KordwDynare&
|
||||
getWelfare() const
|
||||
{
|
||||
return welfare;
|
||||
}
|
||||
const FGSContainer &
|
||||
const FGSContainer&
|
||||
get_rule_ders() const
|
||||
{
|
||||
return *rule_ders;
|
||||
}
|
||||
const FGSContainer &
|
||||
const FGSContainer&
|
||||
get_rule_ders_s() const
|
||||
{
|
||||
return *rule_ders_s;
|
||||
}
|
||||
const FGSContainer &
|
||||
const FGSContainer&
|
||||
get_cond_ders() const
|
||||
{
|
||||
return *cond_ders;
|
||||
}
|
||||
const FoldDecisionRule & getFoldCondWel() const;
|
||||
const FoldDecisionRule& getFoldCondWel() const;
|
||||
|
||||
void approxAtSteady();
|
||||
|
||||
protected:
|
||||
void saveRuleDerivs(const FGSContainer &W);
|
||||
void saveRuleDerivs(const FGSContainer& W);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -20,11 +20,15 @@
|
|||
#include "k_ord_objective.hh"
|
||||
#include "objective_abstract_class.hh"
|
||||
|
||||
#include <utility>
|
||||
#include <cassert>
|
||||
#include <utility>
|
||||
|
||||
KordwDynare::KordwDynare(KordpDynare &m, ConstVector &NNZD_arg, Journal &jr, Vector &inParams, std::unique_ptr<ObjectiveAC> objectiveFile_arg, const std::vector<int> &dr_order) :
|
||||
model{m}, NNZD{NNZD_arg}, journal{jr}, params{inParams}, resid(1), ud{1}, objectiveFile{std::move(objectiveFile_arg)}
|
||||
KordwDynare::KordwDynare(KordpDynare& m, ConstVector& NNZD_arg, Journal& jr, Vector& inParams,
|
||||
std::unique_ptr<ObjectiveAC> objectiveFile_arg,
|
||||
const std::vector<int>& dr_order) :
|
||||
model {m},
|
||||
NNZD {NNZD_arg}, journal {jr}, params {inParams},
|
||||
resid(1), ud {1}, objectiveFile {std::move(objectiveFile_arg)}
|
||||
{
|
||||
dynppToDyn = dr_order;
|
||||
dynToDynpp.resize(model.ny());
|
||||
|
@ -38,14 +42,14 @@ KordwDynare::calcDerivativesAtSteady()
|
|||
|
||||
assert(ud.begin() == ud.end());
|
||||
|
||||
std::vector<TwoDMatrix> dyn_ud; // Planner's objective derivatives, in Dynare form
|
||||
std::vector<TwoDMatrix> dyn_ud; // Planner's objective derivatives, in Dynare form
|
||||
dyn_ud.emplace_back(1, model.ny()); // Allocate Jacobian
|
||||
dyn_ud.back().zeros();
|
||||
|
||||
for (int i = 2; i <= model.order(); i++)
|
||||
{
|
||||
// Higher order derivatives, as sparse (3-column) matrices
|
||||
dyn_ud.emplace_back(static_cast<int>(NNZD[i-1]), 3);
|
||||
dyn_ud.emplace_back(static_cast<int>(NNZD[i - 1]), 3);
|
||||
dyn_ud.back().zeros();
|
||||
}
|
||||
|
||||
|
@ -56,13 +60,12 @@ KordwDynare::calcDerivativesAtSteady()
|
|||
|
||||
for (int i = 1; i <= model.order(); i++)
|
||||
populateDerivativesContainer(dyn_ud, i);
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
KordwDynare::populateDerivativesContainer(const std::vector<TwoDMatrix> &dyn_ud, int ord)
|
||||
KordwDynare::populateDerivativesContainer(const std::vector<TwoDMatrix>& dyn_ud, int ord)
|
||||
{
|
||||
const TwoDMatrix &u = dyn_ud[ord-1];
|
||||
const TwoDMatrix& u = dyn_ud[ord - 1];
|
||||
|
||||
// utility derivatives FSSparseTensor instance
|
||||
auto udTi = std::make_unique<FSSparseTensor>(ord, model.ny(), 1);
|
||||
|
@ -83,8 +86,8 @@ KordwDynare::populateDerivativesContainer(const std::vector<TwoDMatrix> &dyn_ud,
|
|||
else // ord ≥ 2
|
||||
for (int i = 0; i < u.nrows(); i++)
|
||||
{
|
||||
int j = static_cast<int>(u.get(i, 0))-1;
|
||||
int i1 = static_cast<int>(u.get(i, 1))-1;
|
||||
int j = static_cast<int>(u.get(i, 0)) - 1;
|
||||
int i1 = static_cast<int>(u.get(i, 1)) - 1;
|
||||
if (j < 0 || i1 < 0)
|
||||
continue; // Discard empty entries (see comment in DynamicModelAC::unpackSparseMatrix())
|
||||
|
||||
|
@ -107,220 +110,213 @@ KordwDynare::populateDerivativesContainer(const std::vector<TwoDMatrix> &dyn_ud,
|
|||
}
|
||||
|
||||
template<>
|
||||
ctraits<Storage::unfold>::Tg &
|
||||
ctraits<Storage::unfold>::Tg&
|
||||
KOrderWelfare::g<Storage::unfold>()
|
||||
{
|
||||
return _ug;
|
||||
}
|
||||
template<>
|
||||
const ctraits<Storage::unfold>::Tg &
|
||||
const ctraits<Storage::unfold>::Tg&
|
||||
KOrderWelfare::g<Storage::unfold>() const
|
||||
{
|
||||
return _ug;
|
||||
}
|
||||
template<>
|
||||
ctraits<Storage::fold>::Tg &
|
||||
ctraits<Storage::fold>::Tg&
|
||||
KOrderWelfare::g<Storage::fold>()
|
||||
{
|
||||
return _fg;
|
||||
}
|
||||
template<>
|
||||
const ctraits<Storage::fold>::Tg &
|
||||
const ctraits<Storage::fold>::Tg&
|
||||
KOrderWelfare::g<Storage::fold>() const
|
||||
{
|
||||
return _fg;
|
||||
}
|
||||
template<>
|
||||
ctraits<Storage::unfold>::Tgs &
|
||||
ctraits<Storage::unfold>::Tgs&
|
||||
KOrderWelfare::gs<Storage::unfold>()
|
||||
{
|
||||
return _ugs;
|
||||
}
|
||||
template<>
|
||||
const ctraits<Storage::unfold>::Tgs &
|
||||
const ctraits<Storage::unfold>::Tgs&
|
||||
KOrderWelfare::gs<Storage::unfold>() const
|
||||
{
|
||||
return _ugs;
|
||||
}
|
||||
template<>
|
||||
ctraits<Storage::fold>::Tgs &
|
||||
ctraits<Storage::fold>::Tgs&
|
||||
KOrderWelfare::gs<Storage::fold>()
|
||||
{
|
||||
return _fgs;
|
||||
}
|
||||
template<>
|
||||
const ctraits<Storage::fold>::Tgs &
|
||||
const ctraits<Storage::fold>::Tgs&
|
||||
KOrderWelfare::gs<Storage::fold>() const
|
||||
{
|
||||
return _fgs;
|
||||
}
|
||||
|
||||
template<>
|
||||
ctraits<Storage::unfold>::TU &
|
||||
ctraits<Storage::unfold>::TU&
|
||||
KOrderWelfare::U<Storage::unfold>()
|
||||
{
|
||||
return _uU;
|
||||
}
|
||||
template<>
|
||||
const ctraits<Storage::unfold>::TU &
|
||||
const ctraits<Storage::unfold>::TU&
|
||||
KOrderWelfare::U<Storage::unfold>() const
|
||||
{
|
||||
return _uU;
|
||||
}
|
||||
template<>
|
||||
ctraits<Storage::fold>::TU &
|
||||
ctraits<Storage::fold>::TU&
|
||||
KOrderWelfare::U<Storage::fold>()
|
||||
{
|
||||
return _fU;
|
||||
}
|
||||
template<>
|
||||
const ctraits<Storage::fold>::TU &
|
||||
const ctraits<Storage::fold>::TU&
|
||||
KOrderWelfare::U<Storage::fold>() const
|
||||
{
|
||||
return _fU;
|
||||
}
|
||||
template<>
|
||||
ctraits<Storage::unfold>::TW &
|
||||
ctraits<Storage::unfold>::TW&
|
||||
KOrderWelfare::W<Storage::unfold>()
|
||||
{
|
||||
return _uW;
|
||||
}
|
||||
template<>
|
||||
const ctraits<Storage::unfold>::TW &
|
||||
const ctraits<Storage::unfold>::TW&
|
||||
KOrderWelfare::W<Storage::unfold>() const
|
||||
{
|
||||
return _uW;
|
||||
}
|
||||
template<>
|
||||
ctraits<Storage::fold>::TW &
|
||||
ctraits<Storage::fold>::TW&
|
||||
KOrderWelfare::W<Storage::fold>()
|
||||
{
|
||||
return _fW;
|
||||
}
|
||||
template<>
|
||||
const ctraits<Storage::fold>::TW &
|
||||
const ctraits<Storage::fold>::TW&
|
||||
KOrderWelfare::W<Storage::fold>() const
|
||||
{
|
||||
return _fW;
|
||||
}
|
||||
template<>
|
||||
ctraits<Storage::unfold>::TWrond &
|
||||
ctraits<Storage::unfold>::TWrond&
|
||||
KOrderWelfare::Wrond<Storage::unfold>()
|
||||
{
|
||||
return _uWrond;
|
||||
}
|
||||
template<>
|
||||
const ctraits<Storage::unfold>::TWrond &
|
||||
const ctraits<Storage::unfold>::TWrond&
|
||||
KOrderWelfare::Wrond<Storage::unfold>() const
|
||||
{
|
||||
return _uWrond;
|
||||
}
|
||||
template<>
|
||||
ctraits<Storage::fold>::TWrond &
|
||||
ctraits<Storage::fold>::TWrond&
|
||||
KOrderWelfare::Wrond<Storage::fold>()
|
||||
{
|
||||
return _fWrond;
|
||||
}
|
||||
template<>
|
||||
const ctraits<Storage::fold>::TWrond &
|
||||
const ctraits<Storage::fold>::TWrond&
|
||||
KOrderWelfare::Wrond<Storage::fold>() const
|
||||
{
|
||||
return _fWrond;
|
||||
}
|
||||
template<>
|
||||
ctraits<Storage::unfold>::TGstack &
|
||||
ctraits<Storage::unfold>::TGstack&
|
||||
KOrderWelfare::Gstack<Storage::unfold>()
|
||||
{
|
||||
return _uGstack;
|
||||
}
|
||||
template<>
|
||||
const ctraits<Storage::unfold>::TGstack &
|
||||
const ctraits<Storage::unfold>::TGstack&
|
||||
KOrderWelfare::Gstack<Storage::unfold>() const
|
||||
{
|
||||
return _uGstack;
|
||||
}
|
||||
template<>
|
||||
ctraits<Storage::fold>::TGstack &
|
||||
ctraits<Storage::fold>::TGstack&
|
||||
KOrderWelfare::Gstack<Storage::fold>()
|
||||
{
|
||||
return _fGstack;
|
||||
}
|
||||
template<>
|
||||
const ctraits<Storage::fold>::TGstack &
|
||||
const ctraits<Storage::fold>::TGstack&
|
||||
KOrderWelfare::Gstack<Storage::fold>() const
|
||||
{
|
||||
return _fGstack;
|
||||
}
|
||||
template<>
|
||||
ctraits<Storage::unfold>::TXstack &
|
||||
ctraits<Storage::unfold>::TXstack&
|
||||
KOrderWelfare::Xstack<Storage::unfold>()
|
||||
{
|
||||
return _uXstack;
|
||||
}
|
||||
template<>
|
||||
const ctraits<Storage::unfold>::TXstack &
|
||||
const ctraits<Storage::unfold>::TXstack&
|
||||
KOrderWelfare::Xstack<Storage::unfold>() const
|
||||
{
|
||||
return _uXstack;
|
||||
}
|
||||
template<>
|
||||
ctraits<Storage::fold>::TXstack &
|
||||
ctraits<Storage::fold>::TXstack&
|
||||
KOrderWelfare::Xstack<Storage::fold>()
|
||||
{
|
||||
return _fXstack;
|
||||
}
|
||||
template<>
|
||||
const ctraits<Storage::fold>::TXstack &
|
||||
const ctraits<Storage::fold>::TXstack&
|
||||
KOrderWelfare::Xstack<Storage::fold>() const
|
||||
{
|
||||
return _fXstack;
|
||||
}
|
||||
template<>
|
||||
ctraits<Storage::unfold>::Tm &
|
||||
ctraits<Storage::unfold>::Tm&
|
||||
KOrderWelfare::m<Storage::unfold>()
|
||||
{
|
||||
return _um;
|
||||
}
|
||||
template<>
|
||||
const ctraits<Storage::unfold>::Tm &
|
||||
const ctraits<Storage::unfold>::Tm&
|
||||
KOrderWelfare::m<Storage::unfold>() const
|
||||
{
|
||||
return _um;
|
||||
}
|
||||
template<>
|
||||
ctraits<Storage::fold>::Tm &
|
||||
ctraits<Storage::fold>::Tm&
|
||||
KOrderWelfare::m<Storage::fold>()
|
||||
{
|
||||
return _fm;
|
||||
}
|
||||
template<>
|
||||
const ctraits<Storage::fold>::Tm &
|
||||
const ctraits<Storage::fold>::Tm&
|
||||
KOrderWelfare::m<Storage::fold>() const
|
||||
{
|
||||
return _fm;
|
||||
}
|
||||
|
||||
KOrderWelfare::KOrderWelfare(int num_stat, int num_pred,
|
||||
int num_both, int num_forw, int nu, int ord,
|
||||
double discount_factor,
|
||||
const TensorContainer<FSSparseTensor> &ucont,
|
||||
const FGSContainer &g_arg,
|
||||
const FGSContainer &gs_arg,
|
||||
const TwoDMatrix &v,
|
||||
Journal &jr) :
|
||||
ypart(num_stat, num_pred, num_both, num_forw),
|
||||
ny(ypart.ny()), nu(nu), maxk(ucont.getMaxDim()), order(ord),
|
||||
discount_factor{discount_factor}, nvs{ypart.nys(), nu, nu, 1},
|
||||
_uU(4), _fU(4), _uW(4), _fW(4), _uWrond(4), _fWrond(4), _ug(4),
|
||||
_fg(g_arg), _ugs(4), _fgs(gs_arg), _uXstack(&_ug, ny),
|
||||
_fXstack(&_fg, ny), _uGstack(&_ugs, ypart.nys(), nu),
|
||||
_fGstack(&_fgs, ypart.nys(), nu), _um(maxk, v),
|
||||
_fm(_um), u(ucont), journal(jr)
|
||||
KOrderWelfare::KOrderWelfare(int num_stat, int num_pred, int num_both, int num_forw, int nu,
|
||||
int ord, double discount_factor,
|
||||
const TensorContainer<FSSparseTensor>& ucont,
|
||||
const FGSContainer& g_arg, const FGSContainer& gs_arg,
|
||||
const TwoDMatrix& v, Journal& jr) :
|
||||
ypart(num_stat, num_pred, num_both, num_forw),
|
||||
ny(ypart.ny()), nu(nu), maxk(ucont.getMaxDim()),
|
||||
order(ord), discount_factor {discount_factor}, nvs {ypart.nys(), nu, nu, 1}, _uU(4), _fU(4),
|
||||
_uW(4), _fW(4), _uWrond(4), _fWrond(4), _ug(4), _fg(g_arg), _ugs(4), _fgs(gs_arg),
|
||||
_uXstack(&_ug, ny), _fXstack(&_fg, ny), _uGstack(&_ugs, ypart.nys(), nu),
|
||||
_fGstack(&_fgs, ypart.nys(), nu), _um(maxk, v), _fm(_um), u(ucont), journal(jr)
|
||||
{
|
||||
KORD_RAISE_IF(v.ncols() != nu,
|
||||
"Wrong number of columns of Vcov in KOrderWelfare constructor");
|
||||
KORD_RAISE_IF(nu != v.nrows(),
|
||||
"Wrong number of rows of Vcov in KOrderWelfare constructor");
|
||||
KORD_RAISE_IF(v.ncols() != nu, "Wrong number of columns of Vcov in KOrderWelfare constructor");
|
||||
KORD_RAISE_IF(nu != v.nrows(), "Wrong number of rows of Vcov in KOrderWelfare constructor");
|
||||
for (int ord = 1; ord <= order; ord++)
|
||||
{
|
||||
JournalRecordPair pa(journal);
|
||||
|
@ -328,7 +324,7 @@ KOrderWelfare::KOrderWelfare(int num_stat, int num_pred,
|
|||
for (int j = 0; j <= ord; j++)
|
||||
for (int i = 0; i <= j; i++)
|
||||
{
|
||||
Symmetry sym{ord-j, i, 0, j-i};
|
||||
Symmetry sym {ord - j, i, 0, j - i};
|
||||
pa << "Recovering symmetry " << sym << "\n" << endrec;
|
||||
auto U_sym = faaDiBrunoU<Storage::fold>(sym);
|
||||
U<Storage::fold>().insert(std::move(U_sym));
|
||||
|
@ -354,21 +350,18 @@ KOrderWelfare::KOrderWelfare(int num_stat, int num_pred,
|
|||
|
||||
template<>
|
||||
void
|
||||
KOrderWelfare::sylvesterSolve<Storage::unfold>(ctraits<Storage::unfold>::Ttensor &der) const
|
||||
KOrderWelfare::sylvesterSolve<Storage::unfold>(ctraits<Storage::unfold>::Ttensor& der) const
|
||||
{
|
||||
JournalRecordPair pa(journal);
|
||||
pa << "Sylvester equation for dimension = " << der.getSym()[0] << endrec;
|
||||
KORD_RAISE_IF(!der.isFinite(),
|
||||
"RHS of Sylverster is not finite");
|
||||
TwoDMatrix gs_y(gs<Storage::unfold>().get(Symmetry{1, 0, 0, 0}));
|
||||
TwoDMatrix A(1,1);
|
||||
KORD_RAISE_IF(!der.isFinite(), "RHS of Sylverster is not finite");
|
||||
TwoDMatrix gs_y(gs<Storage::unfold>().get(Symmetry {1, 0, 0, 0}));
|
||||
TwoDMatrix A(1, 1);
|
||||
A.unit();
|
||||
TwoDMatrix B(1,1);
|
||||
TwoDMatrix B(1, 1);
|
||||
B.unit();
|
||||
B.mult(-discount_factor);
|
||||
GeneralSylvester sylv(der.getSym()[0], 1, ypart.nys(),
|
||||
0,
|
||||
A.getData(), B.getData(),
|
||||
GeneralSylvester sylv(der.getSym()[0], 1, ypart.nys(), 0, A.getData(), B.getData(),
|
||||
gs_y.getData(), der.getData());
|
||||
sylv.solve();
|
||||
}
|
||||
|
@ -380,10 +373,10 @@ KOrderWelfare::sylvesterSolve<Storage::unfold>(ctraits<Storage::unfold>::Ttensor
|
|||
|
||||
template<>
|
||||
void
|
||||
KOrderWelfare::sylvesterSolve<Storage::fold>(ctraits<Storage::fold>::Ttensor &der) const
|
||||
KOrderWelfare::sylvesterSolve<Storage::fold>(ctraits<Storage::fold>::Ttensor& der) const
|
||||
{
|
||||
ctraits<Storage::unfold>::Ttensor tmp(der);
|
||||
sylvesterSolve<Storage::unfold>(tmp);
|
||||
ctraits<Storage::fold>::Ttensor ftmp(tmp);
|
||||
der.getData() = const_cast<const Vector &>(ftmp.getData());
|
||||
der.getData() = const_cast<const Vector&>(ftmp.getData());
|
||||
}
|
||||
|
|
|
@ -28,40 +28,43 @@ class KordwDynare;
|
|||
class KordwDynare
|
||||
{
|
||||
public:
|
||||
KordpDynare &model;
|
||||
const ConstVector &NNZD;
|
||||
KordpDynare& model;
|
||||
const ConstVector& NNZD;
|
||||
|
||||
private:
|
||||
Journal &journal;
|
||||
Vector ¶ms;
|
||||
Journal& journal;
|
||||
Vector& params;
|
||||
Vector resid;
|
||||
TensorContainer<FSSparseTensor> ud; // planner's objective derivatives, in Dynare++ form
|
||||
std::vector<int> dynppToDyn; // Maps Dynare++ jacobian variable indices to Dynare ones
|
||||
std::vector<int> dynToDynpp; // Maps Dynare jacobian variable indices to Dynare++ ones
|
||||
std::vector<int> dynppToDyn; // Maps Dynare++ jacobian variable indices to Dynare ones
|
||||
std::vector<int> dynToDynpp; // Maps Dynare jacobian variable indices to Dynare++ ones
|
||||
std::unique_ptr<ObjectiveAC> objectiveFile;
|
||||
|
||||
public:
|
||||
KordwDynare(KordpDynare &m, ConstVector &NNZD_arg, Journal &jr, Vector &inParams, std::unique_ptr<ObjectiveAC> objectiveFile_arg, const std::vector<int> &varOrder);
|
||||
KordwDynare(KordpDynare& m, ConstVector& NNZD_arg, Journal& jr, Vector& inParams,
|
||||
std::unique_ptr<ObjectiveAC> objectiveFile_arg, const std::vector<int>& varOrder);
|
||||
void calcDerivativesAtSteady();
|
||||
void populateDerivativesContainer(const std::vector<TwoDMatrix> &dyn_ud, int ord);
|
||||
const TensorContainer<FSSparseTensor> &
|
||||
void populateDerivativesContainer(const std::vector<TwoDMatrix>& dyn_ud, int ord);
|
||||
const TensorContainer<FSSparseTensor>&
|
||||
getPlannerObjDerivatives() const
|
||||
{
|
||||
return ud;
|
||||
}
|
||||
const KordpDynare &
|
||||
const KordpDynare&
|
||||
getModel() const
|
||||
{
|
||||
return model;
|
||||
}
|
||||
const Vector &
|
||||
const Vector&
|
||||
getResid() const
|
||||
{
|
||||
return resid;
|
||||
}
|
||||
|
||||
private:
|
||||
/* Computes the permutations mapping back and forth between Dynare and
|
||||
Dynare++ orderings of variables */
|
||||
void computeJacobianPermutation(const std::vector<int> &var_order);
|
||||
|
||||
void computeJacobianPermutation(const std::vector<int>& var_order);
|
||||
};
|
||||
|
||||
class KOrderWelfare
|
||||
|
@ -98,54 +101,50 @@ public:
|
|||
|
||||
/* Planner objective derivatives: just a reference to the container of sparse
|
||||
tensors of the derivatives, lives outside the class */
|
||||
const TensorContainer<FSSparseTensor> &u;
|
||||
const TensorContainer<FSSparseTensor>& u;
|
||||
|
||||
/* These are the declarations of the template functions accessing the
|
||||
containers. We declare template methods for accessing containers depending
|
||||
on ‘fold’ and ‘unfold’ flag, we implement their specializations*/
|
||||
template<Storage t>
|
||||
typename ctraits<t>::Tg &g();
|
||||
typename ctraits<t>::Tg& g();
|
||||
template<Storage t>
|
||||
const typename ctraits<t>::Tg &g() const;
|
||||
const typename ctraits<t>::Tg& g() const;
|
||||
template<Storage t>
|
||||
typename ctraits<t>::Tgs &gs();
|
||||
typename ctraits<t>::Tgs& gs();
|
||||
template<Storage t>
|
||||
const typename ctraits<t>::Tgs &gs() const;
|
||||
const typename ctraits<t>::Tgs& gs() const;
|
||||
template<Storage t>
|
||||
typename ctraits<t>::TU &U();
|
||||
typename ctraits<t>::TU& U();
|
||||
template<Storage t>
|
||||
const typename ctraits<t>::TU &U() const;
|
||||
const typename ctraits<t>::TU& U() const;
|
||||
template<Storage t>
|
||||
typename ctraits<t>::TW &W();
|
||||
typename ctraits<t>::TW& W();
|
||||
template<Storage t>
|
||||
const typename ctraits<t>::TW &W() const;
|
||||
const typename ctraits<t>::TW& W() const;
|
||||
template<Storage t>
|
||||
typename ctraits<t>::TWrond &Wrond();
|
||||
typename ctraits<t>::TWrond& Wrond();
|
||||
template<Storage t>
|
||||
const typename ctraits<t>::TWrond &Wrond() const;
|
||||
const typename ctraits<t>::TWrond& Wrond() const;
|
||||
template<Storage t>
|
||||
typename ctraits<t>::TXstack &Xstack();
|
||||
typename ctraits<t>::TXstack& Xstack();
|
||||
template<Storage t>
|
||||
const typename ctraits<t>::TXstack &Xstack() const;
|
||||
const typename ctraits<t>::TXstack& Xstack() const;
|
||||
template<Storage t>
|
||||
typename ctraits<t>::TGstack &Gstack();
|
||||
typename ctraits<t>::TGstack& Gstack();
|
||||
template<Storage t>
|
||||
const typename ctraits<t>::TGstack &Gstack() const;
|
||||
const typename ctraits<t>::TGstack& Gstack() const;
|
||||
template<Storage t>
|
||||
typename ctraits<t>::Tm &m();
|
||||
typename ctraits<t>::Tm& m();
|
||||
template<Storage t>
|
||||
const typename ctraits<t>::Tm &m() const;
|
||||
const typename ctraits<t>::Tm& m() const;
|
||||
|
||||
Journal &journal;
|
||||
Journal& journal;
|
||||
|
||||
public:
|
||||
KOrderWelfare(int num_stat, int num_pred, int num_both,
|
||||
int num_forw, int nu, int ord, double discount_factor,
|
||||
const TensorContainer<FSSparseTensor> &ucont,
|
||||
const FGSContainer &g,
|
||||
const FGSContainer &gs,
|
||||
const TwoDMatrix &v,
|
||||
Journal &jr);
|
||||
KOrderWelfare(int num_stat, int num_pred, int num_both, int num_forw, int nu, int ord,
|
||||
double discount_factor, const TensorContainer<FSSparseTensor>& ucont,
|
||||
const FGSContainer& g, const FGSContainer& gs, const TwoDMatrix& v, Journal& jr);
|
||||
|
||||
/* Performs k-order step provided that k=2 or the k−1-th step has been
|
||||
run, this is the core method */
|
||||
|
@ -156,22 +155,22 @@ public:
|
|||
template<Storage t>
|
||||
double check(int dim) const;
|
||||
|
||||
const FGSContainer &
|
||||
const FGSContainer&
|
||||
getFoldU() const
|
||||
{
|
||||
return _fU;
|
||||
}
|
||||
const UGSContainer &
|
||||
const UGSContainer&
|
||||
getUnfoldU() const
|
||||
{
|
||||
return _uU;
|
||||
}
|
||||
const FGSContainer &
|
||||
const FGSContainer&
|
||||
getFoldW() const
|
||||
{
|
||||
return _fW;
|
||||
}
|
||||
const UGSContainer &
|
||||
const UGSContainer&
|
||||
getUnfoldW() const
|
||||
{
|
||||
return _uW;
|
||||
|
@ -186,14 +185,15 @@ protected:
|
|||
/* Calculates derivatives of U by Faà Di Bruno for the sparse container of
|
||||
planner's objective derivatives and the container for the decision rule derivatives*/
|
||||
template<Storage t>
|
||||
std::unique_ptr<typename ctraits<t>::Ttensor> faaDiBrunoU(const Symmetry &sym) const;
|
||||
/* Calculates derivatives of the compounded functions W and Gstack using the Faà Di Bruno formula*/
|
||||
std::unique_ptr<typename ctraits<t>::Ttensor> faaDiBrunoU(const Symmetry& sym) const;
|
||||
/* Calculates derivatives of the compounded functions W and Gstack using the Faà Di Bruno
|
||||
* formula*/
|
||||
template<Storage t>
|
||||
std::unique_ptr<typename ctraits<t>::Ttensor> faaDiBrunoW(const Symmetry &sym) const;
|
||||
std::unique_ptr<typename ctraits<t>::Ttensor> faaDiBrunoW(const Symmetry& sym) const;
|
||||
|
||||
/* Solves the sylvester equation (templated fold, and unfold) */
|
||||
template<Storage t>
|
||||
void sylvesterSolve(typename ctraits<t>::Ttensor &der) const;
|
||||
void sylvesterSolve(typename ctraits<t>::Ttensor& der) const;
|
||||
|
||||
// Recovers W_y*ⁱ
|
||||
template<Storage t>
|
||||
|
@ -230,7 +230,6 @@ protected:
|
|||
typename ctraits<t>::Ttensor calcJ_ik(int i, int k) const;
|
||||
template<Storage t>
|
||||
typename ctraits<t>::Ttensor calcJ_k(int k) const;
|
||||
|
||||
};
|
||||
|
||||
/* Here we implement Faà Di Bruno formula
|
||||
|
@ -242,7 +241,7 @@ protected:
|
|||
where s is a given outer symmetry and k is the dimension of the symmetry. */
|
||||
template<Storage t>
|
||||
std::unique_ptr<typename ctraits<t>::Ttensor>
|
||||
KOrderWelfare::faaDiBrunoU(const Symmetry &sym) const
|
||||
KOrderWelfare::faaDiBrunoU(const Symmetry& sym) const
|
||||
{
|
||||
JournalRecordPair pa(journal);
|
||||
pa << "Faà Di Bruno U container for " << sym << endrec;
|
||||
|
@ -255,7 +254,7 @@ KOrderWelfare::faaDiBrunoU(const Symmetry &sym) const
|
|||
/* The same as KOrder::faaDiBrunoW(), but for W and G stack. */
|
||||
template<Storage t>
|
||||
std::unique_ptr<typename ctraits<t>::Ttensor>
|
||||
KOrderWelfare::faaDiBrunoW(const Symmetry &sym) const
|
||||
KOrderWelfare::faaDiBrunoW(const Symmetry& sym) const
|
||||
{
|
||||
JournalRecordPair pa(journal);
|
||||
pa << "Faà Di Bruno G container for " << sym << endrec;
|
||||
|
@ -270,32 +269,33 @@ template<Storage t>
|
|||
void
|
||||
KOrderWelfare::performStep(int order)
|
||||
{
|
||||
KORD_RAISE_IF(order-1 != W<t>().getMaxDim() and order > 1, "Wrong order for KOrder::performStep");
|
||||
KORD_RAISE_IF(order - 1 != W<t>().getMaxDim() and order > 1,
|
||||
"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);
|
||||
recover_yu<t>(i, order - i);
|
||||
|
||||
recover_ys<t>(order-1, 1);
|
||||
recover_ys<t>(order - 1, 1);
|
||||
|
||||
for (int j = 2; j < order; j++)
|
||||
{
|
||||
for (int i = 1; i <= j-1; i++)
|
||||
recover_yus<t>(order-j, i, j-i);
|
||||
recover_ys<t>(order-j, j);
|
||||
recover_yus<t>(0, order-j, j);
|
||||
for (int i = 1; i <= j - 1; i++)
|
||||
recover_yus<t>(order - j, i, j - i);
|
||||
recover_ys<t>(order - j, j);
|
||||
recover_yus<t>(0, order - j, j);
|
||||
}
|
||||
|
||||
recover_s<t>(order);
|
||||
}
|
||||
|
||||
/* Here we solve [F_yⁱ]=0. First we calculate conditional W_yⁱ (it misses l=i since W_yⁱ does not exist yet). Then calculate conditional F_yⁱ and
|
||||
we have the right hand side of equation. Since we miss two orders, we solve
|
||||
by Sylvester, and the solution as the derivative g_yⁱ. Then we need
|
||||
to update G_yⁱ running multAndAdd() for both dimensions 1 and i.
|
||||
/* Here we solve [F_yⁱ]=0. First we calculate conditional W_yⁱ (it misses l=i since W_yⁱ does not
|
||||
exist yet). Then calculate conditional F_yⁱ and we have the right hand side of equation. Since we
|
||||
miss two orders, we solve by Sylvester, and the solution as the derivative g_yⁱ. Then we need to
|
||||
update G_yⁱ running multAndAdd() for both dimensions 1 and i.
|
||||
|
||||
Requires: everything at order ≤ i−1
|
||||
|
||||
|
@ -305,7 +305,7 @@ template<Storage t>
|
|||
void
|
||||
KOrderWelfare::recover_y(int i)
|
||||
{
|
||||
Symmetry sym{i, 0, 0, 0};
|
||||
Symmetry sym {i, 0, 0, 0};
|
||||
JournalRecordPair pa(journal);
|
||||
pa << "Conditional welfare: recovering symmetry " << sym << "\n" << endrec;
|
||||
|
||||
|
@ -335,7 +335,7 @@ template<Storage t>
|
|||
void
|
||||
KOrderWelfare::recover_yu(int i, int j)
|
||||
{
|
||||
Symmetry sym{i, j, 0, 0};
|
||||
Symmetry sym {i, j, 0, 0};
|
||||
JournalRecordPair pa(journal);
|
||||
pa << "Conditional welfare: recovering symmetry " << sym << endrec;
|
||||
|
||||
|
@ -347,7 +347,6 @@ KOrderWelfare::recover_yu(int i, int j)
|
|||
W_yiuj.add(discount_factor, *Wrond_yiuj_ptr);
|
||||
|
||||
W<t>().insert(std::make_unique<typename ctraits<t>::Ttensor>(W_yiuj));
|
||||
|
||||
}
|
||||
|
||||
/* Here we solve [F_yⁱσʲ]+[Dᵢⱼ]+[Eᵢⱼ]=0 to obtain W_yⁱσʲ. We calculate
|
||||
|
@ -367,7 +366,7 @@ template<Storage t>
|
|||
void
|
||||
KOrderWelfare::recover_ys(int i, int j)
|
||||
{
|
||||
Symmetry sym{i, 0, 0, j};
|
||||
Symmetry sym {i, 0, 0, j};
|
||||
JournalRecordPair pa(journal);
|
||||
pa << "Conditional welfare: recovering symmetry " << sym << endrec;
|
||||
|
||||
|
@ -396,7 +395,7 @@ KOrderWelfare::recover_ys(int i, int j)
|
|||
|
||||
W<t>().insert(std::make_unique<typename ctraits<t>::Ttensor>(W_yisj));
|
||||
|
||||
Gstack<t>().multAndAdd(i+j, W<t>(), *Wrond_yisj_ptr);
|
||||
Gstack<t>().multAndAdd(i + j, W<t>(), *Wrond_yisj_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -417,7 +416,7 @@ template<Storage t>
|
|||
void
|
||||
KOrderWelfare::recover_yus(int i, int j, int k)
|
||||
{
|
||||
Symmetry sym{i, j, 0, k};
|
||||
Symmetry sym {i, j, 0, k};
|
||||
JournalRecordPair pa(journal);
|
||||
pa << "Conditional welfare: recovering symmetry " << sym << endrec;
|
||||
|
||||
|
@ -443,7 +442,7 @@ KOrderWelfare::recover_yus(int i, int j, int k)
|
|||
|
||||
W<t>().insert(std::make_unique<typename ctraits<t>::Ttensor>(W_yiujsk));
|
||||
|
||||
Gstack<t>().multAndAdd(i+j+k, W<t>(), *Wrond_yiujsk_ptr);
|
||||
Gstack<t>().multAndAdd(i + j + k, W<t>(), *Wrond_yiujsk_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -463,7 +462,7 @@ template<Storage t>
|
|||
void
|
||||
KOrderWelfare::recover_s(int i)
|
||||
{
|
||||
Symmetry sym{0, 0, 0, i};
|
||||
Symmetry sym {0, 0, 0, i};
|
||||
JournalRecordPair pa(journal);
|
||||
pa << "Conditional welfare: recovering symmetry " << sym << endrec;
|
||||
|
||||
|
@ -489,7 +488,7 @@ KOrderWelfare::recover_s(int i)
|
|||
W_si.add(-1.0, J_i);
|
||||
}
|
||||
|
||||
W_si.mult(1/(1-discount_factor));
|
||||
W_si.mult(1 / (1 - discount_factor));
|
||||
|
||||
W<t>().insert(std::make_unique<typename ctraits<t>::Ttensor>(W_si));
|
||||
|
||||
|
@ -497,15 +496,16 @@ KOrderWelfare::recover_s(int i)
|
|||
}
|
||||
}
|
||||
|
||||
/* Here we calculate and insert Wrond_yⁱuʲu′ᵐσᵏ⁻ᵐ for m=1,…,k. The derivatives are inserted only for k−m being even. */
|
||||
/* Here we calculate and insert Wrond_yⁱuʲu′ᵐσᵏ⁻ᵐ for m=1,…,k. The derivatives are inserted only for
|
||||
* k−m being even. */
|
||||
template<Storage t>
|
||||
void
|
||||
KOrderWelfare::fillWrond(int i, int j, int k)
|
||||
{
|
||||
for (int m = 1; m <= k; m++)
|
||||
if (is_even(k-m))
|
||||
if (is_even(k - m))
|
||||
{
|
||||
auto Wrond_yiujupms = faaDiBrunoW<t>(Symmetry{i, j, m, k-m});
|
||||
auto Wrond_yiujupms = faaDiBrunoW<t>(Symmetry {i, j, m, k - m});
|
||||
Wrond<t>().insert(std::move(Wrond_yiujupms));
|
||||
}
|
||||
}
|
||||
|
@ -519,12 +519,12 @@ template<Storage t>
|
|||
typename ctraits<t>::Ttensor
|
||||
KOrderWelfare::calcH_ijk(int i, int j, int k) const
|
||||
{
|
||||
typename ctraits<t>::Ttensor res(1, TensorDimens(Symmetry{i, j, 0, 0}, nvs));
|
||||
typename ctraits<t>::Ttensor res(1, TensorDimens(Symmetry {i, j, 0, 0}, nvs));
|
||||
res.zeros();
|
||||
if (is_even(k))
|
||||
{
|
||||
auto tmp = faaDiBrunoW<t>(Symmetry{i, j, k, 0});
|
||||
tmp->contractAndAdd(2, res, m<t>().get(Symmetry{k}));
|
||||
auto tmp = faaDiBrunoW<t>(Symmetry {i, j, k, 0});
|
||||
tmp->contractAndAdd(2, res, m<t>().get(Symmetry {k}));
|
||||
}
|
||||
res.mult(-discount_factor);
|
||||
return res;
|
||||
|
@ -542,13 +542,13 @@ template<Storage t>
|
|||
typename ctraits<t>::Ttensor
|
||||
KOrderWelfare::calcJ_ijk(int i, int j, int k) const
|
||||
{
|
||||
typename ctraits<t>::Ttensor res(1, TensorDimens(Symmetry{i, j, 0, 0}, nvs));
|
||||
typename ctraits<t>::Ttensor res(1, TensorDimens(Symmetry {i, j, 0, 0}, nvs));
|
||||
res.zeros();
|
||||
for (int n = 2; n <= k-1; n += 2)
|
||||
for (int n = 2; n <= k - 1; n += 2)
|
||||
{
|
||||
auto tmp = faaDiBrunoW<t>(Symmetry{i, j, n, k-n});
|
||||
auto tmp = faaDiBrunoW<t>(Symmetry {i, j, n, k - n});
|
||||
tmp->mult(static_cast<double>(PascalTriangle::noverk(k, n)));
|
||||
tmp->contractAndAdd(2, res, m<t>().get(Symmetry{n}));
|
||||
tmp->contractAndAdd(2, res, m<t>().get(Symmetry {n}));
|
||||
}
|
||||
res.mult(-discount_factor);
|
||||
return res;
|
||||
|
@ -590,8 +590,7 @@ template<Storage t>
|
|||
double
|
||||
KOrderWelfare::check(int dim) const
|
||||
{
|
||||
KORD_RAISE_IF(dim > W<t>().getMaxDim(),
|
||||
"Wrong dimension for KOrderWelfare::check");
|
||||
KORD_RAISE_IF(dim > W<t>().getMaxDim(), "Wrong dimension for KOrderWelfare::check");
|
||||
JournalRecordPair pa(journal);
|
||||
pa << "Checking residuals for order = " << dim << endrec;
|
||||
|
||||
|
@ -600,7 +599,7 @@ KOrderWelfare::check(int dim) const
|
|||
// Check for F_yⁱuʲ=0
|
||||
for (int i = 0; i <= dim; i++)
|
||||
{
|
||||
Symmetry sym{dim-i, i, 0, 0};
|
||||
Symmetry sym {dim - i, i, 0, 0};
|
||||
auto r = W<t>().get(sym);
|
||||
r.add(-1.0, U<t>().get(sym));
|
||||
r.add(-discount_factor, Wrond<t>().get(sym));
|
||||
|
@ -610,14 +609,14 @@ KOrderWelfare::check(int dim) const
|
|||
}
|
||||
|
||||
// Check for F_yⁱuʲu′ᵏ+Hᵢⱼₖ+Jᵢⱼₖ=0
|
||||
for (auto &si : SymmetrySet(dim, 3))
|
||||
for (auto& si : SymmetrySet(dim, 3))
|
||||
{
|
||||
int i = si[0];
|
||||
int j = si[1];
|
||||
int k = si[2];
|
||||
if (i+j > 0 && k > 0 && is_even(k))
|
||||
if (i + j > 0 && k > 0 && is_even(k))
|
||||
{
|
||||
Symmetry sym{i, j, 0, k};
|
||||
Symmetry sym {i, j, 0, k};
|
||||
auto r = W<t>().get(sym);
|
||||
r.add(-1.0, U<t>().get(sym));
|
||||
r.add(-discount_factor, Wrond<t>().get(sym));
|
||||
|
@ -634,7 +633,7 @@ KOrderWelfare::check(int dim) const
|
|||
// Check for F_σⁱ+Dᵢ+Eᵢ=0
|
||||
if (is_even(dim))
|
||||
{
|
||||
Symmetry sym{0, 0, 0, dim};
|
||||
Symmetry sym {0, 0, 0, dim};
|
||||
auto r = W<t>().get(sym);
|
||||
r.add(-1.0, U<t>().get(sym));
|
||||
r.add(-discount_factor, Wrond<t>().get(sym));
|
||||
|
|
|
@ -17,17 +17,17 @@
|
|||
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "dynamic_m.hh"
|
||||
#include "dynamic_dll.hh"
|
||||
#include "dynamic_m.hh"
|
||||
#include "objective_m.hh"
|
||||
|
||||
#include "SylvException.hh"
|
||||
#include "approximation.hh"
|
||||
#include "approximation_welfare.hh"
|
||||
#include "exception.hh"
|
||||
#include "dynare_exception.hh"
|
||||
#include "exception.hh"
|
||||
#include "kord_exception.hh"
|
||||
#include "tl_exception.hh"
|
||||
#include "SylvException.hh"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
|
@ -37,13 +37,13 @@
|
|||
/* Convert MATLAB Dynare endo and exo names cell array to a vector<string> array of
|
||||
string pointers. */
|
||||
std::vector<std::string>
|
||||
DynareMxArrayToString(const mxArray *mxFldp)
|
||||
DynareMxArrayToString(const mxArray* mxFldp)
|
||||
{
|
||||
assert(mxIsCell(mxFldp));
|
||||
std::vector<std::string> r;
|
||||
for (size_t i = 0; i < mxGetNumberOfElements(mxFldp); i++)
|
||||
{
|
||||
const mxArray *cell_mx = mxGetCell(mxFldp, i);
|
||||
const mxArray* cell_mx = mxGetCell(mxFldp, i);
|
||||
if (!(cell_mx && mxIsChar(cell_mx)))
|
||||
mexErrMsgTxt("Cell is not a character array");
|
||||
r.emplace_back(mxArrayToString(cell_mx));
|
||||
|
@ -62,48 +62,60 @@ DynareMxArrayToString(const mxArray *mxFldp)
|
|||
std::vector<std::string> W_fieldnames;
|
||||
|
||||
void
|
||||
copy_derivatives(mxArray *destin, const Symmetry &sym, const FGSContainer &derivs, const char *fieldname)
|
||||
copy_derivatives(mxArray* destin, const Symmetry& sym, const FGSContainer& derivs,
|
||||
const char* fieldname)
|
||||
{
|
||||
const FGSTensor &x = derivs.get(sym);
|
||||
const FGSTensor& x = derivs.get(sym);
|
||||
auto x_unfolded = x.unfold();
|
||||
int n = x_unfolded->nrows();
|
||||
int m = x_unfolded->ncols();
|
||||
mxArray *tmp = mxCreateDoubleMatrix(n, m, mxREAL);
|
||||
std::copy_n(x_unfolded->getData().base(), n*m, mxGetPr(tmp));
|
||||
mxArray* tmp = mxCreateDoubleMatrix(n, m, mxREAL);
|
||||
std::copy_n(x_unfolded->getData().base(), n * m, mxGetPr(tmp));
|
||||
mxSetField(destin, 0, fieldname, tmp);
|
||||
}
|
||||
|
||||
/* The k_order_welfare function computes the conditional welfare starting from the non-stochastic steady state and the derivatives of the felicity and welfare functions U(h(yₜ₋₁, uₜ, σ)) and W(yₜ₋₁, uₜ, σ). The unconditional welfare shall be introduced in a future version with the update of the dynare_simul_.
|
||||
/*
|
||||
The k_order_welfare function computes the conditional welfare starting from the non-stochastic
|
||||
steady state and the derivatives of the felicity and welfare functions U(h(yₜ₋₁, uₜ, σ)) and W(yₜ₋₁,
|
||||
uₜ, σ). The unconditional welfare shall be introduced in a future version with the update of the
|
||||
dynare_simul_.
|
||||
|
||||
The routine proceeds in several steps:
|
||||
1. Computation of the kth-order policy functions: the code is a copy-paste from the k_order_perturbation.cc file
|
||||
2. Computation of the kth-order derivatives of the felicity and of the welfare functions. The call to the approxAtSteady method in the ApproximationWelfare class carries out the necessary operation
|
||||
- Importing the derivatives of the felicity function with the calcDerivativesAtSteady() method of the KordwDynare class. It relies on the Matlab-generated files, which are handled by the ObjectiveAC and ObjectiveMFile classes
|
||||
- Pinpointing the derivatives of the felicity and welfare functions. The performStep method of the KOrderWelfare class carries out the calculations,resorting to the FaaDiBruno class and its methods to get the needed intermediary results.
|
||||
1. Computation of the kth-order policy functions: the code is a copy-paste from the
|
||||
k_order_perturbation.cc file
|
||||
2. Computation of the kth-order derivatives of the felicity and of the welfare functions. The call
|
||||
to the approxAtSteady method in the ApproximationWelfare class carries out the necessary
|
||||
operation
|
||||
- Importing the derivatives of the felicity function with the calcDerivativesAtSteady() method of
|
||||
the KordwDynare class. It relies on the Matlab-generated files, which are handled by the
|
||||
ObjectiveAC and ObjectiveMFile classes
|
||||
- Pinpointing the derivatives of the felicity and welfare functions. The performStep method of
|
||||
the KOrderWelfare class carries out the calculations,resorting to the FaaDiBruno class and its
|
||||
methods to get the needed intermediary results.
|
||||
*/
|
||||
|
||||
extern "C" {
|
||||
extern "C"
|
||||
{
|
||||
|
||||
void mexFunction(int nlhs, mxArray *plhs[],
|
||||
int nrhs, const mxArray *prhs[])
|
||||
void
|
||||
mexFunction(int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[])
|
||||
{
|
||||
if (nlhs != 1 || nrhs != 3)
|
||||
mexErrMsgTxt("Must have exactly 3 input arguments and 1 output argument");
|
||||
|
||||
const mxArray *dr_mx = prhs[0];
|
||||
const mxArray *M_mx = prhs[1];
|
||||
const mxArray *options_mx = prhs[2];
|
||||
const mxArray* dr_mx = prhs[0];
|
||||
const mxArray* M_mx = prhs[1];
|
||||
const mxArray* options_mx = prhs[2];
|
||||
|
||||
auto get_int_field = [](const mxArray *struct_mx, const std::string &fieldname)
|
||||
{
|
||||
mxArray *field_mx = mxGetField(struct_mx, 0, fieldname.c_str());
|
||||
if (!(field_mx && mxIsScalar(field_mx) && mxIsNumeric(field_mx)))
|
||||
mexErrMsgTxt(("Field `" + fieldname + "' should be a numeric scalar").c_str());
|
||||
return static_cast<int>(mxGetScalar(field_mx));
|
||||
};
|
||||
auto get_int_field = [](const mxArray* struct_mx, const std::string& fieldname) {
|
||||
mxArray* field_mx = mxGetField(struct_mx, 0, fieldname.c_str());
|
||||
if (!(field_mx && mxIsScalar(field_mx) && mxIsNumeric(field_mx)))
|
||||
mexErrMsgTxt(("Field `" + fieldname + "' should be a numeric scalar").c_str());
|
||||
return static_cast<int>(mxGetScalar(field_mx));
|
||||
};
|
||||
|
||||
// Extract various fields from options_
|
||||
const mxArray *ramsey_policy_mx = mxGetField(options_mx, 0, "ramsey_policy");
|
||||
const mxArray* ramsey_policy_mx = mxGetField(options_mx, 0, "ramsey_policy");
|
||||
if (!(ramsey_policy_mx && mxIsLogicalScalar(ramsey_policy_mx)))
|
||||
mexErrMsgTxt("options_.ramsey_policy should be a logical scalar");
|
||||
bool ramsey_policy = static_cast<bool>(mxGetScalar(ramsey_policy_mx));
|
||||
|
@ -111,53 +123,52 @@ extern "C" {
|
|||
if (ramsey_policy == false)
|
||||
mexErrMsgTxt("The considered model must be a Ramsey-typed model !");
|
||||
|
||||
|
||||
const int kOrder = get_int_field(options_mx, "order");
|
||||
if (kOrder < 1)
|
||||
mexErrMsgTxt("options_.order must be at least 1");
|
||||
|
||||
const mxArray *use_dll_mx = mxGetField(options_mx, 0, "use_dll");
|
||||
const mxArray* use_dll_mx = mxGetField(options_mx, 0, "use_dll");
|
||||
if (!(use_dll_mx && mxIsLogicalScalar(use_dll_mx)))
|
||||
mexErrMsgTxt("options_.use_dll should be a logical scalar");
|
||||
bool use_dll = static_cast<bool>(mxGetScalar(use_dll_mx));
|
||||
|
||||
double qz_criterium = 1+1e-6;
|
||||
const mxArray *qz_criterium_mx = mxGetField(options_mx, 0, "qz_criterium");
|
||||
double qz_criterium = 1 + 1e-6;
|
||||
const mxArray* qz_criterium_mx = mxGetField(options_mx, 0, "qz_criterium");
|
||||
if (qz_criterium_mx && mxIsScalar(qz_criterium_mx) && mxIsNumeric(qz_criterium_mx))
|
||||
qz_criterium = mxGetScalar(qz_criterium_mx);
|
||||
|
||||
const mxArray *threads_mx = mxGetField(options_mx, 0, "threads");
|
||||
const mxArray* threads_mx = mxGetField(options_mx, 0, "threads");
|
||||
if (!threads_mx)
|
||||
mexErrMsgTxt("Can't find field options_.threads");
|
||||
const mxArray *num_threads_mx = mxGetField(threads_mx, 0, "k_order_perturbation");
|
||||
const mxArray* num_threads_mx = mxGetField(threads_mx, 0, "k_order_perturbation");
|
||||
if (!(num_threads_mx && mxIsScalar(num_threads_mx) && mxIsNumeric(num_threads_mx)))
|
||||
mexErrMsgTxt("options_.threads.k_order_perturbation be a numeric scalar");
|
||||
int num_threads = static_cast<int>(mxGetScalar(num_threads_mx));
|
||||
|
||||
const mxArray *debug_mx = mxGetField(options_mx, 0, "debug");
|
||||
const mxArray* debug_mx = mxGetField(options_mx, 0, "debug");
|
||||
if (!(debug_mx && mxIsLogicalScalar(debug_mx)))
|
||||
mexErrMsgTxt("options_.debug should be a logical scalar");
|
||||
bool debug = static_cast<bool>(mxGetScalar(debug_mx));
|
||||
|
||||
const mxArray *pruning_mx = mxGetField(options_mx, 0, "pruning");
|
||||
const mxArray* pruning_mx = mxGetField(options_mx, 0, "pruning");
|
||||
if (!(pruning_mx && mxIsLogicalScalar(pruning_mx)))
|
||||
mexErrMsgTxt("options_.pruning should be a logical scalar");
|
||||
bool pruning = static_cast<bool>(mxGetScalar(pruning_mx));
|
||||
|
||||
// Extract various fields from M_
|
||||
const mxArray *fname_mx = mxGetField(M_mx, 0, "fname");
|
||||
const mxArray* fname_mx = mxGetField(M_mx, 0, "fname");
|
||||
if (!(fname_mx && mxIsChar(fname_mx) && mxGetM(fname_mx) == 1))
|
||||
mexErrMsgTxt("M_.fname should be a character string");
|
||||
std::string fname{mxArrayToString(fname_mx)};
|
||||
std::string fname {mxArrayToString(fname_mx)};
|
||||
|
||||
const mxArray *params_mx = mxGetField(M_mx, 0, "params");
|
||||
const mxArray* params_mx = mxGetField(M_mx, 0, "params");
|
||||
if (!(params_mx && mxIsDouble(params_mx)))
|
||||
mexErrMsgTxt("M_.params should be a double precision array");
|
||||
Vector modParams{ConstVector{params_mx}};
|
||||
Vector modParams {ConstVector {params_mx}};
|
||||
if (!modParams.isFinite())
|
||||
mexErrMsgTxt("M_.params contains NaN or Inf");
|
||||
|
||||
const mxArray *param_names_mx = mxGetField(M_mx, 0, "param_names");
|
||||
const mxArray* param_names_mx = mxGetField(M_mx, 0, "param_names");
|
||||
if (!(param_names_mx && mxIsCell(param_names_mx)))
|
||||
mexErrMsgTxt("M_.param_names should be a cell array");
|
||||
std::vector<std::string> paramNames = DynareMxArrayToString(param_names_mx);
|
||||
|
@ -171,10 +182,10 @@ extern "C" {
|
|||
return; // To silence a GCC warning about discount_factor unitialized
|
||||
}
|
||||
|
||||
const mxArray *sigma_e_mx = mxGetField(M_mx, 0, "Sigma_e");
|
||||
const mxArray* sigma_e_mx = mxGetField(M_mx, 0, "Sigma_e");
|
||||
if (!(sigma_e_mx && mxIsDouble(sigma_e_mx) && mxGetM(sigma_e_mx) == mxGetN(sigma_e_mx)))
|
||||
mexErrMsgTxt("M_.Sigma_e should be a double precision square matrix");
|
||||
TwoDMatrix vCov{ConstTwoDMatrix{sigma_e_mx}};
|
||||
TwoDMatrix vCov {ConstTwoDMatrix {sigma_e_mx}};
|
||||
if (!vCov.isFinite())
|
||||
mexErrMsgTxt("M_.Sigma_e contains NaN or Inf");
|
||||
|
||||
|
@ -187,65 +198,76 @@ extern "C" {
|
|||
const int nEndo = get_int_field(M_mx, "endo_nbr");
|
||||
const int nPar = get_int_field(M_mx, "param_nbr");
|
||||
|
||||
const mxArray *lead_lag_incidence_mx = mxGetField(M_mx, 0, "lead_lag_incidence");
|
||||
if (!(lead_lag_incidence_mx && mxIsDouble(lead_lag_incidence_mx) && mxGetM(lead_lag_incidence_mx) == 3
|
||||
const mxArray* lead_lag_incidence_mx = mxGetField(M_mx, 0, "lead_lag_incidence");
|
||||
if (!(lead_lag_incidence_mx && mxIsDouble(lead_lag_incidence_mx)
|
||||
&& mxGetM(lead_lag_incidence_mx) == 3
|
||||
&& mxGetN(lead_lag_incidence_mx) == static_cast<size_t>(nEndo)))
|
||||
mexErrMsgTxt("M_.lead_lag_incidence should be a double precision matrix with 3 rows and M_.endo_nbr columns");
|
||||
ConstTwoDMatrix llincidence{lead_lag_incidence_mx};
|
||||
mexErrMsgTxt("M_.lead_lag_incidence should be a double precision matrix with 3 rows and "
|
||||
"M_.endo_nbr columns");
|
||||
ConstTwoDMatrix llincidence {lead_lag_incidence_mx};
|
||||
|
||||
const mxArray *nnzderivatives_mx = mxGetField(M_mx, 0, "NNZDerivatives");
|
||||
const mxArray* nnzderivatives_mx = mxGetField(M_mx, 0, "NNZDerivatives");
|
||||
if (!(nnzderivatives_mx && mxIsDouble(nnzderivatives_mx)))
|
||||
mexErrMsgTxt("M_.NNZDerivatives should be a double precision array");
|
||||
ConstVector NNZD{nnzderivatives_mx};
|
||||
if (NNZD.length() < kOrder || NNZD[kOrder-1] == -1)
|
||||
mexErrMsgTxt("The derivatives were not computed for the required order. Make sure that you used the right order option inside the `stoch_simul' command");
|
||||
ConstVector NNZD {nnzderivatives_mx};
|
||||
if (NNZD.length() < kOrder || NNZD[kOrder - 1] == -1)
|
||||
mexErrMsgTxt("The derivatives were not computed for the required order. Make sure that you "
|
||||
"used the right order option inside the `stoch_simul' command");
|
||||
|
||||
const mxArray *nnzderivatives_obj_mx = mxGetField(M_mx, 0, "NNZDerivatives_objective");
|
||||
if (!(nnzderivatives_obj_mx && mxIsDouble(nnzderivatives_obj_mx) && !mxIsComplex(nnzderivatives_obj_mx) && !mxIsSparse(nnzderivatives_obj_mx)))
|
||||
const mxArray* nnzderivatives_obj_mx = mxGetField(M_mx, 0, "NNZDerivatives_objective");
|
||||
if (!(nnzderivatives_obj_mx && mxIsDouble(nnzderivatives_obj_mx)
|
||||
&& !mxIsComplex(nnzderivatives_obj_mx) && !mxIsSparse(nnzderivatives_obj_mx)))
|
||||
mexErrMsgTxt("M_.NNZDerivatives should be a real dense array");
|
||||
ConstVector NNZD_obj{nnzderivatives_obj_mx};
|
||||
if (NNZD.length() < kOrder || NNZD_obj[kOrder-1] == -1)
|
||||
mexErrMsgTxt("The derivatives were not computed for the required order. Make sure that you used the right order option inside the `stoch_simul' command");
|
||||
ConstVector NNZD_obj {nnzderivatives_obj_mx};
|
||||
if (NNZD.length() < kOrder || NNZD_obj[kOrder - 1] == -1)
|
||||
mexErrMsgTxt("The derivatives were not computed for the required order. Make sure that you "
|
||||
"used the right order option inside the `stoch_simul' command");
|
||||
|
||||
const mxArray *endo_names_mx = mxGetField(M_mx, 0, "endo_names");
|
||||
if (!(endo_names_mx && mxIsCell(endo_names_mx) && mxGetNumberOfElements(endo_names_mx) == static_cast<size_t>(nEndo)))
|
||||
const mxArray* endo_names_mx = mxGetField(M_mx, 0, "endo_names");
|
||||
if (!(endo_names_mx && mxIsCell(endo_names_mx)
|
||||
&& mxGetNumberOfElements(endo_names_mx) == static_cast<size_t>(nEndo)))
|
||||
mexErrMsgTxt("M_.endo_names should be a cell array of M_.endo_nbr elements");
|
||||
std::vector<std::string> endoNames = DynareMxArrayToString(endo_names_mx);
|
||||
|
||||
const mxArray *exo_names_mx = mxGetField(M_mx, 0, "exo_names");
|
||||
if (!(exo_names_mx && mxIsCell(exo_names_mx) && mxGetNumberOfElements(exo_names_mx) == static_cast<size_t>(nExog)))
|
||||
const mxArray* exo_names_mx = mxGetField(M_mx, 0, "exo_names");
|
||||
if (!(exo_names_mx && mxIsCell(exo_names_mx)
|
||||
&& mxGetNumberOfElements(exo_names_mx) == static_cast<size_t>(nExog)))
|
||||
mexErrMsgTxt("M_.exo_names should be a cell array of M_.exo_nbr elements");
|
||||
std::vector<std::string> exoNames = DynareMxArrayToString(exo_names_mx);
|
||||
|
||||
const mxArray *dynamic_tmp_nbr_mx = mxGetField(M_mx, 0, "dynamic_tmp_nbr");
|
||||
const mxArray* dynamic_tmp_nbr_mx = mxGetField(M_mx, 0, "dynamic_tmp_nbr");
|
||||
if (!(dynamic_tmp_nbr_mx && mxIsDouble(dynamic_tmp_nbr_mx) && !mxIsComplex(dynamic_tmp_nbr_mx)
|
||||
&& !mxIsSparse(dynamic_tmp_nbr_mx) && mxGetNumberOfElements(dynamic_tmp_nbr_mx) >= static_cast<size_t>(kOrder+1)))
|
||||
mexErrMsgTxt("M_.dynamic_tmp_nbr should be a double precision array with strictly more elements than the order of derivation");
|
||||
int ntt = std::accumulate(mxGetPr(dynamic_tmp_nbr_mx), mxGetPr(dynamic_tmp_nbr_mx)+kOrder+1, 0);
|
||||
&& !mxIsSparse(dynamic_tmp_nbr_mx)
|
||||
&& mxGetNumberOfElements(dynamic_tmp_nbr_mx) >= static_cast<size_t>(kOrder + 1)))
|
||||
mexErrMsgTxt("M_.dynamic_tmp_nbr should be a double precision array with strictly more "
|
||||
"elements than the order of derivation");
|
||||
int ntt
|
||||
= std::accumulate(mxGetPr(dynamic_tmp_nbr_mx), mxGetPr(dynamic_tmp_nbr_mx) + kOrder + 1, 0);
|
||||
|
||||
// Extract various fields from dr
|
||||
const mxArray *ys_mx = mxGetField(dr_mx, 0, "ys"); // and not in order of dr.order_var
|
||||
const mxArray* ys_mx = mxGetField(dr_mx, 0, "ys"); // and not in order of dr.order_var
|
||||
if (!(ys_mx && mxIsDouble(ys_mx) && !mxIsComplex(ys_mx) && !mxIsSparse(ys_mx)))
|
||||
mexErrMsgTxt("dr.ys should be a real dense array");
|
||||
Vector ySteady{ConstVector{ys_mx}};
|
||||
Vector ySteady {ConstVector {ys_mx}};
|
||||
if (!ySteady.isFinite())
|
||||
mexErrMsgTxt("dr.ys contains NaN or Inf");
|
||||
|
||||
const mxArray *order_var_mx = mxGetField(dr_mx, 0, "order_var");
|
||||
const mxArray* order_var_mx = mxGetField(dr_mx, 0, "order_var");
|
||||
if (!(order_var_mx && mxIsDouble(order_var_mx) && !mxIsComplex(order_var_mx)
|
||||
&& !mxIsSparse(order_var_mx)
|
||||
&& mxGetNumberOfElements(order_var_mx) == static_cast<size_t>(nEndo)))
|
||||
mexErrMsgTxt("dr.order_var should be a real dense array of M_.endo_nbr elements");
|
||||
std::vector<int> dr_order(nEndo);
|
||||
std::transform(mxGetPr(order_var_mx), mxGetPr(order_var_mx)+nEndo, dr_order.begin(),
|
||||
[](double x) { return static_cast<int>(x)-1; });
|
||||
std::transform(mxGetPr(order_var_mx), mxGetPr(order_var_mx) + nEndo, dr_order.begin(),
|
||||
[](double x) { return static_cast<int>(x) - 1; });
|
||||
|
||||
const int nSteps = 0; // Dynare++ solving steps, for time being default to 0 = deterministic steady state
|
||||
const int nSteps
|
||||
= 0; // Dynare++ solving steps, for time being default to 0 = deterministic steady state
|
||||
|
||||
// Journal is not written on-disk, unless options_.debug = true (see #1735)
|
||||
Journal journal;
|
||||
if (debug)
|
||||
journal = Journal{fname + ".jnl"};
|
||||
journal = Journal {fname + ".jnl"};
|
||||
|
||||
std::unique_ptr<DynamicModelAC> dynamicModelFile;
|
||||
if (use_dll)
|
||||
|
@ -254,31 +276,31 @@ extern "C" {
|
|||
dynamicModelFile = std::make_unique<DynamicModelMFile>(fname, ntt);
|
||||
|
||||
// intiate tensor library
|
||||
TLStatic::init(kOrder, nStat+2*nPred+3*nBoth+2*nForw+nExog);
|
||||
TLStatic::init(kOrder, nStat + 2 * nPred + 3 * nBoth + 2 * nForw + nExog);
|
||||
|
||||
// Set number of parallel threads
|
||||
sthread::detach_thread_group::max_parallel_threads = num_threads;
|
||||
|
||||
// make KordpDynare object
|
||||
KordpDynare dynare(endoNames, exoNames, nExog, nPar,
|
||||
ySteady, vCov, modParams, nStat, nPred, nForw, nBoth,
|
||||
NNZD, nSteps, kOrder, journal, std::move(dynamicModelFile),
|
||||
KordpDynare dynare(endoNames, exoNames, nExog, nPar, ySteady, vCov, modParams, nStat, nPred,
|
||||
nForw, nBoth, NNZD, nSteps, kOrder, journal, std::move(dynamicModelFile),
|
||||
dr_order, llincidence);
|
||||
|
||||
|
||||
// construct main K-order approximation class
|
||||
Approximation app(dynare, journal, nSteps, false, pruning, qz_criterium);
|
||||
// run stochastic steady
|
||||
app.walkStochSteady();
|
||||
|
||||
const mxArray *objective_tmp_nbr_mx = mxGetField(M_mx, 0, "objective_tmp_nbr");
|
||||
const mxArray* objective_tmp_nbr_mx = mxGetField(M_mx, 0, "objective_tmp_nbr");
|
||||
if (!(objective_tmp_nbr_mx && mxIsDouble(objective_tmp_nbr_mx)
|
||||
&& !mxIsComplex(objective_tmp_nbr_mx) && !mxIsSparse(objective_tmp_nbr_mx)
|
||||
&& mxGetNumberOfElements(objective_tmp_nbr_mx) >= static_cast<size_t>(kOrder+1)))
|
||||
mexErrMsgTxt("M_.objective_tmp_nbr should be a real dense array with strictly more elements than the order of derivation");
|
||||
int ntt_objective = std::accumulate(mxGetPr(objective_tmp_nbr_mx), mxGetPr(objective_tmp_nbr_mx)+kOrder+1, 0);
|
||||
&& mxGetNumberOfElements(objective_tmp_nbr_mx) >= static_cast<size_t>(kOrder + 1)))
|
||||
mexErrMsgTxt("M_.objective_tmp_nbr should be a real dense array with strictly more elements "
|
||||
"than the order of derivation");
|
||||
int ntt_objective = std::accumulate(mxGetPr(objective_tmp_nbr_mx),
|
||||
mxGetPr(objective_tmp_nbr_mx) + kOrder + 1, 0);
|
||||
|
||||
//Getting derivatives of the planner's objective function
|
||||
// Getting derivatives of the planner's objective function
|
||||
std::unique_ptr<ObjectiveAC> objectiveFile;
|
||||
objectiveFile = std::make_unique<ObjectiveMFile>(fname, ntt_objective);
|
||||
|
||||
|
@ -286,25 +308,26 @@ extern "C" {
|
|||
KordwDynare welfare(dynare, NNZD_obj, journal, modParams, std::move(objectiveFile), dr_order);
|
||||
|
||||
// construct main K-order approximation class of welfare
|
||||
ApproximationWelfare appwel(welfare, discount_factor, app.get_rule_ders(), app.get_rule_ders_s(), journal);
|
||||
ApproximationWelfare appwel(welfare, discount_factor, app.get_rule_ders(),
|
||||
app.get_rule_ders_s(), journal);
|
||||
appwel.approxAtSteady();
|
||||
|
||||
const FoldDecisionRule &cond_fdr = appwel.getFoldCondWel();
|
||||
const FoldDecisionRule& cond_fdr = appwel.getFoldCondWel();
|
||||
// Add possibly missing field names
|
||||
for (int i = static_cast<int>(W_fieldnames.size()); i <= kOrder; i++)
|
||||
W_fieldnames.emplace_back("W_" + std::to_string(i));
|
||||
// Create structure for storing derivatives in Dynare++ format
|
||||
const char *W_fieldnames_c[kOrder+1];
|
||||
const char* W_fieldnames_c[kOrder + 1];
|
||||
for (int i = 0; i <= kOrder; i++)
|
||||
W_fieldnames_c[i] = W_fieldnames[i].c_str();
|
||||
plhs[0] = mxCreateStructMatrix(1, 1, kOrder+1, W_fieldnames_c);
|
||||
plhs[0] = mxCreateStructMatrix(1, 1, kOrder + 1, W_fieldnames_c);
|
||||
|
||||
// Fill that structure
|
||||
for (int i = 0; i <= kOrder; i++)
|
||||
{
|
||||
const FFSTensor &t = cond_fdr.get(Symmetry{i});
|
||||
mxArray *tmp = mxCreateDoubleMatrix(t.nrows(), t.ncols(), mxREAL);
|
||||
const ConstVector &vec = t.getData();
|
||||
const FFSTensor& t = cond_fdr.get(Symmetry {i});
|
||||
mxArray* tmp = mxCreateDoubleMatrix(t.nrows(), t.ncols(), mxREAL);
|
||||
const ConstVector& vec = t.getData();
|
||||
assert(vec.skip() == 1);
|
||||
std::copy_n(vec.base(), vec.length(), mxGetPr(tmp));
|
||||
mxSetField(plhs[0], 0, ("W_" + std::to_string(i)).c_str(), tmp);
|
||||
|
|
|
@ -29,10 +29,10 @@ class ObjectiveAC
|
|||
protected:
|
||||
int ntt; // Size of vector of temporary terms
|
||||
public:
|
||||
ObjectiveAC(int ntt_arg) : ntt{ntt_arg}
|
||||
{
|
||||
};
|
||||
ObjectiveAC(int ntt_arg) : ntt {ntt_arg} {};
|
||||
virtual ~ObjectiveAC() = default;
|
||||
virtual void eval(const Vector &y, const Vector &x, const Vector ¶ms, Vector &residual, std::vector<TwoDMatrix> &md) = 0;
|
||||
virtual void eval(const Vector& y, const Vector& x, const Vector& params, Vector& residual,
|
||||
std::vector<TwoDMatrix>& md)
|
||||
= 0;
|
||||
};
|
||||
#endif
|
||||
|
|
|
@ -25,18 +25,17 @@
|
|||
|
||||
#include "objective_m.hh"
|
||||
|
||||
ObjectiveMFile::ObjectiveMFile(const std::string &modName, int ntt_arg) :
|
||||
ObjectiveAC(ntt_arg),
|
||||
ObjectiveMFilename{modName + ".objective.static"}
|
||||
ObjectiveMFile::ObjectiveMFile(const std::string& modName, int ntt_arg) :
|
||||
ObjectiveAC(ntt_arg), ObjectiveMFilename {modName + ".objective.static"}
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
ObjectiveMFile::unpackSparseMatrixAndCopyIntoTwoDMatData(mxArray *sparseMat, TwoDMatrix &tdm)
|
||||
ObjectiveMFile::unpackSparseMatrixAndCopyIntoTwoDMatData(mxArray* sparseMat, TwoDMatrix& tdm)
|
||||
{
|
||||
int totalCols = mxGetN(sparseMat);
|
||||
mwIndex *rowIdxVector = mxGetIr(sparseMat);
|
||||
mwIndex *colIdxVector = mxGetJc(sparseMat);
|
||||
mwIndex* rowIdxVector = mxGetIr(sparseMat);
|
||||
mwIndex* colIdxVector = mxGetJc(sparseMat);
|
||||
|
||||
assert(tdm.ncols() == 3);
|
||||
/* Under MATLAB, the following check always holds at equality; under Octave,
|
||||
|
@ -44,13 +43,13 @@ ObjectiveMFile::unpackSparseMatrixAndCopyIntoTwoDMatData(mxArray *sparseMat, Two
|
|||
zeros in the values vector when calling sparse(). */
|
||||
assert(tdm.nrows() >= static_cast<int>(mxGetNzmax(sparseMat)));
|
||||
|
||||
double *ptr = mxGetPr(sparseMat);
|
||||
double* ptr = mxGetPr(sparseMat);
|
||||
|
||||
int rind = 0;
|
||||
int output_row = 0;
|
||||
|
||||
for (int i = 0; i < totalCols; i++)
|
||||
for (int j = 0; j < static_cast<int>((colIdxVector[i+1]-colIdxVector[i])); j++, rind++)
|
||||
for (int j = 0; j < static_cast<int>((colIdxVector[i + 1] - colIdxVector[i])); j++, rind++)
|
||||
{
|
||||
tdm.get(output_row, 0) = rowIdxVector[rind] + 1;
|
||||
tdm.get(output_row, 1) = i + 1;
|
||||
|
@ -72,28 +71,29 @@ ObjectiveMFile::unpackSparseMatrixAndCopyIntoTwoDMatData(mxArray *sparseMat, Two
|
|||
}
|
||||
|
||||
void
|
||||
ObjectiveMFile::eval(const Vector &y, const Vector &x, const Vector &modParams,
|
||||
Vector &residual, std::vector<TwoDMatrix> &md) noexcept(false)
|
||||
ObjectiveMFile::eval(const Vector& y, const Vector& x, const Vector& modParams, Vector& residual,
|
||||
std::vector<TwoDMatrix>& md) noexcept(false)
|
||||
{
|
||||
mxArray *T_m = mxCreateDoubleMatrix(ntt, 1, mxREAL);
|
||||
mxArray* T_m = mxCreateDoubleMatrix(ntt, 1, mxREAL);
|
||||
|
||||
mxArray *y_m = mxCreateDoubleMatrix(y.length(), 1, mxREAL);
|
||||
mxArray* y_m = mxCreateDoubleMatrix(y.length(), 1, mxREAL);
|
||||
std::copy_n(y.base(), y.length(), mxGetPr(y_m));
|
||||
|
||||
mxArray *x_m = mxCreateDoubleMatrix(1, x.length(), mxREAL);
|
||||
mxArray* x_m = mxCreateDoubleMatrix(1, x.length(), mxREAL);
|
||||
std::copy_n(x.base(), x.length(), mxGetPr(x_m));
|
||||
|
||||
mxArray *params_m = mxCreateDoubleMatrix(modParams.length(), 1, mxREAL);
|
||||
mxArray* params_m = mxCreateDoubleMatrix(modParams.length(), 1, mxREAL);
|
||||
std::copy_n(modParams.base(), modParams.length(), mxGetPr(params_m));
|
||||
|
||||
mxArray *T_flag_m = mxCreateLogicalScalar(false);
|
||||
mxArray* T_flag_m = mxCreateLogicalScalar(false);
|
||||
|
||||
{
|
||||
// Compute temporary terms (for all orders)
|
||||
std::string funcname = ObjectiveMFilename + "_g" + std::to_string(md.size()) + "_tt";
|
||||
mxArray *plhs[1], *prhs[] = { T_m, y_m, x_m, params_m };
|
||||
mxArray *plhs[1], *prhs[] = {T_m, y_m, x_m, params_m};
|
||||
|
||||
int retVal = mexCallMATLAB(std::extent_v<decltype(plhs)>, plhs, std::extent_v<decltype(prhs)>, prhs, funcname.c_str());
|
||||
int retVal = mexCallMATLAB(std::extent_v<decltype(plhs)>, plhs, std::extent_v<decltype(prhs)>,
|
||||
prhs, funcname.c_str());
|
||||
if (retVal != 0)
|
||||
throw DynareException(__FILE__, __LINE__, "Trouble calling " + funcname);
|
||||
|
||||
|
@ -104,13 +104,14 @@ ObjectiveMFile::eval(const Vector &y, const Vector &x, const Vector &modParams,
|
|||
{
|
||||
// Compute residuals
|
||||
std::string funcname = ObjectiveMFilename + "_resid";
|
||||
mxArray *plhs[1], *prhs[] = { T_m, y_m, x_m, params_m, T_flag_m };
|
||||
mxArray *plhs[1], *prhs[] = {T_m, y_m, x_m, params_m, T_flag_m};
|
||||
|
||||
int retVal = mexCallMATLAB(std::extent_v<decltype(plhs)>, plhs, std::extent_v<decltype(prhs)>, prhs, funcname.c_str());
|
||||
int retVal = mexCallMATLAB(std::extent_v<decltype(plhs)>, plhs, std::extent_v<decltype(prhs)>,
|
||||
prhs, funcname.c_str());
|
||||
if (retVal != 0)
|
||||
throw DynareException(__FILE__, __LINE__, "Trouble calling " + funcname);
|
||||
|
||||
residual = Vector{plhs[0]};
|
||||
residual = Vector {plhs[0]};
|
||||
mxDestroyArray(plhs[0]);
|
||||
}
|
||||
|
||||
|
@ -118,20 +119,21 @@ ObjectiveMFile::eval(const Vector &y, const Vector &x, const Vector &modParams,
|
|||
{
|
||||
// Compute model derivatives
|
||||
std::string funcname = ObjectiveMFilename + "_g" + std::to_string(i);
|
||||
mxArray *plhs[1], *prhs[] = { T_m, y_m, x_m, params_m, T_flag_m };
|
||||
mxArray *plhs[1], *prhs[] = {T_m, y_m, x_m, params_m, T_flag_m};
|
||||
|
||||
int retVal = mexCallMATLAB(std::extent_v<decltype(plhs)>, plhs, std::extent_v<decltype(prhs)>, prhs, funcname.c_str());
|
||||
int retVal = mexCallMATLAB(std::extent_v<decltype(plhs)>, plhs, std::extent_v<decltype(prhs)>,
|
||||
prhs, funcname.c_str());
|
||||
if (retVal != 0)
|
||||
throw DynareException(__FILE__, __LINE__, "Trouble calling " + funcname);
|
||||
|
||||
if (i == 1)
|
||||
{
|
||||
assert(static_cast<int>(mxGetM(plhs[0])) == md[i-1].nrows());
|
||||
assert(static_cast<int>(mxGetN(plhs[0])) == md[i-1].ncols());
|
||||
std::copy_n(mxGetPr(plhs[0]), mxGetM(plhs[0])*mxGetN(plhs[0]), md[i-1].base());
|
||||
assert(static_cast<int>(mxGetM(plhs[0])) == md[i - 1].nrows());
|
||||
assert(static_cast<int>(mxGetN(plhs[0])) == md[i - 1].ncols());
|
||||
std::copy_n(mxGetPr(plhs[0]), mxGetM(plhs[0]) * mxGetN(plhs[0]), md[i - 1].base());
|
||||
}
|
||||
else
|
||||
unpackSparseMatrixAndCopyIntoTwoDMatData(plhs[0], md[i-1]);
|
||||
unpackSparseMatrixAndCopyIntoTwoDMatData(plhs[0], md[i - 1]);
|
||||
|
||||
mxDestroyArray(plhs[0]);
|
||||
}
|
||||
|
|
|
@ -33,11 +33,12 @@ class ObjectiveMFile : public ObjectiveAC
|
|||
{
|
||||
private:
|
||||
const std::string ObjectiveMFilename;
|
||||
static void unpackSparseMatrixAndCopyIntoTwoDMatData(mxArray *sparseMat, TwoDMatrix &tdm);
|
||||
static void unpackSparseMatrixAndCopyIntoTwoDMatData(mxArray* sparseMat, TwoDMatrix& tdm);
|
||||
|
||||
public:
|
||||
explicit ObjectiveMFile(const std::string &modName, int ntt_arg);
|
||||
explicit ObjectiveMFile(const std::string& modName, int ntt_arg);
|
||||
virtual ~ObjectiveMFile() = default;
|
||||
void eval(const Vector &y, const Vector &x, const Vector ¶ms,
|
||||
Vector &residual, std::vector<TwoDMatrix> &md) override;
|
||||
void eval(const Vector& y, const Vector& x, const Vector& params, Vector& residual,
|
||||
std::vector<TwoDMatrix>& md) override;
|
||||
};
|
||||
#endif
|
||||
|
|
|
@ -26,7 +26,8 @@
|
|||
++
|
||||
++ [0] T (double) n×n transition matrix.
|
||||
++
|
||||
++ [1] QQ (double) n×n matrix (=R·Q·Rᵀ, where Q is the covariance matrix of the structural innovations).
|
||||
++ [1] QQ (double) n×n matrix (=R·Q·Rᵀ, where Q is the covariance matrix of the
|
||||
structural innovations).
|
||||
++
|
||||
++ [2] Z (double) n×p selection matrix.
|
||||
++
|
||||
|
@ -49,9 +50,9 @@
|
|||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <dynmex.h>
|
||||
#include <dynlapack.h>
|
||||
#include <dynmex.h>
|
||||
#include <memory>
|
||||
|
||||
#define sb02od FORTRAN_WRAPPER(sb02od)
|
||||
|
||||
|
@ -59,19 +60,19 @@ extern "C"
|
|||
{
|
||||
/* Note: matrices q, r and l may be modified internally (though they are
|
||||
restored on exit), hence their pointers are not declared as const */
|
||||
int sb02od(const char *dico, const char *jobb, const char *fact, const char *uplo,
|
||||
const char *jobl, const char *sort, const lapack_int *n, const lapack_int *m,
|
||||
const lapack_int *p, const double *a, const lapack_int *lda, const double *b,
|
||||
const lapack_int *ldb, double *q, const lapack_int *ldq, double *r, const lapack_int *ldr,
|
||||
double *l, const lapack_int *ldl, double *rcond, double *x, const lapack_int *ldx,
|
||||
double *alfar, double *alfai, double *beta, double *s, const lapack_int *lds, double *t,
|
||||
const lapack_int *ldt, double *u, const lapack_int *ldu, const double *tol,
|
||||
lapack_int *iwork, double *dwork, const lapack_int *ldwork, lapack_int *bwork,
|
||||
lapack_int *info);
|
||||
int sb02od(const char* dico, const char* jobb, const char* fact, const char* uplo,
|
||||
const char* jobl, const char* sort, const lapack_int* n, const lapack_int* m,
|
||||
const lapack_int* p, const double* a, const lapack_int* lda, const double* b,
|
||||
const lapack_int* ldb, double* q, const lapack_int* ldq, double* r,
|
||||
const lapack_int* ldr, double* l, const lapack_int* ldl, double* rcond, double* x,
|
||||
const lapack_int* ldx, double* alfar, double* alfai, double* beta, double* s,
|
||||
const lapack_int* lds, double* t, const lapack_int* ldt, double* u,
|
||||
const lapack_int* ldu, const double* tol, lapack_int* iwork, double* dwork,
|
||||
const lapack_int* ldwork, lapack_int* bwork, lapack_int* info);
|
||||
}
|
||||
|
||||
void
|
||||
mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
||||
mexFunction(int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[])
|
||||
{
|
||||
// Check the number of arguments and set some flags.
|
||||
bool measurement_error_flag = true;
|
||||
|
@ -97,10 +98,12 @@ mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
|||
if (mxIsNumeric(prhs[1]) == 0 || mxIsComplex(prhs[1]) == 1)
|
||||
mexErrMsgTxt("kalman_steady_state: The second input argument (QQ) must be a real matrix!");
|
||||
if (q != n)
|
||||
mexErrMsgTxt("kalman_steady_state: The size of the second input argument (QQ) must match the size of the first argument (T)!");
|
||||
mexErrMsgTxt("kalman_steady_state: The size of the second input argument (QQ) must match the "
|
||||
"size of the first argument (T)!");
|
||||
lapack_int p = mxGetN(prhs[2]);
|
||||
if (mxGetM(prhs[2]) != static_cast<size_t>(n))
|
||||
mexErrMsgTxt("kalman_steady_state: The number of rows of the third argument (Z) must match the number of rows of the first argument (T)!");
|
||||
mexErrMsgTxt("kalman_steady_state: The number of rows of the third argument (Z) must match the "
|
||||
"number of rows of the first argument (T)!");
|
||||
if (mxIsNumeric(prhs[2]) == 0 || mxIsComplex(prhs[2]) == 1)
|
||||
mexErrMsgTxt("kalman_steady_state: The third input argument (Z) must be a real matrix!");
|
||||
if (measurement_error_flag)
|
||||
|
@ -108,30 +111,35 @@ mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
|||
if (mxGetM(prhs[3]) != mxGetN(prhs[3]))
|
||||
mexErrMsgTxt("kalman_steady_state: The fourth input argument (H) must be a square matrix!");
|
||||
if (mxGetM(prhs[3]) != static_cast<size_t>(p))
|
||||
mexErrMsgTxt("kalman_steady_state: The number of rows of the fourth input argument (H) must match the number of rows of the third input argument!");
|
||||
mexErrMsgTxt("kalman_steady_state: The number of rows of the fourth input argument (H) "
|
||||
"must match the number of rows of the third input argument!");
|
||||
if (mxIsNumeric(prhs[3]) == 0 || mxIsComplex(prhs[3]) == 1)
|
||||
mexErrMsgTxt("kalman_steady_state: The fifth input argument (H) must be a real matrix!");
|
||||
}
|
||||
// Get input matrices.
|
||||
const double *T = mxGetPr(prhs[0]);
|
||||
auto QQ = std::make_unique<double[]>(n*n);
|
||||
std::copy_n(mxGetPr(prhs[1]), n*n, QQ.get());
|
||||
const double *Z = mxGetPr(prhs[2]);
|
||||
auto H = std::make_unique<double[]>(p*p);
|
||||
const double* T = mxGetPr(prhs[0]);
|
||||
auto QQ = std::make_unique<double[]>(n * n);
|
||||
std::copy_n(mxGetPr(prhs[1]), n * n, QQ.get());
|
||||
const double* Z = mxGetPr(prhs[2]);
|
||||
auto H = std::make_unique<double[]>(p * p);
|
||||
if (measurement_error_flag)
|
||||
std::copy_n(mxGetPr(prhs[3]), p*p, H.get());
|
||||
std::copy_n(mxGetPr(prhs[3]), p * p, H.get());
|
||||
// L will not be used.
|
||||
auto L = std::make_unique<double[]>(n*p);
|
||||
lapack_int nn = 2*n;
|
||||
auto L = std::make_unique<double[]>(n * p);
|
||||
lapack_int nn = 2 * n;
|
||||
lapack_int LDA = std::max(static_cast<lapack_int>(1), n);
|
||||
lapack_int LDQ = LDA;
|
||||
lapack_int LDU = std::max(static_cast<lapack_int>(1), nn);
|
||||
lapack_int LDS = std::max(static_cast<lapack_int>(1), nn+p);
|
||||
lapack_int LDS = std::max(static_cast<lapack_int>(1), nn + p);
|
||||
lapack_int LIWORK = std::max(static_cast<lapack_int>(1), std::max(p, nn));
|
||||
lapack_int LDR = std::max(static_cast<lapack_int>(1), p);
|
||||
lapack_int LDB = LDA, LDL = LDA, LDT = LDS, LDX = LDA;
|
||||
lapack_int LDWORK = std::max(static_cast<lapack_int>(7)*(static_cast<lapack_int>(2)*n + static_cast<lapack_int>(1)) + static_cast<lapack_int>(16), static_cast<lapack_int>(16)*n);
|
||||
LDWORK = std::max(LDWORK, std::max(static_cast<lapack_int>(2)*n + p, static_cast<lapack_int>(3)*p));
|
||||
lapack_int LDWORK = std::max(
|
||||
static_cast<lapack_int>(7) * (static_cast<lapack_int>(2) * n + static_cast<lapack_int>(1))
|
||||
+ static_cast<lapack_int>(16),
|
||||
static_cast<lapack_int>(16) * n);
|
||||
LDWORK = std::max(LDWORK,
|
||||
std::max(static_cast<lapack_int>(2) * n + p, static_cast<lapack_int>(3) * p));
|
||||
double tolerance = 1e-16;
|
||||
lapack_int INFO;
|
||||
// Outputs of subroutine sb02OD
|
||||
|
@ -139,16 +147,16 @@ mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
|||
auto WR = std::make_unique<double[]>(nn);
|
||||
auto WI = std::make_unique<double[]>(nn);
|
||||
auto BETA = std::make_unique<double[]>(nn);
|
||||
auto S = std::make_unique<double[]>(LDS*(nn+p));
|
||||
auto TT = std::make_unique<double[]>(LDT*nn);
|
||||
auto UU = std::make_unique<double[]>(LDU*nn);
|
||||
auto S = std::make_unique<double[]>(LDS * (nn + p));
|
||||
auto TT = std::make_unique<double[]>(LDT * nn);
|
||||
auto UU = std::make_unique<double[]>(LDU * nn);
|
||||
// Working arrays
|
||||
auto IWORK = std::make_unique<lapack_int[]>(LIWORK);
|
||||
auto DWORK = std::make_unique<double[]>(LDWORK);
|
||||
auto BWORK = std::make_unique<lapack_int[]>(nn);
|
||||
// Initialize the output of the mex file
|
||||
plhs[0] = mxCreateDoubleMatrix(n, n, mxREAL);
|
||||
double *P = mxGetPr(plhs[0]);
|
||||
double* P = mxGetPr(plhs[0]);
|
||||
// Call the slicot routine
|
||||
sb02od("D", // We want to solve a discrete Riccati equation.
|
||||
"B", // Matrices Z and H are given.
|
||||
|
@ -156,15 +164,16 @@ mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
|||
"U", // Upper triangle of matrix H is stored.
|
||||
"Z", // L matrix is zero.
|
||||
"S", // Stable eigenvalues come first.
|
||||
&n, &p, &p, T, &LDA, Z, &LDB, QQ.get(), &LDQ, H.get(), &LDR, L.get(), &LDL,
|
||||
&rcond, P, &LDX, WR.get(), WI.get(), BETA.get(), S.get(), &LDS, TT.get(), &LDT, UU.get(),
|
||||
&LDU, &tolerance, IWORK.get(), DWORK.get(), &LDWORK, BWORK.get(), &INFO);
|
||||
&n, &p, &p, T, &LDA, Z, &LDB, QQ.get(), &LDQ, H.get(), &LDR, L.get(), &LDL, &rcond, P,
|
||||
&LDX, WR.get(), WI.get(), BETA.get(), S.get(), &LDS, TT.get(), &LDT, UU.get(), &LDU,
|
||||
&tolerance, IWORK.get(), DWORK.get(), &LDWORK, BWORK.get(), &INFO);
|
||||
switch (INFO)
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
mexErrMsgTxt("The computed extended matrix pencil is singular, possibly due to rounding errors.");
|
||||
mexErrMsgTxt(
|
||||
"The computed extended matrix pencil is singular, possibly due to rounding errors.");
|
||||
break;
|
||||
case 2:
|
||||
mexErrMsgTxt("The QZ (or QR) algorithm failed!");
|
||||
|
@ -173,13 +182,16 @@ mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
|||
mexErrMsgTxt("The reordering of the (generalized) eigenvalues failed!");
|
||||
break;
|
||||
case 4:
|
||||
mexErrMsgTxt("After reordering, roundoff changed values of some complex eigenvalues so that leading eigenvalues\n in the (generalized) Schur form no longer satisfy the stability condition; this could also be caused due to scaling.");
|
||||
mexErrMsgTxt("After reordering, roundoff changed values of some complex eigenvalues so that "
|
||||
"leading eigenvalues\n in the (generalized) Schur form no longer satisfy the "
|
||||
"stability condition; this could also be caused due to scaling.");
|
||||
break;
|
||||
case 5:
|
||||
mexErrMsgTxt("The computed dimension of the solution does not equal n!");
|
||||
break;
|
||||
case 6:
|
||||
mexErrMsgTxt("A singular matrix was encountered during the computation of the solution matrix P!");
|
||||
mexErrMsgTxt(
|
||||
"A singular matrix was encountered during the computation of the solution matrix P!");
|
||||
break;
|
||||
default:
|
||||
mexErrMsgTxt("Unknown problem!");
|
||||
|
|
|
@ -19,8 +19,8 @@
|
|||
|
||||
/*
|
||||
* This mex file computes A·(B⊗C) or A·(B⊗B) without explicitly building B⊗C or B⊗B, so that
|
||||
* one can consider large matrices A, B and/or C, and assuming that A is a the hessian of a DSGE model
|
||||
* (dynare format). This mex file should not be used outside dyn_second_order_solver.m.
|
||||
* one can consider large matrices A, B and/or C, and assuming that A is a the hessian of a DSGE
|
||||
* model (dynare format). This mex file should not be used outside dyn_second_order_solver.m.
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
|
@ -32,8 +32,9 @@
|
|||
#define DEBUG_OMP 0
|
||||
|
||||
void
|
||||
sparse_hessian_times_B_kronecker_B(const mwIndex *isparseA, const mwIndex *jsparseA, const double *vsparseA,
|
||||
const double *B, double *D, size_t mA, size_t nA, size_t mB, size_t nB, int number_of_threads)
|
||||
sparse_hessian_times_B_kronecker_B(const mwIndex* isparseA, const mwIndex* jsparseA,
|
||||
const double* vsparseA, const double* B, double* D, size_t mA,
|
||||
size_t nA, size_t mB, size_t nB, int number_of_threads)
|
||||
{
|
||||
/*
|
||||
** Loop over the columns of B⊗B (or of the result matrix D).
|
||||
|
@ -48,7 +49,7 @@ sparse_hessian_times_B_kronecker_B(const mwIndex *isparseA, const mwIndex *jspar
|
|||
#endif
|
||||
for (mwIndex j2B = j1B; j2B < static_cast<mwIndex>(nB); j2B++)
|
||||
{
|
||||
mwIndex jj = j1B*nB+j2B; // column of B⊗B index.
|
||||
mwIndex jj = j1B * nB + j2B; // column of B⊗B index.
|
||||
mwIndex iv = 0;
|
||||
int nz_in_column_ii_of_A = 0;
|
||||
mwIndex k1 = 0;
|
||||
|
@ -59,47 +60,49 @@ sparse_hessian_times_B_kronecker_B(const mwIndex *isparseA, const mwIndex *jspar
|
|||
for (mwIndex ii = 0; ii < static_cast<mwIndex>(nA); ii++)
|
||||
{
|
||||
k1 = jsparseA[ii];
|
||||
k2 = jsparseA[ii+1];
|
||||
if (k1 < k2) // otherwise column ii of A does not have non zero elements (and there is nothing to compute).
|
||||
k2 = jsparseA[ii + 1];
|
||||
if (k1 < k2) // otherwise column ii of A does not have non zero elements (and there is
|
||||
// nothing to compute).
|
||||
{
|
||||
++nz_in_column_ii_of_A;
|
||||
mwIndex i1B = ii / mB;
|
||||
mwIndex i2B = ii % mB;
|
||||
double bb = B[j1B*mB+i1B]*B[j2B*mB+i2B];
|
||||
double bb = B[j1B * mB + i1B] * B[j2B * mB + i2B];
|
||||
/*
|
||||
** Loop over the non zero entries of A(:,ii).
|
||||
*/
|
||||
for (mwIndex k = k1; k < k2; k++)
|
||||
{
|
||||
mwIndex kk = isparseA[k];
|
||||
D[jj*mA+kk] = D[jj*mA+kk] + bb*vsparseA[iv];
|
||||
D[jj * mA + kk] = D[jj * mA + kk] + bb * vsparseA[iv];
|
||||
iv++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (nz_in_column_ii_of_A > 0)
|
||||
std::copy_n(&D[jj*mA], mA, &D[(j2B*nB+j1B)*mA]);
|
||||
std::copy_n(&D[jj * mA], mA, &D[(j2B * nB + j1B) * mA]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
sparse_hessian_times_B_kronecker_C(const mwIndex *isparseA, const mwIndex *jsparseA, const double *vsparseA,
|
||||
const double *B, const double *C, double *D,
|
||||
size_t mA, size_t nA, size_t mB, size_t nB, size_t mC, size_t nC, int number_of_threads)
|
||||
sparse_hessian_times_B_kronecker_C(const mwIndex* isparseA, const mwIndex* jsparseA,
|
||||
const double* vsparseA, const double* B, const double* C,
|
||||
double* D, size_t mA, size_t nA, size_t mB, size_t nB, size_t mC,
|
||||
size_t nC, int number_of_threads)
|
||||
{
|
||||
/*
|
||||
** Loop over the columns of B⊗B (or of the result matrix D).
|
||||
*/
|
||||
#pragma omp parallel for num_threads(number_of_threads)
|
||||
for (mwIndex jj = 0; jj < static_cast<mwIndex>(nB*nC); jj++) // column of B⊗C index.
|
||||
for (mwIndex jj = 0; jj < static_cast<mwIndex>(nB * nC); jj++) // column of B⊗C index.
|
||||
{
|
||||
// Uncomment the following line to check if all processors are used.
|
||||
#if DEBUG_OMP
|
||||
mexPrintf("%d thread number is %d (%d).\n", jj, omp_get_thread_num(), omp_get_num_threads());
|
||||
#endif
|
||||
mwIndex jB = jj/nC;
|
||||
mwIndex jC = jj%nC;
|
||||
mwIndex jB = jj / nC;
|
||||
mwIndex jC = jj % nC;
|
||||
mwIndex k1 = 0;
|
||||
mwIndex k2 = 0;
|
||||
mwIndex iv = 0;
|
||||
|
@ -110,20 +113,21 @@ sparse_hessian_times_B_kronecker_C(const mwIndex *isparseA, const mwIndex *jspar
|
|||
for (mwIndex ii = 0; ii < static_cast<mwIndex>(nA); ii++)
|
||||
{
|
||||
k1 = jsparseA[ii];
|
||||
k2 = jsparseA[ii+1];
|
||||
if (k1 < k2) // otherwise column ii of A does not have non zero elements (and there is nothing to compute).
|
||||
k2 = jsparseA[ii + 1];
|
||||
if (k1 < k2) // otherwise column ii of A does not have non zero elements (and there is
|
||||
// nothing to compute).
|
||||
{
|
||||
++nz_in_column_ii_of_A;
|
||||
mwIndex iC = ii % mC;
|
||||
mwIndex iB = ii / mC;
|
||||
double cb = C[jC*mC+iC]*B[jB*mB+iB];
|
||||
double cb = C[jC * mC + iC] * B[jB * mB + iB];
|
||||
/*
|
||||
** Loop over the non zero entries of A(:,ii).
|
||||
*/
|
||||
for (mwIndex k = k1; k < k2; k++)
|
||||
{
|
||||
mwIndex kk = isparseA[k];
|
||||
D[jj*mA+kk] = D[jj*mA+kk] + cb*vsparseA[iv];
|
||||
D[jj * mA + kk] = D[jj * mA + kk] + cb * vsparseA[iv];
|
||||
iv++;
|
||||
}
|
||||
}
|
||||
|
@ -132,12 +136,13 @@ sparse_hessian_times_B_kronecker_C(const mwIndex *isparseA, const mwIndex *jspar
|
|||
}
|
||||
|
||||
void
|
||||
mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
||||
mexFunction(int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[])
|
||||
{
|
||||
// Check input and output:
|
||||
if (nrhs > 4 || nrhs < 3 || nlhs != 1)
|
||||
{
|
||||
mexErrMsgTxt("sparse_hessian_times_B_kronecker_C takes 3 or 4 input arguments and provides 1 output argument.");
|
||||
mexErrMsgTxt("sparse_hessian_times_B_kronecker_C takes 3 or 4 input arguments and provides 1 "
|
||||
"output argument.");
|
||||
return; // Needed to shut up some GCC warnings
|
||||
}
|
||||
|
||||
|
@ -158,19 +163,19 @@ mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
|||
{
|
||||
mC = mxGetM(prhs[2]);
|
||||
nC = mxGetN(prhs[2]);
|
||||
if (mB*mC != nA)
|
||||
if (mB * mC != nA)
|
||||
mexErrMsgTxt("Input dimension error!");
|
||||
}
|
||||
else // A·(B⊗B) is to be computed.
|
||||
{
|
||||
if (mB*mB != nA)
|
||||
if (mB * mB != nA)
|
||||
mexErrMsgTxt("Input dimension error!");
|
||||
}
|
||||
// Get input matrices:
|
||||
int numthreads;
|
||||
const double *B = mxGetPr(prhs[1]);
|
||||
const double *C;
|
||||
const mxArray *numthreads_mx;
|
||||
const double* B = mxGetPr(prhs[1]);
|
||||
const double* C;
|
||||
const mxArray* numthreads_mx;
|
||||
if (nrhs == 4)
|
||||
{
|
||||
C = mxGetPr(prhs[2]);
|
||||
|
@ -186,19 +191,21 @@ mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
|||
mexErrMsgTxt("sparse_hessian_times_B_kronecker_C: Last input must be a positive integer.");
|
||||
|
||||
// Sparse (dynare) hessian matrix.
|
||||
const mwIndex *isparseA = mxGetIr(prhs[0]);
|
||||
const mwIndex *jsparseA = mxGetJc(prhs[0]);
|
||||
const double *vsparseA = mxGetPr(prhs[0]);
|
||||
const mwIndex* isparseA = mxGetIr(prhs[0]);
|
||||
const mwIndex* jsparseA = mxGetJc(prhs[0]);
|
||||
const double* vsparseA = mxGetPr(prhs[0]);
|
||||
// Initialization of the ouput:
|
||||
if (nrhs == 4)
|
||||
plhs[0] = mxCreateDoubleMatrix(mA, nB*nC, mxREAL);
|
||||
plhs[0] = mxCreateDoubleMatrix(mA, nB * nC, mxREAL);
|
||||
else
|
||||
plhs[0] = mxCreateDoubleMatrix(mA, nB*nB, mxREAL);
|
||||
double *D = mxGetPr(plhs[0]);
|
||||
plhs[0] = mxCreateDoubleMatrix(mA, nB * nB, mxREAL);
|
||||
double* D = mxGetPr(plhs[0]);
|
||||
|
||||
// Computational part:
|
||||
if (nrhs == 3)
|
||||
sparse_hessian_times_B_kronecker_B(isparseA, jsparseA, vsparseA, B, D, mA, nA, mB, nB, numthreads);
|
||||
sparse_hessian_times_B_kronecker_B(isparseA, jsparseA, vsparseA, B, D, mA, nA, mB, nB,
|
||||
numthreads);
|
||||
else
|
||||
sparse_hessian_times_B_kronecker_C(isparseA, jsparseA, vsparseA, B, C, D, mA, nA, mB, nB, mC, nC, numthreads);
|
||||
sparse_hessian_times_B_kronecker_C(isparseA, jsparseA, vsparseA, B, C, D, mA, nA, mB, nB, mC,
|
||||
nC, numthreads);
|
||||
}
|
||||
|
|
|
@ -29,11 +29,10 @@ class DynamicModelAC
|
|||
protected:
|
||||
int ntt; // Size of vector of temporary terms
|
||||
public:
|
||||
DynamicModelAC(int ntt_arg) : ntt{ntt_arg}
|
||||
{
|
||||
};
|
||||
DynamicModelAC(int ntt_arg) : ntt {ntt_arg} {};
|
||||
virtual ~DynamicModelAC() = default;
|
||||
virtual void eval(const Vector &y, const Vector &x, const Vector ¶ms, const Vector &ySteady,
|
||||
Vector &residual, std::vector<TwoDMatrix> &md) = 0;
|
||||
virtual void eval(const Vector& y, const Vector& x, const Vector& params, const Vector& ySteady,
|
||||
Vector& residual, std::vector<TwoDMatrix>& md)
|
||||
= 0;
|
||||
};
|
||||
#endif
|
||||
|
|
|
@ -19,11 +19,11 @@
|
|||
|
||||
#include "dynamic_dll.hh"
|
||||
|
||||
#include <iostream>
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
|
||||
DynamicModelDLL::DynamicModelDLL(const std::string &modName, int ntt_arg, int order)
|
||||
: DynamicModelAC(ntt_arg)
|
||||
DynamicModelDLL::DynamicModelDLL(const std::string& modName, int ntt_arg, int order) :
|
||||
DynamicModelAC(ntt_arg)
|
||||
{
|
||||
std::string fName;
|
||||
#if !defined(__CYGWIN32__) && !defined(_WIN32)
|
||||
|
@ -37,20 +37,24 @@ DynamicModelDLL::DynamicModelDLL(const std::string &modName, int ntt_arg, int or
|
|||
dynamicHinstance = dlopen(fName.c_str(), RTLD_NOW);
|
||||
#endif
|
||||
if (!dynamicHinstance)
|
||||
throw DynareException(__FILE__, __LINE__, "Error when loading " + fName
|
||||
throw DynareException(__FILE__, __LINE__,
|
||||
"Error when loading " + fName
|
||||
#if !defined(__CYGWIN32__) && !defined(_WIN32)
|
||||
+ ": " + dlerror()
|
||||
+ ": " + dlerror()
|
||||
#endif
|
||||
);
|
||||
);
|
||||
|
||||
dynamic_tt.resize(order+1);
|
||||
dynamic_tt.resize(order + 1);
|
||||
|
||||
std::tie(dynamic_resid, dynamic_tt[0]) = getSymbolsFromDLL<dynamic_resid_or_g1_fct>("dynamic_resid", fName);
|
||||
std::tie(dynamic_g1, dynamic_tt[1]) = getSymbolsFromDLL<dynamic_resid_or_g1_fct>("dynamic_g1", fName);
|
||||
std::tie(dynamic_resid, dynamic_tt[0])
|
||||
= getSymbolsFromDLL<dynamic_resid_or_g1_fct>("dynamic_resid", fName);
|
||||
std::tie(dynamic_g1, dynamic_tt[1])
|
||||
= getSymbolsFromDLL<dynamic_resid_or_g1_fct>("dynamic_g1", fName);
|
||||
|
||||
dynamic_higher_deriv.resize(std::max(0, order-1));
|
||||
dynamic_higher_deriv.resize(std::max(0, order - 1));
|
||||
for (int i = 2; i <= order; i++)
|
||||
std::tie(dynamic_higher_deriv[i-2], dynamic_tt[i]) = getSymbolsFromDLL<dynamic_higher_deriv_fct>("dynamic_g" + std::to_string(i), fName);
|
||||
std::tie(dynamic_higher_deriv[i - 2], dynamic_tt[i])
|
||||
= getSymbolsFromDLL<dynamic_higher_deriv_fct>("dynamic_g" + std::to_string(i), fName);
|
||||
|
||||
tt = std::make_unique<double[]>(ntt);
|
||||
}
|
||||
|
@ -70,19 +74,24 @@ DynamicModelDLL::~DynamicModelDLL()
|
|||
}
|
||||
|
||||
void
|
||||
DynamicModelDLL::eval(const Vector &y, const Vector &x, const Vector &modParams, const Vector &ySteady,
|
||||
Vector &residual, std::vector<TwoDMatrix> &md) noexcept(false)
|
||||
DynamicModelDLL::eval(const Vector& y, const Vector& x, const Vector& modParams,
|
||||
const Vector& ySteady, Vector& residual,
|
||||
std::vector<TwoDMatrix>& md) noexcept(false)
|
||||
{
|
||||
assert(md.size() == dynamic_tt.size()-1);
|
||||
assert(md.size() == dynamic_tt.size() - 1);
|
||||
|
||||
for (size_t i = 0; i < dynamic_tt.size(); i++)
|
||||
{
|
||||
dynamic_tt[i](y.base(), x.base(), 1, modParams.base(), ySteady.base(), 0, tt.get());
|
||||
if (i == 0)
|
||||
dynamic_resid(y.base(), x.base(), 1, modParams.base(), ySteady.base(), 0, tt.get(), residual.base());
|
||||
dynamic_resid(y.base(), x.base(), 1, modParams.base(), ySteady.base(), 0, tt.get(),
|
||||
residual.base());
|
||||
else if (i == 1)
|
||||
dynamic_g1(y.base(), x.base(), 1, modParams.base(), ySteady.base(), 0, tt.get(), md[0].base());
|
||||
dynamic_g1(y.base(), x.base(), 1, modParams.base(), ySteady.base(), 0, tt.get(),
|
||||
md[0].base());
|
||||
else
|
||||
dynamic_higher_deriv[i-2](y.base(), x.base(), 1, modParams.base(), ySteady.base(), 0, tt.get(), &md[i-1].get(0, 0), &md[i-1].get(0, 1), &md[i-1].get(0, 2));
|
||||
dynamic_higher_deriv[i - 2](y.base(), x.base(), 1, modParams.base(), ySteady.base(), 0,
|
||||
tt.get(), &md[i - 1].get(0, 0), &md[i - 1].get(0, 1),
|
||||
&md[i - 1].get(0, 2));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,17 +29,23 @@
|
|||
# include <dlfcn.h> // unix/linux DLL (.so) handling routines
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "dynare_exception.hh"
|
||||
|
||||
#include "dynamic_abstract_class.hh"
|
||||
|
||||
using dynamic_tt_fct = void (*)(const double *y, const double *x, int nb_row_x, const double *params, const double *steady_state, int it_, double *T);
|
||||
using dynamic_resid_or_g1_fct = void (*)(const double *y, const double *x, int nb_row_x, const double *params, const double *steady_state, int it_, const double *T, double *resid_or_g1);
|
||||
using dynamic_higher_deriv_fct = void (*)(const double *y, const double *x, int nb_row_x, const double *params, const double *steady_state, int it_, const double *T, double *g_i, double *g_j, double *g_v);
|
||||
using dynamic_tt_fct
|
||||
= void (*)(const double* y, const double* x, int nb_row_x, const double* params,
|
||||
const double* steady_state, int it_, double* T);
|
||||
using dynamic_resid_or_g1_fct
|
||||
= void (*)(const double* y, const double* x, int nb_row_x, const double* params,
|
||||
const double* steady_state, int it_, const double* T, double* resid_or_g1);
|
||||
using dynamic_higher_deriv_fct = void (*)(const double* y, const double* x, int nb_row_x,
|
||||
const double* params, const double* steady_state, int it_,
|
||||
const double* T, double* g_i, double* g_j, double* g_v);
|
||||
|
||||
/**
|
||||
* creates pointer to Dynamic function inside <model>_dynamic.dll
|
||||
|
@ -54,13 +60,13 @@ private:
|
|||
#if defined(_WIN32) || defined(__CYGWIN32__)
|
||||
HINSTANCE dynamicHinstance; // DLL instance pointer in Windows
|
||||
#else
|
||||
void *dynamicHinstance; // and in Linux or Mac
|
||||
void* dynamicHinstance; // and in Linux or Mac
|
||||
#endif
|
||||
std::unique_ptr<double[]> tt; // Vector of temporary terms
|
||||
|
||||
template<typename T>
|
||||
std::pair<T, dynamic_tt_fct>
|
||||
getSymbolsFromDLL(const std::string &funcname, const std::string &fName)
|
||||
getSymbolsFromDLL(const std::string& funcname, const std::string& fName)
|
||||
{
|
||||
dynamic_tt_fct tt;
|
||||
T deriv;
|
||||
|
@ -68,33 +74,36 @@ private:
|
|||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wcast-function-type"
|
||||
deriv = reinterpret_cast<T>(GetProcAddress(dynamicHinstance, funcname.c_str()));
|
||||
tt = reinterpret_cast<dynamic_tt_fct>(GetProcAddress(dynamicHinstance, (funcname + "_tt").c_str()));
|
||||
tt = reinterpret_cast<dynamic_tt_fct>(
|
||||
GetProcAddress(dynamicHinstance, (funcname + "_tt").c_str()));
|
||||
# pragma GCC diagnostic pop
|
||||
#else
|
||||
deriv = reinterpret_cast<T>(dlsym(dynamicHinstance, funcname.c_str()));
|
||||
tt = reinterpret_cast<dynamic_tt_fct>(dlsym(dynamicHinstance, (funcname + "_tt").c_str()));
|
||||
deriv = reinterpret_cast<T>(dlsym(dynamicHinstance, funcname.c_str()));
|
||||
tt = reinterpret_cast<dynamic_tt_fct>(dlsym(dynamicHinstance, (funcname + "_tt").c_str()));
|
||||
#endif
|
||||
if (!deriv || !tt)
|
||||
{
|
||||
if (!deriv || !tt)
|
||||
{
|
||||
#if defined(__CYGWIN32__) || defined(_WIN32)
|
||||
FreeLibrary(dynamicHinstance);
|
||||
FreeLibrary(dynamicHinstance);
|
||||
#else
|
||||
dlclose(dynamicHinstance);
|
||||
dlclose(dynamicHinstance);
|
||||
#endif
|
||||
throw DynareException(__FILE__, __LINE__, "Error when loading symbols from " + fName
|
||||
throw DynareException(__FILE__, __LINE__,
|
||||
"Error when loading symbols from " + fName
|
||||
#if !defined(__CYGWIN32__) && !defined(_WIN32)
|
||||
+ ": " + dlerror()
|
||||
+ ": " + dlerror()
|
||||
#endif
|
||||
);
|
||||
}
|
||||
return { deriv, tt };
|
||||
);
|
||||
}
|
||||
return {deriv, tt};
|
||||
}
|
||||
|
||||
public:
|
||||
// construct and load Dynamic model DLL
|
||||
explicit DynamicModelDLL(const std::string &fname, int ntt_arg, int order);
|
||||
explicit DynamicModelDLL(const std::string& fname, int ntt_arg, int order);
|
||||
virtual ~DynamicModelDLL();
|
||||
|
||||
void eval(const Vector &y, const Vector &x, const Vector ¶ms, const Vector &ySteady,
|
||||
Vector &residual, std::vector<TwoDMatrix> &md) override;
|
||||
void eval(const Vector& y, const Vector& x, const Vector& params, const Vector& ySteady,
|
||||
Vector& residual, std::vector<TwoDMatrix>& md) override;
|
||||
};
|
||||
#endif
|
||||
|
|
|
@ -25,26 +25,25 @@
|
|||
|
||||
#include "dynamic_m.hh"
|
||||
|
||||
DynamicModelMFile::DynamicModelMFile(const std::string &modName, int ntt_arg) :
|
||||
DynamicModelAC(ntt_arg),
|
||||
DynamicMFilename{modName + ".dynamic"}
|
||||
DynamicModelMFile::DynamicModelMFile(const std::string& modName, int ntt_arg) :
|
||||
DynamicModelAC(ntt_arg), DynamicMFilename {modName + ".dynamic"}
|
||||
{
|
||||
}
|
||||
|
||||
/* NB: This is a duplicate of DynamicModelMatlabCaller::cmplxToReal() in
|
||||
perfect_foresight_problem MEX */
|
||||
mxArray *
|
||||
DynamicModelMFile::cmplxToReal(mxArray *cmplx_mx)
|
||||
mxArray*
|
||||
DynamicModelMFile::cmplxToReal(mxArray* cmplx_mx)
|
||||
{
|
||||
mxArray *real_mx = mxCreateDoubleMatrix(mxGetM(cmplx_mx), mxGetN(cmplx_mx), mxREAL);
|
||||
mxArray* real_mx = mxCreateDoubleMatrix(mxGetM(cmplx_mx), mxGetN(cmplx_mx), mxREAL);
|
||||
|
||||
#if MX_HAS_INTERLEAVED_COMPLEX
|
||||
mxComplexDouble *cmplx = mxGetComplexDoubles(cmplx_mx);
|
||||
mxComplexDouble* cmplx = mxGetComplexDoubles(cmplx_mx);
|
||||
#else
|
||||
double *cmplx_real = mxGetPr(cmplx_mx);
|
||||
double *cmplx_imag = mxGetPi(cmplx_mx);
|
||||
double* cmplx_real = mxGetPr(cmplx_mx);
|
||||
double* cmplx_imag = mxGetPi(cmplx_mx);
|
||||
#endif
|
||||
double *real = mxGetPr(real_mx);
|
||||
double* real = mxGetPr(real_mx);
|
||||
|
||||
for (size_t i = 0; i < mxGetNumberOfElements(cmplx_mx); i++)
|
||||
#if MX_HAS_INTERLEAVED_COMPLEX
|
||||
|
@ -62,11 +61,11 @@ DynamicModelMFile::cmplxToReal(mxArray *cmplx_mx)
|
|||
}
|
||||
|
||||
void
|
||||
DynamicModelMFile::unpackSparseMatrixAndCopyIntoTwoDMatData(mxArray *sparseMat, TwoDMatrix &tdm)
|
||||
DynamicModelMFile::unpackSparseMatrixAndCopyIntoTwoDMatData(mxArray* sparseMat, TwoDMatrix& tdm)
|
||||
{
|
||||
int totalCols = mxGetN(sparseMat);
|
||||
mwIndex *rowIdxVector = mxGetIr(sparseMat);
|
||||
mwIndex *colIdxVector = mxGetJc(sparseMat);
|
||||
mwIndex* rowIdxVector = mxGetIr(sparseMat);
|
||||
mwIndex* colIdxVector = mxGetJc(sparseMat);
|
||||
|
||||
assert(tdm.ncols() == 3);
|
||||
/* Under MATLAB, the following check always holds at equality; under Octave,
|
||||
|
@ -78,7 +77,7 @@ DynamicModelMFile::unpackSparseMatrixAndCopyIntoTwoDMatData(mxArray *sparseMat,
|
|||
int output_row = 0;
|
||||
|
||||
for (int i = 0; i < totalCols; i++)
|
||||
for (int j = 0; j < static_cast<int>((colIdxVector[i+1]-colIdxVector[i])); j++, rind++)
|
||||
for (int j = 0; j < static_cast<int>((colIdxVector[i + 1] - colIdxVector[i])); j++, rind++)
|
||||
{
|
||||
tdm.get(output_row, 0) = rowIdxVector[rind] + 1;
|
||||
tdm.get(output_row, 1) = i + 1;
|
||||
|
@ -114,32 +113,34 @@ DynamicModelMFile::unpackSparseMatrixAndCopyIntoTwoDMatData(mxArray *sparseMat,
|
|||
}
|
||||
|
||||
void
|
||||
DynamicModelMFile::eval(const Vector &y, const Vector &x, const Vector &modParams, const Vector &ySteady,
|
||||
Vector &residual, std::vector<TwoDMatrix> &md) noexcept(false)
|
||||
DynamicModelMFile::eval(const Vector& y, const Vector& x, const Vector& modParams,
|
||||
const Vector& ySteady, Vector& residual,
|
||||
std::vector<TwoDMatrix>& md) noexcept(false)
|
||||
{
|
||||
mxArray *T_m = mxCreateDoubleMatrix(ntt, 1, mxREAL);
|
||||
mxArray* T_m = mxCreateDoubleMatrix(ntt, 1, mxREAL);
|
||||
|
||||
mxArray *y_m = mxCreateDoubleMatrix(y.length(), 1, mxREAL);
|
||||
mxArray* y_m = mxCreateDoubleMatrix(y.length(), 1, mxREAL);
|
||||
std::copy_n(y.base(), y.length(), mxGetPr(y_m));
|
||||
|
||||
mxArray *x_m = mxCreateDoubleMatrix(1, x.length(), mxREAL);
|
||||
mxArray* x_m = mxCreateDoubleMatrix(1, x.length(), mxREAL);
|
||||
std::copy_n(x.base(), x.length(), mxGetPr(x_m));
|
||||
|
||||
mxArray *params_m = mxCreateDoubleMatrix(modParams.length(), 1, mxREAL);
|
||||
mxArray* params_m = mxCreateDoubleMatrix(modParams.length(), 1, mxREAL);
|
||||
std::copy_n(modParams.base(), modParams.length(), mxGetPr(params_m));
|
||||
|
||||
mxArray *steady_state_m = mxCreateDoubleMatrix(ySteady.length(), 1, mxREAL);
|
||||
mxArray* steady_state_m = mxCreateDoubleMatrix(ySteady.length(), 1, mxREAL);
|
||||
std::copy_n(ySteady.base(), ySteady.length(), mxGetPr(steady_state_m));
|
||||
|
||||
mxArray *it_m = mxCreateDoubleScalar(1.0);
|
||||
mxArray *T_flag_m = mxCreateLogicalScalar(false);
|
||||
mxArray* it_m = mxCreateDoubleScalar(1.0);
|
||||
mxArray* T_flag_m = mxCreateLogicalScalar(false);
|
||||
|
||||
{
|
||||
// Compute temporary terms (for all orders)
|
||||
std::string funcname = DynamicMFilename + "_g" + std::to_string(md.size()) + "_tt";
|
||||
mxArray *plhs[1], *prhs[] = { T_m, y_m, x_m, params_m, steady_state_m, it_m };
|
||||
mxArray *plhs[1], *prhs[] = {T_m, y_m, x_m, params_m, steady_state_m, it_m};
|
||||
|
||||
int retVal = mexCallMATLAB(std::extent_v<decltype(plhs)>, plhs, std::extent_v<decltype(prhs)>, prhs, funcname.c_str());
|
||||
int retVal = mexCallMATLAB(std::extent_v<decltype(plhs)>, plhs, std::extent_v<decltype(prhs)>,
|
||||
prhs, funcname.c_str());
|
||||
if (retVal != 0)
|
||||
throw DynareException(__FILE__, __LINE__, "Trouble calling " + funcname);
|
||||
|
||||
|
@ -150,19 +151,21 @@ DynamicModelMFile::eval(const Vector &y, const Vector &x, const Vector &modParam
|
|||
{
|
||||
// Compute residuals
|
||||
std::string funcname = DynamicMFilename + "_resid";
|
||||
mxArray *plhs[1], *prhs[] = { T_m, y_m, x_m, params_m, steady_state_m, it_m, T_flag_m };
|
||||
mxArray *plhs[1], *prhs[] = {T_m, y_m, x_m, params_m, steady_state_m, it_m, T_flag_m};
|
||||
|
||||
int retVal = mexCallMATLAB(std::extent_v<decltype(plhs)>, plhs, std::extent_v<decltype(prhs)>, prhs, funcname.c_str());
|
||||
int retVal = mexCallMATLAB(std::extent_v<decltype(plhs)>, plhs, std::extent_v<decltype(prhs)>,
|
||||
prhs, funcname.c_str());
|
||||
if (retVal != 0)
|
||||
throw DynareException(__FILE__, __LINE__, "Trouble calling " + funcname);
|
||||
|
||||
if (!mxIsDouble(plhs[0]) || mxIsSparse(plhs[0]))
|
||||
throw DynareException(__FILE__, __LINE__, "Residual should be a dense array of double floats");
|
||||
throw DynareException(__FILE__, __LINE__,
|
||||
"Residual should be a dense array of double floats");
|
||||
|
||||
if (mxIsComplex(plhs[0]))
|
||||
plhs[0] = cmplxToReal(plhs[0]);
|
||||
|
||||
residual = Vector{plhs[0]};
|
||||
residual = Vector {plhs[0]};
|
||||
mxDestroyArray(plhs[0]);
|
||||
}
|
||||
|
||||
|
@ -170,28 +173,35 @@ DynamicModelMFile::eval(const Vector &y, const Vector &x, const Vector &modParam
|
|||
{
|
||||
// Compute model derivatives
|
||||
std::string funcname = DynamicMFilename + "_g" + std::to_string(i);
|
||||
mxArray *plhs[1], *prhs[] = { T_m, y_m, x_m, params_m, steady_state_m, it_m, T_flag_m };
|
||||
mxArray *plhs[1], *prhs[] = {T_m, y_m, x_m, params_m, steady_state_m, it_m, T_flag_m};
|
||||
|
||||
int retVal = mexCallMATLAB(std::extent_v<decltype(plhs)>, plhs, std::extent_v<decltype(prhs)>, prhs, funcname.c_str());
|
||||
int retVal = mexCallMATLAB(std::extent_v<decltype(plhs)>, plhs, std::extent_v<decltype(prhs)>,
|
||||
prhs, funcname.c_str());
|
||||
if (retVal != 0)
|
||||
throw DynareException(__FILE__, __LINE__, "Trouble calling " + funcname);
|
||||
|
||||
if (!mxIsDouble(plhs[0]))
|
||||
throw DynareException(__FILE__, __LINE__, "Derivatives matrix at order " + std::to_string(i) + "should be an array of double floats");
|
||||
throw DynareException(__FILE__, __LINE__,
|
||||
"Derivatives matrix at order " + std::to_string(i)
|
||||
+ "should be an array of double floats");
|
||||
|
||||
if (i == 1)
|
||||
{
|
||||
if (mxIsSparse(plhs[0]))
|
||||
throw DynareException(__FILE__, __LINE__, "Derivatives matrix at order " + std::to_string(i) + " should be dense");
|
||||
assert(static_cast<int>(mxGetM(plhs[0])) == md[i-1].nrows());
|
||||
assert(static_cast<int>(mxGetN(plhs[0])) == md[i-1].ncols());
|
||||
std::copy_n(mxGetPr(plhs[0]), mxGetM(plhs[0])*mxGetN(plhs[0]), md[i-1].base());
|
||||
throw DynareException(__FILE__, __LINE__,
|
||||
"Derivatives matrix at order " + std::to_string(i)
|
||||
+ " should be dense");
|
||||
assert(static_cast<int>(mxGetM(plhs[0])) == md[i - 1].nrows());
|
||||
assert(static_cast<int>(mxGetN(plhs[0])) == md[i - 1].ncols());
|
||||
std::copy_n(mxGetPr(plhs[0]), mxGetM(plhs[0]) * mxGetN(plhs[0]), md[i - 1].base());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!mxIsSparse(plhs[0]))
|
||||
throw DynareException(__FILE__, __LINE__, "Derivatives matrix at order " + std::to_string(i) + " should be sparse");
|
||||
unpackSparseMatrixAndCopyIntoTwoDMatData(plhs[0], md[i-1]);
|
||||
throw DynareException(__FILE__, __LINE__,
|
||||
"Derivatives matrix at order " + std::to_string(i)
|
||||
+ " should be sparse");
|
||||
unpackSparseMatrixAndCopyIntoTwoDMatData(plhs[0], md[i - 1]);
|
||||
}
|
||||
|
||||
mxDestroyArray(plhs[0]);
|
||||
|
|
|
@ -36,16 +36,17 @@ private:
|
|||
/* Unpack a sparse matrix (of double floats) into a TwoDMatrix object.
|
||||
Real elements of the original matrix are copied as-is to the new one.
|
||||
Complex elements are replaced by NaNs. */
|
||||
static void unpackSparseMatrixAndCopyIntoTwoDMatData(mxArray *sparseMat, TwoDMatrix &tdm);
|
||||
static void unpackSparseMatrixAndCopyIntoTwoDMatData(mxArray* sparseMat, TwoDMatrix& tdm);
|
||||
/* Given a complex dense matrix (of double floats), returns a real dense matrix of same size.
|
||||
Real elements of the original matrix are copied as-is to the new one.
|
||||
Complex elements are replaced by NaNs.
|
||||
Destroys the original matrix. */
|
||||
static mxArray *cmplxToReal(mxArray *m);
|
||||
static mxArray* cmplxToReal(mxArray* m);
|
||||
|
||||
public:
|
||||
explicit DynamicModelMFile(const std::string &modName, int ntt_arg);
|
||||
explicit DynamicModelMFile(const std::string& modName, int ntt_arg);
|
||||
virtual ~DynamicModelMFile() = default;
|
||||
void eval(const Vector &y, const Vector &x, const Vector ¶ms, const Vector &ySteady,
|
||||
Vector &residual, std::vector<TwoDMatrix> &md) override;
|
||||
void eval(const Vector& y, const Vector& x, const Vector& params, const Vector& ySteady,
|
||||
Vector& residual, std::vector<TwoDMatrix>& md) override;
|
||||
};
|
||||
#endif
|
||||
|
|
|
@ -23,23 +23,21 @@
|
|||
#include "dynamic_abstract_class.hh"
|
||||
#include "dynare_exception.hh"
|
||||
|
||||
#include <utility>
|
||||
#include <cassert>
|
||||
#include <utility>
|
||||
|
||||
KordpDynare::KordpDynare(const std::vector<std::string> &endo,
|
||||
const std::vector<std::string> &exo, int nexog, int npar,
|
||||
Vector &ysteady, TwoDMatrix &vcov, Vector &inParams, int nstat,
|
||||
int npred, int nforw, int nboth, const ConstVector &nnzd,
|
||||
int nsteps, int norder,
|
||||
Journal &jr, std::unique_ptr<DynamicModelAC> dynamicModelFile_arg,
|
||||
const std::vector<int> &dr_order, const ConstTwoDMatrix &llincidence) :
|
||||
nStat{nstat}, nBoth{nboth}, nPred{npred}, nForw{nforw}, nExog{nexog}, nPar{npar},
|
||||
nYs{npred + nboth}, nYss{nboth + nforw}, nY{nstat + npred + nboth + nforw},
|
||||
nJcols{nExog+nY+nYs+nYss}, NNZD{nnzd}, nSteps{nsteps},
|
||||
nOrder{norder}, journal{jr}, ySteady{ysteady}, params{inParams}, vCov{vcov},
|
||||
md{1}, dnl{endo}, denl{exo}, dsnl{*this, dnl, denl},
|
||||
ll_Incidence{llincidence},
|
||||
dynamicModelFile{std::move(dynamicModelFile_arg)}
|
||||
KordpDynare::KordpDynare(const std::vector<std::string>& endo, const std::vector<std::string>& exo,
|
||||
int nexog, int npar, Vector& ysteady, TwoDMatrix& vcov, Vector& inParams,
|
||||
int nstat, int npred, int nforw, int nboth, const ConstVector& nnzd,
|
||||
int nsteps, int norder, Journal& jr,
|
||||
std::unique_ptr<DynamicModelAC> dynamicModelFile_arg,
|
||||
const std::vector<int>& dr_order, const ConstTwoDMatrix& llincidence) :
|
||||
nStat {nstat},
|
||||
nBoth {nboth}, nPred {npred}, nForw {nforw}, nExog {nexog}, nPar {npar}, nYs {npred + nboth},
|
||||
nYss {nboth + nforw}, nY {nstat + npred + nboth + nforw}, nJcols {nExog + nY + nYs + nYss},
|
||||
NNZD {nnzd}, nSteps {nsteps}, nOrder {norder}, journal {jr}, ySteady {ysteady},
|
||||
params {inParams}, vCov {vcov}, md {1}, dnl {endo}, denl {exo}, dsnl {*this, dnl, denl},
|
||||
ll_Incidence {llincidence}, dynamicModelFile {std::move(dynamicModelFile_arg)}
|
||||
{
|
||||
computeJacobianPermutation(dr_order);
|
||||
}
|
||||
|
@ -52,20 +50,22 @@ KordpDynare::solveDeterministicSteady()
|
|||
}
|
||||
|
||||
void
|
||||
KordpDynare::evaluateSystem(Vector &out, [[maybe_unused]] const ConstVector &yy,
|
||||
[[maybe_unused]] const Vector &xx)
|
||||
KordpDynare::evaluateSystem(Vector& out, [[maybe_unused]] const ConstVector& yy,
|
||||
[[maybe_unused]] const Vector& xx)
|
||||
{
|
||||
// This method is only called when checking the residuals at steady state (Approximation::check), so return zero residuals
|
||||
// This method is only called when checking the residuals at steady state (Approximation::check),
|
||||
// so return zero residuals
|
||||
out.zeros();
|
||||
}
|
||||
|
||||
void
|
||||
KordpDynare::evaluateSystem(Vector &out, [[maybe_unused]] const ConstVector &yym,
|
||||
[[maybe_unused]] const ConstVector &yy,
|
||||
[[maybe_unused]] const ConstVector &yyp,
|
||||
[[maybe_unused]] const Vector &xx)
|
||||
KordpDynare::evaluateSystem(Vector& out, [[maybe_unused]] const ConstVector& yym,
|
||||
[[maybe_unused]] const ConstVector& yy,
|
||||
[[maybe_unused]] const ConstVector& yyp,
|
||||
[[maybe_unused]] const Vector& xx)
|
||||
{
|
||||
// This method is only called when checking the residuals at steady state (Approximation::check), so return zero residuals
|
||||
// This method is only called when checking the residuals at steady state (Approximation::check),
|
||||
// so return zero residuals
|
||||
out.zeros();
|
||||
}
|
||||
|
||||
|
@ -82,7 +82,7 @@ KordpDynare::calcDerivativesAtSteady()
|
|||
for (int i = 2; i <= nOrder; i++)
|
||||
{
|
||||
// Higher order derivatives, as sparse (3-column) matrices
|
||||
dyn_md.emplace_back(static_cast<int>(NNZD[i-1]), 3);
|
||||
dyn_md.emplace_back(static_cast<int>(NNZD[i - 1]), 3);
|
||||
dyn_md.back().zeros();
|
||||
}
|
||||
|
||||
|
@ -91,7 +91,7 @@ KordpDynare::calcDerivativesAtSteady()
|
|||
|
||||
Vector out(nY);
|
||||
out.zeros();
|
||||
Vector llxSteady(nJcols-nExog);
|
||||
Vector llxSteady(nJcols - nExog);
|
||||
LLxSteady(ySteady, llxSteady);
|
||||
|
||||
dynamicModelFile->eval(llxSteady, xx, params, ySteady, out, dyn_md);
|
||||
|
@ -101,9 +101,9 @@ KordpDynare::calcDerivativesAtSteady()
|
|||
}
|
||||
|
||||
void
|
||||
KordpDynare::populateDerivativesContainer(const std::vector<TwoDMatrix> &dyn_md, int ord)
|
||||
KordpDynare::populateDerivativesContainer(const std::vector<TwoDMatrix>& dyn_md, int ord)
|
||||
{
|
||||
const TwoDMatrix &g = dyn_md[ord-1];
|
||||
const TwoDMatrix& g = dyn_md[ord - 1];
|
||||
|
||||
// model derivatives FSSparseTensor instance
|
||||
auto mdTi = std::make_unique<FSSparseTensor>(ord, nJcols, nY);
|
||||
|
@ -124,8 +124,8 @@ KordpDynare::populateDerivativesContainer(const std::vector<TwoDMatrix> &dyn_md,
|
|||
else // ord ≥ 2
|
||||
for (int i = 0; i < g.nrows(); i++)
|
||||
{
|
||||
int j = static_cast<int>(g.get(i, 0))-1;
|
||||
int i1 = static_cast<int>(g.get(i, 1))-1;
|
||||
int j = static_cast<int>(g.get(i, 0)) - 1;
|
||||
int i1 = static_cast<int>(g.get(i, 1)) - 1;
|
||||
if (j < 0 || i1 < 0)
|
||||
continue; // Discard empty entries (see comment in DynamicModelAC::unpackSparseMatrix())
|
||||
|
||||
|
@ -150,21 +150,21 @@ KordpDynare::populateDerivativesContainer(const std::vector<TwoDMatrix> &dyn_md,
|
|||
/* Returns ySteady extended with leads and lags suitable for passing to
|
||||
<model>_dynamic */
|
||||
void
|
||||
KordpDynare::LLxSteady(const Vector &yS, Vector &llxSteady)
|
||||
KordpDynare::LLxSteady(const Vector& yS, Vector& llxSteady)
|
||||
{
|
||||
if (yS.length() == nJcols-nExog)
|
||||
if (yS.length() == nJcols - nExog)
|
||||
throw DynareException(__FILE__, __LINE__, "ySteady already of right size");
|
||||
|
||||
/* Create temporary square 2D matrix size nEndo×nEndo (sparse)
|
||||
for the lag, current and lead blocks of the jacobian */
|
||||
if (llxSteady.length() != nJcols-nExog)
|
||||
if (llxSteady.length() != nJcols - nExog)
|
||||
throw DynareException(__FILE__, __LINE__, "llxSteady has wrong size");
|
||||
|
||||
for (int ll_row = 0; ll_row < ll_Incidence.nrows(); ll_row++)
|
||||
// populate (non-sparse) vector with ysteady values
|
||||
for (int i = 0; i < nY; i++)
|
||||
if (ll_Incidence.get(ll_row, i))
|
||||
llxSteady[static_cast<int>(ll_Incidence.get(ll_row, i))-1] = yS[i];
|
||||
llxSteady[static_cast<int>(ll_Incidence.get(ll_row, i)) - 1] = yS[i];
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -186,33 +186,34 @@ KordpDynare::LLxSteady(const Vector &yS, Vector &llxSteady)
|
|||
dr_order is typically equal to oo_.dr.order_var.
|
||||
*/
|
||||
void
|
||||
KordpDynare::computeJacobianPermutation(const std::vector<int> &dr_order)
|
||||
KordpDynare::computeJacobianPermutation(const std::vector<int>& dr_order)
|
||||
{
|
||||
// Compute restricted inverse DR-orderings: x⁻→y⁻ and x⁺→y⁺
|
||||
std::vector<int> dr_inv_order_forw(nBoth+nForw), dr_inv_order_pred(nBoth+nPred);
|
||||
std::vector<int> dr_inv_order_forw(nBoth + nForw), dr_inv_order_pred(nBoth + nPred);
|
||||
std::iota(dr_inv_order_forw.begin(), dr_inv_order_forw.end(), 0);
|
||||
std::sort(dr_inv_order_forw.begin(), dr_inv_order_forw.end(),
|
||||
[&](int i, int j) { return dr_order[nStat+nPred+i] < dr_order[nStat+nPred+j]; });
|
||||
std::sort(dr_inv_order_forw.begin(), dr_inv_order_forw.end(), [&](int i, int j) {
|
||||
return dr_order[nStat + nPred + i] < dr_order[nStat + nPred + j];
|
||||
});
|
||||
std::iota(dr_inv_order_pred.begin(), dr_inv_order_pred.end(), 0);
|
||||
std::sort(dr_inv_order_pred.begin(), dr_inv_order_pred.end(),
|
||||
[&](int i, int j) { return dr_order[nStat+i] < dr_order[nStat+j]; });
|
||||
[&](int i, int j) { return dr_order[nStat + i] < dr_order[nStat + j]; });
|
||||
|
||||
// Compute restricted DR-orderings: y⁻→x⁻ and y⁺→x⁺
|
||||
std::vector<int> dr_order_forw(nBoth+nForw), dr_order_pred(nBoth+nPred);
|
||||
for (int i = 0; i < nBoth+nForw; i++)
|
||||
std::vector<int> dr_order_forw(nBoth + nForw), dr_order_pred(nBoth + nPred);
|
||||
for (int i = 0; i < nBoth + nForw; i++)
|
||||
dr_order_forw[dr_inv_order_forw[i]] = i;
|
||||
for (int i = 0; i < nBoth+nPred; i++)
|
||||
for (int i = 0; i < nBoth + nPred; i++)
|
||||
dr_order_pred[dr_inv_order_pred[i]] = i;
|
||||
|
||||
// Compute Dynare++ → Dynare ordering
|
||||
dynppToDyn.resize(nJcols);
|
||||
int j = 0;
|
||||
for (; j < nYss; j++)
|
||||
dynppToDyn[j] = dr_order_forw[j]+nYs+nY; // Forward variables
|
||||
for (; j < nYss+nY; j++)
|
||||
dynppToDyn[j] = dr_order[j-nYss]+nYs; // Variables in current period
|
||||
for (; j < nYss+nY+nYs; j++)
|
||||
dynppToDyn[j] = dr_order_pred[j-nY-nYss]; // Predetermined variables
|
||||
dynppToDyn[j] = dr_order_forw[j] + nYs + nY; // Forward variables
|
||||
for (; j < nYss + nY; j++)
|
||||
dynppToDyn[j] = dr_order[j - nYss] + nYs; // Variables in current period
|
||||
for (; j < nYss + nY + nYs; j++)
|
||||
dynppToDyn[j] = dr_order_pred[j - nY - nYss]; // Predetermined variables
|
||||
for (; j < nJcols; j++)
|
||||
dynppToDyn[j] = j; // Exogenous
|
||||
|
||||
|
@ -222,16 +223,15 @@ KordpDynare::computeJacobianPermutation(const std::vector<int> &dr_order)
|
|||
dynToDynpp[dynppToDyn[i]] = i;
|
||||
}
|
||||
|
||||
DynareNameList::DynareNameList(std::vector<std::string> names_arg)
|
||||
: names(std::move(names_arg))
|
||||
DynareNameList::DynareNameList(std::vector<std::string> names_arg) : names(std::move(names_arg))
|
||||
{
|
||||
}
|
||||
|
||||
DynareStateNameList::DynareStateNameList(const KordpDynare &dynare, const DynareNameList &dnl,
|
||||
const DynareNameList &denl)
|
||||
DynareStateNameList::DynareStateNameList(const KordpDynare& dynare, const DynareNameList& dnl,
|
||||
const DynareNameList& denl)
|
||||
{
|
||||
for (int i = 0; i < dynare.nYs; i++)
|
||||
names.emplace_back(dnl.getName(i+dynare.nstat()));
|
||||
names.emplace_back(dnl.getName(i + dynare.nstat()));
|
||||
for (int i = 0; i < dynare.nexog(); i++)
|
||||
names.emplace_back(denl.getName(i));
|
||||
}
|
||||
|
|
|
@ -20,18 +20,18 @@
|
|||
#ifndef K_ORD_DYNARE3_H
|
||||
#define K_ORD_DYNARE3_H
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "journal.hh"
|
||||
#include "Vector.hh"
|
||||
#include "twod_matrix.hh"
|
||||
#include "t_container.hh"
|
||||
#include "sparse_tensor.hh"
|
||||
#include "decision_rule.hh"
|
||||
#include "dynamic_model.hh"
|
||||
#include "dynamic_abstract_class.hh"
|
||||
#include "dynamic_model.hh"
|
||||
#include "journal.hh"
|
||||
#include "sparse_tensor.hh"
|
||||
#include "t_container.hh"
|
||||
#include "twod_matrix.hh"
|
||||
|
||||
class KordpDynare;
|
||||
|
||||
|
@ -39,6 +39,7 @@ class KordpDynare;
|
|||
class DynareNameList : public NameList
|
||||
{
|
||||
std::vector<std::string> names;
|
||||
|
||||
public:
|
||||
DynareNameList(std::vector<std::string> names_arg);
|
||||
int
|
||||
|
@ -46,7 +47,7 @@ public:
|
|||
{
|
||||
return static_cast<int>(names.size());
|
||||
}
|
||||
const std::string &
|
||||
const std::string&
|
||||
getName(int i) const override
|
||||
{
|
||||
return names[i];
|
||||
|
@ -56,15 +57,16 @@ public:
|
|||
class DynareStateNameList : public NameList
|
||||
{
|
||||
std::vector<std::string> names;
|
||||
|
||||
public:
|
||||
DynareStateNameList(const KordpDynare &dynare, const DynareNameList &dnl,
|
||||
const DynareNameList &denl);
|
||||
DynareStateNameList(const KordpDynare& dynare, const DynareNameList& dnl,
|
||||
const DynareNameList& denl);
|
||||
int
|
||||
getNum() const override
|
||||
{
|
||||
return static_cast<int>(names.size());
|
||||
}
|
||||
const std::string &
|
||||
const std::string&
|
||||
getName(int i) const override
|
||||
{
|
||||
return names[i];
|
||||
|
@ -82,35 +84,35 @@ public:
|
|||
const int nForw;
|
||||
const int nExog;
|
||||
const int nPar;
|
||||
const int nYs; // = npred + nboth
|
||||
const int nYss; // = nboth + nforw
|
||||
const int nY; // = nstat + npred + nboth + nforw
|
||||
const int nJcols; // nb of jacobian columns = nExog+nY+nYs+nYss
|
||||
const ConstVector &NNZD; /* the total number of non-zero derivative elements
|
||||
const int nYs; // = npred + nboth
|
||||
const int nYss; // = nboth + nforw
|
||||
const int nY; // = nstat + npred + nboth + nforw
|
||||
const int nJcols; // nb of jacobian columns = nExog+nY+nYs+nYss
|
||||
const ConstVector& NNZD; /* the total number of non-zero derivative elements
|
||||
where hessian is 2nd : NNZD(order=2) */
|
||||
const int nSteps;
|
||||
const int nOrder;
|
||||
|
||||
private:
|
||||
Journal &journal;
|
||||
Vector &ySteady;
|
||||
Vector ¶ms;
|
||||
TwoDMatrix &vCov;
|
||||
Journal& journal;
|
||||
Vector& ySteady;
|
||||
Vector& params;
|
||||
TwoDMatrix& vCov;
|
||||
TensorContainer<FSSparseTensor> md; // Model derivatives, in Dynare++ form
|
||||
DynareNameList dnl, denl;
|
||||
DynareStateNameList dsnl;
|
||||
const ConstTwoDMatrix &ll_Incidence;
|
||||
const ConstTwoDMatrix& ll_Incidence;
|
||||
std::vector<int> dynppToDyn; // Maps Dynare++ jacobian variable indices to Dynare ones
|
||||
std::vector<int> dynToDynpp; // Maps Dynare jacobian variable indices to Dynare++ ones
|
||||
|
||||
std::unique_ptr<DynamicModelAC> dynamicModelFile;
|
||||
|
||||
public:
|
||||
KordpDynare(const std::vector<std::string> &endo,
|
||||
const std::vector<std::string> &exo, int num_exo, int num_par,
|
||||
Vector &ySteady, TwoDMatrix &vCov, Vector ¶ms, int nstat, int nPred,
|
||||
int nforw, int nboth, const ConstVector &NNZD,
|
||||
int nSteps, int ord,
|
||||
Journal &jr, std::unique_ptr<DynamicModelAC> dynamicModelFile_arg,
|
||||
const std::vector<int> &varOrder, const ConstTwoDMatrix &ll_Incidence);
|
||||
KordpDynare(const std::vector<std::string>& endo, const std::vector<std::string>& exo,
|
||||
int num_exo, int num_par, Vector& ySteady, TwoDMatrix& vCov, Vector& params,
|
||||
int nstat, int nPred, int nforw, int nboth, const ConstVector& NNZD, int nSteps,
|
||||
int ord, Journal& jr, std::unique_ptr<DynamicModelAC> dynamicModelFile_arg,
|
||||
const std::vector<int>& varOrder, const ConstTwoDMatrix& ll_Incidence);
|
||||
|
||||
int
|
||||
nstat() const override
|
||||
|
@ -140,69 +142,69 @@ public:
|
|||
int
|
||||
ny() const
|
||||
{
|
||||
return nStat+nBoth+nPred+nForw;
|
||||
return nStat + nBoth + nPred + nForw;
|
||||
}
|
||||
int
|
||||
nys() const
|
||||
{
|
||||
return nBoth+nPred;
|
||||
return nBoth + nPred;
|
||||
}
|
||||
int
|
||||
order() const override
|
||||
{
|
||||
return nOrder;
|
||||
}
|
||||
const std::vector<int> &
|
||||
const std::vector<int>&
|
||||
getDynppToDyn() const
|
||||
{
|
||||
return dynppToDyn;
|
||||
}
|
||||
const std::vector<int> &
|
||||
const std::vector<int>&
|
||||
getDynToDynpp() const
|
||||
{
|
||||
return dynToDynpp;
|
||||
}
|
||||
const NameList &
|
||||
const NameList&
|
||||
getAllEndoNames() const override
|
||||
{
|
||||
return dnl;
|
||||
}
|
||||
const NameList &
|
||||
const NameList&
|
||||
getStateNames() const override
|
||||
{
|
||||
return dsnl;
|
||||
}
|
||||
const NameList &
|
||||
const NameList&
|
||||
getExogNames() const override
|
||||
{
|
||||
return denl;
|
||||
}
|
||||
const TwoDMatrix &
|
||||
const TwoDMatrix&
|
||||
getVcov() const override
|
||||
{
|
||||
return vCov;
|
||||
}
|
||||
|
||||
const TensorContainer<FSSparseTensor> &
|
||||
const TensorContainer<FSSparseTensor>&
|
||||
getModelDerivatives() const override
|
||||
{
|
||||
return md;
|
||||
}
|
||||
const Vector &
|
||||
const Vector&
|
||||
getSteady() const override
|
||||
{
|
||||
return ySteady;
|
||||
}
|
||||
Vector &
|
||||
Vector&
|
||||
getSteady() override
|
||||
{
|
||||
return ySteady;
|
||||
}
|
||||
|
||||
void solveDeterministicSteady() override;
|
||||
void evaluateSystem(Vector &out, const ConstVector &yy, const Vector &xx) override;
|
||||
void evaluateSystem(Vector &out, const ConstVector &yym, const ConstVector &yy,
|
||||
const ConstVector &yyp, const Vector &xx) override;
|
||||
void evaluateSystem(Vector& out, const ConstVector& yy, const Vector& xx) override;
|
||||
void evaluateSystem(Vector& out, const ConstVector& yym, const ConstVector& yy,
|
||||
const ConstVector& yyp, const Vector& xx) override;
|
||||
void calcDerivativesAtSteady() override;
|
||||
std::unique_ptr<DynamicModel>
|
||||
clone() const override
|
||||
|
@ -210,14 +212,16 @@ public:
|
|||
std::cerr << "KordpDynare::clone() not implemented" << std::endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
private:
|
||||
// Given the steady state in yS, returns in llxSteady the steady state extended with leads and lags
|
||||
void LLxSteady(const Vector &yS, Vector &llxSteady);
|
||||
// Given the steady state in yS, returns in llxSteady the steady state extended with leads and
|
||||
// lags
|
||||
void LLxSteady(const Vector& yS, Vector& llxSteady);
|
||||
/* Computes the permutations mapping back and forth between Dynare and
|
||||
Dynare++ orderings of variables */
|
||||
void computeJacobianPermutation(const std::vector<int> &var_order);
|
||||
void computeJacobianPermutation(const std::vector<int>& var_order);
|
||||
// Fills model derivatives in Dynare++ form (at a given order) given the Dynare form
|
||||
void populateDerivativesContainer(const std::vector<TwoDMatrix> &dyn_md, int ord);
|
||||
void populateDerivativesContainer(const std::vector<TwoDMatrix>& dyn_md, int ord);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -20,15 +20,15 @@
|
|||
|
||||
#include <utility>
|
||||
|
||||
#include "kord_exception.hh"
|
||||
#include "approximation.hh"
|
||||
#include "first_order.hh"
|
||||
#include "kord_exception.hh"
|
||||
#include "korder_stoch.hh"
|
||||
|
||||
ZAuxContainer::ZAuxContainer(const _Ctype *gss, int ngss, int ng, int ny, int nu)
|
||||
: StackContainer<FGSTensor>(4, 1)
|
||||
ZAuxContainer::ZAuxContainer(const _Ctype* gss, int ngss, int ng, int ny, int nu) :
|
||||
StackContainer<FGSTensor>(4, 1)
|
||||
{
|
||||
stack_sizes = { ngss, ng, ny, nu };
|
||||
stack_sizes = {ngss, ng, ny, nu};
|
||||
conts[0] = gss;
|
||||
calculateOffsets();
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ ZAuxContainer::ZAuxContainer(const _Ctype *gss, int ngss, int ng, int ny, int nu
|
|||
argument we return ‘matrix’, for other three we return ‘zero’. */
|
||||
|
||||
ZAuxContainer::itype
|
||||
ZAuxContainer::getType(int i, const Symmetry &s) const
|
||||
ZAuxContainer::getType(int i, const Symmetry& s) const
|
||||
{
|
||||
if (i == 0)
|
||||
{
|
||||
|
@ -49,20 +49,20 @@ ZAuxContainer::getType(int i, const Symmetry &s) const
|
|||
return itype::zero;
|
||||
}
|
||||
|
||||
Approximation::Approximation(DynamicModel &m, Journal &j, int ns, bool dr_centr, bool pruned_dr, double qz_crit)
|
||||
: model(m), journal(j),
|
||||
ypart(model.nstat(), model.npred(), model.nboth(), model.nforw()),
|
||||
mom(UNormalMoments(model.order(), model.getVcov())),
|
||||
nvs{ypart.nys(), model.nexog(), model.nexog(), 1},
|
||||
steps(ns),
|
||||
dr_centralize(dr_centr), pruning(pruned_dr),
|
||||
qz_criterium(qz_crit), ss(ypart.ny(), steps+1)
|
||||
Approximation::Approximation(DynamicModel& m, Journal& j, int ns, bool dr_centr, bool pruned_dr,
|
||||
double qz_crit) :
|
||||
model(m),
|
||||
journal(j), ypart(model.nstat(), model.npred(), model.nboth(), model.nforw()),
|
||||
mom(UNormalMoments(model.order(), model.getVcov())), nvs {ypart.nys(), model.nexog(),
|
||||
model.nexog(), 1},
|
||||
steps(ns), dr_centralize(dr_centr), pruning(pruned_dr), qz_criterium(qz_crit),
|
||||
ss(ypart.ny(), steps + 1)
|
||||
{
|
||||
ss.nans();
|
||||
}
|
||||
|
||||
/* This just returns ‘fdr’ with a check that it is created. */
|
||||
const FoldDecisionRule &
|
||||
const FoldDecisionRule&
|
||||
Approximation::getFoldDecisionRule() const
|
||||
{
|
||||
KORD_RAISE_IF(!fdr,
|
||||
|
@ -71,21 +71,21 @@ Approximation::getFoldDecisionRule() const
|
|||
}
|
||||
|
||||
/* This just returns ‘fdr_pruning’ with a check that it is created. */
|
||||
const UnfoldDecisionRule &
|
||||
const UnfoldDecisionRule&
|
||||
Approximation::getUnfoldDecisionRulePruning() const
|
||||
{
|
||||
KORD_RAISE_IF(!udr_pruning,
|
||||
"Unfolded decision rule has not been created in Approximation::getUnfoldDecisionRule");
|
||||
KORD_RAISE_IF(
|
||||
!udr_pruning,
|
||||
"Unfolded decision rule has not been created in Approximation::getUnfoldDecisionRule");
|
||||
return *udr_pruning;
|
||||
}
|
||||
|
||||
|
||||
/* This just returns ‘udr’ with a check that it is created. */
|
||||
const UnfoldDecisionRule &
|
||||
const UnfoldDecisionRule&
|
||||
Approximation::getUnfoldDecisionRule() const
|
||||
{
|
||||
KORD_RAISE_IF(!udr,
|
||||
"Unfolded decision rule has not been created in Approximation::getUnfoldDecisionRule");
|
||||
KORD_RAISE_IF(
|
||||
!udr, "Unfolded decision rule has not been created in Approximation::getUnfoldDecisionRule");
|
||||
return *udr;
|
||||
}
|
||||
|
||||
|
@ -97,15 +97,13 @@ void
|
|||
Approximation::approxAtSteady()
|
||||
{
|
||||
model.calcDerivativesAtSteady();
|
||||
FirstOrder fo(model.nstat(), model.npred(), model.nboth(), model.nforw(),
|
||||
model.nexog(), model.getModelDerivatives().get(Symmetry{1}),
|
||||
journal, qz_criterium);
|
||||
FirstOrder fo(model.nstat(), model.npred(), model.nboth(), model.nforw(), model.nexog(),
|
||||
model.getModelDerivatives().get(Symmetry {1}), journal, qz_criterium);
|
||||
|
||||
if (model.order() >= 2)
|
||||
{
|
||||
KOrder korder(model.nstat(), model.npred(), model.nboth(), model.nforw(),
|
||||
model.getModelDerivatives(), fo.getGy(), fo.getGu(),
|
||||
model.getVcov(), journal);
|
||||
model.getModelDerivatives(), fo.getGy(), fo.getGu(), model.getVcov(), journal);
|
||||
korder.switchToFolded();
|
||||
for (int k = 2; k <= model.order(); k++)
|
||||
korder.performStep<Storage::fold>(k);
|
||||
|
@ -157,17 +155,17 @@ Approximation::walkStochSteady()
|
|||
to ‘ss’. */
|
||||
model.solveDeterministicSteady();
|
||||
approxAtSteady();
|
||||
Vector steady0{ss.getCol(0)};
|
||||
Vector steady0 {ss.getCol(0)};
|
||||
steady0 = model.getSteady();
|
||||
|
||||
double sigma_so_far = 0.0;
|
||||
double dsigma = (steps == 0) ? 0.0 : 1.0/steps;
|
||||
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;
|
||||
pa << "Approximation about stochastic steady for sigma=" << sigma_so_far + dsigma << endrec;
|
||||
|
||||
Vector last_steady(const_cast<const Vector &>(model.getSteady()));
|
||||
Vector last_steady(const_cast<const Vector&>(model.getSteady()));
|
||||
|
||||
// calculate fix-point of the last rule for ‘dsigma’
|
||||
/* We form the DRFixPoint object from the last rule with σ=dsigma. Then
|
||||
|
@ -176,8 +174,9 @@ Approximation::walkStochSteady()
|
|||
DRFixPoint<Storage::fold> fp(*rule_ders, ypart, model.getSteady(), dsigma);
|
||||
bool converged = fp.calcFixPoint(model.getSteady());
|
||||
JournalRecord rec(journal);
|
||||
rec << "Fix point calcs: iter=" << fp.getNumIter() << ", newton_iter="
|
||||
<< fp.getNewtonTotalIter() << ", last_newton_iter=" << fp.getNewtonLastIter() << ".";
|
||||
rec << "Fix point calcs: iter=" << fp.getNumIter()
|
||||
<< ", newton_iter=" << fp.getNewtonTotalIter()
|
||||
<< ", last_newton_iter=" << fp.getNewtonLastIter() << ".";
|
||||
if (converged)
|
||||
rec << " Converged." << endrec;
|
||||
else
|
||||
|
@ -185,7 +184,7 @@ Approximation::walkStochSteady()
|
|||
rec << " Not converged!!" << endrec;
|
||||
KORD_RAISE_X("Fix point calculation not converged", KORD_FP_NOT_CONV);
|
||||
}
|
||||
Vector steadyi{ss.getCol(i)};
|
||||
Vector steadyi {ss.getCol(i)};
|
||||
steadyi = model.getSteady();
|
||||
|
||||
// calculate ‘hh’ as expectations of the last g**
|
||||
|
@ -193,11 +192,11 @@ Approximation::walkStochSteady()
|
|||
minus the old steady state. Then we create StochForwardDerivs object,
|
||||
which calculates the derivatives of g** expectations at new sigma and
|
||||
new steady. */
|
||||
Vector dy(const_cast<const Vector &>(model.getSteady()));
|
||||
Vector dy(const_cast<const Vector&>(model.getSteady()));
|
||||
dy.add(-1.0, last_steady);
|
||||
|
||||
StochForwardDerivs<Storage::fold> hh(ypart, model.nexog(), *rule_ders_ss, mom, dy,
|
||||
dsigma, sigma_so_far);
|
||||
StochForwardDerivs<Storage::fold> hh(ypart, model.nexog(), *rule_ders_ss, mom, dy, dsigma,
|
||||
sigma_so_far);
|
||||
JournalRecord rec1(journal);
|
||||
rec1 << "Calculation of g** expectations done" << endrec;
|
||||
|
||||
|
@ -205,38 +204,35 @@ Approximation::walkStochSteady()
|
|||
/* We calculate derivatives of the model at the new steady, form
|
||||
KOrderStoch object and solve, and save the rule. */
|
||||
model.calcDerivativesAtSteady();
|
||||
KOrderStoch korder_stoch(ypart, model.nexog(), model.getModelDerivatives(),
|
||||
hh, journal);
|
||||
KOrderStoch korder_stoch(ypart, model.nexog(), model.getModelDerivatives(), hh, journal);
|
||||
for (int d = 1; d <= model.order(); d++)
|
||||
korder_stoch.performStep<Storage::fold>(d);
|
||||
|
||||
saveRuleDerivs(korder_stoch.getFoldDers());
|
||||
|
||||
check(sigma_so_far+dsigma);
|
||||
check(sigma_so_far + dsigma);
|
||||
sigma_so_far += dsigma;
|
||||
}
|
||||
|
||||
// construct the resulting decision rules
|
||||
udr.reset();
|
||||
fdr = std::make_unique<FoldDecisionRule>(*rule_ders, ypart, model.nexog(),
|
||||
model.getSteady(), 1.0-sigma_so_far);
|
||||
fdr = std::make_unique<FoldDecisionRule>(*rule_ders, ypart, model.nexog(), model.getSteady(),
|
||||
1.0 - sigma_so_far);
|
||||
if (pruning)
|
||||
{
|
||||
fdr_pruning = std::make_unique<FoldDecisionRule>(*rule_ders, ypart,
|
||||
model.nexog(),
|
||||
model.getSteady(),
|
||||
1.0-sigma_so_far,
|
||||
pruning);
|
||||
fdr_pruning = std::make_unique<FoldDecisionRule>(
|
||||
*rule_ders, ypart, model.nexog(), model.getSteady(), 1.0 - sigma_so_far, pruning);
|
||||
udr_pruning = std::make_unique<UnfoldDecisionRule>(*fdr_pruning);
|
||||
}
|
||||
}
|
||||
if (steps == 0 && dr_centralize)
|
||||
{
|
||||
// centralize decision rule for zero steps
|
||||
DRFixPoint<Storage::fold> fp(*rule_ders, ypart, model.getSteady(), 1.0);
|
||||
bool converged = fp.calcFixPoint(model.getSteady());
|
||||
JournalRecord rec(journal);
|
||||
rec << "Fix point calcs: iter=" << fp.getNumIter() << ", newton_iter="
|
||||
<< fp.getNewtonTotalIter() << ", last_newton_iter=" << fp.getNewtonLastIter() << ".";
|
||||
rec << "Fix point calcs: iter=" << fp.getNumIter()
|
||||
<< ", newton_iter=" << fp.getNewtonTotalIter()
|
||||
<< ", last_newton_iter=" << fp.getNewtonLastIter() << ".";
|
||||
if (converged)
|
||||
rec << " Converged." << endrec;
|
||||
else
|
||||
|
@ -259,16 +255,17 @@ Approximation::walkStochSteady()
|
|||
from a temporary object and will be destroyed. */
|
||||
|
||||
void
|
||||
Approximation::saveRuleDerivs(const FGSContainer &g)
|
||||
Approximation::saveRuleDerivs(const FGSContainer& g)
|
||||
{
|
||||
rule_ders = std::make_unique<FGSContainer>(g);
|
||||
rule_ders_s = std::make_unique<FGSContainer>(4);
|
||||
rule_ders_ss = std::make_unique<FGSContainer>(4);
|
||||
for (auto &run : *rule_ders)
|
||||
for (auto& run : *rule_ders)
|
||||
{
|
||||
auto ten_s = std::make_unique<FGSTensor>(ypart.nstat, ypart.nys(), *(run.second));
|
||||
rule_ders_s->insert(std::move(ten_s));
|
||||
auto ten_ss = std::make_unique<FGSTensor>(ypart.nstat+ypart.npred, ypart.nyss(), *(run.second));
|
||||
auto ten_ss
|
||||
= std::make_unique<FGSTensor>(ypart.nstat + ypart.npred, ypart.nyss(), *(run.second));
|
||||
rule_ders_ss->insert(std::move(ten_ss));
|
||||
}
|
||||
}
|
||||
|
@ -289,36 +286,36 @@ Approximation::saveRuleDerivs(const FGSContainer &g)
|
|||
add the σᵈ/d! multiple to the result. */
|
||||
|
||||
void
|
||||
Approximation::calcStochShift(Vector &out, double at_sigma) const
|
||||
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.get(), ypart.nyss(), ypart.ny(),
|
||||
ypart.nys(), model.nexog());
|
||||
ZAuxContainer zaux(rule_ders_ss.get(), 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};
|
||||
Symmetry sym {0, d, 0, 0};
|
||||
|
||||
// calculate F_u′ᵈ via ZAuxContainer
|
||||
auto ten = std::make_unique<FGSTensor>(ypart.ny(), TensorDimens(sym, nvs));
|
||||
ten->zeros();
|
||||
for (int l = 1; l <= d; l++)
|
||||
{
|
||||
const FSSparseTensor &f = model.getModelDerivatives().get(Symmetry{l});
|
||||
const FSSparseTensor& f = model.getModelDerivatives().get(Symmetry {l});
|
||||
zaux.multAndAdd(f, *ten);
|
||||
}
|
||||
|
||||
// multiply with shocks and add to result
|
||||
auto tmp = std::make_unique<FGSTensor>(ypart.ny(), TensorDimens(Symmetry{0, 0, 0, 0}, nvs));
|
||||
auto tmp
|
||||
= std::make_unique<FGSTensor>(ypart.ny(), TensorDimens(Symmetry {0, 0, 0, 0}, nvs));
|
||||
tmp->zeros();
|
||||
ten->contractAndAdd(1, *tmp, mom.get(Symmetry{d}));
|
||||
ten->contractAndAdd(1, *tmp, mom.get(Symmetry {d}));
|
||||
|
||||
out.add(pow(at_sigma, d)/dfac, tmp->getData());
|
||||
out.add(pow(at_sigma, d) / dfac, tmp->getData());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -343,8 +340,8 @@ Approximation::check(double at_sigma) const
|
|||
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;
|
||||
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);
|
||||
|
@ -377,12 +374,12 @@ Approximation::check(double at_sigma) const
|
|||
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});
|
||||
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_cast<const TwoDMatrix &>(G));
|
||||
TwoDMatrix B(const_cast<const TwoDMatrix&>(G));
|
||||
B.mult(-1.0);
|
||||
TwoDMatrix C(transpose(G));
|
||||
TwoDMatrix A(model.numeq(), model.numeq());
|
||||
|
@ -392,8 +389,8 @@ Approximation::calcYCov() const
|
|||
|
||||
TwoDMatrix X((gu * model.getVcov()) * transpose(gu));
|
||||
|
||||
GeneralSylvester gs(1, model.numeq(), model.numeq(), 0,
|
||||
A.getData(), B.getData(), C.getData(), X.getData());
|
||||
GeneralSylvester gs(1, model.numeq(), model.numeq(), 0, A.getData(), B.getData(), C.getData(),
|
||||
X.getData());
|
||||
gs.solve();
|
||||
|
||||
return X;
|
||||
|
|
|
@ -64,10 +64,10 @@
|
|||
#ifndef APPROXIMATION_H
|
||||
#define APPROXIMATION_H
|
||||
|
||||
#include "dynamic_model.hh"
|
||||
#include "decision_rule.hh"
|
||||
#include "korder.hh"
|
||||
#include "dynamic_model.hh"
|
||||
#include "journal.hh"
|
||||
#include "korder.hh"
|
||||
|
||||
#include <memory>
|
||||
|
||||
|
@ -87,8 +87,8 @@ class ZAuxContainer : public StackContainer<FGSTensor>, public FoldedStackContai
|
|||
public:
|
||||
using _Ctype = StackContainer<FGSTensor>::_Ctype;
|
||||
using itype = StackContainer<FGSTensor>::itype;
|
||||
ZAuxContainer(const _Ctype *gss, int ngss, int ng, int ny, int nu);
|
||||
itype getType(int i, const Symmetry &s) const override;
|
||||
ZAuxContainer(const _Ctype* gss, int ngss, int ng, int ny, int nu);
|
||||
itype getType(int i, const Symmetry& s) const override;
|
||||
};
|
||||
|
||||
/* This class provides an interface to approximation algorithms. The core
|
||||
|
@ -119,8 +119,8 @@ public:
|
|||
|
||||
class Approximation
|
||||
{
|
||||
DynamicModel &model;
|
||||
Journal &journal;
|
||||
DynamicModel& model;
|
||||
Journal& journal;
|
||||
std::unique_ptr<FGSContainer> rule_ders;
|
||||
std::unique_ptr<FGSContainer> rule_ders_s;
|
||||
std::unique_ptr<FGSContainer> rule_ders_ss;
|
||||
|
@ -136,18 +136,19 @@ class Approximation
|
|||
bool pruning;
|
||||
double qz_criterium;
|
||||
TwoDMatrix ss;
|
||||
public:
|
||||
Approximation(DynamicModel &m, Journal &j, int ns, bool dr_centr, bool pruning, double qz_crit);
|
||||
|
||||
const FoldDecisionRule &getFoldDecisionRule() const;
|
||||
const UnfoldDecisionRule &getUnfoldDecisionRulePruning() const;
|
||||
const UnfoldDecisionRule &getUnfoldDecisionRule() const;
|
||||
const TwoDMatrix &
|
||||
public:
|
||||
Approximation(DynamicModel& m, Journal& j, int ns, bool dr_centr, bool pruning, double qz_crit);
|
||||
|
||||
const FoldDecisionRule& getFoldDecisionRule() const;
|
||||
const UnfoldDecisionRule& getUnfoldDecisionRulePruning() const;
|
||||
const UnfoldDecisionRule& getUnfoldDecisionRule() const;
|
||||
const TwoDMatrix&
|
||||
getSS() const
|
||||
{
|
||||
return ss;
|
||||
}
|
||||
const DynamicModel &
|
||||
const DynamicModel&
|
||||
getModel() const
|
||||
{
|
||||
return model;
|
||||
|
@ -155,25 +156,26 @@ public:
|
|||
|
||||
void walkStochSteady();
|
||||
TwoDMatrix calcYCov() const;
|
||||
const FGSContainer &
|
||||
const FGSContainer&
|
||||
get_rule_ders() const
|
||||
{
|
||||
return *rule_ders;
|
||||
}
|
||||
const FGSContainer &
|
||||
const FGSContainer&
|
||||
get_rule_ders_s() const
|
||||
{
|
||||
return *rule_ders_s;
|
||||
}
|
||||
const FGSContainer &
|
||||
const FGSContainer&
|
||||
get_rule_ders_ss() const
|
||||
{
|
||||
return *rule_ders_ss;
|
||||
}
|
||||
|
||||
protected:
|
||||
void approxAtSteady();
|
||||
void calcStochShift(Vector &out, double at_sigma) const;
|
||||
void saveRuleDerivs(const FGSContainer &g);
|
||||
void calcStochShift(Vector& out, double at_sigma) const;
|
||||
void saveRuleDerivs(const FGSContainer& g);
|
||||
void check(double at_sigma) const;
|
||||
};
|
||||
|
||||
|
|
|
@ -18,28 +18,28 @@
|
|||
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "kord_exception.hh"
|
||||
#include "decision_rule.hh"
|
||||
#include "dynamic_model.hh"
|
||||
#include "kord_exception.hh"
|
||||
|
||||
#include "SymSchurDecomp.hh"
|
||||
|
||||
#include <memory>
|
||||
|
||||
// FoldDecisionRule conversion from UnfoldDecisionRule
|
||||
FoldDecisionRule::FoldDecisionRule(const UnfoldDecisionRule &udr)
|
||||
: DecisionRuleImpl<Storage::fold>(ctraits<Storage::fold>::Tpol(udr.nrows(), udr.nvars()),
|
||||
FoldDecisionRule::FoldDecisionRule(const UnfoldDecisionRule& udr) :
|
||||
DecisionRuleImpl<Storage::fold>(ctraits<Storage::fold>::Tpol(udr.nrows(), udr.nvars()),
|
||||
udr.ypart, udr.nu, udr.ysteady)
|
||||
{
|
||||
for (const auto &it : udr)
|
||||
for (const auto& it : udr)
|
||||
insert(std::make_unique<ctraits<Storage::fold>::Ttensym>(*(it.second)));
|
||||
}
|
||||
|
||||
// UnfoldDecisionRule conversion from FoldDecisionRule
|
||||
UnfoldDecisionRule::UnfoldDecisionRule(const FoldDecisionRule &fdr)
|
||||
: DecisionRuleImpl<Storage::unfold>(ctraits<Storage::unfold>::Tpol(fdr.nrows(), fdr.nvars()),
|
||||
UnfoldDecisionRule::UnfoldDecisionRule(const FoldDecisionRule& fdr) :
|
||||
DecisionRuleImpl<Storage::unfold>(ctraits<Storage::unfold>::Tpol(fdr.nrows(), fdr.nvars()),
|
||||
fdr.ypart, fdr.nu, fdr.ysteady)
|
||||
{
|
||||
for (const auto &it : fdr)
|
||||
for (const auto& it : fdr)
|
||||
insert(std::make_unique<ctraits<Storage::unfold>::Ttensym>(*(it.second)));
|
||||
}
|
||||
|
|
|
@ -48,26 +48,30 @@
|
|||
class DecisionRule
|
||||
{
|
||||
public:
|
||||
enum class emethod { horner, trad };
|
||||
enum class emethod
|
||||
{
|
||||
horner,
|
||||
trad
|
||||
};
|
||||
virtual ~DecisionRule() = default;
|
||||
|
||||
/* primitive evaluation (it takes a vector of state variables (predetermined,
|
||||
both and shocks) and returns the next period variables. Both input and
|
||||
output are in deviations from the rule's steady. */
|
||||
virtual void eval(emethod em, Vector &out, const ConstVector &v) const = 0;
|
||||
virtual void eval(emethod em, Vector& out, const ConstVector& v) const = 0;
|
||||
|
||||
/* makes only one step of simulation (in terms of absolute values, not
|
||||
deviations) */
|
||||
virtual void evaluate(emethod em, Vector &out, const ConstVector &ys,
|
||||
const ConstVector &u) const = 0;
|
||||
virtual void evaluate(emethod em, Vector& out, const ConstVector& ys, const ConstVector& u) const
|
||||
= 0;
|
||||
|
||||
/* returns a new copy of the decision rule, which is centralized about
|
||||
provided fix-point */
|
||||
virtual std::unique_ptr<DecisionRule> centralizedClone(const Vector &fixpoint) const = 0;
|
||||
virtual std::unique_ptr<DecisionRule> centralizedClone(const Vector& fixpoint) const = 0;
|
||||
|
||||
virtual const Vector &getSteady() const = 0;
|
||||
virtual const Vector& getSteady() const = 0;
|
||||
virtual int nexog() const = 0;
|
||||
virtual const PartitionY &getYPart() const = 0;
|
||||
virtual const PartitionY& getYPart() const = 0;
|
||||
};
|
||||
|
||||
/* The main purpose of this class is to implement DecisionRule interface, which
|
||||
|
@ -111,27 +115,27 @@ protected:
|
|||
const Vector ysteady;
|
||||
const PartitionY ypart;
|
||||
const int nu;
|
||||
|
||||
public:
|
||||
DecisionRuleImpl(const _Tpol &pol, const PartitionY &yp, int nuu,
|
||||
const ConstVector &ys)
|
||||
: ctraits<t>::Tpol(pol), ysteady(ys), ypart(yp), nu(nuu)
|
||||
DecisionRuleImpl(const _Tpol& pol, const PartitionY& yp, int nuu, const ConstVector& ys) :
|
||||
ctraits<t>::Tpol(pol), ysteady(ys), ypart(yp), nu(nuu)
|
||||
{
|
||||
}
|
||||
DecisionRuleImpl(_Tpol &pol, const PartitionY &yp, int nuu,
|
||||
const ConstVector &ys)
|
||||
: ctraits<t>::Tpol(0, yp.ny(), pol), ysteady(ys), ypart(yp),
|
||||
nu(nuu)
|
||||
DecisionRuleImpl(_Tpol& pol, const PartitionY& yp, int nuu, const ConstVector& ys) :
|
||||
ctraits<t>::Tpol(0, yp.ny(), pol), ysteady(ys), ypart(yp), nu(nuu)
|
||||
{
|
||||
}
|
||||
DecisionRuleImpl(const _Tg &g, const PartitionY &yp, int nuu,
|
||||
const ConstVector &ys, double sigma)
|
||||
: ctraits<t>::Tpol(yp.ny(), yp.nys()+nuu), ysteady(ys), ypart(yp), nu(nuu)
|
||||
DecisionRuleImpl(const _Tg& g, const PartitionY& yp, int nuu, const ConstVector& ys,
|
||||
double sigma) :
|
||||
ctraits<t>::Tpol(yp.ny(), yp.nys() + nuu),
|
||||
ysteady(ys), ypart(yp), nu(nuu)
|
||||
{
|
||||
fillTensors(g, sigma);
|
||||
}
|
||||
DecisionRuleImpl(const _Tg &g, const PartitionY &yp, int nuu,
|
||||
const ConstVector &ys, double sigma, bool pruning)
|
||||
: ctraits<t>::Tpol(yp.ny(), yp.nys()+nuu), ysteady(ys), ypart(yp), nu(nuu)
|
||||
DecisionRuleImpl(const _Tg& g, const PartitionY& yp, int nuu, const ConstVector& ys, double sigma,
|
||||
bool pruning) :
|
||||
ctraits<t>::Tpol(yp.ny(), yp.nys() + nuu),
|
||||
ysteady(ys), ypart(yp), nu(nuu)
|
||||
{
|
||||
if (pruning)
|
||||
fillTensorsPruning(g);
|
||||
|
@ -139,44 +143,45 @@ public:
|
|||
fillTensors(g, sigma);
|
||||
}
|
||||
|
||||
DecisionRuleImpl(const _TW &W, int nys, int nuu,
|
||||
const ConstVector &ys)
|
||||
: ctraits<t>::Tpol(1, nys+nuu), ysteady(ys), nu(nuu)
|
||||
DecisionRuleImpl(const _TW& W, int nys, int nuu, const ConstVector& ys) :
|
||||
ctraits<t>::Tpol(1, nys + nuu), ysteady(ys), nu(nuu)
|
||||
{
|
||||
fillTensors(W, nys);
|
||||
}
|
||||
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)
|
||||
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 &
|
||||
const Vector&
|
||||
getSteady() const override
|
||||
{
|
||||
return ysteady;
|
||||
}
|
||||
void evaluate(emethod em, Vector &out, const ConstVector &ys,
|
||||
const ConstVector &u) const override;
|
||||
std::unique_ptr<DecisionRule> centralizedClone(const Vector &fixpoint) const override;
|
||||
void evaluate(emethod em, Vector& out, const ConstVector& ys,
|
||||
const ConstVector& u) const override;
|
||||
std::unique_ptr<DecisionRule> centralizedClone(const Vector& fixpoint) const override;
|
||||
|
||||
int
|
||||
nexog() const override
|
||||
{
|
||||
return nu;
|
||||
}
|
||||
const PartitionY &
|
||||
const PartitionY&
|
||||
getYPart() const override
|
||||
{
|
||||
return ypart;
|
||||
}
|
||||
|
||||
protected:
|
||||
void fillTensors(const _Tg &g, double sigma);
|
||||
void fillTensorsPruning(const _Tg &g);
|
||||
void fillTensors(const _TW &W, int nys);
|
||||
void centralize(const DecisionRuleImpl &dr);
|
||||
void fillTensors(const _Tg& g, double sigma);
|
||||
void fillTensorsPruning(const _Tg& g);
|
||||
void fillTensors(const _TW& W, int nys);
|
||||
void centralize(const DecisionRuleImpl& dr);
|
||||
|
||||
public:
|
||||
void eval(emethod em, Vector &out, const ConstVector &v) const override;
|
||||
void eval(emethod em, Vector& out, const ConstVector& v) const override;
|
||||
};
|
||||
|
||||
/* Here we have to fill the tensor polynomial. This involves two separated
|
||||
|
@ -190,14 +195,14 @@ public:
|
|||
The q-order approximation to the solution can be written as:
|
||||
|
||||
⎡ ⎤
|
||||
q 1 ⎢ ⎛ l ⎞⎡ ⎤ ᵢ ⎡ ⎤αₘ ⱼ ⎡ ⎤βₘ ⎥
|
||||
yₜ − ȳ = ∑ ──⎢ ∑ ⎢ ⎥⎢g_yⁱuʲσᵏ⎥ ∏ ⎢y*ₜ₋₁ − ȳ*⎥ ∏ ⎢uₜ⎥ σᵏ⎥
|
||||
q 1 ⎢ ⎛ l ⎞⎡ ⎤ ᵢ ⎡ ⎤αₘ ⱼ ⎡ ⎤βₘ ⎥
|
||||
yₜ − ȳ = ∑ ──⎢ ∑ ⎢ ⎥⎢g_yⁱuʲσᵏ⎥ ∏ ⎢y*ₜ₋₁ − ȳ*⎥ ∏ ⎢uₜ⎥ σᵏ⎥
|
||||
ˡ⁼¹ l!⎢ⁱ⁺ʲ⁺ᵏ⁼ˡ⎝i,j,k⎠⎣ ⎦α₁…αⱼβ₁…βⱼ ᵐ⁼¹⎣ ⎦ ᵐ⁼¹⎣ ⎦ ⎥
|
||||
⎣ ⎦
|
||||
|
||||
⎡ ⎡ ⎤ ⎤
|
||||
q ⎢ ⎛i+j⎞⎢ₗ₋ᵢ₋ⱼ 1 ⎛l⎞ ⎡ ⎤ ⎥ ᵢ ⎡ ⎤αₘ ⱼ ⎡ ⎤βₘ⎥
|
||||
= ∑ ⎢ ∑ ⎢ ⎥⎢ ∑ ── ⎢ ⎥ ⎢g_yⁱuʲσᵏ⎥ σᵏ⎥ ∏ ⎢y*ₜ₋₁ − ȳ*⎥ ∏ ⎢uₜ⎥ ⎥
|
||||
q ⎢ ⎛i+j⎞⎢ₗ₋ᵢ₋ⱼ 1 ⎛l⎞ ⎡ ⎤ ⎥ ᵢ ⎡ ⎤αₘ ⱼ ⎡ ⎤βₘ⎥
|
||||
= ∑ ⎢ ∑ ⎢ ⎥⎢ ∑ ── ⎢ ⎥ ⎢g_yⁱuʲσᵏ⎥ σᵏ⎥ ∏ ⎢y*ₜ₋₁ − ȳ*⎥ ∏ ⎢uₜ⎥ ⎥
|
||||
ˡ⁼¹⎢i+j≤l ⎝ i ⎠⎢ ᵏ⁼⁰ l! ⎝k⎠ ⎣ ⎦α₁…αⱼβ₁…βⱼ ⎥ ᵐ⁼¹⎣ ⎦ ᵐ⁼¹⎣ ⎦ ⎥
|
||||
⎣ ⎣ ⎦ ⎦
|
||||
|
||||
|
@ -217,13 +222,13 @@ public:
|
|||
|
||||
template<Storage t>
|
||||
void
|
||||
DecisionRuleImpl<t>::fillTensors(const _Tg &g, double sigma)
|
||||
DecisionRuleImpl<t>::fillTensors(const _Tg& g, double sigma)
|
||||
{
|
||||
IntSequence tns{ypart.nys(), nu};
|
||||
IntSequence tns {ypart.nys(), nu};
|
||||
int dfact = 1;
|
||||
for (int d = 0; d <= g.getMaxDim(); d++, dfact *= d)
|
||||
{
|
||||
auto g_yud = std::make_unique<_Ttensym>(ypart.ny(), ypart.nys()+nu, d);
|
||||
auto g_yud = std::make_unique<_Ttensym>(ypart.ny(), ypart.nys() + nu, d);
|
||||
g_yud->zeros();
|
||||
|
||||
// fill tensor of ‘g_yud’ of dimension ‘d’
|
||||
|
@ -239,16 +244,14 @@ DecisionRuleImpl<t>::fillTensors(const _Tg &g, double sigma)
|
|||
|
||||
for (int i = 0; i <= d; i++)
|
||||
{
|
||||
int j = d-i;
|
||||
int j = d - i;
|
||||
int kfact = 1;
|
||||
_Ttensor tmp(ypart.ny(),
|
||||
TensorDimens(Symmetry{i, j}, tns));
|
||||
_Ttensor tmp(ypart.ny(), TensorDimens(Symmetry {i, j}, tns));
|
||||
tmp.zeros();
|
||||
for (int k = 0; k+d <= g.getMaxDim(); k++, kfact *= k)
|
||||
if (Symmetry sym{i, j, 0, k};
|
||||
g.check(sym))
|
||||
for (int k = 0; k + d <= g.getMaxDim(); k++, kfact *= k)
|
||||
if (Symmetry sym {i, j, 0, k}; g.check(sym))
|
||||
{
|
||||
double mult = pow(sigma, k)/dfact/kfact;
|
||||
double mult = pow(sigma, k) / dfact / kfact;
|
||||
tmp.add(mult, g.get(sym));
|
||||
}
|
||||
g_yud->addSubTensor(tmp);
|
||||
|
@ -260,31 +263,30 @@ DecisionRuleImpl<t>::fillTensors(const _Tg &g, double sigma)
|
|||
|
||||
template<Storage t>
|
||||
void
|
||||
DecisionRuleImpl<t>::fillTensorsPruning(const _Tg &g)
|
||||
DecisionRuleImpl<t>::fillTensorsPruning(const _Tg& g)
|
||||
{
|
||||
IntSequence tns{ypart.nys(), nu, 1};
|
||||
IntSequence tns {ypart.nys(), nu, 1};
|
||||
int dfact = 1;
|
||||
for (int d = 0; d <= g.getMaxDim(); d++, dfact *= d)
|
||||
{
|
||||
auto g_yusd = std::make_unique<_Ttensym>(ypart.ny(), ypart.nys()+nu+1, d);
|
||||
auto g_yusd = std::make_unique<_Ttensym>(ypart.ny(), ypart.nys() + nu + 1, d);
|
||||
g_yusd->zeros();
|
||||
// fill tensor of ‘g_yusd’ of dimension ‘d’
|
||||
/*
|
||||
/*
|
||||
Here we have to fill the tensor [g_(yuσ)ᵈ]. So we go through all pairs
|
||||
(i,j,k) such that i+j+k=d. We weight it with 1/(i+j+k)! The factorial
|
||||
is denoted dfact.
|
||||
*/
|
||||
for (int i = 0; i <= d; i++)
|
||||
{
|
||||
for (int j = 0; j <= d-i; j++)
|
||||
for (int j = 0; j <= d - i; j++)
|
||||
{
|
||||
int k = d-i-j;
|
||||
_Ttensor tmp(ypart.ny(),
|
||||
TensorDimens(Symmetry{i, j, k}, tns));
|
||||
int k = d - i - j;
|
||||
_Ttensor tmp(ypart.ny(), TensorDimens(Symmetry {i, j, k}, tns));
|
||||
tmp.zeros();
|
||||
if (Symmetry sym{i, j, 0, k}; g.check(sym))
|
||||
if (Symmetry sym {i, j, 0, k}; g.check(sym))
|
||||
{
|
||||
double mult = 1.0/dfact;
|
||||
double mult = 1.0 / dfact;
|
||||
// mexPrintf("Symmetry found: %d %d %d %.2f %d\n", i, j, k, mult, kfact);
|
||||
tmp.add(mult, g.get(sym));
|
||||
}
|
||||
|
@ -297,13 +299,13 @@ DecisionRuleImpl<t>::fillTensorsPruning(const _Tg &g)
|
|||
|
||||
template<Storage t>
|
||||
void
|
||||
DecisionRuleImpl<t>::fillTensors(const _TW &W, int nys)
|
||||
DecisionRuleImpl<t>::fillTensors(const _TW& W, int nys)
|
||||
{
|
||||
IntSequence tns{nys, nu};
|
||||
IntSequence tns {nys, nu};
|
||||
int dfact = 1;
|
||||
for (int d = 0; d <= W.getMaxDim(); d++, dfact *= d)
|
||||
{
|
||||
auto W_yud = std::make_unique<_Ttensym>(1, nys+nu, d);
|
||||
auto W_yud = std::make_unique<_Ttensym>(1, nys + nu, d);
|
||||
W_yud->zeros();
|
||||
|
||||
// fill tensor of ‘g_yud’ of dimension ‘d’
|
||||
|
@ -319,15 +321,14 @@ DecisionRuleImpl<t>::fillTensors(const _TW &W, int nys)
|
|||
|
||||
for (int i = 0; i <= d; i++)
|
||||
{
|
||||
int j = d-i;
|
||||
int j = d - i;
|
||||
int kfact = 1;
|
||||
_Ttensor tmp(1, TensorDimens(Symmetry{i, j}, tns));
|
||||
_Ttensor tmp(1, TensorDimens(Symmetry {i, j}, tns));
|
||||
tmp.zeros();
|
||||
for (int k = 0; k+d <= W.getMaxDim(); k++, kfact *= k)
|
||||
if (Symmetry sym{i, j, 0, k};
|
||||
W.check(sym))
|
||||
for (int k = 0; k + d <= W.getMaxDim(); k++, kfact *= k)
|
||||
if (Symmetry sym {i, j, 0, k}; W.check(sym))
|
||||
{
|
||||
double mult = 1.0/dfact/kfact;
|
||||
double mult = 1.0 / dfact / kfact;
|
||||
tmp.add(mult, W.get(sym));
|
||||
}
|
||||
W_yud->addSubTensor(tmp);
|
||||
|
@ -351,7 +352,7 @@ DecisionRuleImpl<t>::fillTensors(const _TW &W, int nys)
|
|||
|
||||
template<Storage t>
|
||||
void
|
||||
DecisionRuleImpl<t>::centralize(const DecisionRuleImpl &dr)
|
||||
DecisionRuleImpl<t>::centralize(const DecisionRuleImpl& dr)
|
||||
{
|
||||
Vector dstate(ypart.nys() + nu);
|
||||
dstate.zeros();
|
||||
|
@ -365,9 +366,9 @@ DecisionRuleImpl<t>::centralize(const DecisionRuleImpl &dr)
|
|||
int dfac = 1;
|
||||
for (int d = 1; d <= dr.getMaxDim(); d++, dfac *= d)
|
||||
{
|
||||
pol.derivative(d-1);
|
||||
pol.derivative(d - 1);
|
||||
auto der = pol.evalPartially(d, dstate);
|
||||
der->mult(1.0/dfac);
|
||||
der->mult(1.0 / dfac);
|
||||
this->insert(std::move(der));
|
||||
}
|
||||
}
|
||||
|
@ -379,15 +380,15 @@ DecisionRuleImpl<t>::centralize(const DecisionRuleImpl &dr)
|
|||
|
||||
template<Storage t>
|
||||
void
|
||||
DecisionRuleImpl<t>::evaluate(emethod em, Vector &out, const ConstVector &ys,
|
||||
const ConstVector &u) const
|
||||
DecisionRuleImpl<t>::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_u(ypart.nys() + nu);
|
||||
Vector ys_u1(ys_u, 0, ypart.nys());
|
||||
ys_u1 = ys;
|
||||
ys_u1.add(-1.0, ysteady_pred);
|
||||
|
@ -402,7 +403,7 @@ DecisionRuleImpl<t>::evaluate(emethod em, Vector &out, const ConstVector &ys,
|
|||
|
||||
template<Storage t>
|
||||
std::unique_ptr<DecisionRule>
|
||||
DecisionRuleImpl<t>::centralizedClone(const Vector &fixpoint) const
|
||||
DecisionRuleImpl<t>::centralizedClone(const Vector& fixpoint) const
|
||||
{
|
||||
return std::make_unique<DecisionRuleImpl<t>>(*this, fixpoint);
|
||||
}
|
||||
|
@ -412,7 +413,7 @@ DecisionRuleImpl<t>::centralizedClone(const Vector &fixpoint) const
|
|||
|
||||
template<Storage t>
|
||||
void
|
||||
DecisionRuleImpl<t>::eval(emethod em, Vector &out, const ConstVector &v) const
|
||||
DecisionRuleImpl<t>::eval(emethod em, Vector& out, const ConstVector& v) const
|
||||
{
|
||||
if (em == emethod::horner)
|
||||
_Tpol::evalHorner(out, v);
|
||||
|
@ -428,37 +429,37 @@ class UnfoldDecisionRule;
|
|||
class FoldDecisionRule : public DecisionRuleImpl<Storage::fold>
|
||||
{
|
||||
friend class UnfoldDecisionRule;
|
||||
|
||||
public:
|
||||
FoldDecisionRule(const ctraits<Storage::fold>::Tpol &pol, const PartitionY &yp, int nuu,
|
||||
const ConstVector &ys)
|
||||
: DecisionRuleImpl<Storage::fold>(pol, yp, nuu, ys)
|
||||
FoldDecisionRule(const ctraits<Storage::fold>::Tpol& pol, const PartitionY& yp, int nuu,
|
||||
const ConstVector& ys) :
|
||||
DecisionRuleImpl<Storage::fold>(pol, yp, nuu, ys)
|
||||
{
|
||||
}
|
||||
FoldDecisionRule(ctraits<Storage::fold>::Tpol &pol, const PartitionY &yp, int nuu,
|
||||
const ConstVector &ys)
|
||||
: DecisionRuleImpl<Storage::fold>(pol, yp, nuu, ys)
|
||||
FoldDecisionRule(ctraits<Storage::fold>::Tpol& pol, const PartitionY& yp, int nuu,
|
||||
const ConstVector& ys) :
|
||||
DecisionRuleImpl<Storage::fold>(pol, yp, nuu, ys)
|
||||
{
|
||||
}
|
||||
FoldDecisionRule(const ctraits<Storage::fold>::Tg &g, const PartitionY &yp, int nuu,
|
||||
const ConstVector &ys, double sigma)
|
||||
: DecisionRuleImpl<Storage::fold>(g, yp, nuu, ys, sigma)
|
||||
FoldDecisionRule(const ctraits<Storage::fold>::Tg& g, const PartitionY& yp, int nuu,
|
||||
const ConstVector& ys, double sigma) :
|
||||
DecisionRuleImpl<Storage::fold>(g, yp, nuu, ys, sigma)
|
||||
{
|
||||
}
|
||||
FoldDecisionRule(const ctraits<Storage::fold>::Tg &g, const PartitionY &yp, int nuu,
|
||||
const ConstVector &ys, double sigma, bool pruning)
|
||||
: DecisionRuleImpl<Storage::fold>(g, yp, nuu, ys, sigma, pruning)
|
||||
FoldDecisionRule(const ctraits<Storage::fold>::Tg& g, const PartitionY& yp, int nuu,
|
||||
const ConstVector& ys, double sigma, bool pruning) :
|
||||
DecisionRuleImpl<Storage::fold>(g, yp, nuu, ys, sigma, pruning)
|
||||
{
|
||||
}
|
||||
FoldDecisionRule(const ctraits<Storage::fold>::TW &W, int nys, int nuu,
|
||||
const ConstVector &ys)
|
||||
: DecisionRuleImpl<Storage::fold>(W, nys, nuu, ys)
|
||||
FoldDecisionRule(const ctraits<Storage::fold>::TW& W, int nys, int nuu, const ConstVector& ys) :
|
||||
DecisionRuleImpl<Storage::fold>(W, nys, nuu, ys)
|
||||
{
|
||||
}
|
||||
FoldDecisionRule(const DecisionRuleImpl<Storage::fold> &dr, const ConstVector &fixpoint)
|
||||
: DecisionRuleImpl<Storage::fold>(dr, fixpoint)
|
||||
FoldDecisionRule(const DecisionRuleImpl<Storage::fold>& dr, const ConstVector& fixpoint) :
|
||||
DecisionRuleImpl<Storage::fold>(dr, fixpoint)
|
||||
{
|
||||
}
|
||||
FoldDecisionRule(const UnfoldDecisionRule &udr);
|
||||
FoldDecisionRule(const UnfoldDecisionRule& udr);
|
||||
};
|
||||
|
||||
/* This is exactly the same as DecisionRuleImpl<Storage::unfold>, but with a
|
||||
|
@ -468,27 +469,28 @@ public:
|
|||
class UnfoldDecisionRule : public DecisionRuleImpl<Storage::unfold>
|
||||
{
|
||||
friend class FoldDecisionRule;
|
||||
|
||||
public:
|
||||
UnfoldDecisionRule(const ctraits<Storage::unfold>::Tpol &pol, const PartitionY &yp, int nuu,
|
||||
const ConstVector &ys)
|
||||
: DecisionRuleImpl<Storage::unfold>(pol, yp, nuu, ys)
|
||||
UnfoldDecisionRule(const ctraits<Storage::unfold>::Tpol& pol, const PartitionY& yp, int nuu,
|
||||
const ConstVector& ys) :
|
||||
DecisionRuleImpl<Storage::unfold>(pol, yp, nuu, ys)
|
||||
{
|
||||
}
|
||||
UnfoldDecisionRule(ctraits<Storage::unfold>::Tpol &pol, const PartitionY &yp, int nuu,
|
||||
const ConstVector &ys)
|
||||
: DecisionRuleImpl<Storage::unfold>(pol, yp, nuu, ys)
|
||||
UnfoldDecisionRule(ctraits<Storage::unfold>::Tpol& pol, const PartitionY& yp, int nuu,
|
||||
const ConstVector& ys) :
|
||||
DecisionRuleImpl<Storage::unfold>(pol, yp, nuu, ys)
|
||||
{
|
||||
}
|
||||
UnfoldDecisionRule(const ctraits<Storage::unfold>::Tg &g, const PartitionY &yp, int nuu,
|
||||
const ConstVector &ys, double sigma)
|
||||
: DecisionRuleImpl<Storage::unfold>(g, yp, nuu, ys, sigma)
|
||||
UnfoldDecisionRule(const ctraits<Storage::unfold>::Tg& g, const PartitionY& yp, int nuu,
|
||||
const ConstVector& ys, double sigma) :
|
||||
DecisionRuleImpl<Storage::unfold>(g, yp, nuu, ys, sigma)
|
||||
{
|
||||
}
|
||||
UnfoldDecisionRule(const DecisionRuleImpl<Storage::unfold> &dr, const ConstVector &fixpoint)
|
||||
: DecisionRuleImpl<Storage::unfold>(dr, fixpoint)
|
||||
UnfoldDecisionRule(const DecisionRuleImpl<Storage::unfold>& dr, const ConstVector& fixpoint) :
|
||||
DecisionRuleImpl<Storage::unfold>(dr, fixpoint)
|
||||
{
|
||||
}
|
||||
UnfoldDecisionRule(const FoldDecisionRule &udr);
|
||||
UnfoldDecisionRule(const FoldDecisionRule& udr);
|
||||
};
|
||||
|
||||
/* This class serves for calculation of the fix point of the decision rule
|
||||
|
@ -518,12 +520,12 @@ class DRFixPoint : public ctraits<t>::Tpol
|
|||
const PartitionY ypart;
|
||||
std::unique_ptr<_Tpol> bigf;
|
||||
std::unique_ptr<_Tpol> bigfder;
|
||||
|
||||
public:
|
||||
using emethod = typename DecisionRule::emethod;
|
||||
DRFixPoint(const _Tg &g, const PartitionY &yp,
|
||||
const Vector &ys, double sigma);
|
||||
DRFixPoint(const _Tg& g, const PartitionY& yp, const Vector& ys, double sigma);
|
||||
|
||||
bool calcFixPoint(Vector &out);
|
||||
bool calcFixPoint(Vector& out);
|
||||
|
||||
int
|
||||
getNumIter() const
|
||||
|
@ -540,9 +542,11 @@ public:
|
|||
{
|
||||
return newton_iter_total;
|
||||
}
|
||||
|
||||
protected:
|
||||
void fillTensors(const _Tg &g, double sigma);
|
||||
bool solveNewton(Vector &y);
|
||||
void fillTensors(const _Tg& g, double sigma);
|
||||
bool solveNewton(Vector& y);
|
||||
|
||||
private:
|
||||
int iter;
|
||||
int newton_iter_last;
|
||||
|
@ -555,15 +559,13 @@ private:
|
|||
calculated. */
|
||||
|
||||
template<Storage t>
|
||||
DRFixPoint<t>::DRFixPoint(const _Tg &g, const PartitionY &yp,
|
||||
const Vector &ys, double sigma)
|
||||
: ctraits<t>::Tpol(yp.ny(), yp.nys()),
|
||||
ysteady(ys), ypart(yp)
|
||||
DRFixPoint<t>::DRFixPoint(const _Tg& g, const PartitionY& yp, const Vector& ys, double sigma) :
|
||||
ctraits<t>::Tpol(yp.ny(), yp.nys()), ysteady(ys), ypart(yp)
|
||||
{
|
||||
fillTensors(g, sigma);
|
||||
_Tpol yspol(ypart.nstat, ypart.nys(), *this);
|
||||
bigf = std::make_unique<_Tpol>(const_cast<const _Tpol &>(yspol));
|
||||
_Ttensym &frst = bigf->get(Symmetry{1});
|
||||
bigf = std::make_unique<_Tpol>(const_cast<const _Tpol&>(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 = std::make_unique<_Tpol>(*bigf, 0);
|
||||
|
@ -576,7 +578,7 @@ DRFixPoint<t>::DRFixPoint(const _Tg &g, const PartitionY &yp,
|
|||
|
||||
template<Storage t>
|
||||
void
|
||||
DRFixPoint<t>::fillTensors(const _Tg &g, double sigma)
|
||||
DRFixPoint<t>::fillTensors(const _Tg& g, double sigma)
|
||||
{
|
||||
int dfact = 1;
|
||||
for (int d = 0; d <= g.getMaxDim(); d++, dfact *= d)
|
||||
|
@ -584,11 +586,11 @@ DRFixPoint<t>::fillTensors(const _Tg &g, double sigma)
|
|||
auto g_yd = std::make_unique<_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}))
|
||||
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;
|
||||
const _Ttensor& ten = g.get(Symmetry {d, 0, 0, k});
|
||||
double mult = pow(sigma, k) / dfact / kfact;
|
||||
g_yd->add(mult, ten);
|
||||
}
|
||||
this->insert(std::move(g_yd));
|
||||
|
@ -609,10 +611,10 @@ DRFixPoint<t>::fillTensors(const _Tg &g, double sigma)
|
|||
|
||||
template<Storage t>
|
||||
bool
|
||||
DRFixPoint<t>::solveNewton(Vector &y)
|
||||
DRFixPoint<t>::solveNewton(Vector& y)
|
||||
{
|
||||
const double urelax_threshold = 1.e-5;
|
||||
Vector sol(const_cast<const Vector &>(y));
|
||||
Vector sol(const_cast<const Vector&>(y));
|
||||
Vector delta(y.length());
|
||||
newton_iter_last = 0;
|
||||
bool delta_finite = true;
|
||||
|
@ -642,7 +644,7 @@ DRFixPoint<t>::solveNewton(Vector &y)
|
|||
urelax = 1.0;
|
||||
while (!urelax_found && urelax > urelax_threshold)
|
||||
{
|
||||
Vector soltmp(const_cast<const Vector &>(sol));
|
||||
Vector soltmp(const_cast<const Vector&>(sol));
|
||||
soltmp.add(-urelax, delta);
|
||||
Vector f(sol.length());
|
||||
bigf->evalHorner(f, soltmp);
|
||||
|
@ -650,7 +652,7 @@ DRFixPoint<t>::solveNewton(Vector &y)
|
|||
if (fnorm <= flastnorm)
|
||||
urelax_found = true;
|
||||
else
|
||||
urelax *= std::min(0.5, flastnorm/fnorm);
|
||||
urelax *= std::min(0.5, flastnorm / fnorm);
|
||||
}
|
||||
|
||||
sol.add(-urelax, delta);
|
||||
|
@ -660,13 +662,12 @@ DRFixPoint<t>::solveNewton(Vector &y)
|
|||
converged = delta_finite && fnorm < tol;
|
||||
flastnorm = fnorm;
|
||||
}
|
||||
while (!converged && newton_iter_last < max_newton_iter
|
||||
&& urelax > urelax_threshold);
|
||||
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_cast<const Vector &>(sol);
|
||||
y = const_cast<const Vector&>(sol);
|
||||
return converged;
|
||||
}
|
||||
|
||||
|
@ -685,10 +686,9 @@ DRFixPoint<t>::solveNewton(Vector &y)
|
|||
|
||||
template<Storage t>
|
||||
bool
|
||||
DRFixPoint<t>::calcFixPoint(Vector &out)
|
||||
DRFixPoint<t>::calcFixPoint(Vector& out)
|
||||
{
|
||||
KORD_RAISE_IF(out.length() != ypart.ny(),
|
||||
"Wrong length of out in DRFixPoint::calcFixPoint");
|
||||
KORD_RAISE_IF(out.length() != ypart.ny(), "Wrong length of out in DRFixPoint::calcFixPoint");
|
||||
|
||||
Vector delta(ypart.nys());
|
||||
Vector ystar(ypart.nys());
|
||||
|
@ -700,13 +700,12 @@ DRFixPoint<t>::calcFixPoint(Vector &out)
|
|||
bool converged = false;
|
||||
do
|
||||
{
|
||||
if ((iter/newton_pause)*newton_pause == iter)
|
||||
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_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;
|
||||
|
|
|
@ -20,8 +20,8 @@
|
|||
|
||||
#include "dynamic_model.hh"
|
||||
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
|
||||
void
|
||||
NameList::print() const
|
||||
|
|
|
@ -30,8 +30,8 @@
|
|||
#ifndef DYNAMIC_MODEL_H
|
||||
#define DYNAMIC_MODEL_H
|
||||
|
||||
#include "t_container.hh"
|
||||
#include "sparse_tensor.hh"
|
||||
#include "t_container.hh"
|
||||
|
||||
#include "Vector.hh"
|
||||
|
||||
|
@ -46,7 +46,7 @@ class NameList
|
|||
public:
|
||||
virtual ~NameList() = default;
|
||||
virtual int getNum() const = 0;
|
||||
virtual const std::string &getName(int i) const = 0;
|
||||
virtual const std::string& getName(int i) const = 0;
|
||||
void print() const;
|
||||
};
|
||||
|
||||
|
@ -121,21 +121,22 @@ public:
|
|||
int
|
||||
numeq() const
|
||||
{
|
||||
return nstat()+nboth()+npred()+nforw();
|
||||
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 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 ConstVector &yy, const Vector &xx) = 0;
|
||||
virtual void evaluateSystem(Vector &out, const ConstVector &yym, const ConstVector &yy,
|
||||
const ConstVector &yyp, const Vector &xx) = 0;
|
||||
virtual void evaluateSystem(Vector& out, const ConstVector& yy, const Vector& xx) = 0;
|
||||
virtual void evaluateSystem(Vector& out, const ConstVector& yym, const ConstVector& yy,
|
||||
const ConstVector& yyp, const Vector& xx)
|
||||
= 0;
|
||||
virtual void calcDerivativesAtSteady() = 0;
|
||||
};
|
||||
|
||||
|
|
|
@ -27,9 +27,8 @@
|
|||
/* We take an opportunity to refine the stack container to avoid allocation of
|
||||
more memory than available. */
|
||||
void
|
||||
FaaDiBruno::calculate(const StackContainer<FGSTensor> &cont,
|
||||
const TensorContainer<FSSparseTensor> &f,
|
||||
FGSTensor &out)
|
||||
FaaDiBruno::calculate(const StackContainer<FGSTensor>& cont,
|
||||
const TensorContainer<FSSparseTensor>& f, FGSTensor& out)
|
||||
{
|
||||
out.zeros();
|
||||
for (int l = 1; l <= out.dimen(); l++)
|
||||
|
@ -47,8 +46,7 @@ FaaDiBruno::calculate(const StackContainer<FGSTensor> &cont,
|
|||
/* Here we just simply evaluate multAndAdd() for the dense container. There is
|
||||
no opportunity for tuning. */
|
||||
void
|
||||
FaaDiBruno::calculate(const FoldedStackContainer &cont, const FGSContainer &g,
|
||||
FGSTensor &out)
|
||||
FaaDiBruno::calculate(const FoldedStackContainer& cont, const FGSContainer& g, FGSTensor& out)
|
||||
{
|
||||
out.zeros();
|
||||
for (int l = 1; l <= out.dimen(); l++)
|
||||
|
@ -56,7 +54,7 @@ FaaDiBruno::calculate(const FoldedStackContainer &cont, const FGSContainer &g,
|
|||
long int mem = SystemResources::availableMemory();
|
||||
cont.multAndAdd(l, g, out);
|
||||
JournalRecord rec(journal);
|
||||
int mem_mb = mem/1024/1024;
|
||||
int mem_mb = mem / 1024 / 1024;
|
||||
rec << "dim=" << l << " avmem=" << mem_mb << endrec;
|
||||
}
|
||||
}
|
||||
|
@ -65,9 +63,8 @@ FaaDiBruno::calculate(const FoldedStackContainer &cont, const FGSContainer &g,
|
|||
/* This is the same as FaaDiBruno::calculate() folded sparse code. The only
|
||||
difference is that we construct unfolded fine container. */
|
||||
void
|
||||
FaaDiBruno::calculate(const StackContainer<UGSTensor> &cont,
|
||||
const TensorContainer<FSSparseTensor> &f,
|
||||
UGSTensor &out)
|
||||
FaaDiBruno::calculate(const StackContainer<UGSTensor>& cont,
|
||||
const TensorContainer<FSSparseTensor>& f, UGSTensor& out)
|
||||
{
|
||||
out.zeros();
|
||||
for (int l = 1; l <= out.dimen(); l++)
|
||||
|
@ -84,8 +81,7 @@ FaaDiBruno::calculate(const StackContainer<UGSTensor> &cont,
|
|||
// FaaDiBruno::calculate() unfolded dense code
|
||||
/* Again, no tuning opportunity here. */
|
||||
void
|
||||
FaaDiBruno::calculate(const UnfoldedStackContainer &cont, const UGSContainer &g,
|
||||
UGSTensor &out)
|
||||
FaaDiBruno::calculate(const UnfoldedStackContainer& cont, const UGSContainer& g, UGSTensor& out)
|
||||
{
|
||||
out.zeros();
|
||||
for (int l = 1; l <= out.dimen(); l++)
|
||||
|
@ -93,7 +89,7 @@ FaaDiBruno::calculate(const UnfoldedStackContainer &cont, const UGSContainer &g,
|
|||
long int mem = SystemResources::availableMemory();
|
||||
cont.multAndAdd(l, g, out);
|
||||
JournalRecord rec(journal);
|
||||
int mem_mb = mem/1024/1024;
|
||||
int mem_mb = mem / 1024 / 1024;
|
||||
rec << "dim=" << l << " avmem=" << mem_mb << endrec;
|
||||
}
|
||||
}
|
||||
|
@ -129,21 +125,21 @@ FaaDiBruno::calculate(const UnfoldedStackContainer &cont, const UGSContainer &g,
|
|||
do something. */
|
||||
|
||||
std::tuple<int, int, int>
|
||||
FaaDiBruno::estimRefinement(const TensorDimens &tdims, int nr, int l)
|
||||
FaaDiBruno::estimRefinement(const TensorDimens& tdims, int nr, int l)
|
||||
{
|
||||
int nthreads = sthread::detach_thread_group::max_parallel_threads;
|
||||
long per_size1 = tdims.calcUnfoldMaxOffset();
|
||||
long per_size2 = static_cast<long>(std::pow(tdims.getNVS().getMax(), l));
|
||||
double lambda = 0.0;
|
||||
long per_size = sizeof(double)*nr
|
||||
*static_cast<long>(lambda*per_size1+(1-lambda)*per_size2);
|
||||
long per_size
|
||||
= sizeof(double) * nr * static_cast<long>(lambda * per_size1 + (1 - lambda) * per_size2);
|
||||
long mem = SystemResources::availableMemory();
|
||||
int max = 0;
|
||||
if (double num_cols {static_cast<double>(mem-magic_mult*nthreads*per_size)
|
||||
/nthreads/sizeof(double)/nr};
|
||||
if (double num_cols {static_cast<double>(mem - magic_mult * nthreads * per_size) / nthreads
|
||||
/ sizeof(double) / nr};
|
||||
num_cols > 0)
|
||||
{
|
||||
double maxd = std::pow(num_cols, 1.0/l);
|
||||
double maxd = std::pow(num_cols, 1.0 / l);
|
||||
max = static_cast<int>(std::floor(maxd));
|
||||
}
|
||||
if (max == 0)
|
||||
|
@ -155,7 +151,7 @@ FaaDiBruno::estimRefinement(const TensorDimens &tdims, int nr, int l)
|
|||
rec << " (decrease number of threads)";
|
||||
rec << endrec;
|
||||
}
|
||||
int avmem_mb = mem/1024/1024;
|
||||
int tmpmem_mb = nthreads*per_size/1024/1024;
|
||||
return { max, avmem_mb, tmpmem_mb };
|
||||
int avmem_mb = mem / 1024 / 1024;
|
||||
int tmpmem_mb = nthreads * per_size / 1024 / 1024;
|
||||
return {max, avmem_mb, tmpmem_mb};
|
||||
}
|
||||
|
|
|
@ -32,32 +32,31 @@
|
|||
#ifndef FAA_DI_BRUNO_H
|
||||
#define FAA_DI_BRUNO_H
|
||||
|
||||
#include "gs_tensor.hh"
|
||||
#include "journal.hh"
|
||||
#include "sparse_tensor.hh"
|
||||
#include "stack_container.hh"
|
||||
#include "t_container.hh"
|
||||
#include "sparse_tensor.hh"
|
||||
#include "gs_tensor.hh"
|
||||
|
||||
#include <tuple>
|
||||
|
||||
class FaaDiBruno
|
||||
{
|
||||
Journal &journal;
|
||||
Journal& journal;
|
||||
|
||||
public:
|
||||
FaaDiBruno(Journal &jr)
|
||||
: journal(jr)
|
||||
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);
|
||||
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:
|
||||
std::tuple<int, int, int> estimRefinement(const TensorDimens &tdims, int nr, int l);
|
||||
std::tuple<int, int, int> estimRefinement(const TensorDimens& tdims, int nr, int l);
|
||||
|
||||
// See FaaDiBruno::calculate() folded sparse code for why we have magic_mult
|
||||
constexpr static double magic_mult = 1.5;
|
||||
|
|
|
@ -18,8 +18,8 @@
|
|||
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "kord_exception.hh"
|
||||
#include "first_order.hh"
|
||||
#include "kord_exception.hh"
|
||||
|
||||
#include <dynlapack.h>
|
||||
|
||||
|
@ -31,9 +31,10 @@ std::mutex FirstOrder::mut;
|
|||
criterium). */
|
||||
|
||||
lapack_int
|
||||
FirstOrder::order_eigs(const double *alphar, const double *alphai, const double *beta)
|
||||
FirstOrder::order_eigs(const double* alphar, const double* alphai, const double* beta)
|
||||
{
|
||||
return (*alphar **alphar + *alphai **alphai < *beta **beta * qz_criterium_global * qz_criterium_global);
|
||||
return (*alphar * *alphar + *alphai * *alphai
|
||||
< *beta * *beta * qz_criterium_global * qz_criterium_global);
|
||||
}
|
||||
|
||||
/* Here we solve the linear approximation. The result are the matrices
|
||||
|
@ -49,7 +50,7 @@ FirstOrder::order_eigs(const double *alphar, const double *alphai, const double
|
|||
and partitioning of the vector y (from object). */
|
||||
|
||||
void
|
||||
FirstOrder::solve(const TwoDMatrix &fd)
|
||||
FirstOrder::solve(const TwoDMatrix& fd)
|
||||
{
|
||||
JournalRecordPair pa(journal);
|
||||
pa << "Recovering first order derivatives " << endrec;
|
||||
|
@ -144,14 +145,14 @@ FirstOrder::solve(const TwoDMatrix &fd)
|
|||
off += nu;
|
||||
|
||||
// Form matrix D
|
||||
lapack_int n = ypart.ny()+ypart.nboth;
|
||||
lapack_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);
|
||||
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;
|
||||
matD.get(ypart.ny() + i, ypart.npred + i) = 1.0;
|
||||
lapack_int ldb = matD.getLD();
|
||||
|
||||
// Form matrix E
|
||||
|
@ -159,9 +160,9 @@ FirstOrder::solve(const TwoDMatrix &fd)
|
|||
matE.zeros();
|
||||
matE.place(fymins, 0, 0);
|
||||
matE.place(fyszero, 0, ypart.nys());
|
||||
matE.place(fyfzero, 0, ypart.nys()+ypart.nstat+ypart.nboth);
|
||||
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.get(ypart.ny() + i, ypart.nys() + ypart.nstat + i) = -1.0;
|
||||
matE.mult(-1.0);
|
||||
lapack_int lda = matE.getLD();
|
||||
|
||||
|
@ -169,30 +170,28 @@ FirstOrder::solve(const TwoDMatrix &fd)
|
|||
TwoDMatrix vsl(n, n);
|
||||
TwoDMatrix vsr(n, n);
|
||||
lapack_int ldvsl = vsl.getLD(), ldvsr = vsr.getLD();
|
||||
lapack_int lwork = 100*n+16;
|
||||
lapack_int lwork = 100 * n + 16;
|
||||
Vector work(lwork);
|
||||
auto bwork = std::make_unique<lapack_int[]>(n);
|
||||
lapack_int info;
|
||||
lapack_int sdim2 = sdim;
|
||||
{
|
||||
std::lock_guard<std::mutex> lk{mut};
|
||||
std::lock_guard<std::mutex> lk {mut};
|
||||
qz_criterium_global = qz_criterium;
|
||||
dgges("N", "V", "S", order_eigs, &n, matE.getData().base(), &lda,
|
||||
matD.getData().base(), &ldb, &sdim2, alphar.base(), alphai.base(),
|
||||
beta.base(), vsl.getData().base(), &ldvsl, vsr.getData().base(), &ldvsr,
|
||||
work.base(), &lwork, bwork.get(), &info);
|
||||
dgges("N", "V", "S", order_eigs, &n, matE.getData().base(), &lda, matD.getData().base(), &ldb,
|
||||
&sdim2, alphar.base(), alphai.base(), beta.base(), vsl.getData().base(), &ldvsl,
|
||||
vsr.getData().base(), &ldvsr, work.base(), &lwork, bwork.get(), &info);
|
||||
}
|
||||
if (info)
|
||||
throw KordException(__FILE__, __LINE__,
|
||||
"DGGES returns an error in FirstOrder::solve");
|
||||
throw KordException(__FILE__, __LINE__, "DGGES returns an error in FirstOrder::solve");
|
||||
sdim = sdim2;
|
||||
bk_cond = (sdim == ypart.nys());
|
||||
|
||||
// Setup submatrices of Z
|
||||
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());
|
||||
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());
|
||||
|
||||
// Calculate derivatives of static and forward
|
||||
/* Here we calculate X=−Z₂₂⁻ᵀZ₁₂ᵀ, where X is ‘sfder’ in the code. */
|
||||
|
@ -214,11 +213,12 @@ FirstOrder::solve(const TwoDMatrix &fd)
|
|||
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);
|
||||
GeneralMatrix fder(sfder, ypart.nstat + ypart.nboth, 0, ypart.nforw, ypart.nys());
|
||||
gy.place(fder, ypart.nstat + ypart.nys(), 0);
|
||||
|
||||
// Check difference for derivatives of both
|
||||
GeneralMatrix bder(const_cast<const GeneralMatrix &>(sfder), ypart.nstat, 0, ypart.nboth, ypart.nys());
|
||||
GeneralMatrix bder(const_cast<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();
|
||||
|
@ -237,7 +237,7 @@ FirstOrder::solve(const TwoDMatrix &fd)
|
|||
is ‘matA’ in the code. */
|
||||
GeneralMatrix matA(ypart.ny(), ypart.ny());
|
||||
matA.zeros();
|
||||
ConstGeneralMatrix gss(gy, ypart.nstat+ypart.npred, 0, ypart.nyss(), ypart.nys());
|
||||
ConstGeneralMatrix gss(gy, ypart.nstat + ypart.npred, 0, ypart.nyss(), ypart.nys());
|
||||
matA.place(fyplus * gss, 0, ypart.nstat);
|
||||
ConstGeneralMatrix fyzero(fd, 0, ypart.nyss(), ypart.ny(), ypart.ny());
|
||||
matA.add(1.0, fyzero);
|
||||
|
@ -247,9 +247,7 @@ FirstOrder::solve(const TwoDMatrix &fd)
|
|||
|
||||
journalEigs();
|
||||
|
||||
KORD_RAISE_IF_X(!bk_cond,
|
||||
"The model is not Blanchard-Kahn stable",
|
||||
KORD_MD_NOT_STABLE);
|
||||
KORD_RAISE_IF_X(!bk_cond, "The model is not Blanchard-Kahn stable", KORD_MD_NOT_STABLE);
|
||||
if (!gy.isFinite() || !gu.isFinite())
|
||||
throw KordException(__FILE__, __LINE__,
|
||||
"NaN or Inf asserted in first order derivatives in FirstOrder::solve()");
|
||||
|
@ -283,9 +281,9 @@ FirstOrder::journalEigs()
|
|||
jr << endrec;
|
||||
}
|
||||
JournalRecord jr(journal);
|
||||
double mod = std::sqrt(alphar[i]*alphar[i]+alphai[i]*alphai[i]);
|
||||
mod = mod/std::round(100000*std::abs(beta[i]))*100000;
|
||||
jr << i << "\t(" << alphar[i] << "," << alphai[i] << ") / " << beta[i]
|
||||
<< " \t" << mod << endrec;
|
||||
double mod = std::sqrt(alphar[i] * alphar[i] + alphai[i] * alphai[i]);
|
||||
mod = mod / std::round(100000 * std::abs(beta[i])) * 100000;
|
||||
jr << i << "\t(" << alphar[i] << "," << alphai[i] << ") / " << beta[i] << " \t" << mod
|
||||
<< endrec;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,10 +44,10 @@ class FirstOrder
|
|||
Vector alphai;
|
||||
Vector beta;
|
||||
double qz_criterium;
|
||||
Journal &journal;
|
||||
Journal& journal;
|
||||
|
||||
// Passed to LAPACK's DGGES
|
||||
static lapack_int order_eigs(const double *alphar, const double *alphai, const double *beta);
|
||||
static lapack_int order_eigs(const double* alphar, const double* alphai, const double* beta);
|
||||
|
||||
// The value of qz_criterium_global used by the order_eigs function
|
||||
/* NB: we have no choice but to use a global variable, since LAPACK won't
|
||||
|
@ -56,33 +56,30 @@ class FirstOrder
|
|||
|
||||
// Protects the static qz_criterium_global
|
||||
static std::mutex mut;
|
||||
|
||||
public:
|
||||
FirstOrder(int num_stat, int num_pred, int num_both, int num_forw,
|
||||
int num_u, const FSSparseTensor &f, Journal &jr, double qz_crit)
|
||||
: 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),
|
||||
qz_criterium(qz_crit),
|
||||
FirstOrder(int num_stat, int num_pred, int num_both, int num_forw, int num_u,
|
||||
const FSSparseTensor& f, Journal& jr, double qz_crit) :
|
||||
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), qz_criterium(qz_crit),
|
||||
journal(jr)
|
||||
{
|
||||
solve(FFSTensor(f));
|
||||
}
|
||||
const TwoDMatrix &
|
||||
const TwoDMatrix&
|
||||
getGy() const
|
||||
{
|
||||
return gy;
|
||||
}
|
||||
const TwoDMatrix &
|
||||
const TwoDMatrix&
|
||||
getGu() const
|
||||
{
|
||||
return gu;
|
||||
}
|
||||
|
||||
protected:
|
||||
void solve(const TwoDMatrix &f);
|
||||
void solve(const TwoDMatrix& f);
|
||||
void journalEigs();
|
||||
};
|
||||
|
||||
|
@ -93,15 +90,16 @@ template<Storage t>
|
|||
class FirstOrderDerivs : public ctraits<t>::Tg
|
||||
{
|
||||
public:
|
||||
FirstOrderDerivs(const FirstOrder &fo)
|
||||
: ctraits<t>::Tg(4)
|
||||
FirstOrderDerivs(const FirstOrder& fo) : ctraits<t>::Tg(4)
|
||||
{
|
||||
IntSequence nvs{fo.ypart.nys(), fo.nu, fo.nu, 1};
|
||||
auto ten = std::make_unique<typename ctraits<t>::Ttensor>(fo.ypart.ny(), TensorDimens(Symmetry{1, 0, 0, 0}, nvs));
|
||||
IntSequence nvs {fo.ypart.nys(), fo.nu, fo.nu, 1};
|
||||
auto ten = std::make_unique<typename ctraits<t>::Ttensor>(
|
||||
fo.ypart.ny(), TensorDimens(Symmetry {1, 0, 0, 0}, nvs));
|
||||
ten->zeros();
|
||||
ten->add(1.0, fo.gy);
|
||||
this->insert(std::move(ten));
|
||||
ten = std::make_unique<typename ctraits<t>::Ttensor>(fo.ypart.ny(), TensorDimens(Symmetry{0, 1, 0, 0}, nvs));
|
||||
ten = std::make_unique<typename ctraits<t>::Ttensor>(fo.ypart.ny(),
|
||||
TensorDimens(Symmetry {0, 1, 0, 0}, nvs));
|
||||
ten->zeros();
|
||||
ten->add(1.0, fo.gu);
|
||||
this->insert(std::move(ten));
|
||||
|
|
|
@ -21,30 +21,31 @@
|
|||
#include "journal.hh"
|
||||
#include "kord_exception.hh"
|
||||
|
||||
#include <iomanip>
|
||||
#include <cmath>
|
||||
#include <ctime>
|
||||
#include <iomanip>
|
||||
#include <limits>
|
||||
#include <thread>
|
||||
|
||||
#ifndef _WIN32
|
||||
# include <sys/time.h> // For getrusage()
|
||||
# include <sys/resource.h> // For getrusage()
|
||||
# include <sys/utsname.h> // For uname()
|
||||
# include <cstdlib> // For getloadavg()
|
||||
# include <sys/resource.h> // For getrusage()
|
||||
# include <sys/time.h> // For getrusage()
|
||||
# include <sys/utsname.h> // For uname()
|
||||
# include <unistd.h> // For sysconf()
|
||||
# ifdef __APPLE__
|
||||
# include <sys/types.h>
|
||||
# include <sys/sysctl.h>
|
||||
# include <sys/types.h>
|
||||
# endif
|
||||
#else
|
||||
# ifndef NOMINMAX
|
||||
# define NOMINMAX // Do not define "min" and "max" macros
|
||||
# define NOMINMAX // Do not define "min" and "max" macros
|
||||
# endif
|
||||
# include <windows.h> // For GlobalMemoryStatus()
|
||||
# include <windows.h> // For GlobalMemoryStatus()
|
||||
#endif
|
||||
|
||||
const std::chrono::time_point<std::chrono::high_resolution_clock> SystemResources::start = std::chrono::high_resolution_clock::now();
|
||||
const std::chrono::time_point<std::chrono::high_resolution_clock> SystemResources::start
|
||||
= std::chrono::high_resolution_clock::now();
|
||||
|
||||
#ifndef _WIN32
|
||||
long
|
||||
|
@ -58,11 +59,11 @@ long
|
|||
SystemResources::availableMemory()
|
||||
{
|
||||
#if !defined(_WIN32) && !defined(__APPLE__)
|
||||
return sysconf(_SC_AVPHYS_PAGES)*pageSize();
|
||||
return sysconf(_SC_AVPHYS_PAGES) * pageSize();
|
||||
#elif defined(__APPLE__)
|
||||
unsigned long usermem = 0;
|
||||
size_t len = sizeof usermem;
|
||||
static int mib[2] = { CTL_HW, HW_USERMEM };
|
||||
static int mib[2] = {CTL_HW, HW_USERMEM};
|
||||
int retval = sysctl(mib, 2, &usermem, &len, NULL, 0);
|
||||
if (retval == 0)
|
||||
return static_cast<long>(usermem);
|
||||
|
@ -83,8 +84,8 @@ SystemResources::SystemResources()
|
|||
#ifndef _WIN32
|
||||
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;
|
||||
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 * pageSize();
|
||||
#else
|
||||
|
@ -104,7 +105,7 @@ SystemResources::SystemResources()
|
|||
}
|
||||
|
||||
void
|
||||
SystemResources::diff(const SystemResources &pre)
|
||||
SystemResources::diff(const SystemResources& pre)
|
||||
{
|
||||
utime -= pre.utime;
|
||||
stime -= pre.stime;
|
||||
|
@ -114,14 +115,14 @@ SystemResources::diff(const SystemResources &pre)
|
|||
}
|
||||
|
||||
// JournalRecord::operator<<() symmetry code
|
||||
JournalRecord &
|
||||
JournalRecord::operator<<(const IntSequence &s)
|
||||
JournalRecord&
|
||||
JournalRecord::operator<<(const IntSequence& s)
|
||||
{
|
||||
operator<<('[');
|
||||
for (int i = 0; i < s.size(); i++)
|
||||
{
|
||||
operator<<(s[i]);
|
||||
if (i < s.size()-1)
|
||||
if (i < s.size() - 1)
|
||||
operator<<(',');
|
||||
}
|
||||
operator<<(']');
|
||||
|
@ -129,49 +130,49 @@ JournalRecord::operator<<(const IntSequence &s)
|
|||
}
|
||||
|
||||
void
|
||||
JournalRecord::writeFloatTabular(std::ostream &s, double d, int width)
|
||||
JournalRecord::writeFloatTabular(std::ostream& s, double d, int width)
|
||||
{
|
||||
// Number of digits of integer part
|
||||
int intdigits = std::max(static_cast<int>(std::floor(log10(d))+1), 1);
|
||||
int intdigits = std::max(static_cast<int>(std::floor(log10(d)) + 1), 1);
|
||||
|
||||
int prec = std::max(width - 1 - intdigits, 0);
|
||||
s << std::fixed << std::setw(width) << std::setprecision(prec) << d;
|
||||
}
|
||||
|
||||
void
|
||||
JournalRecord::writePrefix(const SystemResources &f)
|
||||
JournalRecord::writePrefix(const SystemResources& f)
|
||||
{
|
||||
constexpr double mb = 1024*1024;
|
||||
constexpr double mb = 1024 * 1024;
|
||||
std::ostringstream s;
|
||||
s << std::setfill('0');
|
||||
writeFloatTabular(s, f.elapsed, 7);
|
||||
s << "│" << recChar << std::setw(5) << ord << "│";
|
||||
writeFloatTabular(s, f.load_avg, 3);
|
||||
s << "│";
|
||||
writeFloatTabular(s, f.mem_avail/mb, 5);
|
||||
writeFloatTabular(s, f.mem_avail / mb, 5);
|
||||
s << "│ │ ";
|
||||
for (int i = 0; i < 2*journal.getDepth(); i++)
|
||||
for (int i = 0; i < 2 * journal.getDepth(); i++)
|
||||
s << ' ';
|
||||
prefix = s.str();
|
||||
}
|
||||
|
||||
void
|
||||
JournalRecordPair::writePrefixForEnd(const SystemResources &f)
|
||||
JournalRecordPair::writePrefixForEnd(const SystemResources& f)
|
||||
{
|
||||
constexpr double mb = 1024*1024;
|
||||
constexpr double mb = 1024 * 1024;
|
||||
SystemResources difnow;
|
||||
difnow.diff(f);
|
||||
std::ostringstream s;
|
||||
s << std::setfill('0');
|
||||
writeFloatTabular(s, f.elapsed+difnow.elapsed, 7);
|
||||
writeFloatTabular(s, f.elapsed + difnow.elapsed, 7);
|
||||
s << "│E" << std::setw(5) << ord << "│";
|
||||
writeFloatTabular(s, difnow.load_avg, 3);
|
||||
s << "│";
|
||||
writeFloatTabular(s, difnow.mem_avail/mb, 5);
|
||||
writeFloatTabular(s, difnow.mem_avail / mb, 5);
|
||||
s << "│";
|
||||
writeFloatTabular(s, difnow.majflt/mb, 6);
|
||||
writeFloatTabular(s, difnow.majflt / mb, 6);
|
||||
s << "│ ";
|
||||
for (int i = 0; i < 2*journal.getDepth(); i++)
|
||||
for (int i = 0; i < 2 * journal.getDepth(); i++)
|
||||
s << ' ';
|
||||
prefix_end = s.str();
|
||||
}
|
||||
|
@ -186,8 +187,8 @@ JournalRecordPair::~JournalRecordPair()
|
|||
journal.flush();
|
||||
}
|
||||
|
||||
JournalRecord &
|
||||
endrec(JournalRecord &rec)
|
||||
JournalRecord&
|
||||
endrec(JournalRecord& rec)
|
||||
{
|
||||
rec.journal << rec.prefix;
|
||||
rec.journal << rec.mes;
|
||||
|
@ -200,19 +201,15 @@ endrec(JournalRecord &rec)
|
|||
void
|
||||
Journal::printHeader()
|
||||
{
|
||||
*this << "Dynare, version " << PACKAGE_VERSION << '\n'
|
||||
<< '\n'
|
||||
<< "System info: ";
|
||||
*this << "Dynare, version " << PACKAGE_VERSION << '\n' << '\n' << "System info: ";
|
||||
#ifndef _WIN32
|
||||
utsname info;
|
||||
uname(&info);
|
||||
*this << info.sysname << " " << info.release << " " << info.version << " "
|
||||
<< info.machine;
|
||||
*this << info.sysname << " " << info.release << " " << info.version << " " << info.machine;
|
||||
#else
|
||||
*this << "Windows";
|
||||
#endif
|
||||
*this << ", processors online: " << std::thread::hardware_concurrency()
|
||||
<< "\n\nStart time: ";
|
||||
*this << ", processors online: " << std::thread::hardware_concurrency() << "\n\nStart time: ";
|
||||
std::time_t t = std::time(nullptr);
|
||||
// NB: in the date/time string, we avoid using locale-specific strings (#1751)
|
||||
*this << std::put_time(std::localtime(&t),
|
||||
|
|
|
@ -25,11 +25,11 @@
|
|||
|
||||
#include "int_sequence.hh"
|
||||
|
||||
#include <chrono>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <chrono>
|
||||
|
||||
/* Implement static methods for accessing some system resources. An instance of
|
||||
this class is a photograph of these resources at the time of instantiation. */
|
||||
|
@ -52,23 +52,23 @@ struct SystemResources
|
|||
long majflt;
|
||||
|
||||
SystemResources();
|
||||
void diff(const SystemResources &pre);
|
||||
void diff(const SystemResources& pre);
|
||||
};
|
||||
|
||||
class Journal : public std::ofstream
|
||||
{
|
||||
int ord{0};
|
||||
int depth{0};
|
||||
int ord {0};
|
||||
int depth {0};
|
||||
|
||||
public:
|
||||
explicit Journal(const std::string &fname)
|
||||
: std::ofstream(fname)
|
||||
explicit Journal(const std::string& fname) : std::ofstream(fname)
|
||||
{
|
||||
printHeader();
|
||||
}
|
||||
/* Constructor that does not initialize the std::ofstream. To be used when an
|
||||
on-disk journal is not wanted. */
|
||||
Journal() = default;
|
||||
Journal &operator=(Journal &&) = default;
|
||||
Journal& operator=(Journal&&) = default;
|
||||
~Journal() override
|
||||
{
|
||||
flush();
|
||||
|
@ -102,63 +102,64 @@ public:
|
|||
};
|
||||
|
||||
class JournalRecord;
|
||||
JournalRecord &endrec(JournalRecord &);
|
||||
JournalRecord& endrec(JournalRecord&);
|
||||
|
||||
class JournalRecord
|
||||
{
|
||||
protected:
|
||||
char recChar;
|
||||
int ord;
|
||||
|
||||
public:
|
||||
Journal &journal;
|
||||
Journal& journal;
|
||||
std::string prefix;
|
||||
std::string mes;
|
||||
SystemResources flash;
|
||||
using _Tfunc = JournalRecord &(*)(JournalRecord &);
|
||||
using _Tfunc = JournalRecord& (*)(JournalRecord&);
|
||||
|
||||
explicit JournalRecord(Journal &jr, char rc = 'M')
|
||||
: recChar(rc), ord(jr.getOrd()), journal(jr)
|
||||
explicit JournalRecord(Journal& jr, char rc = 'M') : recChar(rc), ord(jr.getOrd()), journal(jr)
|
||||
{
|
||||
writePrefix(flash);
|
||||
}
|
||||
virtual ~JournalRecord() = default;
|
||||
JournalRecord &operator<<(const IntSequence &s);
|
||||
JournalRecord &
|
||||
JournalRecord& operator<<(const IntSequence& s);
|
||||
JournalRecord&
|
||||
operator<<(_Tfunc f)
|
||||
{
|
||||
(*f)(*this);
|
||||
return *this;
|
||||
}
|
||||
JournalRecord &
|
||||
JournalRecord&
|
||||
operator<<(char c)
|
||||
{
|
||||
mes += c;
|
||||
return *this;
|
||||
}
|
||||
JournalRecord &
|
||||
operator<<(const std::string &s)
|
||||
JournalRecord&
|
||||
operator<<(const std::string& s)
|
||||
{
|
||||
mes += s;
|
||||
return *this;
|
||||
}
|
||||
JournalRecord &
|
||||
JournalRecord&
|
||||
operator<<(int i)
|
||||
{
|
||||
mes += std::to_string(i);
|
||||
return *this;
|
||||
}
|
||||
JournalRecord &
|
||||
JournalRecord&
|
||||
operator<<(double d)
|
||||
{
|
||||
mes += std::to_string(d);
|
||||
return *this;
|
||||
}
|
||||
|
||||
protected:
|
||||
void writePrefix(const SystemResources &f);
|
||||
void writePrefix(const SystemResources& f);
|
||||
/* Writes a floating point number as a field of exactly ‘width’ characters
|
||||
large. Note that the width will not be respected if the integer part is
|
||||
too large. */
|
||||
static void writeFloatTabular(std::ostream &s, double d, int width);
|
||||
static void writeFloatTabular(std::ostream& s, double d, int width);
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -170,15 +171,16 @@ protected:
|
|||
class JournalRecordPair : public JournalRecord
|
||||
{
|
||||
std::string prefix_end;
|
||||
|
||||
public:
|
||||
explicit JournalRecordPair(Journal &jr)
|
||||
: JournalRecord(jr, 'S')
|
||||
explicit JournalRecordPair(Journal& jr) : JournalRecord(jr, 'S')
|
||||
{
|
||||
journal.incrementDepth();
|
||||
}
|
||||
~JournalRecordPair() override;
|
||||
|
||||
private:
|
||||
void writePrefixForEnd(const SystemResources &f);
|
||||
void writePrefixForEnd(const SystemResources& f);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -22,23 +22,23 @@
|
|||
|
||||
/* This is a simple code defining an exception and two convenience macros. */
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#ifndef KORD_EXCEPTION_H
|
||||
# define KORD_EXCEPTION_H
|
||||
|
||||
# define KORD_RAISE(mes) \
|
||||
throw KordException(__FILE__, __LINE__, mes);
|
||||
# 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_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_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);
|
||||
# define KORD_RAISE_IF_X(expr, mes, c) \
|
||||
if (expr) \
|
||||
throw KordException(__FILE__, __LINE__, mes, c);
|
||||
|
||||
class KordException
|
||||
{
|
||||
|
@ -47,9 +47,10 @@ protected:
|
|||
int lnum;
|
||||
std::string message;
|
||||
int cd;
|
||||
|
||||
public:
|
||||
KordException(std::string f, int l, std::string mes, int c = 255)
|
||||
: fname{std::move(f)}, lnum{l}, message{std::move(mes)}, cd{c}
|
||||
KordException(std::string f, int l, std::string mes, int c = 255) :
|
||||
fname {std::move(f)}, lnum {l}, message {std::move(mes)}, cd {c}
|
||||
{
|
||||
}
|
||||
virtual ~KordException() = default;
|
||||
|
@ -63,7 +64,7 @@ public:
|
|||
{
|
||||
return cd;
|
||||
}
|
||||
const std::string &
|
||||
const std::string&
|
||||
get_message() const
|
||||
{
|
||||
return message;
|
||||
|
|
|
@ -18,8 +18,8 @@
|
|||
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "kord_exception.hh"
|
||||
#include "korder.hh"
|
||||
#include "kord_exception.hh"
|
||||
|
||||
/* Here we set ‘ipiv’ and ‘inv’ members of the PLUMatrix depending on its
|
||||
content. It is assumed that subclasses will call this method at the end of
|
||||
|
@ -30,26 +30,23 @@ PLUMatrix::calcPLU()
|
|||
{
|
||||
lapack_int info;
|
||||
lapack_int rows = nrows(), lda = ld;
|
||||
inv = const_cast<const Vector &>(getData());
|
||||
inv = const_cast<const Vector&>(getData());
|
||||
dgetrf(&rows, &rows, inv.base(), &lda, ipiv.data(), &info);
|
||||
}
|
||||
|
||||
/* Here we just call the LAPACK machinery to multiply by the inverse. */
|
||||
|
||||
void
|
||||
PLUMatrix::multInv(TwoDMatrix &m) const
|
||||
PLUMatrix::multInv(TwoDMatrix& m) const
|
||||
{
|
||||
KORD_RAISE_IF(m.nrows() != ncols(),
|
||||
"The matrix is not square in PLUMatrix::multInv");
|
||||
KORD_RAISE_IF(m.nrows() != ncols(), "The matrix is not square in PLUMatrix::multInv");
|
||||
lapack_int info;
|
||||
lapack_int lda = ld;
|
||||
lapack_int mcols = m.ncols();
|
||||
lapack_int mrows = m.nrows();
|
||||
lapack_int ldb = m.getLD();
|
||||
dgetrs("N", &mrows, &mcols, inv.base(), &lda, ipiv.data(),
|
||||
m.getData().base(), &ldb, &info);
|
||||
KORD_RAISE_IF(info != 0,
|
||||
"Info!=0 in PLUMatrix::multInv");
|
||||
dgetrs("N", &mrows, &mcols, inv.base(), &lda, ipiv.data(), m.getData().base(), &ldb, &info);
|
||||
KORD_RAISE_IF(info != 0, "Info!=0 in PLUMatrix::multInv");
|
||||
}
|
||||
|
||||
/* Here we construct the matrix A. Its dimension is ‘ny’, and it is
|
||||
|
@ -59,17 +56,17 @@ PLUMatrix::multInv(TwoDMatrix &m) const
|
|||
where the first zero spans ‘nstat’ columns, and last zero spans ‘nforw’
|
||||
columns. */
|
||||
|
||||
MatrixA::MatrixA(const FSSparseTensor &f, const IntSequence &ss,
|
||||
const TwoDMatrix &gy, const PartitionY &ypart)
|
||||
: PLUMatrix(ypart.ny())
|
||||
MatrixA::MatrixA(const FSSparseTensor& f, const IntSequence& ss, const TwoDMatrix& gy,
|
||||
const PartitionY& ypart) :
|
||||
PLUMatrix(ypart.ny())
|
||||
{
|
||||
zeros();
|
||||
|
||||
IntSequence c{1};
|
||||
IntSequence c {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);
|
||||
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());
|
||||
|
@ -85,23 +82,23 @@ MatrixA::MatrixA(const FSSparseTensor &f, const IntSequence &ss,
|
|||
It is, in fact, the matrix A plus the third summand. The first zero in the
|
||||
summand spans ‘nstat’ columns, the second zero spans ‘npred’ columns. */
|
||||
|
||||
MatrixS::MatrixS(const FSSparseTensor &f, const IntSequence &ss,
|
||||
const TwoDMatrix &gy, const PartitionY &ypart)
|
||||
: PLUMatrix(ypart.ny())
|
||||
MatrixS::MatrixS(const FSSparseTensor& f, const IntSequence& ss, const TwoDMatrix& gy,
|
||||
const PartitionY& ypart) :
|
||||
PLUMatrix(ypart.ny())
|
||||
{
|
||||
zeros();
|
||||
|
||||
IntSequence c{1};
|
||||
IntSequence c {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);
|
||||
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());
|
||||
TwoDMatrix sub2(*this, ypart.nstat + ypart.npred, ypart.nyss());
|
||||
sub2.add(1.0, f_yss);
|
||||
|
||||
calcPLU();
|
||||
|
@ -112,169 +109,169 @@ MatrixS::MatrixS(const FSSparseTensor &f, const IntSequence &ss,
|
|||
interesting here. */
|
||||
|
||||
template<>
|
||||
ctraits<Storage::unfold>::Tg &
|
||||
ctraits<Storage::unfold>::Tg&
|
||||
KOrder::g<Storage::unfold>()
|
||||
{
|
||||
return _ug;
|
||||
}
|
||||
template<>
|
||||
const ctraits<Storage::unfold>::Tg &
|
||||
const ctraits<Storage::unfold>::Tg&
|
||||
KOrder::g<Storage::unfold>() const
|
||||
{
|
||||
return _ug;
|
||||
}
|
||||
template<>
|
||||
ctraits<Storage::fold>::Tg &
|
||||
ctraits<Storage::fold>::Tg&
|
||||
KOrder::g<Storage::fold>()
|
||||
{
|
||||
return _fg;
|
||||
}
|
||||
template<>
|
||||
const ctraits<Storage::fold>::Tg &
|
||||
const ctraits<Storage::fold>::Tg&
|
||||
KOrder::g<Storage::fold>() const
|
||||
{
|
||||
return _fg;
|
||||
}
|
||||
template<>
|
||||
ctraits<Storage::unfold>::Tgs &
|
||||
ctraits<Storage::unfold>::Tgs&
|
||||
KOrder::gs<Storage::unfold>()
|
||||
{
|
||||
return _ugs;
|
||||
}
|
||||
template<>
|
||||
const ctraits<Storage::unfold>::Tgs &
|
||||
const ctraits<Storage::unfold>::Tgs&
|
||||
KOrder::gs<Storage::unfold>() const
|
||||
{
|
||||
return _ugs;
|
||||
}
|
||||
template<>
|
||||
ctraits<Storage::fold>::Tgs &
|
||||
ctraits<Storage::fold>::Tgs&
|
||||
KOrder::gs<Storage::fold>()
|
||||
{
|
||||
return _fgs;
|
||||
}
|
||||
template<>
|
||||
const ctraits<Storage::fold>::Tgs &
|
||||
const ctraits<Storage::fold>::Tgs&
|
||||
KOrder::gs<Storage::fold>() const
|
||||
{
|
||||
return _fgs;
|
||||
}
|
||||
template<>
|
||||
ctraits<Storage::unfold>::Tgss &
|
||||
ctraits<Storage::unfold>::Tgss&
|
||||
KOrder::gss<Storage::unfold>()
|
||||
{
|
||||
return _ugss;
|
||||
}
|
||||
template<>
|
||||
const ctraits<Storage::unfold>::Tgss &
|
||||
const ctraits<Storage::unfold>::Tgss&
|
||||
KOrder::gss<Storage::unfold>() const
|
||||
{
|
||||
return _ugss;
|
||||
}
|
||||
template<>
|
||||
ctraits<Storage::fold>::Tgss &
|
||||
ctraits<Storage::fold>::Tgss&
|
||||
KOrder::gss<Storage::fold>()
|
||||
{
|
||||
return _fgss;
|
||||
}
|
||||
template<>
|
||||
const ctraits<Storage::fold>::Tgss &
|
||||
const ctraits<Storage::fold>::Tgss&
|
||||
KOrder::gss<Storage::fold>() const
|
||||
{
|
||||
return _fgss;
|
||||
}
|
||||
template<>
|
||||
ctraits<Storage::unfold>::TG &
|
||||
ctraits<Storage::unfold>::TG&
|
||||
KOrder::G<Storage::unfold>()
|
||||
{
|
||||
return _uG;
|
||||
}
|
||||
template<>
|
||||
const ctraits<Storage::unfold>::TG &
|
||||
const ctraits<Storage::unfold>::TG&
|
||||
KOrder::G<Storage::unfold>() const
|
||||
{
|
||||
return _uG;
|
||||
}
|
||||
template<>
|
||||
ctraits<Storage::fold>::TG &
|
||||
ctraits<Storage::fold>::TG&
|
||||
KOrder::G<Storage::fold>()
|
||||
{
|
||||
return _fG;
|
||||
}
|
||||
template<>
|
||||
const ctraits<Storage::fold>::TG &
|
||||
const ctraits<Storage::fold>::TG&
|
||||
KOrder::G<Storage::fold>() const
|
||||
{
|
||||
return _fG;
|
||||
}
|
||||
template<>
|
||||
ctraits<Storage::unfold>::TZstack &
|
||||
ctraits<Storage::unfold>::TZstack&
|
||||
KOrder::Zstack<Storage::unfold>()
|
||||
{
|
||||
return _uZstack;
|
||||
}
|
||||
template<>
|
||||
const ctraits<Storage::unfold>::TZstack &
|
||||
const ctraits<Storage::unfold>::TZstack&
|
||||
KOrder::Zstack<Storage::unfold>() const
|
||||
{
|
||||
return _uZstack;
|
||||
}
|
||||
template<>
|
||||
ctraits<Storage::fold>::TZstack &
|
||||
ctraits<Storage::fold>::TZstack&
|
||||
KOrder::Zstack<Storage::fold>()
|
||||
{
|
||||
return _fZstack;
|
||||
}
|
||||
template<>
|
||||
const ctraits<Storage::fold>::TZstack &
|
||||
const ctraits<Storage::fold>::TZstack&
|
||||
KOrder::Zstack<Storage::fold>() const
|
||||
{
|
||||
return _fZstack;
|
||||
}
|
||||
template<>
|
||||
ctraits<Storage::unfold>::TGstack &
|
||||
ctraits<Storage::unfold>::TGstack&
|
||||
KOrder::Gstack<Storage::unfold>()
|
||||
{
|
||||
return _uGstack;
|
||||
}
|
||||
template<>
|
||||
const ctraits<Storage::unfold>::TGstack &
|
||||
const ctraits<Storage::unfold>::TGstack&
|
||||
KOrder::Gstack<Storage::unfold>() const
|
||||
{
|
||||
return _uGstack;
|
||||
}
|
||||
template<>
|
||||
ctraits<Storage::fold>::TGstack &
|
||||
ctraits<Storage::fold>::TGstack&
|
||||
KOrder::Gstack<Storage::fold>()
|
||||
{
|
||||
return _fGstack;
|
||||
}
|
||||
template<>
|
||||
const ctraits<Storage::fold>::TGstack &
|
||||
const ctraits<Storage::fold>::TGstack&
|
||||
KOrder::Gstack<Storage::fold>() const
|
||||
{
|
||||
return _fGstack;
|
||||
}
|
||||
template<>
|
||||
ctraits<Storage::unfold>::Tm &
|
||||
ctraits<Storage::unfold>::Tm&
|
||||
KOrder::m<Storage::unfold>()
|
||||
{
|
||||
return _um;
|
||||
}
|
||||
template<>
|
||||
const ctraits<Storage::unfold>::Tm &
|
||||
const ctraits<Storage::unfold>::Tm&
|
||||
KOrder::m<Storage::unfold>() const
|
||||
{
|
||||
return _um;
|
||||
}
|
||||
template<>
|
||||
ctraits<Storage::fold>::Tm &
|
||||
ctraits<Storage::fold>::Tm&
|
||||
KOrder::m<Storage::fold>()
|
||||
{
|
||||
return _fm;
|
||||
}
|
||||
template<>
|
||||
const ctraits<Storage::fold>::Tm &
|
||||
const ctraits<Storage::fold>::Tm&
|
||||
KOrder::m<Storage::fold>() const
|
||||
{
|
||||
return _fm;
|
||||
|
@ -293,56 +290,43 @@ KOrder::m<Storage::fold>() const
|
|||
to comply to preconditions of performStep(). */
|
||||
|
||||
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{ypart.nys(), nu, nu, 1},
|
||||
_ug(4), _fg(4), _ugs(4), _fgs(4), _ugss(4), _fgss(4),
|
||||
_uG(4), _fG(4),
|
||||
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 {ypart.nys(), nu, nu, 1}, _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)
|
||||
_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 constructor");
|
||||
KORD_RAISE_IF(gu.ncols() != nu,
|
||||
"Wrong number of columns in gu in KOrder constructor");
|
||||
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 constructor");
|
||||
KORD_RAISE_IF(gu.ncols() != nu, "Wrong number of columns in gu in KOrder constructor");
|
||||
|
||||
// Put g_y and gᵤ in the container
|
||||
/* Note that g_σ is zero by construction and we do not insert it to the
|
||||
container. We insert a new physical copies. */
|
||||
auto tgy = std::make_unique<UGSTensor>(ny, TensorDimens(Symmetry{1, 0, 0, 0}, nvs));
|
||||
auto tgy = std::make_unique<UGSTensor>(ny, TensorDimens(Symmetry {1, 0, 0, 0}, nvs));
|
||||
tgy->getData() = gy.getData();
|
||||
insertDerivative<Storage::unfold>(std::move(tgy));
|
||||
auto tgu = std::make_unique<UGSTensor>(ny, TensorDimens(Symmetry{0, 1, 0, 0}, nvs));
|
||||
auto tgu = std::make_unique<UGSTensor>(ny, TensorDimens(Symmetry {0, 1, 0, 0}, nvs));
|
||||
tgu->getData() = gu.getData();
|
||||
insertDerivative<Storage::unfold>(std::move(tgu));
|
||||
|
||||
// Put G_y, G_u and G_u′ in the container
|
||||
/* Also note that since g_σ is zero, so is G_σ. */
|
||||
auto tGy = faaDiBrunoG<Storage::unfold>(Symmetry{1, 0, 0, 0});
|
||||
auto tGy = faaDiBrunoG<Storage::unfold>(Symmetry {1, 0, 0, 0});
|
||||
G<Storage::unfold>().insert(std::move(tGy));
|
||||
auto tGu = faaDiBrunoG<Storage::unfold>(Symmetry{0, 1, 0, 0});
|
||||
auto tGu = faaDiBrunoG<Storage::unfold>(Symmetry {0, 1, 0, 0});
|
||||
G<Storage::unfold>().insert(std::move(tGu));
|
||||
auto tGup = faaDiBrunoG<Storage::unfold>(Symmetry{0, 0, 1, 0});
|
||||
auto tGup = faaDiBrunoG<Storage::unfold>(Symmetry {0, 0, 1, 0});
|
||||
G<Storage::unfold>().insert(std::move(tGup));
|
||||
}
|
||||
|
||||
|
@ -361,19 +345,16 @@ KOrder::KOrder(int num_stat, int num_pred, int num_both, int num_forw,
|
|||
|
||||
template<>
|
||||
void
|
||||
KOrder::sylvesterSolve<Storage::unfold>(ctraits<Storage::unfold>::Ttensor &der) const
|
||||
KOrder::sylvesterSolve<Storage::unfold>(ctraits<Storage::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<Storage::unfold>().get(Symmetry{1, 0, 0, 0}));
|
||||
GeneralSylvester sylv(der.getSym()[0], ny, ypart.nys(),
|
||||
ypart.nstat+ypart.npred,
|
||||
matA.getData(), matB.getData(),
|
||||
gs_y.getData(), der.getData());
|
||||
KORD_RAISE_IF(!der.isFinite(), "RHS of Sylverster is not finite");
|
||||
TwoDMatrix gs_y(gs<Storage::unfold>().get(Symmetry {1, 0, 0, 0}));
|
||||
GeneralSylvester sylv(der.getSym()[0], ny, ypart.nys(), ypart.nstat + ypart.npred,
|
||||
matA.getData(), matB.getData(), gs_y.getData(), der.getData());
|
||||
sylv.solve();
|
||||
}
|
||||
else if (ypart.nys() > 0 && ypart.nyss() == 0)
|
||||
|
@ -387,12 +368,12 @@ KOrder::sylvesterSolve<Storage::unfold>(ctraits<Storage::unfold>::Ttensor &der)
|
|||
|
||||
template<>
|
||||
void
|
||||
KOrder::sylvesterSolve<Storage::fold>(ctraits<Storage::fold>::Ttensor &der) const
|
||||
KOrder::sylvesterSolve<Storage::fold>(ctraits<Storage::fold>::Ttensor& der) const
|
||||
{
|
||||
ctraits<Storage::unfold>::Ttensor tmp(der);
|
||||
sylvesterSolve<Storage::unfold>(tmp);
|
||||
ctraits<Storage::fold>::Ttensor ftmp(tmp);
|
||||
der.getData() = const_cast<const Vector &>(ftmp.getData());
|
||||
der.getData() = const_cast<const Vector&>(ftmp.getData());
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -403,7 +384,7 @@ KOrder::switchToFolded()
|
|||
|
||||
int maxdim = g<Storage::unfold>().getMaxDim();
|
||||
for (int dim = 1; dim <= maxdim; dim++)
|
||||
for (auto &si : SymmetrySet(dim, 4))
|
||||
for (auto& si : SymmetrySet(dim, 4))
|
||||
{
|
||||
if (si[2] == 0 && g<Storage::unfold>().check(si))
|
||||
{
|
||||
|
|
|
@ -41,19 +41,19 @@
|
|||
#ifndef KORDER_H
|
||||
#define KORDER_H
|
||||
|
||||
#include "int_sequence.hh"
|
||||
#include "faa_di_bruno.hh"
|
||||
#include "fs_tensor.hh"
|
||||
#include "gs_tensor.hh"
|
||||
#include "t_container.hh"
|
||||
#include "stack_container.hh"
|
||||
#include "normal_moments.hh"
|
||||
#include "t_polynomial.hh"
|
||||
#include "faa_di_bruno.hh"
|
||||
#include "int_sequence.hh"
|
||||
#include "journal.hh"
|
||||
#include "normal_moments.hh"
|
||||
#include "pascal_triangle.hh"
|
||||
#include "stack_container.hh"
|
||||
#include "t_container.hh"
|
||||
#include "t_polynomial.hh"
|
||||
|
||||
#include "kord_exception.hh"
|
||||
#include "GeneralSylvester.hh"
|
||||
#include "kord_exception.hh"
|
||||
|
||||
#include <dynlapack.h>
|
||||
|
||||
|
@ -61,7 +61,11 @@
|
|||
#include <type_traits>
|
||||
|
||||
// The enum class passed as template parameter for many data structures
|
||||
enum class Storage { fold, unfold };
|
||||
enum class Storage
|
||||
{
|
||||
fold,
|
||||
unfold
|
||||
};
|
||||
|
||||
/* In ‘ctraits’ we define a number of types. We have a type for tensor Ttensor,
|
||||
and types for each pair of folded/unfolded containers used as a member in
|
||||
|
@ -90,8 +94,10 @@ public:
|
|||
using TGstack = std::conditional_t<type == Storage::fold, FoldedGContainer, UnfoldedGContainer>;
|
||||
using Tm = std::conditional_t<type == Storage::fold, FNormalMoments, UNormalMoments>;
|
||||
using Tpol = std::conditional_t<type == Storage::fold, FTensorPolynomial, UTensorPolynomial>;
|
||||
using TZXstack = std::conditional_t<type == Storage::fold, FoldedZXContainer, UnfoldedZXContainer>;
|
||||
using TGXstack = std::conditional_t<type == Storage::fold, FoldedGXContainer, UnfoldedGXContainer>;
|
||||
using TZXstack
|
||||
= std::conditional_t<type == Storage::fold, FoldedZXContainer, UnfoldedZXContainer>;
|
||||
using TGXstack
|
||||
= std::conditional_t<type == Storage::fold, FoldedGXContainer, UnfoldedGXContainer>;
|
||||
};
|
||||
|
||||
/* The PartitionY class defines the partitioning of state variables y. The
|
||||
|
@ -117,27 +123,27 @@ struct PartitionY
|
|||
const int npred;
|
||||
const int nboth;
|
||||
const int nforw;
|
||||
PartitionY() : PartitionY(0,0,0,0) {}
|
||||
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)
|
||||
PartitionY() : PartitionY(0, 0, 0, 0)
|
||||
{
|
||||
}
|
||||
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;
|
||||
return nstat + npred + nboth + nforw;
|
||||
}
|
||||
int
|
||||
nys() const
|
||||
{
|
||||
return npred+nboth;
|
||||
return npred + nboth;
|
||||
}
|
||||
int
|
||||
nyss() const
|
||||
{
|
||||
return nboth+nforw;
|
||||
return nboth + nforw;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -151,16 +157,15 @@ struct PartitionY
|
|||
class PLUMatrix : public TwoDMatrix
|
||||
{
|
||||
public:
|
||||
PLUMatrix(int n)
|
||||
: TwoDMatrix(n, n),
|
||||
inv(nrows()*ncols()),
|
||||
ipiv(nrows())
|
||||
PLUMatrix(int n) : TwoDMatrix(n, n), inv(nrows() * ncols()), ipiv(nrows())
|
||||
{
|
||||
}
|
||||
void multInv(TwoDMatrix &m) const;
|
||||
void multInv(TwoDMatrix& m) const;
|
||||
|
||||
private:
|
||||
Vector inv;
|
||||
std::vector<lapack_int> ipiv;
|
||||
|
||||
protected:
|
||||
void calcPLU();
|
||||
};
|
||||
|
@ -171,8 +176,8 @@ protected:
|
|||
class MatrixA : public PLUMatrix
|
||||
{
|
||||
public:
|
||||
MatrixA(const FSSparseTensor &f, const IntSequence &ss,
|
||||
const TwoDMatrix &gy, const PartitionY &ypart);
|
||||
MatrixA(const FSSparseTensor& f, const IntSequence& ss, const TwoDMatrix& gy,
|
||||
const PartitionY& ypart);
|
||||
};
|
||||
|
||||
/* The class MatrixS slightly differs from MatrixA. It is used for
|
||||
|
@ -182,8 +187,8 @@ public:
|
|||
class MatrixS : public PLUMatrix
|
||||
{
|
||||
public:
|
||||
MatrixS(const FSSparseTensor &f, const IntSequence &ss,
|
||||
const TwoDMatrix &gy, const PartitionY &ypart);
|
||||
MatrixS(const FSSparseTensor& f, const IntSequence& ss, const TwoDMatrix& gy,
|
||||
const PartitionY& ypart);
|
||||
};
|
||||
|
||||
/* The B matrix is equal to [f_y**₊]. We have just a constructor. */
|
||||
|
@ -191,9 +196,8 @@ public:
|
|||
class MatrixB : public TwoDMatrix
|
||||
{
|
||||
public:
|
||||
MatrixB(const FSSparseTensor &f, const IntSequence &ss)
|
||||
: TwoDMatrix(FGSTensor(f, ss, IntSequence(1, 0),
|
||||
TensorDimens(ss, IntSequence(1, 0))))
|
||||
MatrixB(const FSSparseTensor& f, const IntSequence& ss) :
|
||||
TwoDMatrix(FGSTensor(f, ss, IntSequence(1, 0), TensorDimens(ss, IntSequence(1, 0))))
|
||||
{
|
||||
}
|
||||
};
|
||||
|
@ -246,7 +250,7 @@ protected:
|
|||
|
||||
/* Dynamic model derivatives: just a reference to the container of sparse
|
||||
tensors of the system derivatives, lives outside the class */
|
||||
const TensorContainer<FSSparseTensor> &f;
|
||||
const TensorContainer<FSSparseTensor>& f;
|
||||
|
||||
/* Matrices: matrix A, matrix S, and matrix B, see MatrixA and MatrixB class
|
||||
declarations */
|
||||
|
@ -258,46 +262,46 @@ protected:
|
|||
containers. We declare template methods for accessing containers depending
|
||||
on ‘fold’ and ‘unfold’ flag, we implement their specializations*/
|
||||
template<Storage t>
|
||||
typename ctraits<t>::Tg &g();
|
||||
typename ctraits<t>::Tg& g();
|
||||
template<Storage t>
|
||||
const typename ctraits<t>::Tg &g() const;
|
||||
const typename ctraits<t>::Tg& g() const;
|
||||
|
||||
template<Storage t>
|
||||
typename ctraits<t>::Tgs &gs();
|
||||
typename ctraits<t>::Tgs& gs();
|
||||
template<Storage t>
|
||||
const typename ctraits<t>::Tgs &gs() const;
|
||||
const typename ctraits<t>::Tgs& gs() const;
|
||||
|
||||
template<Storage t>
|
||||
typename ctraits<t>::Tgss &gss();
|
||||
typename ctraits<t>::Tgss& gss();
|
||||
template<Storage t>
|
||||
const typename ctraits<t>::Tgss &gss() const;
|
||||
const typename ctraits<t>::Tgss& gss() const;
|
||||
|
||||
template<Storage t>
|
||||
typename ctraits<t>::TG &G();
|
||||
typename ctraits<t>::TG& G();
|
||||
template<Storage t>
|
||||
const typename ctraits<t>::TG &G() const;
|
||||
const typename ctraits<t>::TG& G() const;
|
||||
|
||||
template<Storage t>
|
||||
typename ctraits<t>::TZstack &Zstack();
|
||||
typename ctraits<t>::TZstack& Zstack();
|
||||
template<Storage t>
|
||||
const typename ctraits<t>::TZstack &Zstack() const;
|
||||
const typename ctraits<t>::TZstack& Zstack() const;
|
||||
|
||||
template<Storage t>
|
||||
typename ctraits<t>::TGstack &Gstack();
|
||||
typename ctraits<t>::TGstack& Gstack();
|
||||
template<Storage t>
|
||||
const typename ctraits<t>::TGstack &Gstack() const;
|
||||
const typename ctraits<t>::TGstack& Gstack() const;
|
||||
|
||||
template<Storage t>
|
||||
typename ctraits<t>::Tm &m();
|
||||
typename ctraits<t>::Tm& m();
|
||||
template<Storage t>
|
||||
const typename ctraits<t>::Tm &m() const;
|
||||
const typename ctraits<t>::Tm& m() const;
|
||||
|
||||
Journal& journal;
|
||||
|
||||
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);
|
||||
const TensorContainer<FSSparseTensor>& fcont, const TwoDMatrix& gy, const TwoDMatrix& gu,
|
||||
const TwoDMatrix& v, Journal& jr);
|
||||
|
||||
/* Performs k-order step provided that k=2 or the k−1-th step has been
|
||||
run, this is the core method */
|
||||
|
@ -312,22 +316,22 @@ public:
|
|||
template<Storage t>
|
||||
Vector calcStochShift(int order, double sigma) const;
|
||||
void switchToFolded();
|
||||
const PartitionY &
|
||||
const PartitionY&
|
||||
getPartY() const
|
||||
{
|
||||
return ypart;
|
||||
}
|
||||
const FGSContainer &
|
||||
const FGSContainer&
|
||||
getFoldDers() const
|
||||
{
|
||||
return _fg;
|
||||
}
|
||||
const UGSContainer &
|
||||
const UGSContainer&
|
||||
getUnfoldDers() const
|
||||
{
|
||||
return _ug;
|
||||
}
|
||||
const FGSContainer &
|
||||
const FGSContainer&
|
||||
getFoldDersS() const
|
||||
{
|
||||
return _fgs;
|
||||
|
@ -337,6 +341,7 @@ public:
|
|||
{
|
||||
return i % 2 == 0;
|
||||
}
|
||||
|
||||
protected:
|
||||
/* Inserts a g derivative to the g container and also creates subtensors and
|
||||
insert them to g_y* and g_y** containers */
|
||||
|
@ -345,17 +350,17 @@ protected:
|
|||
|
||||
/* Solves the sylvester equation (templated fold, and unfold) */
|
||||
template<Storage t>
|
||||
void sylvesterSolve(typename ctraits<t>::Ttensor &der) const;
|
||||
void sylvesterSolve(typename ctraits<t>::Ttensor& der) const;
|
||||
|
||||
/* Calculates derivatives of F by Faà Di Bruno for the sparse container of
|
||||
system derivatives and Z stack container */
|
||||
template<Storage t>
|
||||
std::unique_ptr<typename ctraits<t>::Ttensor> faaDiBrunoZ(const Symmetry &sym) const;
|
||||
std::unique_ptr<typename ctraits<t>::Ttensor> faaDiBrunoZ(const Symmetry& sym) const;
|
||||
|
||||
/* Calculates derivatives of G by Faà Di Bruno for the dense container g**
|
||||
and G stack */
|
||||
template<Storage t>
|
||||
std::unique_ptr<typename ctraits<t>::Ttensor> faaDiBrunoG(const Symmetry &sym) const;
|
||||
std::unique_ptr<typename ctraits<t>::Ttensor> faaDiBrunoG(const Symmetry& sym) const;
|
||||
|
||||
// Recovers g_y*ⁱ
|
||||
template<Storage t>
|
||||
|
@ -402,8 +407,9 @@ KOrder::insertDerivative(std::unique_ptr<typename ctraits<t>::Ttensor> der)
|
|||
{
|
||||
auto der_ptr = der.get();
|
||||
g<t>().insert(std::move(der));
|
||||
gs<t>().insert(std::make_unique<typename ctraits<t>::Ttensor>(ypart.nstat, ypart.nys(), *der_ptr));
|
||||
gss<t>().insert(std::make_unique<typename ctraits<t>::Ttensor>(ypart.nstat+ypart.npred,
|
||||
gs<t>().insert(
|
||||
std::make_unique<typename ctraits<t>::Ttensor>(ypart.nstat, ypart.nys(), *der_ptr));
|
||||
gss<t>().insert(std::make_unique<typename ctraits<t>::Ttensor>(ypart.nstat + ypart.npred,
|
||||
ypart.nyss(), *der_ptr));
|
||||
}
|
||||
|
||||
|
@ -417,7 +423,7 @@ KOrder::insertDerivative(std::unique_ptr<typename ctraits<t>::Ttensor> der)
|
|||
|
||||
template<Storage t>
|
||||
std::unique_ptr<typename ctraits<t>::Ttensor>
|
||||
KOrder::faaDiBrunoZ(const Symmetry &sym) const
|
||||
KOrder::faaDiBrunoZ(const Symmetry& sym) const
|
||||
{
|
||||
JournalRecordPair pa(journal);
|
||||
pa << "Faà Di Bruno Z container for " << sym << endrec;
|
||||
|
@ -431,7 +437,7 @@ KOrder::faaDiBrunoZ(const Symmetry &sym) const
|
|||
|
||||
template<Storage t>
|
||||
std::unique_ptr<typename ctraits<t>::Ttensor>
|
||||
KOrder::faaDiBrunoG(const Symmetry &sym) const
|
||||
KOrder::faaDiBrunoG(const Symmetry& sym) const
|
||||
{
|
||||
JournalRecordPair pa(journal);
|
||||
pa << "Faà Di Bruno G container for " << sym << endrec;
|
||||
|
@ -456,7 +462,7 @@ template<Storage t>
|
|||
void
|
||||
KOrder::recover_y(int i)
|
||||
{
|
||||
Symmetry sym{i, 0, 0, 0};
|
||||
Symmetry sym {i, 0, 0, 0};
|
||||
JournalRecordPair pa(journal);
|
||||
pa << "Recovering symmetry " << sym << endrec;
|
||||
|
||||
|
@ -471,9 +477,9 @@ KOrder::recover_y(int i)
|
|||
|
||||
insertDerivative<t>(std::move(g_yi));
|
||||
|
||||
auto &gss_y = gss<t>().get(Symmetry{1, 0, 0, 0});
|
||||
auto& gss_y = gss<t>().get(Symmetry {1, 0, 0, 0});
|
||||
gs<t>().multAndAdd(gss_y, *G_yi_ptr);
|
||||
auto &gss_yi = gss<t>().get(sym);
|
||||
auto& gss_yi = gss<t>().get(sym);
|
||||
gs<t>().multAndAdd(gss_yi, *G_yi_ptr);
|
||||
}
|
||||
|
||||
|
@ -490,7 +496,7 @@ template<Storage t>
|
|||
void
|
||||
KOrder::recover_yu(int i, int j)
|
||||
{
|
||||
Symmetry sym{i, j, 0, 0};
|
||||
Symmetry sym {i, j, 0, 0};
|
||||
JournalRecordPair pa(journal);
|
||||
pa << "Recovering symmetry " << sym << endrec;
|
||||
|
||||
|
@ -503,7 +509,7 @@ KOrder::recover_yu(int i, int j)
|
|||
matA.multInv(*g_yiuj);
|
||||
insertDerivative<t>(std::move(g_yiuj));
|
||||
|
||||
gs<t>().multAndAdd(gss<t>().get(Symmetry{1, 0, 0, 0}), *G_yiuj_ptr);
|
||||
gs<t>().multAndAdd(gss<t>().get(Symmetry {1, 0, 0, 0}), *G_yiuj_ptr);
|
||||
}
|
||||
|
||||
/* Here we solve [F_yⁱσʲ]+[Dᵢⱼ]+[Eᵢⱼ]=0 to obtain g_yⁱσʲ. We calculate
|
||||
|
@ -523,7 +529,7 @@ template<Storage t>
|
|||
void
|
||||
KOrder::recover_ys(int i, int j)
|
||||
{
|
||||
Symmetry sym{i, 0, 0, j};
|
||||
Symmetry sym {i, 0, 0, j};
|
||||
JournalRecordPair pa(journal);
|
||||
pa << "Recovering symmetry " << sym << endrec;
|
||||
|
||||
|
@ -555,7 +561,7 @@ KOrder::recover_ys(int i, int j)
|
|||
insertDerivative<t>(std::move(g_yisj));
|
||||
|
||||
Gstack<t>().multAndAdd(1, gss<t>(), *G_yisj_ptr);
|
||||
Gstack<t>().multAndAdd(i+j, gss<t>(), *G_yisj_ptr);
|
||||
Gstack<t>().multAndAdd(i + j, gss<t>(), *G_yisj_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -576,7 +582,7 @@ template<Storage t>
|
|||
void
|
||||
KOrder::recover_yus(int i, int j, int k)
|
||||
{
|
||||
Symmetry sym{i, j, 0, k};
|
||||
Symmetry sym {i, j, 0, k};
|
||||
JournalRecordPair pa(journal);
|
||||
pa << "Recovering symmetry " << sym << endrec;
|
||||
|
||||
|
@ -634,7 +640,7 @@ template<Storage t>
|
|||
void
|
||||
KOrder::recover_s(int i)
|
||||
{
|
||||
Symmetry sym{0, 0, 0, i};
|
||||
Symmetry sym {0, 0, 0, i};
|
||||
JournalRecordPair pa(journal);
|
||||
pa << "Recovering symmetry " << sym << endrec;
|
||||
|
||||
|
@ -677,9 +683,9 @@ void
|
|||
KOrder::fillG(int i, int j, int k)
|
||||
{
|
||||
for (int m = 1; m <= k; m++)
|
||||
if (is_even(k-m))
|
||||
if (is_even(k - m))
|
||||
{
|
||||
auto G_yiujupms = faaDiBrunoG<t>(Symmetry{i, j, m, k-m});
|
||||
auto G_yiujupms = faaDiBrunoG<t>(Symmetry {i, j, m, k - m});
|
||||
G<t>().insert(std::move(G_yiujupms));
|
||||
}
|
||||
}
|
||||
|
@ -694,12 +700,12 @@ template<Storage t>
|
|||
typename ctraits<t>::Ttensor
|
||||
KOrder::calcD_ijk(int i, int j, int k) const
|
||||
{
|
||||
typename ctraits<t>::Ttensor res(ny, TensorDimens(Symmetry{i, j, 0, 0}, nvs));
|
||||
typename ctraits<t>::Ttensor res(ny, TensorDimens(Symmetry {i, j, 0, 0}, nvs));
|
||||
res.zeros();
|
||||
if (is_even(k))
|
||||
{
|
||||
auto tmp = faaDiBrunoZ<t>(Symmetry{i, j, k, 0});
|
||||
tmp->contractAndAdd(2, res, m<t>().get(Symmetry{k}));
|
||||
auto tmp = faaDiBrunoZ<t>(Symmetry {i, j, k, 0});
|
||||
tmp->contractAndAdd(2, res, m<t>().get(Symmetry {k}));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
@ -714,13 +720,13 @@ template<Storage t>
|
|||
typename ctraits<t>::Ttensor
|
||||
KOrder::calcE_ijk(int i, int j, int k) const
|
||||
{
|
||||
typename ctraits<t>::Ttensor res(ny, TensorDimens(Symmetry{i, j, 0, 0}, nvs));
|
||||
typename ctraits<t>::Ttensor res(ny, TensorDimens(Symmetry {i, j, 0, 0}, nvs));
|
||||
res.zeros();
|
||||
for (int n = 2; n <= k-1; n += 2)
|
||||
for (int n = 2; n <= k - 1; n += 2)
|
||||
{
|
||||
auto tmp = faaDiBrunoZ<t>(Symmetry{i, j, n, k-n});
|
||||
auto tmp = faaDiBrunoZ<t>(Symmetry {i, j, n, k - n});
|
||||
tmp->mult(static_cast<double>(PascalTriangle::noverk(k, n)));
|
||||
tmp->contractAndAdd(2, res, m<t>().get(Symmetry{n}));
|
||||
tmp->contractAndAdd(2, res, m<t>().get(Symmetry {n}));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
@ -777,25 +783,24 @@ template<Storage t>
|
|||
void
|
||||
KOrder::performStep(int order)
|
||||
{
|
||||
KORD_RAISE_IF(order-1 != g<t>().getMaxDim(),
|
||||
"Wrong order for KOrder::performStep");
|
||||
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);
|
||||
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 = 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);
|
||||
for (int i = order - 1; i >= 1; i--)
|
||||
recover_yus<t>(0, i, order - i);
|
||||
|
||||
recover_s<t>(order);
|
||||
}
|
||||
|
@ -808,8 +813,7 @@ template<Storage t>
|
|||
double
|
||||
KOrder::check(int dim) const
|
||||
{
|
||||
KORD_RAISE_IF(dim > g<t>().getMaxDim(),
|
||||
"Wrong dimension for KOrder::check");
|
||||
KORD_RAISE_IF(dim > g<t>().getMaxDim(), "Wrong dimension for KOrder::check");
|
||||
JournalRecordPair pa(journal);
|
||||
pa << "Checking residuals for order = " << dim << endrec;
|
||||
|
||||
|
@ -818,7 +822,7 @@ KOrder::check(int dim) const
|
|||
// Check for F_yⁱuʲ=0
|
||||
for (int i = 0; i <= dim; i++)
|
||||
{
|
||||
Symmetry sym{dim-i, i, 0, 0};
|
||||
Symmetry sym {dim - i, i, 0, 0};
|
||||
auto r = faaDiBrunoZ<t>(sym);
|
||||
double err = r->getData().getMax();
|
||||
JournalRecord(journal) << "\terror for symmetry " << sym << "\tis " << err << endrec;
|
||||
|
@ -826,14 +830,14 @@ KOrder::check(int dim) const
|
|||
}
|
||||
|
||||
// Check for F_yⁱuʲu′ᵏ+Dᵢⱼₖ+Eᵢⱼₖ=0
|
||||
for (auto &si : SymmetrySet(dim, 3))
|
||||
for (auto& si : SymmetrySet(dim, 3))
|
||||
{
|
||||
int i = si[0];
|
||||
int j = si[1];
|
||||
int k = si[2];
|
||||
if (i+j > 0 && k > 0)
|
||||
if (i + j > 0 && k > 0)
|
||||
{
|
||||
Symmetry sym{i, j, 0, k};
|
||||
Symmetry sym {i, j, 0, k};
|
||||
auto r = faaDiBrunoZ<t>(sym);
|
||||
auto D_ijk = calcD_ijk<t>(i, j, k);
|
||||
r->add(1.0, D_ijk);
|
||||
|
@ -846,13 +850,13 @@ KOrder::check(int dim) const
|
|||
}
|
||||
|
||||
// Check for F_σⁱ+Dᵢ+Eᵢ=0
|
||||
auto r = faaDiBrunoZ<t>(Symmetry{0, 0, 0, dim});
|
||||
auto r = faaDiBrunoZ<t>(Symmetry {0, 0, 0, dim});
|
||||
auto D_k = calcD_k<t>(dim);
|
||||
r->add(1.0, D_k);
|
||||
auto E_k = calcE_k<t>(dim);
|
||||
r->add(1.0, E_k);
|
||||
double err = r->getData().getMax();
|
||||
Symmetry sym{0, 0, 0, dim};
|
||||
Symmetry sym {0, 0, 0, dim};
|
||||
JournalRecord(journal) << "\terror for symmetry " << sym << "\tis " << err << endrec;
|
||||
maxerror = std::max(err, maxerror);
|
||||
|
||||
|
@ -870,7 +874,7 @@ KOrder::calcStochShift(int order, double sigma) const
|
|||
if (is_even(j))
|
||||
{
|
||||
auto ten = calcD_k<t>(j);
|
||||
res.add(std::pow(sigma, j)/jfac, ten.getData());
|
||||
res.add(std::pow(sigma, j) / jfac, ten.getData());
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
|
|
@ -23,13 +23,13 @@
|
|||
/* Same as MatrixA constructor, but the submatrix ‘gss_ys’ is passed
|
||||
directly. */
|
||||
|
||||
MatrixAA::MatrixAA(const FSSparseTensor &f, const IntSequence &ss,
|
||||
const TwoDMatrix &gss_ys, const PartitionY &ypart)
|
||||
: PLUMatrix(ypart.ny())
|
||||
MatrixAA::MatrixAA(const FSSparseTensor& f, const IntSequence& ss, const TwoDMatrix& gss_ys,
|
||||
const PartitionY& ypart) :
|
||||
PLUMatrix(ypart.ny())
|
||||
{
|
||||
zeros();
|
||||
|
||||
IntSequence c{1};
|
||||
IntSequence c {1};
|
||||
FGSTensor f_y(f, ss, c, TensorDimens(ss, c));
|
||||
add(1.0, f_y);
|
||||
|
||||
|
@ -42,168 +42,158 @@ MatrixAA::MatrixAA(const FSSparseTensor &f, const IntSequence &ss,
|
|||
}
|
||||
|
||||
// KOrderStoch folded constructor code
|
||||
KOrderStoch::KOrderStoch(const PartitionY &yp, int nu,
|
||||
const TensorContainer<FSSparseTensor> &fcont,
|
||||
const FGSContainer &hh, Journal &jr)
|
||||
: nvs{yp.nys(), nu, nu, 1}, ypart(yp), journal(jr),
|
||||
_ug(4), _fg(4), _ugs(4), _fgs(4), _uG(4), _fG(4),
|
||||
_uh(nullptr), _fh(&hh),
|
||||
_uZstack(&_uG, ypart.nyss(), &_ug, ypart.ny(), ypart.nys(), nu),
|
||||
KOrderStoch::KOrderStoch(const PartitionY& yp, int nu, const TensorContainer<FSSparseTensor>& fcont,
|
||||
const FGSContainer& hh, Journal& jr) :
|
||||
nvs {yp.nys(), nu, nu, 1},
|
||||
ypart(yp), journal(jr), _ug(4), _fg(4), _ugs(4), _fgs(4), _uG(4), _fG(4), _uh(nullptr),
|
||||
_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)
|
||||
_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)
|
||||
{
|
||||
}
|
||||
|
||||
// KOrderStoch unfolded constructor code
|
||||
KOrderStoch::KOrderStoch(const PartitionY &yp, int nu,
|
||||
const TensorContainer<FSSparseTensor> &fcont,
|
||||
const UGSContainer &hh, Journal &jr)
|
||||
: nvs{yp.nys(), nu, nu, 1}, ypart(yp), journal(jr),
|
||||
_ug(4), _fg(4), _ugs(4), _fgs(4), _uG(4), _fG(4),
|
||||
_uh(&hh), _fh(nullptr),
|
||||
_uZstack(&_uG, ypart.nyss(), &_ug, ypart.ny(), ypart.nys(), nu),
|
||||
KOrderStoch::KOrderStoch(const PartitionY& yp, int nu, const TensorContainer<FSSparseTensor>& fcont,
|
||||
const UGSContainer& hh, Journal& jr) :
|
||||
nvs {yp.nys(), nu, nu, 1},
|
||||
ypart(yp), journal(jr), _ug(4), _fg(4), _ugs(4), _fgs(4), _uG(4), _fG(4), _uh(&hh),
|
||||
_fh(nullptr), _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)
|
||||
_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)
|
||||
{
|
||||
}
|
||||
|
||||
// KOrderStoch convenience method specializations
|
||||
template<>
|
||||
ctraits<Storage::unfold>::Tg &
|
||||
ctraits<Storage::unfold>::Tg&
|
||||
KOrderStoch::g<Storage::unfold>()
|
||||
{
|
||||
return _ug;
|
||||
}
|
||||
template<>
|
||||
const ctraits<Storage::unfold>::Tg &
|
||||
const ctraits<Storage::unfold>::Tg&
|
||||
KOrderStoch::g<Storage::unfold>() const
|
||||
{
|
||||
return _ug;
|
||||
}
|
||||
template<>
|
||||
ctraits<Storage::fold>::Tg &
|
||||
ctraits<Storage::fold>::Tg&
|
||||
KOrderStoch::g<Storage::fold>()
|
||||
{
|
||||
return _fg;
|
||||
}
|
||||
template<>
|
||||
const ctraits<Storage::fold>::Tg &
|
||||
const ctraits<Storage::fold>::Tg&
|
||||
KOrderStoch::g<Storage::fold>() const
|
||||
{
|
||||
return _fg;
|
||||
}
|
||||
template<>
|
||||
ctraits<Storage::unfold>::Tgs &
|
||||
ctraits<Storage::unfold>::Tgs&
|
||||
KOrderStoch::gs<Storage::unfold>()
|
||||
{
|
||||
return _ugs;
|
||||
}
|
||||
template<>
|
||||
const ctraits<Storage::unfold>::Tgs &
|
||||
const ctraits<Storage::unfold>::Tgs&
|
||||
KOrderStoch::gs<Storage::unfold>() const
|
||||
{
|
||||
return _ugs;
|
||||
}
|
||||
template<>
|
||||
ctraits<Storage::fold>::Tgs &
|
||||
ctraits<Storage::fold>::Tgs&
|
||||
KOrderStoch::gs<Storage::fold>()
|
||||
{
|
||||
return _fgs;
|
||||
}
|
||||
template<>
|
||||
const ctraits<Storage::fold>::Tgs &
|
||||
const ctraits<Storage::fold>::Tgs&
|
||||
KOrderStoch::gs<Storage::fold>() const
|
||||
{
|
||||
return _fgs;
|
||||
}
|
||||
template<>
|
||||
const ctraits<Storage::unfold>::Tgss &
|
||||
const ctraits<Storage::unfold>::Tgss&
|
||||
KOrderStoch::h<Storage::unfold>() const
|
||||
{
|
||||
return *_uh;
|
||||
}
|
||||
template<>
|
||||
const ctraits<Storage::fold>::Tgss &
|
||||
const ctraits<Storage::fold>::Tgss&
|
||||
KOrderStoch::h<Storage::fold>() const
|
||||
{
|
||||
return *_fh;
|
||||
}
|
||||
template<>
|
||||
ctraits<Storage::unfold>::TG &
|
||||
ctraits<Storage::unfold>::TG&
|
||||
KOrderStoch::G<Storage::unfold>()
|
||||
{
|
||||
return _uG;
|
||||
}
|
||||
template<>
|
||||
const ctraits<Storage::unfold>::TG &
|
||||
const ctraits<Storage::unfold>::TG&
|
||||
KOrderStoch::G<Storage::unfold>() const
|
||||
{
|
||||
return _uG;
|
||||
}
|
||||
template<>
|
||||
ctraits<Storage::fold>::TG &
|
||||
ctraits<Storage::fold>::TG&
|
||||
KOrderStoch::G<Storage::fold>()
|
||||
{
|
||||
return _fG;
|
||||
}
|
||||
template<>
|
||||
const ctraits<Storage::fold>::TG &
|
||||
const ctraits<Storage::fold>::TG&
|
||||
KOrderStoch::G<Storage::fold>() const
|
||||
{
|
||||
return _fG;
|
||||
}
|
||||
template<>
|
||||
ctraits<Storage::unfold>::TZXstack &
|
||||
ctraits<Storage::unfold>::TZXstack&
|
||||
KOrderStoch::Zstack<Storage::unfold>()
|
||||
{
|
||||
return _uZstack;
|
||||
}
|
||||
template<>
|
||||
const ctraits<Storage::unfold>::TZXstack &
|
||||
const ctraits<Storage::unfold>::TZXstack&
|
||||
KOrderStoch::Zstack<Storage::unfold>() const
|
||||
{
|
||||
return _uZstack;
|
||||
}
|
||||
template<>
|
||||
ctraits<Storage::fold>::TZXstack &
|
||||
ctraits<Storage::fold>::TZXstack&
|
||||
KOrderStoch::Zstack<Storage::fold>()
|
||||
{
|
||||
return _fZstack;
|
||||
}
|
||||
template<>
|
||||
const ctraits<Storage::fold>::TZXstack &
|
||||
const ctraits<Storage::fold>::TZXstack&
|
||||
KOrderStoch::Zstack<Storage::fold>() const
|
||||
{
|
||||
return _fZstack;
|
||||
}
|
||||
template<>
|
||||
ctraits<Storage::unfold>::TGXstack &
|
||||
ctraits<Storage::unfold>::TGXstack&
|
||||
KOrderStoch::Gstack<Storage::unfold>()
|
||||
{
|
||||
return _uGstack;
|
||||
}
|
||||
template<>
|
||||
const ctraits<Storage::unfold>::TGXstack &
|
||||
const ctraits<Storage::unfold>::TGXstack&
|
||||
KOrderStoch::Gstack<Storage::unfold>() const
|
||||
{
|
||||
return _uGstack;
|
||||
}
|
||||
template<>
|
||||
ctraits<Storage::fold>::TGXstack &
|
||||
ctraits<Storage::fold>::TGXstack&
|
||||
KOrderStoch::Gstack<Storage::fold>()
|
||||
{
|
||||
return _fGstack;
|
||||
}
|
||||
template<>
|
||||
const ctraits<Storage::fold>::TGXstack &
|
||||
const ctraits<Storage::fold>::TGXstack&
|
||||
KOrderStoch::Gstack<Storage::fold>() const
|
||||
{
|
||||
return _fGstack;
|
||||
|
|
|
@ -40,9 +40,9 @@
|
|||
|
||||
#include <memory>
|
||||
|
||||
#include "korder.hh"
|
||||
#include "faa_di_bruno.hh"
|
||||
#include "journal.hh"
|
||||
#include "korder.hh"
|
||||
#include "pascal_triangle.hh"
|
||||
|
||||
/* This class is a container, which has a specialized constructor integrating
|
||||
|
@ -52,8 +52,8 @@ template<Storage t>
|
|||
class IntegDerivs : public ctraits<t>::Tgss
|
||||
{
|
||||
public:
|
||||
IntegDerivs(int r, const IntSequence &nvs, const typename ctraits<t>::Tgss &g,
|
||||
const typename ctraits<t>::Tm &mom, double at_sigma);
|
||||
IntegDerivs(int r, const IntSequence& nvs, const typename ctraits<t>::Tgss& g,
|
||||
const typename ctraits<t>::Tm& mom, double at_sigma);
|
||||
};
|
||||
|
||||
/* This constructor integrates a rule (namely its g** part) with respect to
|
||||
|
@ -102,17 +102,17 @@ public:
|
|||
and this is exactly what the code does.
|
||||
*/
|
||||
template<Storage t>
|
||||
IntegDerivs<t>::IntegDerivs(int r, const IntSequence &nvs, const typename ctraits<t>::Tgss &g,
|
||||
const typename ctraits<t>::Tm &mom, double at_sigma)
|
||||
: ctraits<t>::Tgss(4)
|
||||
IntegDerivs<t>::IntegDerivs(int r, const IntSequence& nvs, const typename ctraits<t>::Tgss& g,
|
||||
const typename ctraits<t>::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};
|
||||
int p = d - i;
|
||||
Symmetry sym {i, 0, 0, p};
|
||||
auto ten = std::make_unique<typename ctraits<t>::Ttensor>(r, TensorDimens(sym, nvs));
|
||||
|
||||
// Calculate derivative h_yⁱσᵖ
|
||||
|
@ -127,20 +127,20 @@ IntegDerivs<t>::IntegDerivs(int r, const IntSequence &nvs, const typename ctrait
|
|||
ten->zeros();
|
||||
for (int n = 0; n <= p; n++)
|
||||
{
|
||||
int k = p-n;
|
||||
int k = p - n;
|
||||
int povern = PascalTriangle::noverk(p, n);
|
||||
int mfac = 1;
|
||||
for (int m = 0; i+m+n+k <= maxd; m++, mfac *= m)
|
||||
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))
|
||||
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))
|
||||
if (m + n > 0 && KOrder::is_even(m + n) && g.check(sym_mn))
|
||||
{
|
||||
typename ctraits<t>::Ttensor gtmp(g.get(sym_mn));
|
||||
gtmp.mult(mult);
|
||||
gtmp.contractAndAdd(1, *ten, mom.get(Symmetry{m+n}));
|
||||
gtmp.contractAndAdd(1, *ten, mom.get(Symmetry {m + n}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -160,9 +160,8 @@ template<Storage t>
|
|||
class StochForwardDerivs : public ctraits<t>::Tgss
|
||||
{
|
||||
public:
|
||||
StochForwardDerivs(const PartitionY &ypart, int nu,
|
||||
const typename ctraits<t>::Tgss &g, const typename ctraits<t>::Tm &m,
|
||||
const Vector &ydelta, double sdelta,
|
||||
StochForwardDerivs(const PartitionY& ypart, int nu, const typename ctraits<t>::Tgss& g,
|
||||
const typename ctraits<t>::Tm& m, const Vector& ydelta, double sdelta,
|
||||
double at_sigma);
|
||||
};
|
||||
|
||||
|
@ -181,12 +180,11 @@ public:
|
|||
— Recover general symmetry tensors from the (full symmetric) polynomial
|
||||
*/
|
||||
template<Storage t>
|
||||
StochForwardDerivs<t>::StochForwardDerivs(const PartitionY &ypart, int nu,
|
||||
const typename ctraits<t>::Tgss &g,
|
||||
const typename ctraits<t>::Tm &m,
|
||||
const Vector &ydelta, double sdelta,
|
||||
double at_sigma)
|
||||
: ctraits<t>::Tgss(4)
|
||||
StochForwardDerivs<t>::StochForwardDerivs(const PartitionY& ypart, int nu,
|
||||
const typename ctraits<t>::Tgss& g,
|
||||
const typename ctraits<t>::Tm& m, const Vector& ydelta,
|
||||
double sdelta, double at_sigma) :
|
||||
ctraits<t>::Tgss(4)
|
||||
{
|
||||
int maxd = g.getMaxDim();
|
||||
int r = ypart.nyss();
|
||||
|
@ -196,22 +194,21 @@ StochForwardDerivs<t>::StochForwardDerivs(const PartitionY &ypart, int nu,
|
|||
the tensors has zero dimensions for shocks, this is because we need to
|
||||
⎡y*⎤
|
||||
make easily stacks of the form ⎣σ ⎦ in the next step. */
|
||||
IntSequence nvs{ypart.nys(), 0, 0, 1};
|
||||
IntSequence nvs {ypart.nys(), 0, 0, 1};
|
||||
IntegDerivs<t> g_int(r, nvs, g, m, at_sigma);
|
||||
|
||||
// Make ‘g_int_sym’ be full symmetric polynomial from ‘g_int’
|
||||
/* Here we just form a polynomial whose unique variable corresponds to
|
||||
⎡y*⎤
|
||||
⎣σ ⎦ stack. */
|
||||
typename ctraits<t>::Tpol g_int_sym(r, ypart.nys()+1);
|
||||
typename ctraits<t>::Tpol g_int_sym(r, ypart.nys() + 1);
|
||||
for (int d = 1; d <= maxd; d++)
|
||||
{
|
||||
auto ten = std::make_unique<typename ctraits<t>::Ttensym>(r, ypart.nys()+1, d);
|
||||
auto ten = std::make_unique<typename ctraits<t>::Ttensym>(r, ypart.nys() + 1, d);
|
||||
ten->zeros();
|
||||
for (int i = 0; i <= d; i++)
|
||||
if (int k {d-i};
|
||||
g_int.check(Symmetry{i, 0, 0, k}))
|
||||
ten->addSubTensor(g_int.get(Symmetry{i, 0, 0, k}));
|
||||
if (int k {d - i}; g_int.check(Symmetry {i, 0, 0, k}))
|
||||
ten->addSubTensor(g_int.get(Symmetry {i, 0, 0, k}));
|
||||
g_int_sym.insert(std::move(ten));
|
||||
}
|
||||
|
||||
|
@ -220,15 +217,15 @@ StochForwardDerivs<t>::StochForwardDerivs(const PartitionY &ypart, int nu,
|
|||
was centralized about (ỹ,σ~). This is done by derivating and evaluating
|
||||
the derivated polynomial at (ȳ−ỹ,σ¯-σ~). The stack of this vector is
|
||||
‘delta’ in the code. */
|
||||
Vector delta(ypart.nys()+1);
|
||||
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;
|
||||
typename ctraits<t>::Tpol g_int_cent(r, ypart.nys()+1);
|
||||
typename ctraits<t>::Tpol g_int_cent(r, ypart.nys() + 1);
|
||||
for (int d = 1; d <= maxd; d++)
|
||||
{
|
||||
g_int_sym.derivative(d-1);
|
||||
g_int_sym.derivative(d - 1);
|
||||
auto der = g_int_sym.evalPartially(d, delta);
|
||||
g_int_cent.insert(std::move(der));
|
||||
}
|
||||
|
@ -236,20 +233,19 @@ StochForwardDerivs<t>::StochForwardDerivs(const PartitionY &ypart, int nu,
|
|||
// Pull out general symmetry tensors from ‘g_int_cent’
|
||||
/* Here we only recover the general symmetry derivatives from the full
|
||||
symmetric polynomial. Note that the derivative get the true ‘nvs’. */
|
||||
IntSequence ss{ypart.nys(), 0, 0, 1};
|
||||
IntSequence pp{0, 1, 2, 3};
|
||||
IntSequence ss {ypart.nys(), 0, 0, 1};
|
||||
IntSequence pp {0, 1, 2, 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}))
|
||||
if (g_int_cent.check(Symmetry {d}))
|
||||
for (int i = 0; i <= d; i++)
|
||||
{
|
||||
Symmetry sym{i, 0, 0, d-i};
|
||||
Symmetry sym {i, 0, 0, d - i};
|
||||
IntSequence coor(pp.unfold(sym));
|
||||
auto ten = std::make_unique<typename ctraits<t>::Ttensor>(g_int_cent.get(Symmetry{d}),
|
||||
ss, coor,
|
||||
TensorDimens(sym, true_nvs));
|
||||
auto ten = std::make_unique<typename ctraits<t>::Ttensor>(
|
||||
g_int_cent.get(Symmetry {d}), ss, coor, TensorDimens(sym, true_nvs));
|
||||
this->insert(std::move(ten));
|
||||
}
|
||||
}
|
||||
|
@ -265,11 +261,10 @@ public:
|
|||
using _Stype = StackContainerInterface<_Ttype>;
|
||||
using _Ctype = typename StackContainer<_Ttype>::_Ctype;
|
||||
using itype = typename StackContainer<_Ttype>::itype;
|
||||
GXContainer(const _Ctype *gs, int ngs, int nu)
|
||||
: GContainer<_Ttype>(gs, ngs, nu)
|
||||
GXContainer(const _Ctype* gs, int ngs, int nu) : GContainer<_Ttype>(gs, ngs, nu)
|
||||
{
|
||||
}
|
||||
itype getType(int i, const Symmetry &s) const override;
|
||||
itype getType(int i, const Symmetry& s) const override;
|
||||
};
|
||||
|
||||
/* This routine corresponds to this stack:
|
||||
|
@ -280,7 +275,7 @@ public:
|
|||
*/
|
||||
template<class _Ttype>
|
||||
typename GXContainer<_Ttype>::itype
|
||||
GXContainer<_Ttype>::getType(int i, const Symmetry &s) const
|
||||
GXContainer<_Ttype>::getType(int i, const Symmetry& s) const
|
||||
{
|
||||
if (i == 0)
|
||||
{
|
||||
|
@ -295,7 +290,7 @@ GXContainer<_Ttype>::getType(int i, const Symmetry &s) const
|
|||
return itype::zero;
|
||||
if (i == 3)
|
||||
{
|
||||
if (s == Symmetry{0, 0, 0, 1})
|
||||
if (s == Symmetry {0, 0, 0, 1})
|
||||
return itype::unit;
|
||||
else
|
||||
return itype::zero;
|
||||
|
@ -315,11 +310,11 @@ public:
|
|||
using _Stype = StackContainerInterface<_Ttype>;
|
||||
using _Ctype = typename StackContainer<_Ttype>::_Ctype;
|
||||
using itype = typename StackContainer<_Ttype>::itype;
|
||||
ZXContainer(const _Ctype *gss, int ngss, const _Ctype *g, int ng, int ny, int nu)
|
||||
: ZContainer<_Ttype>(gss, ngss, g, ng, ny, nu)
|
||||
ZXContainer(const _Ctype* gss, int ngss, const _Ctype* g, int ng, int ny, int nu) :
|
||||
ZContainer<_Ttype>(gss, ngss, g, ng, ny, nu)
|
||||
{
|
||||
}
|
||||
itype getType(int i, const Symmetry &s) const override;
|
||||
itype getType(int i, const Symmetry& s) const override;
|
||||
};
|
||||
|
||||
/* This getType() method corresponds to this stack:
|
||||
|
@ -330,7 +325,7 @@ public:
|
|||
*/
|
||||
template<class _Ttype>
|
||||
typename ZXContainer<_Ttype>::itype
|
||||
ZXContainer<_Ttype>::getType(int i, const Symmetry &s) const
|
||||
ZXContainer<_Ttype>::getType(int i, const Symmetry& s) const
|
||||
{
|
||||
if (i == 0)
|
||||
{
|
||||
|
@ -348,14 +343,14 @@ ZXContainer<_Ttype>::getType(int i, const Symmetry &s) const
|
|||
}
|
||||
if (i == 2)
|
||||
{
|
||||
if (s == Symmetry{1, 0, 0, 0})
|
||||
if (s == Symmetry {1, 0, 0, 0})
|
||||
return itype::unit;
|
||||
else
|
||||
return itype::zero;
|
||||
}
|
||||
if (i == 3)
|
||||
{
|
||||
if (s == Symmetry{0, 1, 0, 0})
|
||||
if (s == Symmetry {0, 1, 0, 0})
|
||||
return itype::unit;
|
||||
else
|
||||
return itype::zero;
|
||||
|
@ -368,8 +363,7 @@ class UnfoldedGXContainer : public GXContainer<UGSTensor>, public UnfoldedStackC
|
|||
{
|
||||
public:
|
||||
using _Ctype = TensorContainer<UGSTensor>;
|
||||
UnfoldedGXContainer(const _Ctype *gs, int ngs, int nu)
|
||||
: GXContainer<UGSTensor>(gs, ngs, nu)
|
||||
UnfoldedGXContainer(const _Ctype* gs, int ngs, int nu) : GXContainer<UGSTensor>(gs, ngs, nu)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
@ -378,8 +372,7 @@ class FoldedGXContainer : public GXContainer<FGSTensor>, public FoldedStackConta
|
|||
{
|
||||
public:
|
||||
using _Ctype = TensorContainer<FGSTensor>;
|
||||
FoldedGXContainer(const _Ctype *gs, int ngs, int nu)
|
||||
: GXContainer<FGSTensor>(gs, ngs, nu)
|
||||
FoldedGXContainer(const _Ctype* gs, int ngs, int nu) : GXContainer<FGSTensor>(gs, ngs, nu)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
@ -388,8 +381,8 @@ class UnfoldedZXContainer : public ZXContainer<UGSTensor>, public UnfoldedStackC
|
|||
{
|
||||
public:
|
||||
using _Ctype = TensorContainer<UGSTensor>;
|
||||
UnfoldedZXContainer(const _Ctype *gss, int ngss, const _Ctype *g, int ng, int ny, int nu)
|
||||
: ZXContainer<UGSTensor>(gss, ngss, g, ng, ny, nu)
|
||||
UnfoldedZXContainer(const _Ctype* gss, int ngss, const _Ctype* g, int ng, int ny, int nu) :
|
||||
ZXContainer<UGSTensor>(gss, ngss, g, ng, ny, nu)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
@ -398,8 +391,8 @@ class FoldedZXContainer : public ZXContainer<FGSTensor>, public FoldedStackConta
|
|||
{
|
||||
public:
|
||||
using _Ctype = TensorContainer<FGSTensor>;
|
||||
FoldedZXContainer(const _Ctype *gss, int ngss, const _Ctype *g, int ng, int ny, int nu)
|
||||
: ZXContainer<FGSTensor>(gss, ngss, g, ng, ny, nu)
|
||||
FoldedZXContainer(const _Ctype* gss, int ngss, const _Ctype* g, int ng, int ny, int nu) :
|
||||
ZXContainer<FGSTensor>(gss, ngss, g, ng, ny, nu)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
@ -415,8 +408,8 @@ public:
|
|||
class MatrixAA : public PLUMatrix
|
||||
{
|
||||
public:
|
||||
MatrixAA(const FSSparseTensor &f, const IntSequence &ss,
|
||||
const TwoDMatrix &gyss, const PartitionY &ypart);
|
||||
MatrixAA(const FSSparseTensor& f, const IntSequence& ss, const TwoDMatrix& gyss,
|
||||
const PartitionY& ypart);
|
||||
};
|
||||
|
||||
/* This class calculates derivatives of g given implicitly by
|
||||
|
@ -436,77 +429,79 @@ class KOrderStoch
|
|||
protected:
|
||||
IntSequence nvs;
|
||||
PartitionY ypart;
|
||||
Journal &journal;
|
||||
Journal& journal;
|
||||
UGSContainer _ug;
|
||||
FGSContainer _fg;
|
||||
UGSContainer _ugs;
|
||||
FGSContainer _fgs;
|
||||
UGSContainer _uG;
|
||||
FGSContainer _fG;
|
||||
const UGSContainer *_uh;
|
||||
const FGSContainer *_fh;
|
||||
const UGSContainer* _uh;
|
||||
const FGSContainer* _fh;
|
||||
UnfoldedZXContainer _uZstack;
|
||||
FoldedZXContainer _fZstack;
|
||||
UnfoldedGXContainer _uGstack;
|
||||
FoldedGXContainer _fGstack;
|
||||
const TensorContainer<FSSparseTensor> &f;
|
||||
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);
|
||||
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);
|
||||
template<Storage t>
|
||||
void performStep(int order);
|
||||
const FGSContainer &
|
||||
const FGSContainer&
|
||||
getFoldDers() const
|
||||
{
|
||||
return _fg;
|
||||
}
|
||||
const UGSContainer &
|
||||
const UGSContainer&
|
||||
getUnfoldDers() const
|
||||
{
|
||||
return _ug;
|
||||
}
|
||||
const FGSContainer &
|
||||
const FGSContainer&
|
||||
getFoldDersS() const
|
||||
{
|
||||
return _fgs;
|
||||
}
|
||||
|
||||
protected:
|
||||
template<Storage t>
|
||||
std::unique_ptr<typename ctraits<t>::Ttensor> faaDiBrunoZ(const Symmetry &sym) const;
|
||||
std::unique_ptr<typename ctraits<t>::Ttensor> faaDiBrunoZ(const Symmetry& sym) const;
|
||||
template<Storage t>
|
||||
std::unique_ptr<typename ctraits<t>::Ttensor> faaDiBrunoG(const Symmetry &sym) const;
|
||||
std::unique_ptr<typename ctraits<t>::Ttensor> faaDiBrunoG(const Symmetry& sym) const;
|
||||
|
||||
// Convenience access methods
|
||||
template<Storage t>
|
||||
typename ctraits<t>::Tg &g();
|
||||
typename ctraits<t>::Tg& g();
|
||||
template<Storage t>
|
||||
const typename ctraits<t>::Tg &g() const;
|
||||
const typename ctraits<t>::Tg& g() const;
|
||||
|
||||
template<Storage t>
|
||||
typename ctraits<t>::Tgs &gs();
|
||||
typename ctraits<t>::Tgs& gs();
|
||||
template<Storage t>
|
||||
const typename ctraits<t>::Tgs &gs() const;
|
||||
const typename ctraits<t>::Tgs& gs() const;
|
||||
|
||||
template<Storage t>
|
||||
const typename ctraits<t>::Tgss &h() const;
|
||||
const typename ctraits<t>::Tgss& h() const;
|
||||
|
||||
template<Storage t>
|
||||
typename ctraits<t>::TG &G();
|
||||
typename ctraits<t>::TG& G();
|
||||
template<Storage t>
|
||||
const typename ctraits<t>::TG &G() const;
|
||||
const typename ctraits<t>::TG& G() const;
|
||||
|
||||
template<Storage t>
|
||||
typename ctraits<t>::TZXstack &Zstack();
|
||||
typename ctraits<t>::TZXstack& Zstack();
|
||||
template<Storage t>
|
||||
const typename ctraits<t>::TZXstack &Zstack() const;
|
||||
const typename ctraits<t>::TZXstack& Zstack() const;
|
||||
|
||||
template<Storage t>
|
||||
typename ctraits<t>::TGXstack &Gstack();
|
||||
typename ctraits<t>::TGXstack& Gstack();
|
||||
template<Storage t>
|
||||
const typename ctraits<t>::TGXstack &Gstack() const;
|
||||
const typename ctraits<t>::TGXstack& Gstack() const;
|
||||
};
|
||||
|
||||
/* This calculates a derivative of f(G(y,u,σ),g(y,u,σ),y,u) of a given
|
||||
|
@ -514,7 +509,7 @@ protected:
|
|||
|
||||
template<Storage t>
|
||||
std::unique_ptr<typename ctraits<t>::Ttensor>
|
||||
KOrderStoch::faaDiBrunoZ(const Symmetry &sym) const
|
||||
KOrderStoch::faaDiBrunoZ(const Symmetry& sym) const
|
||||
{
|
||||
JournalRecordPair pa(journal);
|
||||
pa << "Faà Di Bruno ZX container for " << sym << endrec;
|
||||
|
@ -529,7 +524,7 @@ KOrderStoch::faaDiBrunoZ(const Symmetry &sym) const
|
|||
|
||||
template<Storage t>
|
||||
std::unique_ptr<typename ctraits<t>::Ttensor>
|
||||
KOrderStoch::faaDiBrunoG(const Symmetry &sym) const
|
||||
KOrderStoch::faaDiBrunoG(const Symmetry& sym) const
|
||||
{
|
||||
JournalRecordPair pa(journal);
|
||||
pa << "Faà Di Bruno GX container for " << sym << endrec;
|
||||
|
@ -555,9 +550,9 @@ void
|
|||
KOrderStoch::performStep(int order)
|
||||
{
|
||||
int maxd = g<t>().getMaxDim();
|
||||
KORD_RAISE_IF(order-1 != maxd && (order != 1 || maxd != -1),
|
||||
KORD_RAISE_IF(order - 1 != maxd && (order != 1 || maxd != -1),
|
||||
"Wrong order for KOrderStoch::performStep");
|
||||
for (auto &si : SymmetrySet(order, 4))
|
||||
for (auto& si : SymmetrySet(order, 4))
|
||||
if (si[2] == 0)
|
||||
{
|
||||
JournalRecordPair pa(journal);
|
||||
|
@ -572,8 +567,8 @@ KOrderStoch::performStep(int order)
|
|||
g_sym->mult(-1.0);
|
||||
matA.multInv(*g_sym);
|
||||
g<t>().insert(std::move(g_sym));
|
||||
gs<t>().insert(std::make_unique<typename ctraits<t>::Ttensor>(ypart.nstat, ypart.nys(),
|
||||
*g_sym_ptr));
|
||||
gs<t>().insert(
|
||||
std::make_unique<typename ctraits<t>::Ttensor>(ypart.nstat, ypart.nys(), *g_sym_ptr));
|
||||
|
||||
Gstack<t>().multAndAdd(1, h<t>(), *G_sym_ptr);
|
||||
}
|
||||
|
|
|
@ -19,16 +19,16 @@
|
|||
*/
|
||||
|
||||
#include <chrono>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <random>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
#include "korder.hh"
|
||||
#include "SylvException.hh"
|
||||
#include "korder.hh"
|
||||
|
||||
struct Rand
|
||||
{
|
||||
|
@ -44,32 +44,32 @@ std::mt19937 Rand::mtgen;
|
|||
std::uniform_real_distribution<> Rand::dis;
|
||||
|
||||
ConstTwoDMatrix
|
||||
make_matrix(int rows, int cols, const double *p)
|
||||
make_matrix(int rows, int cols, const double* p)
|
||||
{
|
||||
return ConstTwoDMatrix{rows, cols, ConstVector{p, rows*cols}};
|
||||
return ConstTwoDMatrix {rows, cols, ConstVector {p, rows * cols}};
|
||||
}
|
||||
|
||||
void
|
||||
Rand::init(int n1, int n2, int n3, int n4, int n5)
|
||||
{
|
||||
decltype(mtgen)::result_type seed = n1;
|
||||
seed = 256*seed+n2;
|
||||
seed = 256*seed+n3;
|
||||
seed = 256*seed+n4;
|
||||
seed = 256*seed+n5;
|
||||
seed = 256 * seed + n2;
|
||||
seed = 256 * seed + n3;
|
||||
seed = 256 * seed + n4;
|
||||
seed = 256 * seed + n5;
|
||||
mtgen.seed(seed);
|
||||
}
|
||||
|
||||
double
|
||||
Rand::get(double m)
|
||||
{
|
||||
return 2*m*(dis(mtgen)-0.5);
|
||||
return 2 * m * (dis(mtgen) - 0.5);
|
||||
}
|
||||
|
||||
int
|
||||
Rand::get(int m)
|
||||
{
|
||||
return static_cast<int>(get(0.9999*m));
|
||||
return static_cast<int>(get(0.9999 * m));
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -80,15 +80,13 @@ Rand::discrete(double prob)
|
|||
|
||||
struct SparseGenerator
|
||||
{
|
||||
static std::unique_ptr<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);
|
||||
static std::unique_ptr<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);
|
||||
};
|
||||
|
||||
std::unique_ptr<FSSparseTensor>
|
||||
SparseGenerator::makeTensor(int dim, int nv, int r,
|
||||
double fill, double m)
|
||||
SparseGenerator::makeTensor(int dim, int nv, int r, double fill, double m)
|
||||
{
|
||||
auto res = std::make_unique<FSSparseTensor>(dim, nv, r);
|
||||
FFSTensor dummy(0, nv, dim);
|
||||
|
@ -103,11 +101,10 @@ SparseGenerator::makeTensor(int dim, int nv, int r,
|
|||
}
|
||||
|
||||
void
|
||||
SparseGenerator::fillContainer(TensorContainer<FSSparseTensor> &c,
|
||||
int maxdim, int nv, int r,
|
||||
SparseGenerator::fillContainer(TensorContainer<FSSparseTensor>& c, int maxdim, int nv, int r,
|
||||
double m)
|
||||
{
|
||||
Rand::init(maxdim, nv, r, static_cast<int>(5*m), 0);
|
||||
Rand::init(maxdim, nv, r, static_cast<int>(5 * m), 0);
|
||||
double fill = 0.5;
|
||||
for (int d = 1; d <= maxdim; d++)
|
||||
{
|
||||
|
@ -116,166 +113,159 @@ SparseGenerator::fillContainer(TensorContainer<FSSparseTensor> &c,
|
|||
}
|
||||
}
|
||||
|
||||
const double vdata[] =
|
||||
{ // 3x3
|
||||
0.1307870268, 0.1241940078, 0.1356703123,
|
||||
0.1241940078, 0.1986920419, 0.2010160581,
|
||||
0.1356703123, 0.2010160581, 0.2160336975
|
||||
};
|
||||
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 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 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[] =
|
||||
{ // 10×10 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 vdata2[] = { // 10×10 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 30×20, 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 gy_data2[] = { // 600 items make gy 30×20, 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
|
||||
};
|
||||
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
|
||||
{
|
||||
public:
|
||||
const std::string name;
|
||||
int dim; // dimension of the solved problem
|
||||
int dim; // dimension of the solved problem
|
||||
int nvar; // number of variable of the solved problem
|
||||
TestRunnable(std::string n, int d, int nv)
|
||||
: name{std::move(n)}, dim(d), nvar(nv)
|
||||
TestRunnable(std::string n, int d, int nv) : name {std::move(n)}, dim(d), nvar(nv)
|
||||
{
|
||||
}
|
||||
virtual ~TestRunnable() = default;
|
||||
bool test() const;
|
||||
virtual bool run() const = 0;
|
||||
|
||||
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);
|
||||
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
|
||||
|
@ -289,8 +279,9 @@ TestRunnable::test() const
|
|||
auto end_real = std::chrono::steady_clock::now();
|
||||
std::chrono::duration<double> duration = end_real - start_real;
|
||||
std::cout << "CPU time " << std::setprecision(4) << std::setw(8)
|
||||
<< static_cast<double>(end-start)/CLOCKS_PER_SEC << " (CPU seconds)\n"
|
||||
<< "Real time " << std::setw(8) << duration.count() << " (seconds).....................";
|
||||
<< static_cast<double>(end - start) / CLOCKS_PER_SEC << " (CPU seconds)\n"
|
||||
<< "Real time " << std::setw(8) << duration.count()
|
||||
<< " (seconds).....................";
|
||||
if (passed)
|
||||
std::cout << "passed\n\n";
|
||||
else
|
||||
|
@ -299,20 +290,18 @@ TestRunnable::test() const
|
|||
}
|
||||
|
||||
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)
|
||||
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 ny = nstat + npred + nboth + nforw;
|
||||
int nu = v.nrows();
|
||||
int nz = nboth+nforw+ny+nboth+npred+nu;
|
||||
int nz = nboth + nforw + ny + nboth + npred + nu;
|
||||
SparseGenerator::fillContainer(c, maxdim, nz, ny, 5.0);
|
||||
for (int d = 1; d <= maxdim; d++)
|
||||
std::cout << "\ttensor fill for dim=" << d << " is: "
|
||||
<< std::setprecision(2) << std::setw(6) << std::fixed
|
||||
<< c.get(Symmetry{d}).getFillFactor()*100.0 << " %\n"
|
||||
std::cout << "\ttensor fill for dim=" << d << " is: " << std::setprecision(2) << std::setw(6)
|
||||
<< std::fixed << c.get(Symmetry {d}).getFillFactor() * 100.0 << " %\n"
|
||||
<< std::defaultfloat;
|
||||
Journal jr("out.txt");
|
||||
KOrder kord(nstat, npred, nboth, nforw, c, gy, gu, v, jr);
|
||||
|
@ -322,14 +311,14 @@ TestRunnable::korder_unfold_fold(int maxdim, int unfold_dim,
|
|||
{
|
||||
clock_t pertime = clock();
|
||||
kord.performStep<Storage::unfold>(d);
|
||||
pertime = clock()-pertime;
|
||||
pertime = clock() - pertime;
|
||||
std::cout << "\ttime for unfolded step dim=" << d << ": " << std::setprecision(4)
|
||||
<< static_cast<double>(pertime)/CLOCKS_PER_SEC << std::endl;
|
||||
<< static_cast<double>(pertime) / CLOCKS_PER_SEC << std::endl;
|
||||
clock_t checktime = clock();
|
||||
double err = kord.check<Storage::unfold>(d);
|
||||
checktime = clock()-checktime;
|
||||
checktime = clock() - checktime;
|
||||
std::cout << "\ttime for step check dim=" << d << ": " << std::setprecision(4)
|
||||
<< static_cast<double>(checktime)/CLOCKS_PER_SEC << '\n'
|
||||
<< static_cast<double>(checktime) / CLOCKS_PER_SEC << '\n'
|
||||
<< "\tmax error in step dim=" << d << ": " << std::setprecision(6) << err
|
||||
<< std::endl;
|
||||
maxerror = std::max(err, maxerror);
|
||||
|
@ -339,22 +328,22 @@ TestRunnable::korder_unfold_fold(int maxdim, int unfold_dim,
|
|||
{
|
||||
clock_t swtime = clock();
|
||||
kord.switchToFolded();
|
||||
swtime = clock()-swtime;
|
||||
swtime = clock() - swtime;
|
||||
std::cout << "\ttime for switching dim=" << unfold_dim << ": " << std::setprecision(4)
|
||||
<< static_cast<double>(swtime)/CLOCKS_PER_SEC << std::endl;
|
||||
<< static_cast<double>(swtime) / CLOCKS_PER_SEC << std::endl;
|
||||
|
||||
for (int d = unfold_dim+1; d <= maxdim; d++)
|
||||
for (int d = unfold_dim + 1; d <= maxdim; d++)
|
||||
{
|
||||
clock_t pertime = clock();
|
||||
kord.performStep<Storage::fold>(d);
|
||||
pertime = clock()-pertime;
|
||||
pertime = clock() - pertime;
|
||||
std::cout << "\ttime for folded step dim=" << d << ": " << std::setprecision(4)
|
||||
<< static_cast<double>(pertime)/CLOCKS_PER_SEC << std::endl;
|
||||
<< static_cast<double>(pertime) / CLOCKS_PER_SEC << std::endl;
|
||||
clock_t checktime = clock();
|
||||
double err = kord.check<Storage::fold>(d);
|
||||
checktime = clock()-checktime;
|
||||
checktime = clock() - checktime;
|
||||
std::cout << "\ttime for step check dim=" << d << ": " << std::setprecision(4)
|
||||
<< static_cast<double>(checktime)/CLOCKS_PER_SEC << '\n'
|
||||
<< static_cast<double>(checktime) / CLOCKS_PER_SEC << '\n'
|
||||
<< "\tmax error in step dim=" << d << ": " << std::setprecision(6) << err
|
||||
<< std::endl;
|
||||
maxerror = std::max(err, maxerror);
|
||||
|
@ -366,20 +355,18 @@ TestRunnable::korder_unfold_fold(int maxdim, int unfold_dim,
|
|||
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)
|
||||
UnfoldKOrderSmall() :
|
||||
TestRunnable("unfold-3 fold-4 korder (stat=2,pred=3,both=1,forw=2,u=3,dim=4)", 4, 18)
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
run() const override
|
||||
{
|
||||
TwoDMatrix gy{make_matrix(8, 4, gy_data)};
|
||||
TwoDMatrix gu{make_matrix(8, 3, gu_data)};
|
||||
TwoDMatrix v{make_matrix(3, 3, vdata)};
|
||||
double err = korder_unfold_fold(4, 3, 2, 3, 1, 2,
|
||||
gy, gu, v);
|
||||
TwoDMatrix gy {make_matrix(8, 4, gy_data)};
|
||||
TwoDMatrix gu {make_matrix(8, 3, gu_data)};
|
||||
TwoDMatrix v {make_matrix(3, 3, vdata)};
|
||||
double err = korder_unfold_fold(4, 3, 2, 3, 1, 2, gy, gu, v);
|
||||
|
||||
return err < 5e-7;
|
||||
}
|
||||
|
@ -389,22 +376,20 @@ public:
|
|||
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)
|
||||
UnfoldKOrderSW() :
|
||||
TestRunnable("unfold S&W korder (stat=5,pred=12,both=8,forw=5,u=10,dim=4)", 4, 73)
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
run() const override
|
||||
{
|
||||
TwoDMatrix gy{make_matrix(30, 20, gy_data2)};
|
||||
TwoDMatrix gu{make_matrix(30, 10, gu_data2)};
|
||||
TwoDMatrix v{make_matrix(10, 10, vdata2)};
|
||||
TwoDMatrix gy {make_matrix(30, 20, gy_data2)};
|
||||
TwoDMatrix gu {make_matrix(30, 10, gu_data2)};
|
||||
TwoDMatrix v {make_matrix(10, 10, vdata2)};
|
||||
v.mult(0.001);
|
||||
gu.mult(.01);
|
||||
double err = korder_unfold_fold(4, 4, 5, 12, 8, 5,
|
||||
gy, gu, v);
|
||||
double err = korder_unfold_fold(4, 4, 5, 12, 8, 5, gy, gu, v);
|
||||
|
||||
return err < 0.5;
|
||||
}
|
||||
|
@ -413,22 +398,20 @@ public:
|
|||
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)
|
||||
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 override
|
||||
{
|
||||
TwoDMatrix gy{make_matrix(30, 20, gy_data2)};
|
||||
TwoDMatrix gu{make_matrix(30, 10, gu_data2)};
|
||||
TwoDMatrix v{make_matrix(10, 10, vdata2)};
|
||||
TwoDMatrix gy {make_matrix(30, 20, gy_data2)};
|
||||
TwoDMatrix gu {make_matrix(30, 10, gu_data2)};
|
||||
TwoDMatrix v {make_matrix(10, 10, vdata2)};
|
||||
v.mult(0.001);
|
||||
gu.mult(.01);
|
||||
double err = korder_unfold_fold(4, 3, 5, 12, 8, 5,
|
||||
gy, gu, v);
|
||||
double err = korder_unfold_fold(4, 3, 5, 12, 8, 5, gy, gu, v);
|
||||
|
||||
return err < 0.5;
|
||||
}
|
||||
|
@ -446,7 +429,7 @@ main()
|
|||
// Find maximum dimension and maximum nvar
|
||||
int dmax = 0;
|
||||
int nvmax = 0;
|
||||
for (const auto &test : all_tests)
|
||||
for (const auto& test : all_tests)
|
||||
{
|
||||
if (dmax < test->dim)
|
||||
dmax = test->dim;
|
||||
|
@ -457,19 +440,19 @@ main()
|
|||
|
||||
// Launch the tests
|
||||
int success = 0;
|
||||
for (const auto &test : all_tests)
|
||||
for (const auto& test : all_tests)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (test->test())
|
||||
success++;
|
||||
}
|
||||
catch (const TLException &e)
|
||||
catch (const TLException& e)
|
||||
{
|
||||
std::cout << "Caught TL exception in <" << test->name << ">:" << std::endl;
|
||||
e.print();
|
||||
}
|
||||
catch (SylvException &e)
|
||||
catch (SylvException& e)
|
||||
{
|
||||
std::cout << "Caught Sylv exception in <" << test->name << ">:" << std::endl;
|
||||
e.printMessage();
|
||||
|
@ -477,8 +460,8 @@ main()
|
|||
}
|
||||
|
||||
int nfailed = all_tests.size() - success;
|
||||
std::cout << "There were " << nfailed << " tests that failed out of "
|
||||
<< all_tests.size() << " tests run." << std::endl;
|
||||
std::cout << "There were " << nfailed << " tests that failed out of " << all_tests.size()
|
||||
<< " tests run." << std::endl;
|
||||
|
||||
if (nfailed)
|
||||
return EXIT_FAILURE;
|
||||
|
|
|
@ -24,9 +24,8 @@
|
|||
#include <iostream>
|
||||
#include <utility>
|
||||
|
||||
BlockDiagonal::BlockDiagonal(ConstVector d, int d_size)
|
||||
: QuasiTriangular(std::move(d), d_size),
|
||||
row_len(d_size), col_len(d_size)
|
||||
BlockDiagonal::BlockDiagonal(ConstVector d, int d_size) :
|
||||
QuasiTriangular(std::move(d), d_size), row_len(d_size), col_len(d_size)
|
||||
{
|
||||
for (int i = 0; i < d_size; i++)
|
||||
{
|
||||
|
@ -35,9 +34,8 @@ BlockDiagonal::BlockDiagonal(ConstVector d, int d_size)
|
|||
}
|
||||
}
|
||||
|
||||
BlockDiagonal::BlockDiagonal(const QuasiTriangular &t)
|
||||
: QuasiTriangular(t),
|
||||
row_len(t.nrows()), col_len(t.nrows())
|
||||
BlockDiagonal::BlockDiagonal(const QuasiTriangular& t) :
|
||||
QuasiTriangular(t), row_len(t.nrows()), col_len(t.nrows())
|
||||
{
|
||||
for (int i = 0; i < t.nrows(); i++)
|
||||
{
|
||||
|
@ -73,57 +71,53 @@ BlockDiagonal::setZeroBlockEdge(diag_iter edge)
|
|||
|
||||
int iedge = edge->getIndex();
|
||||
for (diag_iter run = diag_begin(); run != edge; ++run)
|
||||
if (int ind {run->getIndex()};
|
||||
row_len[ind] > iedge)
|
||||
if (int ind {run->getIndex()}; row_len[ind] > iedge)
|
||||
{
|
||||
row_len[ind] = iedge;
|
||||
if (!run->isReal())
|
||||
row_len[ind+1] = iedge;
|
||||
row_len[ind + 1] = iedge;
|
||||
}
|
||||
for (diag_iter run = edge; run != diag_end(); ++run)
|
||||
if (int ind {run->getIndex()};
|
||||
col_len[ind] < iedge)
|
||||
if (int ind {run->getIndex()}; col_len[ind] < iedge)
|
||||
{
|
||||
col_len[ind] = iedge;
|
||||
if (!run->isReal())
|
||||
col_len[ind+1] = iedge;
|
||||
col_len[ind + 1] = iedge;
|
||||
}
|
||||
}
|
||||
|
||||
BlockDiagonal::const_col_iter
|
||||
BlockDiagonal::col_begin(const DiagonalBlock &b) const
|
||||
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]);
|
||||
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)
|
||||
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]);
|
||||
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
|
||||
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]);
|
||||
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)
|
||||
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]);
|
||||
return row_iter(&getData()[d_size * row_len[jbar] + jbar], d_size, b.isReal(), row_len[jbar]);
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -141,8 +135,7 @@ BlockDiagonal::findBlockStart(const_diag_iter from) const
|
|||
if (from != diag_end())
|
||||
{
|
||||
++from;
|
||||
while (from != diag_end()
|
||||
&& col_len[from->getIndex()] != from->getIndex())
|
||||
while (from != diag_end() && col_len[from->getIndex()] != from->getIndex())
|
||||
++from;
|
||||
}
|
||||
return from;
|
||||
|
@ -160,7 +153,7 @@ BlockDiagonal::getLargestBlock() const
|
|||
int ei = diagonal.getSize();
|
||||
if (end != diag_end())
|
||||
ei = end->getIndex();
|
||||
largest = std::max(largest, ei-si);
|
||||
largest = std::max(largest, ei - si);
|
||||
start = end;
|
||||
end = findBlockStart(start);
|
||||
}
|
||||
|
@ -168,19 +161,19 @@ BlockDiagonal::getLargestBlock() const
|
|||
}
|
||||
|
||||
void
|
||||
BlockDiagonal::savePartOfX(int si, int ei, const KronVector &x, Vector &work)
|
||||
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());
|
||||
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
|
||||
BlockDiagonal::multKronBlock(const_diag_iter start, const_diag_iter end, KronVector& x,
|
||||
Vector& work) const
|
||||
{
|
||||
int si = start->getIndex();
|
||||
int ei = diagonal.getSize();
|
||||
|
@ -189,28 +182,27 @@ BlockDiagonal::multKronBlock(const_diag_iter start, const_diag_iter end,
|
|||
savePartOfX(si, ei, x, work);
|
||||
|
||||
for (const_diag_iter di = start; di != end; ++di)
|
||||
if (int jbar {di->getIndex()};
|
||||
di->isReal())
|
||||
if (int jbar {di->getIndex()}; di->isReal())
|
||||
{
|
||||
KronVector xi(x, jbar);
|
||||
xi.zeros();
|
||||
Vector wi(work, (jbar-si)*xi.length(), xi.length());
|
||||
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());
|
||||
Vector wj(work, (col - si) * xi.length(), xi.length());
|
||||
xi.add(*ri, wj);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
KronVector xi(x, jbar);
|
||||
KronVector xii(x, jbar+1);
|
||||
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());
|
||||
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);
|
||||
|
@ -218,7 +210,7 @@ BlockDiagonal::multKronBlock(const_diag_iter start, const_diag_iter end,
|
|||
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());
|
||||
Vector wj(work, (col - si) * xi.length(), xi.length());
|
||||
xi.add(ri.a(), wj);
|
||||
xii.add(ri.b(), wj);
|
||||
}
|
||||
|
@ -226,8 +218,8 @@ BlockDiagonal::multKronBlock(const_diag_iter start, const_diag_iter end,
|
|||
}
|
||||
|
||||
void
|
||||
BlockDiagonal::multKronBlockTrans(const_diag_iter start, const_diag_iter end,
|
||||
KronVector &x, Vector &work) const
|
||||
BlockDiagonal::multKronBlockTrans(const_diag_iter start, const_diag_iter end, KronVector& x,
|
||||
Vector& work) const
|
||||
{
|
||||
int si = start->getIndex();
|
||||
int ei = diagonal.getSize();
|
||||
|
@ -236,28 +228,27 @@ BlockDiagonal::multKronBlockTrans(const_diag_iter start, const_diag_iter end,
|
|||
savePartOfX(si, ei, x, work);
|
||||
|
||||
for (const_diag_iter di = start; di != end; ++di)
|
||||
if (int jbar {di->getIndex()};
|
||||
di->isReal())
|
||||
if (int jbar {di->getIndex()}; di->isReal())
|
||||
{
|
||||
KronVector xi(x, jbar);
|
||||
xi.zeros();
|
||||
Vector wi(work, (jbar-si)*xi.length(), xi.length());
|
||||
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());
|
||||
Vector wj(work, (row - si) * xi.length(), xi.length());
|
||||
xi.add(*ci, wj);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
KronVector xi(x, jbar);
|
||||
KronVector xii(x, jbar+1);
|
||||
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());
|
||||
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);
|
||||
|
@ -265,7 +256,7 @@ BlockDiagonal::multKronBlockTrans(const_diag_iter start, const_diag_iter end,
|
|||
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());
|
||||
Vector wj(work, (row - si) * xi.length(), xi.length());
|
||||
xi.add(ci.a(), wj);
|
||||
xii.add(ci.b(), wj);
|
||||
}
|
||||
|
@ -273,10 +264,10 @@ BlockDiagonal::multKronBlockTrans(const_diag_iter start, const_diag_iter end,
|
|||
}
|
||||
|
||||
void
|
||||
BlockDiagonal::multKron(KronVector &x) const
|
||||
BlockDiagonal::multKron(KronVector& x) const
|
||||
{
|
||||
int largest = getLargestBlock();
|
||||
Vector work(largest *x.getN()*power(x.getM(), x.getDepth()-1));
|
||||
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())
|
||||
|
@ -288,10 +279,10 @@ BlockDiagonal::multKron(KronVector &x) const
|
|||
}
|
||||
|
||||
void
|
||||
BlockDiagonal::multKronTrans(KronVector &x) const
|
||||
BlockDiagonal::multKronTrans(KronVector& x) const
|
||||
{
|
||||
int largest = getLargestBlock();
|
||||
Vector work(largest *x.getN()*power(x.getM(), x.getDepth()-1));
|
||||
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())
|
||||
|
@ -315,14 +306,15 @@ BlockDiagonal::printInfo() const
|
|||
int ei = diagonal.getSize();
|
||||
if (end != diag_end())
|
||||
ei = end->getIndex();
|
||||
std::cout << ' ' << ei-si;
|
||||
std::cout << ' ' << ei - si;
|
||||
num_blocks++;
|
||||
start = end;
|
||||
end = findBlockStart(start);
|
||||
}
|
||||
std::cout << std::endl
|
||||
<< "Num blocks: " << num_blocks << std::endl
|
||||
<< "There are " << getNumZeros() << " zeros out of " << getNumOffdiagonal() << std::endl;
|
||||
<< "There are " << getNumZeros() << " zeros out of " << getNumOffdiagonal()
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
int
|
||||
|
|
|
@ -29,16 +29,18 @@
|
|||
class BlockDiagonal : public QuasiTriangular
|
||||
{
|
||||
std::vector<int> row_len, col_len;
|
||||
|
||||
public:
|
||||
BlockDiagonal(ConstVector d, int d_size);
|
||||
BlockDiagonal(const BlockDiagonal &b) = default;
|
||||
explicit BlockDiagonal(const QuasiTriangular &t);
|
||||
BlockDiagonal &operator=(const QuasiTriangular &t)
|
||||
BlockDiagonal(const BlockDiagonal& b) = default;
|
||||
explicit BlockDiagonal(const QuasiTriangular& t);
|
||||
BlockDiagonal&
|
||||
operator=(const QuasiTriangular& t)
|
||||
{
|
||||
GeneralMatrix::operator=(t);
|
||||
return *this;
|
||||
}
|
||||
BlockDiagonal &operator=(const BlockDiagonal &b) = default;
|
||||
BlockDiagonal& operator=(const BlockDiagonal& b) = default;
|
||||
~BlockDiagonal() override = default;
|
||||
void setZeroBlockEdge(diag_iter edge);
|
||||
int getNumZeros() const;
|
||||
|
@ -46,26 +48,26 @@ public:
|
|||
int getLargestBlock() const;
|
||||
void printInfo() const;
|
||||
|
||||
void multKron(KronVector &x) const override;
|
||||
void multKronTrans(KronVector &x) const override;
|
||||
void multKron(KronVector& x) const override;
|
||||
void multKronTrans(KronVector& x) const override;
|
||||
|
||||
const_col_iter col_begin(const DiagonalBlock &b) const override;
|
||||
col_iter col_begin(const DiagonalBlock &b) override;
|
||||
const_row_iter row_end(const DiagonalBlock &b) const override;
|
||||
row_iter row_end(const DiagonalBlock &b) override;
|
||||
const_col_iter col_begin(const DiagonalBlock& b) const override;
|
||||
col_iter col_begin(const DiagonalBlock& b) override;
|
||||
const_row_iter row_end(const DiagonalBlock& b) const override;
|
||||
row_iter row_end(const DiagonalBlock& b) override;
|
||||
std::unique_ptr<QuasiTriangular>
|
||||
clone() const override
|
||||
{
|
||||
return std::make_unique<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;
|
||||
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 */
|
||||
|
|
|
@ -18,43 +18,43 @@
|
|||
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "SylvException.hh"
|
||||
#include "GeneralMatrix.hh"
|
||||
#include "SylvException.hh"
|
||||
|
||||
#include <dynblas.h>
|
||||
#include <dynlapack.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <cstdlib>
|
||||
#include <cmath>
|
||||
#include <cstdlib>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
|
||||
GeneralMatrix::GeneralMatrix(const GeneralMatrix &m)
|
||||
: data(m.rows*m.cols), rows(m.rows), cols(m.cols), ld(m.rows)
|
||||
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)
|
||||
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, int i, int j, int nrows, int ncols)
|
||||
: data(nrows*ncols), rows(nrows), cols(ncols), ld(nrows)
|
||||
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.data, m.ld*j+i, m.ld*(ncols-1)+nrows), rows(nrows), cols(ncols), ld(m.ld)
|
||||
GeneralMatrix::GeneralMatrix(GeneralMatrix& m, int i, int j, int nrows, int ncols) :
|
||||
data(m.data, m.ld * j + i, m.ld * (ncols - 1) + nrows), rows(nrows), cols(ncols), ld(m.ld)
|
||||
{
|
||||
}
|
||||
|
||||
GeneralMatrix &
|
||||
GeneralMatrix::operator=(const ConstGeneralMatrix &m)
|
||||
GeneralMatrix&
|
||||
GeneralMatrix::operator=(const ConstGeneralMatrix& m)
|
||||
{
|
||||
data = m.data;
|
||||
rows = m.rows;
|
||||
|
@ -66,32 +66,31 @@ GeneralMatrix::operator=(const ConstGeneralMatrix &m)
|
|||
Vector
|
||||
GeneralMatrix::getRow(int row)
|
||||
{
|
||||
return Vector{data, row, ld, cols};
|
||||
return Vector {data, row, ld, cols};
|
||||
}
|
||||
|
||||
Vector
|
||||
GeneralMatrix::getCol(int col)
|
||||
{
|
||||
return Vector{data, ld*col, rows};
|
||||
return Vector {data, ld * col, rows};
|
||||
}
|
||||
|
||||
ConstVector
|
||||
GeneralMatrix::getRow(int row) const
|
||||
{
|
||||
return ConstVector{data, row, ld, cols};
|
||||
return ConstVector {data, row, ld, cols};
|
||||
}
|
||||
|
||||
ConstVector
|
||||
GeneralMatrix::getCol(int col) const
|
||||
{
|
||||
return ConstVector{data, ld*col, rows};
|
||||
return ConstVector {data, ld * col, rows};
|
||||
}
|
||||
|
||||
void
|
||||
GeneralMatrix::place(const ConstGeneralMatrix &m, int i, int j)
|
||||
GeneralMatrix::place(const ConstGeneralMatrix& m, int i, int j)
|
||||
{
|
||||
if (i + m.nrows() > nrows()
|
||||
|| j + m.ncols() > ncols())
|
||||
if (i + m.nrows() > nrows() || j + m.ncols() > ncols())
|
||||
throw SYLV_MES_EXCEPTION("Bad submatrix placement, matrix dimensions exceeded.");
|
||||
|
||||
GeneralMatrix tmpsub(*this, i, j, m.nrows(), m.ncols());
|
||||
|
@ -99,42 +98,41 @@ GeneralMatrix::place(const ConstGeneralMatrix &m, int i, int j)
|
|||
}
|
||||
|
||||
void
|
||||
GeneralMatrix::mult(const ConstGeneralMatrix &a, const ConstGeneralMatrix &b)
|
||||
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)
|
||||
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,
|
||||
[[maybe_unused]] const std::string &dum, double mult)
|
||||
GeneralMatrix::multAndAdd(const ConstGeneralMatrix& a, const ConstGeneralMatrix& b,
|
||||
[[maybe_unused]] const std::string& dum, double mult)
|
||||
{
|
||||
gemm("N", a, "T", b, mult, 1.0);
|
||||
}
|
||||
|
||||
void
|
||||
GeneralMatrix::multAndAdd(const ConstGeneralMatrix &a, [[maybe_unused]] const std::string &dum,
|
||||
const ConstGeneralMatrix &b, double mult)
|
||||
GeneralMatrix::multAndAdd(const ConstGeneralMatrix& a, [[maybe_unused]] const std::string& dum,
|
||||
const ConstGeneralMatrix& b, double mult)
|
||||
{
|
||||
gemm("T", a, "N", b, mult, 1.0);
|
||||
}
|
||||
|
||||
void
|
||||
GeneralMatrix::multAndAdd(const ConstGeneralMatrix &a, [[maybe_unused]] const std::string &dum1,
|
||||
const ConstGeneralMatrix &b, [[maybe_unused]] const std::string &dum2,
|
||||
GeneralMatrix::multAndAdd(const ConstGeneralMatrix& a, [[maybe_unused]] const std::string& dum1,
|
||||
const ConstGeneralMatrix& b, [[maybe_unused]] const std::string& dum2,
|
||||
double mult)
|
||||
{
|
||||
gemm("T", a, "T", b, mult, 1.0);
|
||||
}
|
||||
|
||||
void
|
||||
GeneralMatrix::addOuter(const ConstVector &a, double mult)
|
||||
GeneralMatrix::addOuter(const ConstVector& a, double mult)
|
||||
{
|
||||
if (nrows() != ncols())
|
||||
throw SYLV_MES_EXCEPTION("Matrix is not square in GeneralMatrix::addOuter.");
|
||||
|
@ -145,7 +143,7 @@ GeneralMatrix::addOuter(const ConstVector &a, double mult)
|
|||
for (int i = 0; i < nrows(); i++)
|
||||
for (int j = i; j < nrows(); j++)
|
||||
{
|
||||
double s = mult*a[i]*a[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;
|
||||
|
@ -153,25 +151,25 @@ GeneralMatrix::addOuter(const ConstVector &a, double mult)
|
|||
}
|
||||
|
||||
void
|
||||
GeneralMatrix::multRight(const ConstGeneralMatrix &m)
|
||||
GeneralMatrix::multRight(const ConstGeneralMatrix& m)
|
||||
{
|
||||
gemm_partial_right("N", m, 1.0, 0.0);
|
||||
}
|
||||
|
||||
void
|
||||
GeneralMatrix::multLeft(const ConstGeneralMatrix &m)
|
||||
GeneralMatrix::multLeft(const ConstGeneralMatrix& m)
|
||||
{
|
||||
gemm_partial_left("N", m, 1.0, 0.0);
|
||||
}
|
||||
|
||||
void
|
||||
GeneralMatrix::multRightTrans(const ConstGeneralMatrix &m)
|
||||
GeneralMatrix::multRightTrans(const ConstGeneralMatrix& m)
|
||||
{
|
||||
gemm_partial_right("T", m, 1.0, 0.0);
|
||||
}
|
||||
|
||||
void
|
||||
GeneralMatrix::multLeftTrans(const ConstGeneralMatrix &m)
|
||||
GeneralMatrix::multLeftTrans(const ConstGeneralMatrix& m)
|
||||
{
|
||||
gemm_partial_left("T", m, 1.0, 0.0);
|
||||
}
|
||||
|
@ -229,7 +227,7 @@ GeneralMatrix::mult(double a)
|
|||
|
||||
// here we must be careful for ld
|
||||
void
|
||||
GeneralMatrix::add(double a, const ConstGeneralMatrix &m)
|
||||
GeneralMatrix::add(double a, const ConstGeneralMatrix& m)
|
||||
{
|
||||
if (m.nrows() != rows || m.ncols() != cols)
|
||||
throw SYLV_MES_EXCEPTION("Matrix has different size in GeneralMatrix::add.");
|
||||
|
@ -239,32 +237,32 @@ GeneralMatrix::add(double a, const ConstGeneralMatrix &m)
|
|||
else
|
||||
for (int i = 0; i < rows; i++)
|
||||
for (int j = 0; j < cols; j++)
|
||||
get(i, j) += a*m.get(i, j);
|
||||
get(i, j) += a * m.get(i, j);
|
||||
}
|
||||
|
||||
void
|
||||
GeneralMatrix::add(double a, const ConstGeneralMatrix &m, [[maybe_unused]] const std::string &dum)
|
||||
GeneralMatrix::add(double a, const ConstGeneralMatrix& m, [[maybe_unused]] const std::string& dum)
|
||||
{
|
||||
if (m.nrows() != cols || m.ncols() != 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);
|
||||
get(i, j) += a * m.get(j, i);
|
||||
}
|
||||
|
||||
void
|
||||
GeneralMatrix::copy(const ConstGeneralMatrix &m, int ioff, int joff)
|
||||
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);
|
||||
get(i, j) = m.get(i + ioff, j + joff);
|
||||
}
|
||||
|
||||
void
|
||||
GeneralMatrix::gemm(const std::string &transa, const ConstGeneralMatrix &a,
|
||||
const std::string &transb, const ConstGeneralMatrix &b,
|
||||
double alpha, double beta)
|
||||
GeneralMatrix::gemm(const std::string& transa, const ConstGeneralMatrix& a,
|
||||
const std::string& transb, const ConstGeneralMatrix& b, double alpha,
|
||||
double beta)
|
||||
{
|
||||
int opa_rows = a.nrows();
|
||||
int opa_cols = a.ncols();
|
||||
|
@ -281,9 +279,7 @@ GeneralMatrix::gemm(const std::string &transa, const ConstGeneralMatrix &a,
|
|||
opb_cols = b.nrows();
|
||||
}
|
||||
|
||||
if (opa_rows != nrows()
|
||||
|| opb_cols != ncols()
|
||||
|| opa_cols != opb_rows)
|
||||
if (opa_rows != nrows() || opb_cols != ncols() || opa_cols != opb_rows)
|
||||
throw SYLV_MES_EXCEPTION("Wrong dimensions for matrix multiplication.");
|
||||
|
||||
blas_int m = opa_rows;
|
||||
|
@ -293,9 +289,9 @@ GeneralMatrix::gemm(const std::string &transa, const ConstGeneralMatrix &a,
|
|||
blas_int ldb = b.ld;
|
||||
blas_int ldc = ld;
|
||||
if (lda > 0 && ldb > 0 && ldc > 0)
|
||||
dgemm(transa.c_str(), transb.c_str(), &m, &n, &k, &alpha, a.data.base(), &lda,
|
||||
b.data.base(), &ldb, &beta, data.base(), &ldc);
|
||||
else if (nrows()*ncols() > 0)
|
||||
dgemm(transa.c_str(), transb.c_str(), &m, &n, &k, &alpha, a.data.base(), &lda, b.data.base(),
|
||||
&ldb, &beta, data.base(), &ldc);
|
||||
else if (nrows() * ncols() > 0)
|
||||
{
|
||||
if (beta == 0.0)
|
||||
zeros();
|
||||
|
@ -305,70 +301,73 @@ GeneralMatrix::gemm(const std::string &transa, const ConstGeneralMatrix &a,
|
|||
}
|
||||
|
||||
void
|
||||
GeneralMatrix::gemm_partial_left(const std::string &trans, const ConstGeneralMatrix &m,
|
||||
GeneralMatrix::gemm_partial_left(const std::string& trans, const ConstGeneralMatrix& m,
|
||||
double alpha, double beta)
|
||||
{
|
||||
int icol;
|
||||
for (icol = 0; icol + md_length < cols; icol += md_length)
|
||||
{
|
||||
GeneralMatrix incopy(const_cast<const GeneralMatrix &>(*this), 0, icol, rows, md_length);
|
||||
GeneralMatrix incopy(const_cast<const GeneralMatrix&>(*this), 0, icol, rows, md_length);
|
||||
GeneralMatrix inplace(*this, 0, icol, rows, md_length);
|
||||
inplace.gemm(trans, m, "N", ConstGeneralMatrix(incopy), alpha, beta);
|
||||
}
|
||||
if (cols > icol)
|
||||
{
|
||||
GeneralMatrix incopy(const_cast<const GeneralMatrix &>(*this), 0, icol, rows, cols - icol);
|
||||
GeneralMatrix incopy(const_cast<const GeneralMatrix&>(*this), 0, icol, rows, cols - icol);
|
||||
GeneralMatrix inplace(*this, 0, icol, rows, cols - icol);
|
||||
inplace.gemm(trans, m, "N", ConstGeneralMatrix(incopy), alpha, beta);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
GeneralMatrix::gemm_partial_right(const std::string &trans, const ConstGeneralMatrix &m,
|
||||
GeneralMatrix::gemm_partial_right(const std::string& trans, const ConstGeneralMatrix& m,
|
||||
double alpha, double beta)
|
||||
{
|
||||
int irow;
|
||||
for (irow = 0; irow + md_length < rows; irow += md_length)
|
||||
{
|
||||
GeneralMatrix incopy(const_cast<const GeneralMatrix &>(*this), irow, 0, md_length, cols);
|
||||
GeneralMatrix incopy(const_cast<const GeneralMatrix&>(*this), irow, 0, md_length, cols);
|
||||
GeneralMatrix inplace(*this, irow, 0, md_length, cols);
|
||||
inplace.gemm("N", ConstGeneralMatrix(incopy), trans, m, alpha, beta);
|
||||
}
|
||||
if (rows > irow)
|
||||
{
|
||||
GeneralMatrix incopy(const_cast<const GeneralMatrix &>(*this), irow, 0, rows - irow, cols);
|
||||
GeneralMatrix incopy(const_cast<const GeneralMatrix&>(*this), irow, 0, rows - irow, cols);
|
||||
GeneralMatrix inplace(*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())
|
||||
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())
|
||||
{
|
||||
// FIXME: check that the submatrix 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())
|
||||
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())
|
||||
{
|
||||
// FIXME: check that the submatrix is fully in the matrix
|
||||
}
|
||||
|
||||
ConstGeneralMatrix::ConstGeneralMatrix(const GeneralMatrix &m)
|
||||
: data(m.data), rows(m.rows), cols(m.cols), ld(m.ld)
|
||||
ConstGeneralMatrix::ConstGeneralMatrix(const GeneralMatrix& m) :
|
||||
data(m.data), rows(m.rows), cols(m.cols), ld(m.ld)
|
||||
{
|
||||
}
|
||||
|
||||
ConstVector
|
||||
ConstGeneralMatrix::getRow(int row) const
|
||||
{
|
||||
return ConstVector{data, row, ld, cols};
|
||||
return ConstVector {data, row, ld, cols};
|
||||
}
|
||||
|
||||
ConstVector
|
||||
ConstGeneralMatrix::getCol(int col) const
|
||||
{
|
||||
return ConstVector{data, ld*col, rows};
|
||||
return ConstVector {data, ld * col, rows};
|
||||
}
|
||||
|
||||
double
|
||||
|
@ -396,7 +395,7 @@ ConstGeneralMatrix::getNorm1() const
|
|||
}
|
||||
|
||||
void
|
||||
ConstGeneralMatrix::multVec(double a, Vector &x, double b, const ConstVector &d) const
|
||||
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.");
|
||||
|
@ -409,15 +408,12 @@ ConstGeneralMatrix::multVec(double a, Vector &x, double b, const ConstVector &d)
|
|||
blas_int incx = d.skip();
|
||||
double beta = a;
|
||||
blas_int incy = x.skip();
|
||||
dgemv("N", &mm, &nn, &alpha, data.base(), &lda, d.base(), &incx,
|
||||
&beta, x.base(), &incy);
|
||||
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
|
||||
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.");
|
||||
|
@ -430,14 +426,14 @@ ConstGeneralMatrix::multVecTrans(double a, Vector &x, double b,
|
|||
blas_int incx = d.skip();
|
||||
double beta = a;
|
||||
blas_int incy = x.skip();
|
||||
dgemv("T", &mm, &nn, &alpha, data.base(), &lda, d.base(), &incx,
|
||||
&beta, x.base(), &incy);
|
||||
dgemv("T", &mm, &nn, &alpha, data.base(), &lda, d.base(), &incx, &beta, x.base(), &incy);
|
||||
}
|
||||
}
|
||||
|
||||
/* m = inv(this)*m */
|
||||
void
|
||||
ConstGeneralMatrix::multInvLeft(const std::string &trans, int mrows, int mcols, int mld, double *d) const
|
||||
ConstGeneralMatrix::multInvLeft(const std::string& trans, int mrows, int mcols, int mld,
|
||||
double* d) const
|
||||
{
|
||||
if (rows != cols)
|
||||
throw SYLV_MES_EXCEPTION("The matrix is not square for inversion.");
|
||||
|
@ -451,28 +447,27 @@ ConstGeneralMatrix::multInvLeft(const std::string &trans, int mrows, int mcols,
|
|||
lapack_int info;
|
||||
lapack_int rows2 = rows, mcols2 = mcols, mld2 = mld, lda = inv.ld;
|
||||
dgetrf(&rows2, &rows2, inv.getData().base(), &lda, ipiv.get(), &info);
|
||||
dgetrs(trans.c_str(), &rows2, &mcols2, inv.base(), &lda, ipiv.get(), d,
|
||||
&mld2, &info);
|
||||
dgetrs(trans.c_str(), &rows2, &mcols2, inv.base(), &lda, ipiv.get(), d, &mld2, &info);
|
||||
}
|
||||
}
|
||||
|
||||
/* m = inv(this)*m */
|
||||
void
|
||||
ConstGeneralMatrix::multInvLeft(GeneralMatrix &m) const
|
||||
ConstGeneralMatrix::multInvLeft(GeneralMatrix& m) const
|
||||
{
|
||||
multInvLeft("N", m.nrows(), m.ncols(), m.getLD(), m.getData().base());
|
||||
}
|
||||
|
||||
/* m = inv(this')*m */
|
||||
void
|
||||
ConstGeneralMatrix::multInvLeftTrans(GeneralMatrix &m) const
|
||||
ConstGeneralMatrix::multInvLeftTrans(GeneralMatrix& m) const
|
||||
{
|
||||
multInvLeft("T", m.nrows(), m.ncols(), m.getLD(), m.getData().base());
|
||||
}
|
||||
|
||||
/* d = inv(this)*d */
|
||||
void
|
||||
ConstGeneralMatrix::multInvLeft(Vector &d) const
|
||||
ConstGeneralMatrix::multInvLeft(Vector& d) const
|
||||
{
|
||||
if (d.skip() != 1)
|
||||
throw SYLV_MES_EXCEPTION("Skip≠1 not implemented in ConstGeneralMatrix::multInvLeft(Vector&)");
|
||||
|
@ -482,7 +477,7 @@ ConstGeneralMatrix::multInvLeft(Vector &d) const
|
|||
|
||||
/* d = inv(this')*d */
|
||||
void
|
||||
ConstGeneralMatrix::multInvLeftTrans(Vector &d) const
|
||||
ConstGeneralMatrix::multInvLeftTrans(Vector& d) const
|
||||
{
|
||||
if (d.skip() != 1)
|
||||
throw SYLV_MES_EXCEPTION("Skip≠1 not implemented in ConstGeneralMatrix::multInvLeft(Vector&)");
|
||||
|
@ -517,8 +512,7 @@ ConstGeneralMatrix::print() const
|
|||
std::cout << "rows=" << rows << ", cols=" << cols << std::endl;
|
||||
for (int i = 0; i < rows; i++)
|
||||
{
|
||||
std::cout << "row " << i << ':' << std::endl
|
||||
<< std::setprecision(3);
|
||||
std::cout << "row " << i << ':' << std::endl << std::setprecision(3);
|
||||
for (int j = 0; j < cols; j++)
|
||||
std::cout << std::setw(6) << get(i, j) << ' ';
|
||||
std::cout << std::endl;
|
||||
|
@ -527,7 +521,7 @@ ConstGeneralMatrix::print() const
|
|||
}
|
||||
|
||||
void
|
||||
SVDDecomp::construct(const GeneralMatrix &A)
|
||||
SVDDecomp::construct(const GeneralMatrix& A)
|
||||
{
|
||||
// quick exit if empty matrix
|
||||
if (minmn == 0)
|
||||
|
@ -543,26 +537,24 @@ SVDDecomp::construct(const GeneralMatrix &A)
|
|||
|
||||
lapack_int m = AA.nrows();
|
||||
lapack_int n = AA.ncols();
|
||||
double *a = AA.base();
|
||||
double* a = AA.base();
|
||||
lapack_int lda = AA.getLD();
|
||||
double *s = sigma.base();
|
||||
double *u = U.base();
|
||||
double* s = sigma.base();
|
||||
double* u = U.base();
|
||||
lapack_int ldu = U.getLD();
|
||||
double *vt = VT.base();
|
||||
double* vt = VT.base();
|
||||
lapack_int ldvt = VT.getLD();
|
||||
double tmpwork;
|
||||
lapack_int lwork = -1;
|
||||
lapack_int info;
|
||||
|
||||
auto iwork = std::make_unique<lapack_int[]>(8*minmn);
|
||||
auto iwork = std::make_unique<lapack_int[]>(8 * minmn);
|
||||
// query for optimal lwork
|
||||
dgesdd("A", &m, &n, a, &lda, s, u, &ldu, vt, &ldvt, &tmpwork,
|
||||
&lwork, iwork.get(), &info);
|
||||
dgesdd("A", &m, &n, a, &lda, s, u, &ldu, vt, &ldvt, &tmpwork, &lwork, iwork.get(), &info);
|
||||
lwork = static_cast<lapack_int>(tmpwork);
|
||||
Vector work(lwork);
|
||||
// do the decomposition
|
||||
dgesdd("A", &m, &n, a, &lda, s, u, &ldu, vt, &ldvt, work.base(),
|
||||
&lwork, iwork.get(), &info);
|
||||
dgesdd("A", &m, &n, a, &lda, s, u, &ldu, vt, &ldvt, work.base(), &lwork, iwork.get(), &info);
|
||||
if (info < 0)
|
||||
throw SYLV_MES_EXCEPTION("Internal error in SVDDecomp constructor");
|
||||
if (info == 0)
|
||||
|
@ -570,7 +562,7 @@ SVDDecomp::construct(const GeneralMatrix &A)
|
|||
}
|
||||
|
||||
void
|
||||
SVDDecomp::solve(const ConstGeneralMatrix &B, GeneralMatrix &X) const
|
||||
SVDDecomp::solve(const ConstGeneralMatrix& B, GeneralMatrix& X) const
|
||||
{
|
||||
if (B.nrows() != U.nrows())
|
||||
throw SYLV_MES_EXCEPTION("Incompatible number of rows ");
|
||||
|
@ -581,20 +573,20 @@ SVDDecomp::solve(const ConstGeneralMatrix &B, GeneralMatrix &X) const
|
|||
|
||||
// determine nz=number of zeros in the end of sigma
|
||||
int nz = 0;
|
||||
while (nz < minmn && sigma[minmn-1-nz] < rcond*sigma[0])
|
||||
while (nz < minmn && sigma[minmn - 1 - nz] < rcond * sigma[0])
|
||||
nz++;
|
||||
// take relevant B for sigma inversion
|
||||
int m = U.nrows();
|
||||
int n = VT.ncols();
|
||||
GeneralMatrix Bprime(transpose(U) * B, m-minmn, 0, minmn-nz, B.ncols());
|
||||
GeneralMatrix Bprime(transpose(U) * B, m - minmn, 0, minmn - nz, B.ncols());
|
||||
// solve sigma
|
||||
for (int i = 0; i < minmn-nz; i++)
|
||||
Bprime.getRow(i).mult(1.0/sigma[i]);
|
||||
for (int i = 0; i < minmn - nz; i++)
|
||||
Bprime.getRow(i).mult(1.0 / sigma[i]);
|
||||
// solve VT
|
||||
X.zeros();
|
||||
//- copy Bprime to right place of X
|
||||
for (int i = 0; i < minmn-nz; i++)
|
||||
X.getRow(n-minmn+i) = Bprime.getRow(i);
|
||||
for (int i = 0; i < minmn - nz; i++)
|
||||
X.getRow(n - minmn + i) = Bprime.getRow(i);
|
||||
//- multiply with VT
|
||||
X.multLeftTrans(VT);
|
||||
}
|
||||
|
|
|
@ -21,36 +21,36 @@
|
|||
#ifndef GENERAL_MATRIX_H
|
||||
#define GENERAL_MATRIX_H
|
||||
|
||||
#include "Vector.hh"
|
||||
#include "SylvException.hh"
|
||||
#include "Vector.hh"
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
template<class T>
|
||||
class TransposedMatrix
|
||||
{
|
||||
friend class GeneralMatrix;
|
||||
template<class T2>
|
||||
friend GeneralMatrix operator*(const ConstGeneralMatrix &a, const TransposedMatrix<T2> &b);
|
||||
friend GeneralMatrix operator*(const ConstGeneralMatrix& a, const TransposedMatrix<T2>& b);
|
||||
template<class T2>
|
||||
friend GeneralMatrix operator*(const TransposedMatrix<T2> &a, const ConstGeneralMatrix &b);
|
||||
friend GeneralMatrix operator*(const TransposedMatrix<T2>& a, const ConstGeneralMatrix& b);
|
||||
template<class T1, class T2>
|
||||
friend GeneralMatrix operator*(const TransposedMatrix<T1> &a, const TransposedMatrix<T2> &b);
|
||||
friend GeneralMatrix operator*(const TransposedMatrix<T1>& a, const TransposedMatrix<T2>& b);
|
||||
|
||||
private:
|
||||
T &orig;
|
||||
T& orig;
|
||||
|
||||
public:
|
||||
TransposedMatrix(T &orig_arg) : orig{orig_arg}
|
||||
{
|
||||
};
|
||||
TransposedMatrix(T& orig_arg) : orig {orig_arg} {};
|
||||
};
|
||||
|
||||
// Syntactic sugar for representing a transposed matrix
|
||||
template<class T>
|
||||
TransposedMatrix<T>
|
||||
transpose(T &m)
|
||||
transpose(T& m)
|
||||
{
|
||||
return TransposedMatrix<T>(m);
|
||||
}
|
||||
|
@ -60,50 +60,51 @@ class GeneralMatrix;
|
|||
class ConstGeneralMatrix
|
||||
{
|
||||
friend class GeneralMatrix;
|
||||
friend GeneralMatrix operator*(const ConstGeneralMatrix &a, const ConstGeneralMatrix &b);
|
||||
friend GeneralMatrix operator*(const ConstGeneralMatrix& a, const ConstGeneralMatrix& b);
|
||||
template<class T>
|
||||
friend GeneralMatrix operator*(const ConstGeneralMatrix &a, const TransposedMatrix<T> &b);
|
||||
friend GeneralMatrix operator*(const ConstGeneralMatrix& a, const TransposedMatrix<T>& b);
|
||||
template<class T>
|
||||
friend GeneralMatrix operator*(const TransposedMatrix<T> &a, const ConstGeneralMatrix &b);
|
||||
friend GeneralMatrix operator*(const TransposedMatrix<T>& a, const ConstGeneralMatrix& b);
|
||||
template<class T1, class T2>
|
||||
friend GeneralMatrix operator*(const TransposedMatrix<T1> &a, const TransposedMatrix<T2> &b);
|
||||
friend GeneralMatrix operator*(const TransposedMatrix<T1>& a, const TransposedMatrix<T2>& b);
|
||||
|
||||
protected:
|
||||
ConstVector data; // Has unit-stride
|
||||
int rows;
|
||||
int cols;
|
||||
int ld;
|
||||
|
||||
public:
|
||||
ConstGeneralMatrix(ConstVector d, int m, int n)
|
||||
: data(std::move(d)), rows(m), cols(n), ld(m)
|
||||
ConstGeneralMatrix(ConstVector d, int m, int n) : data(std::move(d)), rows(m), cols(n), ld(m)
|
||||
{
|
||||
if (data.skip() > 1)
|
||||
throw SYLV_MES_EXCEPTION("Vector must have unit-stride");
|
||||
if (data.length() < m*n)
|
||||
if (data.length() < m * n)
|
||||
throw SYLV_MES_EXCEPTION("Vector is too small");
|
||||
}
|
||||
ConstGeneralMatrix(const ConstGeneralMatrix &m) = default;
|
||||
ConstGeneralMatrix(ConstGeneralMatrix &&m) = default;
|
||||
ConstGeneralMatrix(const ConstGeneralMatrix& m) = default;
|
||||
ConstGeneralMatrix(ConstGeneralMatrix&& m) = default;
|
||||
// Implicit conversion from GeneralMatrix is ok, since it's cheap
|
||||
ConstGeneralMatrix(const GeneralMatrix &m);
|
||||
ConstGeneralMatrix(const GeneralMatrix& m);
|
||||
// Create submatrix (with data sharing)
|
||||
ConstGeneralMatrix(const GeneralMatrix &m, int i, int j, int nrows, int ncols);
|
||||
ConstGeneralMatrix(const GeneralMatrix& m, int i, int j, int nrows, int ncols);
|
||||
// Create submatrix (with data sharing)
|
||||
ConstGeneralMatrix(const ConstGeneralMatrix &m, int i, int j, int nrows, int ncols);
|
||||
ConstGeneralMatrix(const ConstGeneralMatrix& m, int i, int j, int nrows, int ncols);
|
||||
#if defined(MATLAB_MEX_FILE) || defined(OCTAVE_MEX_FILE)
|
||||
explicit ConstGeneralMatrix(const mxArray *p)
|
||||
: data(p), rows{static_cast<int>(mxGetM(p))}, cols{static_cast<int>(mxGetN(p))}, ld{rows}
|
||||
explicit ConstGeneralMatrix(const mxArray* p) :
|
||||
data(p), rows {static_cast<int>(mxGetM(p))}, cols {static_cast<int>(mxGetN(p))}, ld {rows}
|
||||
{
|
||||
}
|
||||
#endif
|
||||
virtual ~ConstGeneralMatrix() = default;
|
||||
|
||||
ConstGeneralMatrix &operator=(const ConstGeneralMatrix &v) = delete;
|
||||
ConstGeneralMatrix &operator=(ConstGeneralMatrix &&v) = delete;
|
||||
ConstGeneralMatrix& operator=(const ConstGeneralMatrix& v) = delete;
|
||||
ConstGeneralMatrix& operator=(ConstGeneralMatrix&& v) = delete;
|
||||
|
||||
const double &
|
||||
const double&
|
||||
get(int i, int j) const
|
||||
{
|
||||
return data[j*ld+i];
|
||||
return data[j * ld + i];
|
||||
}
|
||||
int
|
||||
nrows() const
|
||||
|
@ -120,12 +121,12 @@ public:
|
|||
{
|
||||
return ld;
|
||||
}
|
||||
const double *
|
||||
const double*
|
||||
base() const
|
||||
{
|
||||
return data.base();
|
||||
}
|
||||
const ConstVector &
|
||||
const ConstVector&
|
||||
getData() const
|
||||
{
|
||||
return data;
|
||||
|
@ -136,91 +137,92 @@ public:
|
|||
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;
|
||||
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;
|
||||
void multVecTrans(double a, Vector& x, double b, const ConstVector& d) const;
|
||||
/* x = x + this*d */
|
||||
void
|
||||
multaVec(Vector &x, const ConstVector &d) const
|
||||
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
|
||||
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
|
||||
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
|
||||
multsVecTrans(Vector& x, const ConstVector& d) const
|
||||
{
|
||||
multVecTrans(1.0, x, -1.0, d);
|
||||
}
|
||||
/* m = inv(this)*m */
|
||||
void multInvLeft(GeneralMatrix &m) const;
|
||||
void multInvLeft(GeneralMatrix& m) const;
|
||||
/* m = inv(this')*m */
|
||||
void multInvLeftTrans(GeneralMatrix &m) const;
|
||||
void multInvLeftTrans(GeneralMatrix& m) const;
|
||||
/* d = inv(this)*d */
|
||||
void multInvLeft(Vector &d) const;
|
||||
void multInvLeft(Vector& d) const;
|
||||
/* d = inv(this')*d */
|
||||
void multInvLeftTrans(Vector &d) const;
|
||||
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 std::string &trans, int mrows, int mcols, int mld, double *d) const;
|
||||
void multInvLeft(const std::string& trans, int mrows, int mcols, int mld, double* d) const;
|
||||
};
|
||||
|
||||
class GeneralMatrix
|
||||
{
|
||||
friend class ConstGeneralMatrix;
|
||||
friend GeneralMatrix operator*(const ConstGeneralMatrix &a, const ConstGeneralMatrix &b);
|
||||
friend GeneralMatrix operator*(const ConstGeneralMatrix& a, const ConstGeneralMatrix& b);
|
||||
template<class T>
|
||||
friend GeneralMatrix operator*(const ConstGeneralMatrix &a, const TransposedMatrix<T> &b);
|
||||
friend GeneralMatrix operator*(const ConstGeneralMatrix& a, const TransposedMatrix<T>& b);
|
||||
template<class T>
|
||||
friend GeneralMatrix operator*(const TransposedMatrix<T> &a, const ConstGeneralMatrix &b);
|
||||
friend GeneralMatrix operator*(const TransposedMatrix<T>& a, const ConstGeneralMatrix& b);
|
||||
template<class T1, class T2>
|
||||
friend GeneralMatrix operator*(const TransposedMatrix<T1> &a, const TransposedMatrix<T2> &b);
|
||||
friend GeneralMatrix operator*(const TransposedMatrix<T1>& a, const TransposedMatrix<T2>& b);
|
||||
|
||||
protected:
|
||||
Vector data; // Has unit-stride
|
||||
int rows;
|
||||
int cols;
|
||||
int ld;
|
||||
|
||||
public:
|
||||
GeneralMatrix(int m, int n)
|
||||
: data(m*n), rows(m), cols(n), ld(m)
|
||||
GeneralMatrix(int m, int n) : data(m * n), rows(m), cols(n), ld(m)
|
||||
{
|
||||
}
|
||||
GeneralMatrix(Vector d, int m, int n)
|
||||
: data(std::move(d)), rows(m), cols(n), ld(m)
|
||||
GeneralMatrix(Vector d, int m, int n) : data(std::move(d)), rows(m), cols(n), ld(m)
|
||||
{
|
||||
if (data.skip() > 1)
|
||||
throw SYLV_MES_EXCEPTION("Vector must have unit-stride");
|
||||
if (data.length() < m*n)
|
||||
if (data.length() < m * n)
|
||||
throw SYLV_MES_EXCEPTION("Vector is too small");
|
||||
}
|
||||
|
||||
/* The copies will have ld==rows, for memory efficiency (hence we do not use
|
||||
the default copy constructor) */
|
||||
GeneralMatrix(const GeneralMatrix &m);
|
||||
GeneralMatrix(const GeneralMatrix& m);
|
||||
// We don't want implict conversion from ConstGeneralMatrix, since it's expensive
|
||||
explicit GeneralMatrix(const ConstGeneralMatrix &m);
|
||||
explicit GeneralMatrix(const ConstGeneralMatrix& m);
|
||||
|
||||
GeneralMatrix(GeneralMatrix &&m) = default;
|
||||
GeneralMatrix(GeneralMatrix&& m) = default;
|
||||
|
||||
template<class T>
|
||||
explicit GeneralMatrix(const TransposedMatrix<T> &m)
|
||||
: data(m.orig.rows*m.orig.cols), rows(m.orig.cols), cols(m.orig.rows), ld(rows)
|
||||
explicit GeneralMatrix(const TransposedMatrix<T>& m) :
|
||||
data(m.orig.rows * m.orig.cols), rows(m.orig.cols), cols(m.orig.rows), ld(rows)
|
||||
{
|
||||
for (int i = 0; i < rows; i++)
|
||||
for (int j = 0; j < cols; j++)
|
||||
|
@ -228,31 +230,31 @@ public:
|
|||
}
|
||||
|
||||
// Create submatrix (with data copy)
|
||||
GeneralMatrix(const GeneralMatrix &m, int i, int j, int nrows, int ncols);
|
||||
GeneralMatrix(const GeneralMatrix& m, int i, int j, int nrows, int ncols);
|
||||
// Create submatrix (with data sharing)
|
||||
GeneralMatrix(GeneralMatrix &m, int i, int j, int nrows, int ncols);
|
||||
GeneralMatrix(GeneralMatrix& m, int i, int j, int nrows, int ncols);
|
||||
|
||||
#if defined(MATLAB_MEX_FILE) || defined(OCTAVE_MEX_FILE)
|
||||
explicit GeneralMatrix(mxArray *p)
|
||||
: data(p), rows{static_cast<int>(mxGetM(p))}, cols{static_cast<int>(mxGetN(p))}, ld{rows}
|
||||
explicit GeneralMatrix(mxArray* p) :
|
||||
data(p), rows {static_cast<int>(mxGetM(p))}, cols {static_cast<int>(mxGetN(p))}, ld {rows}
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
virtual ~GeneralMatrix() = default;
|
||||
GeneralMatrix &operator=(const GeneralMatrix &m) = default;
|
||||
GeneralMatrix &operator=(GeneralMatrix &&m) = default;
|
||||
GeneralMatrix &operator=(const ConstGeneralMatrix &m);
|
||||
GeneralMatrix& operator=(const GeneralMatrix& m) = default;
|
||||
GeneralMatrix& operator=(GeneralMatrix&& m) = default;
|
||||
GeneralMatrix& operator=(const ConstGeneralMatrix& m);
|
||||
|
||||
const double &
|
||||
const double&
|
||||
get(int i, int j) const
|
||||
{
|
||||
return data[j*ld+i];
|
||||
return data[j * ld + i];
|
||||
}
|
||||
double &
|
||||
double&
|
||||
get(int i, int j)
|
||||
{
|
||||
return data[j*ld+i];
|
||||
return data[j * ld + i];
|
||||
}
|
||||
int
|
||||
nrows() const
|
||||
|
@ -269,17 +271,17 @@ public:
|
|||
{
|
||||
return ld;
|
||||
}
|
||||
double *
|
||||
double*
|
||||
base()
|
||||
{
|
||||
return data.base();
|
||||
}
|
||||
const double *
|
||||
const double*
|
||||
base() const
|
||||
{
|
||||
return data.base();
|
||||
}
|
||||
Vector &
|
||||
Vector&
|
||||
getData()
|
||||
{
|
||||
return data;
|
||||
|
@ -306,139 +308,137 @@ public:
|
|||
}
|
||||
|
||||
/* place matrix m to the position (i,j) */
|
||||
void place(const ConstGeneralMatrix &m, int i, int j);
|
||||
void place(const ConstGeneralMatrix& m, int i, int j);
|
||||
void
|
||||
place(const GeneralMatrix &m, int i, int j)
|
||||
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 ConstGeneralMatrix& a, const ConstGeneralMatrix& b);
|
||||
void
|
||||
mult(const GeneralMatrix &a, const GeneralMatrix &b)
|
||||
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 ConstGeneralMatrix& a, const ConstGeneralMatrix& b, double mult = 1.0);
|
||||
void
|
||||
multAndAdd(const GeneralMatrix &a, const GeneralMatrix &b,
|
||||
double mult = 1.0)
|
||||
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 std::string &dum, double mult = 1.0);
|
||||
void multAndAdd(const ConstGeneralMatrix& a, const ConstGeneralMatrix& b, const std::string& dum,
|
||||
double mult = 1.0);
|
||||
void
|
||||
multAndAdd(const GeneralMatrix &a, const GeneralMatrix &b,
|
||||
const std::string &dum, double mult = 1.0)
|
||||
multAndAdd(const GeneralMatrix& a, const GeneralMatrix& b, const std::string& dum,
|
||||
double mult = 1.0)
|
||||
{
|
||||
multAndAdd(ConstGeneralMatrix(a), ConstGeneralMatrix(b), dum, mult);
|
||||
}
|
||||
|
||||
// this = this + scalar·aᵀ·b
|
||||
void multAndAdd(const ConstGeneralMatrix &a, const std::string &dum, const ConstGeneralMatrix &b,
|
||||
void multAndAdd(const ConstGeneralMatrix& a, const std::string& dum, const ConstGeneralMatrix& b,
|
||||
double mult = 1.0);
|
||||
void
|
||||
multAndAdd(const GeneralMatrix &a, const std::string &dum, const GeneralMatrix &b,
|
||||
multAndAdd(const GeneralMatrix& a, const std::string& 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 std::string &dum1,
|
||||
const ConstGeneralMatrix &b, const std::string &dum2, double mult = 1.0);
|
||||
void multAndAdd(const ConstGeneralMatrix& a, const std::string& dum1, const ConstGeneralMatrix& b,
|
||||
const std::string& dum2, double mult = 1.0);
|
||||
void
|
||||
multAndAdd(const GeneralMatrix &a, const std::string &dum1,
|
||||
const GeneralMatrix &b, const std::string &dum2, double mult = 1.0)
|
||||
multAndAdd(const GeneralMatrix& a, const std::string& dum1, const GeneralMatrix& b,
|
||||
const std::string& 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 ConstVector& a, double mult = 1.0);
|
||||
void
|
||||
addOuter(const Vector &a, double mult = 1.0)
|
||||
addOuter(const Vector& a, double mult = 1.0)
|
||||
{
|
||||
addOuter(ConstVector(a), mult);
|
||||
}
|
||||
|
||||
// this = this·m
|
||||
void multRight(const ConstGeneralMatrix &m);
|
||||
void multRight(const ConstGeneralMatrix& m);
|
||||
void
|
||||
multRight(const GeneralMatrix &m)
|
||||
multRight(const GeneralMatrix& m)
|
||||
{
|
||||
multRight(ConstGeneralMatrix(m));
|
||||
}
|
||||
|
||||
// this = m·this
|
||||
void multLeft(const ConstGeneralMatrix &m);
|
||||
void multLeft(const ConstGeneralMatrix& m);
|
||||
void
|
||||
multLeft(const GeneralMatrix &m)
|
||||
multLeft(const GeneralMatrix& m)
|
||||
{
|
||||
multLeft(ConstGeneralMatrix(m));
|
||||
}
|
||||
|
||||
// this = this·mᵀ
|
||||
void multRightTrans(const ConstGeneralMatrix &m);
|
||||
void multRightTrans(const ConstGeneralMatrix& m);
|
||||
void
|
||||
multRightTrans(const GeneralMatrix &m)
|
||||
multRightTrans(const GeneralMatrix& m)
|
||||
{
|
||||
multRightTrans(ConstGeneralMatrix(m));
|
||||
}
|
||||
|
||||
// this = mᵀ·this
|
||||
void multLeftTrans(const ConstGeneralMatrix &m);
|
||||
void multLeftTrans(const ConstGeneralMatrix& m);
|
||||
void
|
||||
multLeftTrans(const GeneralMatrix &m)
|
||||
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
|
||||
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
|
||||
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
|
||||
multaVec(Vector& x, const ConstVector& d) const
|
||||
{
|
||||
ConstGeneralMatrix(*this).multaVec(x, d);
|
||||
}
|
||||
|
||||
// x = x + thisᵀ·d */
|
||||
void
|
||||
multaVecTrans(Vector &x, const ConstVector &d) const
|
||||
multaVecTrans(Vector& x, const ConstVector& d) const
|
||||
{
|
||||
ConstGeneralMatrix(*this).multaVecTrans(x, d);
|
||||
}
|
||||
|
||||
// x = x - this·d
|
||||
void
|
||||
multsVec(Vector &x, const ConstVector &d) const
|
||||
multsVec(Vector& x, const ConstVector& d) const
|
||||
{
|
||||
ConstGeneralMatrix(*this).multsVec(x, d);
|
||||
}
|
||||
|
||||
// x = x - thisᵀ·d
|
||||
void
|
||||
multsVecTrans(Vector &x, const ConstVector &d) const
|
||||
multsVecTrans(Vector& x, const ConstVector& d) const
|
||||
{
|
||||
ConstGeneralMatrix(*this).multsVecTrans(x, d);
|
||||
}
|
||||
|
@ -459,17 +459,17 @@ public:
|
|||
void mult(double a);
|
||||
|
||||
// this = this + scalar·m
|
||||
void add(double a, const ConstGeneralMatrix &m);
|
||||
void add(double a, const ConstGeneralMatrix& m);
|
||||
void
|
||||
add(double a, const GeneralMatrix &m)
|
||||
add(double a, const GeneralMatrix& m)
|
||||
{
|
||||
add(a, ConstGeneralMatrix(m));
|
||||
}
|
||||
|
||||
// this = this + scalar·mᵀ
|
||||
void add(double a, const ConstGeneralMatrix &m, const std::string &dum);
|
||||
void add(double a, const ConstGeneralMatrix& m, const std::string& dum);
|
||||
void
|
||||
add(double a, const GeneralMatrix &m, const std::string &dum)
|
||||
add(double a, const GeneralMatrix& m, const std::string& dum)
|
||||
{
|
||||
add(a, ConstGeneralMatrix(m), dum);
|
||||
}
|
||||
|
@ -491,42 +491,38 @@ public:
|
|||
{
|
||||
ConstGeneralMatrix(*this).print();
|
||||
}
|
||||
|
||||
private:
|
||||
void copy(const ConstGeneralMatrix &m, int ioff = 0, int joff = 0);
|
||||
void copy(const ConstGeneralMatrix& m, int ioff = 0, int joff = 0);
|
||||
void
|
||||
copy(const GeneralMatrix &m, int ioff = 0, int joff = 0)
|
||||
copy(const GeneralMatrix& m, int ioff = 0, int joff = 0)
|
||||
{
|
||||
copy(ConstGeneralMatrix(m), ioff, joff);
|
||||
}
|
||||
|
||||
void gemm(const std::string &transa, const ConstGeneralMatrix &a,
|
||||
const std::string &transb, const ConstGeneralMatrix &b,
|
||||
double alpha, double beta);
|
||||
void gemm(const std::string& transa, const ConstGeneralMatrix& a, const std::string& transb,
|
||||
const ConstGeneralMatrix& b, double alpha, double beta);
|
||||
void
|
||||
gemm(const std::string &transa, const GeneralMatrix &a,
|
||||
const std::string &transb, const GeneralMatrix &b,
|
||||
double alpha, double beta)
|
||||
gemm(const std::string& transa, const GeneralMatrix& a, const std::string& transb,
|
||||
const GeneralMatrix& b, double alpha, double beta)
|
||||
{
|
||||
gemm(transa, ConstGeneralMatrix(a), transb, ConstGeneralMatrix(b),
|
||||
alpha, beta);
|
||||
gemm(transa, ConstGeneralMatrix(a), transb, ConstGeneralMatrix(b), alpha, beta);
|
||||
}
|
||||
|
||||
/* this = this * op(m) (without whole copy of this) */
|
||||
void gemm_partial_right(const std::string &trans, const ConstGeneralMatrix &m,
|
||||
double alpha, double beta);
|
||||
void gemm_partial_right(const std::string& trans, const ConstGeneralMatrix& m, double alpha,
|
||||
double beta);
|
||||
void
|
||||
gemm_partial_right(const std::string &trans, const GeneralMatrix &m,
|
||||
double alpha, double beta)
|
||||
gemm_partial_right(const std::string& 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 std::string &trans, const ConstGeneralMatrix &m,
|
||||
double alpha, double beta);
|
||||
void gemm_partial_left(const std::string& trans, const ConstGeneralMatrix& m, double alpha,
|
||||
double beta);
|
||||
void
|
||||
gemm_partial_left(const std::string &trans, const GeneralMatrix &m,
|
||||
double alpha, double beta)
|
||||
gemm_partial_left(const std::string& trans, const GeneralMatrix& m, double alpha, double beta)
|
||||
{
|
||||
gemm_partial_left(trans, ConstGeneralMatrix(m), alpha, beta);
|
||||
}
|
||||
|
@ -537,7 +533,7 @@ private:
|
|||
|
||||
// Computes a·b
|
||||
inline GeneralMatrix
|
||||
operator*(const ConstGeneralMatrix &a, const ConstGeneralMatrix &b)
|
||||
operator*(const ConstGeneralMatrix& a, const ConstGeneralMatrix& b)
|
||||
{
|
||||
GeneralMatrix m(a.rows, b.cols);
|
||||
m.gemm("N", a, "N", b, 1.0, 0.0);
|
||||
|
@ -547,7 +543,7 @@ operator*(const ConstGeneralMatrix &a, const ConstGeneralMatrix &b)
|
|||
// Computes a·bᵀ
|
||||
template<class T>
|
||||
GeneralMatrix
|
||||
operator*(const ConstGeneralMatrix &a, const TransposedMatrix<T> &b)
|
||||
operator*(const ConstGeneralMatrix& a, const TransposedMatrix<T>& b)
|
||||
{
|
||||
GeneralMatrix m(a.rows, b.orig.rows);
|
||||
m.gemm("N", a, "T", b.orig, 1.0, 0.0);
|
||||
|
@ -557,7 +553,7 @@ operator*(const ConstGeneralMatrix &a, const TransposedMatrix<T> &b)
|
|||
// Computes aᵀ·b
|
||||
template<class T>
|
||||
GeneralMatrix
|
||||
operator*(const TransposedMatrix<T> &a, const ConstGeneralMatrix &b)
|
||||
operator*(const TransposedMatrix<T>& a, const ConstGeneralMatrix& b)
|
||||
{
|
||||
GeneralMatrix m(a.orig.cols, b.cols);
|
||||
m.gemm("T", a.orig, "N", b, 1.0, 0.0);
|
||||
|
@ -567,7 +563,7 @@ operator*(const TransposedMatrix<T> &a, const ConstGeneralMatrix &b)
|
|||
// Computes aᵀ·bᵀ
|
||||
template<class T1, class T2>
|
||||
GeneralMatrix
|
||||
operator*(const TransposedMatrix<T1> &a, const TransposedMatrix<T2> &b)
|
||||
operator*(const TransposedMatrix<T1>& a, const TransposedMatrix<T2>& b)
|
||||
{
|
||||
GeneralMatrix m(a.orig.cols, b.orig.rows);
|
||||
m.gemm("T", a.orig, "T", b.orig, 1.0, 0.0);
|
||||
|
@ -587,35 +583,34 @@ protected:
|
|||
GeneralMatrix VT;
|
||||
// Convered flag
|
||||
bool conv;
|
||||
|
||||
public:
|
||||
SVDDecomp(const GeneralMatrix &A)
|
||||
: minmn(std::min<int>(A.nrows(), A.ncols())),
|
||||
sigma(minmn),
|
||||
U(A.nrows(), A.nrows()),
|
||||
VT(A.ncols(), A.ncols()),
|
||||
conv(false)
|
||||
SVDDecomp(const GeneralMatrix& A) :
|
||||
minmn(std::min<int>(A.nrows(), A.ncols())), sigma(minmn), U(A.nrows(), A.nrows()),
|
||||
VT(A.ncols(), A.ncols()), conv(false)
|
||||
{
|
||||
construct(A);
|
||||
}
|
||||
const GeneralMatrix &
|
||||
const GeneralMatrix&
|
||||
getU() const
|
||||
{
|
||||
return U;
|
||||
}
|
||||
const GeneralMatrix &
|
||||
const GeneralMatrix&
|
||||
getVT() const
|
||||
{
|
||||
return VT;
|
||||
}
|
||||
void solve(const ConstGeneralMatrix &B, GeneralMatrix &X) const;
|
||||
void solve(const ConstGeneralMatrix& B, GeneralMatrix& X) const;
|
||||
void
|
||||
solve(const ConstVector &b, Vector &x) const
|
||||
solve(const ConstVector& b, Vector& x) const
|
||||
{
|
||||
GeneralMatrix xmat(x, x.length(), 1);
|
||||
solve(ConstGeneralMatrix(b, b.length(), 1), xmat);
|
||||
}
|
||||
|
||||
private:
|
||||
void construct(const GeneralMatrix &A);
|
||||
void construct(const GeneralMatrix& A);
|
||||
};
|
||||
|
||||
#endif /* GENERAL_MATRIX_H */
|
||||
|
|
|
@ -19,58 +19,50 @@
|
|||
*/
|
||||
|
||||
#include "GeneralSylvester.hh"
|
||||
#include "IterativeSylvester.hh"
|
||||
#include "SchurDecomp.hh"
|
||||
#include "SylvException.hh"
|
||||
#include "TriangularSylvester.hh"
|
||||
#include "IterativeSylvester.hh"
|
||||
#include "int_power.hh"
|
||||
|
||||
#include <ctime>
|
||||
|
||||
GeneralSylvester::GeneralSylvester(int ord, int n, int m, int zero_cols,
|
||||
const ConstVector &da, const ConstVector &db,
|
||||
const ConstVector &dc, const ConstVector &dd,
|
||||
const SylvParams &ps)
|
||||
: pars(ps),
|
||||
order(ord), a(Vector{da}, n),
|
||||
b(Vector{db}, n, n-zero_cols), c(Vector{dc}, m), d(Vector{dd}, n, power(m, order)),
|
||||
solved(false)
|
||||
GeneralSylvester::GeneralSylvester(int ord, int n, int m, int zero_cols, const ConstVector& da,
|
||||
const ConstVector& db, const ConstVector& dc,
|
||||
const ConstVector& dd, const SylvParams& ps) :
|
||||
pars(ps),
|
||||
order(ord), a(Vector {da}, n), b(Vector {db}, n, n - zero_cols), c(Vector {dc}, m),
|
||||
d(Vector {dd}, n, power(m, order)), solved(false)
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
GeneralSylvester::GeneralSylvester(int ord, int n, int m, int zero_cols,
|
||||
const ConstVector &da, const ConstVector &db,
|
||||
const ConstVector &dc, Vector &dd,
|
||||
const SylvParams &ps)
|
||||
: pars(ps),
|
||||
order(ord), a(Vector{da}, n),
|
||||
b(Vector{db}, n, n-zero_cols), c(Vector{dc}, m), d(dd, n, power(m, order)),
|
||||
solved(false)
|
||||
GeneralSylvester::GeneralSylvester(int ord, int n, int m, int zero_cols, const ConstVector& da,
|
||||
const ConstVector& db, const ConstVector& dc, Vector& dd,
|
||||
const SylvParams& ps) :
|
||||
pars(ps),
|
||||
order(ord), a(Vector {da}, n), b(Vector {db}, n, n - zero_cols), c(Vector {dc}, m),
|
||||
d(dd, n, power(m, order)), solved(false)
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
GeneralSylvester::GeneralSylvester(int ord, int n, int m, int zero_cols,
|
||||
const ConstVector &da, const ConstVector &db,
|
||||
const ConstVector &dc, const ConstVector &dd,
|
||||
bool alloc_for_check)
|
||||
: pars(alloc_for_check),
|
||||
order(ord), a(Vector{da}, n),
|
||||
b(Vector{db}, n, n-zero_cols), c(Vector{dc}, m), d(Vector{dd}, n, power(m, order)),
|
||||
solved(false)
|
||||
GeneralSylvester::GeneralSylvester(int ord, int n, int m, int zero_cols, const ConstVector& da,
|
||||
const ConstVector& db, const ConstVector& dc,
|
||||
const ConstVector& dd, bool alloc_for_check) :
|
||||
pars(alloc_for_check),
|
||||
order(ord), a(Vector {da}, n), b(Vector {db}, n, n - zero_cols), c(Vector {dc}, m),
|
||||
d(Vector {dd}, n, power(m, order)), solved(false)
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
GeneralSylvester::GeneralSylvester(int ord, int n, int m, int zero_cols,
|
||||
const ConstVector &da, const ConstVector &db,
|
||||
const ConstVector &dc, Vector &dd,
|
||||
bool alloc_for_check)
|
||||
: pars(alloc_for_check),
|
||||
order(ord), a(Vector{da}, n),
|
||||
b(Vector{db}, n, n-zero_cols), c(Vector{dc}, m), d(dd, n, power(m, order)),
|
||||
solved(false)
|
||||
GeneralSylvester::GeneralSylvester(int ord, int n, int m, int zero_cols, const ConstVector& da,
|
||||
const ConstVector& db, const ConstVector& dc, Vector& dd,
|
||||
bool alloc_for_check) :
|
||||
pars(alloc_for_check),
|
||||
order(ord), a(Vector {da}, n), b(Vector {db}, n, n - zero_cols), c(Vector {dc}, m),
|
||||
d(dd, n, power(m, order)), solved(false)
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
@ -112,27 +104,27 @@ GeneralSylvester::solve()
|
|||
d.multLeftI(bdecomp->getQ());
|
||||
d.multRightKron(cdecomp->getInvQ(), order);
|
||||
clock_t end = clock();
|
||||
pars.cpu_time = static_cast<double>(end-start)/CLOCKS_PER_SEC;
|
||||
pars.cpu_time = static_cast<double>(end - start) / CLOCKS_PER_SEC;
|
||||
|
||||
solved = true;
|
||||
}
|
||||
|
||||
void
|
||||
GeneralSylvester::check(const ConstVector &ds)
|
||||
GeneralSylvester::check(const ConstVector& ds)
|
||||
{
|
||||
if (!solved)
|
||||
throw SYLV_MES_EXCEPTION("Cannot run check on system, which is not solved yet.");
|
||||
|
||||
// calculate xcheck = A·X+B·X·⊗ⁱC−D
|
||||
SylvMatrix dcheck(d.nrows(), d.ncols());
|
||||
dcheck.multLeft(b.nrows()-b.ncols(), b, d);
|
||||
dcheck.multLeft(b.nrows() - b.ncols(), b, d);
|
||||
dcheck.multRightKron(c, order);
|
||||
dcheck.multAndAdd(a, d);
|
||||
dcheck.getData().add(-1.0, ds);
|
||||
// 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();
|
||||
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();
|
||||
}
|
||||
|
|
|
@ -21,8 +21,8 @@
|
|||
#ifndef GENERAL_SYLVESTER_H
|
||||
#define GENERAL_SYLVESTER_H
|
||||
|
||||
#include "SylvMatrix.hh"
|
||||
#include "SimilarityDecomp.hh"
|
||||
#include "SylvMatrix.hh"
|
||||
#include "SylvesterSolver.hh"
|
||||
|
||||
#include <memory>
|
||||
|
@ -39,25 +39,21 @@ class GeneralSylvester
|
|||
std::unique_ptr<SchurDecompZero> bdecomp;
|
||||
std::unique_ptr<SimilarityDecomp> cdecomp;
|
||||
std::unique_ptr<SylvesterSolver> sylv;
|
||||
|
||||
public:
|
||||
// Construct with my copy of d
|
||||
GeneralSylvester(int ord, int n, int m, int zero_cols,
|
||||
const ConstVector &da, const ConstVector &db,
|
||||
const ConstVector &dc, const ConstVector &dd,
|
||||
const SylvParams &ps);
|
||||
GeneralSylvester(int ord, int n, int m, int zero_cols,
|
||||
const ConstVector &da, const ConstVector &db,
|
||||
const ConstVector &dc, const ConstVector &dd,
|
||||
GeneralSylvester(int ord, int n, int m, int zero_cols, const ConstVector& da,
|
||||
const ConstVector& db, const ConstVector& dc, const ConstVector& dd,
|
||||
const SylvParams& ps);
|
||||
GeneralSylvester(int ord, int n, int m, int zero_cols, const ConstVector& da,
|
||||
const ConstVector& db, const ConstVector& dc, const ConstVector& dd,
|
||||
bool alloc_for_check = false);
|
||||
// Construct with provided storage for d
|
||||
GeneralSylvester(int ord, int n, int m, int zero_cols,
|
||||
const ConstVector &da, const ConstVector &db,
|
||||
const ConstVector &dc, Vector &dd,
|
||||
GeneralSylvester(int ord, int n, int m, int zero_cols, const ConstVector& da,
|
||||
const ConstVector& db, const ConstVector& dc, Vector& dd,
|
||||
bool alloc_for_check = false);
|
||||
GeneralSylvester(int ord, int n, int m, int zero_cols,
|
||||
const ConstVector &da, const ConstVector &db,
|
||||
const ConstVector &dc, Vector &dd,
|
||||
const SylvParams &ps);
|
||||
GeneralSylvester(int ord, int n, int m, int zero_cols, const ConstVector& da,
|
||||
const ConstVector& db, const ConstVector& dc, Vector& dd, const SylvParams& ps);
|
||||
virtual ~GeneralSylvester() = default;
|
||||
int
|
||||
getM() const
|
||||
|
@ -69,23 +65,24 @@ public:
|
|||
{
|
||||
return a.nrows();
|
||||
}
|
||||
const double *
|
||||
const double*
|
||||
getResult() const
|
||||
{
|
||||
return d.base();
|
||||
}
|
||||
const SylvParams &
|
||||
const SylvParams&
|
||||
getParams() const
|
||||
{
|
||||
return pars;
|
||||
}
|
||||
SylvParams &
|
||||
SylvParams&
|
||||
getParams()
|
||||
{
|
||||
return pars;
|
||||
}
|
||||
void solve();
|
||||
void check(const ConstVector &ds);
|
||||
void check(const ConstVector& ds);
|
||||
|
||||
private:
|
||||
void init();
|
||||
};
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
#include "KronUtils.hh"
|
||||
|
||||
void
|
||||
IterativeSylvester::solve(SylvParams &pars, KronVector &x) const
|
||||
IterativeSylvester::solve(SylvParams& pars, KronVector& x) const
|
||||
{
|
||||
int max_steps = *(pars.max_num_iter);
|
||||
int steps = 1;
|
||||
|
@ -45,9 +45,9 @@ IterativeSylvester::solve(SylvParams &pars, KronVector &x) const
|
|||
}
|
||||
|
||||
double
|
||||
IterativeSylvester::performFirstStep(KronVector &x) const
|
||||
IterativeSylvester::performFirstStep(KronVector& x) const
|
||||
{
|
||||
KronVector xtmp(const_cast<const KronVector &>(x));
|
||||
KronVector xtmp(const_cast<const KronVector&>(x));
|
||||
KronUtils::multKron(*matrixF, *matrixK, xtmp);
|
||||
x.add(-1., xtmp);
|
||||
double norm = xtmp.getMax();
|
||||
|
@ -55,10 +55,9 @@ IterativeSylvester::performFirstStep(KronVector &x) const
|
|||
}
|
||||
|
||||
double
|
||||
IterativeSylvester::performStep(const QuasiTriangular &k, const QuasiTriangular &f,
|
||||
KronVector &x)
|
||||
IterativeSylvester::performStep(const QuasiTriangular& k, const QuasiTriangular& f, KronVector& x)
|
||||
{
|
||||
KronVector xtmp(const_cast<const KronVector &>(x));
|
||||
KronVector xtmp(const_cast<const KronVector&>(x));
|
||||
KronUtils::multKron(f, k, xtmp);
|
||||
x.add(1.0, xtmp);
|
||||
double norm = xtmp.getMax();
|
||||
|
|
|
@ -21,31 +21,30 @@
|
|||
#ifndef ITERATIVE_SYLVESTER_H
|
||||
#define ITERATIVE_SYLVESTER_H
|
||||
|
||||
#include "SylvesterSolver.hh"
|
||||
#include "KronVector.hh"
|
||||
#include "QuasiTriangular.hh"
|
||||
#include "SimilarityDecomp.hh"
|
||||
#include "SylvesterSolver.hh"
|
||||
|
||||
class IterativeSylvester : public SylvesterSolver
|
||||
{
|
||||
public:
|
||||
IterativeSylvester(const QuasiTriangular &k, const QuasiTriangular &f)
|
||||
: SylvesterSolver(k, f)
|
||||
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 SchurDecomp& fdecomp) :
|
||||
SylvesterSolver(kdecomp, fdecomp)
|
||||
{
|
||||
}
|
||||
IterativeSylvester(const SchurDecompZero &kdecomp, const SimilarityDecomp &fdecomp)
|
||||
: SylvesterSolver(kdecomp, fdecomp)
|
||||
IterativeSylvester(const SchurDecompZero& kdecomp, const SimilarityDecomp& fdecomp) :
|
||||
SylvesterSolver(kdecomp, fdecomp)
|
||||
{
|
||||
}
|
||||
void solve(SylvParams &pars, KronVector &x) const override;
|
||||
void solve(SylvParams& pars, KronVector& x) const override;
|
||||
|
||||
private:
|
||||
double performFirstStep(KronVector &x) const;
|
||||
static double performStep(const QuasiTriangular &k, const QuasiTriangular &f,
|
||||
KronVector &x);
|
||||
double performFirstStep(KronVector& x) const;
|
||||
static double performStep(const QuasiTriangular& k, const QuasiTriangular& f, KronVector& x);
|
||||
};
|
||||
|
||||
#endif /* ITERATIVE_SYLVESTER_H */
|
||||
|
|
|
@ -22,8 +22,7 @@
|
|||
#include "int_power.hh"
|
||||
|
||||
void
|
||||
KronUtils::multAtLevel(int level, const QuasiTriangular &t,
|
||||
KronVector &x)
|
||||
KronUtils::multAtLevel(int level, const QuasiTriangular& t, KronVector& x)
|
||||
{
|
||||
if (0 < level && level < x.getDepth())
|
||||
for (int i = 0; i < x.getM(); i++)
|
||||
|
@ -38,7 +37,7 @@ KronUtils::multAtLevel(int level, const QuasiTriangular &t,
|
|||
}
|
||||
else if (0 == level && 0 == x.getDepth())
|
||||
{
|
||||
Vector b(const_cast<const KronVector &>(x));
|
||||
Vector b(const_cast<const KronVector&>(x));
|
||||
t.multVec(x, b);
|
||||
}
|
||||
else // 0 < level == depth
|
||||
|
@ -46,8 +45,7 @@ KronUtils::multAtLevel(int level, const QuasiTriangular &t,
|
|||
}
|
||||
|
||||
void
|
||||
KronUtils::multAtLevelTrans(int level, const QuasiTriangular &t,
|
||||
KronVector &x)
|
||||
KronUtils::multAtLevelTrans(int level, const QuasiTriangular& t, KronVector& x)
|
||||
{
|
||||
if (0 < level && level < x.getDepth())
|
||||
for (int i = 0; i < x.getM(); i++)
|
||||
|
@ -62,7 +60,7 @@ KronUtils::multAtLevelTrans(int level, const QuasiTriangular &t,
|
|||
}
|
||||
else if (level == 0 && 0 == x.getDepth())
|
||||
{
|
||||
Vector b(const_cast<const KronVector &>(x));
|
||||
Vector b(const_cast<const KronVector&>(x));
|
||||
t.multVecTrans(x, b);
|
||||
}
|
||||
else // 0 < level == depth
|
||||
|
@ -70,8 +68,7 @@ KronUtils::multAtLevelTrans(int level, const QuasiTriangular &t,
|
|||
}
|
||||
|
||||
void
|
||||
KronUtils::multKron(const QuasiTriangular &f, const QuasiTriangular &k,
|
||||
KronVector &x)
|
||||
KronUtils::multKron(const QuasiTriangular& f, const QuasiTriangular& k, KronVector& x)
|
||||
{
|
||||
multAtLevel(0, k, x);
|
||||
if (x.getDepth() > 0)
|
||||
|
|
|
@ -31,14 +31,11 @@ public:
|
|||
T must be m×m, number of ⊗ is d, level is the number of Iₘ’s
|
||||
between T and Iₙ plus 1. If level=0, then we multiply by Iₘ⊗…⊗Iₘ⊗T,
|
||||
T must be n×n. */
|
||||
static void multAtLevel(int level, const QuasiTriangular &t,
|
||||
KronVector &x);
|
||||
static void multAtLevelTrans(int level, const QuasiTriangular &t,
|
||||
KronVector &x);
|
||||
static void multAtLevel(int level, const QuasiTriangular& t, KronVector& x);
|
||||
static void multAtLevelTrans(int level, const QuasiTriangular& t, KronVector& x);
|
||||
|
||||
// Computes x=(Fᵀ⊗Fᵀ⊗…⊗K)·x
|
||||
static void multKron(const QuasiTriangular &f, const QuasiTriangular &k,
|
||||
KronVector &x);
|
||||
static void multKron(const QuasiTriangular& f, const QuasiTriangular& k, KronVector& x);
|
||||
};
|
||||
|
||||
#endif /* KRON_UTILS_H */
|
||||
|
|
|
@ -24,33 +24,30 @@
|
|||
|
||||
#include <utility>
|
||||
|
||||
KronVector::KronVector(int mm, int nn, int dp)
|
||||
: Vector(power(mm, dp)*nn), m(mm), n(nn), depth(dp)
|
||||
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)
|
||||
KronVector::KronVector(Vector& v, int mm, int nn, int dp) : Vector(v), m(mm), n(nn), depth(dp)
|
||||
{
|
||||
if (length() != power(m, depth)*n)
|
||||
if (length() != power(m, depth) * n)
|
||||
throw SYLV_MES_EXCEPTION("Bad conversion KronVector from Vector.");
|
||||
}
|
||||
|
||||
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)
|
||||
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), m(v.m), n(v.n), depth(v.depth)
|
||||
KronVector::KronVector(const ConstKronVector& v) : Vector(v), m(v.m), n(v.n), depth(v.depth)
|
||||
{
|
||||
}
|
||||
|
||||
KronVector &
|
||||
KronVector::operator=(const ConstKronVector &v)
|
||||
KronVector&
|
||||
KronVector::operator=(const ConstKronVector& v)
|
||||
{
|
||||
Vector::operator=(v);
|
||||
m = v.m;
|
||||
|
@ -59,8 +56,8 @@ KronVector::operator=(const ConstKronVector &v)
|
|||
return *this;
|
||||
}
|
||||
|
||||
KronVector &
|
||||
KronVector::operator=(const Vector &v)
|
||||
KronVector&
|
||||
KronVector::operator=(const Vector& v)
|
||||
{
|
||||
if (length() != v.length())
|
||||
throw SYLV_MES_EXCEPTION("Wrong lengths for vector operator =.");
|
||||
|
@ -68,37 +65,37 @@ KronVector::operator=(const Vector &v)
|
|||
return *this;
|
||||
}
|
||||
|
||||
ConstKronVector::ConstKronVector(const KronVector &v)
|
||||
: ConstVector(v), m(v.m), n(v.n), depth(v.depth)
|
||||
ConstKronVector::ConstKronVector(const KronVector& v) :
|
||||
ConstVector(v), m(v.m), n(v.n), depth(v.depth)
|
||||
{
|
||||
}
|
||||
|
||||
ConstKronVector::ConstKronVector(const Vector &v, int mm, int nn, int dp)
|
||||
: ConstVector(v), m(mm), n(nn), depth(dp)
|
||||
ConstKronVector::ConstKronVector(const Vector& v, int mm, int nn, int dp) :
|
||||
ConstVector(v), m(mm), n(nn), depth(dp)
|
||||
{
|
||||
if (length() != power(m, depth)*n)
|
||||
if (length() != power(m, depth) * n)
|
||||
throw SYLV_MES_EXCEPTION("Bad conversion KronVector from Vector.");
|
||||
}
|
||||
|
||||
ConstKronVector::ConstKronVector(ConstVector v, int mm, int nn, int dp)
|
||||
: ConstVector(std::move(v)), m(mm), n(nn), depth(dp)
|
||||
ConstKronVector::ConstKronVector(ConstVector v, int mm, int nn, int dp) :
|
||||
ConstVector(std::move(v)), m(mm), n(nn), depth(dp)
|
||||
{
|
||||
if (length() != power(m, depth)*n)
|
||||
if (length() != power(m, depth) * n)
|
||||
throw SYLV_MES_EXCEPTION("Bad conversion KronVector from Vector.");
|
||||
}
|
||||
|
||||
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)
|
||||
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)
|
||||
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.");
|
||||
|
|
|
@ -28,23 +28,25 @@ class ConstKronVector;
|
|||
class KronVector : public Vector
|
||||
{
|
||||
friend class ConstKronVector;
|
||||
|
||||
protected:
|
||||
int m{0};
|
||||
int n{0};
|
||||
int depth{0};
|
||||
int m {0};
|
||||
int n {0};
|
||||
int depth {0};
|
||||
|
||||
public:
|
||||
KronVector() = default;
|
||||
KronVector(const KronVector &v) = default;
|
||||
KronVector(KronVector &&v) = default;
|
||||
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 KronVector& v) = default;
|
||||
KronVector(KronVector&& v) = default;
|
||||
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
|
||||
// We don't want implict conversion from ConstKronVector, since it's expensive
|
||||
explicit KronVector(const ConstKronVector &v); // new instance and copy
|
||||
KronVector &operator=(const KronVector &v) = default;
|
||||
KronVector &operator=(KronVector &&v) = default;
|
||||
KronVector &operator=(const ConstKronVector &v);
|
||||
KronVector &operator=(const Vector &v);
|
||||
explicit KronVector(const ConstKronVector& v); // new instance and copy
|
||||
KronVector& operator=(const KronVector& v) = default;
|
||||
KronVector& operator=(KronVector&& v) = default;
|
||||
KronVector& operator=(const ConstKronVector& v);
|
||||
KronVector& operator=(const Vector& v);
|
||||
int
|
||||
getM() const
|
||||
{
|
||||
|
@ -65,21 +67,23 @@ public:
|
|||
class ConstKronVector : public ConstVector
|
||||
{
|
||||
friend class KronVector;
|
||||
|
||||
protected:
|
||||
int m;
|
||||
int n;
|
||||
int depth;
|
||||
|
||||
public:
|
||||
// Implicit conversion from KronVector is ok, since it's cheap
|
||||
ConstKronVector(const KronVector &v);
|
||||
ConstKronVector(const ConstKronVector &v) = default;
|
||||
ConstKronVector(ConstKronVector &&v) = default;
|
||||
ConstKronVector(const Vector &v, int mm, int nn, int dp);
|
||||
ConstKronVector(const KronVector& v);
|
||||
ConstKronVector(const ConstKronVector& v) = default;
|
||||
ConstKronVector(ConstKronVector&& v) = default;
|
||||
ConstKronVector(const Vector& v, int mm, int nn, int dp);
|
||||
ConstKronVector(ConstVector v, int mm, int nn, int dp);
|
||||
ConstKronVector(const KronVector &v, int i);
|
||||
ConstKronVector(const ConstKronVector &v, int i);
|
||||
ConstKronVector &operator=(const ConstKronVector &v) = delete;
|
||||
ConstKronVector &operator=(ConstKronVector &&v) = delete;
|
||||
ConstKronVector(const KronVector& v, int i);
|
||||
ConstKronVector(const ConstKronVector& v, int i);
|
||||
ConstKronVector& operator=(const ConstKronVector& v) = delete;
|
||||
ConstKronVector& operator=(ConstKronVector&& v) = delete;
|
||||
int
|
||||
getM() const
|
||||
{
|
||||
|
|
|
@ -19,27 +19,27 @@
|
|||
*/
|
||||
|
||||
#include "QuasiTriangular.hh"
|
||||
#include "SylvException.hh"
|
||||
#include "SchurDecomp.hh"
|
||||
#include "SylvException.hh"
|
||||
#include "int_power.hh"
|
||||
|
||||
#include <dynblas.h>
|
||||
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <limits>
|
||||
#include <sstream>
|
||||
|
||||
double
|
||||
DiagonalBlock::getDeterminant() const
|
||||
{
|
||||
return (*alpha)*(*alpha) + getSBeta();
|
||||
return (*alpha) * (*alpha) + getSBeta();
|
||||
}
|
||||
|
||||
double
|
||||
DiagonalBlock::getSBeta() const
|
||||
{
|
||||
return -(*beta1)*(*beta2);
|
||||
return -(*beta1) * (*beta2);
|
||||
}
|
||||
|
||||
double
|
||||
|
@ -63,12 +63,12 @@ DiagonalBlock::setReal()
|
|||
}
|
||||
|
||||
void
|
||||
DiagonalBlock::checkBlock(const double *d, int d_size)
|
||||
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;
|
||||
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)
|
||||
|
@ -79,25 +79,24 @@ DiagonalBlock::checkBlock(const double *d, int d_size)
|
|||
throw SYLV_MES_EXCEPTION("Bad alpha2.");
|
||||
}
|
||||
|
||||
Diagonal::Diagonal(double *data, int d_size)
|
||||
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;
|
||||
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]))
|
||||
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
|
||||
blocks.emplace_back(jbar, false, &data[id], &data[idd],
|
||||
&data[iur], &data[ill]);
|
||||
blocks.emplace_back(jbar, false, &data[id], &data[idd], &data[iur], &data[ill]);
|
||||
jbar++;
|
||||
}
|
||||
else
|
||||
|
@ -108,90 +107,87 @@ Diagonal::Diagonal(double *data, int d_size)
|
|||
}
|
||||
}
|
||||
|
||||
Diagonal::Diagonal(double *data, const Diagonal &d)
|
||||
Diagonal::Diagonal(double* data, const Diagonal& d)
|
||||
{
|
||||
num_all = d.num_all;
|
||||
num_real = d.num_real;
|
||||
int d_size = d.getSize();
|
||||
for (const auto &block : d)
|
||||
for (const auto& block : d)
|
||||
{
|
||||
double *beta1 = nullptr;
|
||||
double *beta2 = nullptr;
|
||||
int id = block.getIndex()*(d_size+1);
|
||||
double* beta1 = nullptr;
|
||||
double* beta2 = nullptr;
|
||||
int id = block.getIndex() * (d_size + 1);
|
||||
int idd = id;
|
||||
if (!block.isReal())
|
||||
{
|
||||
beta1 = &data[id+d_size];
|
||||
beta2 = &data[id+1];
|
||||
beta1 = &data[id + d_size];
|
||||
beta2 = &data[id + 1];
|
||||
idd = id + d_size + 1;
|
||||
}
|
||||
blocks.emplace_back(block.getIndex(), block.isReal(),
|
||||
&data[id], &data[idd], beta1, beta2);
|
||||
blocks.emplace_back(block.getIndex(), block.isReal(), &data[id], &data[idd], beta1, beta2);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
Diagonal::getNumComplex(const double *data, int d_size)
|
||||
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)
|
||||
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]))
|
||||
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)
|
||||
Diagonal::changeBase(double* p)
|
||||
{
|
||||
int d_size = getSize();
|
||||
for (auto &it : *this)
|
||||
for (auto& it : *this)
|
||||
{
|
||||
const DiagonalBlock &b = it;
|
||||
const DiagonalBlock& b = it;
|
||||
int jbar = b.getIndex();
|
||||
int base = d_size*jbar + jbar;
|
||||
int base = d_size * jbar + jbar;
|
||||
if (b.isReal())
|
||||
{
|
||||
DiagonalBlock bnew(jbar, true, &p[base], &p[base],
|
||||
nullptr, nullptr);
|
||||
DiagonalBlock bnew(jbar, true, &p[base], &p[base], nullptr, nullptr);
|
||||
it = bnew;
|
||||
}
|
||||
else
|
||||
{
|
||||
DiagonalBlock bnew(jbar, false, &p[base], &p[base+d_size+1],
|
||||
&p[base+d_size], &p[base+1]);
|
||||
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
|
||||
Diagonal::getEigenValues(Vector& eig) const
|
||||
{
|
||||
if (int d_size {getSize()};
|
||||
eig.length() != 2*d_size)
|
||||
if (int d_size {getSize()}; eig.length() != 2 * d_size)
|
||||
{
|
||||
std::ostringstream mes;
|
||||
mes << "Wrong length of vector for eigenvalues len=" << eig.length()
|
||||
<< ", should be=" << 2*d_size << '.' << std::endl;
|
||||
<< ", should be=" << 2 * d_size << '.' << std::endl;
|
||||
throw SYLV_MES_EXCEPTION(mes.str());
|
||||
}
|
||||
for (const auto &b : *this)
|
||||
for (const auto& b : *this)
|
||||
{
|
||||
int ind = b.getIndex();
|
||||
eig[2*ind] = *(b.getAlpha());
|
||||
eig[2 * ind] = *(b.getAlpha());
|
||||
if (b.isReal())
|
||||
eig[2*ind+1] = 0.0;
|
||||
eig[2 * ind + 1] = 0.0;
|
||||
else
|
||||
{
|
||||
double beta = std::sqrt(b.getSBeta());
|
||||
eig[2*ind+1] = beta;
|
||||
eig[2*ind+2] = eig[2*ind];
|
||||
eig[2*ind+3] = -beta;
|
||||
eig[2 * ind + 1] = beta;
|
||||
eig[2 * ind + 2] = eig[2 * ind];
|
||||
eig[2 * ind + 3] = -beta;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -208,25 +204,25 @@ Diagonal::swapLogically(diag_iter it)
|
|||
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;
|
||||
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);
|
||||
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;
|
||||
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);
|
||||
DiagonalBlock new_itp(itp->jbar - 1, d2, d3);
|
||||
*itp = new_itp;
|
||||
}
|
||||
}
|
||||
|
@ -238,12 +234,12 @@ Diagonal::checkConsistency(diag_iter it)
|
|||
{
|
||||
it->getBeta2() = 0.0; // put exact zero
|
||||
int jbar = it->getIndex();
|
||||
double *d2 = it->alpha.a2;
|
||||
double* d2 = it->alpha.a2;
|
||||
it->alpha.a2 = it->alpha.a1;
|
||||
it->real = true;
|
||||
it->beta1 = nullptr;
|
||||
it->beta2 = nullptr;
|
||||
blocks.emplace(++it, jbar+1, d2);
|
||||
blocks.emplace(++it, jbar + 1, d2);
|
||||
num_real += 2;
|
||||
num_all++;
|
||||
}
|
||||
|
@ -260,7 +256,7 @@ Diagonal::getAverageSize(diag_iter start, diag_iter end)
|
|||
res += run->getSize();
|
||||
}
|
||||
if (num > 0)
|
||||
res = res/num;
|
||||
res = res / num;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -270,8 +266,7 @@ Diagonal::findClosestBlock(diag_iter start, diag_iter end, double a)
|
|||
diag_iter closest = start;
|
||||
double minim {std::numeric_limits<double>::infinity()};
|
||||
for (diag_iter run = start; run != end; ++run)
|
||||
if (double dist = std::abs(a - run->getSize());
|
||||
dist < minim)
|
||||
if (double dist = std::abs(a - run->getSize()); dist < minim)
|
||||
{
|
||||
minim = dist;
|
||||
closest = run;
|
||||
|
@ -285,8 +280,7 @@ Diagonal::findNextLargerBlock(diag_iter start, diag_iter end, double a)
|
|||
diag_iter closest = start;
|
||||
double minim {std::numeric_limits<double>::infinity()};
|
||||
for (diag_iter run = start; run != end; ++run)
|
||||
if (double dist = run->getSize() - a;
|
||||
0 <= dist && dist < minim)
|
||||
if (double dist = run->getSize() - a; 0 <= dist && dist < minim)
|
||||
{
|
||||
minim = dist;
|
||||
closest = run;
|
||||
|
@ -300,14 +294,12 @@ Diagonal::print() const
|
|||
auto ff = std::cout.flags();
|
||||
std::cout << "Num real: " << getNumReal() << ", num complex: " << getNumComplex() << std::endl
|
||||
<< std::fixed;
|
||||
for (const auto &it : *this)
|
||||
for (const auto& it : *this)
|
||||
if (it.isReal())
|
||||
std::cout << "real: jbar=" << it.getIndex() << ", alpha=" << *(it.getAlpha()) << std::endl;
|
||||
else
|
||||
std::cout << "complex: jbar=" << it.getIndex()
|
||||
<< ", alpha=" << *(it.getAlpha())
|
||||
<< ", beta1=" << it.getBeta1()
|
||||
<< ", beta2=" << it.getBeta2() << std::endl;
|
||||
std::cout << "complex: jbar=" << it.getIndex() << ", alpha=" << *(it.getAlpha())
|
||||
<< ", beta1=" << it.getBeta1() << ", beta2=" << it.getBeta2() << std::endl;
|
||||
std::cout.flags(ff);
|
||||
}
|
||||
|
||||
|
@ -318,28 +310,28 @@ Diagonal::isZero(double p)
|
|||
}
|
||||
|
||||
QuasiTriangular::const_col_iter
|
||||
QuasiTriangular::col_begin(const DiagonalBlock &b) const
|
||||
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);
|
||||
return const_col_iter(&getData()[jbar * d_size], d_size, b.isReal(), 0);
|
||||
}
|
||||
|
||||
QuasiTriangular::col_iter
|
||||
QuasiTriangular::col_begin(const DiagonalBlock &b)
|
||||
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);
|
||||
return col_iter(&getData()[jbar * d_size], d_size, b.isReal(), 0);
|
||||
}
|
||||
|
||||
QuasiTriangular::const_row_iter
|
||||
QuasiTriangular::row_begin(const DiagonalBlock &b) const
|
||||
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;
|
||||
int off = jbar * d_size + jbar + d_size;
|
||||
int col = jbar + 1;
|
||||
if (!b.isReal())
|
||||
{
|
||||
off = off + d_size;
|
||||
|
@ -349,12 +341,12 @@ QuasiTriangular::row_begin(const DiagonalBlock &b) const
|
|||
}
|
||||
|
||||
QuasiTriangular::row_iter
|
||||
QuasiTriangular::row_begin(const DiagonalBlock &b)
|
||||
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;
|
||||
int off = jbar * d_size + jbar + d_size;
|
||||
int col = jbar + 1;
|
||||
if (!b.isReal())
|
||||
{
|
||||
off = off + d_size;
|
||||
|
@ -364,113 +356,112 @@ QuasiTriangular::row_begin(const DiagonalBlock &b)
|
|||
}
|
||||
|
||||
QuasiTriangular::const_col_iter
|
||||
QuasiTriangular::col_end(const DiagonalBlock &b) const
|
||||
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);
|
||||
return const_col_iter(getData().base() + jbar * d_size + jbar, d_size, b.isReal(), jbar);
|
||||
}
|
||||
|
||||
QuasiTriangular::col_iter
|
||||
QuasiTriangular::col_end(const DiagonalBlock &b)
|
||||
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);
|
||||
return col_iter(&getData()[jbar * d_size + jbar], d_size, b.isReal(), jbar);
|
||||
}
|
||||
|
||||
QuasiTriangular::const_row_iter
|
||||
QuasiTriangular::row_end(const DiagonalBlock &b) const
|
||||
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);
|
||||
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)
|
||||
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);
|
||||
return row_iter(&getData()[d_size * d_size + jbar], d_size, b.isReal(), d_size);
|
||||
}
|
||||
|
||||
QuasiTriangular::QuasiTriangular(double r, const QuasiTriangular &t)
|
||||
: SqSylvMatrix(t.nrows()), diagonal(getData().base(), t.diagonal)
|
||||
QuasiTriangular::QuasiTriangular(double r, const QuasiTriangular& t) :
|
||||
SqSylvMatrix(t.nrows()), diagonal(getData().base(), t.diagonal)
|
||||
{
|
||||
setMatrix(r, t);
|
||||
}
|
||||
|
||||
QuasiTriangular::QuasiTriangular(double r, const QuasiTriangular &t,
|
||||
double r2, const QuasiTriangular &t2)
|
||||
: SqSylvMatrix(t.nrows()), diagonal(getData().base(), t.diagonal)
|
||||
QuasiTriangular::QuasiTriangular(double r, const QuasiTriangular& t, double r2,
|
||||
const QuasiTriangular& t2) :
|
||||
SqSylvMatrix(t.nrows()),
|
||||
diagonal(getData().base(), t.diagonal)
|
||||
{
|
||||
setMatrix(r, t);
|
||||
addMatrix(r2, t2);
|
||||
}
|
||||
|
||||
QuasiTriangular::QuasiTriangular(const QuasiTriangular &t)
|
||||
: SqSylvMatrix(t), diagonal(getData().base(), t.diagonal)
|
||||
QuasiTriangular::QuasiTriangular(const QuasiTriangular& t) :
|
||||
SqSylvMatrix(t), diagonal(getData().base(), t.diagonal)
|
||||
{
|
||||
}
|
||||
|
||||
QuasiTriangular::QuasiTriangular(const ConstVector &d, int d_size)
|
||||
: SqSylvMatrix(Vector{d}, d_size), diagonal(getData().base(), d_size)
|
||||
QuasiTriangular::QuasiTriangular(const ConstVector& d, int d_size) :
|
||||
SqSylvMatrix(Vector {d}, d_size), diagonal(getData().base(), d_size)
|
||||
{
|
||||
}
|
||||
|
||||
QuasiTriangular::QuasiTriangular([[maybe_unused]] const std::string &dummy, const QuasiTriangular &t)
|
||||
: SqSylvMatrix(t.nrows()), diagonal(getData().base(), t.diagonal)
|
||||
QuasiTriangular::QuasiTriangular([[maybe_unused]] const std::string& dummy,
|
||||
const QuasiTriangular& t) :
|
||||
SqSylvMatrix(t.nrows()),
|
||||
diagonal(getData().base(), t.diagonal)
|
||||
{
|
||||
Vector aux(t.getData());
|
||||
blas_int d_size = diagonal.getSize();
|
||||
double alpha = 1.0;
|
||||
double beta = 0.0;
|
||||
blas_int lda = t.getLD(), ldb = t.getLD(), ldc = ld;
|
||||
dgemm("N", "N", &d_size, &d_size, &d_size, &alpha, aux.base(),
|
||||
&lda, t.getData().base(), &ldb, &beta, getData().base(), &ldc);
|
||||
dgemm("N", "N", &d_size, &d_size, &d_size, &alpha, aux.base(), &lda, t.getData().base(), &ldb,
|
||||
&beta, getData().base(), &ldc);
|
||||
}
|
||||
|
||||
QuasiTriangular::QuasiTriangular(const SchurDecomp &decomp)
|
||||
: SqSylvMatrix(decomp.getT()),
|
||||
diagonal(getData().base(), decomp.getDim())
|
||||
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())
|
||||
QuasiTriangular::QuasiTriangular(const SchurDecompZero& decomp) : SqSylvMatrix(decomp.getDim())
|
||||
{
|
||||
// nullify first decomp.getZeroCols() columns
|
||||
int zeros = decomp.getZeroCols()*decomp.getDim();
|
||||
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().nrows(); i++)
|
||||
for (int j = 0; j < decomp.getRU().ncols(); j++)
|
||||
getData()[(j+decomp.getZeroCols())*decomp.getDim()+i] = decomp.getRU().get(i, 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().nrows(); i++)
|
||||
for (int j = 0; j < decomp.getT().ncols(); j++)
|
||||
getData()[(j+decomp.getZeroCols())*decomp.getDim()+decomp.getZeroCols()+i]
|
||||
= decomp.getT().get(i, j);
|
||||
getData()[(j + decomp.getZeroCols()) * decomp.getDim() + decomp.getZeroCols() + i]
|
||||
= decomp.getT().get(i, j);
|
||||
|
||||
// construct diagonal
|
||||
diagonal = Diagonal{getData().base(), decomp.getDim()};
|
||||
diagonal = Diagonal {getData().base(), decomp.getDim()};
|
||||
}
|
||||
|
||||
void
|
||||
QuasiTriangular::setMatrix(double r, const QuasiTriangular &t)
|
||||
QuasiTriangular::setMatrix(double r, const QuasiTriangular& t)
|
||||
{
|
||||
getData().zeros();
|
||||
getData().add(r, t.getData());
|
||||
}
|
||||
|
||||
void
|
||||
QuasiTriangular::addMatrix(double r, const QuasiTriangular &t)
|
||||
QuasiTriangular::addMatrix(double r, const QuasiTriangular& t)
|
||||
{
|
||||
getData().add(r, t.getData());
|
||||
}
|
||||
|
@ -483,21 +474,21 @@ QuasiTriangular::addUnit()
|
|||
}
|
||||
|
||||
void
|
||||
QuasiTriangular::solve(Vector &x, const ConstVector &b, double &eig_min)
|
||||
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)
|
||||
QuasiTriangular::solveTrans(Vector& x, const ConstVector& b, double& eig_min)
|
||||
{
|
||||
x = b;
|
||||
solvePreTrans(x, eig_min);
|
||||
}
|
||||
|
||||
void
|
||||
QuasiTriangular::solvePre(Vector &x, double &eig_min)
|
||||
QuasiTriangular::solvePre(Vector& x, double& eig_min)
|
||||
{
|
||||
addUnit();
|
||||
for (diag_iter di = diag_begin(); di != diag_end(); ++di)
|
||||
|
@ -506,10 +497,10 @@ QuasiTriangular::solvePre(Vector &x, double &eig_min)
|
|||
if (!di->isReal())
|
||||
{
|
||||
eig_size = di->getDeterminant();
|
||||
eliminateLeft(di->getIndex()+1, di->getIndex(), x);
|
||||
eliminateLeft(di->getIndex() + 1, di->getIndex(), x);
|
||||
}
|
||||
else
|
||||
eig_size = *di->getAlpha()*(*di->getAlpha());
|
||||
eig_size = *di->getAlpha() * (*di->getAlpha());
|
||||
eig_min = std::min(eig_min, eig_size);
|
||||
}
|
||||
|
||||
|
@ -520,7 +511,7 @@ QuasiTriangular::solvePre(Vector &x, double &eig_min)
|
|||
}
|
||||
|
||||
void
|
||||
QuasiTriangular::solvePreTrans(Vector &x, double &eig_min)
|
||||
QuasiTriangular::solvePreTrans(Vector& x, double& eig_min)
|
||||
{
|
||||
addUnit();
|
||||
for (diag_iter di = diag_begin(); di != diag_end(); ++di)
|
||||
|
@ -529,10 +520,10 @@ QuasiTriangular::solvePreTrans(Vector &x, double &eig_min)
|
|||
if (!di->isReal())
|
||||
{
|
||||
eig_size = di->getDeterminant();
|
||||
eliminateRight(di->getIndex()+1, di->getIndex(), x);
|
||||
eliminateRight(di->getIndex() + 1, di->getIndex(), x);
|
||||
}
|
||||
else
|
||||
eig_size = *di->getAlpha()*(*di->getAlpha());
|
||||
eig_size = *di->getAlpha() * (*di->getAlpha());
|
||||
if (eig_size < eig_min)
|
||||
eig_min = eig_size;
|
||||
}
|
||||
|
@ -545,7 +536,7 @@ QuasiTriangular::solvePreTrans(Vector &x, double &eig_min)
|
|||
|
||||
// Calculates x = T·b
|
||||
void
|
||||
QuasiTriangular::multVec(Vector &x, const ConstVector &b) const
|
||||
QuasiTriangular::multVec(Vector& x, const ConstVector& b) const
|
||||
{
|
||||
x = b;
|
||||
blas_int nn = diagonal.getSize();
|
||||
|
@ -556,12 +547,12 @@ QuasiTriangular::multVec(Vector &x, const ConstVector &b) const
|
|||
if (!di->isReal())
|
||||
{
|
||||
int jbar = di->getIndex();
|
||||
x[jbar+1] += di->getBeta2()*(b[jbar]);
|
||||
x[jbar + 1] += di->getBeta2() * (b[jbar]);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
QuasiTriangular::multVecTrans(Vector &x, const ConstVector &b) const
|
||||
QuasiTriangular::multVecTrans(Vector& x, const ConstVector& b) const
|
||||
{
|
||||
x = b;
|
||||
blas_int nn = diagonal.getSize();
|
||||
|
@ -572,31 +563,31 @@ QuasiTriangular::multVecTrans(Vector &x, const ConstVector &b) const
|
|||
if (!di->isReal())
|
||||
{
|
||||
int jbar = di->getIndex();
|
||||
x[jbar] += di->getBeta2()*b[jbar+1];
|
||||
x[jbar] += di->getBeta2() * b[jbar + 1];
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
QuasiTriangular::multaVec(Vector &x, const ConstVector &b) const
|
||||
QuasiTriangular::multaVec(Vector& x, const ConstVector& b) const
|
||||
{
|
||||
Vector tmp(const_cast<const Vector &>(x)); // new copy
|
||||
Vector tmp(const_cast<const Vector&>(x)); // new copy
|
||||
multVec(x, b);
|
||||
x.add(1.0, tmp);
|
||||
}
|
||||
|
||||
void
|
||||
QuasiTriangular::multaVecTrans(Vector &x, const ConstVector &b) const
|
||||
QuasiTriangular::multaVecTrans(Vector& x, const ConstVector& b) const
|
||||
{
|
||||
Vector tmp(const_cast<const Vector &>(x)); // new copy
|
||||
Vector tmp(const_cast<const Vector&>(x)); // new copy
|
||||
multVecTrans(x, b);
|
||||
x.add(1.0, tmp);
|
||||
}
|
||||
|
||||
// Calculates x=x+(this⊗I)·b, where size of I is given by b (KronVector)
|
||||
void
|
||||
QuasiTriangular::multaKron(KronVector &x, const ConstKronVector &b) const
|
||||
QuasiTriangular::multaKron(KronVector& x, const ConstKronVector& b) const
|
||||
{
|
||||
int id = b.getN()*power(b.getM(), b.getDepth()-1);
|
||||
int id = b.getN() * power(b.getM(), b.getDepth() - 1);
|
||||
ConstGeneralMatrix b_resh(b, id, b.getM());
|
||||
GeneralMatrix x_resh(x, id, b.getM());
|
||||
x_resh.multAndAdd(b_resh, ConstGeneralMatrix(*this), "trans");
|
||||
|
@ -604,38 +595,38 @@ QuasiTriangular::multaKron(KronVector &x, const ConstKronVector &b) const
|
|||
|
||||
// Calculates x=x+(this⊗I)·b, where size of I is given by b (KronVector)
|
||||
void
|
||||
QuasiTriangular::multaKronTrans(KronVector &x, const ConstKronVector &b) const
|
||||
QuasiTriangular::multaKronTrans(KronVector& x, const ConstKronVector& b) const
|
||||
{
|
||||
int id = b.getN()*power(b.getM(), b.getDepth()-1);
|
||||
int id = b.getN() * power(b.getM(), b.getDepth() - 1);
|
||||
ConstGeneralMatrix b_resh(b, id, b.getM());
|
||||
GeneralMatrix x_resh(x, id, b.getM());
|
||||
x_resh.multAndAdd(b_resh, ConstGeneralMatrix(*this));
|
||||
}
|
||||
|
||||
void
|
||||
QuasiTriangular::multKron(KronVector &x) const
|
||||
QuasiTriangular::multKron(KronVector& x) const
|
||||
{
|
||||
KronVector b(const_cast<const KronVector &>(x)); // make copy
|
||||
KronVector b(const_cast<const KronVector&>(x)); // make copy
|
||||
x.zeros();
|
||||
multaKron(x, b);
|
||||
}
|
||||
|
||||
void
|
||||
QuasiTriangular::multKronTrans(KronVector &x) const
|
||||
QuasiTriangular::multKronTrans(KronVector& x) const
|
||||
{
|
||||
KronVector b(const_cast<const KronVector &>(x)); // make copy
|
||||
KronVector b(const_cast<const KronVector&>(x)); // make copy
|
||||
x.zeros();
|
||||
multaKronTrans(x, b);
|
||||
}
|
||||
|
||||
void
|
||||
QuasiTriangular::multLeftOther(GeneralMatrix &a) const
|
||||
QuasiTriangular::multLeftOther(GeneralMatrix& a) const
|
||||
{
|
||||
a.multLeft(*this);
|
||||
}
|
||||
|
||||
void
|
||||
QuasiTriangular::multLeftOtherTrans(GeneralMatrix &a) const
|
||||
QuasiTriangular::multLeftOtherTrans(GeneralMatrix& a) const
|
||||
{
|
||||
a.multLeftTrans(*this);
|
||||
}
|
||||
|
@ -673,5 +664,5 @@ QuasiTriangular::findNextLargerBlock(diag_iter start, diag_iter end, double a)
|
|||
int
|
||||
QuasiTriangular::getNumOffdiagonal() const
|
||||
{
|
||||
return diagonal.getSize()*(diagonal.getSize()-1)/2 - diagonal.getNumComplex();
|
||||
return diagonal.getSize() * (diagonal.getSize() - 1) / 2 - diagonal.getNumComplex();
|
||||
}
|
||||
|
|
|
@ -21,9 +21,9 @@
|
|||
#ifndef QUASI_TRIANGULAR_H
|
||||
#define QUASI_TRIANGULAR_H
|
||||
|
||||
#include "Vector.hh"
|
||||
#include "KronVector.hh"
|
||||
#include "SylvMatrix.hh"
|
||||
#include "Vector.hh"
|
||||
|
||||
#include <list>
|
||||
#include <memory>
|
||||
|
@ -33,23 +33,24 @@ class Diagonal;
|
|||
class DiagPair
|
||||
{
|
||||
private:
|
||||
double *a1;
|
||||
double *a2;
|
||||
double* a1;
|
||||
double* a2;
|
||||
|
||||
public:
|
||||
DiagPair() = default;
|
||||
DiagPair(double *aa1, double *aa2) : a1{aa1}, a2{aa2}
|
||||
DiagPair(double* aa1, double* aa2) : a1 {aa1}, a2 {aa2}
|
||||
{
|
||||
}
|
||||
DiagPair(const DiagPair &p) = default;
|
||||
DiagPair &operator=(const DiagPair &p) = default;
|
||||
DiagPair &
|
||||
DiagPair(const DiagPair& p) = default;
|
||||
DiagPair& operator=(const DiagPair& p) = default;
|
||||
DiagPair&
|
||||
operator=(double v)
|
||||
{
|
||||
*a1 = v;
|
||||
*a2 = v;
|
||||
return *this;
|
||||
}
|
||||
const double &
|
||||
const double&
|
||||
operator*() const
|
||||
{
|
||||
return *a1;
|
||||
|
@ -71,29 +72,28 @@ private:
|
|||
int jbar; // Index of block in the diagonal
|
||||
bool real;
|
||||
DiagPair alpha;
|
||||
double *beta1;
|
||||
double *beta2;
|
||||
double* beta1;
|
||||
double* beta2;
|
||||
|
||||
public:
|
||||
DiagonalBlock() = default;
|
||||
DiagonalBlock(int jb, bool r, double *a1, double *a2,
|
||||
double *b1, double *b2)
|
||||
: jbar{jb}, real{r}, alpha{a1, a2}, beta1{b1}, beta2{b2}
|
||||
DiagonalBlock(int jb, bool r, double* a1, double* a2, double* b1, double* b2) :
|
||||
jbar {jb}, real {r}, alpha {a1, a2}, beta1 {b1}, beta2 {b2}
|
||||
{
|
||||
}
|
||||
// Construct a complex 2×2 block
|
||||
/* β₁ and β₂ will be deduced from pointers to α₁ and α₂ */
|
||||
DiagonalBlock(int jb, double *a1, double *a2)
|
||||
: jbar{jb}, real{false}, alpha{a1, a2}, beta1{a2-1}, beta2{a1+1}
|
||||
DiagonalBlock(int jb, double* a1, double* a2) :
|
||||
jbar {jb}, real {false}, alpha {a1, a2}, beta1 {a2 - 1}, beta2 {a1 + 1}
|
||||
{
|
||||
}
|
||||
// Construct a real 1×1 block
|
||||
DiagonalBlock(int jb, double *a1)
|
||||
: jbar{jb}, real{true}, alpha{a1, a1}, beta1{nullptr}, beta2{nullptr}
|
||||
DiagonalBlock(int jb, double* a1) :
|
||||
jbar {jb}, real {true}, alpha {a1, a1}, beta1 {nullptr}, beta2 {nullptr}
|
||||
{
|
||||
}
|
||||
DiagonalBlock(const DiagonalBlock &b) = default;
|
||||
DiagonalBlock &operator=(const DiagonalBlock &b) = default;
|
||||
DiagonalBlock(const DiagonalBlock& b) = default;
|
||||
DiagonalBlock& operator=(const DiagonalBlock& b) = default;
|
||||
int
|
||||
getIndex() const
|
||||
{
|
||||
|
@ -104,22 +104,22 @@ public:
|
|||
{
|
||||
return real;
|
||||
}
|
||||
const DiagPair &
|
||||
const DiagPair&
|
||||
getAlpha() const
|
||||
{
|
||||
return alpha;
|
||||
}
|
||||
DiagPair &
|
||||
DiagPair&
|
||||
getAlpha()
|
||||
{
|
||||
return alpha;
|
||||
}
|
||||
double &
|
||||
double&
|
||||
getBeta1() const
|
||||
{
|
||||
return *beta1;
|
||||
}
|
||||
double &
|
||||
double&
|
||||
getBeta2() const
|
||||
{
|
||||
return *beta2;
|
||||
|
@ -133,7 +133,7 @@ public:
|
|||
// Transforms this block into a real one
|
||||
void setReal();
|
||||
// Verifies that the block information is consistent with the matrix d (for debugging)
|
||||
void checkBlock(const double *d, int d_size);
|
||||
void checkBlock(const double* d, int d_size);
|
||||
friend class Diagonal;
|
||||
};
|
||||
|
||||
|
@ -143,19 +143,20 @@ class Diagonal
|
|||
public:
|
||||
using const_diag_iter = std::list<DiagonalBlock>::const_iterator;
|
||||
using diag_iter = std::list<DiagonalBlock>::iterator;
|
||||
|
||||
private:
|
||||
int num_all{0}; // Total number of blocks
|
||||
int num_all {0}; // Total number of blocks
|
||||
std::list<DiagonalBlock> blocks;
|
||||
int num_real{0}; // Number of 1×1 (real) blocks
|
||||
int num_real {0}; // Number of 1×1 (real) blocks
|
||||
public:
|
||||
Diagonal() = default;
|
||||
// Construct the diagonal blocks of (quasi-triangular) matrix ‘data’
|
||||
Diagonal(double *data, int d_size);
|
||||
Diagonal(double* data, int d_size);
|
||||
/* Construct the diagonal blocks of (quasi-triangular) matrix ‘data’,
|
||||
assuming it has the same shape as ‘d’ */
|
||||
Diagonal(double *data, const Diagonal &d);
|
||||
Diagonal(const Diagonal &d) = default;
|
||||
Diagonal &operator=(const Diagonal &d) = default;
|
||||
Diagonal(double* data, const Diagonal& d);
|
||||
Diagonal(const Diagonal& d) = default;
|
||||
Diagonal& operator=(const Diagonal& d) = default;
|
||||
virtual ~Diagonal() = default;
|
||||
|
||||
// Returns number of 2×2 blocks on the diagonal
|
||||
|
@ -174,7 +175,7 @@ public:
|
|||
int
|
||||
getSize() const
|
||||
{
|
||||
return getNumReal() + 2*getNumComplex();
|
||||
return getNumReal() + 2 * getNumComplex();
|
||||
}
|
||||
// Returns total number of blocks on the diagonal
|
||||
int
|
||||
|
@ -182,7 +183,7 @@ public:
|
|||
{
|
||||
return num_all;
|
||||
}
|
||||
void getEigenValues(Vector &eig) const;
|
||||
void getEigenValues(Vector& eig) const;
|
||||
void swapLogically(diag_iter it);
|
||||
void checkConsistency(diag_iter it);
|
||||
double getAverageSize(diag_iter start, diag_iter end);
|
||||
|
@ -212,12 +213,13 @@ public:
|
|||
}
|
||||
|
||||
/* redefine pointers as data start at p */
|
||||
void changeBase(double *p);
|
||||
void changeBase(double* p);
|
||||
|
||||
private:
|
||||
constexpr static double EPS = 1.0e-300;
|
||||
/* Computes number of 2×2 diagonal blocks on the quasi-triangular matrix
|
||||
represented by data (of size d_size×d_size) */
|
||||
static int getNumComplex(const double *data, int d_size);
|
||||
static int getNumComplex(const double* data, int d_size);
|
||||
// Checks whether |p|<EPS
|
||||
static bool isZero(double p);
|
||||
};
|
||||
|
@ -229,6 +231,7 @@ struct _matrix_iter
|
|||
int d_size;
|
||||
bool real;
|
||||
_TPtr ptr;
|
||||
|
||||
public:
|
||||
_matrix_iter(_TPtr base, int ds, bool r)
|
||||
{
|
||||
|
@ -238,12 +241,12 @@ public:
|
|||
}
|
||||
virtual ~_matrix_iter() = default;
|
||||
bool
|
||||
operator==(const _Self &it) const
|
||||
operator==(const _Self& it) const
|
||||
{
|
||||
return ptr == it.ptr;
|
||||
}
|
||||
bool
|
||||
operator!=(const _Self &it) const
|
||||
operator!=(const _Self& it) const
|
||||
{
|
||||
return ptr != it.ptr;
|
||||
}
|
||||
|
@ -257,7 +260,7 @@ public:
|
|||
{
|
||||
return *ptr;
|
||||
}
|
||||
virtual _Self &operator++() = 0;
|
||||
virtual _Self& operator++() = 0;
|
||||
};
|
||||
|
||||
template<class _TRef, class _TPtr>
|
||||
|
@ -266,12 +269,11 @@ class _column_iter : public _matrix_iter<_TRef, _TPtr>
|
|||
using _Tparent = _matrix_iter<_TRef, _TPtr>;
|
||||
using _Self = _column_iter<_TRef, _TPtr>;
|
||||
int row;
|
||||
|
||||
public:
|
||||
_column_iter(_TPtr base, int ds, bool r, int rw)
|
||||
: _matrix_iter<_TRef, _TPtr>(base, ds, r), row(rw)
|
||||
{
|
||||
};
|
||||
_Self &
|
||||
_column_iter(_TPtr base, int ds, bool r, int rw) :
|
||||
_matrix_iter<_TRef, _TPtr>(base, ds, r), row(rw) {};
|
||||
_Self&
|
||||
operator++() override
|
||||
{
|
||||
_Tparent::ptr++;
|
||||
|
@ -284,7 +286,7 @@ public:
|
|||
if (_Tparent::real)
|
||||
return *(_Tparent::ptr);
|
||||
else
|
||||
return *(_Tparent::ptr+_Tparent::d_size);
|
||||
return *(_Tparent::ptr + _Tparent::d_size);
|
||||
}
|
||||
int
|
||||
getRow() const
|
||||
|
@ -299,12 +301,11 @@ class _row_iter : public _matrix_iter<_TRef, _TPtr>
|
|||
using _Tparent = _matrix_iter<_TRef, _TPtr>;
|
||||
using _Self = _row_iter<_TRef, _TPtr>;
|
||||
int col;
|
||||
|
||||
public:
|
||||
_row_iter(_TPtr base, int ds, bool r, int cl)
|
||||
: _matrix_iter<_TRef, _TPtr>(base, ds, r), col(cl)
|
||||
{
|
||||
};
|
||||
_Self &
|
||||
_row_iter(_TPtr base, int ds, bool r, int cl) :
|
||||
_matrix_iter<_TRef, _TPtr>(base, ds, r), col(cl) {};
|
||||
_Self&
|
||||
operator++() override
|
||||
{
|
||||
_Tparent::ptr += _Tparent::d_size;
|
||||
|
@ -317,7 +318,7 @@ public:
|
|||
if (_Tparent::real)
|
||||
return *(_Tparent::ptr);
|
||||
else
|
||||
return *(_Tparent::ptr+1);
|
||||
return *(_Tparent::ptr + 1);
|
||||
}
|
||||
int
|
||||
getCol() const
|
||||
|
@ -338,29 +339,30 @@ class SchurDecompZero;
|
|||
class QuasiTriangular : public SqSylvMatrix
|
||||
{
|
||||
public:
|
||||
using const_col_iter = _column_iter<const double &, const double *>;
|
||||
using col_iter = _column_iter<double &, double *>;
|
||||
using const_row_iter = _row_iter<const double &, const double *>;
|
||||
using row_iter = _row_iter<double &, double *>;
|
||||
using const_col_iter = _column_iter<const double&, const double*>;
|
||||
using col_iter = _column_iter<double&, double*>;
|
||||
using const_row_iter = _row_iter<const double&, const double*>;
|
||||
using row_iter = _row_iter<double&, double*>;
|
||||
using const_diag_iter = Diagonal::const_diag_iter;
|
||||
using diag_iter = Diagonal::diag_iter;
|
||||
|
||||
protected:
|
||||
Diagonal diagonal;
|
||||
|
||||
public:
|
||||
QuasiTriangular(const ConstVector &d, int d_size);
|
||||
QuasiTriangular(const ConstVector& d, int d_size);
|
||||
// Initializes with r·t
|
||||
QuasiTriangular(double r, const QuasiTriangular &t);
|
||||
QuasiTriangular(double r, const QuasiTriangular& t);
|
||||
// Initializes with r·t+r₂·t₂
|
||||
QuasiTriangular(double r, const QuasiTriangular &t,
|
||||
double r2, const QuasiTriangular &t2);
|
||||
QuasiTriangular(double r, const QuasiTriangular& t, double r2, const QuasiTriangular& t2);
|
||||
// Initializes with t²
|
||||
QuasiTriangular(const std::string &dummy, const QuasiTriangular &t);
|
||||
explicit QuasiTriangular(const SchurDecomp &decomp);
|
||||
explicit QuasiTriangular(const SchurDecompZero &decomp);
|
||||
QuasiTriangular(const QuasiTriangular &t);
|
||||
QuasiTriangular(const std::string& dummy, const QuasiTriangular& t);
|
||||
explicit QuasiTriangular(const SchurDecomp& decomp);
|
||||
explicit QuasiTriangular(const SchurDecompZero& decomp);
|
||||
QuasiTriangular(const QuasiTriangular& t);
|
||||
|
||||
~QuasiTriangular() override = default;
|
||||
const Diagonal &
|
||||
const Diagonal&
|
||||
getDiagonal() const
|
||||
{
|
||||
return diagonal;
|
||||
|
@ -373,29 +375,29 @@ public:
|
|||
diag_iter findNextLargerBlock(diag_iter start, diag_iter end, double a);
|
||||
|
||||
/* (I+this)·y = x, y→x */
|
||||
virtual void solvePre(Vector &x, double &eig_min);
|
||||
virtual void solvePre(Vector& x, double& eig_min);
|
||||
/* (I+thisᵀ)·y = x, y→x */
|
||||
virtual void solvePreTrans(Vector &x, double &eig_min);
|
||||
virtual void solvePreTrans(Vector& x, double& eig_min);
|
||||
/* (I+this)·x = b */
|
||||
virtual void solve(Vector &x, const ConstVector &b, double &eig_min);
|
||||
virtual void solve(Vector& x, const ConstVector& b, double& eig_min);
|
||||
/* (I+thisᵀ)·x = b */
|
||||
virtual void solveTrans(Vector &x, const ConstVector &b, double &eig_min);
|
||||
virtual void solveTrans(Vector& x, const ConstVector& b, double& eig_min);
|
||||
/* x = this·b */
|
||||
virtual void multVec(Vector &x, const ConstVector &b) const;
|
||||
virtual void multVec(Vector& x, const ConstVector& b) const;
|
||||
/* x = thisᵀ·b */
|
||||
virtual void multVecTrans(Vector &x, const ConstVector &b) const;
|
||||
virtual void multVecTrans(Vector& x, const ConstVector& b) const;
|
||||
/* x = x + this·b */
|
||||
virtual void multaVec(Vector &x, const ConstVector &b) const;
|
||||
virtual void multaVec(Vector& x, const ConstVector& b) const;
|
||||
/* x = x + thisᵀ·b */
|
||||
virtual void multaVecTrans(Vector &x, const ConstVector &b) const;
|
||||
virtual void multaVecTrans(Vector& x, const ConstVector& b) const;
|
||||
/* x = (this⊗I)·x */
|
||||
virtual void multKron(KronVector &x) const;
|
||||
virtual void multKron(KronVector& x) const;
|
||||
/* x = (thisᵀ⊗I)·x */
|
||||
virtual void multKronTrans(KronVector &x) const;
|
||||
virtual void multKronTrans(KronVector& x) const;
|
||||
/* A = this·A */
|
||||
virtual void multLeftOther(GeneralMatrix &a) const;
|
||||
virtual void multLeftOther(GeneralMatrix& a) const;
|
||||
/* A = thisᵀ·A */
|
||||
virtual void multLeftOtherTrans(GeneralMatrix &a) const;
|
||||
virtual void multLeftOtherTrans(GeneralMatrix& a) const;
|
||||
|
||||
const_diag_iter
|
||||
diag_begin() const
|
||||
|
@ -419,14 +421,14 @@ public:
|
|||
}
|
||||
|
||||
/* 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);
|
||||
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);
|
||||
|
||||
virtual std::unique_ptr<QuasiTriangular>
|
||||
clone() const
|
||||
|
@ -447,25 +449,27 @@ public:
|
|||
}
|
||||
// Returns r·this + r₂·t₂
|
||||
virtual std::unique_ptr<QuasiTriangular>
|
||||
linearlyCombine(double r, double r2, const QuasiTriangular &t2) const
|
||||
linearlyCombine(double r, double r2, const QuasiTriangular& t2) const
|
||||
{
|
||||
return std::make_unique<QuasiTriangular>(r, *this, r2, t2);
|
||||
}
|
||||
|
||||
protected:
|
||||
// this = r·t
|
||||
void setMatrix(double r, const QuasiTriangular &t);
|
||||
void setMatrix(double r, const QuasiTriangular& t);
|
||||
// this = this + r·t
|
||||
void addMatrix(double r, const QuasiTriangular &t);
|
||||
void addMatrix(double r, const QuasiTriangular& t);
|
||||
|
||||
private:
|
||||
// this = this + I
|
||||
void addUnit();
|
||||
/* x = x + (this⊗I)·b */
|
||||
void multaKron(KronVector &x, const ConstKronVector &b) const;
|
||||
void multaKron(KronVector& x, const ConstKronVector& b) const;
|
||||
/* x = x + (thisᵀ⊗I)·b */
|
||||
void multaKronTrans(KronVector &x, const ConstKronVector &b) const;
|
||||
void multaKronTrans(KronVector& x, const ConstKronVector& b) const;
|
||||
/* hide noneffective implementations of parents */
|
||||
void multsVec(Vector &x, const ConstVector &d) const;
|
||||
void multsVecTrans(Vector &x, const ConstVector &d) const;
|
||||
void multsVec(Vector& x, const ConstVector& d) const;
|
||||
void multsVecTrans(Vector& x, const ConstVector& d) const;
|
||||
};
|
||||
|
||||
#endif /* QUASI_TRIANGULAR_H */
|
||||
|
|
|
@ -20,69 +20,58 @@
|
|||
|
||||
#include "QuasiTriangularZero.hh"
|
||||
#include "SchurDecomp.hh"
|
||||
#include "SylvMatrix.hh"
|
||||
#include "SylvException.hh"
|
||||
#include "SylvMatrix.hh"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
QuasiTriangularZero::QuasiTriangularZero(int num_zeros, const ConstVector &d,
|
||||
int d_size)
|
||||
: QuasiTriangular(SqSylvMatrix(GeneralMatrix(Vector{d}, num_zeros+d_size, d_size),
|
||||
num_zeros, 0, d_size).getData(),
|
||||
d_size),
|
||||
QuasiTriangularZero::QuasiTriangularZero(int num_zeros, const ConstVector& d, int d_size) :
|
||||
QuasiTriangular(
|
||||
SqSylvMatrix(GeneralMatrix(Vector {d}, num_zeros + d_size, d_size), num_zeros, 0, d_size)
|
||||
.getData(),
|
||||
d_size),
|
||||
nz(num_zeros),
|
||||
ru(GeneralMatrix(Vector{d}, num_zeros+d_size, d_size), 0, 0, num_zeros, d_size)
|
||||
ru(GeneralMatrix(Vector {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)
|
||||
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 r2,
|
||||
const QuasiTriangularZero &t2)
|
||||
: QuasiTriangular(r, t, r2, t2),
|
||||
nz(t.nz),
|
||||
ru(t.ru)
|
||||
QuasiTriangularZero::QuasiTriangularZero(double r, const QuasiTriangularZero& t, double r2,
|
||||
const QuasiTriangularZero& t2) :
|
||||
QuasiTriangular(r, t, r2, t2),
|
||||
nz(t.nz), ru(t.ru)
|
||||
{
|
||||
ru.mult(r);
|
||||
ru.add(r2, t2.ru);
|
||||
}
|
||||
|
||||
QuasiTriangularZero::QuasiTriangularZero(const std::string &dummy, const QuasiTriangularZero &t)
|
||||
: QuasiTriangular(dummy, t),
|
||||
nz(t.nz),
|
||||
ru(t.ru)
|
||||
QuasiTriangularZero::QuasiTriangularZero(const std::string& dummy, const QuasiTriangularZero& t) :
|
||||
QuasiTriangular(dummy, t), nz(t.nz), ru(t.ru)
|
||||
{
|
||||
ru.multRight(t);
|
||||
}
|
||||
|
||||
QuasiTriangularZero::QuasiTriangularZero(const SchurDecompZero &decomp)
|
||||
: QuasiTriangular(decomp.getT().getData(),
|
||||
decomp.getT().nrows()),
|
||||
nz(decomp.getZeroCols()),
|
||||
QuasiTriangularZero::QuasiTriangularZero(const SchurDecompZero& decomp) :
|
||||
QuasiTriangular(decomp.getT().getData(), decomp.getT().nrows()), nz(decomp.getZeroCols()),
|
||||
ru(decomp.getRU())
|
||||
{
|
||||
}
|
||||
|
||||
QuasiTriangularZero::QuasiTriangularZero(const QuasiTriangular &t)
|
||||
: QuasiTriangular(t),
|
||||
nz(0), ru(0, t.getDiagonal().getSize())
|
||||
QuasiTriangularZero::QuasiTriangularZero(const QuasiTriangular& t) :
|
||||
QuasiTriangular(t), nz(0), ru(0, t.getDiagonal().getSize())
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
QuasiTriangularZero::solvePre(Vector &x, double &eig_min)
|
||||
QuasiTriangularZero::solvePre(Vector& x, double& eig_min)
|
||||
{
|
||||
Vector xu(x, 0, nz);
|
||||
Vector xl(x, nz, x.length()-nz);
|
||||
Vector xl(x, nz, x.length() - nz);
|
||||
QuasiTriangular::solvePre(xl, eig_min);
|
||||
ru.multsVec(xu, xl);
|
||||
if (nz > 0)
|
||||
|
@ -90,10 +79,10 @@ QuasiTriangularZero::solvePre(Vector &x, double &eig_min)
|
|||
}
|
||||
|
||||
void
|
||||
QuasiTriangularZero::solvePreTrans(Vector &x, double &eig_min)
|
||||
QuasiTriangularZero::solvePreTrans(Vector& x, double& eig_min)
|
||||
{
|
||||
Vector xu(x, 0, nz);
|
||||
Vector xl(x, nz, x.length()-nz);
|
||||
Vector xl(x, nz, x.length() - nz);
|
||||
ru.multsVecTrans(xl, xu);
|
||||
QuasiTriangular::solvePreTrans(xl, eig_min);
|
||||
if (nz > 0)
|
||||
|
@ -101,47 +90,47 @@ QuasiTriangularZero::solvePreTrans(Vector &x, double &eig_min)
|
|||
}
|
||||
|
||||
void
|
||||
QuasiTriangularZero::multVec(Vector &x, const ConstVector &b) const
|
||||
QuasiTriangularZero::multVec(Vector& x, const ConstVector& b) const
|
||||
{
|
||||
x.zeros();
|
||||
multaVec(x, b);
|
||||
}
|
||||
|
||||
void
|
||||
QuasiTriangularZero::multVecTrans(Vector &x, const ConstVector &b) const
|
||||
QuasiTriangularZero::multVecTrans(Vector& x, const ConstVector& b) const
|
||||
{
|
||||
x.zeros();
|
||||
multaVecTrans(x, b);
|
||||
}
|
||||
|
||||
void
|
||||
QuasiTriangularZero::multaVec(Vector &x, const ConstVector &b) const
|
||||
QuasiTriangularZero::multaVec(Vector& x, const ConstVector& b) const
|
||||
{
|
||||
ConstVector bl(b, nz, b.length()-nz);
|
||||
ConstVector bl(b, nz, b.length() - nz);
|
||||
Vector xu(x, 0, nz);
|
||||
Vector xl(x, nz, x.length()-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
|
||||
QuasiTriangularZero::multaVecTrans(Vector& x, const ConstVector& b) const
|
||||
{
|
||||
ConstVector bu(b, 0, b.length());
|
||||
ConstVector bl(b, nz, b.length()-nz);
|
||||
ConstVector bl(b, nz, b.length() - nz);
|
||||
Vector xu(x, 0, nz);
|
||||
Vector xl(x, nz, x.length()-nz);
|
||||
Vector xl(x, nz, x.length() - nz);
|
||||
xu.zeros();
|
||||
QuasiTriangular::multVecTrans(xl, bl);
|
||||
ru.multaVecTrans(xl, bu);
|
||||
}
|
||||
|
||||
void
|
||||
QuasiTriangularZero::multLeftOther(GeneralMatrix &a) const
|
||||
QuasiTriangularZero::multLeftOther(GeneralMatrix& a) const
|
||||
{
|
||||
GeneralMatrix a1(a, 0, 0, nz, a.ncols());
|
||||
GeneralMatrix a2(a, nz, 0, a.nrows()-nz, a.ncols());
|
||||
GeneralMatrix a2(a, nz, 0, a.nrows() - nz, a.ncols());
|
||||
a1.mult(ru, a2);
|
||||
QuasiTriangular::multLeftOther(a2);
|
||||
}
|
||||
|
@ -151,19 +140,18 @@ QuasiTriangularZero::print() const
|
|||
{
|
||||
std::cout << "super=" << std::endl;
|
||||
QuasiTriangular::print();
|
||||
std::cout << "nz=" << nz << std::endl
|
||||
<< "ru=" << std::endl;
|
||||
std::cout << "nz=" << nz << std::endl << "ru=" << std::endl;
|
||||
ru.print();
|
||||
}
|
||||
|
||||
void
|
||||
QuasiTriangularZero::multKron([[maybe_unused]] KronVector &x) const
|
||||
QuasiTriangularZero::multKron([[maybe_unused]] KronVector& x) const
|
||||
{
|
||||
throw SYLV_MES_EXCEPTION("Attempt to run QuasiTriangularZero::multKron.");
|
||||
}
|
||||
|
||||
void
|
||||
QuasiTriangularZero::multKronTrans([[maybe_unused]] KronVector &x) const
|
||||
QuasiTriangularZero::multKronTrans([[maybe_unused]] KronVector& x) const
|
||||
{
|
||||
throw SYLV_MES_EXCEPTION("Attempt to run QuasiTriangularZero::multKronTrans.");
|
||||
}
|
||||
|
|
|
@ -21,8 +21,8 @@
|
|||
#ifndef QUASI_TRIANGULAR_ZERO_H
|
||||
#define QUASI_TRIANGULAR_ZERO_H
|
||||
|
||||
#include "QuasiTriangular.hh"
|
||||
#include "GeneralMatrix.hh"
|
||||
#include "QuasiTriangular.hh"
|
||||
|
||||
#include <memory>
|
||||
|
||||
|
@ -36,29 +36,29 @@
|
|||
|
||||
class QuasiTriangularZero : public QuasiTriangular
|
||||
{
|
||||
int nz; // number of zero columns
|
||||
int nz; // number of zero columns
|
||||
GeneralMatrix ru; // data in right upper part (of size nz×d_size)
|
||||
public:
|
||||
QuasiTriangularZero(int num_zeros, const ConstVector &d, int d_size);
|
||||
QuasiTriangularZero(int num_zeros, const ConstVector& d, int d_size);
|
||||
// Initializes with r·t
|
||||
QuasiTriangularZero(double r, const QuasiTriangularZero &t);
|
||||
QuasiTriangularZero(double r, const QuasiTriangularZero& t);
|
||||
// Initializes with r·t+r₂·t₂
|
||||
QuasiTriangularZero(double r, const QuasiTriangularZero &t,
|
||||
double r2, const QuasiTriangularZero &t2);
|
||||
QuasiTriangularZero(double r, const QuasiTriangularZero& t, double r2,
|
||||
const QuasiTriangularZero& t2);
|
||||
// Initializes with t²
|
||||
QuasiTriangularZero(const std::string &dummy, const QuasiTriangularZero &t);
|
||||
explicit QuasiTriangularZero(const QuasiTriangular &t);
|
||||
explicit QuasiTriangularZero(const SchurDecompZero &decomp);
|
||||
QuasiTriangularZero(const std::string& dummy, const QuasiTriangularZero& t);
|
||||
explicit QuasiTriangularZero(const QuasiTriangular& t);
|
||||
explicit QuasiTriangularZero(const SchurDecompZero& decomp);
|
||||
~QuasiTriangularZero() override = default;
|
||||
void solvePre(Vector &x, double &eig_min) override;
|
||||
void solvePreTrans(Vector &x, double &eig_min) override;
|
||||
void multVec(Vector &x, const ConstVector &b) const override;
|
||||
void multVecTrans(Vector &x, const ConstVector &b) const override;
|
||||
void multaVec(Vector &x, const ConstVector &b) const override;
|
||||
void multaVecTrans(Vector &x, const ConstVector &b) const override;
|
||||
void multKron(KronVector &x) const override;
|
||||
void multKronTrans(KronVector &x) const override;
|
||||
void multLeftOther(GeneralMatrix &a) const override;
|
||||
void solvePre(Vector& x, double& eig_min) override;
|
||||
void solvePreTrans(Vector& x, double& eig_min) override;
|
||||
void multVec(Vector& x, const ConstVector& b) const override;
|
||||
void multVecTrans(Vector& x, const ConstVector& b) const override;
|
||||
void multaVec(Vector& x, const ConstVector& b) const override;
|
||||
void multaVecTrans(Vector& x, const ConstVector& b) const override;
|
||||
void multKron(KronVector& x) const override;
|
||||
void multKronTrans(KronVector& x) const override;
|
||||
void multLeftOther(GeneralMatrix& a) const override;
|
||||
|
||||
std::unique_ptr<QuasiTriangular>
|
||||
clone() const override
|
||||
|
@ -76,9 +76,10 @@ public:
|
|||
return std::make_unique<QuasiTriangularZero>(r, *this);
|
||||
}
|
||||
std::unique_ptr<QuasiTriangular>
|
||||
linearlyCombine(double r, double r2, const QuasiTriangular &t2) const override
|
||||
linearlyCombine(double r, double r2, const QuasiTriangular& t2) const override
|
||||
{
|
||||
return std::make_unique<QuasiTriangularZero>(r, *this, r2, dynamic_cast<const QuasiTriangularZero &>(t2));
|
||||
return std::make_unique<QuasiTriangularZero>(r, *this, r2,
|
||||
dynamic_cast<const QuasiTriangularZero&>(t2));
|
||||
}
|
||||
void print() const override;
|
||||
};
|
||||
|
|
|
@ -24,8 +24,7 @@
|
|||
|
||||
#include <dynlapack.h>
|
||||
|
||||
SchurDecomp::SchurDecomp(const SqSylvMatrix &m)
|
||||
: q(m.nrows())
|
||||
SchurDecomp::SchurDecomp(const SqSylvMatrix& m) : q(m.nrows())
|
||||
{
|
||||
lapack_int rows = m.nrows();
|
||||
SqSylvMatrix auxt(m);
|
||||
|
@ -33,24 +32,22 @@ SchurDecomp::SchurDecomp(const SqSylvMatrix &m)
|
|||
lapack_int sdim;
|
||||
auto wr = std::make_unique<double[]>(rows);
|
||||
auto wi = std::make_unique<double[]>(rows);
|
||||
lapack_int lwork = 6*rows;
|
||||
lapack_int lwork = 6 * rows;
|
||||
auto work = std::make_unique<double[]>(lwork);
|
||||
lapack_int info;
|
||||
dgees("V", "N", nullptr, &rows, auxt.base(), &lda, &sdim,
|
||||
wr.get(), wi.get(), q.base(), &ldvs,
|
||||
dgees("V", "N", nullptr, &rows, auxt.base(), &lda, &sdim, wr.get(), wi.get(), q.base(), &ldvs,
|
||||
work.get(), &lwork, nullptr, &info);
|
||||
t_storage = std::make_unique<QuasiTriangular>(auxt.getData(), rows);
|
||||
t = t_storage.get();
|
||||
}
|
||||
|
||||
SchurDecomp::SchurDecomp(const QuasiTriangular &tr)
|
||||
: q(tr.nrows()), t_storage{std::make_unique<QuasiTriangular>(tr)}, t{t_storage.get()}
|
||||
SchurDecomp::SchurDecomp(const QuasiTriangular& tr) :
|
||||
q(tr.nrows()), t_storage {std::make_unique<QuasiTriangular>(tr)}, t {t_storage.get()}
|
||||
{
|
||||
q.setUnit();
|
||||
}
|
||||
|
||||
SchurDecomp::SchurDecomp(QuasiTriangular &tr)
|
||||
: q(tr.nrows()), t{&tr}
|
||||
SchurDecomp::SchurDecomp(QuasiTriangular& tr) : q(tr.nrows()), t {&tr}
|
||||
{
|
||||
q.setUnit();
|
||||
}
|
||||
|
@ -61,9 +58,9 @@ SchurDecomp::getDim() const
|
|||
return t->nrows();
|
||||
}
|
||||
|
||||
SchurDecompZero::SchurDecompZero(const GeneralMatrix &m)
|
||||
: SchurDecomp(SqSylvMatrix(m, m.nrows()-m.ncols(), 0, m.ncols())),
|
||||
ru(m, 0, 0, m.nrows()-m.ncols(), m.ncols())
|
||||
SchurDecompZero::SchurDecompZero(const GeneralMatrix& m) :
|
||||
SchurDecomp(SqSylvMatrix(m, m.nrows() - m.ncols(), 0, m.ncols())),
|
||||
ru(m, 0, 0, m.nrows() - m.ncols(), m.ncols())
|
||||
{
|
||||
ru.multRight(getQ());
|
||||
}
|
||||
|
@ -71,5 +68,5 @@ SchurDecompZero::SchurDecompZero(const GeneralMatrix &m)
|
|||
int
|
||||
SchurDecompZero::getDim() const
|
||||
{
|
||||
return getT().nrows()+ru.nrows();
|
||||
return getT().nrows() + ru.nrows();
|
||||
}
|
||||
|
|
|
@ -21,8 +21,8 @@
|
|||
#ifndef SCHUR_DECOMP_H
|
||||
#define SCHUR_DECOMP_H
|
||||
|
||||
#include "SylvMatrix.hh"
|
||||
#include "QuasiTriangular.hh"
|
||||
#include "SylvMatrix.hh"
|
||||
|
||||
#include <memory>
|
||||
|
||||
|
@ -32,27 +32,28 @@ class SchurDecomp
|
|||
SqSylvMatrix q;
|
||||
// Stores t if is owned
|
||||
std::unique_ptr<QuasiTriangular> t_storage;
|
||||
QuasiTriangular *t;
|
||||
QuasiTriangular* t;
|
||||
|
||||
public:
|
||||
SchurDecomp(const SqSylvMatrix &m);
|
||||
SchurDecomp(const QuasiTriangular &tr);
|
||||
SchurDecomp(QuasiTriangular &tr);
|
||||
const SqSylvMatrix &
|
||||
SchurDecomp(const SqSylvMatrix& m);
|
||||
SchurDecomp(const QuasiTriangular& tr);
|
||||
SchurDecomp(QuasiTriangular& tr);
|
||||
const SqSylvMatrix&
|
||||
getQ() const
|
||||
{
|
||||
return q;
|
||||
}
|
||||
const QuasiTriangular &
|
||||
const QuasiTriangular&
|
||||
getT() const
|
||||
{
|
||||
return *t;
|
||||
}
|
||||
SqSylvMatrix &
|
||||
SqSylvMatrix&
|
||||
getQ()
|
||||
{
|
||||
return q;
|
||||
}
|
||||
QuasiTriangular &
|
||||
QuasiTriangular&
|
||||
getT()
|
||||
{
|
||||
return *t;
|
||||
|
@ -65,7 +66,7 @@ class SchurDecompZero : public SchurDecomp
|
|||
{
|
||||
GeneralMatrix ru; // right upper matrix
|
||||
public:
|
||||
SchurDecompZero(const GeneralMatrix &m);
|
||||
SchurDecompZero(const GeneralMatrix& m);
|
||||
ConstGeneralMatrix
|
||||
getRU() const
|
||||
{
|
||||
|
|
|
@ -67,7 +67,7 @@ SchurDecompEig::bubbleEigen(diag_iter from, diag_iter to)
|
|||
The success is signaled by returned true.
|
||||
*/
|
||||
bool
|
||||
SchurDecompEig::tryToSwap(diag_iter &it, diag_iter &itadd)
|
||||
SchurDecompEig::tryToSwap(diag_iter& it, diag_iter& itadd)
|
||||
{
|
||||
itadd = it;
|
||||
--itadd;
|
||||
|
@ -77,8 +77,7 @@ SchurDecompEig::tryToSwap(diag_iter &it, diag_iter &itadd)
|
|||
lapack_int ilst = itadd->getIndex() + 1;
|
||||
auto work = std::make_unique<double[]>(n);
|
||||
lapack_int info;
|
||||
dtrexc("V", &n, getT().base(), &ldt, getQ().base(), &ldq, &ifst, &ilst, work.get(),
|
||||
&info);
|
||||
dtrexc("V", &n, getT().base(), &ldt, getQ().base(), &ldq, &ifst, &ilst, work.get(), &info);
|
||||
if (info < 0)
|
||||
throw SYLV_MES_EXCEPTION("Wrong argument to dtrexc.");
|
||||
|
||||
|
@ -105,8 +104,7 @@ SchurDecompEig::orderEigen()
|
|||
double last_size = 0.0;
|
||||
while (runp != getT().diag_end())
|
||||
{
|
||||
diag_iter least = getT().findNextLargerBlock(run, getT().diag_end(),
|
||||
last_size);
|
||||
diag_iter least = getT().findNextLargerBlock(run, getT().diag_end(), last_size);
|
||||
last_size = least->getSize();
|
||||
if (run == least)
|
||||
++run;
|
||||
|
|
|
@ -23,26 +23,25 @@
|
|||
#ifndef SCHUR_DECOMP_EIG_H
|
||||
#define SCHUR_DECOMP_EIG_H
|
||||
|
||||
#include "SchurDecomp.hh"
|
||||
#include "QuasiTriangular.hh"
|
||||
#include "SchurDecomp.hh"
|
||||
|
||||
class SchurDecompEig : public SchurDecomp
|
||||
{
|
||||
public:
|
||||
using diag_iter = QuasiTriangular::diag_iter;
|
||||
SchurDecompEig(const SqSylvMatrix &m) : SchurDecomp(m)
|
||||
SchurDecompEig(const SqSylvMatrix& m) : SchurDecomp(m)
|
||||
{
|
||||
}
|
||||
SchurDecompEig(const QuasiTriangular &tr) : SchurDecomp(tr)
|
||||
{
|
||||
};
|
||||
SchurDecompEig(QuasiTriangular &tr) : SchurDecomp(tr)
|
||||
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);
|
||||
bool tryToSwap(diag_iter& it, diag_iter& itadd);
|
||||
};
|
||||
|
||||
#endif /* SCHUR_DECOMP_EIG_H */
|
||||
|
|
|
@ -27,9 +27,9 @@
|
|||
|
||||
#include <cmath>
|
||||
|
||||
SimilarityDecomp::SimilarityDecomp(const ConstVector &d, int d_size, double log10norm)
|
||||
SimilarityDecomp::SimilarityDecomp(const ConstVector& d, int d_size, double log10norm)
|
||||
{
|
||||
SchurDecomp sd(SqSylvMatrix(Vector{d}, d_size));
|
||||
SchurDecomp sd(SqSylvMatrix(Vector {d}, d_size));
|
||||
q = std::make_unique<SqSylvMatrix>(sd.getQ());
|
||||
b = std::make_unique<BlockDiagonal>(sd.getT());
|
||||
invq = std::make_unique<SqSylvMatrix>(d_size);
|
||||
|
@ -40,8 +40,7 @@ SimilarityDecomp::SimilarityDecomp(const ConstVector &d, int d_size, double log1
|
|||
}
|
||||
|
||||
void
|
||||
SimilarityDecomp::getXDim(diag_iter start, diag_iter end,
|
||||
int &rows, int &cols) const
|
||||
SimilarityDecomp::getXDim(diag_iter start, diag_iter end, int& rows, int& cols) const
|
||||
{
|
||||
int si = start->getIndex();
|
||||
int ei = end->getIndex();
|
||||
|
@ -54,15 +53,14 @@ SimilarityDecomp::getXDim(diag_iter start, diag_iter end,
|
|||
norm, X is not changed and flase is returned.
|
||||
*/
|
||||
bool
|
||||
SimilarityDecomp::solveX(diag_iter start, diag_iter end,
|
||||
GeneralMatrix &X, double norm) const
|
||||
SimilarityDecomp::solveX(diag_iter start, diag_iter end, GeneralMatrix& X, double norm) const
|
||||
{
|
||||
int si = start->getIndex();
|
||||
int ei = end->getIndex();
|
||||
|
||||
SqSylvMatrix A(const_cast<const BlockDiagonal &>(*b), si, si, X.nrows());
|
||||
SqSylvMatrix B(const_cast<const BlockDiagonal &>(*b), ei, ei, X.ncols());
|
||||
GeneralMatrix C(const_cast<const BlockDiagonal &>(*b), si, ei, X.nrows(), X.ncols());
|
||||
SqSylvMatrix A(const_cast<const BlockDiagonal&>(*b), si, si, X.nrows());
|
||||
SqSylvMatrix B(const_cast<const BlockDiagonal&>(*b), ei, ei, X.ncols());
|
||||
GeneralMatrix C(const_cast<const BlockDiagonal&>(*b), si, ei, X.nrows(), X.ncols());
|
||||
|
||||
lapack_int isgn = -1;
|
||||
lapack_int m = A.nrows();
|
||||
|
@ -70,8 +68,7 @@ SimilarityDecomp::solveX(diag_iter start, diag_iter end,
|
|||
lapack_int lda = A.getLD(), ldb = B.getLD();
|
||||
double scale;
|
||||
lapack_int info;
|
||||
dtrsyl("N", "N", &isgn, &m, &n, A.base(), &lda, B.base(), &ldb,
|
||||
C.base(), &m, &scale, &info);
|
||||
dtrsyl("N", "N", &isgn, &m, &n, A.base(), &lda, B.base(), &ldb, C.base(), &m, &scale, &info);
|
||||
if (info < -1)
|
||||
throw SYLV_MES_EXCEPTION("Wrong parameter to LAPACK dtrsyl.");
|
||||
|
||||
|
@ -87,8 +84,7 @@ SimilarityDecomp::solveX(diag_iter start, diag_iter end,
|
|||
/* ⎛I −X⎞ ⎛I X⎞
|
||||
Multiply Q and invQ with ⎝0 I⎠ and ⎝0 I⎠ respectively. This also sets X=−X. */
|
||||
void
|
||||
SimilarityDecomp::updateTransform(diag_iter start, diag_iter end,
|
||||
GeneralMatrix &X)
|
||||
SimilarityDecomp::updateTransform(diag_iter start, diag_iter end, GeneralMatrix& X)
|
||||
{
|
||||
int si = start->getIndex();
|
||||
int ei = end->getIndex();
|
||||
|
@ -105,11 +101,11 @@ SimilarityDecomp::updateTransform(diag_iter start, diag_iter end,
|
|||
}
|
||||
|
||||
void
|
||||
SimilarityDecomp::bringGuiltyBlock(diag_iter start, diag_iter &end)
|
||||
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(*b); // works on b including diagonal structure
|
||||
SchurDecompEig sd(*b); // works on b including diagonal structure
|
||||
end = sd.bubbleEigen(guilty, end); // iterators are valid
|
||||
++end;
|
||||
q->multRight(sd.getQ());
|
||||
|
@ -142,7 +138,7 @@ SimilarityDecomp::diagonalize(double norm)
|
|||
}
|
||||
|
||||
void
|
||||
SimilarityDecomp::check(SylvParams &pars, const GeneralMatrix &m) const
|
||||
SimilarityDecomp::check(SylvParams& pars, const GeneralMatrix& m) const
|
||||
{
|
||||
// M − Q·B·Q⁻¹
|
||||
SqSylvMatrix c(getQ() * getB());
|
||||
|
@ -167,7 +163,7 @@ SimilarityDecomp::check(SylvParams &pars, const GeneralMatrix &m) const
|
|||
}
|
||||
|
||||
void
|
||||
SimilarityDecomp::infoToPars(SylvParams &pars) const
|
||||
SimilarityDecomp::infoToPars(SylvParams& pars) const
|
||||
{
|
||||
pars.f_blocks = getB().getNumBlocks();
|
||||
pars.f_largest = getB().getLargestBlock();
|
||||
|
|
|
@ -21,8 +21,8 @@
|
|||
#ifndef SIMILARITY_DECOMP_H
|
||||
#define SIMILARITY_DECOMP_H
|
||||
|
||||
#include "SylvMatrix.hh"
|
||||
#include "BlockDiagonal.hh"
|
||||
#include "SylvMatrix.hh"
|
||||
#include "SylvParams.hh"
|
||||
|
||||
#include <memory>
|
||||
|
@ -33,31 +33,33 @@ class SimilarityDecomp
|
|||
std::unique_ptr<BlockDiagonal> b;
|
||||
std::unique_ptr<SqSylvMatrix> invq;
|
||||
using diag_iter = BlockDiagonal::diag_iter;
|
||||
|
||||
public:
|
||||
SimilarityDecomp(const ConstVector &d, int d_size, double log10norm = 3.0);
|
||||
SimilarityDecomp(const ConstVector& d, int d_size, double log10norm = 3.0);
|
||||
virtual ~SimilarityDecomp() = default;
|
||||
const SqSylvMatrix &
|
||||
const SqSylvMatrix&
|
||||
getQ() const
|
||||
{
|
||||
return *q;
|
||||
}
|
||||
const SqSylvMatrix &
|
||||
const SqSylvMatrix&
|
||||
getInvQ() const
|
||||
{
|
||||
return *invq;
|
||||
}
|
||||
const BlockDiagonal &
|
||||
const BlockDiagonal&
|
||||
getB() const
|
||||
{
|
||||
return *b;
|
||||
}
|
||||
void check(SylvParams &pars, const GeneralMatrix &m) const;
|
||||
void infoToPars(SylvParams &pars) const;
|
||||
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 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);
|
||||
};
|
||||
|
||||
|
|
|
@ -23,8 +23,7 @@
|
|||
#include <iostream>
|
||||
#include <utility>
|
||||
|
||||
SylvException::SylvException(std::string f, int l)
|
||||
: file{std::move(f)}, line{l}
|
||||
SylvException::SylvException(std::string f, int l) : file {std::move(f)}, line {l}
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -40,9 +39,8 @@ SylvException::getMessage() const
|
|||
return "From " + file + ':' + std::to_string(line) + '\n';
|
||||
}
|
||||
|
||||
SylvExceptionMessage::SylvExceptionMessage(std::string f, int i,
|
||||
std::string mes)
|
||||
: SylvException{std::move(f), i}, message{std::move(mes)}
|
||||
SylvExceptionMessage::SylvExceptionMessage(std::string f, int i, std::string mes) :
|
||||
SylvException {std::move(f), i}, message {std::move(mes)}
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@ class SylvException
|
|||
protected:
|
||||
std::string file;
|
||||
int line;
|
||||
|
||||
public:
|
||||
SylvException(std::string f, int l);
|
||||
virtual ~SylvException() = default;
|
||||
|
@ -38,6 +39,7 @@ public:
|
|||
class SylvExceptionMessage : public SylvException
|
||||
{
|
||||
std::string message;
|
||||
|
||||
public:
|
||||
SylvExceptionMessage(std::string f, int l, std::string mes);
|
||||
std::string getMessage() const override;
|
||||
|
|
|
@ -18,8 +18,8 @@
|
|||
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "SylvException.hh"
|
||||
#include "SylvMatrix.hh"
|
||||
#include "SylvException.hh"
|
||||
#include "int_power.hh"
|
||||
|
||||
#include <dynblas.h>
|
||||
|
@ -29,7 +29,7 @@
|
|||
#include <memory>
|
||||
|
||||
void
|
||||
SylvMatrix::multLeftI(const SqSylvMatrix &m)
|
||||
SylvMatrix::multLeftI(const SqSylvMatrix& m)
|
||||
{
|
||||
int off = rows - m.nrows();
|
||||
if (off < 0)
|
||||
|
@ -40,7 +40,7 @@ SylvMatrix::multLeftI(const SqSylvMatrix &m)
|
|||
}
|
||||
|
||||
void
|
||||
SylvMatrix::multLeftITrans(const SqSylvMatrix &m)
|
||||
SylvMatrix::multLeftITrans(const SqSylvMatrix& m)
|
||||
{
|
||||
int off = rows - m.nrows();
|
||||
if (off < 0)
|
||||
|
@ -51,11 +51,10 @@ SylvMatrix::multLeftITrans(const SqSylvMatrix &m)
|
|||
}
|
||||
|
||||
void
|
||||
SylvMatrix::multLeft(int zero_cols, const GeneralMatrix &a, const GeneralMatrix &b)
|
||||
SylvMatrix::multLeft(int zero_cols, const GeneralMatrix& a, const GeneralMatrix& b)
|
||||
{
|
||||
int off = a.nrows() - a.ncols();
|
||||
if (off < 0 || a.nrows() != rows || off != zero_cols
|
||||
|| rows != b.nrows() || cols != b.ncols())
|
||||
if (off < 0 || a.nrows() != rows || off != zero_cols || rows != b.nrows() || cols != b.ncols())
|
||||
throw SYLV_MES_EXCEPTION("Wrong matrix dimensions for multLeft.");
|
||||
|
||||
/* Here we cannot call SylvMatrix::gemm() since it would require
|
||||
|
@ -71,77 +70,77 @@ SylvMatrix::multLeft(int zero_cols, const GeneralMatrix &a, const GeneralMatrix
|
|||
blas_int ldb = ld;
|
||||
double beta = 0.0;
|
||||
blas_int ldc = ld;
|
||||
dgemm("N", "N", &mm, &nn, &kk, &alpha, a.getData().base(), &lda,
|
||||
b.getData().base()+off, &ldb, &beta, data.base(), &ldc);
|
||||
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)
|
||||
SylvMatrix::multRightKron(const SqSylvMatrix& m, int order)
|
||||
{
|
||||
if (power(m.nrows(), order) != cols)
|
||||
throw SYLV_MES_EXCEPTION("Wrong number of cols for right kron multiply.");
|
||||
|
||||
KronVector auxrow(m.nrows(), m.nrows(), order-1);
|
||||
KronVector auxrow(m.nrows(), m.nrows(), order - 1);
|
||||
for (int i = 0; i < rows; i++)
|
||||
{
|
||||
Vector rowi{getRow(i)};
|
||||
KronVector rowikron(rowi, m.nrows(), m.nrows(), order-1);
|
||||
Vector rowi {getRow(i)};
|
||||
KronVector rowikron(rowi, m.nrows(), m.nrows(), order - 1);
|
||||
auxrow = rowi; // copy data
|
||||
m.multVecKronTrans(rowikron, auxrow);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SylvMatrix::multRightKronTrans(const SqSylvMatrix &m, int order)
|
||||
SylvMatrix::multRightKronTrans(const SqSylvMatrix& m, int order)
|
||||
{
|
||||
if (power(m.nrows(), order) != cols)
|
||||
throw SYLV_MES_EXCEPTION("Wrong number of cols for right kron multiply.");
|
||||
|
||||
KronVector auxrow(m.nrows(), m.nrows(), order-1);
|
||||
KronVector auxrow(m.nrows(), m.nrows(), order - 1);
|
||||
for (int i = 0; i < rows; i++)
|
||||
{
|
||||
Vector rowi{getRow(i)};
|
||||
KronVector rowikron(rowi, m.nrows(), m.nrows(), order-1);
|
||||
Vector rowi {getRow(i)};
|
||||
KronVector rowikron(rowi, m.nrows(), m.nrows(), order - 1);
|
||||
auxrow = rowi; // copy data
|
||||
m.multVecKron(rowikron, auxrow);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SylvMatrix::eliminateLeft(int row, int col, Vector &x)
|
||||
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;
|
||||
double mult = e / d;
|
||||
for (int i = col + 1; i < ncols(); i++)
|
||||
get(row, i) = get(row, i) - mult*get(col, i);
|
||||
x[row] = x[row] - mult*x[col];
|
||||
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;
|
||||
double mult = d / e;
|
||||
for (int i = col + 1; i < ncols(); i++)
|
||||
{
|
||||
double tx = get(col, i);
|
||||
double ty = get(row, i);
|
||||
get(col, i) = ty;
|
||||
get(row, i) = tx - mult*ty;
|
||||
get(row, i) = tx - mult * ty;
|
||||
}
|
||||
double tx = x[col];
|
||||
double ty = x[row];
|
||||
x[col] = ty;
|
||||
x[row] = tx - mult*ty;
|
||||
x[row] = tx - mult * ty;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SylvMatrix::eliminateRight(int row, int col, Vector &x)
|
||||
SylvMatrix::eliminateRight(int row, int col, Vector& x)
|
||||
{
|
||||
double d = get(row, row);
|
||||
double e = get(row, col);
|
||||
|
@ -149,32 +148,32 @@ SylvMatrix::eliminateRight(int row, int col, Vector &x)
|
|||
if (std::abs(d) > std::abs(e))
|
||||
{
|
||||
get(row, col) = 0.0;
|
||||
double mult = e/d;
|
||||
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];
|
||||
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;
|
||||
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;
|
||||
get(i, col) = tx - mult * ty;
|
||||
}
|
||||
double tx = x[row];
|
||||
double ty = x[col];
|
||||
x[row] = ty;
|
||||
x[col] = tx - mult*ty;
|
||||
x[col] = tx - mult * ty;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SqSylvMatrix::multVecKron(KronVector &x, const ConstKronVector &d) const
|
||||
SqSylvMatrix::multVecKron(KronVector& x, const ConstKronVector& d) const
|
||||
{
|
||||
x.zeros();
|
||||
if (d.getDepth() == 0)
|
||||
|
@ -201,7 +200,7 @@ SqSylvMatrix::multVecKron(KronVector &x, const ConstKronVector &d) const
|
|||
}
|
||||
|
||||
void
|
||||
SqSylvMatrix::multVecKronTrans(KronVector &x, const ConstKronVector &d) const
|
||||
SqSylvMatrix::multVecKronTrans(KronVector& x, const ConstKronVector& d) const
|
||||
{
|
||||
x.zeros();
|
||||
if (d.getDepth() == 0)
|
||||
|
@ -228,8 +227,8 @@ SqSylvMatrix::multVecKronTrans(KronVector &x, const ConstKronVector &d) const
|
|||
}
|
||||
|
||||
void
|
||||
SqSylvMatrix::multInvLeft2(GeneralMatrix &a, GeneralMatrix &b,
|
||||
double &rcond1, double &rcondinf) const
|
||||
SqSylvMatrix::multInvLeft2(GeneralMatrix& a, GeneralMatrix& b, double& rcond1,
|
||||
double& rcondinf) const
|
||||
{
|
||||
if (rows != a.nrows() || rows != b.nrows())
|
||||
throw SYLV_MES_EXCEPTION("Wrong dimensions for multInvLeft2.");
|
||||
|
@ -242,24 +241,20 @@ SqSylvMatrix::multInvLeft2(GeneralMatrix &a, GeneralMatrix &b,
|
|||
dgetrf(&rows2, &rows2, inv.base(), &lda, ipiv.get(), &info);
|
||||
// solve a
|
||||
lapack_int acols = a.ncols();
|
||||
double *abase = a.base();
|
||||
dgetrs("N", &rows2, &acols, inv.base(), &lda, ipiv.get(),
|
||||
abase, &rows2, &info);
|
||||
double* abase = a.base();
|
||||
dgetrs("N", &rows2, &acols, inv.base(), &lda, ipiv.get(), abase, &rows2, &info);
|
||||
// solve b
|
||||
lapack_int bcols = b.ncols();
|
||||
double *bbase = b.base();
|
||||
dgetrs("N", &rows2, &bcols, inv.base(), &lda, ipiv.get(),
|
||||
bbase, &rows2, &info);
|
||||
double* bbase = b.base();
|
||||
dgetrs("N", &rows2, &bcols, inv.base(), &lda, ipiv.get(), bbase, &rows2, &info);
|
||||
|
||||
// condition numbers
|
||||
auto work = std::make_unique<double[]>(4*rows);
|
||||
auto work = std::make_unique<double[]>(4 * rows);
|
||||
auto iwork = std::make_unique<lapack_int[]>(rows);
|
||||
double norm1 = getNorm1();
|
||||
dgecon("1", &rows2, inv.base(), &lda, &norm1, &rcond1,
|
||||
work.get(), iwork.get(), &info);
|
||||
dgecon("1", &rows2, inv.base(), &lda, &norm1, &rcond1, work.get(), iwork.get(), &info);
|
||||
double norminf = getNormInf();
|
||||
dgecon("I", &rows2, inv.base(), &lda, &norminf, &rcondinf,
|
||||
work.get(), iwork.get(), &info);
|
||||
dgecon("I", &rows2, inv.base(), &lda, &norminf, &rcondinf, work.get(), iwork.get(), &info);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -31,49 +31,46 @@ class SqSylvMatrix;
|
|||
class SylvMatrix : public GeneralMatrix
|
||||
{
|
||||
public:
|
||||
SylvMatrix(int m, int n)
|
||||
: GeneralMatrix(m, n)
|
||||
SylvMatrix(int m, int n) : GeneralMatrix(m, n)
|
||||
{
|
||||
}
|
||||
SylvMatrix(Vector d, int m, int n)
|
||||
: GeneralMatrix(std::move(d), m, n)
|
||||
SylvMatrix(Vector d, int m, int n) : GeneralMatrix(std::move(d), m, n)
|
||||
{
|
||||
}
|
||||
SylvMatrix(const GeneralMatrix &m)
|
||||
: GeneralMatrix(m)
|
||||
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(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(GeneralMatrix& m, int i, int j, int nrows, int ncols) :
|
||||
GeneralMatrix(m, i, j, nrows, ncols)
|
||||
{
|
||||
}
|
||||
SylvMatrix(const SylvMatrix &m) = default;
|
||||
SylvMatrix(SylvMatrix &&m) = default;
|
||||
SylvMatrix &operator=(const SylvMatrix &m) = default;
|
||||
SylvMatrix &operator=(SylvMatrix &&m) = default;
|
||||
SylvMatrix(const SylvMatrix& m) = default;
|
||||
SylvMatrix(SylvMatrix&& m) = default;
|
||||
SylvMatrix& operator=(const SylvMatrix& m) = default;
|
||||
SylvMatrix& operator=(SylvMatrix&& m) = default;
|
||||
|
||||
/* ⎛I 0⎞
|
||||
this = ⎝0 m⎠·this */
|
||||
void multLeftI(const SqSylvMatrix &m);
|
||||
void multLeftI(const SqSylvMatrix& m);
|
||||
/* ⎛I 0⎞
|
||||
this = ⎝0 mᵀ⎠·this */
|
||||
void multLeftITrans(const SqSylvMatrix &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);
|
||||
void multLeft(int zero_cols, const GeneralMatrix& a, const GeneralMatrix& b);
|
||||
// this = this·(m⊗m⊗…⊗m)
|
||||
void multRightKron(const SqSylvMatrix &m, int order);
|
||||
void multRightKron(const SqSylvMatrix& m, int order);
|
||||
// this = this·(mᵀ⊗mᵀ⊗…⊗mᵀ)
|
||||
void multRightKronTrans(const SqSylvMatrix &m, int order);
|
||||
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);
|
||||
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);
|
||||
void eliminateRight(int row, int col, Vector& x);
|
||||
};
|
||||
|
||||
class SqSylvMatrix : public SylvMatrix
|
||||
|
@ -85,28 +82,25 @@ public:
|
|||
SqSylvMatrix(Vector d, int m) : SylvMatrix(std::move(d), m, m)
|
||||
{
|
||||
}
|
||||
SqSylvMatrix(const SylvMatrix &m) : SylvMatrix(m)
|
||||
SqSylvMatrix(const SylvMatrix& m) : SylvMatrix(m)
|
||||
{
|
||||
}
|
||||
SqSylvMatrix(const SqSylvMatrix &m) = default;
|
||||
SqSylvMatrix(SqSylvMatrix &&m) = default;
|
||||
SqSylvMatrix(const GeneralMatrix &m, int i, int j, int nrows)
|
||||
: SylvMatrix(m, i, j, nrows, nrows)
|
||||
SqSylvMatrix(const SqSylvMatrix& m) = default;
|
||||
SqSylvMatrix(SqSylvMatrix&& m) = default;
|
||||
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(GeneralMatrix& m, int i, int j, int nrows) : SylvMatrix(m, i, j, nrows, nrows)
|
||||
{
|
||||
}
|
||||
SqSylvMatrix &operator=(const SqSylvMatrix &m) = default;
|
||||
SqSylvMatrix &operator=(SqSylvMatrix &&m) = default;
|
||||
SqSylvMatrix& operator=(const SqSylvMatrix& m) = default;
|
||||
SqSylvMatrix& operator=(SqSylvMatrix&& m) = default;
|
||||
// x = (this⊗this⊗…⊗this)·d
|
||||
void multVecKron(KronVector &x, const ConstKronVector &d) const;
|
||||
void multVecKron(KronVector& x, const ConstKronVector& d) const;
|
||||
// x = (thisᵀ⊗thisᵀ⊗…⊗thisᵀ)·d
|
||||
void multVecKronTrans(KronVector &x, const ConstKronVector &d) const;
|
||||
void multVecKronTrans(KronVector& x, const ConstKronVector& d) const;
|
||||
// a = this⁻¹·a, b=this⁻¹·b */
|
||||
void multInvLeft2(GeneralMatrix &a, GeneralMatrix &b,
|
||||
double &rcond1, double &rcondinf) const;
|
||||
void multInvLeft2(GeneralMatrix& a, GeneralMatrix& b, double& rcond1, double& rcondinf) const;
|
||||
// this = I
|
||||
void setUnit();
|
||||
};
|
||||
|
|
|
@ -23,38 +23,38 @@
|
|||
#include <iostream>
|
||||
|
||||
void
|
||||
SylvParams::print(const std::string &prefix) const
|
||||
SylvParams::print(const std::string& prefix) const
|
||||
{
|
||||
print(std::cout, prefix);
|
||||
}
|
||||
|
||||
void
|
||||
SylvParams::print(std::ostream &fdesc, const std::string &prefix) const
|
||||
SylvParams::print(std::ostream& fdesc, const std::string& prefix) const
|
||||
{
|
||||
method.print(fdesc, prefix, "method ");
|
||||
rcondA1.print(fdesc, prefix, "reci. cond1 A ");
|
||||
rcondAI.print(fdesc, prefix, "reci. cond∞ A ");
|
||||
bs_norm.print(fdesc, prefix, "log₁₀ diag norm ");
|
||||
f_err1.print(fdesc, prefix, "abs. err 1 F diag ");
|
||||
f_errI.print(fdesc, prefix, "abs. err ∞ F diag ");
|
||||
viv_err1.print(fdesc, prefix, "abs. err 1 V·V⁻¹ ");
|
||||
viv_errI.print(fdesc, prefix, "abs. err ∞ V·V⁻¹ ");
|
||||
ivv_err1.print(fdesc, prefix, "abs. err 1 V⁻¹·V ");
|
||||
ivv_errI.print(fdesc, prefix, "abs. err ∞ V⁻¹·V ");
|
||||
f_blocks.print(fdesc, prefix, "num blocks in F ");
|
||||
method.print(fdesc, prefix, "method ");
|
||||
rcondA1.print(fdesc, prefix, "reci. cond1 A ");
|
||||
rcondAI.print(fdesc, prefix, "reci. cond∞ A ");
|
||||
bs_norm.print(fdesc, prefix, "log₁₀ diag norm ");
|
||||
f_err1.print(fdesc, prefix, "abs. err 1 F diag ");
|
||||
f_errI.print(fdesc, prefix, "abs. err ∞ F diag ");
|
||||
viv_err1.print(fdesc, prefix, "abs. err 1 V·V⁻¹ ");
|
||||
viv_errI.print(fdesc, prefix, "abs. err ∞ V·V⁻¹ ");
|
||||
ivv_err1.print(fdesc, prefix, "abs. err 1 V⁻¹·V ");
|
||||
ivv_errI.print(fdesc, prefix, "abs. err ∞ V⁻¹·V ");
|
||||
f_blocks.print(fdesc, prefix, "num blocks in F ");
|
||||
f_largest.print(fdesc, prefix, "largest block in F ");
|
||||
f_zeros.print(fdesc, prefix, "num zeros in F ");
|
||||
f_zeros.print(fdesc, prefix, "num zeros in F ");
|
||||
f_offdiag.print(fdesc, prefix, "num offdiag in F ");
|
||||
if (*method == solve_method::iter)
|
||||
{
|
||||
converged.print(fdesc, prefix, "converged ");
|
||||
converged.print(fdesc, prefix, "converged ");
|
||||
convergence_tol.print(fdesc, prefix, "convergence tol. ");
|
||||
iter_last_norm.print(fdesc, prefix, "last norm ");
|
||||
max_num_iter.print(fdesc, prefix, "max num iter ");
|
||||
num_iter.print(fdesc, prefix, "num iter ");
|
||||
iter_last_norm.print(fdesc, prefix, "last norm ");
|
||||
max_num_iter.print(fdesc, prefix, "max num iter ");
|
||||
num_iter.print(fdesc, prefix, "num iter ");
|
||||
}
|
||||
else
|
||||
eig_min.print(fdesc, prefix, "minimum eigenvalue ");
|
||||
eig_min.print(fdesc, prefix, "minimum eigenvalue ");
|
||||
|
||||
mat_err1.print(fdesc, prefix, "rel. matrix norm1 ");
|
||||
mat_errI.print(fdesc, prefix, "rel. matrix norm∞ ");
|
||||
|
@ -65,7 +65,7 @@ SylvParams::print(std::ostream &fdesc, const std::string &prefix) const
|
|||
}
|
||||
|
||||
void
|
||||
SylvParams::setArrayNames(int &num, const char **names) const
|
||||
SylvParams::setArrayNames(int& num, const char** names) const
|
||||
{
|
||||
num = 0;
|
||||
if (method.getStatus() != status::undef)
|
||||
|
@ -123,25 +123,25 @@ SylvParams::setArrayNames(int &num, const char **names) const
|
|||
}
|
||||
|
||||
#if defined(MATLAB_MEX_FILE) || defined(OCTAVE_MEX_FILE)
|
||||
mxArray *
|
||||
mxArray*
|
||||
SylvParams::DoubleParamItem::createMatlabArray() const
|
||||
{
|
||||
return mxCreateDoubleScalar(value);
|
||||
}
|
||||
|
||||
mxArray *
|
||||
mxArray*
|
||||
SylvParams::IntParamItem::createMatlabArray() const
|
||||
{
|
||||
mxArray *res = mxCreateNumericMatrix(1, 1, mxINT32_CLASS, mxREAL);
|
||||
mxArray* res = mxCreateNumericMatrix(1, 1, mxINT32_CLASS, mxREAL);
|
||||
# if MX_HAS_INTERLEAVED_COMPLEX
|
||||
*mxGetInt32s(res) = value;
|
||||
# else
|
||||
*static_cast<int *>(mxGetData(res)) = value;
|
||||
*static_cast<int*>(mxGetData(res)) = value;
|
||||
# endif
|
||||
return res;
|
||||
}
|
||||
|
||||
mxArray *
|
||||
mxArray*
|
||||
SylvParams::BoolParamItem::createMatlabArray() const
|
||||
{
|
||||
if (value)
|
||||
|
@ -150,7 +150,7 @@ SylvParams::BoolParamItem::createMatlabArray() const
|
|||
return mxCreateString("false");
|
||||
}
|
||||
|
||||
mxArray *
|
||||
mxArray*
|
||||
SylvParams::MethodParamItem::createMatlabArray() const
|
||||
{
|
||||
if (value == solve_method::iter)
|
||||
|
@ -159,14 +159,14 @@ SylvParams::MethodParamItem::createMatlabArray() const
|
|||
return mxCreateString("recursive");
|
||||
}
|
||||
|
||||
mxArray *
|
||||
mxArray*
|
||||
SylvParams::createStructArray() const
|
||||
{
|
||||
const char *names[50];
|
||||
const char* names[50];
|
||||
int num;
|
||||
setArrayNames(num, names);
|
||||
const mwSize dims[] = {1, 1};
|
||||
mxArray *const res = mxCreateStructArray(2, dims, num, names);
|
||||
mxArray* const res = mxCreateStructArray(2, dims, num, names);
|
||||
|
||||
int i = 0;
|
||||
if (method.getStatus() != status::undef)
|
||||
|
|
|
@ -21,14 +21,19 @@
|
|||
#ifndef SYLV_PARAMS_H
|
||||
#define SYLV_PARAMS_H
|
||||
|
||||
#include <string>
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
|
||||
#if defined(MATLAB_MEX_FILE) || defined(OCTAVE_MEX_FILE)
|
||||
# include <dynmex.h>
|
||||
#endif
|
||||
|
||||
enum class status { def, changed, undef };
|
||||
enum class status
|
||||
{
|
||||
def,
|
||||
changed,
|
||||
undef
|
||||
};
|
||||
|
||||
template<class _Type>
|
||||
struct ParamItem
|
||||
|
@ -37,6 +42,7 @@ protected:
|
|||
using _Self = ParamItem<_Type>;
|
||||
status s;
|
||||
_Type value;
|
||||
|
||||
public:
|
||||
ParamItem()
|
||||
{
|
||||
|
@ -47,10 +53,10 @@ public:
|
|||
value = val;
|
||||
s = status::def;
|
||||
}
|
||||
ParamItem(const _Self &item) = default;
|
||||
_Self &operator=(const _Self &item) = default;
|
||||
_Self &
|
||||
operator=(const _Type &val)
|
||||
ParamItem(const _Self& item) = default;
|
||||
_Self& operator=(const _Self& item) = default;
|
||||
_Self&
|
||||
operator=(const _Type& val)
|
||||
{
|
||||
value = val;
|
||||
s = status::changed;
|
||||
|
@ -67,7 +73,7 @@ public:
|
|||
return s;
|
||||
}
|
||||
void
|
||||
print(std::ostream &out, const std::string &prefix, const std::string &str) const
|
||||
print(std::ostream& out, const std::string& prefix, const std::string& str) const
|
||||
{
|
||||
if (s == status::undef)
|
||||
return;
|
||||
|
@ -81,7 +87,11 @@ public:
|
|||
class SylvParams
|
||||
{
|
||||
public:
|
||||
enum class solve_method { iter, recurse };
|
||||
enum class solve_method
|
||||
{
|
||||
iter,
|
||||
recurse
|
||||
};
|
||||
|
||||
protected:
|
||||
class DoubleParamItem : public ParamItem<double>
|
||||
|
@ -93,14 +103,15 @@ protected:
|
|||
DoubleParamItem(double val) : ParamItem<double>(val)
|
||||
{
|
||||
}
|
||||
DoubleParamItem(const DoubleParamItem &item) = default;
|
||||
DoubleParamItem &
|
||||
operator=(const double &val)
|
||||
DoubleParamItem(const DoubleParamItem& item) = default;
|
||||
DoubleParamItem&
|
||||
operator=(const double& val)
|
||||
{
|
||||
ParamItem<double>::operator=(val); return *this;
|
||||
ParamItem<double>::operator=(val);
|
||||
return *this;
|
||||
}
|
||||
#if defined(MATLAB_MEX_FILE) || defined(OCTAVE_MEX_FILE)
|
||||
mxArray *createMatlabArray() const;
|
||||
mxArray* createMatlabArray() const;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -113,14 +124,15 @@ protected:
|
|||
IntParamItem(int val) : ParamItem<int>(val)
|
||||
{
|
||||
}
|
||||
IntParamItem(const IntParamItem &item) = default;
|
||||
IntParamItem &
|
||||
operator=(const int &val)
|
||||
IntParamItem(const IntParamItem& item) = default;
|
||||
IntParamItem&
|
||||
operator=(const int& val)
|
||||
{
|
||||
ParamItem<int>::operator=(val); return *this;
|
||||
ParamItem<int>::operator=(val);
|
||||
return *this;
|
||||
}
|
||||
#if defined(MATLAB_MEX_FILE) || defined(OCTAVE_MEX_FILE)
|
||||
mxArray *createMatlabArray() const;
|
||||
mxArray* createMatlabArray() const;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -133,14 +145,15 @@ protected:
|
|||
BoolParamItem(bool val) : ParamItem<bool>(val)
|
||||
{
|
||||
}
|
||||
BoolParamItem(const BoolParamItem &item) = default;
|
||||
BoolParamItem &
|
||||
operator=(const bool &val)
|
||||
BoolParamItem(const BoolParamItem& item) = default;
|
||||
BoolParamItem&
|
||||
operator=(const bool& val)
|
||||
{
|
||||
ParamItem<bool>::operator=(val); return *this;
|
||||
ParamItem<bool>::operator=(val);
|
||||
return *this;
|
||||
}
|
||||
#if defined(MATLAB_MEX_FILE) || defined(OCTAVE_MEX_FILE)
|
||||
mxArray *createMatlabArray() const;
|
||||
mxArray* createMatlabArray() const;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -153,68 +166,69 @@ protected:
|
|||
MethodParamItem(solve_method val) : ParamItem<solve_method>(val)
|
||||
{
|
||||
}
|
||||
MethodParamItem(const MethodParamItem &item) = default;
|
||||
MethodParamItem(const MethodParamItem& item) = default;
|
||||
MethodParamItem
|
||||
operator=(const solve_method &val)
|
||||
operator=(const solve_method& val)
|
||||
{
|
||||
ParamItem<solve_method>::operator=(val); return *this;
|
||||
ParamItem<solve_method>::operator=(val);
|
||||
return *this;
|
||||
}
|
||||
#if defined(MATLAB_MEX_FILE) || defined(OCTAVE_MEX_FILE)
|
||||
mxArray *createMatlabArray() const;
|
||||
mxArray* createMatlabArray() const;
|
||||
#endif
|
||||
};
|
||||
|
||||
public:
|
||||
// input parameters
|
||||
MethodParamItem method; // method of solution: iter/recurse
|
||||
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 log₁₀ of norm for diagonalization
|
||||
BoolParamItem want_check; // true => allocate extra space for checks
|
||||
IntParamItem max_num_iter; // max number of iterations
|
||||
DoubleParamItem bs_norm; // Bavely Stewart log₁₀ of norm for diagonalization
|
||||
BoolParamItem want_check; // true => allocate extra space for checks
|
||||
// output parameters
|
||||
BoolParamItem converged; // true if converged
|
||||
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·V⁻¹
|
||||
DoubleParamItem f_errI; // norm ∞ of diagonalization abs. error C−V·F·V⁻¹
|
||||
DoubleParamItem viv_err1; // norm 1 of error I−V·V⁻¹
|
||||
DoubleParamItem viv_errI; // norm ∞ of error I−V·V⁻¹
|
||||
DoubleParamItem ivv_err1; // norm 1 of error I−V⁻¹·V
|
||||
DoubleParamItem ivv_errI; // norm ∞ of error I−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 ∞ number of A
|
||||
DoubleParamItem eig_min; // minimum eigenvalue of the solved system
|
||||
DoubleParamItem mat_err1; // rel. matrix 1 norm of A·X−B·X·⊗ⁱC−D
|
||||
DoubleParamItem mat_errI; // rel. matrix ∞ norm of A·X−B·X·⊗ⁱC−D
|
||||
DoubleParamItem mat_errF; // rel. matrix Frob. norm of A·X−B·X·⊗ⁱC−D
|
||||
DoubleParamItem vec_err1; // rel. vector 1 norm of A·X−B·X·⊗ⁱC−D
|
||||
DoubleParamItem vec_errI; // rel. vector ∞ norm of A·X−B·X·⊗ⁱC−D
|
||||
DoubleParamItem cpu_time; // time of the job in CPU seconds
|
||||
IntParamItem num_iter; // number of iterations
|
||||
DoubleParamItem f_err1; // norm 1 of diagonalization abs. error C−V·F·V⁻¹
|
||||
DoubleParamItem f_errI; // norm ∞ of diagonalization abs. error C−V·F·V⁻¹
|
||||
DoubleParamItem viv_err1; // norm 1 of error I−V·V⁻¹
|
||||
DoubleParamItem viv_errI; // norm ∞ of error I−V·V⁻¹
|
||||
DoubleParamItem ivv_err1; // norm 1 of error I−V⁻¹·V
|
||||
DoubleParamItem ivv_errI; // norm ∞ of error I−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 ∞ number of A
|
||||
DoubleParamItem eig_min; // minimum eigenvalue of the solved system
|
||||
DoubleParamItem mat_err1; // rel. matrix 1 norm of A·X−B·X·⊗ⁱC−D
|
||||
DoubleParamItem mat_errI; // rel. matrix ∞ norm of A·X−B·X·⊗ⁱC−D
|
||||
DoubleParamItem mat_errF; // rel. matrix Frob. norm of A·X−B·X·⊗ⁱC−D
|
||||
DoubleParamItem vec_err1; // rel. vector 1 norm of A·X−B·X·⊗ⁱC−D
|
||||
DoubleParamItem vec_errI; // rel. vector ∞ norm of A·X−B·X·⊗ⁱC−D
|
||||
DoubleParamItem cpu_time; // time of the job in CPU seconds
|
||||
|
||||
SylvParams(bool wc = false)
|
||||
: method(solve_method::recurse), convergence_tol(1.e-30), max_num_iter(15),
|
||||
bs_norm(1.3), want_check(wc)
|
||||
SylvParams(bool wc = false) :
|
||||
method(solve_method::recurse), convergence_tol(1.e-30), max_num_iter(15), bs_norm(1.3),
|
||||
want_check(wc)
|
||||
{
|
||||
}
|
||||
SylvParams(const SylvParams &p) = default;
|
||||
SylvParams &operator=(const SylvParams &p) = default;
|
||||
SylvParams(const SylvParams& p) = default;
|
||||
SylvParams& operator=(const SylvParams& p) = default;
|
||||
~SylvParams() = default;
|
||||
void print(const std::string &prefix) const;
|
||||
void print(std::ostream &fdesc, const std::string &prefix) const;
|
||||
void setArrayNames(int &num, const char **names) const;
|
||||
void print(const std::string& prefix) const;
|
||||
void print(std::ostream& fdesc, const std::string& prefix) const;
|
||||
void setArrayNames(int& num, const char** names) const;
|
||||
#if defined(MATLAB_MEX_FILE) || defined(OCTAVE_MEX_FILE)
|
||||
mxArray *createStructArray() const;
|
||||
mxArray* createStructArray() const;
|
||||
#endif
|
||||
private:
|
||||
void copy(const SylvParams &p);
|
||||
void copy(const SylvParams& p);
|
||||
};
|
||||
|
||||
inline std::ostream &
|
||||
operator<<(std::ostream &out, SylvParams::solve_method m)
|
||||
inline std::ostream&
|
||||
operator<<(std::ostream& out, SylvParams::solve_method m)
|
||||
{
|
||||
switch (m)
|
||||
{
|
||||
|
|
|
@ -24,9 +24,9 @@
|
|||
#include "KronVector.hh"
|
||||
#include "QuasiTriangular.hh"
|
||||
#include "QuasiTriangularZero.hh"
|
||||
#include "SchurDecomp.hh"
|
||||
#include "SimilarityDecomp.hh"
|
||||
#include "SylvParams.hh"
|
||||
#include "SchurDecomp.hh"
|
||||
|
||||
#include <memory>
|
||||
|
||||
|
@ -35,37 +35,35 @@ class SylvesterSolver
|
|||
protected:
|
||||
const std::unique_ptr<const QuasiTriangular> matrixK;
|
||||
const std::unique_ptr<const QuasiTriangular> matrixF;
|
||||
|
||||
private:
|
||||
/* Return true when it is more efficient to use QuasiTriangular
|
||||
than QuasiTriangularZero */
|
||||
static bool
|
||||
zeroPad(const SchurDecompZero &kdecomp)
|
||||
zeroPad(const SchurDecompZero& kdecomp)
|
||||
{
|
||||
return ((kdecomp.getZeroCols()*3 < kdecomp.getDim()*2)
|
||||
|| (kdecomp.getZeroCols() < 10));
|
||||
return ((kdecomp.getZeroCols() * 3 < kdecomp.getDim() * 2) || (kdecomp.getZeroCols() < 10));
|
||||
}
|
||||
|
||||
public:
|
||||
SylvesterSolver(const QuasiTriangular &k, const QuasiTriangular &f)
|
||||
: matrixK(std::make_unique<QuasiTriangular>(k)),
|
||||
matrixF(std::make_unique<QuasiTriangular>(f))
|
||||
SylvesterSolver(const QuasiTriangular& k, const QuasiTriangular& f) :
|
||||
matrixK(std::make_unique<QuasiTriangular>(k)), matrixF(std::make_unique<QuasiTriangular>(f))
|
||||
{
|
||||
}
|
||||
SylvesterSolver(const SchurDecompZero &kdecomp, const SchurDecomp &fdecomp)
|
||||
: matrixK((zeroPad(kdecomp)) ?
|
||||
std::make_unique<QuasiTriangular>(kdecomp) :
|
||||
std::make_unique<QuasiTriangularZero>(kdecomp)),
|
||||
SylvesterSolver(const SchurDecompZero& kdecomp, const SchurDecomp& fdecomp) :
|
||||
matrixK((zeroPad(kdecomp)) ? std::make_unique<QuasiTriangular>(kdecomp)
|
||||
: std::make_unique<QuasiTriangularZero>(kdecomp)),
|
||||
matrixF(std::make_unique<QuasiTriangular>(fdecomp))
|
||||
{
|
||||
}
|
||||
SylvesterSolver(const SchurDecompZero &kdecomp, const SimilarityDecomp &fdecomp)
|
||||
: matrixK((zeroPad(kdecomp)) ?
|
||||
std::make_unique<QuasiTriangular>(kdecomp) :
|
||||
std::make_unique<QuasiTriangularZero>(kdecomp)),
|
||||
SylvesterSolver(const SchurDecompZero& kdecomp, const SimilarityDecomp& fdecomp) :
|
||||
matrixK((zeroPad(kdecomp)) ? std::make_unique<QuasiTriangular>(kdecomp)
|
||||
: std::make_unique<QuasiTriangularZero>(kdecomp)),
|
||||
matrixF(std::make_unique<BlockDiagonal>(fdecomp.getB()))
|
||||
{
|
||||
}
|
||||
virtual ~SylvesterSolver() = default;
|
||||
virtual void solve(SylvParams &pars, KronVector &x) const = 0;
|
||||
virtual void solve(SylvParams& pars, KronVector& x) const = 0;
|
||||
};
|
||||
|
||||
#endif /* SYLVESTER_SOLVER_H */
|
||||
|
|
|
@ -27,8 +27,8 @@
|
|||
#include <cmath>
|
||||
#include <memory>
|
||||
|
||||
SymSchurDecomp::SymSchurDecomp(const ConstGeneralMatrix &mata)
|
||||
: lambda(mata.nrows()), q(mata.nrows())
|
||||
SymSchurDecomp::SymSchurDecomp(const ConstGeneralMatrix& mata) :
|
||||
lambda(mata.nrows()), q(mata.nrows())
|
||||
{
|
||||
// check mata is square
|
||||
if (mata.nrows() != mata.ncols())
|
||||
|
@ -37,20 +37,20 @@ SymSchurDecomp::SymSchurDecomp(const ConstGeneralMatrix &mata)
|
|||
// prepare for dsyevr
|
||||
lapack_int n = mata.nrows();
|
||||
GeneralMatrix tmpa(mata);
|
||||
double *a = tmpa.base();
|
||||
double* a = tmpa.base();
|
||||
lapack_int lda = tmpa.getLD();
|
||||
double dum;
|
||||
double *vl = &dum;
|
||||
double *vu = &dum;
|
||||
double* vl = &dum;
|
||||
double* vu = &dum;
|
||||
lapack_int idum;
|
||||
lapack_int *il = &idum;
|
||||
lapack_int *iu = &idum;
|
||||
lapack_int* il = &idum;
|
||||
lapack_int* iu = &idum;
|
||||
double abstol = 0.0;
|
||||
lapack_int m = n;
|
||||
double *w = lambda.base();
|
||||
double *z = q.base();
|
||||
double* w = lambda.base();
|
||||
double* z = q.base();
|
||||
lapack_int ldz = q.getLD();
|
||||
auto isuppz = std::make_unique<lapack_int[]>(2*std::max(1, static_cast<int>(m)));
|
||||
auto isuppz = std::make_unique<lapack_int[]>(2 * std::max(1, static_cast<int>(m)));
|
||||
double tmpwork;
|
||||
lapack_int lwork = -1;
|
||||
lapack_int tmpiwork;
|
||||
|
@ -58,8 +58,8 @@ SymSchurDecomp::SymSchurDecomp(const ConstGeneralMatrix &mata)
|
|||
lapack_int info;
|
||||
|
||||
// query for lwork and liwork
|
||||
dsyevr("V", "A", "U", &n, a, &lda, vl, vu, il, iu, &abstol,
|
||||
&m, w, z, &ldz, isuppz.get(), &tmpwork, &lwork, &tmpiwork, &liwork, &info);
|
||||
dsyevr("V", "A", "U", &n, a, &lda, vl, vu, il, iu, &abstol, &m, w, z, &ldz, isuppz.get(),
|
||||
&tmpwork, &lwork, &tmpiwork, &liwork, &info);
|
||||
lwork = static_cast<lapack_int>(tmpwork);
|
||||
liwork = tmpiwork;
|
||||
// allocate work arrays
|
||||
|
@ -67,8 +67,8 @@ SymSchurDecomp::SymSchurDecomp(const ConstGeneralMatrix &mata)
|
|||
auto iwork = std::make_unique<lapack_int[]>(liwork);
|
||||
|
||||
// do the calculation
|
||||
dsyevr("V", "A", "U", &n, a, &lda, vl, vu, il, iu, &abstol,
|
||||
&m, w, z, &ldz, isuppz.get(), work.get(), &lwork, iwork.get(), &liwork, &info);
|
||||
dsyevr("V", "A", "U", &n, a, &lda, vl, vu, il, iu, &abstol, &m, w, z, &ldz, isuppz.get(),
|
||||
work.get(), &lwork, iwork.get(), &liwork, &info);
|
||||
|
||||
if (info < 0)
|
||||
throw SYLV_MES_EXCEPTION("Internal error in SymSchurDecomp constructor");
|
||||
|
@ -77,19 +77,20 @@ SymSchurDecomp::SymSchurDecomp(const ConstGeneralMatrix &mata)
|
|||
}
|
||||
|
||||
void
|
||||
SymSchurDecomp::getFactor(GeneralMatrix &f) const
|
||||
SymSchurDecomp::getFactor(GeneralMatrix& f) const
|
||||
{
|
||||
if (f.nrows() != q.nrows())
|
||||
throw SYLV_MES_EXCEPTION("Wrong dimension of factor matrix in SymSchurDecomp::getFactor");
|
||||
if (f.nrows() != f.ncols())
|
||||
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");
|
||||
throw SYLV_MES_EXCEPTION(
|
||||
"Symmetric decomposition not positive semidefinite in SymSchurDecomp::getFactor");
|
||||
|
||||
f = q;
|
||||
for (int i = 0; i < f.ncols(); i++)
|
||||
{
|
||||
Vector fi{f.getCol(i)};
|
||||
Vector fi {f.getCol(i)};
|
||||
fi.mult(std::sqrt(lambda[i]));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,25 +28,26 @@ class SymSchurDecomp
|
|||
protected:
|
||||
Vector lambda;
|
||||
SqSylvMatrix q;
|
||||
|
||||
public:
|
||||
/* Computes the factorization A = Q·Λ·Qᵀ, where A is assummed to be
|
||||
symmetric and Λ real diagonal, hence a vector. */
|
||||
SymSchurDecomp(const ConstGeneralMatrix &a);
|
||||
SymSchurDecomp(const SymSchurDecomp &ssd) = default;
|
||||
SymSchurDecomp(const ConstGeneralMatrix& a);
|
||||
SymSchurDecomp(const SymSchurDecomp& ssd) = default;
|
||||
virtual ~SymSchurDecomp() = default;
|
||||
const Vector &
|
||||
const Vector&
|
||||
getLambda() const
|
||||
{
|
||||
return lambda;
|
||||
}
|
||||
const SqSylvMatrix &
|
||||
const SqSylvMatrix&
|
||||
getQ() const
|
||||
{
|
||||
return q;
|
||||
}
|
||||
/* Return factor F·Fᵀ = A, raises and exception if A is not
|
||||
positive semidefinite, F must be square. */
|
||||
void getFactor(GeneralMatrix &f) const;
|
||||
void getFactor(GeneralMatrix& f) const;
|
||||
// Returns true if A is positive semidefinite.
|
||||
bool isPositiveSemidefinite() const;
|
||||
/* Correct definitness. This sets all eigenvalues between minus
|
||||
|
|
|
@ -19,34 +19,29 @@
|
|||
*/
|
||||
|
||||
#include "TriangularSylvester.hh"
|
||||
#include "QuasiTriangularZero.hh"
|
||||
#include "KronUtils.hh"
|
||||
#include "BlockDiagonal.hh"
|
||||
#include "KronUtils.hh"
|
||||
#include "QuasiTriangularZero.hh"
|
||||
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
|
||||
TriangularSylvester::TriangularSylvester(const QuasiTriangular &k,
|
||||
const QuasiTriangular &f)
|
||||
: SylvesterSolver(k, f),
|
||||
matrixKK{matrixK->square()},
|
||||
matrixFF{matrixF->square()}
|
||||
TriangularSylvester::TriangularSylvester(const QuasiTriangular& k, const QuasiTriangular& f) :
|
||||
SylvesterSolver(k, f), matrixKK {matrixK->square()}, matrixFF {matrixF->square()}
|
||||
{
|
||||
}
|
||||
|
||||
TriangularSylvester::TriangularSylvester(const SchurDecompZero &kdecomp,
|
||||
const SchurDecomp &fdecomp)
|
||||
: SylvesterSolver(kdecomp, fdecomp),
|
||||
matrixKK{matrixK->square()},
|
||||
matrixFF{matrixF->square()}
|
||||
TriangularSylvester::TriangularSylvester(const SchurDecompZero& kdecomp,
|
||||
const SchurDecomp& fdecomp) :
|
||||
SylvesterSolver(kdecomp, fdecomp),
|
||||
matrixKK {matrixK->square()}, matrixFF {matrixF->square()}
|
||||
{
|
||||
}
|
||||
|
||||
TriangularSylvester::TriangularSylvester(const SchurDecompZero &kdecomp,
|
||||
const SimilarityDecomp &fdecomp)
|
||||
: SylvesterSolver(kdecomp, fdecomp),
|
||||
matrixKK{matrixK->square()},
|
||||
matrixFF{matrixF->square()}
|
||||
TriangularSylvester::TriangularSylvester(const SchurDecompZero& kdecomp,
|
||||
const SimilarityDecomp& fdecomp) :
|
||||
SylvesterSolver(kdecomp, fdecomp),
|
||||
matrixKK {matrixK->square()}, matrixFF {matrixF->square()}
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -60,7 +55,7 @@ TriangularSylvester::print() const
|
|||
}
|
||||
|
||||
void
|
||||
TriangularSylvester::solve(SylvParams &pars, KronVector &d) const
|
||||
TriangularSylvester::solve(SylvParams& pars, KronVector& d) const
|
||||
{
|
||||
double eig_min = 1e30;
|
||||
solvi(1., d, eig_min);
|
||||
|
@ -68,7 +63,7 @@ TriangularSylvester::solve(SylvParams &pars, KronVector &d) const
|
|||
}
|
||||
|
||||
void
|
||||
TriangularSylvester::solvi(double r, KronVector &d, double &eig_min) const
|
||||
TriangularSylvester::solvi(double r, KronVector& d, double& eig_min) const
|
||||
{
|
||||
if (d.getDepth() == 0)
|
||||
{
|
||||
|
@ -77,9 +72,7 @@ TriangularSylvester::solvi(double r, KronVector &d, double &eig_min) const
|
|||
}
|
||||
else
|
||||
{
|
||||
for (const_diag_iter di = matrixF->diag_begin();
|
||||
di != matrixF->diag_end();
|
||||
++di)
|
||||
for (const_diag_iter di = matrixF->diag_begin(); di != matrixF->diag_end(); ++di)
|
||||
if (di->isReal())
|
||||
solviRealAndEliminate(r, di, d, eig_min);
|
||||
else
|
||||
|
@ -88,20 +81,18 @@ TriangularSylvester::solvi(double r, KronVector &d, double &eig_min) const
|
|||
}
|
||||
|
||||
void
|
||||
TriangularSylvester::solvii(double alpha, double beta1, double beta2,
|
||||
KronVector &d1, KronVector &d2,
|
||||
double &eig_min) const
|
||||
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);
|
||||
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
|
||||
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)
|
||||
|
@ -113,8 +104,8 @@ TriangularSylvester::solviip(double alpha, double betas,
|
|||
|
||||
if (d.getDepth() == 0)
|
||||
{
|
||||
double aspbs = alpha*alpha+betas;
|
||||
auto t = matrixK->linearlyCombine(2*alpha, aspbs, *matrixKK);
|
||||
double aspbs = alpha * alpha + betas;
|
||||
auto t = matrixK->linearlyCombine(2 * alpha, aspbs, *matrixKK);
|
||||
t->solvePre(d, eig_min);
|
||||
}
|
||||
else
|
||||
|
@ -130,18 +121,18 @@ TriangularSylvester::solviip(double alpha, double betas,
|
|||
}
|
||||
|
||||
void
|
||||
TriangularSylvester::solviRealAndEliminate(double r, const_diag_iter di,
|
||||
KronVector &d, double &eig_min) const
|
||||
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 (std::abs(r*f) > diag_zero)
|
||||
solvi(r*f, dj, eig_min);
|
||||
if (std::abs(r * f) > diag_zero)
|
||||
solvi(r * f, dj, eig_min);
|
||||
// calculate y
|
||||
KronVector y(const_cast<const KronVector &>(dj));
|
||||
KronVector y(const_cast<const KronVector&>(dj));
|
||||
KronUtils::multKron(*matrixF, *matrixK, y);
|
||||
y.mult(r);
|
||||
double divisor = 1.0;
|
||||
|
@ -149,20 +140,19 @@ TriangularSylvester::solviRealAndEliminate(double r, const_diag_iter di,
|
|||
}
|
||||
|
||||
void
|
||||
TriangularSylvester::solviEliminateReal(const_diag_iter di, KronVector &d,
|
||||
const KronVector &y, double divisor) const
|
||||
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)
|
||||
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);
|
||||
dk.add(-(*ri) / divisor, y);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TriangularSylvester::solviComplexAndEliminate(double r, const_diag_iter di,
|
||||
KronVector &d, double &eig_min) const
|
||||
TriangularSylvester::solviComplexAndEliminate(double r, const_diag_iter di, KronVector& d,
|
||||
double& eig_min) const
|
||||
{
|
||||
// di is complex
|
||||
int jbar = di->getIndex();
|
||||
|
@ -172,10 +162,10 @@ TriangularSylvester::solviComplexAndEliminate(double r, const_diag_iter di,
|
|||
double beta2 = -di->getBeta1();
|
||||
double aspbs = di->getDeterminant();
|
||||
KronVector dj(d, jbar);
|
||||
KronVector djj(d, jbar+1);
|
||||
KronVector djj(d, jbar + 1);
|
||||
// solve
|
||||
if (r*r*aspbs > diag_zero_sq)
|
||||
solvii(r*alpha, r*beta1, r*beta2, dj, djj, eig_min);
|
||||
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);
|
||||
|
@ -187,38 +177,36 @@ TriangularSylvester::solviComplexAndEliminate(double r, const_diag_iter di,
|
|||
}
|
||||
|
||||
void
|
||||
TriangularSylvester::solviEliminateComplex(const_diag_iter di, KronVector &d,
|
||||
const KronVector &y1, const KronVector &y2,
|
||||
double divisor) const
|
||||
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)
|
||||
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);
|
||||
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
|
||||
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;
|
||||
double aspbs = alpha * alpha + betas;
|
||||
// pick data
|
||||
double f = *(di->getAlpha());
|
||||
double fs = f*f;
|
||||
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_cast<const KronVector &>(dj));
|
||||
KronVector y2(const_cast<const KronVector &>(dj));
|
||||
if (fs * aspbs > diag_zero_sq)
|
||||
solviip(f * alpha, fs * betas, dj, eig_min);
|
||||
KronVector y1(const_cast<const KronVector&>(dj));
|
||||
KronVector y2(const_cast<const KronVector&>(dj));
|
||||
KronUtils::multKron(*matrixF, *matrixK, y1);
|
||||
y1.mult(2*alpha);
|
||||
y1.mult(2 * alpha);
|
||||
KronUtils::multKron(*matrixFF, *matrixKK, y2);
|
||||
y2.mult(aspbs);
|
||||
double divisor = 1.0;
|
||||
|
@ -227,9 +215,8 @@ TriangularSylvester::solviipRealAndEliminate(double alpha, double betas,
|
|||
}
|
||||
|
||||
void
|
||||
TriangularSylvester::solviipEliminateReal(const_diag_iter di, const_diag_iter dsi,
|
||||
KronVector &d,
|
||||
const KronVector &y1, const KronVector &y2,
|
||||
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);
|
||||
|
@ -237,43 +224,43 @@ TriangularSylvester::solviipEliminateReal(const_diag_iter di, const_diag_iter ds
|
|||
for (; ri != matrixF->row_end(*di); ++ri, ++rsi)
|
||||
{
|
||||
KronVector dk(d, ri.getCol());
|
||||
dk.add(-(*ri)/divisor, y1);
|
||||
dk.add(-(*rsi)/divisor2, y2);
|
||||
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
|
||||
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;
|
||||
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)
|
||||
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_cast<const KronVector &>(dj));
|
||||
KronVector y1(const_cast<const KronVector&>(dj));
|
||||
KronUtils::multKron(*matrixF, *matrixK, y1);
|
||||
y1.mult(2*alpha);
|
||||
y1.mult(2 * alpha);
|
||||
// y11
|
||||
KronVector y11(const_cast<const KronVector &>(djj));
|
||||
KronVector y11(const_cast<const KronVector&>(djj));
|
||||
KronUtils::multKron(*matrixF, *matrixK, y11);
|
||||
y11.mult(2*alpha);
|
||||
y11.mult(2 * alpha);
|
||||
// y2
|
||||
KronVector y2(const_cast<const KronVector &>(dj));
|
||||
KronVector y2(const_cast<const KronVector&>(dj));
|
||||
KronUtils::multKron(*matrixFF, *matrixKK, y2);
|
||||
y2.mult(aspbs);
|
||||
// y22
|
||||
KronVector y22(const_cast<const KronVector &>(djj));
|
||||
KronVector y22(const_cast<const KronVector&>(djj));
|
||||
KronUtils::multKron(*matrixFF, *matrixKK, y22);
|
||||
y22.mult(aspbs);
|
||||
|
||||
|
@ -282,32 +269,29 @@ TriangularSylvester::solviipComplexAndEliminate(double alpha, double betas,
|
|||
}
|
||||
|
||||
void
|
||||
TriangularSylvester::solviipComplex(double alpha, double betas, double gamma,
|
||||
double delta1, double delta2,
|
||||
KronVector &d1, KronVector &d2,
|
||||
double &eig_min) const
|
||||
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 = std::sqrt(delta1*delta2);
|
||||
quaEval(alpha, betas, gamma, delta1, delta2, d1, d2, d1tmp, d2tmp);
|
||||
double delta = std::sqrt(delta1 * delta2);
|
||||
double beta = std::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);
|
||||
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,
|
||||
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);
|
||||
|
@ -315,17 +299,17 @@ TriangularSylvester::solviipEliminateComplex(const_diag_iter di, const_diag_iter
|
|||
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);
|
||||
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
|
||||
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
|
||||
|
@ -337,10 +321,9 @@ TriangularSylvester::linEval(double alpha, double beta1, double beta2,
|
|||
}
|
||||
|
||||
void
|
||||
TriangularSylvester::quaEval(double alpha, double betas,
|
||||
double gamma, double delta1, double delta2,
|
||||
KronVector &x1, KronVector &x2,
|
||||
const ConstKronVector &d1, const ConstKronVector &d2) const
|
||||
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
|
||||
|
@ -348,37 +331,36 @@ TriangularSylvester::quaEval(double alpha, double betas,
|
|||
KronUtils::multKron(*matrixF, *matrixK, d2tmp);
|
||||
x1 = d1;
|
||||
x2 = d2;
|
||||
Vector::mult2a(2*alpha*gamma, 2*alpha*delta1, -2*alpha*delta2,
|
||||
x1, x2, d1tmp, d2tmp);
|
||||
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 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);
|
||||
Vector feig(2 * f_size);
|
||||
matrixF->getDiagonal().getEigenValues(feig);
|
||||
int k_size = matrixK->getDiagonal().getSize();
|
||||
Vector keig(2*k_size);
|
||||
Vector keig(2 * k_size);
|
||||
matrixK->getDiagonal().getEigenValues(keig);
|
||||
|
||||
KronVector eig(f_size, 2*k_size, depth);
|
||||
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++)
|
||||
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;
|
||||
double alpha = eig[2 * i];
|
||||
double beta = eig[2 * i + 1];
|
||||
double ss = (alpha + 1) * (alpha + 1) + beta * beta;
|
||||
min = std::min(min, ss);
|
||||
}
|
||||
|
||||
|
@ -386,8 +368,7 @@ TriangularSylvester::getEigSep(int depth) const
|
|||
}
|
||||
|
||||
void
|
||||
TriangularSylvester::multEigVector(KronVector &eig, const Vector &feig,
|
||||
const Vector &keig)
|
||||
TriangularSylvester::multEigVector(KronVector& eig, const Vector& feig, const Vector& keig)
|
||||
{
|
||||
int depth = eig.getDepth();
|
||||
int m = eig.getM();
|
||||
|
@ -397,13 +378,13 @@ TriangularSylvester::multEigVector(KronVector &eig, const Vector &feig,
|
|||
eig = keig;
|
||||
else
|
||||
{
|
||||
KronVector aux(m, n, depth-1);
|
||||
KronVector aux(m, n, depth - 1);
|
||||
multEigVector(aux, feig, keig);
|
||||
for (int i = 0; i < m; i++)
|
||||
{
|
||||
KronVector eigi(eig, i);
|
||||
eigi.zeros();
|
||||
eigi.addComplex({ feig[2*i], feig[2*i+1] }, aux);
|
||||
eigi.addComplex({feig[2 * i], feig[2 * i + 1]}, aux);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,11 +21,11 @@
|
|||
#ifndef TRIANGULAR_SYLVESTER_H
|
||||
#define TRIANGULAR_SYLVESTER_H
|
||||
|
||||
#include "SylvesterSolver.hh"
|
||||
#include "KronVector.hh"
|
||||
#include "QuasiTriangular.hh"
|
||||
#include "QuasiTriangularZero.hh"
|
||||
#include "SimilarityDecomp.hh"
|
||||
#include "SylvesterSolver.hh"
|
||||
|
||||
#include <memory>
|
||||
|
||||
|
@ -33,36 +33,32 @@ class TriangularSylvester : public SylvesterSolver
|
|||
{
|
||||
const std::unique_ptr<const QuasiTriangular> matrixKK;
|
||||
const std::unique_ptr<const QuasiTriangular> matrixFF;
|
||||
|
||||
public:
|
||||
TriangularSylvester(const QuasiTriangular &k, const QuasiTriangular &f);
|
||||
TriangularSylvester(const SchurDecompZero &kdecomp, const SchurDecomp &fdecomp);
|
||||
TriangularSylvester(const SchurDecompZero &kdecomp, const SimilarityDecomp &fdecomp);
|
||||
TriangularSylvester(const QuasiTriangular& k, const QuasiTriangular& f);
|
||||
TriangularSylvester(const SchurDecompZero& kdecomp, const SchurDecomp& fdecomp);
|
||||
TriangularSylvester(const SchurDecompZero& kdecomp, const SimilarityDecomp& fdecomp);
|
||||
|
||||
~TriangularSylvester() override = default;
|
||||
void print() const;
|
||||
void solve(SylvParams &pars, KronVector &d) const override;
|
||||
void solve(SylvParams& pars, KronVector& d) const override;
|
||||
|
||||
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;
|
||||
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;
|
||||
/* Computes:
|
||||
⎛x₁⎞ ⎛d₁⎞ ⎛ α −β₁⎞ ⎛d₁⎞
|
||||
⎢ ⎥=⎢ ⎥+⎢ ⎥⊗Fᵀ⊗Fᵀ⊗…⊗K·⎢ ⎥
|
||||
⎝x₂⎠ ⎝d₂⎠ ⎝−β₂ α ⎠ ⎝d₂⎠
|
||||
*/
|
||||
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 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(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));
|
||||
linEval(alpha, beta1, beta2, x1, x2, ConstKronVector(d1), ConstKronVector(d2));
|
||||
}
|
||||
|
||||
/* Computes:
|
||||
|
@ -70,64 +66,51 @@ public:
|
|||
⎢ ⎥=⎢ ⎥+2α⎢ ⎥⊗Fᵀ⊗Fᵀ⊗…⊗K·⎢ ⎥+(α²+β)⎢ ⎥ ⊗Fᵀ²⊗Fᵀ²⊗…⊗K²·⎢ ⎥
|
||||
⎝x₂⎠ ⎝d₂⎠ ⎝δ₂ γ ⎠ ⎝d₂⎠ ⎝δ₂ γ ⎠ ⎝d₂⎠
|
||||
*/
|
||||
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 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(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));
|
||||
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;
|
||||
// Recursively calculates kronecker product of complex vectors (used in getEigSep)
|
||||
static void multEigVector(KronVector &eig, const Vector &feig, const Vector &keig);
|
||||
static void multEigVector(KronVector& eig, const Vector& feig, const Vector& keig);
|
||||
|
||||
using const_diag_iter = QuasiTriangular::const_diag_iter;
|
||||
using const_row_iter = QuasiTriangular::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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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 constexpr double diag_zero = 1.e-15;
|
||||
static constexpr double diag_zero_sq = diag_zero*diag_zero;
|
||||
static constexpr double diag_zero_sq = diag_zero * diag_zero;
|
||||
};
|
||||
|
||||
#endif /* TRIANGULAR_SYLVESTER_H */
|
||||
|
|
|
@ -24,26 +24,24 @@
|
|||
|
||||
#include <dynblas.h>
|
||||
|
||||
#include <cmath>
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
|
||||
Vector::Vector(const Vector &v)
|
||||
: len(v.len), data{new double[len]}
|
||||
Vector::Vector(const Vector& v) : len(v.len), data {new double[len]}
|
||||
{
|
||||
copy(v.data, v.s);
|
||||
}
|
||||
|
||||
Vector::Vector(const ConstVector &v)
|
||||
: len(v.len), data{new double[len]}
|
||||
Vector::Vector(const ConstVector& v) : len(v.len), data {new double[len]}
|
||||
{
|
||||
copy(v.data, v.s);
|
||||
}
|
||||
|
||||
Vector &
|
||||
Vector::operator=(const Vector &v)
|
||||
Vector&
|
||||
Vector::operator=(const Vector& v)
|
||||
{
|
||||
if (this == &v)
|
||||
return *this;
|
||||
|
@ -52,24 +50,24 @@ Vector::operator=(const Vector &v)
|
|||
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)
|
||||
&& ((data <= v.data && v.data < data + len * s)
|
||||
|| (v.data <= data && data < v.data + v.len * v.s))
|
||||
&& (data - v.data) % s == 0)
|
||||
throw SYLV_MES_EXCEPTION("Attempt to assign overlapping vectors.");
|
||||
|
||||
copy(v.data, v.s);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Vector &
|
||||
Vector::operator=(const ConstVector &v)
|
||||
Vector&
|
||||
Vector::operator=(const ConstVector& v)
|
||||
{
|
||||
if (v.len != len)
|
||||
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)
|
||||
&& ((data <= v.data && v.data < data + len * s)
|
||||
|| (v.data <= data && data < v.data + v.len * v.s))
|
||||
&& (data - v.data) % s == 0)
|
||||
throw SYLV_MES_EXCEPTION("Attempt to assign overlapping vectors.");
|
||||
|
||||
copy(v.data, v.s);
|
||||
|
@ -77,7 +75,7 @@ Vector::operator=(const ConstVector &v)
|
|||
}
|
||||
|
||||
void
|
||||
Vector::copy(const double *d, int inc)
|
||||
Vector::copy(const double* d, int inc)
|
||||
{
|
||||
blas_int n = len;
|
||||
blas_int incy = s;
|
||||
|
@ -85,36 +83,33 @@ Vector::copy(const double *d, int inc)
|
|||
dcopy(&n, d, &inc2, data, &incy);
|
||||
}
|
||||
|
||||
Vector::Vector(Vector &v, int off_arg, int l)
|
||||
: len(l), s(v.s), data{v.data+off_arg*v.s}, destroy{false}
|
||||
Vector::Vector(Vector& v, int off_arg, int l) :
|
||||
len(l), s(v.s), data {v.data + off_arg * v.s}, destroy {false}
|
||||
{
|
||||
if (off_arg < 0 || off_arg + len > v.len)
|
||||
throw SYLV_MES_EXCEPTION("Subvector not contained in supvector.");
|
||||
}
|
||||
|
||||
Vector::Vector(const Vector &v, int off_arg, int l)
|
||||
: len(l), data{new double[len]}
|
||||
Vector::Vector(const Vector& v, int off_arg, int l) : len(l), data {new double[len]}
|
||||
{
|
||||
if (off_arg < 0 || off_arg + len > v.len)
|
||||
throw SYLV_MES_EXCEPTION("Subvector not contained in supvector.");
|
||||
copy(v.data+off_arg*v.s, v.s);
|
||||
copy(v.data + off_arg * v.s, v.s);
|
||||
}
|
||||
|
||||
Vector::Vector(Vector &v, int off_arg, int skip, int l)
|
||||
: len(l), s(v.s*skip), data{v.data+off_arg*v.s}, destroy{false}
|
||||
Vector::Vector(Vector& v, int off_arg, int skip, int l) :
|
||||
len(l), s(v.s * skip), data {v.data + off_arg * v.s}, destroy {false}
|
||||
{
|
||||
}
|
||||
|
||||
Vector::Vector(const Vector &v, int off_arg, int skip, int l)
|
||||
: len(l), data{new double[len]}
|
||||
Vector::Vector(const Vector& v, int off_arg, int skip, int l) : len(l), data {new double[len]}
|
||||
{
|
||||
copy(v.data+off_arg*v.s, v.s*skip);
|
||||
copy(v.data + off_arg * v.s, v.s * skip);
|
||||
}
|
||||
|
||||
#if defined(MATLAB_MEX_FILE) || defined(OCTAVE_MEX_FILE)
|
||||
Vector::Vector(mxArray *p)
|
||||
: len{static_cast<int>(mxGetNumberOfElements(p))},
|
||||
data{mxGetPr(p)}, destroy{false}
|
||||
Vector::Vector(mxArray* p) :
|
||||
len {static_cast<int>(mxGetNumberOfElements(p))}, data {mxGetPr(p)}, destroy {false}
|
||||
{
|
||||
if (!mxIsDouble(p) || mxIsComplex(p) || mxIsSparse(p))
|
||||
throw SYLV_MES_EXCEPTION("This is not a dense array of real doubles.");
|
||||
|
@ -122,37 +117,37 @@ Vector::Vector(mxArray *p)
|
|||
#endif
|
||||
|
||||
bool
|
||||
Vector::operator==(const Vector &y) const
|
||||
Vector::operator==(const Vector& y) const
|
||||
{
|
||||
return ConstVector(*this) == y;
|
||||
}
|
||||
|
||||
bool
|
||||
Vector::operator!=(const Vector &y) const
|
||||
Vector::operator!=(const Vector& y) const
|
||||
{
|
||||
return ConstVector(*this) != y;
|
||||
}
|
||||
|
||||
bool
|
||||
Vector::operator<(const Vector &y) const
|
||||
Vector::operator<(const Vector& y) const
|
||||
{
|
||||
return ConstVector(*this) < y;
|
||||
}
|
||||
|
||||
bool
|
||||
Vector::operator<=(const Vector &y) const
|
||||
Vector::operator<=(const Vector& y) const
|
||||
{
|
||||
return ConstVector(*this) <= y;
|
||||
}
|
||||
|
||||
bool
|
||||
Vector::operator>(const Vector &y) const
|
||||
Vector::operator>(const Vector& y) const
|
||||
{
|
||||
return ConstVector(*this) > y;
|
||||
}
|
||||
|
||||
bool
|
||||
Vector::operator>=(const Vector &y) const
|
||||
Vector::operator>=(const Vector& y) const
|
||||
{
|
||||
return ConstVector(*this) >= y;
|
||||
}
|
||||
|
@ -184,19 +179,19 @@ Vector::infs()
|
|||
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);
|
||||
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)
|
||||
Vector::add(double r, const Vector& v)
|
||||
{
|
||||
add(r, ConstVector(v));
|
||||
}
|
||||
|
||||
void
|
||||
Vector::add(double r, const ConstVector &v)
|
||||
Vector::add(double r, const ConstVector& v)
|
||||
{
|
||||
blas_int n = len;
|
||||
blas_int incx = v.s;
|
||||
|
@ -205,15 +200,15 @@ Vector::add(double r, const ConstVector &v)
|
|||
}
|
||||
|
||||
void
|
||||
Vector::addComplex(const std::complex<double> &z, const Vector &v)
|
||||
Vector::addComplex(const std::complex<double>& z, const Vector& v)
|
||||
{
|
||||
addComplex(z, ConstVector(v));
|
||||
}
|
||||
|
||||
void
|
||||
Vector::addComplex(const std::complex<double> &z, const ConstVector &v)
|
||||
Vector::addComplex(const std::complex<double>& z, const ConstVector& v)
|
||||
{
|
||||
blas_int n = len/2;
|
||||
blas_int n = len / 2;
|
||||
blas_int incx = v.s;
|
||||
blas_int incy = s;
|
||||
zaxpy(&n, reinterpret_cast<const double(&)[2]>(z), v.data, &incx, data, &incy);
|
||||
|
@ -228,9 +223,8 @@ Vector::mult(double r)
|
|||
}
|
||||
|
||||
void
|
||||
Vector::mult2(double alpha, double beta1, double beta2,
|
||||
Vector &x1, Vector &x2,
|
||||
const Vector &b1, const Vector &b2)
|
||||
Vector::mult2(double alpha, double beta1, double beta2, Vector& x1, Vector& x2, const Vector& b1,
|
||||
const Vector& b2)
|
||||
{
|
||||
x1.zeros();
|
||||
x2.zeros();
|
||||
|
@ -238,9 +232,8 @@ Vector::mult2(double alpha, double beta1, double beta2,
|
|||
}
|
||||
|
||||
void
|
||||
Vector::mult2a(double alpha, double beta1, double beta2,
|
||||
Vector &x1, Vector &x2,
|
||||
const Vector &b1, const Vector &b2)
|
||||
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);
|
||||
|
@ -270,7 +263,7 @@ Vector::getNorm1() const
|
|||
}
|
||||
|
||||
double
|
||||
Vector::dot(const Vector &y) const
|
||||
Vector::dot(const Vector& y) const
|
||||
{
|
||||
return ConstVector(*this).dot(ConstVector(y));
|
||||
}
|
||||
|
@ -291,32 +284,29 @@ Vector::print() const
|
|||
std::cout.flags(ff);
|
||||
}
|
||||
|
||||
ConstVector::ConstVector(const Vector &v)
|
||||
: len{v.len}, s{v.s}, data{v.data}
|
||||
ConstVector::ConstVector(const Vector& v) : len {v.len}, s {v.s}, data {v.data}
|
||||
{
|
||||
}
|
||||
|
||||
ConstVector::ConstVector(const ConstVector &v, int off_arg, int l)
|
||||
: len{l}, s{v.s}, data{v.data+off_arg*v.s}
|
||||
ConstVector::ConstVector(const ConstVector& v, int off_arg, int l) :
|
||||
len {l}, s {v.s}, data {v.data + off_arg * v.s}
|
||||
{
|
||||
if (off_arg < 0 || off_arg + len > v.len)
|
||||
throw SYLV_MES_EXCEPTION("Subvector not contained in supvector.");
|
||||
}
|
||||
|
||||
ConstVector::ConstVector(const ConstVector &v, int off_arg, int skip, int l)
|
||||
: len(l), s{v.s*skip}, data{v.data+off_arg*v.s}
|
||||
ConstVector::ConstVector(const ConstVector& v, int off_arg, int skip, int l) :
|
||||
len(l), s {v.s * skip}, data {v.data + off_arg * v.s}
|
||||
{
|
||||
}
|
||||
|
||||
ConstVector::ConstVector(const double *d, int skip, int l)
|
||||
: len{l}, s{skip}, data{d}
|
||||
ConstVector::ConstVector(const double* d, int skip, int l) : len {l}, s {skip}, data {d}
|
||||
{
|
||||
}
|
||||
|
||||
#if defined(MATLAB_MEX_FILE) || defined(OCTAVE_MEX_FILE)
|
||||
ConstVector::ConstVector(const mxArray *p)
|
||||
: len{static_cast<int>(mxGetNumberOfElements(p))},
|
||||
data{mxGetPr(p)}
|
||||
ConstVector::ConstVector(const mxArray* p) :
|
||||
len {static_cast<int>(mxGetNumberOfElements(p))}, data {mxGetPr(p)}
|
||||
{
|
||||
if (!mxIsDouble(p))
|
||||
throw SYLV_MES_EXCEPTION("This is not a MATLAB array of doubles.");
|
||||
|
@ -324,7 +314,7 @@ ConstVector::ConstVector(const mxArray *p)
|
|||
#endif
|
||||
|
||||
bool
|
||||
ConstVector::operator==(const ConstVector &y) const
|
||||
ConstVector::operator==(const ConstVector& y) const
|
||||
{
|
||||
if (len != y.len)
|
||||
return false;
|
||||
|
@ -337,7 +327,7 @@ ConstVector::operator==(const ConstVector &y) const
|
|||
}
|
||||
|
||||
bool
|
||||
ConstVector::operator<(const ConstVector &y) const
|
||||
ConstVector::operator<(const ConstVector& y) const
|
||||
{
|
||||
int i = std::min(len, y.len);
|
||||
int ii = 0;
|
||||
|
@ -354,7 +344,7 @@ ConstVector::getNorm() const
|
|||
{
|
||||
double s = 0;
|
||||
for (int i = 0; i < len; i++)
|
||||
s += operator[](i)*operator[](i);
|
||||
s += operator[](i) * operator[](i);
|
||||
return sqrt(s);
|
||||
}
|
||||
|
||||
|
@ -377,7 +367,7 @@ ConstVector::getNorm1() const
|
|||
}
|
||||
|
||||
double
|
||||
ConstVector::dot(const ConstVector &y) const
|
||||
ConstVector::dot(const ConstVector& y) const
|
||||
{
|
||||
if (len != y.len)
|
||||
throw SYLV_MES_EXCEPTION("Vector has different length in ConstVector::dot.");
|
||||
|
|
|
@ -38,62 +38,63 @@ class ConstVector;
|
|||
class Vector
|
||||
{
|
||||
friend class ConstVector;
|
||||
|
||||
protected:
|
||||
int len{0};
|
||||
int s{1}; // stride (also called “skip” in some places)
|
||||
double *data;
|
||||
bool destroy{true};
|
||||
int len {0};
|
||||
int s {1}; // stride (also called “skip” in some places)
|
||||
double* data;
|
||||
bool destroy {true};
|
||||
|
||||
public:
|
||||
Vector() : data{nullptr}, destroy{false}
|
||||
Vector() : data {nullptr}, destroy {false}
|
||||
{
|
||||
}
|
||||
Vector(int l) : len{l}, data{new double[l]}
|
||||
Vector(int l) : len {l}, data {new double[l]}
|
||||
{
|
||||
}
|
||||
Vector(Vector &v) : len{v.len}, s{v.s}, data{v.data}, destroy{false}
|
||||
Vector(Vector& v) : len {v.len}, s {v.s}, data {v.data}, destroy {false}
|
||||
{
|
||||
}
|
||||
Vector(const Vector &v);
|
||||
Vector(Vector &&v) : len{std::exchange(v.len, 0)}, s{v.s},
|
||||
data{std::exchange(v.data, nullptr)},
|
||||
destroy{std::exchange(v.destroy, false)}
|
||||
Vector(const Vector& v);
|
||||
Vector(Vector&& v) :
|
||||
len {std::exchange(v.len, 0)}, s {v.s}, data {std::exchange(v.data, nullptr)},
|
||||
destroy {std::exchange(v.destroy, false)}
|
||||
{
|
||||
}
|
||||
// We don't want implict conversion from ConstVector, since it’s expensive
|
||||
explicit Vector(const ConstVector &v);
|
||||
Vector(double *d, int l)
|
||||
: len(l), data{d}, destroy{false}
|
||||
explicit Vector(const ConstVector& v);
|
||||
Vector(double* d, int l) : len(l), data {d}, destroy {false}
|
||||
{
|
||||
}
|
||||
Vector(Vector &v, int off_arg, int l);
|
||||
Vector(const Vector &v, int off_arg, int l);
|
||||
Vector(Vector &v, int off_arg, int skip, int l);
|
||||
Vector(const Vector &v, int off_arg, int skip, int l);
|
||||
Vector(Vector& v, int off_arg, int l);
|
||||
Vector(const Vector& v, int off_arg, int l);
|
||||
Vector(Vector& v, int off_arg, int skip, int l);
|
||||
Vector(const Vector& v, int off_arg, int skip, int l);
|
||||
#if defined(MATLAB_MEX_FILE) || defined(OCTAVE_MEX_FILE)
|
||||
explicit Vector(mxArray *p);
|
||||
explicit Vector(mxArray* p);
|
||||
#endif
|
||||
Vector &operator=(const Vector &v);
|
||||
Vector& operator=(const Vector& v);
|
||||
/* The move-assignment operator is not implemented, because moving pointers
|
||||
across class instances would break the “reference semantics” that the
|
||||
Vector class implements. The copy-assignment operator is thus used as a
|
||||
fallback. */
|
||||
Vector &operator=(const ConstVector &v);
|
||||
double &
|
||||
Vector& operator=(const ConstVector& v);
|
||||
double&
|
||||
operator[](int i)
|
||||
{
|
||||
return data[s*i];
|
||||
return data[s * i];
|
||||
}
|
||||
const double &
|
||||
const double&
|
||||
operator[](int i) const
|
||||
{
|
||||
return data[s*i];
|
||||
return data[s * i];
|
||||
}
|
||||
const double *
|
||||
const double*
|
||||
base() const
|
||||
{
|
||||
return data;
|
||||
}
|
||||
double *
|
||||
double*
|
||||
base()
|
||||
{
|
||||
return data;
|
||||
|
@ -110,13 +111,13 @@ public:
|
|||
}
|
||||
|
||||
// Exact equality.
|
||||
bool operator==(const Vector &y) const;
|
||||
bool operator!=(const Vector &y) const;
|
||||
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;
|
||||
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()
|
||||
{
|
||||
|
@ -128,18 +129,18 @@ public:
|
|||
void infs();
|
||||
void rotatePair(double alpha, double beta1, double beta2, int i);
|
||||
// Computes this = this + r·v
|
||||
void add(double r, const Vector &v);
|
||||
void add(double r, const Vector& v);
|
||||
// Computes this = this + r·v
|
||||
void add(double r, const ConstVector &v);
|
||||
void add(double r, const ConstVector& v);
|
||||
// Computes this = this + z·v (where this and v are intepreted as complex vectors)
|
||||
void addComplex(const std::complex<double> &z, const Vector &v);
|
||||
void addComplex(const std::complex<double>& z, const Vector& v);
|
||||
// Computes this = this + z·v (where this and v are intepreted as complex vectors)
|
||||
void addComplex(const std::complex<double> &z, const ConstVector &v);
|
||||
void addComplex(const std::complex<double>& z, const ConstVector& v);
|
||||
void mult(double r);
|
||||
double getNorm() const;
|
||||
double getMax() const;
|
||||
double getNorm1() const;
|
||||
double dot(const Vector &y) const;
|
||||
double dot(const Vector& y) const;
|
||||
bool isFinite() const;
|
||||
void print() const;
|
||||
|
||||
|
@ -148,31 +149,29 @@ public:
|
|||
⎢ ⎥=⎢ ⎥⊗I·⎢ ⎥
|
||||
⎝x₂⎠ ⎝−β₂ α ⎠ ⎝b₂⎠
|
||||
*/
|
||||
static void mult2(double alpha, double beta1, double beta2,
|
||||
Vector &x1, Vector &x2,
|
||||
const Vector &b1, const Vector &b2);
|
||||
static void mult2(double alpha, double beta1, double beta2, Vector& x1, Vector& x2,
|
||||
const Vector& b1, const Vector& b2);
|
||||
/* Computes:
|
||||
⎛x₁⎞ ⎛x₁⎞ ⎛ α −β₁⎞ ⎛b₁⎞
|
||||
⎢ ⎥=⎢ ⎥+⎢ ⎥⊗I·⎢ ⎥
|
||||
⎝x₂⎠ ⎝x₂⎠ ⎝−β₂ α ⎠ ⎝b₂⎠
|
||||
*/
|
||||
static void mult2a(double alpha, double beta1, double beta2,
|
||||
Vector &x1, Vector &x2,
|
||||
const Vector &b1, const Vector &b2);
|
||||
static void mult2a(double alpha, double beta1, double beta2, Vector& x1, Vector& x2,
|
||||
const Vector& b1, const Vector& b2);
|
||||
/* Computes:
|
||||
⎛x₁⎞ ⎛x₁⎞ ⎛ α −β₁⎞ ⎛b₁⎞
|
||||
⎢ ⎥=⎢ ⎥−⎢ ⎥⊗I·⎢ ⎥
|
||||
⎝x₂⎠ ⎝x₂⎠ ⎝−β₂ α ⎠ ⎝b₂⎠
|
||||
*/
|
||||
static void
|
||||
mult2s(double alpha, double beta1, double beta2,
|
||||
Vector &x1, Vector &x2,
|
||||
const Vector &b1, const Vector &b2)
|
||||
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);
|
||||
void copy(const double* d, int inc);
|
||||
};
|
||||
|
||||
class ConstGeneralMatrix;
|
||||
|
@ -180,33 +179,35 @@ class ConstGeneralMatrix;
|
|||
class ConstVector
|
||||
{
|
||||
friend class Vector;
|
||||
|
||||
protected:
|
||||
int len;
|
||||
int s{1}; // stride (also called “skip” in some places)
|
||||
const double *data;
|
||||
int s {1}; // stride (also called “skip” in some places)
|
||||
const double* data;
|
||||
|
||||
public:
|
||||
// Implicit conversion from Vector is ok, since it’s cheap
|
||||
ConstVector(const Vector &v);
|
||||
ConstVector(const ConstVector &v) = default;
|
||||
ConstVector(ConstVector &&v) = default;
|
||||
ConstVector(const double *d, int l) : len{l}, data{d}
|
||||
ConstVector(const Vector& v);
|
||||
ConstVector(const ConstVector& v) = default;
|
||||
ConstVector(ConstVector&& v) = default;
|
||||
ConstVector(const double* d, int l) : len {l}, data {d}
|
||||
{
|
||||
}
|
||||
ConstVector(const ConstVector &v, int off_arg, int l);
|
||||
ConstVector(const ConstVector &v, int off_arg, int skip, int l);
|
||||
ConstVector(const double *d, int skip, int l);
|
||||
ConstVector(const ConstVector& v, int off_arg, int l);
|
||||
ConstVector(const ConstVector& v, int off_arg, int skip, int l);
|
||||
ConstVector(const double* d, int skip, int l);
|
||||
#if defined(MATLAB_MEX_FILE) || defined(OCTAVE_MEX_FILE)
|
||||
explicit ConstVector(const mxArray *p);
|
||||
explicit ConstVector(const mxArray* p);
|
||||
#endif
|
||||
virtual ~ConstVector() = default;
|
||||
ConstVector &operator=(const ConstVector &v) = delete;
|
||||
ConstVector &operator=(ConstVector &&v) = delete;
|
||||
const double &
|
||||
ConstVector& operator=(const ConstVector& v) = delete;
|
||||
ConstVector& operator=(ConstVector&& v) = delete;
|
||||
const double&
|
||||
operator[](int i) const
|
||||
{
|
||||
return data[s*i];
|
||||
return data[s * i];
|
||||
}
|
||||
const double *
|
||||
const double*
|
||||
base() const
|
||||
{
|
||||
return data;
|
||||
|
@ -222,26 +223,26 @@ public:
|
|||
return s;
|
||||
}
|
||||
// Exact equality
|
||||
bool operator==(const ConstVector &y) const;
|
||||
bool operator==(const ConstVector& y) const;
|
||||
bool
|
||||
operator!=(const ConstVector &y) const
|
||||
operator!=(const ConstVector& y) const
|
||||
{
|
||||
return !operator==(y);
|
||||
}
|
||||
// Lexicographic ordering
|
||||
bool operator<(const ConstVector &y) const;
|
||||
bool operator<(const ConstVector& y) const;
|
||||
bool
|
||||
operator<=(const ConstVector &y) const
|
||||
operator<=(const ConstVector& y) const
|
||||
{
|
||||
return operator<(y) || operator==(y);
|
||||
}
|
||||
bool
|
||||
operator>(const ConstVector &y) const
|
||||
operator>(const ConstVector& y) const
|
||||
{
|
||||
return !operator<=(y);
|
||||
}
|
||||
bool
|
||||
operator>=(const ConstVector &y) const
|
||||
operator>=(const ConstVector& y) const
|
||||
{
|
||||
return !operator<(y);
|
||||
}
|
||||
|
@ -249,7 +250,7 @@ public:
|
|||
double getNorm() const;
|
||||
double getMax() const;
|
||||
double getNorm1() const;
|
||||
double dot(const ConstVector &y) const;
|
||||
double dot(const ConstVector& y) const;
|
||||
bool isFinite() const;
|
||||
void print() const;
|
||||
};
|
||||
|
|
|
@ -23,11 +23,11 @@
|
|||
#include <fstream>
|
||||
#include <iomanip>
|
||||
|
||||
MMMatrixIn::MMMatrixIn(const std::string &fname)
|
||||
MMMatrixIn::MMMatrixIn(const std::string& fname)
|
||||
{
|
||||
std::ifstream fd{fname};
|
||||
std::ifstream fd {fname};
|
||||
if (fd.fail())
|
||||
throw MMException("Cannot open file "+fname+" for reading\n");
|
||||
throw MMException("Cannot open file " + fname + " for reading\n");
|
||||
|
||||
// jump over initial comments
|
||||
while (fd.peek() == '%')
|
||||
|
@ -38,7 +38,7 @@ MMMatrixIn::MMMatrixIn(const std::string &fname)
|
|||
if (fd.fail())
|
||||
throw MMException("Couldn't parse rows and cols\n");
|
||||
// read in data
|
||||
int len = rows*cols;
|
||||
int len = rows * cols;
|
||||
data.resize(len);
|
||||
int i = 0;
|
||||
while (!fd.eof() && i < len)
|
||||
|
@ -55,11 +55,11 @@ MMMatrixIn::MMMatrixIn(const std::string &fname)
|
|||
}
|
||||
|
||||
void
|
||||
MMMatrixOut::write(const std::string &fname, const GeneralMatrix &m)
|
||||
MMMatrixOut::write(const std::string& fname, const GeneralMatrix& m)
|
||||
{
|
||||
std::ofstream fd{fname, std::ios::out | std::ios::trunc};
|
||||
std::ofstream fd {fname, std::ios::out | std::ios::trunc};
|
||||
if (fd.fail())
|
||||
throw MMException("Cannot open file "+fname+" for writing\n");
|
||||
throw MMException("Cannot open file " + fname + " for writing\n");
|
||||
|
||||
fd << "%%%%MatrixMarket matrix array real general" << std::endl
|
||||
<< m.nrows() << ' ' << m.ncols() << std::endl
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
class MMException
|
||||
{
|
||||
std::string message;
|
||||
|
||||
public:
|
||||
MMException(std::string mes) : message(std::move(mes))
|
||||
{
|
||||
|
@ -46,18 +47,19 @@ class MMMatrixIn
|
|||
std::vector<double> data;
|
||||
int rows;
|
||||
int cols;
|
||||
|
||||
public:
|
||||
MMMatrixIn(const std::string &fname);
|
||||
MMMatrixIn(const std::string& fname);
|
||||
~MMMatrixIn() = default;
|
||||
Vector
|
||||
getData()
|
||||
{
|
||||
return Vector{data.data(), size()};
|
||||
return Vector {data.data(), size()};
|
||||
}
|
||||
int
|
||||
size() const
|
||||
{
|
||||
return rows*cols;
|
||||
return rows * cols;
|
||||
}
|
||||
int
|
||||
row() const
|
||||
|
@ -74,7 +76,7 @@ public:
|
|||
class MMMatrixOut
|
||||
{
|
||||
public:
|
||||
static void write(const std::string &fname, const GeneralMatrix &m);
|
||||
static void write(const std::string& fname, const GeneralMatrix& m);
|
||||
};
|
||||
|
||||
#endif /* MM_MATRIX_H */
|
||||
|
|
|
@ -18,29 +18,29 @@
|
|||
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "SylvException.hh"
|
||||
#include "GeneralSylvester.hh"
|
||||
#include "IterativeSylvester.hh"
|
||||
#include "KronUtils.hh"
|
||||
#include "KronVector.hh"
|
||||
#include "QuasiTriangular.hh"
|
||||
#include "QuasiTriangularZero.hh"
|
||||
#include "Vector.hh"
|
||||
#include "KronVector.hh"
|
||||
#include "KronUtils.hh"
|
||||
#include "TriangularSylvester.hh"
|
||||
#include "GeneralSylvester.hh"
|
||||
#include "SchurDecompEig.hh"
|
||||
#include "SimilarityDecomp.hh"
|
||||
#include "IterativeSylvester.hh"
|
||||
#include "SylvException.hh"
|
||||
#include "SylvMatrix.hh"
|
||||
#include "TriangularSylvester.hh"
|
||||
#include "Vector.hh"
|
||||
#include "int_power.hh"
|
||||
|
||||
#include "MMMatrix.hh"
|
||||
|
||||
#include <ctime>
|
||||
#include <cmath>
|
||||
#include <ctime>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <memory>
|
||||
|
||||
class TestRunnable
|
||||
{
|
||||
|
@ -53,30 +53,31 @@ public:
|
|||
virtual ~TestRunnable() = default;
|
||||
bool test() const;
|
||||
virtual bool run() const = 0;
|
||||
|
||||
protected:
|
||||
// declaration of auxiliary static methods
|
||||
static bool quasi_solve(bool trans, const std::string &mname, const std::string &vname);
|
||||
static bool mult_kron(bool trans, const std::string &mname, const std::string &vname,
|
||||
const std::string &cname, int m, int n, int depth);
|
||||
static bool level_kron(bool trans, const std::string &mname, const std::string &vname,
|
||||
const std::string &cname, int level, int m, int n, int depth);
|
||||
static bool kron_power(const std::string &m1name, const std::string &m2name, const std::string &vname,
|
||||
const std::string &cname, int m, int n, int depth);
|
||||
static bool lin_eval(const std::string &m1name, const std::string &m2name, const std::string &vname,
|
||||
const std::string &cname, int m, int n, int depth,
|
||||
static bool quasi_solve(bool trans, const std::string& mname, const std::string& vname);
|
||||
static bool mult_kron(bool trans, const std::string& mname, const std::string& vname,
|
||||
const std::string& cname, int m, int n, int depth);
|
||||
static bool level_kron(bool trans, const std::string& mname, const std::string& vname,
|
||||
const std::string& cname, int level, int m, int n, int depth);
|
||||
static bool kron_power(const std::string& m1name, const std::string& m2name,
|
||||
const std::string& vname, const std::string& cname, int m, int n,
|
||||
int depth);
|
||||
static bool lin_eval(const std::string& m1name, const std::string& m2name,
|
||||
const std::string& vname, const std::string& cname, int m, int n, int depth,
|
||||
double alpha, double beta1, double beta2);
|
||||
static bool qua_eval(const std::string &m1name, const std::string &m2name, const std::string &vname,
|
||||
const std::string &cname, int m, int n, int depth,
|
||||
double alpha, double betas, double gamma,
|
||||
double delta1, double delta2);
|
||||
static bool tri_sylv(const std::string &m1name, const std::string &m2name, const std::string &vname,
|
||||
int m, int n, int depth);
|
||||
static bool gen_sylv(const std::string &aname, const std::string &bname, const std::string &cname,
|
||||
const std::string &dname, int m, int n, int order);
|
||||
static bool eig_bubble(const std::string &aname, int from, int to);
|
||||
static bool block_diag(const std::string &aname, double log10norm = 3.0);
|
||||
static bool iter_sylv(const std::string &m1name, const std::string &m2name, const std::string &vname,
|
||||
int m, int n, int depth);
|
||||
static bool qua_eval(const std::string& m1name, const std::string& m2name,
|
||||
const std::string& vname, const std::string& cname, int m, int n, int depth,
|
||||
double alpha, double betas, double gamma, double delta1, double delta2);
|
||||
static bool tri_sylv(const std::string& m1name, const std::string& m2name,
|
||||
const std::string& vname, int m, int n, int depth);
|
||||
static bool gen_sylv(const std::string& aname, const std::string& bname, const std::string& cname,
|
||||
const std::string& dname, int m, int n, int order);
|
||||
static bool eig_bubble(const std::string& aname, int from, int to);
|
||||
static bool block_diag(const std::string& aname, double log10norm = 3.0);
|
||||
static bool iter_sylv(const std::string& m1name, const std::string& m2name,
|
||||
const std::string& vname, int m, int n, int depth);
|
||||
};
|
||||
|
||||
bool
|
||||
|
@ -86,7 +87,8 @@ TestRunnable::test() const
|
|||
clock_t start = clock();
|
||||
bool passed = run();
|
||||
clock_t end = clock();
|
||||
std::cout << "CPU time " << (static_cast<double>(end-start))/CLOCKS_PER_SEC << " (CPU seconds)..................";
|
||||
std::cout << "CPU time " << (static_cast<double>(end - start)) / CLOCKS_PER_SEC
|
||||
<< " (CPU seconds)..................";
|
||||
if (passed)
|
||||
std::cout << "passed";
|
||||
else
|
||||
|
@ -100,7 +102,7 @@ TestRunnable::test() const
|
|||
/**********************************************************/
|
||||
|
||||
bool
|
||||
TestRunnable::quasi_solve(bool trans, const std::string &mname, const std::string &vname)
|
||||
TestRunnable::quasi_solve(bool trans, const std::string& mname, const std::string& vname)
|
||||
{
|
||||
MMMatrixIn mmt(mname);
|
||||
MMMatrixIn mmv(vname);
|
||||
|
@ -114,15 +116,16 @@ TestRunnable::quasi_solve(bool trans, const std::string &mname, const std::strin
|
|||
}
|
||||
else if (mmt.row() > mmt.col())
|
||||
{
|
||||
t = std::make_unique<QuasiTriangularZero>(mmt.row()-mmt.col(), mmt.getData(), mmt.col());
|
||||
tsave = std::make_unique<QuasiTriangularZero>(const_cast<const QuasiTriangularZero &>(dynamic_cast<QuasiTriangularZero &>(*t)));
|
||||
t = std::make_unique<QuasiTriangularZero>(mmt.row() - mmt.col(), mmt.getData(), mmt.col());
|
||||
tsave = std::make_unique<QuasiTriangularZero>(
|
||||
const_cast<const QuasiTriangularZero&>(dynamic_cast<QuasiTriangularZero&>(*t)));
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << " Wrong quasi triangular dimensions, rows must be >= cols.\n";
|
||||
return false;
|
||||
}
|
||||
ConstVector v{mmv.getData()};
|
||||
ConstVector v {mmv.getData()};
|
||||
Vector x(v.length());
|
||||
double eig_min = 1.0e20;
|
||||
if (trans)
|
||||
|
@ -143,29 +146,26 @@ TestRunnable::quasi_solve(bool trans, const std::string &mname, const std::strin
|
|||
}
|
||||
|
||||
bool
|
||||
TestRunnable::mult_kron(bool trans, const std::string &mname, const std::string &vname,
|
||||
const std::string &cname, int m, int n, int depth)
|
||||
TestRunnable::mult_kron(bool trans, const std::string& mname, const std::string& vname,
|
||||
const std::string& cname, int m, int n, int depth)
|
||||
{
|
||||
MMMatrixIn mmt(mname);
|
||||
MMMatrixIn mmv(vname);
|
||||
MMMatrixIn mmc(cname);
|
||||
|
||||
int length = power(m, depth)*n;
|
||||
if (mmt.row() != m
|
||||
|| mmv.row() != length
|
||||
|| mmc.row() != length)
|
||||
int length = power(m, depth) * n;
|
||||
if (mmt.row() != m || mmv.row() != length || mmc.row() != length)
|
||||
{
|
||||
std::cout << " Incompatible sizes for kron mult action, len=" << length
|
||||
<< ", matrow=" << mmt.row() << ", m=" << m
|
||||
<< ", vrow=" << mmv.row() << ", crow=" << mmc.row()
|
||||
<< std::endl;
|
||||
<< ", matrow=" << mmt.row() << ", m=" << m << ", vrow=" << mmv.row()
|
||||
<< ", crow=" << mmc.row() << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
QuasiTriangular t(mmt.getData(), mmt.row());
|
||||
Vector vraw{mmv.getData()};
|
||||
Vector vraw {mmv.getData()};
|
||||
KronVector v(vraw, m, n, depth);
|
||||
Vector craw{mmc.getData()};
|
||||
Vector craw {mmc.getData()};
|
||||
KronVector c(craw, m, n, depth);
|
||||
if (trans)
|
||||
t.multKronTrans(v);
|
||||
|
@ -178,30 +178,27 @@ TestRunnable::mult_kron(bool trans, const std::string &mname, const std::string
|
|||
}
|
||||
|
||||
bool
|
||||
TestRunnable::level_kron(bool trans, const std::string &mname, const std::string &vname,
|
||||
const std::string &cname, int level, int m, int n, int depth)
|
||||
TestRunnable::level_kron(bool trans, const std::string& mname, const std::string& vname,
|
||||
const std::string& cname, int level, int m, int n, int depth)
|
||||
{
|
||||
MMMatrixIn mmt(mname);
|
||||
MMMatrixIn mmv(vname);
|
||||
MMMatrixIn mmc(cname);
|
||||
|
||||
int length = power(m, depth)*n;
|
||||
if ((level > 0 && mmt.row() != m)
|
||||
|| (level == 0 && mmt.row() != n)
|
||||
|| mmv.row() != length
|
||||
int length = power(m, depth) * n;
|
||||
if ((level > 0 && mmt.row() != m) || (level == 0 && mmt.row() != n) || mmv.row() != length
|
||||
|| mmc.row() != length)
|
||||
{
|
||||
std::cout << " Incompatible sizes for kron mult action, len=" << length
|
||||
<< ", matrow=" << mmt.row() << ", m=" << m << ", n=" << n
|
||||
<< ", vrow=" << mmv.row() << ", crow=" << mmc.row()
|
||||
<< std::endl;
|
||||
<< ", matrow=" << mmt.row() << ", m=" << m << ", n=" << n << ", vrow=" << mmv.row()
|
||||
<< ", crow=" << mmc.row() << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
QuasiTriangular t(mmt.getData(), mmt.row());
|
||||
Vector vraw{mmv.getData()};
|
||||
Vector vraw {mmv.getData()};
|
||||
ConstKronVector v(vraw, m, n, depth);
|
||||
Vector craw{mmc.getData()};
|
||||
Vector craw {mmc.getData()};
|
||||
KronVector c(craw, m, n, depth);
|
||||
KronVector x(v);
|
||||
if (trans)
|
||||
|
@ -215,33 +212,29 @@ TestRunnable::level_kron(bool trans, const std::string &mname, const std::string
|
|||
}
|
||||
|
||||
bool
|
||||
TestRunnable::kron_power(const std::string &m1name, const std::string &m2name, const std::string &vname,
|
||||
const std::string &cname, int m, int n, int depth)
|
||||
TestRunnable::kron_power(const std::string& m1name, const std::string& m2name,
|
||||
const std::string& vname, const std::string& cname, int m, int n,
|
||||
int depth)
|
||||
{
|
||||
MMMatrixIn mmt1(m1name);
|
||||
MMMatrixIn mmt2(m2name);
|
||||
MMMatrixIn mmv(vname);
|
||||
MMMatrixIn mmc(cname);
|
||||
|
||||
int length = power(m, depth)*n;
|
||||
if (mmt1.row() != m
|
||||
|| mmt2.row() != n
|
||||
|| mmv.row() != length
|
||||
|| mmc.row() != length)
|
||||
int length = power(m, depth) * n;
|
||||
if (mmt1.row() != m || mmt2.row() != n || mmv.row() != length || mmc.row() != length)
|
||||
{
|
||||
std::cout << " Incompatible sizes for kron power mult action, len=" << length
|
||||
<< ", row1=" << mmt1.row() << ", row2=" << mmt2.row()
|
||||
<< ", m=" << m << ", n=" << n
|
||||
<< ", vrow=" << mmv.row() << ", crow=" << mmc.row()
|
||||
<< std::endl;
|
||||
<< ", row1=" << mmt1.row() << ", row2=" << mmt2.row() << ", m=" << m << ", n=" << n
|
||||
<< ", vrow=" << mmv.row() << ", crow=" << mmc.row() << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
QuasiTriangular t1(mmt1.getData(), mmt1.row());
|
||||
QuasiTriangular t2(mmt2.getData(), mmt2.row());
|
||||
Vector vraw{mmv.getData()};
|
||||
Vector vraw {mmv.getData()};
|
||||
ConstKronVector v(vraw, m, n, depth);
|
||||
Vector craw{mmc.getData()};
|
||||
Vector craw {mmc.getData()};
|
||||
KronVector c(craw, m, n, depth);
|
||||
KronVector x(v);
|
||||
KronUtils::multKron(t1, t2, x);
|
||||
|
@ -252,8 +245,8 @@ TestRunnable::kron_power(const std::string &m1name, const std::string &m2name, c
|
|||
}
|
||||
|
||||
bool
|
||||
TestRunnable::lin_eval(const std::string &m1name, const std::string &m2name, const std::string &vname,
|
||||
const std::string &cname, int m, int n, int depth,
|
||||
TestRunnable::lin_eval(const std::string& m1name, const std::string& m2name,
|
||||
const std::string& vname, const std::string& cname, int m, int n, int depth,
|
||||
double alpha, double beta1, double beta2)
|
||||
{
|
||||
MMMatrixIn mmt1(m1name);
|
||||
|
@ -261,30 +254,25 @@ TestRunnable::lin_eval(const std::string &m1name, const std::string &m2name, con
|
|||
MMMatrixIn mmv(vname);
|
||||
MMMatrixIn mmc(cname);
|
||||
|
||||
int length = power(m, depth)*n;
|
||||
if (mmt1.row() != m
|
||||
|| mmt2.row() != n
|
||||
|| mmv.row() != 2*length
|
||||
|| mmc.row() != 2*length)
|
||||
int length = power(m, depth) * n;
|
||||
if (mmt1.row() != m || mmt2.row() != n || mmv.row() != 2 * length || mmc.row() != 2 * length)
|
||||
{
|
||||
std::cout << " Incompatible sizes for lin eval action, len=" << length
|
||||
<< ", row1=" << mmt1.row() << ", row2=" << mmt2.row()
|
||||
<< ", m=" << m << ", n=" << n
|
||||
<< ", vrow=" << mmv.row() << ", crow=" << mmc.row()
|
||||
<< std::endl;
|
||||
<< ", row1=" << mmt1.row() << ", row2=" << mmt2.row() << ", m=" << m << ", n=" << n
|
||||
<< ", vrow=" << mmv.row() << ", crow=" << mmc.row() << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
QuasiTriangular t1(mmt1.getData(), mmt1.row());
|
||||
QuasiTriangular t2(mmt2.getData(), mmt2.row());
|
||||
TriangularSylvester ts(t2, t1);
|
||||
ConstVector vraw1{mmv.getData(), 0, length};
|
||||
ConstVector vraw1 {mmv.getData(), 0, length};
|
||||
ConstKronVector v1(vraw1, m, n, depth);
|
||||
ConstVector vraw2{mmv.getData(), length, length};
|
||||
ConstVector vraw2 {mmv.getData(), length, length};
|
||||
ConstKronVector v2(vraw2, m, n, depth);
|
||||
ConstVector craw1{mmc.getData(), 0, length};
|
||||
ConstVector craw1 {mmc.getData(), 0, length};
|
||||
ConstKronVector c1(craw1, m, n, depth);
|
||||
ConstVector craw2{mmc.getData(), length, length};
|
||||
ConstVector craw2 {mmc.getData(), length, length};
|
||||
ConstKronVector c2(craw2, m, n, depth);
|
||||
KronVector x1(m, n, depth);
|
||||
KronVector x2(m, n, depth);
|
||||
|
@ -294,44 +282,38 @@ TestRunnable::lin_eval(const std::string &m1name, const std::string &m2name, con
|
|||
double norm1 = x1.getNorm();
|
||||
double norm2 = x2.getNorm();
|
||||
std::cout << "\terror norm1 = " << norm1 << "\n\terror norm2 = " << norm2 << '\n';
|
||||
return (norm1*norm1+norm2*norm2 < eps_norm*eps_norm);
|
||||
return (norm1 * norm1 + norm2 * norm2 < eps_norm * eps_norm);
|
||||
}
|
||||
|
||||
bool
|
||||
TestRunnable::qua_eval(const std::string &m1name, const std::string &m2name, const std::string &vname,
|
||||
const std::string &cname, int m, int n, int depth,
|
||||
double alpha, double betas, double gamma,
|
||||
double delta1, double delta2)
|
||||
TestRunnable::qua_eval(const std::string& m1name, const std::string& m2name,
|
||||
const std::string& vname, const std::string& cname, int m, int n, int depth,
|
||||
double alpha, double betas, double gamma, double delta1, double delta2)
|
||||
{
|
||||
MMMatrixIn mmt1(m1name);
|
||||
MMMatrixIn mmt2(m2name);
|
||||
MMMatrixIn mmv(vname);
|
||||
MMMatrixIn mmc(cname);
|
||||
|
||||
int length = power(m, depth)*n;
|
||||
if (mmt1.row() != m
|
||||
|| mmt2.row() != n
|
||||
|| mmv.row() != 2*length
|
||||
|| mmc.row() != 2*length)
|
||||
int length = power(m, depth) * n;
|
||||
if (mmt1.row() != m || mmt2.row() != n || mmv.row() != 2 * length || mmc.row() != 2 * length)
|
||||
{
|
||||
std::cout << " Incompatible sizes for qua eval action, len=" << length
|
||||
<< ", row1=" << mmt1.row() << ", row2=" << mmt2.row()
|
||||
<< ", m=" << m << ", n=" << n
|
||||
<< ", vrow=" << mmv.row() << ", crow=" << mmc.row()
|
||||
<< std::endl;
|
||||
<< ", row1=" << mmt1.row() << ", row2=" << mmt2.row() << ", m=" << m << ", n=" << n
|
||||
<< ", vrow=" << mmv.row() << ", crow=" << mmc.row() << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
QuasiTriangular t1(mmt1.getData(), mmt1.row());
|
||||
QuasiTriangular t2(mmt2.getData(), mmt2.row());
|
||||
TriangularSylvester ts(t2, t1);
|
||||
ConstVector vraw1{mmv.getData(), 0, length};
|
||||
ConstVector vraw1 {mmv.getData(), 0, length};
|
||||
ConstKronVector v1(vraw1, m, n, depth);
|
||||
ConstVector vraw2{mmv.getData(), length, length};
|
||||
ConstVector vraw2 {mmv.getData(), length, length};
|
||||
ConstKronVector v2(vraw2, m, n, depth);
|
||||
ConstVector craw1{mmc.getData(), 0, length};
|
||||
ConstVector craw1 {mmc.getData(), 0, length};
|
||||
ConstKronVector c1(craw1, m, n, depth);
|
||||
ConstVector craw2{mmc.getData(), length, length};
|
||||
ConstVector craw2 {mmc.getData(), length, length};
|
||||
ConstKronVector c2(craw2, m, n, depth);
|
||||
KronVector x1(m, n, depth);
|
||||
KronVector x2(m, n, depth);
|
||||
|
@ -341,86 +323,77 @@ TestRunnable::qua_eval(const std::string &m1name, const std::string &m2name, con
|
|||
double norm1 = x1.getNorm();
|
||||
double norm2 = x2.getNorm();
|
||||
std::cout << "\terror norm1 = " << norm1 << "\n\terror norm2 = " << norm2 << std::endl;
|
||||
return (norm1*norm1+norm2*norm2 < 100*eps_norm*eps_norm); // relax norm
|
||||
return (norm1 * norm1 + norm2 * norm2 < 100 * eps_norm * eps_norm); // relax norm
|
||||
}
|
||||
|
||||
bool
|
||||
TestRunnable::tri_sylv(const std::string &m1name, const std::string &m2name, const std::string &vname,
|
||||
int m, int n, int depth)
|
||||
TestRunnable::tri_sylv(const std::string& m1name, const std::string& m2name,
|
||||
const std::string& vname, int m, int n, int depth)
|
||||
{
|
||||
MMMatrixIn mmt1(m1name);
|
||||
MMMatrixIn mmt2(m2name);
|
||||
MMMatrixIn mmv(vname);
|
||||
|
||||
int length = power(m, depth)*n;
|
||||
if (mmt1.row() != m
|
||||
|| mmt2.row() != n
|
||||
|| mmv.row() != length)
|
||||
int length = power(m, depth) * n;
|
||||
if (mmt1.row() != m || mmt2.row() != n || mmv.row() != length)
|
||||
{
|
||||
std::cout << " Incompatible sizes for triangular sylvester action, len=" << length
|
||||
<< ", row1=" << mmt1.row() << ", row2=" << mmt2.row()
|
||||
<< ", m=" << m << ", n=" << n
|
||||
<< ", vrow=" << mmv.row()
|
||||
<< std::endl;
|
||||
<< ", row1=" << mmt1.row() << ", row2=" << mmt2.row() << ", m=" << m << ", n=" << n
|
||||
<< ", vrow=" << mmv.row() << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
QuasiTriangular t1(mmt1.getData(), mmt1.row());
|
||||
QuasiTriangular t2(mmt2.getData(), mmt2.row());
|
||||
TriangularSylvester ts(t2, t1);
|
||||
Vector vraw{mmv.getData()};
|
||||
Vector vraw {mmv.getData()};
|
||||
ConstKronVector v(vraw, m, n, depth);
|
||||
KronVector d(v); // copy of v
|
||||
SylvParams pars;
|
||||
ts.solve(pars, d);
|
||||
pars.print("\t");
|
||||
KronVector dcheck(const_cast<const KronVector &>(d));
|
||||
KronVector dcheck(const_cast<const KronVector&>(d));
|
||||
KronUtils::multKron(t1, t2, dcheck);
|
||||
dcheck.add(1.0, d);
|
||||
dcheck.add(-1.0, v);
|
||||
double norm = dcheck.getNorm();
|
||||
double xnorm = v.getNorm();
|
||||
std::cout << "\trel. error norm = " << norm/xnorm << std::endl;
|
||||
std::cout << "\trel. error norm = " << norm / xnorm << std::endl;
|
||||
double max = dcheck.getMax();
|
||||
double xmax = v.getMax();
|
||||
std::cout << "\trel. error max = " << max/xmax << std::endl;
|
||||
return (norm < xnorm*eps_norm);
|
||||
std::cout << "\trel. error max = " << max / xmax << std::endl;
|
||||
return (norm < xnorm * eps_norm);
|
||||
}
|
||||
|
||||
bool
|
||||
TestRunnable::gen_sylv(const std::string &aname, const std::string &bname, const std::string &cname,
|
||||
const std::string &dname, int m, int n, int order)
|
||||
TestRunnable::gen_sylv(const std::string& aname, const std::string& bname, const std::string& cname,
|
||||
const std::string& dname, int m, int n, int order)
|
||||
{
|
||||
MMMatrixIn mma(aname);
|
||||
MMMatrixIn mmb(bname);
|
||||
MMMatrixIn mmc(cname);
|
||||
MMMatrixIn mmd(dname);
|
||||
|
||||
if (m != mmc.row() || m != mmc.col()
|
||||
|| n != mma.row() || n != mma.col()
|
||||
|| n != mmb.row() || n < mmb.col()
|
||||
|| n != mmd.row() || power(m, order) != mmd.col())
|
||||
if (m != mmc.row() || m != mmc.col() || n != mma.row() || n != mma.col() || n != mmb.row()
|
||||
|| n < mmb.col() || n != mmd.row() || power(m, order) != mmd.col())
|
||||
{
|
||||
std::cout << " Incompatible sizes for gen_sylv.\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
SylvParams ps(true);
|
||||
GeneralSylvester gs(order, n, m, n-mmb.col(),
|
||||
mma.getData(), mmb.getData(),
|
||||
mmc.getData(), mmd.getData(),
|
||||
ps);
|
||||
GeneralSylvester gs(order, n, m, n - mmb.col(), mma.getData(), mmb.getData(), mmc.getData(),
|
||||
mmd.getData(), ps);
|
||||
gs.solve();
|
||||
gs.check(mmd.getData());
|
||||
const SylvParams &pars = gs.getParams();
|
||||
const SylvParams& pars = gs.getParams();
|
||||
pars.print("\t");
|
||||
return (*(pars.mat_err1) < eps_norm && *(pars.mat_errI) < eps_norm
|
||||
&& *(pars.mat_errF) < eps_norm && *(pars.vec_err1) < eps_norm
|
||||
&& *(pars.vec_errI) < eps_norm);
|
||||
return (*(pars.mat_err1) < eps_norm && *(pars.mat_errI) < eps_norm && *(pars.mat_errF) < eps_norm
|
||||
&& *(pars.vec_err1) < eps_norm && *(pars.vec_errI) < eps_norm);
|
||||
}
|
||||
|
||||
bool
|
||||
TestRunnable::eig_bubble(const std::string &aname, int from, int to)
|
||||
TestRunnable::eig_bubble(const std::string& aname, int from, int to)
|
||||
{
|
||||
MMMatrixIn mma(aname);
|
||||
|
||||
|
@ -432,7 +405,7 @@ TestRunnable::eig_bubble(const std::string &aname, int from, int to)
|
|||
|
||||
int n = mma.row();
|
||||
QuasiTriangular orig(mma.getData(), n);
|
||||
SchurDecompEig dec(const_cast<const QuasiTriangular &>(orig));
|
||||
SchurDecompEig dec(const_cast<const QuasiTriangular&>(orig));
|
||||
QuasiTriangular::diag_iter itf = dec.getT().diag_begin();
|
||||
QuasiTriangular::diag_iter itt = dec.getT().diag_begin();
|
||||
for (int i = 0; i < from; i++)
|
||||
|
@ -449,13 +422,13 @@ TestRunnable::eig_bubble(const std::string &aname, int from, int to)
|
|||
double onormInf = orig.getNormInf();
|
||||
std::cout << "\tabs. error1 = " << norm1 << std::endl
|
||||
<< "\tabs. error∞ = " << normInf << std::endl
|
||||
<< "\trel. error1 = " << norm1/onorm1 << std::endl
|
||||
<< "\trel. error∞ = " << normInf/onormInf << std::endl;
|
||||
return (norm1 < eps_norm*onorm1 && normInf < eps_norm*onormInf);
|
||||
<< "\trel. error1 = " << norm1 / onorm1 << std::endl
|
||||
<< "\trel. error∞ = " << normInf / onormInf << std::endl;
|
||||
return (norm1 < eps_norm * onorm1 && normInf < eps_norm * onormInf);
|
||||
}
|
||||
|
||||
bool
|
||||
TestRunnable::block_diag(const std::string &aname, double log10norm)
|
||||
TestRunnable::block_diag(const std::string& aname, double log10norm)
|
||||
{
|
||||
MMMatrixIn mma(aname);
|
||||
|
||||
|
@ -479,8 +452,8 @@ TestRunnable::block_diag(const std::string &aname, double log10norm)
|
|||
std::cout << "\terror Q·B·Q⁻¹:" << std::endl
|
||||
<< "\tabs. error1 = " << norm1 << std::endl
|
||||
<< "\tabs. error∞ = " << normInf << std::endl
|
||||
<< "\trel. error1 = " << norm1/onorm1 << std::endl
|
||||
<< "\trel. error∞ = " << normInf/onormInf << std::endl;
|
||||
<< "\trel. error1 = " << norm1 / onorm1 << std::endl
|
||||
<< "\trel. error∞ = " << normInf / onormInf << std::endl;
|
||||
SqSylvMatrix check2(dec.getQ() * dec.getInvQ());
|
||||
SqSylvMatrix in(n);
|
||||
in.setUnit();
|
||||
|
@ -490,51 +463,47 @@ TestRunnable::block_diag(const std::string &aname, double log10norm)
|
|||
std::cout << "\terror Q·Q⁻¹:" << std::endl
|
||||
<< "\tabs. error1 = " << nor1 << std::endl
|
||||
<< "\tabs. error∞ = " << norInf << std::endl;
|
||||
return (norm1 < eps_norm*pow(10, log10norm)*onorm1);
|
||||
return (norm1 < eps_norm * pow(10, log10norm) * onorm1);
|
||||
}
|
||||
|
||||
bool
|
||||
TestRunnable::iter_sylv(const std::string &m1name, const std::string &m2name, const std::string &vname,
|
||||
int m, int n, int depth)
|
||||
TestRunnable::iter_sylv(const std::string& m1name, const std::string& m2name,
|
||||
const std::string& vname, int m, int n, int depth)
|
||||
{
|
||||
MMMatrixIn mmt1(m1name);
|
||||
MMMatrixIn mmt2(m2name);
|
||||
MMMatrixIn mmv(vname);
|
||||
|
||||
int length = power(m, depth)*n;
|
||||
if (mmt1.row() != m
|
||||
|| mmt2.row() != n
|
||||
|| mmv.row() != length)
|
||||
int length = power(m, depth) * n;
|
||||
if (mmt1.row() != m || mmt2.row() != n || mmv.row() != length)
|
||||
{
|
||||
std::cout << " Incompatible sizes for triangular sylvester iteration, len=" << length
|
||||
<< ", row1=" << mmt1.row() << ", row2=" << mmt2.row()
|
||||
<< ", m=" << m << ", n=" << n
|
||||
<< ", vrow=" << mmv.row()
|
||||
<< std::endl;
|
||||
<< ", row1=" << mmt1.row() << ", row2=" << mmt2.row() << ", m=" << m << ", n=" << n
|
||||
<< ", vrow=" << mmv.row() << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
QuasiTriangular t1(mmt1.getData(), mmt1.row());
|
||||
QuasiTriangular t2(mmt2.getData(), mmt2.row());
|
||||
IterativeSylvester is(t2, t1);
|
||||
Vector vraw{mmv.getData()};
|
||||
Vector vraw {mmv.getData()};
|
||||
ConstKronVector v(vraw, m, n, depth);
|
||||
KronVector d(v); // copy of v
|
||||
SylvParams pars;
|
||||
pars.method = SylvParams::solve_method::iter;
|
||||
is.solve(pars, d);
|
||||
pars.print("\t");
|
||||
KronVector dcheck(const_cast<const KronVector &>(d));
|
||||
KronVector dcheck(const_cast<const KronVector&>(d));
|
||||
KronUtils::multKron(t1, t2, dcheck);
|
||||
dcheck.add(1.0, d);
|
||||
dcheck.add(-1.0, v);
|
||||
double cnorm = dcheck.getNorm();
|
||||
double xnorm = v.getNorm();
|
||||
std::cout << "\trel. error norm = " << cnorm/xnorm << std::endl;
|
||||
std::cout << "\trel. error norm = " << cnorm / xnorm << std::endl;
|
||||
double max = dcheck.getMax();
|
||||
double xmax = v.getMax();
|
||||
std::cout << "\trel. error max = " << max/xmax << std::endl;
|
||||
return (cnorm < xnorm*eps_norm);
|
||||
std::cout << "\trel. error max = " << max / xmax << std::endl;
|
||||
return (cnorm < xnorm * eps_norm);
|
||||
}
|
||||
|
||||
/**********************************************************/
|
||||
|
@ -1018,29 +987,25 @@ KronPowerTest::run() const
|
|||
bool
|
||||
SmallLinEvalTest::run() const
|
||||
{
|
||||
return lin_eval("qt2x2.mm", "qt3x3.mm", "v24.mm", "vcheck24.mm", 2, 3, 2,
|
||||
2, 1, 3);
|
||||
return lin_eval("qt2x2.mm", "qt3x3.mm", "v24.mm", "vcheck24.mm", 2, 3, 2, 2, 1, 3);
|
||||
}
|
||||
|
||||
bool
|
||||
LinEvalTest::run() const
|
||||
{
|
||||
return lin_eval("qt7x7.mm", "tr5x5.mm", "v490.mm", "vcheck490.mm", 7, 5, 2,
|
||||
2, 1, 3);
|
||||
return lin_eval("qt7x7.mm", "tr5x5.mm", "v490.mm", "vcheck490.mm", 7, 5, 2, 2, 1, 3);
|
||||
}
|
||||
|
||||
bool
|
||||
SmallQuaEvalTest::run() const
|
||||
{
|
||||
return qua_eval("qt2x2.mm", "qt3x3.mm", "v24.mm", "vcheck24q.mm", 2, 3, 2,
|
||||
-0.5, 3, 2, 1, 3);
|
||||
return qua_eval("qt2x2.mm", "qt3x3.mm", "v24.mm", "vcheck24q.mm", 2, 3, 2, -0.5, 3, 2, 1, 3);
|
||||
}
|
||||
|
||||
bool
|
||||
QuaEvalTest::run() const
|
||||
{
|
||||
return qua_eval("qt7x7.mm", "tr5x5.mm", "v490.mm", "vcheck490q.mm", 7, 5, 2,
|
||||
-0.5, 3, 2, 1, 3);
|
||||
return qua_eval("qt7x7.mm", "tr5x5.mm", "v490.mm", "vcheck490q.mm", 7, 5, 2, -0.5, 3, 2, 1, 3);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -1204,18 +1169,18 @@ main()
|
|||
// launch the tests
|
||||
std::cout << std::setprecision(4);
|
||||
int success = 0;
|
||||
for (const auto &test : all_tests)
|
||||
for (const auto& test : all_tests)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (test->test())
|
||||
success++;
|
||||
}
|
||||
catch (const MMException &e)
|
||||
catch (const MMException& e)
|
||||
{
|
||||
std::cout << "Caught MM exception in <" << test->name << ">:\n" << e.getMessage();
|
||||
}
|
||||
catch (SylvException &e)
|
||||
catch (SylvException& e)
|
||||
{
|
||||
std::cout << "Caught Sylv exception in " << test->name << ":\n";
|
||||
e.printMessage();
|
||||
|
@ -1223,8 +1188,8 @@ main()
|
|||
}
|
||||
|
||||
int nfailed = all_tests.size() - success;
|
||||
std::cout << "There were " << nfailed << " tests that failed out of "
|
||||
<< all_tests.size() << " tests run." << std::endl;
|
||||
std::cout << "There were " << nfailed << " tests that failed out of " << all_tests.size()
|
||||
<< " tests run." << std::endl;
|
||||
|
||||
if (nfailed)
|
||||
return EXIT_FAILURE;
|
||||
|
|
|
@ -27,8 +27,7 @@
|
|||
int
|
||||
OrdSequence::operator[](int i) const
|
||||
{
|
||||
TL_RAISE_IF((i < 0 || i >= length()),
|
||||
"Index out of range in OrdSequence::operator[]");
|
||||
TL_RAISE_IF((i < 0 || i >= length()), "Index out of range in OrdSequence::operator[]");
|
||||
return data[i];
|
||||
}
|
||||
|
||||
|
@ -37,7 +36,7 @@ OrdSequence::operator[](int i) const
|
|||
according to the average, and then according to the first item. */
|
||||
|
||||
bool
|
||||
OrdSequence::operator<(const OrdSequence &s) const
|
||||
OrdSequence::operator<(const OrdSequence& s) const
|
||||
{
|
||||
double ta = average();
|
||||
double sa = s.average();
|
||||
|
@ -45,7 +44,7 @@ OrdSequence::operator<(const OrdSequence &s) const
|
|||
}
|
||||
|
||||
bool
|
||||
OrdSequence::operator==(const OrdSequence &s) const
|
||||
OrdSequence::operator==(const OrdSequence& s) const
|
||||
{
|
||||
if (length() != s.length())
|
||||
return false;
|
||||
|
@ -73,7 +72,7 @@ OrdSequence::add(int i)
|
|||
}
|
||||
|
||||
void
|
||||
OrdSequence::add(const OrdSequence &s)
|
||||
OrdSequence::add(const OrdSequence& s)
|
||||
{
|
||||
auto vit = s.data.begin();
|
||||
while (vit != s.data.end())
|
||||
|
@ -104,14 +103,13 @@ OrdSequence::average() const
|
|||
double res = 0;
|
||||
for (int i : data)
|
||||
res += i;
|
||||
TL_RAISE_IF(data.size() == 0,
|
||||
"Attempt to take average of empty class in OrdSequence::average");
|
||||
return res/data.size();
|
||||
TL_RAISE_IF(data.size() == 0, "Attempt to take average of empty class in OrdSequence::average");
|
||||
return res / data.size();
|
||||
}
|
||||
|
||||
/* Debug print. */
|
||||
void
|
||||
OrdSequence::print(const std::string &prefix) const
|
||||
OrdSequence::print(const std::string& prefix) const
|
||||
{
|
||||
std::cout << prefix;
|
||||
for (int i : data)
|
||||
|
@ -119,8 +117,7 @@ OrdSequence::print(const std::string &prefix) const
|
|||
std::cout << '\n';
|
||||
}
|
||||
|
||||
Equivalence::Equivalence(int num)
|
||||
: n(num)
|
||||
Equivalence::Equivalence(int num) : n(num)
|
||||
{
|
||||
for (int i = 0; i < num; i++)
|
||||
{
|
||||
|
@ -130,8 +127,7 @@ Equivalence::Equivalence(int num)
|
|||
}
|
||||
}
|
||||
|
||||
Equivalence::Equivalence(int num, [[maybe_unused]] const std::string &dummy)
|
||||
: n(num)
|
||||
Equivalence::Equivalence(int num, [[maybe_unused]] const std::string& dummy) : n(num)
|
||||
{
|
||||
OrdSequence s;
|
||||
for (int i = 0; i < num; i++)
|
||||
|
@ -141,9 +137,7 @@ Equivalence::Equivalence(int num, [[maybe_unused]] const std::string &dummy)
|
|||
|
||||
/* Copy constructor that also glues a given couple. */
|
||||
|
||||
Equivalence::Equivalence(const Equivalence &e, int i1, int i2)
|
||||
: n(e.n),
|
||||
classes(e.classes)
|
||||
Equivalence::Equivalence(const Equivalence& e, int i1, int i2) : n(e.n), classes(e.classes)
|
||||
{
|
||||
auto s1 = find(i1);
|
||||
auto s2 = find(i2);
|
||||
|
@ -158,7 +152,7 @@ Equivalence::Equivalence(const Equivalence &e, int i1, int i2)
|
|||
}
|
||||
|
||||
bool
|
||||
Equivalence::operator==(const Equivalence &e) const
|
||||
Equivalence::operator==(const Equivalence& e) const
|
||||
{
|
||||
if (!std::operator==(classes, e.classes))
|
||||
return false;
|
||||
|
@ -181,8 +175,7 @@ Equivalence::findHaving(int i) const
|
|||
return si;
|
||||
++si;
|
||||
}
|
||||
TL_RAISE_IF(si == classes.end(),
|
||||
"Couldn't find equivalence class in Equivalence::findHaving");
|
||||
TL_RAISE_IF(si == classes.end(), "Couldn't find equivalence class in Equivalence::findHaving");
|
||||
return si;
|
||||
}
|
||||
|
||||
|
@ -196,8 +189,7 @@ Equivalence::findHaving(int i)
|
|||
return si;
|
||||
++si;
|
||||
}
|
||||
TL_RAISE_IF(si == classes.end(),
|
||||
"Couldn't find equivalence class in Equivalence::findHaving");
|
||||
TL_RAISE_IF(si == classes.end(), "Couldn't find equivalence class in Equivalence::findHaving");
|
||||
return si;
|
||||
}
|
||||
|
||||
|
@ -213,8 +205,7 @@ Equivalence::find(int j) const
|
|||
++si;
|
||||
i++;
|
||||
}
|
||||
TL_RAISE_IF(si == classes.end(),
|
||||
"Couldn't find equivalence class in Equivalence::find");
|
||||
TL_RAISE_IF(si == classes.end(), "Couldn't find equivalence class in Equivalence::find");
|
||||
return si;
|
||||
}
|
||||
|
||||
|
@ -228,14 +219,13 @@ Equivalence::find(int j)
|
|||
++si;
|
||||
i++;
|
||||
}
|
||||
TL_RAISE_IF(si == classes.end(),
|
||||
"Couldn't find equivalence class in Equivalence::find");
|
||||
TL_RAISE_IF(si == classes.end(), "Couldn't find equivalence class in Equivalence::find");
|
||||
return si;
|
||||
}
|
||||
|
||||
/* Insert a new class yielding the ordering. */
|
||||
void
|
||||
Equivalence::insert(const OrdSequence &s)
|
||||
Equivalence::insert(const OrdSequence& s)
|
||||
{
|
||||
auto si = classes.begin();
|
||||
while (si != classes.end() && *si < s)
|
||||
|
@ -250,26 +240,23 @@ Equivalence::insert(const OrdSequence &s)
|
|||
number of classes from the beginning. */
|
||||
|
||||
void
|
||||
Equivalence::trace(IntSequence &out, int num) const
|
||||
Equivalence::trace(IntSequence& out, int num) const
|
||||
{
|
||||
int i = 0;
|
||||
int nc = 0;
|
||||
for (auto 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");
|
||||
TL_RAISE_IF(i >= out.size(), "Wrong size of output sequence in Equivalence::trace");
|
||||
out[i] = (*it)[j];
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Equivalence::trace(IntSequence &out, const Permutation &per) const
|
||||
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");
|
||||
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++)
|
||||
{
|
||||
|
@ -281,12 +268,10 @@ Equivalence::trace(IntSequence &out, const Permutation &per) const
|
|||
|
||||
/* Debug print. */
|
||||
void
|
||||
Equivalence::print(const std::string &prefix) const
|
||||
Equivalence::print(const std::string& prefix) const
|
||||
{
|
||||
int i = 0;
|
||||
for (auto it = classes.begin();
|
||||
it != classes.end();
|
||||
++it, i++)
|
||||
for (auto it = classes.begin(); it != classes.end(); ++it, i++)
|
||||
{
|
||||
std::cout << prefix << "class " << i << ": ";
|
||||
it->print("");
|
||||
|
@ -311,8 +296,7 @@ Equivalence::print(const std::string &prefix) const
|
|||
classes. Obviously, the list is decreasing in a number of classes
|
||||
(since it is constructed by gluing attempts). */
|
||||
|
||||
EquivalenceSet::EquivalenceSet(int num)
|
||||
: n(num)
|
||||
EquivalenceSet::EquivalenceSet(int num) : n(num)
|
||||
{
|
||||
std::list<Equivalence> added;
|
||||
Equivalence first(n);
|
||||
|
@ -338,7 +322,7 @@ EquivalenceSet::EquivalenceSet(int num)
|
|||
classes to more classes. hence the reverse order. */
|
||||
|
||||
bool
|
||||
EquivalenceSet::has(const Equivalence &e) const
|
||||
EquivalenceSet::has(const Equivalence& e) const
|
||||
{
|
||||
auto rit = equis.rbegin();
|
||||
while (rit != equis.rend() && *rit != e)
|
||||
|
@ -356,16 +340,14 @@ EquivalenceSet::has(const Equivalence &e) const
|
|||
be added. */
|
||||
|
||||
void
|
||||
EquivalenceSet::addParents(const Equivalence &e,
|
||||
std::list<Equivalence> &added)
|
||||
EquivalenceSet::addParents(const Equivalence& e, std::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++)
|
||||
if (Equivalence ns(e, i1, i2);
|
||||
!has(ns))
|
||||
for (int i2 = i1 + 1; i2 < e.numClasses(); i2++)
|
||||
if (Equivalence ns(e, i1, i2); !has(ns))
|
||||
{
|
||||
added.push_back(ns);
|
||||
equis.push_back(std::move(ns));
|
||||
|
@ -374,15 +356,12 @@ EquivalenceSet::addParents(const Equivalence &e,
|
|||
|
||||
/* Debug print. */
|
||||
void
|
||||
EquivalenceSet::print(const std::string &prefix) const
|
||||
EquivalenceSet::print(const std::string& prefix) const
|
||||
{
|
||||
int i = 0;
|
||||
for (auto it = equis.begin();
|
||||
it != equis.end();
|
||||
++it, i++)
|
||||
for (auto it = equis.begin(); it != equis.end(); ++it, i++)
|
||||
{
|
||||
std::cout << prefix << "equivalence " << i << ":(classes "
|
||||
<< it->numClasses() << ")\n";
|
||||
std::cout << prefix << "equivalence " << i << ":(classes " << it->numClasses() << ")\n";
|
||||
it->print(prefix + " ");
|
||||
}
|
||||
}
|
||||
|
@ -395,12 +374,12 @@ EquivalenceBundle::EquivalenceBundle(int nmax)
|
|||
}
|
||||
|
||||
/* Remember, that the first item is EquivalenceSet(1). */
|
||||
const EquivalenceSet &
|
||||
const EquivalenceSet&
|
||||
EquivalenceBundle::get(int n) const
|
||||
{
|
||||
TL_RAISE_IF(n > static_cast<int>(bundle.size()) || n < 1,
|
||||
"Equivalence set not found in EquivalenceBundle::get");
|
||||
return bundle[n-1];
|
||||
return bundle[n - 1];
|
||||
}
|
||||
|
||||
/* Get ‘curmax’ which is a maximum size in the bundle, and generate for
|
||||
|
@ -410,6 +389,6 @@ void
|
|||
EquivalenceBundle::generateUpTo(int nmax)
|
||||
{
|
||||
int curmax = bundle.size();
|
||||
for (int i = curmax+1; i <= nmax; i++)
|
||||
for (int i = curmax + 1; i <= nmax; i++)
|
||||
bundle.emplace_back(i);
|
||||
}
|
||||
|
|
|
@ -55,9 +55,9 @@
|
|||
|
||||
#include "int_sequence.hh"
|
||||
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
/* Here is the abstraction for an equivalence class. We implement it as
|
||||
vector<int>. We have a constructor for empty class, copy
|
||||
|
@ -69,14 +69,15 @@
|
|||
class OrdSequence
|
||||
{
|
||||
std::vector<int> data;
|
||||
|
||||
public:
|
||||
OrdSequence() : data()
|
||||
{
|
||||
}
|
||||
bool operator==(const OrdSequence &s) const;
|
||||
bool operator==(const OrdSequence& s) const;
|
||||
int operator[](int i) const;
|
||||
bool operator<(const OrdSequence &s) const;
|
||||
const std::vector<int> &
|
||||
bool operator<(const OrdSequence& s) const;
|
||||
const std::vector<int>&
|
||||
getData() const
|
||||
{
|
||||
return data;
|
||||
|
@ -87,9 +88,10 @@ public:
|
|||
return data.size();
|
||||
}
|
||||
void add(int i);
|
||||
void add(const OrdSequence &s);
|
||||
void add(const OrdSequence& s);
|
||||
bool has(int i) const;
|
||||
void print(const std::string &prefix) const;
|
||||
void print(const std::string& prefix) const;
|
||||
|
||||
private:
|
||||
double average() const;
|
||||
};
|
||||
|
@ -106,6 +108,7 @@ class Equivalence
|
|||
private:
|
||||
int n;
|
||||
std::list<OrdSequence> classes;
|
||||
|
||||
public:
|
||||
using const_seqit = std::list<OrdSequence>::const_iterator;
|
||||
using seqit = std::list<OrdSequence>::iterator;
|
||||
|
@ -113,13 +116,13 @@ public:
|
|||
// Constructs { {0}, {1}, …, {n-1} }
|
||||
explicit Equivalence(int num);
|
||||
// Constructs { {0,1,…,n-1 } }
|
||||
Equivalence(int num, const std::string &dummy);
|
||||
Equivalence(int num, const std::string& dummy);
|
||||
// Copy constructor plus gluing i1 and i2 in one class
|
||||
Equivalence(const Equivalence &e, int i1, int i2);
|
||||
Equivalence(const Equivalence& e, int i1, int i2);
|
||||
|
||||
bool operator==(const Equivalence &e) const;
|
||||
bool operator==(const Equivalence& e) const;
|
||||
bool
|
||||
operator!=(const Equivalence &e) const
|
||||
operator!=(const Equivalence& e) const
|
||||
{
|
||||
return !operator==(e);
|
||||
}
|
||||
|
@ -133,14 +136,14 @@ public:
|
|||
{
|
||||
return classes.size();
|
||||
}
|
||||
void trace(IntSequence &out, int n) const;
|
||||
void trace(IntSequence& out, int n) const;
|
||||
void
|
||||
trace(IntSequence &out) const
|
||||
trace(IntSequence& out) const
|
||||
{
|
||||
trace(out, numClasses());
|
||||
}
|
||||
void trace(IntSequence &out, const Permutation &per) const;
|
||||
void print(const std::string &prefix) const;
|
||||
void trace(IntSequence& out, const Permutation& per) const;
|
||||
void print(const std::string& prefix) const;
|
||||
seqit
|
||||
begin()
|
||||
{
|
||||
|
@ -163,6 +166,7 @@ public:
|
|||
}
|
||||
const_seqit find(int i) const;
|
||||
seqit find(int i);
|
||||
|
||||
protected:
|
||||
/* Here we have find methods. We can find an equivalence class having a
|
||||
given number or we can find an equivalence class of a given index within
|
||||
|
@ -172,8 +176,7 @@ protected:
|
|||
according to the class ordering. */
|
||||
const_seqit findHaving(int i) const;
|
||||
seqit findHaving(int i);
|
||||
void insert(const OrdSequence &s);
|
||||
|
||||
void insert(const OrdSequence& s);
|
||||
};
|
||||
|
||||
/* The EquivalenceSet is a list of equivalences. The unique
|
||||
|
@ -187,9 +190,10 @@ class EquivalenceSet
|
|||
{
|
||||
int n;
|
||||
std::list<Equivalence> equis;
|
||||
|
||||
public:
|
||||
explicit EquivalenceSet(int num);
|
||||
void print(const std::string &prefix) const;
|
||||
void print(const std::string& prefix) const;
|
||||
auto
|
||||
begin() const
|
||||
{
|
||||
|
@ -200,9 +204,10 @@ public:
|
|||
{
|
||||
return equis.end();
|
||||
}
|
||||
|
||||
private:
|
||||
bool has(const Equivalence &e) const;
|
||||
void addParents(const Equivalence &e, std::list<Equivalence> &added);
|
||||
bool has(const Equivalence& e) const;
|
||||
void addParents(const Equivalence& e, std::list<Equivalence>& added);
|
||||
};
|
||||
|
||||
/* The equivalence bundle class only encapsulates EquivalenceSet·s
|
||||
|
@ -215,9 +220,10 @@ private:
|
|||
class EquivalenceBundle
|
||||
{
|
||||
std::vector<EquivalenceSet> bundle;
|
||||
|
||||
public:
|
||||
explicit EquivalenceBundle(int nmax);
|
||||
const EquivalenceSet &get(int n) const;
|
||||
const EquivalenceSet& get(int n) const;
|
||||
void generateUpTo(int nmax);
|
||||
};
|
||||
|
||||
|
|
|
@ -25,22 +25,22 @@
|
|||
/* Here we construct the vector of new sizes of containers (before
|
||||
nc) and copy all remaining sizes behind nc. */
|
||||
|
||||
SizeRefinement::SizeRefinement(const IntSequence &s, int nc, int max)
|
||||
SizeRefinement::SizeRefinement(const IntSequence& s, int nc, int max)
|
||||
{
|
||||
new_nc = 0;
|
||||
for (int i = 0; i < nc; i++)
|
||||
{
|
||||
int nr = s[i]/max;
|
||||
int nr = s[i] / max;
|
||||
if (s[i] % max != 0)
|
||||
nr++;
|
||||
int ss = (nr > 0) ? static_cast<int>(round(static_cast<double>(s[i])/nr)) : 0;
|
||||
int ss = (nr > 0) ? static_cast<int>(round(static_cast<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);
|
||||
rsizes.push_back(s[i] - (nr - 1) * ss);
|
||||
ind_map.push_back(i);
|
||||
new_nc++;
|
||||
}
|
||||
|
|
|
@ -47,8 +47,8 @@
|
|||
|
||||
#include "stack_container.hh"
|
||||
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
/* This class splits the first nc elements of the given sequence s
|
||||
to a sequence not having items greater than given max. The remaining
|
||||
|
@ -61,8 +61,9 @@ class SizeRefinement
|
|||
std::vector<int> rsizes;
|
||||
std::vector<int> ind_map;
|
||||
int new_nc;
|
||||
|
||||
public:
|
||||
SizeRefinement(const IntSequence &s, int nc, int max);
|
||||
SizeRefinement(const IntSequence& s, int nc, int max);
|
||||
int
|
||||
getRefSize(int i) const
|
||||
{
|
||||
|
@ -98,7 +99,8 @@ protected:
|
|||
using _Ctype = typename StackContainerInterface<_Ttype>::_Ctype;
|
||||
using itype = typename StackContainerInterface<_Ttype>::itype;
|
||||
std::vector<std::unique_ptr<_Ctype>> ref_conts;
|
||||
const _Stype &stack_cont;
|
||||
const _Stype& stack_cont;
|
||||
|
||||
public:
|
||||
/* Here we construct the SizeRefinement and allocate space for the
|
||||
refined containers. Then, the containers are created and put to
|
||||
|
@ -114,11 +116,10 @@ public:
|
|||
StackContainer has only a const method to return a member of
|
||||
conts. */
|
||||
|
||||
FineContainer(const _Stype &sc, int max)
|
||||
: SizeRefinement(sc.getStackSizes(), sc.numConts(), max),
|
||||
StackContainer<_Ttype>(numRefinements(), getNC()),
|
||||
ref_conts(getNC()),
|
||||
stack_cont(sc)
|
||||
FineContainer(const _Stype& sc, int max) :
|
||||
SizeRefinement(sc.getStackSizes(), sc.numConts(), max), StackContainer<_Ttype>(
|
||||
numRefinements(), getNC()),
|
||||
ref_conts(getNC()), stack_cont(sc)
|
||||
{
|
||||
for (int i = 0; i < numRefinements(); i++)
|
||||
_Stype::stack_sizes[i] = getRefSize(i);
|
||||
|
@ -134,26 +135,25 @@ public:
|
|||
last_row = 0;
|
||||
}
|
||||
ref_conts[i] = std::make_unique<_Ctype>(last_row, _Stype::stack_sizes[i],
|
||||
const_cast<_Ctype &>(stack_cont.getCont(last_cont)));
|
||||
const_cast<_Ctype&>(stack_cont.getCont(last_cont)));
|
||||
_Stype::conts[i] = ref_conts[i].get();
|
||||
last_row += _Stype::stack_sizes[i];
|
||||
}
|
||||
}
|
||||
|
||||
itype
|
||||
getType(int i, const Symmetry &s) const override
|
||||
getType(int i, const Symmetry& s) const override
|
||||
{
|
||||
return stack_cont.getType(getOldIndex(i), s);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/* Here is FineContainer specialization for folded tensors. */
|
||||
class FoldedFineContainer : public FineContainer<FGSTensor>, public FoldedStackContainer
|
||||
{
|
||||
public:
|
||||
FoldedFineContainer(const StackContainer<FGSTensor> &sc, int max)
|
||||
: FineContainer<FGSTensor>(sc, max)
|
||||
FoldedFineContainer(const StackContainer<FGSTensor>& sc, int max) :
|
||||
FineContainer<FGSTensor>(sc, max)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
@ -162,8 +162,8 @@ public:
|
|||
class UnfoldedFineContainer : public FineContainer<UGSTensor>, public UnfoldedStackContainer
|
||||
{
|
||||
public:
|
||||
UnfoldedFineContainer(const StackContainer<UGSTensor> &sc, int max)
|
||||
: FineContainer<UGSTensor>(sc, max)
|
||||
UnfoldedFineContainer(const StackContainer<UGSTensor>& sc, int max) :
|
||||
FineContainer<UGSTensor>(sc, max)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
|
|
@ -20,10 +20,10 @@
|
|||
|
||||
#include "fs_tensor.hh"
|
||||
#include "gs_tensor.hh"
|
||||
#include "sparse_tensor.hh"
|
||||
#include "rfs_tensor.hh"
|
||||
#include "tl_exception.hh"
|
||||
#include "pascal_triangle.hh"
|
||||
#include "rfs_tensor.hh"
|
||||
#include "sparse_tensor.hh"
|
||||
#include "tl_exception.hh"
|
||||
|
||||
/* This constructs a fully symmetric tensor as given by the contraction:
|
||||
|
||||
|
@ -34,13 +34,12 @@
|
|||
coordinates obtaining a column of tensor [t]. The column is multiplied
|
||||
by an appropriate item of x and added to the column of [g] tensor. */
|
||||
|
||||
FFSTensor::FFSTensor(const FFSTensor &t, const ConstVector &x)
|
||||
: FTensor(indor::along_col, IntSequence(t.dimen()-1, t.nvar()),
|
||||
t.nrows(), calcMaxOffset(t.nvar(), t.dimen()-1), t.dimen()-1),
|
||||
FFSTensor::FFSTensor(const FFSTensor& t, const ConstVector& x) :
|
||||
FTensor(indor::along_col, IntSequence(t.dimen() - 1, t.nvar()), t.nrows(),
|
||||
calcMaxOffset(t.nvar(), t.dimen() - 1), t.dimen() - 1),
|
||||
nv(t.nvar())
|
||||
{
|
||||
TL_RAISE_IF(t.dimen() < 1,
|
||||
"Wrong dimension for tensor contraction of FFSTensor");
|
||||
TL_RAISE_IF(t.dimen() < 1, "Wrong dimension for tensor contraction of FFSTensor");
|
||||
TL_RAISE_IF(t.nvar() != x.length(),
|
||||
"Wrong number of variables for tensor contraction of FFSTensor");
|
||||
|
||||
|
@ -73,13 +72,13 @@ FFSTensor::calcMaxOffset(int nvar, int d)
|
|||
|
||||
/* The conversion from sparse tensor is clear. We go through all the
|
||||
tensor and write to the dense what is found. */
|
||||
FFSTensor::FFSTensor(const FSSparseTensor &t)
|
||||
: FTensor(indor::along_col, IntSequence(t.dimen(), t.nvar()),
|
||||
t.nrows(), calcMaxOffset(t.nvar(), t.dimen()), t.dimen()),
|
||||
FFSTensor::FFSTensor(const FSSparseTensor& t) :
|
||||
FTensor(indor::along_col, IntSequence(t.dimen(), t.nvar()), t.nrows(),
|
||||
calcMaxOffset(t.nvar(), t.dimen()), t.dimen()),
|
||||
nv(t.nvar())
|
||||
{
|
||||
zeros();
|
||||
for (const auto &it : t.getMap())
|
||||
for (const auto& it : t.getMap())
|
||||
{
|
||||
index ind(*this, it.first);
|
||||
get(it.second.first, *ind) = it.second.second;
|
||||
|
@ -91,9 +90,9 @@ FFSTensor::FFSTensor(const FSSparseTensor &t)
|
|||
(this), make an index of the unfolded vector from coordinates, and
|
||||
copy the column. */
|
||||
|
||||
FFSTensor::FFSTensor(const UFSTensor &ut)
|
||||
: FTensor(indor::along_col, IntSequence(ut.dimen(), ut.nvar()),
|
||||
ut.nrows(), calcMaxOffset(ut.nvar(), ut.dimen()), ut.dimen()),
|
||||
FFSTensor::FFSTensor(const UFSTensor& ut) :
|
||||
FTensor(indor::along_col, IntSequence(ut.dimen(), ut.nvar()), ut.nrows(),
|
||||
calcMaxOffset(ut.nvar(), ut.dimen()), ut.dimen()),
|
||||
nv(ut.nvar())
|
||||
{
|
||||
for (index in = begin(); in != end(); ++in)
|
||||
|
@ -116,10 +115,9 @@ FFSTensor::unfold() const
|
|||
which corresponds to monotonizeing the integer sequence. */
|
||||
|
||||
void
|
||||
FFSTensor::increment(IntSequence &v) const
|
||||
FFSTensor::increment(IntSequence& v) const
|
||||
{
|
||||
TL_RAISE_IF(v.size() != dimen(),
|
||||
"Wrong input/output vector size in FFSTensor::increment");
|
||||
TL_RAISE_IF(v.size() != dimen(), "Wrong input/output vector size in FFSTensor::increment");
|
||||
|
||||
UTensor::increment(v, nv);
|
||||
v.monotone();
|
||||
|
@ -128,19 +126,17 @@ FFSTensor::increment(IntSequence &v) const
|
|||
/* Decrement calls static FTensor::decrement(). */
|
||||
|
||||
void
|
||||
FFSTensor::decrement(IntSequence &v) const
|
||||
FFSTensor::decrement(IntSequence& v) const
|
||||
{
|
||||
TL_RAISE_IF(v.size() != dimen(),
|
||||
"Wrong input/output vector size in FFSTensor::decrement");
|
||||
TL_RAISE_IF(v.size() != dimen(), "Wrong input/output vector size in FFSTensor::decrement");
|
||||
|
||||
FTensor::decrement(v, nv);
|
||||
}
|
||||
|
||||
int
|
||||
FFSTensor::getOffset(const IntSequence &v) const
|
||||
FFSTensor::getOffset(const IntSequence& v) const
|
||||
{
|
||||
TL_RAISE_IF(v.size() != dimen(),
|
||||
"Wrong input vector size in FFSTensor::getOffset");
|
||||
TL_RAISE_IF(v.size() != dimen(), "Wrong input vector size in FFSTensor::getOffset");
|
||||
|
||||
return FTensor::getOffset(v, nv);
|
||||
}
|
||||
|
@ -156,18 +152,16 @@ FFSTensor::getOffset(const IntSequence &v) const
|
|||
through the columns in general symmetry, adding the shift and sorting. */
|
||||
|
||||
void
|
||||
FFSTensor::addSubTensor(const FGSTensor &t)
|
||||
FFSTensor::addSubTensor(const FGSTensor& t)
|
||||
{
|
||||
TL_RAISE_IF(dimen() != t.getDims().dimen(),
|
||||
"Wrong dimensions for FFSTensor::addSubTensor");
|
||||
TL_RAISE_IF(nvar() != t.getDims().getNVS().sum(),
|
||||
"Wrong nvs for FFSTensor::addSubTensor");
|
||||
TL_RAISE_IF(dimen() != t.getDims().dimen(), "Wrong dimensions for FFSTensor::addSubTensor");
|
||||
TL_RAISE_IF(nvar() != t.getDims().getNVS().sum(), "Wrong nvs for FFSTensor::addSubTensor");
|
||||
|
||||
// set shift for addSubTensor()
|
||||
/* Code shared with UFSTensor::addSubTensor() */
|
||||
IntSequence shift_pre(t.getSym().num(), 0);
|
||||
for (int i = 1; i < t.getSym().num(); i++)
|
||||
shift_pre[i] = shift_pre[i-1]+t.getDims().getNVS()[i-1];
|
||||
shift_pre[i] = shift_pre[i - 1] + t.getDims().getNVS()[i - 1];
|
||||
IntSequence shift(shift_pre.unfold(t.getSym()));
|
||||
|
||||
for (Tensor::index ind = t.begin(); ind != t.end(); ++ind)
|
||||
|
@ -185,13 +179,12 @@ FFSTensor::addSubTensor(const FGSTensor &t)
|
|||
We do not add column by column but we do it by submatrices due to
|
||||
regularity of the unfolded tensor. */
|
||||
|
||||
UFSTensor::UFSTensor(const UFSTensor &t, const ConstVector &x)
|
||||
: UTensor(indor::along_col, IntSequence(t.dimen()-1, t.nvar()),
|
||||
t.nrows(), calcMaxOffset(t.nvar(), t.dimen()-1), t.dimen()-1),
|
||||
UFSTensor::UFSTensor(const UFSTensor& t, const ConstVector& x) :
|
||||
UTensor(indor::along_col, IntSequence(t.dimen() - 1, t.nvar()), t.nrows(),
|
||||
calcMaxOffset(t.nvar(), t.dimen() - 1), t.dimen() - 1),
|
||||
nv(t.nvar())
|
||||
{
|
||||
TL_RAISE_IF(t.dimen() < 1,
|
||||
"Wrong dimension for tensor contraction of UFSTensor");
|
||||
TL_RAISE_IF(t.dimen() < 1, "Wrong dimension for tensor contraction of UFSTensor");
|
||||
TL_RAISE_IF(t.nvar() != x.length(),
|
||||
"Wrong number of variables for tensor contraction of UFSTensor");
|
||||
|
||||
|
@ -199,8 +192,8 @@ UFSTensor::UFSTensor(const UFSTensor &t, const ConstVector &x)
|
|||
|
||||
for (int i = 0; i < ncols(); i++)
|
||||
{
|
||||
ConstTwoDMatrix tpart(t, i *nvar(), nvar());
|
||||
Vector outcol{getCol(i)};
|
||||
ConstTwoDMatrix tpart(t, i * nvar(), nvar());
|
||||
Vector outcol {getCol(i)};
|
||||
tpart.multaVec(outcol, x);
|
||||
}
|
||||
}
|
||||
|
@ -208,9 +201,9 @@ UFSTensor::UFSTensor(const UFSTensor &t, const ConstVector &x)
|
|||
/* Here we convert folded full symmetry tensor to unfolded. We copy all
|
||||
columns of folded tensor, and then call unfoldData(). */
|
||||
|
||||
UFSTensor::UFSTensor(const FFSTensor &ft)
|
||||
: UTensor(indor::along_col, IntSequence(ft.dimen(), ft.nvar()),
|
||||
ft.nrows(), calcMaxOffset(ft.nvar(), ft.dimen()), ft.dimen()),
|
||||
UFSTensor::UFSTensor(const FFSTensor& ft) :
|
||||
UTensor(indor::along_col, IntSequence(ft.dimen(), ft.nvar()), ft.nrows(),
|
||||
calcMaxOffset(ft.nvar(), ft.dimen()), ft.dimen()),
|
||||
nv(ft.nvar())
|
||||
{
|
||||
for (index src = ft.begin(); src != ft.end(); ++src)
|
||||
|
@ -230,28 +223,25 @@ UFSTensor::fold() const
|
|||
// UFSTensor increment and decrement
|
||||
/* Here we just call UTensor respective static methods. */
|
||||
void
|
||||
UFSTensor::increment(IntSequence &v) const
|
||||
UFSTensor::increment(IntSequence& v) const
|
||||
{
|
||||
TL_RAISE_IF(v.size() != dimen(),
|
||||
"Wrong input/output vector size in UFSTensor::increment");
|
||||
TL_RAISE_IF(v.size() != dimen(), "Wrong input/output vector size in UFSTensor::increment");
|
||||
|
||||
UTensor::increment(v, nv);
|
||||
}
|
||||
|
||||
void
|
||||
UFSTensor::decrement(IntSequence &v) const
|
||||
UFSTensor::decrement(IntSequence& v) const
|
||||
{
|
||||
TL_RAISE_IF(v.size() != dimen(),
|
||||
"Wrong input/output vector size in UFSTensor::decrement");
|
||||
TL_RAISE_IF(v.size() != dimen(), "Wrong input/output vector size in UFSTensor::decrement");
|
||||
|
||||
UTensor::decrement(v, nv);
|
||||
}
|
||||
|
||||
int
|
||||
UFSTensor::getOffset(const IntSequence &v) const
|
||||
UFSTensor::getOffset(const IntSequence& v) const
|
||||
{
|
||||
TL_RAISE_IF(v.size() != dimen(),
|
||||
"Wrong input vector size in UFSTensor::getOffset");
|
||||
TL_RAISE_IF(v.size() != dimen(), "Wrong input vector size in UFSTensor::getOffset");
|
||||
|
||||
return UTensor::getOffset(v, nv);
|
||||
}
|
||||
|
@ -263,18 +253,16 @@ UFSTensor::getOffset(const IntSequence &v) const
|
|||
tensor, and add it. */
|
||||
|
||||
void
|
||||
UFSTensor::addSubTensor(const UGSTensor &t)
|
||||
UFSTensor::addSubTensor(const UGSTensor& t)
|
||||
{
|
||||
TL_RAISE_IF(dimen() != t.getDims().dimen(),
|
||||
"Wrong dimensions for UFSTensor::addSubTensor");
|
||||
TL_RAISE_IF(nvar() != t.getDims().getNVS().sum(),
|
||||
"Wrong nvs for UFSTensor::addSubTensor");
|
||||
TL_RAISE_IF(dimen() != t.getDims().dimen(), "Wrong dimensions for UFSTensor::addSubTensor");
|
||||
TL_RAISE_IF(nvar() != t.getDims().getNVS().sum(), "Wrong nvs for UFSTensor::addSubTensor");
|
||||
|
||||
// set shift for addSubTensor()
|
||||
/* Code shared with FFSTensor::addSubTensor() */
|
||||
IntSequence shift_pre(t.getSym().num(), 0);
|
||||
for (int i = 1; i < t.getSym().num(); i++)
|
||||
shift_pre[i] = shift_pre[i-1]+t.getDims().getNVS()[i-1];
|
||||
shift_pre[i] = shift_pre[i - 1] + t.getDims().getNVS()[i - 1];
|
||||
IntSequence shift(shift_pre.unfold(t.getSym()));
|
||||
|
||||
for (Tensor::index tar = begin(); tar != end(); ++tar)
|
||||
|
|
|
@ -27,9 +27,9 @@
|
|||
#ifndef FS_TENSOR_H
|
||||
#define FS_TENSOR_H
|
||||
|
||||
#include "tensor.hh"
|
||||
#include "symmetry.hh"
|
||||
#include "int_power.hh"
|
||||
#include "symmetry.hh"
|
||||
#include "tensor.hh"
|
||||
|
||||
class FGSTensor;
|
||||
class UGSTensor;
|
||||
|
@ -59,14 +59,13 @@ class UFSTensor;
|
|||
class FFSTensor : public FTensor
|
||||
{
|
||||
int nv;
|
||||
|
||||
public:
|
||||
/* Constructs given the number of rows (explicit since the tensor is
|
||||
column-oriented), the number of variables in each dimension, and the
|
||||
number of dimensions */
|
||||
FFSTensor(int r, int nvar, int d)
|
||||
: FTensor(indor::along_col, IntSequence(d, nvar),
|
||||
r, calcMaxOffset(nvar, d), d),
|
||||
nv(nvar)
|
||||
FFSTensor(int r, int nvar, int d) :
|
||||
FTensor(indor::along_col, IntSequence(d, nvar), r, calcMaxOffset(nvar, d), d), nv(nvar)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -76,35 +75,34 @@ public:
|
|||
[g_yⁿ]_α₁…αₙ = [t_yⁿ⁺¹]_α₁…αₙβ [x]^β
|
||||
|
||||
See the implementation for details. */
|
||||
FFSTensor(const FFSTensor &t, const ConstVector &x);
|
||||
FFSTensor(const FFSTensor& t, const ConstVector& x);
|
||||
|
||||
/* Converts from sparse tensor (which is fully symmetric and folded by
|
||||
nature). */
|
||||
explicit FFSTensor(const FSSparseTensor &t);
|
||||
explicit FFSTensor(const FSSparseTensor& t);
|
||||
|
||||
FFSTensor(const FFSTensor &) = default;
|
||||
FFSTensor(FFSTensor &&) = default;
|
||||
FFSTensor(const FFSTensor&) = default;
|
||||
FFSTensor(FFSTensor&&) = default;
|
||||
|
||||
// Constructs from unfolded fully symmetric
|
||||
explicit FFSTensor(const UFSTensor &ut);
|
||||
explicit FFSTensor(const UFSTensor& ut);
|
||||
|
||||
// Constructs a subtensor of selected rows
|
||||
FFSTensor(int first_row, int num, FFSTensor &t)
|
||||
: FTensor(first_row, num, t), nv(t.nv)
|
||||
FFSTensor(int first_row, int num, FFSTensor& t) : FTensor(first_row, num, t), nv(t.nv)
|
||||
{
|
||||
}
|
||||
|
||||
void increment(IntSequence &v) const override;
|
||||
void decrement(IntSequence &v) const override;
|
||||
void increment(IntSequence& v) const override;
|
||||
void decrement(IntSequence& v) const override;
|
||||
std::unique_ptr<UTensor> unfold() const override;
|
||||
Symmetry
|
||||
getSym() const
|
||||
{
|
||||
return Symmetry{dimen()};
|
||||
return Symmetry {dimen()};
|
||||
}
|
||||
|
||||
int getOffset(const IntSequence &v) const override;
|
||||
void addSubTensor(const FGSTensor &t);
|
||||
int getOffset(const IntSequence& v) const override;
|
||||
void addSubTensor(const FGSTensor& t);
|
||||
int
|
||||
nvar() const
|
||||
{
|
||||
|
@ -122,33 +120,31 @@ public:
|
|||
class UFSTensor : public UTensor
|
||||
{
|
||||
int nv;
|
||||
|
||||
public:
|
||||
UFSTensor(int r, int nvar, int d)
|
||||
: UTensor(indor::along_col, IntSequence(d, nvar),
|
||||
r, calcMaxOffset(nvar, d), d),
|
||||
nv(nvar)
|
||||
UFSTensor(int r, int nvar, int d) :
|
||||
UTensor(indor::along_col, IntSequence(d, nvar), r, calcMaxOffset(nvar, d), d), nv(nvar)
|
||||
{
|
||||
}
|
||||
UFSTensor(const UFSTensor &t, const ConstVector &x);
|
||||
UFSTensor(const UFSTensor &) = default;
|
||||
UFSTensor(UFSTensor &&) = default;
|
||||
explicit UFSTensor(const FFSTensor &ft);
|
||||
UFSTensor(int first_row, int num, UFSTensor &t)
|
||||
: UTensor(first_row, num, t), nv(t.nv)
|
||||
UFSTensor(const UFSTensor& t, const ConstVector& x);
|
||||
UFSTensor(const UFSTensor&) = default;
|
||||
UFSTensor(UFSTensor&&) = default;
|
||||
explicit UFSTensor(const FFSTensor& ft);
|
||||
UFSTensor(int first_row, int num, UFSTensor& t) : UTensor(first_row, num, t), nv(t.nv)
|
||||
{
|
||||
}
|
||||
|
||||
void increment(IntSequence &v) const override;
|
||||
void decrement(IntSequence &v) const override;
|
||||
void increment(IntSequence& v) const override;
|
||||
void decrement(IntSequence& v) const override;
|
||||
std::unique_ptr<FTensor> fold() const override;
|
||||
Symmetry
|
||||
getSym() const
|
||||
{
|
||||
return Symmetry{dimen()};
|
||||
return Symmetry {dimen()};
|
||||
}
|
||||
|
||||
int getOffset(const IntSequence &v) const override;
|
||||
void addSubTensor(const UGSTensor &t);
|
||||
int getOffset(const IntSequence& v) const override;
|
||||
void addSubTensor(const UGSTensor& t);
|
||||
int
|
||||
nvar() const
|
||||
{
|
||||
|
@ -159,6 +155,7 @@ public:
|
|||
{
|
||||
return power(nvar, d);
|
||||
}
|
||||
|
||||
private:
|
||||
void unfoldData();
|
||||
};
|
||||
|
|
|
@ -19,10 +19,10 @@
|
|||
*/
|
||||
|
||||
#include "gs_tensor.hh"
|
||||
#include "sparse_tensor.hh"
|
||||
#include "tl_exception.hh"
|
||||
#include "kron_prod.hh"
|
||||
#include "pascal_triangle.hh"
|
||||
#include "sparse_tensor.hh"
|
||||
#include "tl_exception.hh"
|
||||
|
||||
/* Constructor used for slicing fully symmetric tensor. It constructs the
|
||||
dimensions from the partitioning of variables of fully symmetric tensor. Let
|
||||
|
@ -35,14 +35,11 @@
|
|||
sizes of partitions (n_a,n_b,n_c,n_d) as IntSequence, and indices of
|
||||
picked partitions, in our case (1,1,3,3,3), as IntSequence. */
|
||||
|
||||
TensorDimens::TensorDimens(const IntSequence &ss, const IntSequence &coor)
|
||||
: nvs(ss),
|
||||
sym(ss.size()),
|
||||
nvmax(coor.size(), 0)
|
||||
TensorDimens::TensorDimens(const IntSequence& ss, const IntSequence& coor) :
|
||||
nvs(ss), sym(ss.size()), nvmax(coor.size(), 0)
|
||||
{
|
||||
TL_RAISE_IF(!coor.isSorted(),
|
||||
"Coordinates not sorted in TensorDimens slicing constructor");
|
||||
TL_RAISE_IF(coor[0] < 0 || coor[coor.size()-1] >= ss.size(),
|
||||
TL_RAISE_IF(!coor.isSorted(), "Coordinates not sorted in TensorDimens slicing constructor");
|
||||
TL_RAISE_IF(coor[0] < 0 || coor[coor.size() - 1] >= ss.size(),
|
||||
"A coordinate out of stack range in TensorDimens slicing constructor");
|
||||
|
||||
for (int i = 0; i < coor.size(); i++)
|
||||
|
@ -71,7 +68,7 @@ TensorDimens::calcFoldMaxOffset() const
|
|||
if (nvs[i] == 0 && sym[i] > 0)
|
||||
return 0;
|
||||
if (sym[i] > 0)
|
||||
res *= PascalTriangle::noverk(nvs[i]+sym[i]-1, sym[i]);
|
||||
res *= PascalTriangle::noverk(nvs[i] + sym[i] - 1, sym[i]);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
@ -97,26 +94,23 @@ TensorDimens::calcFoldMaxOffset() const
|
|||
product in ‘pow’. */
|
||||
|
||||
int
|
||||
TensorDimens::calcFoldOffset(const IntSequence &v) const
|
||||
TensorDimens::calcFoldOffset(const IntSequence& v) const
|
||||
{
|
||||
TL_RAISE_IF(v.size() != dimen(),
|
||||
"Wrong input vector size in TensorDimens::getFoldOffset");
|
||||
TL_RAISE_IF(v.size() != dimen(), "Wrong input vector size in TensorDimens::getFoldOffset");
|
||||
|
||||
int res = 0;
|
||||
int pow = 1;
|
||||
int blstart = v.size();
|
||||
for (int ibl = getSym().num()-1; ibl >= 0; ibl--)
|
||||
if (int bldim { getSym()[ibl] };
|
||||
bldim > 0)
|
||||
for (int ibl = getSym().num() - 1; ibl >= 0; ibl--)
|
||||
if (int bldim {getSym()[ibl]}; bldim > 0)
|
||||
{
|
||||
blstart -= bldim;
|
||||
int blnvar = getNVX(blstart);
|
||||
IntSequence subv(v, blstart, blstart+bldim);
|
||||
res += FTensor::getOffset(subv, blnvar)*pow;
|
||||
IntSequence subv(v, blstart, blstart + bldim);
|
||||
res += FTensor::getOffset(subv, blnvar) * pow;
|
||||
pow *= FFSTensor::calcMaxOffset(blnvar, bldim);
|
||||
}
|
||||
TL_RAISE_IF(blstart != 0,
|
||||
"Error in tracing symmetry in TensorDimens::getFoldOffset");
|
||||
TL_RAISE_IF(blstart != 0, "Error in tracing symmetry in TensorDimens::getFoldOffset");
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -138,17 +132,17 @@ TensorDimens::calcFoldOffset(const IntSequence &v) const
|
|||
index (fully symmetric within that partition). */
|
||||
|
||||
void
|
||||
TensorDimens::decrement(IntSequence &v) const
|
||||
TensorDimens::decrement(IntSequence& v) const
|
||||
{
|
||||
TL_RAISE_IF(getNVX().size() != v.size(),
|
||||
"Wrong size of input/output sequence in TensorDimens::decrement");
|
||||
|
||||
int iblock = getSym().num()-1;
|
||||
int iblock = getSym().num() - 1;
|
||||
int block_last = v.size();
|
||||
int block_first = block_last-getSym()[iblock];
|
||||
int block_first = block_last - getSym()[iblock];
|
||||
|
||||
// check for zero trailing blocks
|
||||
while (iblock > 0 && v[block_last-1] == 0)
|
||||
while (iblock > 0 && v[block_last - 1] == 0)
|
||||
{
|
||||
for (int i = block_first; i < block_last; i++)
|
||||
v[i] = getNVX(i); // equivalent to nvs[iblock]
|
||||
|
@ -165,9 +159,9 @@ TensorDimens::decrement(IntSequence &v) const
|
|||
// FGSTensor conversion from UGSTensor
|
||||
/* Here we go through columns of folded, calculate column of unfolded,
|
||||
and copy data. */
|
||||
FGSTensor::FGSTensor(const UGSTensor &ut)
|
||||
: FTensor(indor::along_col, ut.tdims.getNVX(), ut.nrows(),
|
||||
ut.tdims.calcFoldMaxOffset(), ut.dimen()),
|
||||
FGSTensor::FGSTensor(const UGSTensor& ut) :
|
||||
FTensor(indor::along_col, ut.tdims.getNVX(), ut.nrows(), ut.tdims.calcFoldMaxOffset(),
|
||||
ut.dimen()),
|
||||
tdims(ut.tdims)
|
||||
{
|
||||
for (index ti = begin(); ti != end(); ++ti)
|
||||
|
@ -186,10 +180,9 @@ FGSTensor::FGSTensor(const UGSTensor &ut)
|
|||
in Cartesian ordering (this corresponds to belonging to the
|
||||
slices). If it belongs, then we subtract the lower bound ‘lb’ to
|
||||
obtain coordinates in the ‘this’ tensor and we copy the item. */
|
||||
FGSTensor::FGSTensor(const FSSparseTensor &t, const IntSequence &ss,
|
||||
const IntSequence &coor, TensorDimens td)
|
||||
: FTensor(indor::along_col, td.getNVX(), t.nrows(),
|
||||
td.calcFoldMaxOffset(), td.dimen()),
|
||||
FGSTensor::FGSTensor(const FSSparseTensor& t, const IntSequence& ss, const IntSequence& coor,
|
||||
TensorDimens td) :
|
||||
FTensor(indor::along_col, td.getNVX(), t.nrows(), td.calcFoldMaxOffset(), td.dimen()),
|
||||
tdims(std::move(td))
|
||||
{
|
||||
// set ‘lb’ and ‘ub’ to lower and upper bounds of indices
|
||||
|
@ -201,7 +194,7 @@ FGSTensor::FGSTensor(const FSSparseTensor &t, const IntSequence &ss,
|
|||
slice. */
|
||||
IntSequence s_offsets(ss.size(), 0);
|
||||
for (int i = 1; i < ss.size(); i++)
|
||||
s_offsets[i] = s_offsets[i-1] + ss[i-1];
|
||||
s_offsets[i] = s_offsets[i - 1] + ss[i - 1];
|
||||
|
||||
IntSequence lb(coor.size());
|
||||
IntSequence ub(coor.size());
|
||||
|
@ -228,10 +221,9 @@ FGSTensor::FGSTensor(const FSSparseTensor &t, const IntSequence &ss,
|
|||
|
||||
// FGSTensor slicing from FFSTensor
|
||||
/* The code is similar to FGSTensor slicing from FSSparseTensor. */
|
||||
FGSTensor::FGSTensor(const FFSTensor &t, const IntSequence &ss,
|
||||
const IntSequence &coor, TensorDimens td)
|
||||
: FTensor(indor::along_col, td.getNVX(), t.nrows(),
|
||||
td.calcFoldMaxOffset(), td.dimen()),
|
||||
FGSTensor::FGSTensor(const FFSTensor& t, const IntSequence& ss, const IntSequence& coor,
|
||||
TensorDimens td) :
|
||||
FTensor(indor::along_col, td.getNVX(), t.nrows(), td.calcFoldMaxOffset(), td.dimen()),
|
||||
tdims(std::move(td))
|
||||
{
|
||||
if (ncols() == 0)
|
||||
|
@ -241,7 +233,7 @@ FGSTensor::FGSTensor(const FFSTensor &t, const IntSequence &ss,
|
|||
/* Same code as in the previous converting constructor */
|
||||
IntSequence s_offsets(ss.size(), 0);
|
||||
for (int i = 1; i < ss.size(); i++)
|
||||
s_offsets[i] = s_offsets[i-1] + ss[i-1];
|
||||
s_offsets[i] = s_offsets[i - 1] + ss[i - 1];
|
||||
|
||||
IntSequence lb(coor.size());
|
||||
IntSequence ub(coor.size());
|
||||
|
@ -268,12 +260,13 @@ FGSTensor::FGSTensor(const FFSTensor &t, const IntSequence &ss,
|
|||
}
|
||||
|
||||
// FGSTensor conversion from GSSparseTensor
|
||||
FGSTensor::FGSTensor(const GSSparseTensor &t)
|
||||
: FTensor(indor::along_col, t.getDims().getNVX(), t.nrows(),
|
||||
t.getDims().calcFoldMaxOffset(), t.dimen()), tdims(t.getDims())
|
||||
FGSTensor::FGSTensor(const GSSparseTensor& t) :
|
||||
FTensor(indor::along_col, t.getDims().getNVX(), t.nrows(), t.getDims().calcFoldMaxOffset(),
|
||||
t.dimen()),
|
||||
tdims(t.getDims())
|
||||
{
|
||||
zeros();
|
||||
for (const auto &it : t.getMap())
|
||||
for (const auto& it : t.getMap())
|
||||
{
|
||||
index ind(*this, it.first);
|
||||
get(it.second.first, *ind) = it.second.second;
|
||||
|
@ -285,10 +278,9 @@ FGSTensor::FGSTensor(const GSSparseTensor &t)
|
|||
IntSequence::pmonotone(). */
|
||||
|
||||
void
|
||||
FGSTensor::increment(IntSequence &v) const
|
||||
FGSTensor::increment(IntSequence& v) const
|
||||
{
|
||||
TL_RAISE_IF(v.size() != dimen(),
|
||||
"Wrong input/output vector size in FGSTensor::increment");
|
||||
TL_RAISE_IF(v.size() != dimen(), "Wrong input/output vector size in FGSTensor::increment");
|
||||
|
||||
UTensor::increment(v, tdims.getNVX());
|
||||
v.pmonotone(tdims.getSym());
|
||||
|
@ -322,11 +314,9 @@ FGSTensor::unfold() const
|
|||
starting from 0. */
|
||||
|
||||
void
|
||||
FGSTensor::contractAndAdd(int i, FGSTensor &out,
|
||||
const FRSingleTensor &col) const
|
||||
FGSTensor::contractAndAdd(int i, FGSTensor& out, const FRSingleTensor& col) const
|
||||
{
|
||||
TL_RAISE_IF(i < 0 || i >= getSym().num(),
|
||||
"Wrong index for FGSTensor::contractAndAdd");
|
||||
TL_RAISE_IF(i < 0 || i >= getSym().num(), "Wrong index for FGSTensor::contractAndAdd");
|
||||
|
||||
TL_RAISE_IF(getSym()[i] != col.dimen() || tdims.getNVS()[i] != col.nvar(),
|
||||
"Wrong dimensions for FGSTensor::contractAndAdd");
|
||||
|
@ -362,9 +352,9 @@ FGSTensor::contractAndAdd(int i, FGSTensor &out,
|
|||
of the unfolded tensor and copy the data to the unfolded. Then we
|
||||
unfold data within the unfolded tensor. */
|
||||
|
||||
UGSTensor::UGSTensor(const FGSTensor &ft)
|
||||
: UTensor(indor::along_col, ft.tdims.getNVX(), ft.nrows(),
|
||||
ft.tdims.calcUnfoldMaxOffset(), ft.dimen()),
|
||||
UGSTensor::UGSTensor(const FGSTensor& ft) :
|
||||
UTensor(indor::along_col, ft.tdims.getNVX(), ft.nrows(), ft.tdims.calcUnfoldMaxOffset(),
|
||||
ft.dimen()),
|
||||
tdims(ft.tdims)
|
||||
{
|
||||
for (index fi = ft.begin(); fi != ft.end(); ++fi)
|
||||
|
@ -377,10 +367,9 @@ UGSTensor::UGSTensor(const FGSTensor &ft)
|
|||
|
||||
// UGSTensor slicing from FSSparseTensor
|
||||
/* This makes a folded slice from the sparse tensor and unfolds it. */
|
||||
UGSTensor::UGSTensor(const FSSparseTensor &t, const IntSequence &ss,
|
||||
const IntSequence &coor, TensorDimens td)
|
||||
: UTensor(indor::along_col, td.getNVX(), t.nrows(),
|
||||
td.calcUnfoldMaxOffset(), td.dimen()),
|
||||
UGSTensor::UGSTensor(const FSSparseTensor& t, const IntSequence& ss, const IntSequence& coor,
|
||||
TensorDimens td) :
|
||||
UTensor(indor::along_col, td.getNVX(), t.nrows(), td.calcUnfoldMaxOffset(), td.dimen()),
|
||||
tdims(std::move(td))
|
||||
{
|
||||
if (ncols() == 0)
|
||||
|
@ -397,10 +386,9 @@ UGSTensor::UGSTensor(const FSSparseTensor &t, const IntSequence &ss,
|
|||
|
||||
// UGSTensor slicing from UFSTensor
|
||||
/* This makes a folded slice from dense and unfolds it. */
|
||||
UGSTensor::UGSTensor(const UFSTensor &t, const IntSequence &ss,
|
||||
const IntSequence &coor, TensorDimens td)
|
||||
: UTensor(indor::along_col, td.getNVX(), t.nrows(),
|
||||
td.calcUnfoldMaxOffset(), td.dimen()),
|
||||
UGSTensor::UGSTensor(const UFSTensor& t, const IntSequence& ss, const IntSequence& coor,
|
||||
TensorDimens td) :
|
||||
UTensor(indor::along_col, td.getNVX(), t.nrows(), td.calcUnfoldMaxOffset(), td.dimen()),
|
||||
tdims(std::move(td))
|
||||
{
|
||||
FFSTensor folded(t);
|
||||
|
@ -416,19 +404,17 @@ UGSTensor::UGSTensor(const UFSTensor &t, const IntSequence &ss,
|
|||
// UGSTensor increment and decrement codes
|
||||
/* Clear, just call UTensor static methods. */
|
||||
void
|
||||
UGSTensor::increment(IntSequence &v) const
|
||||
UGSTensor::increment(IntSequence& v) const
|
||||
{
|
||||
TL_RAISE_IF(v.size() != dimen(),
|
||||
"Wrong input/output vector size in UGSTensor::increment");
|
||||
TL_RAISE_IF(v.size() != dimen(), "Wrong input/output vector size in UGSTensor::increment");
|
||||
|
||||
UTensor::increment(v, tdims.getNVX());
|
||||
}
|
||||
|
||||
void
|
||||
UGSTensor::decrement(IntSequence &v) const
|
||||
UGSTensor::decrement(IntSequence& v) const
|
||||
{
|
||||
TL_RAISE_IF(v.size() != dimen(),
|
||||
"Wrong input/output vector size in UGSTensor::decrement");
|
||||
TL_RAISE_IF(v.size() != dimen(), "Wrong input/output vector size in UGSTensor::decrement");
|
||||
|
||||
UTensor::decrement(v, tdims.getNVX());
|
||||
}
|
||||
|
@ -442,10 +428,9 @@ UGSTensor::fold() const
|
|||
|
||||
/* Return an offset of a given index. */
|
||||
int
|
||||
UGSTensor::getOffset(const IntSequence &v) const
|
||||
UGSTensor::getOffset(const IntSequence& v) const
|
||||
{
|
||||
TL_RAISE_IF(v.size() != dimen(),
|
||||
"Wrong input vector size in UGSTensor::getOffset");
|
||||
TL_RAISE_IF(v.size() != dimen(), "Wrong input vector size in UGSTensor::getOffset");
|
||||
|
||||
return UTensor::getOffset(v, tdims.getNVX());
|
||||
}
|
||||
|
@ -465,13 +450,13 @@ UGSTensor::unfoldData()
|
|||
partitions of the index. */
|
||||
|
||||
Tensor::index
|
||||
UGSTensor::getFirstIndexOf(const index &in) const
|
||||
UGSTensor::getFirstIndexOf(const index& in) const
|
||||
{
|
||||
IntSequence v(in.getCoor());
|
||||
int last = 0;
|
||||
for (int i = 0; i < tdims.getSym().num(); i++)
|
||||
{
|
||||
IntSequence vtmp(v, last, last+tdims.getSym()[i]);
|
||||
IntSequence vtmp(v, last, last + tdims.getSym()[i]);
|
||||
vtmp.sort();
|
||||
last += tdims.getSym()[i];
|
||||
}
|
||||
|
@ -482,11 +467,9 @@ UGSTensor::getFirstIndexOf(const index &in) const
|
|||
FGSTensor::contractAndAdd(). */
|
||||
|
||||
void
|
||||
UGSTensor::contractAndAdd(int i, UGSTensor &out,
|
||||
const URSingleTensor &col) const
|
||||
UGSTensor::contractAndAdd(int i, UGSTensor& out, const URSingleTensor& col) const
|
||||
{
|
||||
TL_RAISE_IF(i < 0 || i >= getSym().num(),
|
||||
"Wrong index for UGSTensor::contractAndAdd");
|
||||
TL_RAISE_IF(i < 0 || i >= getSym().num(), "Wrong index for UGSTensor::contractAndAdd");
|
||||
TL_RAISE_IF(getSym()[i] != col.dimen() || tdims.getNVS()[i] != col.nvar(),
|
||||
"Wrong dimensions for UGSTensor::contractAndAdd");
|
||||
|
||||
|
|
|
@ -37,10 +37,10 @@
|
|||
#ifndef GS_TENSOR_H
|
||||
#define GS_TENSOR_H
|
||||
|
||||
#include "tensor.hh"
|
||||
#include "fs_tensor.hh"
|
||||
#include "symmetry.hh"
|
||||
#include "rfs_tensor.hh"
|
||||
#include "symmetry.hh"
|
||||
#include "tensor.hh"
|
||||
|
||||
class FGSTensor;
|
||||
class UGSTensor;
|
||||
|
@ -63,26 +63,26 @@ protected:
|
|||
IntSequence nvs;
|
||||
Symmetry sym;
|
||||
IntSequence nvmax;
|
||||
|
||||
public:
|
||||
TensorDimens(Symmetry s, IntSequence nvars)
|
||||
: nvs(std::move(nvars)), sym(std::move(s)), nvmax(nvs.unfold(sym))
|
||||
TensorDimens(Symmetry s, IntSequence nvars) :
|
||||
nvs(std::move(nvars)), sym(std::move(s)), nvmax(nvs.unfold(sym))
|
||||
{
|
||||
}
|
||||
// Full-symmetry special case
|
||||
TensorDimens(int nvar, int dimen)
|
||||
: nvs{nvar}, sym{dimen}, nvmax(dimen, nvar)
|
||||
TensorDimens(int nvar, int dimen) : nvs {nvar}, sym {dimen}, nvmax(dimen, nvar)
|
||||
{
|
||||
}
|
||||
// Constructs the tensor dimensions for slicing (see the implementation for details)
|
||||
TensorDimens(const IntSequence &ss, const IntSequence &coor);
|
||||
TensorDimens(const IntSequence& ss, const IntSequence& coor);
|
||||
|
||||
bool
|
||||
operator==(const TensorDimens &td) const
|
||||
operator==(const TensorDimens& td) const
|
||||
{
|
||||
return nvs == td.nvs && sym == td.sym;
|
||||
}
|
||||
bool
|
||||
operator!=(const TensorDimens &td) const
|
||||
operator!=(const TensorDimens& td) const
|
||||
{
|
||||
return !operator==(td);
|
||||
}
|
||||
|
@ -97,17 +97,17 @@ public:
|
|||
{
|
||||
return nvmax[i];
|
||||
}
|
||||
const IntSequence &
|
||||
const IntSequence&
|
||||
getNVS() const
|
||||
{
|
||||
return nvs;
|
||||
}
|
||||
const IntSequence &
|
||||
const IntSequence&
|
||||
getNVX() const
|
||||
{
|
||||
return nvmax;
|
||||
}
|
||||
const Symmetry &
|
||||
const Symmetry&
|
||||
getSym() const
|
||||
{
|
||||
return sym;
|
||||
|
@ -115,8 +115,8 @@ public:
|
|||
|
||||
int calcUnfoldMaxOffset() const;
|
||||
int calcFoldMaxOffset() const;
|
||||
int calcFoldOffset(const IntSequence &v) const;
|
||||
void decrement(IntSequence &v) const;
|
||||
int calcFoldOffset(const IntSequence& v) const;
|
||||
void decrement(IntSequence& v) const;
|
||||
};
|
||||
|
||||
/* Here is a class for folded general symmetry tensor. It only contains
|
||||
|
@ -129,51 +129,49 @@ class FGSTensor : public FTensor
|
|||
friend class UGSTensor;
|
||||
|
||||
const TensorDimens tdims;
|
||||
|
||||
public:
|
||||
FGSTensor(int r, TensorDimens td)
|
||||
: FTensor(indor::along_col, td.getNVX(), r,
|
||||
td.calcFoldMaxOffset(), td.dimen()), tdims(std::move(td))
|
||||
FGSTensor(int r, TensorDimens td) :
|
||||
FTensor(indor::along_col, td.getNVX(), r, td.calcFoldMaxOffset(), td.dimen()),
|
||||
tdims(std::move(td))
|
||||
{
|
||||
}
|
||||
FGSTensor(const FGSTensor &) = default;
|
||||
FGSTensor(FGSTensor &&) = default;
|
||||
FGSTensor(const FGSTensor&) = default;
|
||||
FGSTensor(FGSTensor&&) = default;
|
||||
|
||||
FGSTensor(int first_row, int num, FGSTensor &t)
|
||||
: FTensor(first_row, num, t), tdims(t.tdims)
|
||||
FGSTensor(int first_row, int num, FGSTensor& t) : FTensor(first_row, num, t), tdims(t.tdims)
|
||||
{
|
||||
}
|
||||
|
||||
// Constructs a slice from a fully symmetric sparse tensor
|
||||
FGSTensor(const FSSparseTensor &t, const IntSequence &ss,
|
||||
const IntSequence &coor, TensorDimens td);
|
||||
FGSTensor(const FSSparseTensor& t, const IntSequence& ss, const IntSequence& coor,
|
||||
TensorDimens td);
|
||||
|
||||
// Constructs a slice from a fully symmetric dense tensor
|
||||
FGSTensor(const FFSTensor &t, const IntSequence &ss,
|
||||
const IntSequence &coor, TensorDimens td);
|
||||
FGSTensor(const FFSTensor& t, const IntSequence& ss, const IntSequence& coor, TensorDimens td);
|
||||
|
||||
// Converting constructors
|
||||
explicit FGSTensor(const UGSTensor &ut);
|
||||
explicit FGSTensor(const GSSparseTensor &sp);
|
||||
explicit FGSTensor(FFSTensor &t)
|
||||
: FTensor(0, t.nrows(), t), tdims(t.nvar(), t.dimen())
|
||||
explicit FGSTensor(const UGSTensor& ut);
|
||||
explicit FGSTensor(const GSSparseTensor& sp);
|
||||
explicit FGSTensor(FFSTensor& t) : FTensor(0, t.nrows(), t), tdims(t.nvar(), t.dimen())
|
||||
{
|
||||
}
|
||||
|
||||
~FGSTensor() override = default;
|
||||
|
||||
void increment(IntSequence &v) const override;
|
||||
void increment(IntSequence& v) const override;
|
||||
void
|
||||
decrement(IntSequence &v) const override
|
||||
decrement(IntSequence& v) const override
|
||||
{
|
||||
tdims.decrement(v);
|
||||
}
|
||||
std::unique_ptr<UTensor> unfold() const override;
|
||||
const TensorDimens &
|
||||
const TensorDimens&
|
||||
getDims() const
|
||||
{
|
||||
return tdims;
|
||||
}
|
||||
const Symmetry &
|
||||
const Symmetry&
|
||||
getSym() const
|
||||
{
|
||||
return getDims().getSym();
|
||||
|
@ -184,11 +182,10 @@ public:
|
|||
|
||||
[r_xⁱzᵏ]_α₁…αᵢγ₁…γₖ = [t_xⁱyʲzᵏ]_α₁…αᵢβ₁…βⱼγ₁…γₖ·[c]^β₁…βⱼ
|
||||
*/
|
||||
void contractAndAdd(int i, FGSTensor &out,
|
||||
const FRSingleTensor &col) const;
|
||||
void contractAndAdd(int i, FGSTensor& out, const FRSingleTensor& col) const;
|
||||
|
||||
int
|
||||
getOffset(const IntSequence &v) const override
|
||||
getOffset(const IntSequence& v) const override
|
||||
{
|
||||
return tdims.calcFoldOffset(v);
|
||||
}
|
||||
|
@ -204,59 +201,58 @@ class UGSTensor : public UTensor
|
|||
friend class FGSTensor;
|
||||
|
||||
const TensorDimens tdims;
|
||||
|
||||
public:
|
||||
UGSTensor(int r, TensorDimens td)
|
||||
: UTensor(indor::along_col, td.getNVX(), r,
|
||||
td.calcUnfoldMaxOffset(), td.dimen()), tdims(std::move(td))
|
||||
UGSTensor(int r, TensorDimens td) :
|
||||
UTensor(indor::along_col, td.getNVX(), r, td.calcUnfoldMaxOffset(), td.dimen()),
|
||||
tdims(std::move(td))
|
||||
{
|
||||
}
|
||||
|
||||
UGSTensor(const UGSTensor &) = default;
|
||||
UGSTensor(UGSTensor &&) = default;
|
||||
UGSTensor(const UGSTensor&) = default;
|
||||
UGSTensor(UGSTensor&&) = default;
|
||||
|
||||
UGSTensor(int first_row, int num, UGSTensor &t)
|
||||
: UTensor(first_row, num, t), tdims(t.tdims)
|
||||
UGSTensor(int first_row, int num, UGSTensor& t) : UTensor(first_row, num, t), tdims(t.tdims)
|
||||
{
|
||||
}
|
||||
|
||||
// Constructs a slice from fully symmetric sparse tensor
|
||||
UGSTensor(const FSSparseTensor &t, const IntSequence &ss,
|
||||
const IntSequence &coor, TensorDimens td);
|
||||
UGSTensor(const FSSparseTensor& t, const IntSequence& ss, const IntSequence& coor,
|
||||
TensorDimens td);
|
||||
|
||||
// Constructs a slice from fully symmetric dense unfolded tensor
|
||||
UGSTensor(const UFSTensor &t, const IntSequence &ss,
|
||||
const IntSequence &coor, TensorDimens td);
|
||||
UGSTensor(const UFSTensor& t, const IntSequence& ss, const IntSequence& coor, TensorDimens td);
|
||||
|
||||
// Converting constructors
|
||||
explicit UGSTensor(const FGSTensor &ft);
|
||||
explicit UGSTensor(UFSTensor &t)
|
||||
: UTensor(0, t.nrows(), t), tdims(t.nvar(), t.dimen())
|
||||
explicit UGSTensor(const FGSTensor& ft);
|
||||
explicit UGSTensor(UFSTensor& t) : UTensor(0, t.nrows(), t), tdims(t.nvar(), t.dimen())
|
||||
{
|
||||
}
|
||||
|
||||
~UGSTensor() override = default;
|
||||
|
||||
void increment(IntSequence &v) const override;
|
||||
void decrement(IntSequence &v) const override;
|
||||
void increment(IntSequence& v) const override;
|
||||
void decrement(IntSequence& v) const override;
|
||||
std::unique_ptr<FTensor> fold() const override;
|
||||
const TensorDimens &
|
||||
const TensorDimens&
|
||||
getDims() const
|
||||
{
|
||||
return tdims;
|
||||
}
|
||||
const Symmetry &
|
||||
const Symmetry&
|
||||
getSym() const
|
||||
{
|
||||
return getDims().getSym();
|
||||
}
|
||||
|
||||
void contractAndAdd(int i, UGSTensor &out,
|
||||
const URSingleTensor &col) const;
|
||||
int getOffset(const IntSequence &v) const override;
|
||||
void contractAndAdd(int i, UGSTensor& out, const URSingleTensor& col) const;
|
||||
int getOffset(const IntSequence& v) const override;
|
||||
|
||||
private:
|
||||
void unfoldData();
|
||||
|
||||
public:
|
||||
index getFirstIndexOf(const index &in) const;
|
||||
index getFirstIndexOf(const index& in) const;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -19,16 +19,16 @@
|
|||
*/
|
||||
|
||||
#include "int_sequence.hh"
|
||||
#include "pascal_triangle.hh"
|
||||
#include "symmetry.hh"
|
||||
#include "tl_exception.hh"
|
||||
#include "pascal_triangle.hh"
|
||||
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
#include <numeric>
|
||||
|
||||
IntSequence
|
||||
IntSequence::unfold(const Symmetry &sy) const
|
||||
IntSequence::unfold(const Symmetry& sy) const
|
||||
{
|
||||
IntSequence r(sy.dimen());
|
||||
int k = 0;
|
||||
|
@ -47,7 +47,7 @@ IntSequence::getSymmetry() const
|
|||
r[p] = 1;
|
||||
for (int i = 1; i < size(); i++)
|
||||
{
|
||||
if (operator[](i) != operator[](i-1))
|
||||
if (operator[](i) != operator[](i - 1))
|
||||
p++;
|
||||
r[p]++;
|
||||
}
|
||||
|
@ -57,41 +57,40 @@ IntSequence::getSymmetry() const
|
|||
IntSequence
|
||||
IntSequence::insert(int i) const
|
||||
{
|
||||
IntSequence r(size()+1);
|
||||
IntSequence r(size() + 1);
|
||||
int j;
|
||||
for (j = 0; j < size() && operator[](j) < i; j++)
|
||||
r[j] = operator[](j);
|
||||
r[j] = i;
|
||||
for (; j < size(); j++)
|
||||
r[j+1] = operator[](j);
|
||||
r[j + 1] = operator[](j);
|
||||
return r;
|
||||
}
|
||||
|
||||
IntSequence
|
||||
IntSequence::insert(int i, int pos) const
|
||||
{
|
||||
TL_RAISE_IF(pos < 0 || pos > size(),
|
||||
"Wrong position for IntSequence::insert()");
|
||||
IntSequence r(size()+1);
|
||||
TL_RAISE_IF(pos < 0 || pos > size(), "Wrong position for IntSequence::insert()");
|
||||
IntSequence r(size() + 1);
|
||||
int j;
|
||||
for (j = 0; j < pos; j++)
|
||||
r[j] = operator[](j);
|
||||
r[j] = i;
|
||||
for (; j < size(); j++)
|
||||
r[j+1] = operator[](j);
|
||||
r[j + 1] = operator[](j);
|
||||
return r;
|
||||
}
|
||||
|
||||
IntSequence &
|
||||
IntSequence::operator=(const IntSequence &s)
|
||||
IntSequence&
|
||||
IntSequence::operator=(const IntSequence& s)
|
||||
{
|
||||
TL_RAISE_IF(length != s.length, "Wrong length for in-place IntSequence::operator=");
|
||||
std::copy_n(s.data, length, data);
|
||||
return *this;
|
||||
}
|
||||
|
||||
IntSequence &
|
||||
IntSequence::operator=(IntSequence &&s)
|
||||
IntSequence&
|
||||
IntSequence::operator=(IntSequence&& s)
|
||||
{
|
||||
TL_RAISE_IF(length != s.length, "Wrong length for in-place IntSequence::operator=");
|
||||
std::copy_n(s.data, length, data);
|
||||
|
@ -99,24 +98,21 @@ IntSequence::operator=(IntSequence &&s)
|
|||
}
|
||||
|
||||
bool
|
||||
IntSequence::operator==(const IntSequence &s) const
|
||||
IntSequence::operator==(const IntSequence& s) const
|
||||
{
|
||||
return std::equal(data, data+length,
|
||||
s.data, s.data+s.length);
|
||||
return std::equal(data, data + length, s.data, s.data + s.length);
|
||||
}
|
||||
|
||||
bool
|
||||
IntSequence::operator<(const IntSequence &s) const
|
||||
IntSequence::operator<(const IntSequence& s) const
|
||||
{
|
||||
return std::lexicographical_compare(data, data+length,
|
||||
s.data, s.data+s.length);
|
||||
return std::lexicographical_compare(data, data + length, s.data, s.data + s.length);
|
||||
}
|
||||
|
||||
bool
|
||||
IntSequence::lessEq(const IntSequence &s) const
|
||||
IntSequence::lessEq(const IntSequence& s) const
|
||||
{
|
||||
TL_RAISE_IF(size() != s.size(),
|
||||
"Sequence with different lengths in IntSequence::lessEq");
|
||||
TL_RAISE_IF(size() != s.size(), "Sequence with different lengths in IntSequence::lessEq");
|
||||
|
||||
int i = 0;
|
||||
while (i < size() && operator[](i) <= s[i])
|
||||
|
@ -125,10 +121,9 @@ IntSequence::lessEq(const IntSequence &s) const
|
|||
}
|
||||
|
||||
bool
|
||||
IntSequence::less(const IntSequence &s) const
|
||||
IntSequence::less(const IntSequence& s) const
|
||||
{
|
||||
TL_RAISE_IF(size() != s.size(),
|
||||
"Sequence with different lengths in IntSequence::less");
|
||||
TL_RAISE_IF(size() != s.size(), "Sequence with different lengths in IntSequence::less");
|
||||
|
||||
int i = 0;
|
||||
while (i < size() && operator[](i) < s[i])
|
||||
|
@ -139,26 +134,26 @@ IntSequence::less(const IntSequence &s) const
|
|||
void
|
||||
IntSequence::sort()
|
||||
{
|
||||
std::sort(data, data+length);
|
||||
std::sort(data, data + length);
|
||||
}
|
||||
|
||||
void
|
||||
IntSequence::monotone()
|
||||
{
|
||||
for (int i = 1; i < length; i++)
|
||||
if (operator[](i-1) > operator[](i))
|
||||
operator[](i) = operator[](i-1);
|
||||
if (operator[](i - 1) > operator[](i))
|
||||
operator[](i) = operator[](i - 1);
|
||||
}
|
||||
|
||||
void
|
||||
IntSequence::pmonotone(const Symmetry &s)
|
||||
IntSequence::pmonotone(const Symmetry& s)
|
||||
{
|
||||
int cum = 0;
|
||||
for (int i = 0; i < s.num(); i++)
|
||||
{
|
||||
for (int j = cum + 1; j < cum + s[i]; j++)
|
||||
if (operator[](j-1) > operator[](j))
|
||||
operator[](j) = operator[](j-1);
|
||||
if (operator[](j - 1) > operator[](j))
|
||||
operator[](j) = operator[](j - 1);
|
||||
cum += s[i];
|
||||
}
|
||||
}
|
||||
|
@ -166,23 +161,22 @@ IntSequence::pmonotone(const Symmetry &s)
|
|||
int
|
||||
IntSequence::sum() const
|
||||
{
|
||||
return std::accumulate(data, data+length, 0);
|
||||
return std::accumulate(data, data + length, 0);
|
||||
}
|
||||
|
||||
int
|
||||
IntSequence::mult(int i1, int i2) const
|
||||
{
|
||||
return std::accumulate(data+i1, data+i2,
|
||||
1, std::multiplies<int>());
|
||||
return std::accumulate(data + i1, data + i2, 1, std::multiplies<int>());
|
||||
}
|
||||
|
||||
int
|
||||
IntSequence::getPrefixLength() const
|
||||
{
|
||||
int i = 0;
|
||||
while (i+1 < size() && operator[](i+1) == operator[](0))
|
||||
while (i + 1 < size() && operator[](i + 1) == operator[](0))
|
||||
i++;
|
||||
return i+1;
|
||||
return i + 1;
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -192,7 +186,7 @@ IntSequence::getNumDistinct() const
|
|||
if (length > 0)
|
||||
res++;
|
||||
for (int i = 1; i < length; i++)
|
||||
if (operator[](i) != operator[](i-1))
|
||||
if (operator[](i) != operator[](i - 1))
|
||||
res++;
|
||||
return res;
|
||||
}
|
||||
|
@ -202,7 +196,7 @@ IntSequence::getMax() const
|
|||
{
|
||||
if (length == 0)
|
||||
return std::numeric_limits<int>::min();
|
||||
return *std::max_element(data, data+length);
|
||||
return *std::max_element(data, data + length);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -213,19 +207,17 @@ IntSequence::add(int i)
|
|||
}
|
||||
|
||||
void
|
||||
IntSequence::add(int f, const IntSequence &s)
|
||||
IntSequence::add(int f, const IntSequence& s)
|
||||
{
|
||||
TL_RAISE_IF(size() != s.size(),
|
||||
"Wrong sequence length in IntSequence::add");
|
||||
TL_RAISE_IF(size() != s.size(), "Wrong sequence length in IntSequence::add");
|
||||
for (int j = 0; j < size(); j++)
|
||||
operator[](j) += f*s[j];
|
||||
operator[](j) += f * s[j];
|
||||
}
|
||||
|
||||
bool
|
||||
IntSequence::isPositive() const
|
||||
{
|
||||
return std::all_of(data, data+length,
|
||||
[](int x) { return x >= 0; });
|
||||
return std::all_of(data, data + length, [](int x) { return x >= 0; });
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -233,14 +225,13 @@ IntSequence::isConstant() const
|
|||
{
|
||||
if (length < 2)
|
||||
return true;
|
||||
return std::all_of(data+1, data+length,
|
||||
[this](int x) { return x == operator[](0); });
|
||||
return std::all_of(data + 1, data + length, [this](int x) { return x == operator[](0); });
|
||||
}
|
||||
|
||||
bool
|
||||
IntSequence::isSorted() const
|
||||
{
|
||||
return std::is_sorted(data, data+length);
|
||||
return std::is_sorted(data, data + length);
|
||||
}
|
||||
|
||||
/* Debug print. */
|
||||
|
|
|
@ -42,10 +42,10 @@
|
|||
#ifndef INT_SEQUENCE_H
|
||||
#define INT_SEQUENCE_H
|
||||
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <initializer_list>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
/* The implementation of IntSequence is straightforward. It has a pointer
|
||||
‘data’, an ‘offset’ integer indicating the beginning of the data relatively
|
||||
|
@ -59,76 +59,72 @@
|
|||
class Symmetry;
|
||||
class IntSequence
|
||||
{
|
||||
int *data;
|
||||
int* data;
|
||||
int length;
|
||||
bool destroy{true};
|
||||
bool destroy {true};
|
||||
|
||||
public:
|
||||
// Constructor allocating a given length of (uninitialized) data
|
||||
explicit IntSequence(int l)
|
||||
: data{new int[l]}, length{l}
|
||||
explicit IntSequence(int l) : data {new int[l]}, length {l}
|
||||
{
|
||||
}
|
||||
// Constructor allocating and then initializing all members to a given number
|
||||
IntSequence(int l, int n)
|
||||
: data{new int[l]}, length{l}
|
||||
IntSequence(int l, int n) : data {new int[l]}, length {l}
|
||||
{
|
||||
std::fill_n(data, length, n);
|
||||
}
|
||||
/* Constructor using an initializer list (gives the contents of the
|
||||
IntSequence, similarly to std::vector) */
|
||||
IntSequence(std::initializer_list<int> init)
|
||||
: data{new int[init.size()]},
|
||||
length{static_cast<int>(init.size())}
|
||||
IntSequence(std::initializer_list<int> init) :
|
||||
data {new int[init.size()]}, length {static_cast<int>(init.size())}
|
||||
{
|
||||
std::copy(init.begin(), init.end(), data);
|
||||
}
|
||||
// Copy constructor
|
||||
IntSequence(const IntSequence &s)
|
||||
: data{new int[s.length]}, length{s.length}
|
||||
IntSequence(const IntSequence& s) : data {new int[s.length]}, length {s.length}
|
||||
{
|
||||
std::copy_n(s.data, length, data);
|
||||
}
|
||||
// Move constructor
|
||||
IntSequence(IntSequence &&s) noexcept
|
||||
: data{std::exchange(s.data, nullptr)}, length{std::exchange(s.length, 0)},
|
||||
destroy{std::exchange(s.destroy, false)}
|
||||
IntSequence(IntSequence&& s) noexcept :
|
||||
data {std::exchange(s.data, nullptr)}, length {std::exchange(s.length, 0)},
|
||||
destroy {std::exchange(s.destroy, false)}
|
||||
{
|
||||
}
|
||||
// Subsequence constructor (which shares the data pointer)
|
||||
IntSequence(IntSequence &s, int i1, int i2)
|
||||
: data{s.data+i1}, length{i2-i1}, destroy{false}
|
||||
IntSequence(IntSequence& s, int i1, int i2) :
|
||||
data {s.data + i1}, length {i2 - i1}, destroy {false}
|
||||
{
|
||||
}
|
||||
// Subsequence constructor (without pointer sharing)
|
||||
IntSequence(const IntSequence &s, int i1, int i2)
|
||||
: data{new int[i2-i1]}, length{i2-i1}
|
||||
IntSequence(const IntSequence& s, int i1, int i2) : data {new int[i2 - i1]}, length {i2 - i1}
|
||||
{
|
||||
std::copy_n(s.data+i1, length, data);
|
||||
std::copy_n(s.data + i1, length, data);
|
||||
}
|
||||
/* Unfolds a given integer sequence with respect to a given symmetry. If for
|
||||
example the sequence is (a,b) and the symmetry is (2,3), then the
|
||||
result is (a,a,b,b,b). */
|
||||
IntSequence unfold(const Symmetry &sy) const;
|
||||
IntSequence unfold(const Symmetry& sy) const;
|
||||
|
||||
/* Constructs a symmetry from the integer sequence (supposed to be ordered) as
|
||||
a symmetry counting successively equal items. For instance the sequence
|
||||
(a,a,a,b,c,c,d,d,d,d) produces symmetry (3,1,2,4). */
|
||||
Symmetry getSymmetry() const;
|
||||
|
||||
IntSequence &operator=(const IntSequence &s);
|
||||
IntSequence &operator=(IntSequence &&s);
|
||||
IntSequence& operator=(const IntSequence& s);
|
||||
IntSequence& operator=(IntSequence&& s);
|
||||
virtual ~IntSequence()
|
||||
{
|
||||
if (destroy)
|
||||
delete[] data;
|
||||
}
|
||||
bool operator==(const IntSequence &s) const;
|
||||
bool operator==(const IntSequence& s) const;
|
||||
bool
|
||||
operator!=(const IntSequence &s) const
|
||||
operator!=(const IntSequence& s) const
|
||||
{
|
||||
return !operator==(s);
|
||||
}
|
||||
int &
|
||||
int&
|
||||
operator[](int i)
|
||||
{
|
||||
return data[i];
|
||||
|
@ -147,14 +143,14 @@ public:
|
|||
/* We provide two orderings. The first operator<() is the linear
|
||||
lexicographic ordering, the second less() is the non-linear Cartesian
|
||||
ordering. */
|
||||
bool operator<(const IntSequence &s) const;
|
||||
bool operator<(const IntSequence& s) const;
|
||||
bool
|
||||
operator<=(const IntSequence &s) const
|
||||
operator<=(const IntSequence& s) const
|
||||
{
|
||||
return (operator==(s) || operator<(s));
|
||||
}
|
||||
bool lessEq(const IntSequence &s) const;
|
||||
bool less(const IntSequence &s) const;
|
||||
bool lessEq(const IntSequence& s) const;
|
||||
bool less(const IntSequence& s) const;
|
||||
|
||||
// Inserts an element into an ordered sequence
|
||||
IntSequence insert(int i) const;
|
||||
|
@ -173,8 +169,7 @@ public:
|
|||
symmetry. So the subsequence given by the symmetry classes are
|
||||
monotonized. For example, if the symmetry is y²u³, and the
|
||||
IntSequence is (5,3,1,6,4), the result is (5,5,1,6,6). */
|
||||
void pmonotone(const Symmetry &s);
|
||||
|
||||
void pmonotone(const Symmetry& s);
|
||||
|
||||
// Returns the sum of all elements. Useful for symmetries
|
||||
int sum() const;
|
||||
|
@ -190,7 +185,7 @@ public:
|
|||
return mult(0, length);
|
||||
}
|
||||
void add(int i);
|
||||
void add(int f, const IntSequence &s);
|
||||
void add(int f, const IntSequence& s);
|
||||
|
||||
/* Return the number of identical elements at the beginning of the sequence. */
|
||||
int getPrefixLength() const;
|
||||
|
|
|
@ -34,12 +34,10 @@
|
|||
|
||||
Then we fork according to i. */
|
||||
|
||||
KronProdDimens::KronProdDimens(const KronProdDimens &kd, int i)
|
||||
: rows((i == 0 || i == kd.dimen()-1) ? 2 : 3),
|
||||
cols((i == 0 || i == kd.dimen()-1) ? 2 : 3)
|
||||
KronProdDimens::KronProdDimens(const KronProdDimens& kd, int i) :
|
||||
rows((i == 0 || i == kd.dimen() - 1) ? 2 : 3), cols((i == 0 || i == kd.dimen() - 1) ? 2 : 3)
|
||||
{
|
||||
TL_RAISE_IF(i < 0 || i >= kd.dimen(),
|
||||
"Wrong index for pickup in KronProdDimens constructor");
|
||||
TL_RAISE_IF(i < 0 || i >= kd.dimen(), "Wrong index for pickup in KronProdDimens constructor");
|
||||
|
||||
int kdim = kd.dimen();
|
||||
if (i == 0)
|
||||
|
@ -53,16 +51,16 @@ KronProdDimens::KronProdDimens(const KronProdDimens &kd, int i)
|
|||
cols[0] = kd.cols[0];
|
||||
cols[1] = rows[1];
|
||||
}
|
||||
else if (i == kdim-1)
|
||||
else if (i == kdim - 1)
|
||||
{
|
||||
// set I⊗A dimensions
|
||||
/* The second dimension is taken from ‘kd’. The dimension of the identity
|
||||
matrix is the number of columns of A₁⊗…⊗Aₙ₋₁, since the matrix I⊗Aₙ is
|
||||
the last. */
|
||||
rows[0] = kd.cols.mult(0, kdim-1);
|
||||
rows[1] = kd.rows[kdim-1];
|
||||
rows[0] = kd.cols.mult(0, kdim - 1);
|
||||
rows[1] = kd.rows[kdim - 1];
|
||||
cols[0] = rows[0];
|
||||
cols[1] = kd.cols[kdim-1];
|
||||
cols[1] = kd.cols[kdim - 1];
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -75,7 +73,7 @@ KronProdDimens::KronProdDimens(const KronProdDimens &kd, int i)
|
|||
cols[0] = rows[0];
|
||||
rows[1] = kd.rows[i];
|
||||
cols[1] = kd.cols[i];
|
||||
cols[2] = kd.rows.mult(i+1, kdim);
|
||||
cols[2] = kd.rows.mult(i + 1, kdim);
|
||||
rows[2] = cols[2];
|
||||
}
|
||||
}
|
||||
|
@ -84,7 +82,7 @@ KronProdDimens::KronProdDimens(const KronProdDimens &kd, int i)
|
|||
out = in·this. */
|
||||
|
||||
void
|
||||
KronProd::checkDimForMult(const ConstTwoDMatrix &in, const TwoDMatrix &out) const
|
||||
KronProd::checkDimForMult(const ConstTwoDMatrix& in, const TwoDMatrix& out) const
|
||||
{
|
||||
auto [my_rows, my_cols] = kpd.getRC();
|
||||
TL_RAISE_IF(in.nrows() != out.nrows() || in.ncols() != my_rows,
|
||||
|
@ -95,21 +93,20 @@ KronProd::checkDimForMult(const ConstTwoDMatrix &in, const TwoDMatrix &out) cons
|
|||
store the result in preallocated ‘res’. */
|
||||
|
||||
void
|
||||
KronProd::kronMult(const ConstVector &v1, const ConstVector &v2,
|
||||
Vector &res)
|
||||
KronProd::kronMult(const ConstVector& v1, const ConstVector& v2, Vector& res)
|
||||
{
|
||||
TL_RAISE_IF(res.length() != v1.length()*v2.length(),
|
||||
TL_RAISE_IF(res.length() != v1.length() * v2.length(),
|
||||
"Wrong vector lengths in KronProd::kronMult");
|
||||
res.zeros();
|
||||
for (int i = 0; i < v1.length(); i++)
|
||||
{
|
||||
Vector sub(res, i *v2.length(), v2.length());
|
||||
Vector sub(res, i * v2.length(), v2.length());
|
||||
sub.add(v1[i], v2);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
KronProdAll::setMat(int i, const TwoDMatrix &m)
|
||||
KronProdAll::setMat(int i, const TwoDMatrix& m)
|
||||
{
|
||||
matlist[i] = &m;
|
||||
kpd.setRC(i, m.nrows(), m.ncols());
|
||||
|
@ -138,7 +135,7 @@ KronProdAll::isUnit() const
|
|||
partitions of ‘in’, and ‘id_cols’ is m. We employ level-2 BLAS. */
|
||||
|
||||
void
|
||||
KronProdIA::mult(const ConstTwoDMatrix &in, TwoDMatrix &out) const
|
||||
KronProdIA::mult(const ConstTwoDMatrix& in, TwoDMatrix& out) const
|
||||
{
|
||||
checkDimForMult(in, out);
|
||||
|
||||
|
@ -154,8 +151,7 @@ KronProdIA::mult(const ConstTwoDMatrix &in, TwoDMatrix &out) const
|
|||
}
|
||||
|
||||
/* Here we construct KronProdAI from KronProdIAI. It is clear. */
|
||||
KronProdAI::KronProdAI(const KronProdIAI &kpiai)
|
||||
: KronProd(KronProdDimens(2)), mat(kpiai.mat)
|
||||
KronProdAI::KronProdAI(const KronProdIAI& kpiai) : KronProd(KronProdDimens(2)), mat(kpiai.mat)
|
||||
{
|
||||
kpd.rows[0] = mat.nrows();
|
||||
kpd.cols[0] = mat.ncols();
|
||||
|
@ -174,17 +170,16 @@ KronProdAI::KronProdAI(const KronProdIAI &kpiai)
|
|||
|
||||
For cases where the leading dimension is not equal to the number of
|
||||
rows, we partition the matrix A⊗I into m×n square partitions aᵢⱼI.
|
||||
Therefore, we partition B into m partitions (B₁ B₂ … Bₘ). Each partition of B has the same number of
|
||||
columns as the identity matrix. If R denotes the resulting matrix,
|
||||
then it can be partitioned into n partitions
|
||||
(R₁ R₂ … Rₙ). Each partition of R has the same number of
|
||||
columns as the identity matrix. Then we have Rᵢ=∑aⱼᵢBⱼ.
|
||||
Therefore, we partition B into m partitions (B₁ B₂ … Bₘ). Each partition of B has the same number
|
||||
of columns as the identity matrix. If R denotes the resulting matrix, then it can be partitioned
|
||||
into n partitions (R₁ R₂ … Rₙ). Each partition of R has the same number of columns as the
|
||||
identity matrix. Then we have Rᵢ=∑aⱼᵢBⱼ.
|
||||
|
||||
In the implementation, ‘outi’ is Rᵢ, ‘ini’ is Bⱼ, and ‘id_cols’ is the
|
||||
dimension of the identity matrix. */
|
||||
|
||||
void
|
||||
KronProdAI::mult(const ConstTwoDMatrix &in, TwoDMatrix &out) const
|
||||
KronProdAI::mult(const ConstTwoDMatrix& in, TwoDMatrix& out) const
|
||||
{
|
||||
checkDimForMult(in, out);
|
||||
|
||||
|
@ -193,8 +188,8 @@ KronProdAI::mult(const ConstTwoDMatrix &in, TwoDMatrix &out) const
|
|||
|
||||
if (in.getLD() == in.nrows())
|
||||
{
|
||||
ConstTwoDMatrix in_resh(in.nrows()*id_cols, a.nrows(), in.getData());
|
||||
TwoDMatrix out_resh(in.nrows()*id_cols, a.ncols(), out.getData());
|
||||
ConstTwoDMatrix in_resh(in.nrows() * id_cols, a.nrows(), in.getData());
|
||||
TwoDMatrix out_resh(in.nrows() * id_cols, a.ncols(), out.getData());
|
||||
out_resh.mult(in_resh, a);
|
||||
}
|
||||
else
|
||||
|
@ -202,10 +197,10 @@ KronProdAI::mult(const ConstTwoDMatrix &in, TwoDMatrix &out) const
|
|||
out.zeros();
|
||||
for (int i = 0; i < a.ncols(); i++)
|
||||
{
|
||||
TwoDMatrix outi(out, i *id_cols, id_cols);
|
||||
TwoDMatrix outi(out, i * id_cols, id_cols);
|
||||
for (int j = 0; j < a.nrows(); j++)
|
||||
{
|
||||
ConstTwoDMatrix ini(in, j *id_cols, id_cols);
|
||||
ConstTwoDMatrix ini(in, j * id_cols, id_cols);
|
||||
outi.add(a.get(j, i), ini);
|
||||
}
|
||||
}
|
||||
|
@ -223,7 +218,7 @@ KronProdAI::mult(const ConstTwoDMatrix &in, TwoDMatrix &out) const
|
|||
and ‘out_bl_width’ are the rows and cols of A⊗I. */
|
||||
|
||||
void
|
||||
KronProdIAI::mult(const ConstTwoDMatrix &in, TwoDMatrix &out) const
|
||||
KronProdIAI::mult(const ConstTwoDMatrix& in, TwoDMatrix& out) const
|
||||
{
|
||||
checkDimForMult(in, out);
|
||||
|
||||
|
@ -234,8 +229,8 @@ KronProdIAI::mult(const ConstTwoDMatrix &in, TwoDMatrix &out) const
|
|||
|
||||
for (int i = 0; i < id_cols; i++)
|
||||
{
|
||||
TwoDMatrix outi(out, i *out_bl_width, out_bl_width);
|
||||
ConstTwoDMatrix ini(in, i *in_bl_width, in_bl_width);
|
||||
TwoDMatrix outi(out, i * out_bl_width, out_bl_width);
|
||||
ConstTwoDMatrix ini(in, i * in_bl_width, in_bl_width);
|
||||
akronid.mult(ini, outi);
|
||||
}
|
||||
}
|
||||
|
@ -254,7 +249,7 @@ KronProdIAI::mult(const ConstTwoDMatrix &in, TwoDMatrix &out) const
|
|||
handle ‘last’ safely also if no calcs are done. */
|
||||
|
||||
void
|
||||
KronProdAll::mult(const ConstTwoDMatrix &in, TwoDMatrix &out) const
|
||||
KronProdAll::mult(const ConstTwoDMatrix& in, TwoDMatrix& out) const
|
||||
{
|
||||
// quick copy if product is unit
|
||||
if (isUnit())
|
||||
|
@ -298,13 +293,13 @@ KronProdAll::mult(const ConstTwoDMatrix &in, TwoDMatrix &out) const
|
|||
akronid.mult(in, *last);
|
||||
}
|
||||
else
|
||||
last = std::make_unique<TwoDMatrix>(in.nrows(), in.ncols(), Vector{in.getData()});
|
||||
last = std::make_unique<TwoDMatrix>(in.nrows(), in.ncols(), Vector {in.getData()});
|
||||
|
||||
// perform intermediate multiplications by I⊗Aᵢ⊗I
|
||||
/* Here we go through all I⊗Aᵢ⊗I, construct the product, allocate new storage
|
||||
for result ‘newlast’, perform the multiplication and set ‘last’ to
|
||||
‘newlast’. */
|
||||
for (int i = 1; i < dimen()-1; i++)
|
||||
for (int i = 1; i < dimen() - 1; i++)
|
||||
if (matlist[i])
|
||||
{
|
||||
KronProdIAI interkron(*this, i);
|
||||
|
@ -315,7 +310,7 @@ KronProdAll::mult(const ConstTwoDMatrix &in, TwoDMatrix &out) const
|
|||
}
|
||||
|
||||
// perform last multiplication by I⊗Aₙ
|
||||
if (matlist[dimen()-1])
|
||||
if (matlist[dimen() - 1])
|
||||
{
|
||||
KronProdIA idkrona(*this);
|
||||
idkrona.mult(*last, out);
|
||||
|
@ -329,17 +324,16 @@ KronProdAll::mult(const ConstTwoDMatrix &in, TwoDMatrix &out) const
|
|||
returned. */
|
||||
|
||||
std::unique_ptr<Vector>
|
||||
KronProdAll::multRows(const IntSequence &irows) const
|
||||
KronProdAll::multRows(const IntSequence& irows) const
|
||||
{
|
||||
TL_RAISE_IF(irows.size() != dimen(),
|
||||
"Wrong length of row indices in KronProdAll::multRows");
|
||||
TL_RAISE_IF(irows.size() != dimen(), "Wrong length of row indices in KronProdAll::multRows");
|
||||
|
||||
std::unique_ptr<Vector> last;
|
||||
std::unique_ptr<ConstVector> row;
|
||||
std::vector<std::unique_ptr<Vector>> to_delete;
|
||||
for (int i = 0; i < dimen(); i++)
|
||||
{
|
||||
int j = dimen()-1-i;
|
||||
int j = dimen() - 1 - i;
|
||||
|
||||
// set ‘row’ to the number of rows of j-th matrix
|
||||
/* If the j-th matrix is a real matrix, then the row is constructed from
|
||||
|
@ -363,7 +357,7 @@ KronProdAll::multRows(const IntSequence &irows) const
|
|||
‘row’. */
|
||||
if (last)
|
||||
{
|
||||
auto newlast = std::make_unique<Vector>(last->length()*row->length());
|
||||
auto newlast = std::make_unique<Vector>(last->length() * row->length());
|
||||
kronMult(*row, ConstVector(*last), *newlast);
|
||||
last = std::move(newlast);
|
||||
}
|
||||
|
@ -387,24 +381,24 @@ KronProdAllOptim::optimizeOrder()
|
|||
for (int i = 0; i < dimen(); i++)
|
||||
{
|
||||
int swaps = 0;
|
||||
for (int j = 0; j < dimen()-1; j++)
|
||||
if (static_cast<double>(kpd.rows[j])/kpd.cols[j]
|
||||
< static_cast<double>(kpd.rows[j+1])/kpd.cols[j+1])
|
||||
for (int j = 0; j < dimen() - 1; j++)
|
||||
if (static_cast<double>(kpd.rows[j]) / kpd.cols[j]
|
||||
< static_cast<double>(kpd.rows[j + 1]) / kpd.cols[j + 1])
|
||||
{
|
||||
// swap dimensions and matrices at j and j+1
|
||||
int s = kpd.rows[j+1];
|
||||
kpd.rows[j+1] = kpd.rows[j];
|
||||
int s = kpd.rows[j + 1];
|
||||
kpd.rows[j + 1] = kpd.rows[j];
|
||||
kpd.rows[j] = s;
|
||||
s = kpd.cols[j+1];
|
||||
kpd.cols[j+1] = kpd.cols[j];
|
||||
s = kpd.cols[j + 1];
|
||||
kpd.cols[j + 1] = kpd.cols[j];
|
||||
kpd.cols[j] = s;
|
||||
const TwoDMatrix *m = matlist[j+1];
|
||||
matlist[j+1] = matlist[j];
|
||||
const TwoDMatrix* m = matlist[j + 1];
|
||||
matlist[j + 1] = matlist[j];
|
||||
matlist[j] = m;
|
||||
|
||||
// project the swap to the permutation ‘oper’
|
||||
s = oper.getMap()[j+1];
|
||||
oper.getMap()[j+1] = oper.getMap()[j];
|
||||
s = oper.getMap()[j + 1];
|
||||
oper.getMap()[j + 1] = oper.getMap()[j];
|
||||
oper.getMap()[j] = s;
|
||||
swaps++;
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue