148 lines
3.9 KiB
C++
148 lines
3.9 KiB
C++
/*
|
||
* 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 <http://www.gnu.org/licenses/>.
|
||
*/
|
||
|
||
#include "vector_function.hh"
|
||
|
||
#include <dynlapack.h>
|
||
|
||
#include <cmath>
|
||
#include <algorithm>
|
||
|
||
/* 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<size_t>(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<VectorFunction> 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
|
||
}
|