@q $Id: fine_container.hweb 332 2005-07-15 13:41:48Z kamenik $ @> @q Copyright 2005, Ondra Kamenik @> @*2 Refined stack of containers. Start of {\tt fine\_container.h} file. This file defines a refinement of the stack container. It makes a vertical refinement of a given stack container, it refines only matrix items, the items which are always zero, or can be identity matrices are not refined. The refinement is done by a simple construction from the stack container being refined. A parameter is passed meaning a maximum size of each stack in the refined container. The resulting object is stack container, so everything works seamlessly. We define here a class for refinement of sizes |SizeRefinement|, this is purely an auxiliary class allowing us to write a code more concisely. The main class of this file is |FineContainer|, which corresponds to refining. The two more classes |FoldedFineContainer| and |UnfoldedFineContainer| are its specializations. NOTE: This code was implemented with a hope that it will help to cut down memory allocations during the Faa Di Bruno formula evaluation. However, it seems that this needs to be accompanied with a similar thing for tensor multidimensional index. Thus, the abstraction is not currently used, but it might be useful in future. @s SizeRefinement int @s FineContainer int @s FoldedFineContainer int @s UnfoldedFineContainer int @c #ifndef FINE_CONTAINER_H #define FINE_CONTAINER_H #include "stack_container.h" #include @<|SizeRefinement| class declaration@>; @<|FineContainer| class declaration@>; @<|FoldedFineContainer| class declaration@>; @<|UnfoldedFineContainer| class declaration@>; #endif @ This class splits the first |nc| elements of the given sequence |s| to a sequence not having items greater than given |max|. The remaining elements (those behind |nc|) are left untouched. It also remembers the mapping, i.e. for a given index in a new sequence, it is able to return a corresponding index in old sequence. @<|SizeRefinement| class declaration@>= class SizeRefinement { vector rsizes; vector ind_map; int new_nc; public:@; SizeRefinement(const IntSequence& s, int nc, int max); int getRefSize(int i) const {@+ return rsizes[i];@+} int numRefinements() const {@+ return rsizes.size();@+} int getOldIndex(int i) const {@+ return ind_map[i];@+} int getNC() const {@+ return new_nc;@+} }; @ This main class of this class refines a given stack container, and inherits from the stack container. It also defines the |getType| method, which returns a type for a given stack as the type of the corresponding (old) stack of the former stack container. @<|FineContainer| class declaration@>= template @; class FineContainer : public SizeRefinement, public StackContainer<_Ttype> { protected:@; typedef StackContainer<_Ttype> _Stype; typedef typename StackContainerInterface<_Ttype>::_Ctype _Ctype; typedef typename StackContainerInterface<_Ttype>::itype itype; _Ctype** const ref_conts; const _Stype& stack_cont; public:@; @<|FineContainer| constructor@>; @<|FineContainer| destructor@>; itype getType(int i, const Symmetry& s) const {@+ return stack_cont.getType(getOldIndex(i), s);@+} }; @ Here we construct the |SizeRefinement| and allocate space for the refined containers. Then, the containers are created and put to |conts| array. Note that the containers do not claim any further space, since all the tensors of the created containers are in-place submatrices. Here we use a dirty trick of converting |const| pointer to non-|const| pointer and passing it to a subtensor container constructor. The containers are stored in |ref_conts| and then in |conts| from |StackContainer|. However, this is safe since neither |ref_conts| nor |conts| are used in non-|const| contexts. For example, |StackContainer| has only a |const| method to return a member of |conts|. @<|FineContainer| constructor@>= FineContainer(const _Stype& sc, int max) : SizeRefinement(sc.getStackSizes(), sc.numConts(), max), StackContainer<_Ttype>(numRefinements(), getNC()), ref_conts(new _Ctype*[getNC()]), stack_cont(sc) { for (int i = 0; i < numRefinements(); i++) _Stype::stack_sizes[i] = getRefSize(i); _Stype::calculateOffsets(); int last_cont = -1; int last_row = 0; for (int i = 0; i < getNC(); i++) { if (getOldIndex(i) != last_cont) { last_cont = getOldIndex(i); last_row = 0; } union {const _Ctype* c; _Ctype* n;} convert; convert.c = stack_cont.getCont(last_cont); ref_conts[i] = new _Ctype(last_row, _Stype::stack_sizes[i], *(convert.n)); _Stype::conts[i] = ref_conts[i]; last_row += _Stype::stack_sizes[i]; } } @ Here we deallocate the refined containers, and deallocate the array of refined containers. @<|FineContainer| destructor@>= virtual ~FineContainer() { for (int i = 0; i < _Stype::numConts(); i++) delete ref_conts[i]; delete [] ref_conts; } @ Here is |FineContainer| specialization for folded tensors. @<|FoldedFineContainer| class declaration@>= class FoldedFineContainer : public FineContainer, public FoldedStackContainer { public:@; FoldedFineContainer(const StackContainer& sc, int max) : FineContainer(sc, max) @+ {} }; @ Here is |FineContainer| specialization for unfolded tensors. @<|UnfoldedFineContainer| class declaration@>= class UnfoldedFineContainer : public FineContainer, public UnfoldedStackContainer { public:@; UnfoldedFineContainer(const StackContainer& sc, int max) : FineContainer(sc, max) @+ {} }; @ End of {\tt fine\_container.h} file.