@q $Id: int_sequence.cweb 148 2005-04-19 15:12:26Z kamenik $ @> @q Copyright 2004, Ondra Kamenik @> @ Start of {\tt int\_sequence.cpp} file. @c #include "int_sequence.h" #include "symmetry.h" #include "tl_exception.h" #include #include @<|IntSequence| constructor code 1@>; @<|IntSequence| constructor code 2@>; @<|IntSequence| constructor code 3@>; @<|IntSequence| constructor code 4@>; @<|IntSequence::operator=| code@>; @<|IntSequence::operator==| code@>; @<|IntSequence::operator<| code@>; @<|IntSequence::lessEq| code@>; @<|IntSequence::less| code@>; @<|IntSequence::sort| code@>; @<|IntSequence::monotone| code@>; @<|IntSequence::pmonotone| code@>; @<|IntSequence::sum| code@>; @<|IntSequence::mult| code@>; @<|IntSequence::getPrefixLength| code@>; @<|IntSequence::getNumDistinct| code@>; @<|IntSequence::getMax| code@>; @<|IntSequence::add| code 1@>; @<|IntSequence::add| code 2@>; @<|IntSequence::isPositive| code@>; @<|IntSequence::isConstant| code@>; @<|IntSequence::isSorted| code@>; @<|IntSequence::print| code@>; @ This unfolds a given integer sequence with respect to the given symmetry. If for example the symmetry is $(2,3)$, and the sequence is $(a,b)$, then the result is $(a,a,b,b,b)$. @<|IntSequence| constructor code 1@>= IntSequence::IntSequence(const Symmetry& sy, const IntSequence& se) : data(new int[sy.dimen()]), length(sy.dimen()), destroy(true) { int k = 0; for (int i = 0; i < sy.num(); i++) for (int j = 0; j < sy[i]; j++, k++) operator[](k) = se[i]; } @ This constructs an implied symmetry (implemented as |IntSequence| from a more general symmetry and equivalence class (implemented as |vector|). For example, let the general symmetry be $y^3u^2$ and the equivalence class is $\{0,4\}$ picking up first and fifth variable, we calculate symmetry (at this point only |IntSequence|) corresponding to the picked variables. These are $yu$. Thus the constructed sequence must be $(1,1)$, meaning that we picked one $y$ and one $u$. @<|IntSequence| constructor code 2@>= IntSequence::IntSequence(const Symmetry& sy, const vector& se) : data(new int[sy.num()]), length(sy.num()), destroy(true) { TL_RAISE_IF(sy.dimen() <= se[se.size()-1], "Sequence is not reachable by symmetry in IntSequence()"); for (int i = 0; i < length; i++) @/ operator[](i) = 0; for (unsigned int i = 0; i < se.size(); i++) @/ operator[](sy.findClass(se[i]))++; } @ This constructs an ordered integer sequence from the given ordered sequence inserting the given number to the sequence. @<|IntSequence| constructor code 3@>= IntSequence::IntSequence(int i, const IntSequence& s) : data(new int[s.size()+1]), length(s.size()+1), destroy(true) { int j = 0; while (j < s.size() && s[j] < i) j++; for (int jj = 0; jj < j; jj++) operator[](jj) = s[jj]; operator[](j) = i; for (int jj = j; jj < s.size(); jj++) operator[](jj+1) = s[jj]; } @ @<|IntSequence| constructor code 4@>= IntSequence::IntSequence(int i, const IntSequence& s, int pos) : data(new int[s.size()+1]), length(s.size()+1), destroy(true) { TL_RAISE_IF(pos < 0 || pos > s.size(), "Wrong position for insertion IntSequence constructor"); for (int jj = 0; jj < pos; jj++) operator[](jj) = s[jj]; operator[](pos) = i; for (int jj = pos; jj < s.size(); jj++) operator[](jj+1) = s[jj]; } @ @<|IntSequence::operator=| code@>= const IntSequence& IntSequence::operator=(const IntSequence& s) { TL_RAISE_IF(!destroy && length != s.length, "Wrong length for in-place IntSequence::operator="); if (destroy && length != s.length) { delete [] data; data = new int[s.length]; destroy = true; length = s.length; } memcpy(data, s.data, sizeof(int)*length); return *this; } @ @<|IntSequence::operator==| code@>= bool IntSequence::operator==(const IntSequence& s) const { if (size() != s.size()) return false; int i = 0; while (i < size() && operator[](i) == s[i]) i++; return i == size(); } @ We need some linear irreflexive ordering, we implement it as lexicographic ordering without identity. @<|IntSequence::operator<| code@>= bool IntSequence::operator<(const IntSequence& s) const { int len = min(size(), s.size()); int i = 0; while (i < len && operator[](i) == s[i]) i++; return (i < s.size() && (i == size() || operator[](i) < s[i])); } @ @<|IntSequence::lessEq| code@>= bool IntSequence::lessEq(const IntSequence& s) const { TL_RAISE_IF(size() != s.size(), "Sequence with different lengths in IntSequence::lessEq"); int i = 0; while (i < size() && operator[](i) <= s[i]) i++; return (i == size()); } @ @<|IntSequence::less| code@>= bool IntSequence::less(const IntSequence& s) const { TL_RAISE_IF(size() != s.size(), "Sequence with different lengths in IntSequence::less"); int i = 0; while (i < size() && operator[](i) < s[i]) i++; return (i == size()); } @ This is a bubble sort, all sequences are usually very short, so this sin might be forgiven. @<|IntSequence::sort| code@>= void IntSequence::sort() { for (int i = 0; i < length; i++) { int swaps = 0; for (int j = 0; j < length-1; j++) { if (data[j] > data[j+1]) { int s = data[j+1]; data[j+1] = data[j]; data[j] = s; swaps++; } } if (swaps == 0) return; } } @ Here we monotonize the sequence. If an item is less then its predecessor, it is equalized. @<|IntSequence::monotone| code@>= void IntSequence::monotone() { for (int i = 1; i < length; i++) if (data[i-1] > data[i])@/ data[i] = data[i-1]; } @ This partially monotones the sequence. The partitioning is done by a symmetry. So the subsequence given by the symmetry classes are monotonized. For example, if the symmetry is $y^2u^3$, and the |IntSequence| is $(5,3,1,6,4)$, the result is $(5,5,1,6,6)$. @<|IntSequence::pmonotone| code@>= void IntSequence::pmonotone(const Symmetry& s) { int cum = 0; for (int i = 0; i < s.num(); i++) { for (int j = cum + 1; j < cum + s[i]; j++) if (data[j-1] > data[j])@/ data[j] = data[j-1]; cum += s[i]; } } @ This returns sum of all elements. Useful for symmetries. @<|IntSequence::sum| code@>= int IntSequence::sum() const { int res = 0; for (int i = 0; i < length; i++) @/ res += operator[](i); return res; } @ This returns product of subsequent items. Useful for Kronecker product dimensions. @<|IntSequence::mult| code@>= int IntSequence::mult(int i1, int i2) const { int res = 1; for (int i = i1; i < i2; i++)@/ res *= operator[](i); return res; } @ Return a number of the same items in the beginning of the sequence. @<|IntSequence::getPrefixLength| code@>= int IntSequence::getPrefixLength() const { int i = 0; while (i+1 < size() && operator[](i+1) == operator[](0)) i++; return i+1; } @ This returns a number of distinct items in the sequence. It supposes that the sequence is ordered. For the empty sequence it returns zero. @<|IntSequence::getNumDistinct| code@>= int IntSequence::getNumDistinct() const { int res = 0; if (size() > 0) res++; for (int i = 1; i < size(); i++) if (operator[](i) != operator[](i-1)) res++; return res; } @ This returns a maximum of the sequence. If the sequence is empty, it returns the least possible |int| value. @<|IntSequence::getMax| code@>= int IntSequence::getMax() const { int res = INT_MIN; for (int i = 0; i < size(); i++) if (operator[](i) > res) res = operator[](i); return res; } @ @<|IntSequence::add| code 1@>= void IntSequence::add(int i) { for (int j = 0; j < size(); j++) operator[](j) += i; } @ @<|IntSequence::add| code 2@>= void IntSequence::add(int f, const IntSequence& s) { TL_RAISE_IF(size() != s.size(), "Wrong sequence length in IntSequence::add"); for (int j = 0; j < size(); j++) operator[](j) += f*s[j]; } @ @<|IntSequence::isPositive| code@>= bool IntSequence::isPositive() const { int i = 0; while (i < size() && operator[](i) >= 0) i++; return (i == size()); } @ @<|IntSequence::isConstant| code@>= bool IntSequence::isConstant() const { bool res = true; int i = 1; while (res && i < size()) { res = res && operator[](0) == operator[](i); i++; } return res; } @ @<|IntSequence::isSorted| code@>= bool IntSequence::isSorted() const { bool res = true; int i = 1; while (res && i < size()) { res = res && operator[](i-1) <= operator[](i); i++; } return res; } @ Debug print. @<|IntSequence::print| code@>= void IntSequence::print() const { printf("["); for (int i = 0; i < size(); i++)@/ printf("%2d ",operator[](i)); printf("]\n"); } @ End of {\tt int\_sequence.cpp} file.