2019-06-19 14:34:30 +02:00
|
|
|
|
/*
|
|
|
|
|
* Copyright © 2004-2011 Ondra Kamenik
|
2023-12-05 15:44:23 +01:00
|
|
|
|
* Copyright © 2019-2023 Dynare Team
|
2019-06-19 14:34:30 +02:00
|
|
|
|
*
|
|
|
|
|
* 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
|
2021-06-09 17:33:48 +02:00
|
|
|
|
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
|
2019-06-19 14:34:30 +02:00
|
|
|
|
*/
|
2009-09-08 15:55:19 +02:00
|
|
|
|
|
|
|
|
|
#ifndef QUASI_TRIANGULAR_H
|
|
|
|
|
#define QUASI_TRIANGULAR_H
|
|
|
|
|
|
2019-01-08 17:12:05 +01:00
|
|
|
|
#include "KronVector.hh"
|
|
|
|
|
#include "SylvMatrix.hh"
|
2023-11-29 19:00:21 +01:00
|
|
|
|
#include "Vector.hh"
|
2009-09-08 15:55:19 +02:00
|
|
|
|
|
|
|
|
|
#include <list>
|
2019-01-15 18:55:09 +01:00
|
|
|
|
#include <memory>
|
2009-09-08 15:55:19 +02:00
|
|
|
|
|
|
|
|
|
class DiagonalBlock;
|
|
|
|
|
class Diagonal;
|
2017-05-16 16:30:27 +02:00
|
|
|
|
class DiagPair
|
|
|
|
|
{
|
2009-09-08 15:55:19 +02:00
|
|
|
|
private:
|
2023-11-29 19:00:21 +01:00
|
|
|
|
double* a1;
|
|
|
|
|
double* a2;
|
|
|
|
|
|
2009-09-08 15:55:19 +02:00
|
|
|
|
public:
|
2019-01-15 18:55:09 +01:00
|
|
|
|
DiagPair() = default;
|
2023-11-29 19:00:21 +01:00
|
|
|
|
DiagPair(double* aa1, double* aa2) : a1 {aa1}, a2 {aa2}
|
2017-05-16 16:30:27 +02:00
|
|
|
|
{
|
|
|
|
|
}
|
2023-11-29 19:00:21 +01:00
|
|
|
|
DiagPair(const DiagPair& p) = default;
|
|
|
|
|
DiagPair& operator=(const DiagPair& p) = default;
|
|
|
|
|
DiagPair&
|
2017-05-16 16:30:27 +02:00
|
|
|
|
operator=(double v)
|
|
|
|
|
{
|
2019-01-25 15:27:20 +01:00
|
|
|
|
*a1 = v;
|
|
|
|
|
*a2 = v;
|
|
|
|
|
return *this;
|
2017-05-16 16:30:27 +02:00
|
|
|
|
}
|
2023-11-29 19:00:21 +01:00
|
|
|
|
const double&
|
2017-05-16 16:30:27 +02:00
|
|
|
|
operator*() const
|
|
|
|
|
{
|
|
|
|
|
return *a1;
|
|
|
|
|
}
|
2019-03-28 18:56:46 +01:00
|
|
|
|
/* Here we must not define double& operator*(), since it wouldn't
|
|
|
|
|
rewrite both values, we use operator=() for this */
|
2017-05-16 16:30:27 +02:00
|
|
|
|
friend class Diagonal;
|
|
|
|
|
friend class DiagonalBlock;
|
2009-09-08 15:55:19 +02:00
|
|
|
|
};
|
|
|
|
|
|
2019-03-28 18:56:46 +01:00
|
|
|
|
/* Stores a diagonal block of a quasi-triangular real matrix:
|
|
|
|
|
– either a 1×1 block, i.e. a real scalar, stored in α₁
|
|
|
|
|
⎛α₁ β₁⎞
|
|
|
|
|
– or a 2×2 block, stored as ⎝β₂ α₂⎠
|
|
|
|
|
*/
|
2017-05-16 16:30:27 +02:00
|
|
|
|
class DiagonalBlock
|
|
|
|
|
{
|
2009-09-08 15:55:19 +02:00
|
|
|
|
private:
|
2019-03-28 18:56:46 +01:00
|
|
|
|
int jbar; // Index of block in the diagonal
|
2017-05-16 16:30:27 +02:00
|
|
|
|
bool real;
|
|
|
|
|
DiagPair alpha;
|
2023-11-29 19:00:21 +01:00
|
|
|
|
double* beta1;
|
|
|
|
|
double* beta2;
|
2009-09-08 15:55:19 +02:00
|
|
|
|
|
|
|
|
|
public:
|
2019-01-15 18:55:09 +01:00
|
|
|
|
DiagonalBlock() = default;
|
2023-11-29 19:00:21 +01:00
|
|
|
|
DiagonalBlock(int jb, bool r, double* a1, double* a2, double* b1, double* b2) :
|
|
|
|
|
jbar {jb}, real {r}, alpha {a1, a2}, beta1 {b1}, beta2 {b2}
|
2017-05-16 16:30:27 +02:00
|
|
|
|
{
|
|
|
|
|
}
|
2019-03-28 18:56:46 +01:00
|
|
|
|
// Construct a complex 2×2 block
|
|
|
|
|
/* β₁ and β₂ will be deduced from pointers to α₁ and α₂ */
|
2023-11-29 19:00:21 +01:00
|
|
|
|
DiagonalBlock(int jb, double* a1, double* a2) :
|
|
|
|
|
jbar {jb}, real {false}, alpha {a1, a2}, beta1 {a2 - 1}, beta2 {a1 + 1}
|
2017-05-16 16:30:27 +02:00
|
|
|
|
{
|
|
|
|
|
}
|
2019-03-28 18:56:46 +01:00
|
|
|
|
// Construct a real 1×1 block
|
2023-11-29 19:00:21 +01:00
|
|
|
|
DiagonalBlock(int jb, double* a1) :
|
|
|
|
|
jbar {jb}, real {true}, alpha {a1, a1}, beta1 {nullptr}, beta2 {nullptr}
|
2017-05-16 16:30:27 +02:00
|
|
|
|
{
|
|
|
|
|
}
|
2023-11-29 19:00:21 +01:00
|
|
|
|
DiagonalBlock(const DiagonalBlock& b) = default;
|
|
|
|
|
DiagonalBlock& operator=(const DiagonalBlock& b) = default;
|
2023-12-05 15:44:23 +01:00
|
|
|
|
[[nodiscard]] int
|
2017-05-16 16:30:27 +02:00
|
|
|
|
getIndex() const
|
|
|
|
|
{
|
|
|
|
|
return jbar;
|
|
|
|
|
}
|
2023-12-05 15:44:23 +01:00
|
|
|
|
[[nodiscard]] bool
|
2017-05-16 16:30:27 +02:00
|
|
|
|
isReal() const
|
|
|
|
|
{
|
|
|
|
|
return real;
|
|
|
|
|
}
|
2023-12-05 15:44:23 +01:00
|
|
|
|
[[nodiscard]] const DiagPair&
|
2017-05-16 16:30:27 +02:00
|
|
|
|
getAlpha() const
|
|
|
|
|
{
|
|
|
|
|
return alpha;
|
|
|
|
|
}
|
2023-11-29 19:00:21 +01:00
|
|
|
|
DiagPair&
|
2017-05-16 16:30:27 +02:00
|
|
|
|
getAlpha()
|
|
|
|
|
{
|
|
|
|
|
return alpha;
|
|
|
|
|
}
|
2023-12-05 15:44:23 +01:00
|
|
|
|
[[nodiscard]] double&
|
2017-05-16 16:30:27 +02:00
|
|
|
|
getBeta1() const
|
|
|
|
|
{
|
|
|
|
|
return *beta1;
|
|
|
|
|
}
|
2023-12-05 15:44:23 +01:00
|
|
|
|
[[nodiscard]] double&
|
2017-05-16 16:30:27 +02:00
|
|
|
|
getBeta2() const
|
|
|
|
|
{
|
|
|
|
|
return *beta2;
|
|
|
|
|
}
|
2019-03-28 18:56:46 +01:00
|
|
|
|
// Returns determinant of this block (assuming it is 2×2)
|
2023-12-05 15:44:23 +01:00
|
|
|
|
[[nodiscard]] double getDeterminant() const;
|
2019-03-28 18:56:46 +01:00
|
|
|
|
// Returns −β₁β₂
|
2023-12-05 15:44:23 +01:00
|
|
|
|
[[nodiscard]] double getSBeta() const;
|
2019-03-28 18:56:46 +01:00
|
|
|
|
// Returns the modulus of the eigenvalue(s) contained in this block
|
2023-12-05 15:44:23 +01:00
|
|
|
|
[[nodiscard]] double getSize() const;
|
2019-03-28 18:56:46 +01:00
|
|
|
|
// Transforms this block into a real one
|
2017-05-16 16:30:27 +02:00
|
|
|
|
void setReal();
|
2019-03-28 18:56:46 +01:00
|
|
|
|
// Verifies that the block information is consistent with the matrix d (for debugging)
|
2023-11-29 19:00:21 +01:00
|
|
|
|
void checkBlock(const double* d, int d_size);
|
2017-05-16 16:30:27 +02:00
|
|
|
|
friend class Diagonal;
|
2009-09-08 15:55:19 +02:00
|
|
|
|
};
|
|
|
|
|
|
2019-03-28 18:56:46 +01:00
|
|
|
|
// Stores the diagonal blocks of a quasi-triangular real matrix
|
2017-05-16 16:30:27 +02:00
|
|
|
|
class Diagonal
|
|
|
|
|
{
|
2009-09-08 15:55:19 +02:00
|
|
|
|
public:
|
2019-01-25 15:27:20 +01:00
|
|
|
|
using const_diag_iter = std::list<DiagonalBlock>::const_iterator;
|
|
|
|
|
using diag_iter = std::list<DiagonalBlock>::iterator;
|
2023-11-29 19:00:21 +01:00
|
|
|
|
|
2009-09-08 15:55:19 +02:00
|
|
|
|
private:
|
2023-11-29 19:00:21 +01:00
|
|
|
|
int num_all {0}; // Total number of blocks
|
2019-01-25 15:27:20 +01:00
|
|
|
|
std::list<DiagonalBlock> blocks;
|
2023-11-29 19:00:21 +01:00
|
|
|
|
int num_real {0}; // Number of 1×1 (real) blocks
|
2009-09-08 15:55:19 +02:00
|
|
|
|
public:
|
2019-01-15 18:55:09 +01:00
|
|
|
|
Diagonal() = default;
|
2019-03-28 18:56:46 +01:00
|
|
|
|
// Construct the diagonal blocks of (quasi-triangular) matrix ‘data’
|
2023-11-29 19:00:21 +01:00
|
|
|
|
Diagonal(double* data, int d_size);
|
2019-03-28 18:56:46 +01:00
|
|
|
|
/* Construct the diagonal blocks of (quasi-triangular) matrix ‘data’,
|
|
|
|
|
assuming it has the same shape as ‘d’ */
|
2023-11-29 19:00:21 +01:00
|
|
|
|
Diagonal(double* data, const Diagonal& d);
|
|
|
|
|
Diagonal(const Diagonal& d) = default;
|
|
|
|
|
Diagonal& operator=(const Diagonal& d) = default;
|
2019-01-15 18:55:09 +01:00
|
|
|
|
virtual ~Diagonal() = default;
|
2009-09-08 15:55:19 +02:00
|
|
|
|
|
2019-03-28 18:56:46 +01:00
|
|
|
|
// Returns number of 2×2 blocks on the diagonal
|
2023-12-05 15:44:23 +01:00
|
|
|
|
[[nodiscard]] int
|
2017-05-16 16:30:27 +02:00
|
|
|
|
getNumComplex() const
|
|
|
|
|
{
|
|
|
|
|
return num_all - num_real;
|
|
|
|
|
}
|
2019-03-28 18:56:46 +01:00
|
|
|
|
// Returns number of 1×1 blocks on the diagonal
|
2023-12-05 15:44:23 +01:00
|
|
|
|
[[nodiscard]] int
|
2017-05-16 16:30:27 +02:00
|
|
|
|
getNumReal() const
|
|
|
|
|
{
|
|
|
|
|
return num_real;
|
|
|
|
|
}
|
2019-03-28 18:56:46 +01:00
|
|
|
|
// Returns number of scalar elements on the diagonal
|
2023-12-05 15:44:23 +01:00
|
|
|
|
[[nodiscard]] int
|
2017-05-16 16:30:27 +02:00
|
|
|
|
getSize() const
|
|
|
|
|
{
|
2023-11-29 19:00:21 +01:00
|
|
|
|
return getNumReal() + 2 * getNumComplex();
|
2017-05-16 16:30:27 +02:00
|
|
|
|
}
|
2019-03-28 18:56:46 +01:00
|
|
|
|
// Returns total number of blocks on the diagonal
|
2023-12-05 15:44:23 +01:00
|
|
|
|
[[nodiscard]] int
|
2017-05-16 16:30:27 +02:00
|
|
|
|
getNumBlocks() const
|
|
|
|
|
{
|
|
|
|
|
return num_all;
|
|
|
|
|
}
|
2023-11-29 19:00:21 +01:00
|
|
|
|
void getEigenValues(Vector& eig) const;
|
2017-05-16 16:30:27 +02:00
|
|
|
|
void swapLogically(diag_iter it);
|
|
|
|
|
void checkConsistency(diag_iter it);
|
|
|
|
|
double getAverageSize(diag_iter start, diag_iter end);
|
|
|
|
|
diag_iter findClosestBlock(diag_iter start, diag_iter end, double a);
|
|
|
|
|
diag_iter findNextLargerBlock(diag_iter start, diag_iter end, double a);
|
|
|
|
|
void print() const;
|
2009-09-08 15:55:19 +02:00
|
|
|
|
|
2017-05-16 16:30:27 +02:00
|
|
|
|
diag_iter
|
|
|
|
|
begin()
|
|
|
|
|
{
|
2019-01-25 15:27:20 +01:00
|
|
|
|
return blocks.begin();
|
2017-05-16 16:30:27 +02:00
|
|
|
|
}
|
2023-12-05 15:44:23 +01:00
|
|
|
|
[[nodiscard]] const_diag_iter
|
2017-05-16 16:30:27 +02:00
|
|
|
|
begin() const
|
|
|
|
|
{
|
2019-01-25 15:27:20 +01:00
|
|
|
|
return blocks.begin();
|
2017-05-16 16:30:27 +02:00
|
|
|
|
}
|
|
|
|
|
diag_iter
|
|
|
|
|
end()
|
|
|
|
|
{
|
2019-01-25 15:27:20 +01:00
|
|
|
|
return blocks.end();
|
2017-05-16 16:30:27 +02:00
|
|
|
|
}
|
2023-12-05 15:44:23 +01:00
|
|
|
|
[[nodiscard]] const_diag_iter
|
2017-05-16 16:30:27 +02:00
|
|
|
|
end() const
|
|
|
|
|
{
|
2019-01-25 15:27:20 +01:00
|
|
|
|
return blocks.end();
|
2017-05-16 16:30:27 +02:00
|
|
|
|
}
|
2009-09-08 15:55:19 +02:00
|
|
|
|
|
2017-05-16 16:30:27 +02:00
|
|
|
|
/* redefine pointers as data start at p */
|
2023-11-29 19:00:21 +01:00
|
|
|
|
void changeBase(double* p);
|
|
|
|
|
|
2009-09-08 15:55:19 +02:00
|
|
|
|
private:
|
2019-01-16 17:52:16 +01:00
|
|
|
|
constexpr static double EPS = 1.0e-300;
|
2019-03-28 18:56:46 +01:00
|
|
|
|
/* Computes number of 2×2 diagonal blocks on the quasi-triangular matrix
|
|
|
|
|
represented by data (of size d_size×d_size) */
|
2023-11-29 19:00:21 +01:00
|
|
|
|
static int getNumComplex(const double* data, int d_size);
|
2019-03-28 18:56:46 +01:00
|
|
|
|
// Checks whether |p|<EPS
|
2017-05-16 16:30:27 +02:00
|
|
|
|
static bool isZero(double p);
|
2009-09-08 15:55:19 +02:00
|
|
|
|
};
|
|
|
|
|
|
2019-12-20 14:36:20 +01:00
|
|
|
|
template<class _TRef, class _TPtr>
|
2017-05-16 16:30:27 +02:00
|
|
|
|
struct _matrix_iter
|
|
|
|
|
{
|
2019-01-09 17:21:14 +01:00
|
|
|
|
using _Self = _matrix_iter<_TRef, _TPtr>;
|
2017-05-16 16:30:27 +02:00
|
|
|
|
int d_size;
|
|
|
|
|
bool real;
|
|
|
|
|
_TPtr ptr;
|
2023-11-29 19:00:21 +01:00
|
|
|
|
|
2009-09-08 15:55:19 +02:00
|
|
|
|
public:
|
2017-05-16 16:30:27 +02:00
|
|
|
|
_matrix_iter(_TPtr base, int ds, bool r)
|
|
|
|
|
{
|
2019-01-25 15:27:20 +01:00
|
|
|
|
ptr = base;
|
|
|
|
|
d_size = ds;
|
|
|
|
|
real = r;
|
2017-05-16 16:30:27 +02:00
|
|
|
|
}
|
2019-01-15 18:55:09 +01:00
|
|
|
|
virtual ~_matrix_iter() = default;
|
2017-05-16 16:30:27 +02:00
|
|
|
|
bool
|
2023-11-29 19:00:21 +01:00
|
|
|
|
operator==(const _Self& it) const
|
2017-05-16 16:30:27 +02:00
|
|
|
|
{
|
|
|
|
|
return ptr == it.ptr;
|
|
|
|
|
}
|
|
|
|
|
bool
|
2023-11-29 19:00:21 +01:00
|
|
|
|
operator!=(const _Self& it) const
|
2017-05-16 16:30:27 +02:00
|
|
|
|
{
|
|
|
|
|
return ptr != it.ptr;
|
|
|
|
|
}
|
|
|
|
|
_TRef
|
|
|
|
|
operator*() const
|
|
|
|
|
{
|
|
|
|
|
return *ptr;
|
|
|
|
|
}
|
|
|
|
|
_TRef
|
|
|
|
|
a() const
|
|
|
|
|
{
|
|
|
|
|
return *ptr;
|
|
|
|
|
}
|
2023-11-29 19:00:21 +01:00
|
|
|
|
virtual _Self& operator++() = 0;
|
2009-09-08 15:55:19 +02:00
|
|
|
|
};
|
|
|
|
|
|
2019-12-20 14:36:20 +01:00
|
|
|
|
template<class _TRef, class _TPtr>
|
2017-05-16 16:30:27 +02:00
|
|
|
|
class _column_iter : public _matrix_iter<_TRef, _TPtr>
|
|
|
|
|
{
|
2019-01-09 17:21:14 +01:00
|
|
|
|
using _Tparent = _matrix_iter<_TRef, _TPtr>;
|
|
|
|
|
using _Self = _column_iter<_TRef, _TPtr>;
|
2017-05-16 16:30:27 +02:00
|
|
|
|
int row;
|
2023-11-29 19:00:21 +01:00
|
|
|
|
|
2009-09-08 15:55:19 +02:00
|
|
|
|
public:
|
2023-11-29 19:00:21 +01:00
|
|
|
|
_column_iter(_TPtr base, int ds, bool r, int rw) :
|
|
|
|
|
_matrix_iter<_TRef, _TPtr>(base, ds, r), row(rw) {};
|
|
|
|
|
_Self&
|
2019-01-09 16:26:42 +01:00
|
|
|
|
operator++() override
|
2017-05-16 16:30:27 +02:00
|
|
|
|
{
|
2019-01-25 15:27:20 +01:00
|
|
|
|
_Tparent::ptr++;
|
|
|
|
|
row++;
|
|
|
|
|
return *this;
|
2017-05-16 16:30:27 +02:00
|
|
|
|
}
|
|
|
|
|
_TRef
|
|
|
|
|
b() const
|
|
|
|
|
{
|
|
|
|
|
if (_Tparent::real)
|
2019-01-25 15:27:20 +01:00
|
|
|
|
return *(_Tparent::ptr);
|
2017-05-16 16:30:27 +02:00
|
|
|
|
else
|
2023-11-29 19:00:21 +01:00
|
|
|
|
return *(_Tparent::ptr + _Tparent::d_size);
|
2017-05-16 16:30:27 +02:00
|
|
|
|
}
|
2023-12-05 15:44:23 +01:00
|
|
|
|
[[nodiscard]] int
|
2017-05-16 16:30:27 +02:00
|
|
|
|
getRow() const
|
|
|
|
|
{
|
|
|
|
|
return row;
|
|
|
|
|
}
|
2009-09-08 15:55:19 +02:00
|
|
|
|
};
|
|
|
|
|
|
2019-12-20 14:36:20 +01:00
|
|
|
|
template<class _TRef, class _TPtr>
|
2017-05-16 16:30:27 +02:00
|
|
|
|
class _row_iter : public _matrix_iter<_TRef, _TPtr>
|
|
|
|
|
{
|
2019-01-09 17:21:14 +01:00
|
|
|
|
using _Tparent = _matrix_iter<_TRef, _TPtr>;
|
|
|
|
|
using _Self = _row_iter<_TRef, _TPtr>;
|
2017-05-16 16:30:27 +02:00
|
|
|
|
int col;
|
2023-11-29 19:00:21 +01:00
|
|
|
|
|
2009-09-08 15:55:19 +02:00
|
|
|
|
public:
|
2023-11-29 19:00:21 +01:00
|
|
|
|
_row_iter(_TPtr base, int ds, bool r, int cl) :
|
|
|
|
|
_matrix_iter<_TRef, _TPtr>(base, ds, r), col(cl) {};
|
|
|
|
|
_Self&
|
2019-01-09 16:26:42 +01:00
|
|
|
|
operator++() override
|
2017-05-16 16:30:27 +02:00
|
|
|
|
{
|
2019-01-25 15:27:20 +01:00
|
|
|
|
_Tparent::ptr += _Tparent::d_size;
|
|
|
|
|
col++;
|
|
|
|
|
return *this;
|
2017-05-16 16:30:27 +02:00
|
|
|
|
}
|
|
|
|
|
virtual _TRef
|
|
|
|
|
b() const
|
|
|
|
|
{
|
|
|
|
|
if (_Tparent::real)
|
2019-01-25 15:27:20 +01:00
|
|
|
|
return *(_Tparent::ptr);
|
2017-05-16 16:30:27 +02:00
|
|
|
|
else
|
2023-11-29 19:00:21 +01:00
|
|
|
|
return *(_Tparent::ptr + 1);
|
2017-05-16 16:30:27 +02:00
|
|
|
|
}
|
2023-12-05 15:44:23 +01:00
|
|
|
|
[[nodiscard]] int
|
2017-05-16 16:30:27 +02:00
|
|
|
|
getCol() const
|
|
|
|
|
{
|
|
|
|
|
return col;
|
|
|
|
|
}
|
2009-09-08 15:55:19 +02:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class SchurDecomp;
|
|
|
|
|
class SchurDecompZero;
|
|
|
|
|
|
2019-01-25 15:27:20 +01:00
|
|
|
|
/* Represents an upper quasi-triangular matrix.
|
|
|
|
|
All the elements are stored in the SqSylvMatrix super-class.
|
2019-03-28 18:56:46 +01:00
|
|
|
|
Additionally, a list of the diagonal blocks (1×1 or 2×2), is stored in the
|
|
|
|
|
“diagonal” member, in order to optimize some operations (where the matrix is
|
|
|
|
|
seen as an upper-triangular matrix, plus sub-diagonal elements of the 2×2
|
2019-01-25 15:27:20 +01:00
|
|
|
|
diagonal blocks) */
|
2017-05-16 16:30:27 +02:00
|
|
|
|
class QuasiTriangular : public SqSylvMatrix
|
|
|
|
|
{
|
2009-09-08 15:55:19 +02:00
|
|
|
|
public:
|
2023-11-29 19:00:21 +01:00
|
|
|
|
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*>;
|
2019-01-09 17:21:14 +01:00
|
|
|
|
using const_diag_iter = Diagonal::const_diag_iter;
|
|
|
|
|
using diag_iter = Diagonal::diag_iter;
|
2023-11-29 19:00:21 +01:00
|
|
|
|
|
2009-09-08 15:55:19 +02:00
|
|
|
|
protected:
|
2017-05-16 16:30:27 +02:00
|
|
|
|
Diagonal diagonal;
|
2023-11-29 19:00:21 +01:00
|
|
|
|
|
2009-09-08 15:55:19 +02:00
|
|
|
|
public:
|
2023-11-29 19:00:21 +01:00
|
|
|
|
QuasiTriangular(const ConstVector& d, int d_size);
|
2019-03-29 15:27:34 +01:00
|
|
|
|
// Initializes with r·t
|
2023-11-29 19:00:21 +01:00
|
|
|
|
QuasiTriangular(double r, const QuasiTriangular& t);
|
2019-03-29 15:27:34 +01:00
|
|
|
|
// Initializes with r·t+r₂·t₂
|
2023-11-29 19:00:21 +01:00
|
|
|
|
QuasiTriangular(double r, const QuasiTriangular& t, double r2, const QuasiTriangular& t2);
|
2019-03-29 15:27:34 +01:00
|
|
|
|
// Initializes with t²
|
2023-11-29 19:00:21 +01:00
|
|
|
|
QuasiTriangular(const std::string& dummy, const QuasiTriangular& t);
|
|
|
|
|
explicit QuasiTriangular(const SchurDecomp& decomp);
|
|
|
|
|
explicit QuasiTriangular(const SchurDecompZero& decomp);
|
|
|
|
|
QuasiTriangular(const QuasiTriangular& t);
|
2019-12-20 14:36:20 +01:00
|
|
|
|
|
2019-01-15 18:55:09 +01:00
|
|
|
|
~QuasiTriangular() override = default;
|
2023-12-05 15:44:23 +01:00
|
|
|
|
[[nodiscard]] const Diagonal&
|
2017-05-16 16:30:27 +02:00
|
|
|
|
getDiagonal() const
|
|
|
|
|
{
|
|
|
|
|
return diagonal;
|
|
|
|
|
}
|
2023-12-05 15:44:23 +01:00
|
|
|
|
[[nodiscard]] int getNumOffdiagonal() const;
|
2017-05-16 16:30:27 +02:00
|
|
|
|
void swapDiagLogically(diag_iter it);
|
|
|
|
|
void checkDiagConsistency(diag_iter it);
|
|
|
|
|
double getAverageDiagSize(diag_iter start, diag_iter end);
|
|
|
|
|
diag_iter findClosestDiagBlock(diag_iter start, diag_iter end, double a);
|
|
|
|
|
diag_iter findNextLargerBlock(diag_iter start, diag_iter end, double a);
|
2009-09-08 15:55:19 +02:00
|
|
|
|
|
2019-03-28 18:56:46 +01:00
|
|
|
|
/* (I+this)·y = x, y→x */
|
2023-11-29 19:00:21 +01:00
|
|
|
|
virtual void solvePre(Vector& x, double& eig_min);
|
2019-03-28 18:56:46 +01:00
|
|
|
|
/* (I+thisᵀ)·y = x, y→x */
|
2023-11-29 19:00:21 +01:00
|
|
|
|
virtual void solvePreTrans(Vector& x, double& eig_min);
|
2019-03-28 18:56:46 +01:00
|
|
|
|
/* (I+this)·x = b */
|
2023-11-29 19:00:21 +01:00
|
|
|
|
virtual void solve(Vector& x, const ConstVector& b, double& eig_min);
|
2019-03-28 18:56:46 +01:00
|
|
|
|
/* (I+thisᵀ)·x = b */
|
2023-11-29 19:00:21 +01:00
|
|
|
|
virtual void solveTrans(Vector& x, const ConstVector& b, double& eig_min);
|
2019-03-28 18:56:46 +01:00
|
|
|
|
/* x = this·b */
|
2023-11-29 19:00:21 +01:00
|
|
|
|
virtual void multVec(Vector& x, const ConstVector& b) const;
|
2019-03-28 18:56:46 +01:00
|
|
|
|
/* x = thisᵀ·b */
|
2023-11-29 19:00:21 +01:00
|
|
|
|
virtual void multVecTrans(Vector& x, const ConstVector& b) const;
|
2019-03-28 18:56:46 +01:00
|
|
|
|
/* x = x + this·b */
|
2023-11-29 19:00:21 +01:00
|
|
|
|
virtual void multaVec(Vector& x, const ConstVector& b) const;
|
2019-03-28 18:56:46 +01:00
|
|
|
|
/* x = x + thisᵀ·b */
|
2023-11-29 19:00:21 +01:00
|
|
|
|
virtual void multaVecTrans(Vector& x, const ConstVector& b) const;
|
2019-03-28 18:56:46 +01:00
|
|
|
|
/* x = (this⊗I)·x */
|
2023-11-29 19:00:21 +01:00
|
|
|
|
virtual void multKron(KronVector& x) const;
|
2019-03-28 18:56:46 +01:00
|
|
|
|
/* x = (thisᵀ⊗I)·x */
|
2023-11-29 19:00:21 +01:00
|
|
|
|
virtual void multKronTrans(KronVector& x) const;
|
2019-03-28 18:56:46 +01:00
|
|
|
|
/* A = this·A */
|
2023-11-29 19:00:21 +01:00
|
|
|
|
virtual void multLeftOther(GeneralMatrix& a) const;
|
2019-03-28 18:56:46 +01:00
|
|
|
|
/* A = thisᵀ·A */
|
2023-11-29 19:00:21 +01:00
|
|
|
|
virtual void multLeftOtherTrans(GeneralMatrix& a) const;
|
2009-09-08 15:55:19 +02:00
|
|
|
|
|
2023-12-05 15:44:23 +01:00
|
|
|
|
[[nodiscard]] const_diag_iter
|
2017-05-16 16:30:27 +02:00
|
|
|
|
diag_begin() const
|
|
|
|
|
{
|
|
|
|
|
return diagonal.begin();
|
|
|
|
|
}
|
|
|
|
|
diag_iter
|
|
|
|
|
diag_begin()
|
|
|
|
|
{
|
|
|
|
|
return diagonal.begin();
|
|
|
|
|
}
|
2023-12-05 15:44:23 +01:00
|
|
|
|
[[nodiscard]] const_diag_iter
|
2017-05-16 16:30:27 +02:00
|
|
|
|
diag_end() const
|
|
|
|
|
{
|
|
|
|
|
return diagonal.end();
|
|
|
|
|
}
|
|
|
|
|
diag_iter
|
|
|
|
|
diag_end()
|
|
|
|
|
{
|
|
|
|
|
return diagonal.end();
|
|
|
|
|
}
|
2009-09-08 15:55:19 +02:00
|
|
|
|
|
2017-05-16 16:30:27 +02:00
|
|
|
|
/* iterators for off diagonal elements */
|
2023-12-05 15:44:23 +01:00
|
|
|
|
[[nodiscard]] virtual const_col_iter col_begin(const DiagonalBlock& b) const;
|
2023-11-29 19:00:21 +01:00
|
|
|
|
virtual col_iter col_begin(const DiagonalBlock& b);
|
2023-12-05 15:44:23 +01:00
|
|
|
|
[[nodiscard]] virtual const_row_iter row_begin(const DiagonalBlock& b) const;
|
2023-11-29 19:00:21 +01:00
|
|
|
|
virtual row_iter row_begin(const DiagonalBlock& b);
|
2023-12-05 15:44:23 +01:00
|
|
|
|
[[nodiscard]] virtual const_col_iter col_end(const DiagonalBlock& b) const;
|
2023-11-29 19:00:21 +01:00
|
|
|
|
virtual col_iter col_end(const DiagonalBlock& b);
|
2023-12-05 15:44:23 +01:00
|
|
|
|
[[nodiscard]] virtual const_row_iter row_end(const DiagonalBlock& b) const;
|
2023-11-29 19:00:21 +01:00
|
|
|
|
virtual row_iter row_end(const DiagonalBlock& b);
|
2009-09-08 15:55:19 +02:00
|
|
|
|
|
2023-12-05 15:44:23 +01:00
|
|
|
|
[[nodiscard]] virtual std::unique_ptr<QuasiTriangular>
|
2017-05-16 16:30:27 +02:00
|
|
|
|
clone() const
|
|
|
|
|
{
|
2019-01-15 18:55:09 +01:00
|
|
|
|
return std::make_unique<QuasiTriangular>(*this);
|
2017-05-16 16:30:27 +02:00
|
|
|
|
}
|
2019-03-29 15:27:34 +01:00
|
|
|
|
// Returns this²
|
2023-12-05 15:44:23 +01:00
|
|
|
|
[[nodiscard]] virtual std::unique_ptr<QuasiTriangular>
|
2019-03-29 15:27:34 +01:00
|
|
|
|
square() const
|
2017-05-16 16:30:27 +02:00
|
|
|
|
{
|
2019-03-29 15:27:34 +01:00
|
|
|
|
return std::make_unique<QuasiTriangular>("square", *this);
|
2017-05-16 16:30:27 +02:00
|
|
|
|
}
|
2019-03-29 15:27:34 +01:00
|
|
|
|
// Returns r·this
|
2023-12-05 15:44:23 +01:00
|
|
|
|
[[nodiscard]] virtual std::unique_ptr<QuasiTriangular>
|
2019-03-29 15:27:34 +01:00
|
|
|
|
scale(double r) const
|
2017-05-16 16:30:27 +02:00
|
|
|
|
{
|
2019-01-15 18:55:09 +01:00
|
|
|
|
return std::make_unique<QuasiTriangular>(r, *this);
|
2017-05-16 16:30:27 +02:00
|
|
|
|
}
|
2019-03-29 15:27:34 +01:00
|
|
|
|
// Returns r·this + r₂·t₂
|
2023-12-05 15:44:23 +01:00
|
|
|
|
[[nodiscard]] virtual std::unique_ptr<QuasiTriangular>
|
2023-11-29 19:00:21 +01:00
|
|
|
|
linearlyCombine(double r, double r2, const QuasiTriangular& t2) const
|
2017-05-16 16:30:27 +02:00
|
|
|
|
{
|
2019-03-29 15:27:34 +01:00
|
|
|
|
return std::make_unique<QuasiTriangular>(r, *this, r2, t2);
|
2017-05-16 16:30:27 +02:00
|
|
|
|
}
|
2023-11-29 19:00:21 +01:00
|
|
|
|
|
2009-09-08 15:55:19 +02:00
|
|
|
|
protected:
|
2019-03-28 18:56:46 +01:00
|
|
|
|
// this = r·t
|
2023-11-29 19:00:21 +01:00
|
|
|
|
void setMatrix(double r, const QuasiTriangular& t);
|
2019-03-28 18:56:46 +01:00
|
|
|
|
// this = this + r·t
|
2023-11-29 19:00:21 +01:00
|
|
|
|
void addMatrix(double r, const QuasiTriangular& t);
|
|
|
|
|
|
2009-09-08 15:55:19 +02:00
|
|
|
|
private:
|
2019-03-28 18:56:46 +01:00
|
|
|
|
// this = this + I
|
2017-05-16 16:30:27 +02:00
|
|
|
|
void addUnit();
|
2019-03-28 18:56:46 +01:00
|
|
|
|
/* x = x + (this⊗I)·b */
|
2023-11-29 19:00:21 +01:00
|
|
|
|
void multaKron(KronVector& x, const ConstKronVector& b) const;
|
2019-03-28 18:56:46 +01:00
|
|
|
|
/* x = x + (thisᵀ⊗I)·b */
|
2023-11-29 19:00:21 +01:00
|
|
|
|
void multaKronTrans(KronVector& x, const ConstKronVector& b) const;
|
2017-05-16 16:30:27 +02:00
|
|
|
|
/* hide noneffective implementations of parents */
|
2023-11-29 19:00:21 +01:00
|
|
|
|
void multsVec(Vector& x, const ConstVector& d) const;
|
|
|
|
|
void multsVecTrans(Vector& x, const ConstVector& d) const;
|
2009-09-08 15:55:19 +02:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
#endif /* QUASI_TRIANGULAR_H */
|