diff options
Diffstat (limited to 'casa/covering/bookkeeping/Coverage.H')
-rw-r--r-- | casa/covering/bookkeeping/Coverage.H | 313 |
1 files changed, 313 insertions, 0 deletions
diff --git a/casa/covering/bookkeeping/Coverage.H b/casa/covering/bookkeeping/Coverage.H new file mode 100644 index 0000000..c0ce2b3 --- /dev/null +++ b/casa/covering/bookkeeping/Coverage.H @@ -0,0 +1,313 @@ +// Copyright 2008, 2009 Brady J. Garvin + +// This file is part of Covering Arrays by Simulated Annealing (CASA). + +// CASA is free software: you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// CASA is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with CASA. If not, see <http://www.gnu.org/licenses/>. + + +#ifndef COVERAGE_H +#define COVERAGE_H + +#include "PascalTriangle.H" +#include "Combinadic.H" + +#include "SubstitutionArray.H" + +#include "covering/bookkeeping/Options.H" + +template<class T>class Coverage { +protected: + unsigned strength; + Options options; + // The offsets are indices into the contents array; entry offsets[i], where i + // is the combinadic encoding of a set of columns, is the beginning of the + // contents for that column set's t-sets. + Array<unsigned> offsets; + SubstitutionArray<T> contents; + +public: + Coverage(unsigned strength, Options options) : + strength(strength), + options(options), + offsets(triangle.nCr(options.getSize(), strength)) { + unsigned size = 0; + unsigned offsetIndex = 0; + for (Array<unsigned>columns = combinadic.begin(strength); + columns[strength - 1] < options.getSize(); + combinadic.next(columns)) { + unsigned blockSize = 1; + for (unsigned i = strength; i--;) { + blockSize *= options.getSymbolCount(columns[i]); + } + offsets[offsetIndex++] = size; + size += blockSize; + } + contents = Array<T>(size); + } + + Coverage(const Coverage©) : + strength(copy.strength), + options(copy.options), + offsets(copy.offsets), + contents(copy.contents) {} + +protected: + // The method encode, in its various forms, is responsible for converting a + // sorted t-set to an index into the contents array. + + // These hinted versions of encode are for when some information has already + // been computed. indexHint is the combinadic encoding of the set of columns; + // columnsHint is this set of columns in sorted order; firstsHint is an array + // of corresponding first symbols; and countsHint is an array of symbol counts + // for each column. + unsigned encode + (unsigned indexHint, + Array<unsigned>columnsHint, + Array<unsigned>firstsHint, + Array<unsigned>countsHint, + Array<unsigned>sortedCombination) const { + assert(sortedCombination.getSize() == strength); + assert(indexHint < offsets.getSize()); + unsigned offset = offsets[indexHint]; + unsigned index = 0; + for (unsigned i = strength; i--;) { + unsigned column = columnsHint[i]; + unsigned base = firstsHint[column]; + unsigned count = countsHint[column]; + index *= count; + index += sortedCombination[i] - base; + } + return offset + index; + } + + unsigned encode + (Array<unsigned>columnsHint, + Array<unsigned>firstsHint, + Array<unsigned>countsHint, + Array<unsigned>sortedCombination) const { + return encode + (combinadic.encode(columnsHint), + columnsHint, + firstsHint, + countsHint, + sortedCombination); + } + + unsigned encode(Array<unsigned>sortedCombination) const { + assert(sortedCombination.getSize() == strength); + Array<unsigned>columns(strength); + for (unsigned i = strength; i--;) { + columns[i] = options.getOption(sortedCombination[i]); + } + unsigned offsetIndex = combinadic.encode(columns); + assert(offsetIndex < offsets.getSize()); + unsigned offset = offsets[offsetIndex]; + unsigned index = 0; + for (unsigned i = strength; i--;) { + unsigned column = columns[i]; + unsigned base = options.getFirstSymbol(column); + unsigned count = options.getSymbolCount(column); + index *= count; + index += sortedCombination[i] - base; + } + return offset + index; + } + + // The method decode, of course, does the opposite of encode. + Array<unsigned>decode(unsigned encoding) const { + unsigned offsetIndex = offsets.getSize(); + while (offsets[--offsetIndex] > encoding); + unsigned index = encoding - offsets[offsetIndex]; + Array<unsigned>columns = combinadic.decode(offsetIndex, strength); + Array<unsigned>result(strength); + for (unsigned i = 0; i < strength; ++i) { + unsigned column = columns[i]; + unsigned base = options.getFirstSymbol(column); + unsigned count = options.getSymbolCount(column); + unsigned digit = index % count; + index -= digit; + index /= count; + result[i] = base + digit; + } + assert(encode(result) == encoding); + return result; + } + +public: + unsigned getStrength() const { + return strength; + } + const Options&getOptions() const { + return options; + } + + class Entry{ + protected: + Coverage& owner; + unsigned index; + public: + Entry(const Coverage&owner,unsigned index) : + owner(const_cast<Coverage&>(owner)), + index(index) {} + operator T() const { + return owner.contents[index]; + } + Entry&operator =(const T&value) { + owner.contents[index] = value; + return *this; + } + Entry&operator --() { + --owner.contents[index]; + return *this; + } + Entry&operator ++() { + ++owner.contents[index]; + return *this; + } + }; + + const Entry operator[](Array<unsigned>sortedCombination) const { + return Entry(*this, encode(sortedCombination)); + } + Entry operator [](Array<unsigned>sortedCombination) { + return Entry(*this, encode(sortedCombination)); + } + + // The methods named hintGet work like the [] operator with the aforementioned + // hints. + const Entry hintGet + (unsigned indexHint, + Array<unsigned>columnsHint, + Array<unsigned>firstsHint, + Array<unsigned>countsHint, + Array<unsigned>sortedCombination) const { + return Entry + (*this, + encode + (indexHint, columnsHint, firstsHint, countsHint, sortedCombination)); + } + + Entry hintGet + (unsigned indexHint, + Array<unsigned>columnsHint, + Array<unsigned>firstsHint, + Array<unsigned>countsHint, + Array<unsigned>sortedCombination) { + return Entry + (*this, + encode + (indexHint, columnsHint, firstsHint, countsHint, sortedCombination)); + } + + const Entry hintGet + (Array<unsigned>columnsHint, + Array<unsigned>firstsHint, + Array<unsigned>countsHint, + Array<unsigned>sortedCombination) const { + return Entry + (*this, + encode(columnsHint, firstsHint, countsHint, sortedCombination)); + } + + Entry hintGet + (Array<unsigned>columnsHint, + Array<unsigned>firstsHint, + Array<unsigned>countsHint, + Array<unsigned>sortedCombination) { + return Entry + (*this, + encode(columnsHint, firstsHint, countsHint, sortedCombination)); + } + + class iterator { + protected: + Coverage& owner; + unsigned index; + public: + iterator(Coverage&owner, unsigned index) : + owner(owner), + index(index) {} + const Entry operator *() const { + return Entry(owner, index); + } + Entry operator *() { + return Entry(owner, index); + } + iterator&operator ++() { + ++index; + return *this; + } + bool operator ==(const iterator&other) const { + return &owner == &other.owner && index == other.index; + } + bool operator !=(const iterator&other) const { + return &owner != &other.owner || index != other.index; + } + Array<unsigned>getCombination() const { + return owner.decode(index); + } + }; + + class const_iterator { + protected: + const Coverage& owner; + unsigned index; + public: + const_iterator(const Coverage&owner, unsigned index) : + owner(owner), + index(index) {} + const_iterator(const iterator©) : + owner(copy.owner), + index(copy.index) {} + const Entry operator *() const { + return Entry(owner, index); + } + const_iterator&operator ++() { + ++index; + return *this; + } + bool operator ==(const const_iterator&other) const { + return &owner == &other.owner && index == other.index; + } + bool operator != (const const_iterator&other) const { + return &owner != &other.owner || index != other.index; + } + Array<unsigned>getCombination() const { + return owner.decode(index); + } + }; + + iterator begin() { + return iterator(*this, 0); + } + const_iterator begin() const { + return const_iterator(*this, 0); + } + iterator end() { + return iterator(*this, contents.getSize()); + } + const_iterator end() const { + return const_iterator(*this, contents.getSize()); + } + + unsigned getSize() const { + return contents.getSize(); + } + + void fill(const T&filler) { + contents.fill(filler); + } +}; + +#endif |