2019-06-19 14:34:30 +02:00
|
|
|
|
/*
|
|
|
|
|
* Copyright © 2004 Ondra Kamenik
|
2023-04-11 14:46:04 +02: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
|
|
|
|
*/
|
2019-01-08 16:09:25 +01:00
|
|
|
|
|
|
|
|
|
// Stack of containers.
|
|
|
|
|
|
|
|
|
|
/* Here we develop abstractions for stacked containers of tensors. For
|
2019-03-27 19:22:35 +01:00
|
|
|
|
instance, in perturbation methods for DSGE models, we need the function:
|
|
|
|
|
|
2019-04-05 18:39:47 +02:00
|
|
|
|
⎛ G(y*,u,u′,σ) ⎞
|
|
|
|
|
z(y*,u,u′,σ) = ⎢ g(y*,u,σ) ⎥
|
|
|
|
|
⎢ y* ⎥
|
|
|
|
|
⎝ u ⎠
|
2019-03-27 19:22:35 +01:00
|
|
|
|
|
|
|
|
|
and we need to calculate one step of Faà Di Bruno formula:
|
|
|
|
|
|
2019-04-05 18:39:47 +02:00
|
|
|
|
ₗ
|
2019-05-06 18:43:54 +02:00
|
|
|
|
[B_sᵏ]_α₁…αₗ = [f_zˡ]_β₁…βₗ ∑ ∏ [z_{s^|cₘ|}]_cₘ(α)^βₘ
|
2019-04-05 18:39:47 +02:00
|
|
|
|
c∈ℳₗ,ₖ ᵐ⁼¹
|
2019-03-27 19:22:35 +01:00
|
|
|
|
|
|
|
|
|
where we have containers for derivatives of G and g.
|
2019-01-08 16:09:25 +01:00
|
|
|
|
|
|
|
|
|
The main purpose of this file is to define abstractions for stack of
|
2019-03-27 19:22:35 +01:00
|
|
|
|
containers and possibly raw variables, and code multAndAdd() method
|
|
|
|
|
calculating (one step of) the Faà Di Bruno formula for folded and
|
|
|
|
|
unfolded tensors. Note also, that tensors [f_zˡ] are sparse.
|
2019-01-08 16:09:25 +01:00
|
|
|
|
|
|
|
|
|
The abstractions are built as follows. At the top, there is an
|
|
|
|
|
interface describing stack of columns. It contains pure virtual
|
|
|
|
|
methods needed for manipulating the container stack. For technical
|
|
|
|
|
reasons it is a template. Both versions (folded, and unfolded) provide
|
2019-03-27 19:22:35 +01:00
|
|
|
|
all interface necessary for implementation of multAndAdd(). The second
|
2019-01-08 16:09:25 +01:00
|
|
|
|
way of inheritance is first general implementation of the interface
|
2019-03-27 19:22:35 +01:00
|
|
|
|
StackContainer, and then specific (ZContainer for our specific z).
|
|
|
|
|
The only method which is virtual also after StackContainer is
|
|
|
|
|
getType(), which is implemented in the specialization and determines
|
2019-01-08 16:09:25 +01:00
|
|
|
|
behaviour of the stack. The complete classes are obtained by
|
|
|
|
|
inheriting from the both branches, as it is drawn below:
|
|
|
|
|
|
2019-05-06 18:43:54 +02:00
|
|
|
|
|
|
|
|
|
StackContainerInterface<FGSTensor>
|
|
|
|
|
↙ ↘
|
|
|
|
|
StackContainer<FGSTensor> FoldedStackContainer
|
|
|
|
|
↓
|
|
|
|
|
ZContainer<FGSTensor> ↙
|
|
|
|
|
↘
|
|
|
|
|
FoldedZContainer
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
StackContainerInterface<UGSTensor>
|
|
|
|
|
↙ ↘
|
|
|
|
|
StackContainer<UGSTensor> UnfoldedStackContainer
|
|
|
|
|
↓
|
|
|
|
|
ZContainer<UGSTensor> ↙
|
|
|
|
|
↘
|
|
|
|
|
UnfoldedZContainer
|
|
|
|
|
|
2019-01-08 16:09:25 +01:00
|
|
|
|
|
2019-03-27 19:22:35 +01:00
|
|
|
|
We have also two supporting classes StackProduct and KronProdStack
|
2019-01-08 16:09:25 +01:00
|
|
|
|
and a number of worker classes used as threads. */
|
|
|
|
|
|
|
|
|
|
#ifndef STACK_CONTAINER_H
|
|
|
|
|
#define STACK_CONTAINER_H
|
|
|
|
|
|
|
|
|
|
#include "equivalence.hh"
|
2023-11-29 19:00:21 +01:00
|
|
|
|
#include "int_sequence.hh"
|
2019-01-08 16:09:25 +01:00
|
|
|
|
#include "kron_prod.hh"
|
|
|
|
|
#include "permutation.hh"
|
|
|
|
|
#include "sthread.hh"
|
2023-11-29 19:00:21 +01:00
|
|
|
|
#include "t_container.hh"
|
|
|
|
|
#include "tl_static.hh"
|
2019-01-08 16:09:25 +01:00
|
|
|
|
|
|
|
|
|
/* Here is the general interface to stack container. The subclasses
|
2019-05-06 18:43:54 +02:00
|
|
|
|
maintain IntSequence of stack sizes, i.e. size of G, g, y, and
|
|
|
|
|
u. Then a convenience IntSequence of stack offsets. Then vector of
|
|
|
|
|
pointers to containers, in our example G, and g.
|
2019-01-08 16:09:25 +01:00
|
|
|
|
|
2019-05-06 18:43:54 +02:00
|
|
|
|
A non-virtual subclass must implement getType() which determines
|
2019-01-08 16:09:25 +01:00
|
|
|
|
dependency of stack items on symmetries. There are three possible types
|
|
|
|
|
for a symmetry. Either the stack item derivative wrt. the symmetry is
|
|
|
|
|
a matrix, or a unit matrix, or zero.
|
|
|
|
|
|
2019-05-06 18:43:54 +02:00
|
|
|
|
Method isZero() returns true if the derivative of a given stack item
|
|
|
|
|
wrt. to given symmetry is zero as defined by getType() or the
|
2019-01-08 16:09:25 +01:00
|
|
|
|
derivative is not present in the container. In this way, we can
|
|
|
|
|
implement the formula conditional some of the tensors are zero, which
|
|
|
|
|
is not true (they are only missing).
|
|
|
|
|
|
2019-05-06 18:43:54 +02:00
|
|
|
|
Method createPackedColumn() returns a vector of stack derivatives with
|
2019-01-08 16:09:25 +01:00
|
|
|
|
respect to the given symmetry and of the given column, where all zeros
|
2019-03-27 19:22:35 +01:00
|
|
|
|
from zero types, or unit matrices are deleted. See kron_prod.hh for an
|
|
|
|
|
explanation. */
|
2019-01-08 16:09:25 +01:00
|
|
|
|
|
2019-12-20 14:36:20 +01:00
|
|
|
|
template<class _Ttype>
|
2019-01-08 16:09:25 +01:00
|
|
|
|
class StackContainerInterface
|
|
|
|
|
{
|
|
|
|
|
public:
|
2019-01-09 17:21:14 +01:00
|
|
|
|
using _Ctype = TensorContainer<_Ttype>;
|
2023-11-29 19:00:21 +01:00
|
|
|
|
enum class itype
|
|
|
|
|
{
|
|
|
|
|
matrix,
|
|
|
|
|
unit,
|
|
|
|
|
zero
|
|
|
|
|
};
|
|
|
|
|
|
2019-01-08 16:09:25 +01:00
|
|
|
|
public:
|
2019-02-21 18:46:53 +01:00
|
|
|
|
StackContainerInterface() = default;
|
2019-02-26 18:57:36 +01:00
|
|
|
|
virtual ~StackContainerInterface() = default;
|
2023-12-05 15:44:23 +01:00
|
|
|
|
[[nodiscard]] virtual const IntSequence& getStackSizes() const = 0;
|
2023-11-29 19:00:21 +01:00
|
|
|
|
virtual IntSequence& getStackSizes() = 0;
|
2023-12-05 15:44:23 +01:00
|
|
|
|
[[nodiscard]] virtual const IntSequence& getStackOffsets() const = 0;
|
2023-11-29 19:00:21 +01:00
|
|
|
|
virtual IntSequence& getStackOffsets() = 0;
|
2023-12-05 15:44:23 +01:00
|
|
|
|
[[nodiscard]] virtual int numConts() const = 0;
|
|
|
|
|
[[nodiscard]] virtual const _Ctype& getCont(int i) const = 0;
|
|
|
|
|
[[nodiscard]] virtual itype getType(int i, const Symmetry& s) const = 0;
|
|
|
|
|
[[nodiscard]] virtual int numStacks() const = 0;
|
|
|
|
|
[[nodiscard]] virtual bool isZero(int i, const Symmetry& s) const = 0;
|
|
|
|
|
[[nodiscard]] virtual const _Ttype& getMatrix(int i, const Symmetry& s) const = 0;
|
|
|
|
|
[[nodiscard]] virtual int getLengthOfMatrixStacks(const Symmetry& s) const = 0;
|
|
|
|
|
[[nodiscard]] virtual int getUnitPos(const Symmetry& s) const = 0;
|
2023-11-29 19:00:21 +01:00
|
|
|
|
virtual std::unique_ptr<Vector> createPackedColumn(const Symmetry& s, const IntSequence& coor,
|
|
|
|
|
int& iu) const
|
|
|
|
|
= 0;
|
2023-12-05 15:44:23 +01:00
|
|
|
|
[[nodiscard]] int
|
2019-01-08 16:09:25 +01:00
|
|
|
|
getAllSize() const
|
|
|
|
|
{
|
2023-11-29 19:00:21 +01:00
|
|
|
|
return getStackOffsets()[numStacks() - 1] + getStackSizes()[numStacks() - 1];
|
2019-01-08 16:09:25 +01:00
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2019-05-06 18:43:54 +02:00
|
|
|
|
/* Here is StackContainer, which implements almost all interface
|
|
|
|
|
StackContainerInterface but one method getType() which is left for
|
2019-02-26 18:57:36 +01:00
|
|
|
|
implementation to specializations.
|
|
|
|
|
|
|
|
|
|
It does not own its tensors. */
|
2019-01-08 16:09:25 +01:00
|
|
|
|
|
2019-12-20 14:36:20 +01:00
|
|
|
|
template<class _Ttype>
|
2019-01-08 16:09:25 +01:00
|
|
|
|
class StackContainer : virtual public StackContainerInterface<_Ttype>
|
|
|
|
|
{
|
|
|
|
|
public:
|
2019-01-09 17:21:14 +01:00
|
|
|
|
using _Stype = StackContainerInterface<_Ttype>;
|
|
|
|
|
using _Ctype = typename StackContainerInterface<_Ttype>::_Ctype;
|
|
|
|
|
using itype = typename StackContainerInterface<_Ttype>::itype;
|
2023-11-29 19:00:21 +01:00
|
|
|
|
|
2019-01-08 16:09:25 +01:00
|
|
|
|
protected:
|
|
|
|
|
int num_conts;
|
|
|
|
|
IntSequence stack_sizes;
|
|
|
|
|
IntSequence stack_offsets;
|
2023-11-29 19:00:21 +01:00
|
|
|
|
std::vector<const _Ctype*> conts;
|
|
|
|
|
|
2019-01-08 16:09:25 +01:00
|
|
|
|
public:
|
2023-11-29 19:00:21 +01:00
|
|
|
|
StackContainer(int ns, int nc) : stack_sizes(ns, 0), stack_offsets(ns, 0), conts(nc)
|
2019-01-08 16:09:25 +01:00
|
|
|
|
{
|
|
|
|
|
}
|
2023-12-05 15:44:23 +01:00
|
|
|
|
[[nodiscard]] const IntSequence&
|
2019-01-09 16:26:42 +01:00
|
|
|
|
getStackSizes() const override
|
2019-01-08 16:09:25 +01:00
|
|
|
|
{
|
|
|
|
|
return stack_sizes;
|
|
|
|
|
}
|
2023-11-29 19:00:21 +01:00
|
|
|
|
IntSequence&
|
2019-01-09 16:26:42 +01:00
|
|
|
|
getStackSizes() override
|
2019-01-08 16:09:25 +01:00
|
|
|
|
{
|
|
|
|
|
return stack_sizes;
|
|
|
|
|
}
|
2023-12-05 15:44:23 +01:00
|
|
|
|
[[nodiscard]] const IntSequence&
|
2019-01-09 16:26:42 +01:00
|
|
|
|
getStackOffsets() const override
|
2019-01-08 16:09:25 +01:00
|
|
|
|
{
|
|
|
|
|
return stack_offsets;
|
|
|
|
|
}
|
2023-11-29 19:00:21 +01:00
|
|
|
|
IntSequence&
|
2019-01-09 16:26:42 +01:00
|
|
|
|
getStackOffsets() override
|
2019-01-08 16:09:25 +01:00
|
|
|
|
{
|
|
|
|
|
return stack_offsets;
|
|
|
|
|
}
|
2023-12-05 15:44:23 +01:00
|
|
|
|
[[nodiscard]] int
|
2019-01-09 16:26:42 +01:00
|
|
|
|
numConts() const override
|
2019-01-08 16:09:25 +01:00
|
|
|
|
{
|
2019-02-26 18:57:36 +01:00
|
|
|
|
return conts.size();
|
2019-01-08 16:09:25 +01:00
|
|
|
|
}
|
2023-12-05 15:44:23 +01:00
|
|
|
|
[[nodiscard]] const _Ctype&
|
2019-01-09 16:26:42 +01:00
|
|
|
|
getCont(int i) const override
|
2019-01-08 16:09:25 +01:00
|
|
|
|
{
|
2019-02-26 18:57:36 +01:00
|
|
|
|
return *(conts[i]);
|
2019-01-08 16:09:25 +01:00
|
|
|
|
}
|
2023-12-05 15:44:23 +01:00
|
|
|
|
[[nodiscard]] itype getType(int i, const Symmetry& s) const override = 0;
|
|
|
|
|
[[nodiscard]] int
|
2019-01-09 16:26:42 +01:00
|
|
|
|
numStacks() const override
|
2019-01-08 16:09:25 +01:00
|
|
|
|
{
|
|
|
|
|
return stack_sizes.size();
|
|
|
|
|
}
|
2023-12-05 15:44:23 +01:00
|
|
|
|
[[nodiscard]] bool
|
2023-11-29 19:00:21 +01:00
|
|
|
|
isZero(int i, const Symmetry& s) const override
|
2019-01-08 16:09:25 +01:00
|
|
|
|
{
|
2023-11-29 19:00:21 +01:00
|
|
|
|
TL_RAISE_IF(i < 0 || i >= numStacks(), "Wrong index to stack in StackContainer::isZero.");
|
2019-02-26 18:57:36 +01:00
|
|
|
|
return (getType(i, s) == itype::zero
|
|
|
|
|
|| (getType(i, s) == itype::matrix && !conts[i]->check(s)));
|
2019-01-08 16:09:25 +01:00
|
|
|
|
}
|
|
|
|
|
|
2023-12-05 15:44:23 +01:00
|
|
|
|
[[nodiscard]] const _Ttype&
|
2023-11-29 19:00:21 +01:00
|
|
|
|
getMatrix(int i, const Symmetry& s) const override
|
2019-01-08 16:09:25 +01:00
|
|
|
|
{
|
2019-02-26 18:57:36 +01:00
|
|
|
|
TL_RAISE_IF(isZero(i, s) || getType(i, s) == itype::unit,
|
2019-01-08 16:09:25 +01:00
|
|
|
|
"Matrix is not returned in StackContainer::getMatrix");
|
|
|
|
|
return conts[i]->get(s);
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-05 15:44:23 +01:00
|
|
|
|
[[nodiscard]] int
|
2023-11-29 19:00:21 +01:00
|
|
|
|
getLengthOfMatrixStacks(const Symmetry& s) const override
|
2019-01-08 16:09:25 +01:00
|
|
|
|
{
|
|
|
|
|
int res = 0;
|
|
|
|
|
int i = 0;
|
2019-02-26 18:57:36 +01:00
|
|
|
|
while (i < numStacks() && getType(i, s) == itype::matrix)
|
2019-01-08 16:09:25 +01:00
|
|
|
|
res += stack_sizes[i++];
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-05 15:44:23 +01:00
|
|
|
|
[[nodiscard]] int
|
2023-11-29 19:00:21 +01:00
|
|
|
|
getUnitPos(const Symmetry& s) const override
|
2019-01-08 16:09:25 +01:00
|
|
|
|
{
|
|
|
|
|
if (s.dimen() != 1)
|
|
|
|
|
return -1;
|
2023-11-29 19:00:21 +01:00
|
|
|
|
int i = numStacks() - 1;
|
2019-02-26 18:57:36 +01:00
|
|
|
|
while (i >= 0 && getType(i, s) != itype::unit)
|
2019-01-08 16:09:25 +01:00
|
|
|
|
i--;
|
|
|
|
|
return i;
|
|
|
|
|
}
|
|
|
|
|
|
2019-02-26 18:57:36 +01:00
|
|
|
|
std::unique_ptr<Vector>
|
2023-11-29 19:00:21 +01:00
|
|
|
|
createPackedColumn(const Symmetry& s, const IntSequence& coor, int& iu) const override
|
2019-01-08 16:09:25 +01:00
|
|
|
|
{
|
|
|
|
|
TL_RAISE_IF(s.dimen() != coor.size(),
|
|
|
|
|
"Incompatible coordinates for symmetry in StackContainer::createPackedColumn");
|
|
|
|
|
|
|
|
|
|
int len = getLengthOfMatrixStacks(s);
|
|
|
|
|
iu = -1;
|
|
|
|
|
int i = 0;
|
|
|
|
|
if (-1 != (i = getUnitPos(s)))
|
|
|
|
|
{
|
|
|
|
|
iu = stack_offsets[i] + coor[0];
|
|
|
|
|
len++;
|
|
|
|
|
}
|
|
|
|
|
|
2019-02-26 18:57:36 +01:00
|
|
|
|
auto res = std::make_unique<Vector>(len);
|
2019-01-08 16:09:25 +01:00
|
|
|
|
i = 0;
|
2019-02-26 18:57:36 +01:00
|
|
|
|
while (i < numStacks() && getType(i, s) == itype::matrix)
|
2019-01-08 16:09:25 +01:00
|
|
|
|
{
|
2023-11-29 19:00:21 +01:00
|
|
|
|
const _Ttype& t = getMatrix(i, s);
|
2019-02-20 17:51:05 +01:00
|
|
|
|
Tensor::index ind(t, coor);
|
2019-01-08 16:09:25 +01:00
|
|
|
|
Vector subres(*res, stack_offsets[i], stack_sizes[i]);
|
2019-02-20 17:51:05 +01:00
|
|
|
|
subres = ConstGeneralMatrix(t).getCol(*ind);
|
2019-01-08 16:09:25 +01:00
|
|
|
|
i++;
|
|
|
|
|
}
|
|
|
|
|
if (iu != -1)
|
2023-11-29 19:00:21 +01:00
|
|
|
|
(*res)[len - 1] = 1;
|
2019-01-08 16:09:25 +01:00
|
|
|
|
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
void
|
|
|
|
|
calculateOffsets()
|
|
|
|
|
{
|
|
|
|
|
stack_offsets[0] = 0;
|
|
|
|
|
for (int i = 1; i < stack_offsets.size(); i++)
|
2023-11-29 19:00:21 +01:00
|
|
|
|
stack_offsets[i] = stack_offsets[i - 1] + stack_sizes[i - 1];
|
2019-01-08 16:09:25 +01:00
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class WorkerFoldMAADense;
|
|
|
|
|
class WorkerFoldMAASparse1;
|
|
|
|
|
class WorkerFoldMAASparse2;
|
|
|
|
|
class WorkerFoldMAASparse4;
|
|
|
|
|
class FoldedStackContainer : virtual public StackContainerInterface<FGSTensor>
|
|
|
|
|
{
|
|
|
|
|
friend class WorkerFoldMAADense;
|
|
|
|
|
friend class WorkerFoldMAASparse1;
|
|
|
|
|
friend class WorkerFoldMAASparse2;
|
|
|
|
|
friend class WorkerFoldMAASparse4;
|
2023-11-29 19:00:21 +01:00
|
|
|
|
|
2019-01-08 16:09:25 +01:00
|
|
|
|
public:
|
2019-02-27 19:07:01 +01:00
|
|
|
|
static constexpr double fill_threshold = 0.00005;
|
2019-01-08 16:09:25 +01:00
|
|
|
|
void
|
2023-11-29 19:00:21 +01:00
|
|
|
|
multAndAdd(int dim, const TensorContainer<FSSparseTensor>& c, FGSTensor& out) const
|
2019-01-08 16:09:25 +01:00
|
|
|
|
{
|
2023-11-29 19:00:21 +01:00
|
|
|
|
if (c.check(Symmetry {dim}))
|
|
|
|
|
multAndAdd(c.get(Symmetry {dim}), out);
|
2019-01-08 16:09:25 +01:00
|
|
|
|
}
|
2023-11-29 19:00:21 +01:00
|
|
|
|
void multAndAdd(const FSSparseTensor& t, FGSTensor& out) const;
|
|
|
|
|
void multAndAdd(int dim, const FGSContainer& c, FGSTensor& out) const;
|
|
|
|
|
|
2019-01-08 16:09:25 +01:00
|
|
|
|
protected:
|
2023-11-29 19:00:21 +01:00
|
|
|
|
void multAndAddSparse1(const FSSparseTensor& t, FGSTensor& out) const;
|
|
|
|
|
void multAndAddSparse2(const FSSparseTensor& t, FGSTensor& out) const;
|
|
|
|
|
void multAndAddSparse3(const FSSparseTensor& t, FGSTensor& out) const;
|
|
|
|
|
void multAndAddSparse4(const FSSparseTensor& t, FGSTensor& out) const;
|
|
|
|
|
void multAndAddStacks(const IntSequence& fi, const FGSTensor& g, FGSTensor& out,
|
|
|
|
|
std::mutex& mut) const;
|
|
|
|
|
void multAndAddStacks(const IntSequence& fi, const GSSparseTensor& g, FGSTensor& out,
|
|
|
|
|
std::mutex& mut) const;
|
2019-01-08 16:09:25 +01:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class WorkerUnfoldMAADense;
|
|
|
|
|
class WorkerUnfoldMAASparse1;
|
|
|
|
|
class WorkerUnfoldMAASparse2;
|
|
|
|
|
class UnfoldedStackContainer : virtual public StackContainerInterface<UGSTensor>
|
|
|
|
|
{
|
|
|
|
|
friend class WorkerUnfoldMAADense;
|
|
|
|
|
friend class WorkerUnfoldMAASparse1;
|
|
|
|
|
friend class WorkerUnfoldMAASparse2;
|
2023-11-29 19:00:21 +01:00
|
|
|
|
|
2019-01-08 16:09:25 +01:00
|
|
|
|
public:
|
2019-02-27 19:07:01 +01:00
|
|
|
|
static constexpr double fill_threshold = 0.00005;
|
2019-01-08 16:09:25 +01:00
|
|
|
|
void
|
2023-11-29 19:00:21 +01:00
|
|
|
|
multAndAdd(int dim, const TensorContainer<FSSparseTensor>& c, UGSTensor& out) const
|
2019-01-08 16:09:25 +01:00
|
|
|
|
{
|
2023-11-29 19:00:21 +01:00
|
|
|
|
if (c.check(Symmetry {dim}))
|
|
|
|
|
multAndAdd(c.get(Symmetry {dim}), out);
|
2019-01-08 16:09:25 +01:00
|
|
|
|
}
|
2023-11-29 19:00:21 +01:00
|
|
|
|
void multAndAdd(const FSSparseTensor& t, UGSTensor& out) const;
|
|
|
|
|
void multAndAdd(int dim, const UGSContainer& c, UGSTensor& out) const;
|
|
|
|
|
|
2019-01-08 16:09:25 +01:00
|
|
|
|
protected:
|
2023-11-29 19:00:21 +01:00
|
|
|
|
void multAndAddSparse1(const FSSparseTensor& t, UGSTensor& out) const;
|
|
|
|
|
void multAndAddSparse2(const FSSparseTensor& t, UGSTensor& out) const;
|
|
|
|
|
void multAndAddStacks(const IntSequence& fi, const UGSTensor& g, UGSTensor& out,
|
|
|
|
|
std::mutex& mut) const;
|
2019-01-08 16:09:25 +01:00
|
|
|
|
};
|
|
|
|
|
|
2021-06-15 14:30:32 +02:00
|
|
|
|
/* Here is the specialization of the StackContainer. We implement
|
2023-11-29 19:00:21 +01:00
|
|
|
|
here the x needed in DSGE context for welfare assessment. We implement getType() and define a
|
|
|
|
|
constructor feeding the data and sizes.
|
2021-06-15 14:30:32 +02:00
|
|
|
|
|
2023-11-29 19:00:21 +01:00
|
|
|
|
It depends on four variables U(y,u,u',σ), the variable u' being introduced to enable additions
|
|
|
|
|
with 4-variable tensors*/
|
2021-06-15 14:30:32 +02:00
|
|
|
|
|
|
|
|
|
template<class _Ttype>
|
|
|
|
|
class XContainer : public StackContainer<_Ttype>
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
using _Tparent = StackContainer<_Ttype>;
|
|
|
|
|
using _Stype = StackContainerInterface<_Ttype>;
|
|
|
|
|
using _Ctype = typename _Tparent::_Ctype;
|
|
|
|
|
using itype = typename _Tparent::itype;
|
2023-11-29 19:00:21 +01:00
|
|
|
|
XContainer(const _Ctype* g, int ng) : _Tparent(1, 1)
|
2021-06-15 14:30:32 +02:00
|
|
|
|
{
|
2023-11-29 19:00:21 +01:00
|
|
|
|
_Tparent::stack_sizes = {ng};
|
2021-06-15 14:30:32 +02:00
|
|
|
|
_Tparent::conts[0] = g;
|
|
|
|
|
_Tparent::calculateOffsets();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Here we say, what happens if we derive z. recall the top of the
|
|
|
|
|
file, how z looks, and code is clear. */
|
|
|
|
|
|
2023-12-05 15:44:23 +01:00
|
|
|
|
[[nodiscard]] itype
|
2023-11-29 19:00:21 +01:00
|
|
|
|
getType(int i, const Symmetry& s) const override
|
2021-06-15 14:30:32 +02:00
|
|
|
|
{
|
2023-11-29 19:00:21 +01:00
|
|
|
|
if (i == 0)
|
2023-04-11 14:46:04 +02:00
|
|
|
|
{
|
|
|
|
|
if (s[2] > 0)
|
|
|
|
|
return itype::zero;
|
|
|
|
|
else
|
|
|
|
|
return itype::matrix;
|
|
|
|
|
}
|
2021-06-15 14:30:32 +02:00
|
|
|
|
|
|
|
|
|
TL_RAISE("Wrong stack index in XContainer::getType");
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2023-11-29 19:00:21 +01:00
|
|
|
|
class FoldedXContainer : public XContainer<FGSTensor>, public FoldedStackContainer
|
2021-06-15 14:30:32 +02:00
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
using _Ctype = TensorContainer<FGSTensor>;
|
2023-11-29 19:00:21 +01:00
|
|
|
|
FoldedXContainer(const _Ctype* g, int ng) : XContainer<FGSTensor>(g, ng)
|
2021-06-15 14:30:32 +02:00
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2023-11-29 19:00:21 +01:00
|
|
|
|
class UnfoldedXContainer : public XContainer<UGSTensor>, public UnfoldedStackContainer
|
2021-06-15 14:30:32 +02:00
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
using _Ctype = TensorContainer<UGSTensor>;
|
2023-11-29 19:00:21 +01:00
|
|
|
|
UnfoldedXContainer(const _Ctype* g, int ng) : XContainer<UGSTensor>(g, ng)
|
2021-06-15 14:30:32 +02:00
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
};
|
2019-05-06 18:43:54 +02:00
|
|
|
|
/* Here is the specialization of the StackContainer. We implement
|
|
|
|
|
here the z needed in DSGE context. We implement getType() and define
|
2019-01-08 16:09:25 +01:00
|
|
|
|
a constructor feeding the data and sizes.
|
|
|
|
|
|
2019-05-06 18:43:54 +02:00
|
|
|
|
Note that it has two containers, the first is dependent on four variables
|
|
|
|
|
G(y*,u,u′,σ), and the second dependent on three variables g(y*,u,σ). So that
|
|
|
|
|
we would be able to stack them, we make the second container g be dependent
|
|
|
|
|
on four variables, the third being u′ a dummy and always returning zero if
|
|
|
|
|
dimension of u′ is positive. */
|
2019-01-08 16:09:25 +01:00
|
|
|
|
|
2019-12-20 14:36:20 +01:00
|
|
|
|
template<class _Ttype>
|
2019-01-08 16:09:25 +01:00
|
|
|
|
class ZContainer : public StackContainer<_Ttype>
|
|
|
|
|
{
|
|
|
|
|
public:
|
2019-01-09 17:21:14 +01:00
|
|
|
|
using _Tparent = StackContainer<_Ttype>;
|
|
|
|
|
using _Stype = StackContainerInterface<_Ttype>;
|
|
|
|
|
using _Ctype = typename _Tparent::_Ctype;
|
|
|
|
|
using itype = typename _Tparent::itype;
|
2023-11-29 19:00:21 +01:00
|
|
|
|
ZContainer(const _Ctype* gss, int ngss, const _Ctype* g, int ng, int ny, int nu) : _Tparent(4, 2)
|
2019-01-08 16:09:25 +01:00
|
|
|
|
{
|
2023-11-29 19:00:21 +01:00
|
|
|
|
_Tparent::stack_sizes = {ngss, ng, ny, nu};
|
2019-01-08 16:09:25 +01:00
|
|
|
|
_Tparent::conts[0] = gss;
|
|
|
|
|
_Tparent::conts[1] = g;
|
|
|
|
|
_Tparent::calculateOffsets();
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-06 18:43:54 +02:00
|
|
|
|
/* Here we say, what happens if we derive z. recall the top of the
|
|
|
|
|
file, how z looks, and code is clear. */
|
2019-01-08 16:09:25 +01:00
|
|
|
|
|
2023-12-05 15:44:23 +01:00
|
|
|
|
[[nodiscard]] itype
|
2023-11-29 19:00:21 +01:00
|
|
|
|
getType(int i, const Symmetry& s) const override
|
2019-01-08 16:09:25 +01:00
|
|
|
|
{
|
|
|
|
|
if (i == 0)
|
2019-02-26 18:57:36 +01:00
|
|
|
|
return itype::matrix;
|
2019-01-08 16:09:25 +01:00
|
|
|
|
if (i == 1)
|
2023-04-11 14:46:04 +02:00
|
|
|
|
{
|
|
|
|
|
if (s[2] > 0)
|
|
|
|
|
return itype::zero;
|
|
|
|
|
else
|
|
|
|
|
return itype::matrix;
|
|
|
|
|
}
|
2019-01-08 16:09:25 +01:00
|
|
|
|
if (i == 2)
|
2023-04-11 14:46:04 +02:00
|
|
|
|
{
|
2023-11-29 19:00:21 +01:00
|
|
|
|
if (s == Symmetry {1, 0, 0, 0})
|
2023-04-11 14:46:04 +02:00
|
|
|
|
return itype::unit;
|
|
|
|
|
else
|
|
|
|
|
return itype::zero;
|
|
|
|
|
}
|
2019-01-08 16:09:25 +01:00
|
|
|
|
if (i == 3)
|
2023-04-11 14:46:04 +02:00
|
|
|
|
{
|
2023-11-29 19:00:21 +01:00
|
|
|
|
if (s == Symmetry {0, 1, 0, 0})
|
2023-04-11 14:46:04 +02:00
|
|
|
|
return itype::unit;
|
|
|
|
|
else
|
|
|
|
|
return itype::zero;
|
|
|
|
|
}
|
2019-01-08 16:09:25 +01:00
|
|
|
|
|
|
|
|
|
TL_RAISE("Wrong stack index in ZContainer::getType");
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2023-11-29 19:00:21 +01:00
|
|
|
|
class FoldedZContainer : public ZContainer<FGSTensor>, public FoldedStackContainer
|
2019-01-08 16:09:25 +01:00
|
|
|
|
{
|
|
|
|
|
public:
|
2019-01-09 17:21:14 +01:00
|
|
|
|
using _Ctype = TensorContainer<FGSTensor>;
|
2023-11-29 19:00:21 +01:00
|
|
|
|
FoldedZContainer(const _Ctype* gss, int ngss, const _Ctype* g, int ng, int ny, int nu) :
|
|
|
|
|
ZContainer<FGSTensor>(gss, ngss, g, ng, ny, nu)
|
2019-01-08 16:09:25 +01:00
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2023-11-29 19:00:21 +01:00
|
|
|
|
class UnfoldedZContainer : public ZContainer<UGSTensor>, public UnfoldedStackContainer
|
2019-01-08 16:09:25 +01:00
|
|
|
|
{
|
|
|
|
|
public:
|
2019-01-09 17:21:14 +01:00
|
|
|
|
using _Ctype = TensorContainer<UGSTensor>;
|
2023-11-29 19:00:21 +01:00
|
|
|
|
UnfoldedZContainer(const _Ctype* gss, int ngss, const _Ctype* g, int ng, int ny, int nu) :
|
|
|
|
|
ZContainer<UGSTensor>(gss, ngss, g, ng, ny, nu)
|
2019-01-08 16:09:25 +01:00
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/* Here we have another specialization of container used in context of
|
2019-03-07 18:17:43 +01:00
|
|
|
|
DSGE. We define a container for
|
2019-01-08 16:09:25 +01:00
|
|
|
|
|
2019-05-06 18:43:54 +02:00
|
|
|
|
G(y,u,u′,σ)=g**(g*(y,u,σ),u′,σ)
|
|
|
|
|
|
|
|
|
|
For some reason, the symmetry of g** has length 4 although it
|
|
|
|
|
is really dependent on three variables (To now the reason, consult
|
|
|
|
|
the ZContainer class declaration). So, it has four stacks, the
|
2019-01-08 16:09:25 +01:00
|
|
|
|
third one is dummy, and always returns zero. The first stack
|
2019-05-06 18:43:54 +02:00
|
|
|
|
corresponds to a container of g*. */
|
2019-01-08 16:09:25 +01:00
|
|
|
|
|
2019-12-20 14:36:20 +01:00
|
|
|
|
template<class _Ttype>
|
2019-01-08 16:09:25 +01:00
|
|
|
|
class GContainer : public StackContainer<_Ttype>
|
|
|
|
|
{
|
|
|
|
|
public:
|
2019-01-09 17:21:14 +01:00
|
|
|
|
using _Tparent = StackContainer<_Ttype>;
|
|
|
|
|
using _Stype = StackContainerInterface<_Ttype>;
|
|
|
|
|
using _Ctype = typename StackContainer<_Ttype>::_Ctype;
|
|
|
|
|
using itype = typename StackContainer<_Ttype>::itype;
|
2023-11-29 19:00:21 +01:00
|
|
|
|
GContainer(const _Ctype* gs, int ngs, int nu) : StackContainer<_Ttype>(4, 1)
|
2019-01-08 16:09:25 +01:00
|
|
|
|
{
|
2023-11-29 19:00:21 +01:00
|
|
|
|
_Tparent::stack_sizes = {ngs, nu, nu, 1};
|
2019-01-08 16:09:25 +01:00
|
|
|
|
_Tparent::conts[0] = gs;
|
|
|
|
|
_Tparent::calculateOffsets();
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-06 18:43:54 +02:00
|
|
|
|
/* Here we define the dependencies in g**(g*(y,u,σ),u′,σ). Also note, that
|
|
|
|
|
first derivative of g* w.r.t. σ is always zero, so we also add this
|
2019-01-08 16:09:25 +01:00
|
|
|
|
information. */
|
|
|
|
|
|
2023-12-05 15:44:23 +01:00
|
|
|
|
[[nodiscard]] itype
|
2023-11-29 19:00:21 +01:00
|
|
|
|
getType(int i, const Symmetry& s) const override
|
2019-01-08 16:09:25 +01:00
|
|
|
|
{
|
|
|
|
|
if (i == 0)
|
2023-04-11 14:46:04 +02:00
|
|
|
|
{
|
2023-11-29 19:00:21 +01:00
|
|
|
|
if (s[2] > 0 || s == Symmetry {0, 0, 0, 1})
|
2023-04-11 14:46:04 +02:00
|
|
|
|
return itype::zero;
|
|
|
|
|
else
|
|
|
|
|
return itype::matrix;
|
|
|
|
|
}
|
2019-01-08 16:09:25 +01:00
|
|
|
|
if (i == 1)
|
2023-04-11 14:46:04 +02:00
|
|
|
|
{
|
2023-11-29 19:00:21 +01:00
|
|
|
|
if (s == Symmetry {0, 0, 1, 0})
|
2023-04-11 14:46:04 +02:00
|
|
|
|
return itype::unit;
|
|
|
|
|
else
|
|
|
|
|
return itype::zero;
|
|
|
|
|
}
|
2019-01-08 16:09:25 +01:00
|
|
|
|
if (i == 2)
|
2019-02-26 18:57:36 +01:00
|
|
|
|
return itype::zero;
|
2019-01-08 16:09:25 +01:00
|
|
|
|
if (i == 3)
|
2023-04-11 14:46:04 +02:00
|
|
|
|
{
|
2023-11-29 19:00:21 +01:00
|
|
|
|
if (s == Symmetry {0, 0, 0, 1})
|
2023-04-11 14:46:04 +02:00
|
|
|
|
return itype::unit;
|
|
|
|
|
else
|
|
|
|
|
return itype::zero;
|
|
|
|
|
}
|
2019-01-08 16:09:25 +01:00
|
|
|
|
|
|
|
|
|
TL_RAISE("Wrong stack index in GContainer::getType");
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2023-11-29 19:00:21 +01:00
|
|
|
|
class FoldedGContainer : public GContainer<FGSTensor>, public FoldedStackContainer
|
2019-01-08 16:09:25 +01:00
|
|
|
|
{
|
|
|
|
|
public:
|
2019-01-09 17:21:14 +01:00
|
|
|
|
using _Ctype = TensorContainer<FGSTensor>;
|
2023-11-29 19:00:21 +01:00
|
|
|
|
FoldedGContainer(const _Ctype* gs, int ngs, int nu) : GContainer<FGSTensor>(gs, ngs, nu)
|
2019-01-08 16:09:25 +01:00
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2023-11-29 19:00:21 +01:00
|
|
|
|
class UnfoldedGContainer : public GContainer<UGSTensor>, public UnfoldedStackContainer
|
2019-01-08 16:09:25 +01:00
|
|
|
|
{
|
|
|
|
|
public:
|
2019-01-09 17:21:14 +01:00
|
|
|
|
using _Ctype = TensorContainer<UGSTensor>;
|
2023-11-29 19:00:21 +01:00
|
|
|
|
UnfoldedGContainer(const _Ctype* gs, int ngs, int nu) : GContainer<UGSTensor>(gs, ngs, nu)
|
2019-01-08 16:09:25 +01:00
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2019-05-06 18:43:54 +02:00
|
|
|
|
/* Here we have a support class for product of StackContainers. It
|
|
|
|
|
only adds a dimension to StackContainer. It selects the symmetries
|
2019-01-08 16:09:25 +01:00
|
|
|
|
according to equivalence classes passed to the constructor. The
|
|
|
|
|
equivalence can have permuted classes by some given
|
|
|
|
|
permutation. Nothing else is interesting. */
|
|
|
|
|
|
2019-12-20 14:36:20 +01:00
|
|
|
|
template<class _Ttype>
|
2019-01-08 16:09:25 +01:00
|
|
|
|
class StackProduct
|
|
|
|
|
{
|
|
|
|
|
public:
|
2019-01-09 17:21:14 +01:00
|
|
|
|
using _Stype = StackContainerInterface<_Ttype>;
|
|
|
|
|
using _Ctype = typename _Stype::_Ctype;
|
|
|
|
|
using itype = typename _Stype::itype;
|
2023-11-29 19:00:21 +01:00
|
|
|
|
|
2019-01-08 16:09:25 +01:00
|
|
|
|
protected:
|
2023-11-29 19:00:21 +01:00
|
|
|
|
const _Stype& stack_cont;
|
2019-01-08 16:09:25 +01:00
|
|
|
|
InducedSymmetries syms;
|
|
|
|
|
Permutation per;
|
2023-11-29 19:00:21 +01:00
|
|
|
|
|
2019-01-08 16:09:25 +01:00
|
|
|
|
public:
|
2023-11-29 19:00:21 +01:00
|
|
|
|
StackProduct(const _Stype& sc, const Equivalence& e, const Symmetry& os) :
|
|
|
|
|
stack_cont(sc), syms(e, os), per(e)
|
2019-01-08 16:09:25 +01:00
|
|
|
|
{
|
|
|
|
|
}
|
2023-11-29 19:00:21 +01:00
|
|
|
|
StackProduct(const _Stype& sc, const Equivalence& e, const Permutation& p, const Symmetry& os) :
|
|
|
|
|
stack_cont(sc), syms(e, p, os), per(e, p)
|
2019-01-08 16:09:25 +01:00
|
|
|
|
{
|
|
|
|
|
}
|
2023-12-05 15:44:23 +01:00
|
|
|
|
[[nodiscard]] int
|
2019-01-08 16:09:25 +01:00
|
|
|
|
dimen() const
|
|
|
|
|
{
|
|
|
|
|
return syms.size();
|
|
|
|
|
}
|
2023-12-05 15:44:23 +01:00
|
|
|
|
[[nodiscard]] int
|
2019-01-08 16:09:25 +01:00
|
|
|
|
getAllSize() const
|
|
|
|
|
{
|
|
|
|
|
return stack_cont.getAllSize();
|
|
|
|
|
}
|
2023-12-05 15:44:23 +01:00
|
|
|
|
[[nodiscard]] const Symmetry&
|
2019-01-08 16:09:25 +01:00
|
|
|
|
getProdSym(int ip) const
|
|
|
|
|
{
|
|
|
|
|
return syms[ip];
|
|
|
|
|
}
|
2023-12-05 15:44:23 +01:00
|
|
|
|
[[nodiscard]] bool
|
2023-11-29 19:00:21 +01:00
|
|
|
|
isZero(const IntSequence& istacks) const
|
2019-01-08 16:09:25 +01:00
|
|
|
|
{
|
2023-11-29 19:00:21 +01:00
|
|
|
|
TL_RAISE_IF(istacks.size() != dimen(), "Wrong istacks coordinates for StackProduct::isZero");
|
2019-01-08 16:09:25 +01:00
|
|
|
|
|
|
|
|
|
bool res = false;
|
|
|
|
|
int i = 0;
|
|
|
|
|
while (i < dimen() && !(res = stack_cont.isZero(istacks[i], syms[i])))
|
|
|
|
|
i++;
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
itype
|
|
|
|
|
getType(int is, int ip) const
|
|
|
|
|
{
|
|
|
|
|
TL_RAISE_IF(is < 0 || is >= stack_cont.numStacks(),
|
|
|
|
|
"Wrong index to stack in StackProduct::getType");
|
2023-11-29 19:00:21 +01:00
|
|
|
|
TL_RAISE_IF(ip < 0 || ip >= dimen(), "Wrong index to stack container in StackProduct::getType");
|
2019-01-08 16:09:25 +01:00
|
|
|
|
return stack_cont.getType(is, syms[ip]);
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-29 19:00:21 +01:00
|
|
|
|
const _Ttype&
|
2019-01-08 16:09:25 +01:00
|
|
|
|
getMatrix(int is, int ip) const
|
|
|
|
|
{
|
|
|
|
|
return stack_cont.getMatrix(is, syms[ip]);
|
|
|
|
|
}
|
|
|
|
|
|
2019-02-26 18:57:36 +01:00
|
|
|
|
std::vector<std::unique_ptr<Vector>>
|
2023-11-29 19:00:21 +01:00
|
|
|
|
createPackedColumns(const IntSequence& coor, IntSequence& iu) const
|
2019-01-08 16:09:25 +01:00
|
|
|
|
{
|
|
|
|
|
TL_RAISE_IF(iu.size() != dimen(),
|
2019-02-26 18:57:36 +01:00
|
|
|
|
"Wrong storage length for unit flags in StackProduct::createPackedColumns");
|
2019-01-08 16:09:25 +01:00
|
|
|
|
TL_RAISE_IF(coor.size() != per.size(),
|
2019-02-26 18:57:36 +01:00
|
|
|
|
"Wrong size of index coor in StackProduct::createPackedColumns");
|
2019-01-08 16:09:25 +01:00
|
|
|
|
IntSequence perindex(coor.size());
|
2019-02-26 18:57:36 +01:00
|
|
|
|
std::vector<std::unique_ptr<Vector>> vs;
|
2019-01-08 16:09:25 +01:00
|
|
|
|
per.apply(coor, perindex);
|
|
|
|
|
int off = 0;
|
|
|
|
|
for (int i = 0; i < dimen(); i++)
|
|
|
|
|
{
|
|
|
|
|
IntSequence percoor(perindex, off, syms[i].dimen() + off);
|
2019-02-26 18:57:36 +01:00
|
|
|
|
vs.push_back(stack_cont.createPackedColumn(syms[i], percoor, iu[i]));
|
2019-01-08 16:09:25 +01:00
|
|
|
|
off += syms[i].dimen();
|
|
|
|
|
}
|
2019-02-26 18:57:36 +01:00
|
|
|
|
return vs;
|
2019-01-08 16:09:25 +01:00
|
|
|
|
}
|
|
|
|
|
|
2023-12-05 15:44:23 +01:00
|
|
|
|
[[nodiscard]] int
|
2019-01-08 16:09:25 +01:00
|
|
|
|
getSize(int is) const
|
|
|
|
|
{
|
|
|
|
|
return stack_cont.getStackSizes()[is];
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-05 15:44:23 +01:00
|
|
|
|
[[nodiscard]] int
|
2023-11-29 19:00:21 +01:00
|
|
|
|
numMatrices(const IntSequence& istacks) const
|
2019-01-08 16:09:25 +01:00
|
|
|
|
{
|
|
|
|
|
TL_RAISE_IF(istacks.size() != dimen(),
|
|
|
|
|
"Wrong size of stack coordinates in StackContainer::numMatrices");
|
|
|
|
|
int ret = 0;
|
|
|
|
|
int ip = 0;
|
|
|
|
|
while (ip < dimen() && getType(istacks[ip], ip) == _Stype::matrix)
|
|
|
|
|
{
|
|
|
|
|
ret++;
|
|
|
|
|
ip++;
|
|
|
|
|
}
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2019-05-06 18:43:54 +02:00
|
|
|
|
/* Here we only inherit from Kronecker product KronProdAllOptim, only to
|
|
|
|
|
allow for a constructor constructing from StackProduct. */
|
2019-01-08 16:09:25 +01:00
|
|
|
|
|
2019-12-20 14:36:20 +01:00
|
|
|
|
template<class _Ttype>
|
2019-01-08 16:09:25 +01:00
|
|
|
|
class KronProdStack : public KronProdAllOptim
|
|
|
|
|
{
|
|
|
|
|
public:
|
2019-01-09 17:21:14 +01:00
|
|
|
|
using _Ptype = StackProduct<_Ttype>;
|
|
|
|
|
using _Stype = StackContainerInterface<_Ttype>;
|
2019-01-08 16:09:25 +01:00
|
|
|
|
|
2019-05-06 18:43:54 +02:00
|
|
|
|
/* Here we construct KronProdAllOptim from StackContainer and given
|
2019-01-08 16:09:25 +01:00
|
|
|
|
selections of stack items from stack containers in the product. We
|
|
|
|
|
only decide whether to insert matrix, or unit matrix.
|
|
|
|
|
|
2019-05-06 18:43:54 +02:00
|
|
|
|
At this point, we do not call KronProdAllOptim::optimizeOrder(), so
|
|
|
|
|
the KronProdStack behaves like KronProdAll (i.e. no optimization
|
2019-01-08 16:09:25 +01:00
|
|
|
|
is done). */
|
|
|
|
|
|
2023-11-29 19:00:21 +01:00
|
|
|
|
KronProdStack(const _Ptype& sp, const IntSequence& istack) : KronProdAllOptim(sp.dimen())
|
2019-01-08 16:09:25 +01:00
|
|
|
|
{
|
|
|
|
|
TL_RAISE_IF(sp.dimen() != istack.size(),
|
|
|
|
|
"Wrong stack product dimension for KronProdStack constructor");
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < sp.dimen(); i++)
|
|
|
|
|
{
|
2019-02-26 18:57:36 +01:00
|
|
|
|
TL_RAISE_IF(sp.getType(istack[i], i) == _Stype::itype::zero,
|
2019-01-08 16:09:25 +01:00
|
|
|
|
"Attempt to construct KronProdStack from zero matrix");
|
2019-02-26 18:57:36 +01:00
|
|
|
|
if (sp.getType(istack[i], i) == _Stype::itype::unit)
|
2019-01-08 16:09:25 +01:00
|
|
|
|
setUnit(i, sp.getSize(istack[i]));
|
2019-02-26 18:57:36 +01:00
|
|
|
|
if (sp.getType(istack[i], i) == _Stype::itype::matrix)
|
2019-01-08 16:09:25 +01:00
|
|
|
|
{
|
2023-11-29 19:00:21 +01:00
|
|
|
|
const TwoDMatrix& m = sp.getMatrix(istack[i], i);
|
2019-02-20 17:51:05 +01:00
|
|
|
|
TL_RAISE_IF(m.nrows() != sp.getSize(istack[i]),
|
2019-01-08 16:09:25 +01:00
|
|
|
|
"Wrong size of returned matrix in KronProdStack constructor");
|
2019-02-20 17:51:05 +01:00
|
|
|
|
setMat(i, m);
|
2019-01-08 16:09:25 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2019-01-28 18:39:42 +01:00
|
|
|
|
class WorkerFoldMAADense : public sthread::detach_thread
|
2019-01-08 16:09:25 +01:00
|
|
|
|
{
|
2023-11-29 19:00:21 +01:00
|
|
|
|
const FoldedStackContainer& cont;
|
2019-01-08 16:09:25 +01:00
|
|
|
|
Symmetry sym;
|
2023-11-29 19:00:21 +01:00
|
|
|
|
const FGSContainer& dense_cont;
|
|
|
|
|
FGSTensor& out;
|
|
|
|
|
|
2019-01-08 16:09:25 +01:00
|
|
|
|
public:
|
2023-11-29 19:00:21 +01:00
|
|
|
|
WorkerFoldMAADense(const FoldedStackContainer& container, Symmetry s,
|
|
|
|
|
const FGSContainer& dcontainer, FGSTensor& outten);
|
|
|
|
|
void operator()(std::mutex& mut) override;
|
2019-01-08 16:09:25 +01:00
|
|
|
|
};
|
|
|
|
|
|
2019-01-28 18:39:42 +01:00
|
|
|
|
class WorkerFoldMAASparse1 : public sthread::detach_thread
|
2019-01-08 16:09:25 +01:00
|
|
|
|
{
|
2023-11-29 19:00:21 +01:00
|
|
|
|
const FoldedStackContainer& cont;
|
|
|
|
|
const FSSparseTensor& t;
|
|
|
|
|
FGSTensor& out;
|
2019-01-08 16:09:25 +01:00
|
|
|
|
IntSequence coor;
|
2023-11-29 19:00:21 +01:00
|
|
|
|
|
2019-01-08 16:09:25 +01:00
|
|
|
|
public:
|
2023-11-29 19:00:21 +01:00
|
|
|
|
WorkerFoldMAASparse1(const FoldedStackContainer& container, const FSSparseTensor& ten,
|
|
|
|
|
FGSTensor& outten, IntSequence c);
|
|
|
|
|
void operator()(std::mutex& mut) override;
|
2019-01-08 16:09:25 +01:00
|
|
|
|
};
|
|
|
|
|
|
2019-01-28 18:39:42 +01:00
|
|
|
|
class WorkerFoldMAASparse2 : public sthread::detach_thread
|
2019-01-08 16:09:25 +01:00
|
|
|
|
{
|
2023-11-29 19:00:21 +01:00
|
|
|
|
const FoldedStackContainer& cont;
|
|
|
|
|
const FSSparseTensor& t;
|
|
|
|
|
FGSTensor& out;
|
2019-01-08 16:09:25 +01:00
|
|
|
|
IntSequence coor;
|
2023-11-29 19:00:21 +01:00
|
|
|
|
|
2019-01-08 16:09:25 +01:00
|
|
|
|
public:
|
2023-11-29 19:00:21 +01:00
|
|
|
|
WorkerFoldMAASparse2(const FoldedStackContainer& container, const FSSparseTensor& ten,
|
|
|
|
|
FGSTensor& outten, IntSequence c);
|
|
|
|
|
void operator()(std::mutex& mut) override;
|
2019-01-08 16:09:25 +01:00
|
|
|
|
};
|
|
|
|
|
|
2019-01-28 18:39:42 +01:00
|
|
|
|
class WorkerFoldMAASparse4 : public sthread::detach_thread
|
2019-01-08 16:09:25 +01:00
|
|
|
|
{
|
2023-11-29 19:00:21 +01:00
|
|
|
|
const FoldedStackContainer& cont;
|
|
|
|
|
const FSSparseTensor& t;
|
|
|
|
|
FGSTensor& out;
|
2019-01-08 16:09:25 +01:00
|
|
|
|
IntSequence coor;
|
2023-11-29 19:00:21 +01:00
|
|
|
|
|
2019-01-08 16:09:25 +01:00
|
|
|
|
public:
|
2023-11-29 19:00:21 +01:00
|
|
|
|
WorkerFoldMAASparse4(const FoldedStackContainer& container, const FSSparseTensor& ten,
|
|
|
|
|
FGSTensor& outten, IntSequence c);
|
|
|
|
|
void operator()(std::mutex& mut) override;
|
2019-01-08 16:09:25 +01:00
|
|
|
|
};
|
|
|
|
|
|
2019-01-28 18:39:42 +01:00
|
|
|
|
class WorkerUnfoldMAADense : public sthread::detach_thread
|
2019-01-08 16:09:25 +01:00
|
|
|
|
{
|
2023-11-29 19:00:21 +01:00
|
|
|
|
const UnfoldedStackContainer& cont;
|
2019-01-08 16:09:25 +01:00
|
|
|
|
Symmetry sym;
|
2023-11-29 19:00:21 +01:00
|
|
|
|
const UGSContainer& dense_cont;
|
|
|
|
|
UGSTensor& out;
|
|
|
|
|
|
2019-01-08 16:09:25 +01:00
|
|
|
|
public:
|
2023-11-29 19:00:21 +01:00
|
|
|
|
WorkerUnfoldMAADense(const UnfoldedStackContainer& container, Symmetry s,
|
|
|
|
|
const UGSContainer& dcontainer, UGSTensor& outten);
|
|
|
|
|
void operator()(std::mutex& mut) override;
|
2019-01-08 16:09:25 +01:00
|
|
|
|
};
|
|
|
|
|
|
2019-01-28 18:39:42 +01:00
|
|
|
|
class WorkerUnfoldMAASparse1 : public sthread::detach_thread
|
2019-01-08 16:09:25 +01:00
|
|
|
|
{
|
2023-11-29 19:00:21 +01:00
|
|
|
|
const UnfoldedStackContainer& cont;
|
|
|
|
|
const FSSparseTensor& t;
|
|
|
|
|
UGSTensor& out;
|
2019-01-08 16:09:25 +01:00
|
|
|
|
IntSequence coor;
|
2023-11-29 19:00:21 +01:00
|
|
|
|
|
2019-01-08 16:09:25 +01:00
|
|
|
|
public:
|
2023-11-29 19:00:21 +01:00
|
|
|
|
WorkerUnfoldMAASparse1(const UnfoldedStackContainer& container, const FSSparseTensor& ten,
|
|
|
|
|
UGSTensor& outten, IntSequence c);
|
|
|
|
|
void operator()(std::mutex& mut) override;
|
2019-01-08 16:09:25 +01:00
|
|
|
|
};
|
|
|
|
|
|
2019-01-28 18:39:42 +01:00
|
|
|
|
class WorkerUnfoldMAASparse2 : public sthread::detach_thread
|
2019-01-08 16:09:25 +01:00
|
|
|
|
{
|
2023-11-29 19:00:21 +01:00
|
|
|
|
const UnfoldedStackContainer& cont;
|
|
|
|
|
const FSSparseTensor& t;
|
|
|
|
|
UGSTensor& out;
|
2019-01-08 16:09:25 +01:00
|
|
|
|
IntSequence coor;
|
2023-11-29 19:00:21 +01:00
|
|
|
|
|
2019-01-08 16:09:25 +01:00
|
|
|
|
public:
|
2023-11-29 19:00:21 +01:00
|
|
|
|
WorkerUnfoldMAASparse2(const UnfoldedStackContainer& container, const FSSparseTensor& ten,
|
|
|
|
|
UGSTensor& outten, IntSequence c);
|
|
|
|
|
void operator()(std::mutex& mut) override;
|
2019-01-08 16:09:25 +01:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
#endif
|