dynare/dynare++/tl/cc/permutation.cweb

189 lines
4.4 KiB
Plaintext

@q $Id: permutation.cweb 332 2005-07-15 13:41:48Z kamenik $ @>
@q Copyright 2004, Ondra Kamenik @>
@ Start of {\tt permutation.cweb} file.
@c
#include "permutation.h"
#include "tl_exception.h"
@<|Permutation::apply| code@>;
@<|Permutation::inverse| code@>;
@<|Permutation::tailIdentity| code@>;
@<|Permutation::computeSortingMap| code@>;
@<|PermutationSet| constructor code 1@>;
@<|PermutationSet| constructor code 2@>;
@<|PermutationSet| destructor code@>;
@<|PermutationSet::getPreserving| code@>;
@<|PermutationBundle| constructor code@>;
@<|PermutationBundle| destructor code@>;
@<|PermutationBundle::get| code@>;
@<|PermutationBundle::generateUpTo| code@>;
@ This is easy, we simply apply the map in the fashion $s\circ m$..
@<|Permutation::apply| code@>=
void Permutation::apply(const IntSequence& src, IntSequence& tar) const
{
TL_RAISE_IF(src.size() != permap.size() || tar.size() != permap.size(),
"Wrong sizes of input or output in Permutation::apply");
for (int i = 0; i < permap.size(); i++)
tar[i] = src[permap[i]];
}
void Permutation::apply(IntSequence& tar) const
{
IntSequence tmp(tar);
apply(tmp, tar);
}
@
@<|Permutation::inverse| code@>=
void Permutation::inverse()
{
IntSequence former(permap);
for (int i = 0; i < size(); i++)
permap[former[i]] = i;
}
@ Here we find a number of trailing indices which are identical with
the permutation.
@<|Permutation::tailIdentity| code@>=
int Permutation::tailIdentity() const
{
int i = permap.size();
while (i > 0 && permap[i-1] == i-1)
i--;
return permap.size() - i;
}
@ This calculates a map which corresponds to sorting in the following
sense: $(\hbox{sorted }s)\circ m = s$, where $s$ is a given sequence.
We go through |s| and find an the same item in sorted |s|. We
construct the |permap| from the found pair of indices. We have to be
careful, to not assign to two positions in |s| the same position in
sorted |s|, so we maintain a bitmap |flag|, in which we remember
indices from the sorted |s| already assigned.
@<|Permutation::computeSortingMap| code@>=
void Permutation::computeSortingMap(const IntSequence& s)
{
IntSequence srt(s);
srt.sort();
IntSequence flags(s.size(),0);
for (int i = 0; i < s.size(); i++) {
int j = 0;
while (j < s.size() && (flags[j] || srt[j] != s[i]))
j++;
TL_RAISE_IF(j == s.size(),
"Internal algorithm error in Permutation::computeSortingMap");
flags[j] = 1;
permap[i] = j;
}
}
@
@<|PermutationSet| constructor code 1@>=
PermutationSet::PermutationSet()
: order(1), size(1), pers(new const Permutation*[size])
{
pers[0] = new Permutation(1);
}
@
@<|PermutationSet| constructor code 2@>=
PermutationSet::PermutationSet(const PermutationSet& sp, int n)
: order(n), size(n*sp.size),
pers(new const Permutation*[size])
{
for (int i = 0; i < size; i++)
pers[i] = NULL;
TL_RAISE_IF(n != sp.order+1,
"Wrong new order in PermutationSet constructor");
int k = 0;
for (int i = 0; i < sp.size; i++) {
for (int j = 0; j < order; j++,k++) {
pers[k] = new Permutation(*(sp.pers[i]), j);
}
}
}
@
@<|PermutationSet| destructor code@>=
PermutationSet::~PermutationSet()
{
for (int i = 0; i < size; i++)
if (pers[i])
delete pers[i];
delete [] pers;
}
@
@<|PermutationSet::getPreserving| code@>=
vector<const Permutation*> PermutationSet::getPreserving(const IntSequence& s) const
{
TL_RAISE_IF(s.size() != order,
"Wrong sequence length in PermutationSet::getPreserving");
vector<const Permutation*> res;
IntSequence tmp(s.size());
for (int i = 0; i < size; i++) {
pers[i]->apply(s, tmp);
if (s == tmp) {
res.push_back(pers[i]);
}
}
return res;
}
@
@<|PermutationBundle| constructor code@>=
PermutationBundle::PermutationBundle(int nmax)
{
nmax = max(nmax, 1);
generateUpTo(nmax);
}
@
@<|PermutationBundle| destructor code@>=
PermutationBundle::~PermutationBundle()
{
for (unsigned int i = 0; i < bundle.size(); i++)
delete bundle[i];
}
@
@<|PermutationBundle::get| code@>=
const PermutationSet& PermutationBundle::get(int n) const
{
if (n > (int)(bundle.size()) || n < 1) {
TL_RAISE("Permutation set not found in PermutationSet::get");
return *(bundle[0]);
} else {
return *(bundle[n-1]);
}
}
@
@<|PermutationBundle::generateUpTo| code@>=
void PermutationBundle::generateUpTo(int nmax)
{
if (bundle.size() == 0)
bundle.push_back(new PermutationSet());
int curmax = bundle.size();
for (int n = curmax+1; n <= nmax; n++) {
bundle.push_back(new PermutationSet(*(bundle.back()), n));
}
}
@ End of {\tt permutation.cweb} file.