dynare/dynare++/tl/cc/t_container.cweb

139 lines
3.9 KiB
Plaintext

@q $Id: t_container.cweb 148 2005-04-19 15:12:26Z kamenik $ @>
@q Copyright 2004, Ondra Kamenik @>
@ Start of {\tt t\_container.cpp} file.
@s USubTensor int
@c
#include "t_container.h"
#include "kron_prod.h"
#include "ps_tensor.h"
#include "pyramid_prod.h"
const int FGSContainer::num_one_time = 10;
@<|UGSContainer| conversion from |FGSContainer|@>;
@<|UGSContainer::multAndAdd| code@>;
@<|FGSContainer| conversion from |UGSContainer|@>;
@<|FGSContainer::multAndAdd| folded code@>;
@<|FGSContainer::multAndAdd| unfolded code@>;
@<|FGSContainer::getIndices| code@>;
@
@<|UGSContainer| conversion from |FGSContainer|@>=
UGSContainer::UGSContainer(const FGSContainer& c)
: TensorContainer<UGSTensor>(c.num())
{
for (FGSContainer::const_iterator it = c.begin();
it != c.end(); ++it) {
UGSTensor* unfolded = new UGSTensor(*((*it).second));
insert(unfolded);
}
}
@ We set |l| to dimension of |t|, this is a tensor which multiplies
tensors from the container from the left. Also we set |k| to a
dimension of the resulting tensor. We go through all equivalences on
|k| element set and pickup only those which have $l$ classes.
In each loop, we fetch all necessary tensors for the product to the
vector |ts|. Then we form Kronecker product |KronProdAll| and feed it
with tensors from |ts|. Then we form unfolded permuted symmetry tensor
|UPSTensor| as matrix product of |t| and Kronecker product |kp|. Then
we add the permuted data to |out|. This is done by |UPSTensor| method
|addTo|.
@<|UGSContainer::multAndAdd| code@>=
void UGSContainer::multAndAdd(const UGSTensor& t, UGSTensor& out) const
{
int l = t.dimen();
int k = out.dimen();
const EquivalenceSet& eset = ebundle.get(k);
for (EquivalenceSet::const_iterator it = eset.begin();
it != eset.end(); ++it) {
if ((*it).numClasses() == l) {
vector<const UGSTensor*> ts =
fetchTensors(out.getSym(), *it);
KronProdAllOptim kp(l);
for (int i = 0; i < l; i++)
kp.setMat(i, *(ts[i]));
kp.optimizeOrder();
UPSTensor ups(out.getDims(), *it, t, kp);
ups.addTo(out);
}
}
}
@
@<|FGSContainer| conversion from |UGSContainer|@>=
FGSContainer::FGSContainer(const UGSContainer& c)
: TensorContainer<FGSTensor>(c.num())
{
for (UGSContainer::const_iterator it = c.begin();
it != c.end(); ++it) {
FGSTensor* folded = new FGSTensor(*((*it).second));
insert(folded);
}
}
@ Here we perform one step of the Faa Di Bruno operation. We call the
|multAndAdd| for unfolded tensor.
@<|FGSContainer::multAndAdd| folded code@>=
void FGSContainer::multAndAdd(const FGSTensor& t, FGSTensor& out) const
{
UGSTensor ut(t);
multAndAdd(ut, out);
}
@ This is the same as |@<|UGSContainer::multAndAdd| code@>|
but we do not construct |UPSTensor| from the Kronecker
product, but |FPSTensor|.
@<|FGSContainer::multAndAdd| unfolded code@>=
void FGSContainer::multAndAdd(const UGSTensor& t, FGSTensor& out) const
{
int l = t.dimen();
int k = out.dimen();
const EquivalenceSet& eset = ebundle.get(k);
for (EquivalenceSet::const_iterator it = eset.begin();
it != eset.end(); ++it) {
if ((*it).numClasses() == l) {
vector<const FGSTensor*> ts =
fetchTensors(out.getSym(), *it);
KronProdAllOptim kp(l);
for (int i = 0; i < l; i++)
kp.setMat(i, *(ts[i]));
kp.optimizeOrder();
FPSTensor fps(out.getDims(), *it, t, kp);
fps.addTo(out);
}
}
}
@ This fills a given vector with integer sequences corresponding to
first |num| indices from interval |start| (including) to |end|
(excluding). If there are not |num| of such indices, the shorter vector
is returned.
@<|FGSContainer::getIndices| code@>=
Tensor::index
FGSContainer::getIndices(int num, vector<IntSequence>& out,
const Tensor::index& start,
const Tensor::index& end)
{
out.clear();
int i = 0;
Tensor::index run = start;
while (i < num && run != end) {
out.push_back(run.getCoor());
i++;
++run;
}
return run;
}
@ End of {\tt t\_container.cpp} file.