/* * Copyright © 2005 Ondra Kamenik * Copyright © 2019 Dynare Team * * This file is part of Dynare. * * Dynare is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Dynare is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Dynare. If not, see . */ #include "vector_function.hh" #include #include #include /* Just an easy constructor of sequence of booleans defaulting to change everywhere. */ ParameterSignal::ParameterSignal(int n) : data(n, true) { } /* This sets ‘false’ (no change) before a given parameter, and ‘true’ (change) after the given parameter (including). */ void ParameterSignal::signalAfter(int l) { for (size_t i = 0; i < std::min(static_cast(l), data.size()); i++) data[i] = false; for (size_t i = l; i < data.size(); i++) data[i] = true; } /* This constructs a function set hardcopying also the first. */ VectorFunctionSet::VectorFunctionSet(const VectorFunction &f, int n) : funcs(n) { for (int i = 0; i < n; i++) { func_copies.push_back(f.clone()); funcs[i] = func_copies.back().get(); } } /* This constructs a function set with shallow copy in the first and hard copies in others. */ VectorFunctionSet::VectorFunctionSet(VectorFunction &f, int n) : funcs(n) { if (n > 0) funcs[0] = &f; for (int i = 1; i < n; i++) { func_copies.push_back(f.clone()); funcs[i] = func_copies.back().get(); } } /* Here we construct the object from the given function f and given variance-covariance matrix Σ=vcov. The matrix A is calculated as lower triangular and yields Σ=AAᵀ. */ GaussConverterFunction::GaussConverterFunction(VectorFunction &f, const GeneralMatrix &vcov) : VectorFunction(f), func(&f), A(vcov.nrows(), vcov.nrows()), multiplier(calcMultiplier()) { // TODO: raise if A.nrows() ≠ indim() calcCholeskyFactor(vcov); } GaussConverterFunction::GaussConverterFunction(std::unique_ptr f, const GeneralMatrix &vcov) : VectorFunction(*f), func_storage{move(f)}, func{func_storage.get()}, A(vcov.nrows(), vcov.nrows()), multiplier(calcMultiplier()) { // TODO: raise if A.nrows() ≠ indim() calcCholeskyFactor(vcov); } GaussConverterFunction::GaussConverterFunction(const GaussConverterFunction &f) : VectorFunction(f), func_storage{f.func->clone()}, func{func_storage.get()}, A(f.A), multiplier(f.multiplier) { } /* Here we evaluate the function g(y) = 1/√(πⁿ) f(√2·Ay). Since the matrix A is lower triangular, the change signal for the function f will look like (0,…,0,1,…,1) where the first 1 is in the same position as the first change in the given signal ‘sig’ of the input y=point. */ void GaussConverterFunction::eval(const Vector &point, const ParameterSignal &sig, Vector &out) { ParameterSignal s(sig); int i = 0; while (i < indim() && !sig[i]) i++; s.signalAfter(i); Vector x(indim()); x.zeros(); A.multaVec(x, point); x.mult(sqrt(2.0)); func->eval(x, s, out); out.mult(multiplier); } /* This returns 1/√(πⁿ). */ double GaussConverterFunction::calcMultiplier() const { return sqrt(pow(M_PI, -1*indim())); } void GaussConverterFunction::calcCholeskyFactor(const GeneralMatrix &vcov) { A = vcov; lapack_int rows = A.nrows(), lda = A.getLD(); for (int i = 0; i < rows; i++) for (int j = i+1; j < rows; j++) A.get(i, j) = 0.0; lapack_int info; dpotrf("L", &rows, A.base(), &lda, &info); // TODO: raise if info≠1 }