@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(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 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(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 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& 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.