From 2a43625498cb3c302a0b813f475dc03a9c48aafc Mon Sep 17 00:00:00 2001 From: Matthias Maier Date: Tue, 8 Sep 2015 22:08:08 -0500 Subject: [PATCH] TableIndices: Cleanup This is a major cleanup: - remove all template specializations - also remove the base class - implement one convenience constructor that takes care of everything --- include/deal.II/base/table_indices.h | 590 +++++---------------------- 1 file changed, 106 insertions(+), 484 deletions(-) diff --git a/include/deal.II/base/table_indices.h b/include/deal.II/base/table_indices.h index 2162a69352..fd8a41a163 100644 --- a/include/deal.II/base/table_indices.h +++ b/include/deal.II/base/table_indices.h @@ -19,29 +19,57 @@ #include #include +#include +#include #include - DEAL_II_NAMESPACE_OPEN /** - * Base class for an array of indices of fixed size used for the TableBase and - * SymmetricTensor classes. Actually, this class serves a dual purpose, as it - * not only stores indices into the TableBase class, but also the sizes of the - * table in its various coordinates. + * A class representing a fixed size array of indices. + * + * It is used in tensorial objects like the TableBase and SymmetricTensor + * classes to represent a nested choice of indices. * * @ingroup data - * @author Wolfgang Bangerth, 2002 + * @author Wolfgang Bangerth, Matthias Maier, 2002, 2015 */ template -class TableIndicesBase +class TableIndices { public: + + /** + * Default constructor. It sets all indices to zero. + */ + TableIndices(); + + /** + * Convenience constructor that takes up to 9 arguments. It can be used + * to populate a TableIndices object upon creation, either completely, or + * partially. + * + * Index entries that are not set by this 1 - 9 arguments (either + * because they are omitted, or because @tparam N is larger than 9) are + * set to numbers::invalid_unsigned_int. + * + * Note that only the first @tparam N arguments are actually used. + */ + TableIndices (const unsigned int index0, + const unsigned int index1 = numbers::invalid_unsigned_int, + const unsigned int index2 = numbers::invalid_unsigned_int, + const unsigned int index3 = numbers::invalid_unsigned_int, + const unsigned int index4 = numbers::invalid_unsigned_int, + const unsigned int index5 = numbers::invalid_unsigned_int, + const unsigned int index6 = numbers::invalid_unsigned_int, + const unsigned int index7 = numbers::invalid_unsigned_int, + const unsigned int index8 = numbers::invalid_unsigned_int); + /** - * Access the value of the ith index. + * Read-only access the value of the ith index. */ unsigned int operator[] (const unsigned int i) const; @@ -53,12 +81,12 @@ public: /** * Compare two index fields for equality. */ - bool operator == (const TableIndicesBase &other) const; + bool operator == (const TableIndices &other) const; /** * Compare two index fields for inequality. */ - bool operator != (const TableIndicesBase &other) const; + bool operator != (const TableIndices &other) const; /** * Sort the indices in ascending order. While this operation is not very @@ -81,294 +109,79 @@ protected: }; -/** - * Array of indices of fixed size used for the TableBase class. - * - * This is the general template, and has no implementation. There are a number - * of specializations that are actually implemented (one for each used value - * of N), which only differ in the way they implement their - * constructors (they take N arguments, something that cannot be - * represented by a general template). Actual storage of and access to data is - * done by the TableIndicesBase base class of a specializations. - * - * @ingroup data - * @author Wolfgang Bangerth, 2002 - */ -template -class TableIndices : public TableIndicesBase -{ - /** - * Standard constructor, setting all indices to zero. - */ - TableIndices(); - /** - * The actual constructor, taking @p N arguments of type unsigned - * int to initialize the index object. - */ - TableIndices(...); -}; - - - -/** - * Array of indices of fixed size used for the TableBase class. - * - * This is the specialization for a one-dimensional table, i.e. a vector. This - * class only differs in the non-default constructors from the other - * specializations. Actual storage of and access to data is done by the - * TableIndicesBase base class of a specializations. - * - * @ingroup data - * @author Wolfgang Bangerth, 2002 - */ -template <> -class TableIndices<1> : public TableIndicesBase<1> -{ -public: - /** - * Default constructor. Set all indices to zero. - */ - TableIndices (); - - /** - * Constructor. Set indices to the given values. - */ - TableIndices (const unsigned int index1); -}; - -//TODO: Remove the default arguments and trickery below and put all -//the constructors into the class template - -/** - * Array of indices of fixed size used for the TableBase class. - * - * This is the specialization for a two-dimensional table. This class only - * differs in the non-default constructors from the other specializations. - * Actual storage of and access to data is done by the TableIndicesBase base - * class of a specializations. - * - * @ingroup data - * @author Wolfgang Bangerth, 2002 - */ -template <> -class TableIndices<2> : public TableIndicesBase<2> -{ -public: - /** - * Default constructor. Set all indices to zero. - */ - TableIndices (); - - /** - * Constructor. Set indices to the given values. - * - * The default values for the second and subsequent arguments are necessary - * for some neat template tricks in SymmetricTensor where we only want to - * set the first index and construct the subsequent ones later on, i.e. for - * the moment we don't care about the later indices. - */ - TableIndices (const unsigned int index1, - const unsigned int index2 = numbers::invalid_unsigned_int); -}; - - -/** - * Array of indices of fixed size used for the TableBase class. - * - * This is the specialization for a three-dimensional table. This class only - * differs in the non-default constructors from the other specializations. - * Actual storage of and access to data is done by the TableIndicesBase base - * class of a specializations. - * - * @ingroup data - * @author Wolfgang Bangerth, 2002 - */ -template <> -class TableIndices<3> : public TableIndicesBase<3> -{ -public: - /** - * Default constructor. Set all indices to zero. - */ - TableIndices (); - - /** - * Constructor. Set indices to the given values. - * - * The default values for the second and subsequent arguments are necessary - * for some neat template tricks in SymmetricTensor where we only want to - * set the first index and construct the subsequent ones later on, i.e. for - * the moment we don't care about the later indices. - */ - TableIndices (const unsigned int index1, - const unsigned int index2 = numbers::invalid_unsigned_int, - const unsigned int index3 = numbers::invalid_unsigned_int); -}; - - -/** - * Array of indices of fixed size used for the TableBase class. - * - * This is the specialization for a four-dimensional table. This class only - * differs in the non-default constructors from the other specializations. - * Actual storage of and access to data is done by the TableIndicesBase base - * class of a specializations. - * - * @ingroup data - * @author Wolfgang Bangerth, Ralf Hartmann 2002 - */ -template <> -class TableIndices<4> : public TableIndicesBase<4> -{ -public: - /** - * Default constructor. Set all indices to zero. - */ - TableIndices (); - - /** - * Constructor. Set indices to the given values. - * - * The default values for the second and subsequent arguments are necessary - * for some neat template tricks in SymmetricTensor where we only want to - * set the first index and construct the subsequent ones later on, i.e. for - * the moment we don't care about the later indices. - */ - TableIndices (const unsigned int index1, - const unsigned int index2 = numbers::invalid_unsigned_int, - const unsigned int index3 = numbers::invalid_unsigned_int, - const unsigned int index4 = numbers::invalid_unsigned_int); -}; - - -/** - * Array of indices of fixed size used for the TableBase class. - * - * This is the specialization for a five-dimensional table. This class only - * differs in the non-default constructors from the other specializations. - * Actual storage of and access to data is done by the TableIndicesBase base - * class of a specializations. - * - * @ingroup data - * @author Wolfgang Bangerth, Ralf Hartmann 2002 - */ -template <> -class TableIndices<5> : public TableIndicesBase<5> -{ -public: - /** - * Default constructor. Set all indices to zero. - */ - TableIndices (); - - /** - * Constructor. Set indices to the given values. - * - * The default values for the second and subsequent arguments are necessary - * for some neat template tricks in SymmetricTensor where we only want to - * set the first index and construct the subsequent ones later on, i.e. for - * the moment we don't care about the later indices. - */ - TableIndices (const unsigned int index1, - const unsigned int index2 = numbers::invalid_unsigned_int, - const unsigned int index3 = numbers::invalid_unsigned_int, - const unsigned int index4 = numbers::invalid_unsigned_int, - const unsigned int index5 = numbers::invalid_unsigned_int); -}; +/* --------------------- Template and inline functions ---------------- */ -/** - * Array of indices of fixed size used for the TableBase class. - * - * This is the specialization for a six-dimensional table. This class only - * differs in the non-default constructors from the other specializations. - * Actual storage of and access to data is done by the TableIndicesBase base - * class of a specializations. - * - * @ingroup data - * @author Wolfgang Bangerth, Ralf Hartmann 2002 - */ -template <> -class TableIndices<6> : public TableIndicesBase<6> +template +TableIndices::TableIndices() { -public: - /** - * Default constructor. Set all indices to zero. - */ - TableIndices (); + Assert (N != 0, ExcMessage("Cannot create a TableIndices object of size 0")); - /** - * Constructor. Set indices to the given values. - * - * The default values for the second and subsequent arguments are necessary - * for some neat template tricks in SymmetricTensor where we only want to - * set the first index and construct the subsequent ones later on, i.e. for - * the moment we don't care about the later indices. - */ - TableIndices (const unsigned int index1, - const unsigned int index2 = numbers::invalid_unsigned_int, - const unsigned int index3 = numbers::invalid_unsigned_int, - const unsigned int index4 = numbers::invalid_unsigned_int, - const unsigned int index5 = numbers::invalid_unsigned_int, - const unsigned int index6 = numbers::invalid_unsigned_int); -}; + for (unsigned int i=0; i -class TableIndices<7> : public TableIndicesBase<7> +template +TableIndices::TableIndices(const unsigned int index0, + const unsigned int index1, + const unsigned int index2, + const unsigned int index3, + const unsigned int index4, + const unsigned int index5, + const unsigned int index6, + const unsigned int index7, + const unsigned int index8) { -public: - /** - * Default constructor. Set all indices to zero. - */ - TableIndices (); - - /** - * Constructor. Set indices to the given values. - * - * The default values for the second and subsequent arguments are necessary - * for some neat template tricks in SymmetricTensor where we only want to - * set the first index and construct the subsequent ones later on, i.e. for - * the moment we don't care about the later indices. - */ - TableIndices (const unsigned int index1, - const unsigned int index2 = numbers::invalid_unsigned_int, - const unsigned int index3 = numbers::invalid_unsigned_int, - const unsigned int index4 = numbers::invalid_unsigned_int, - const unsigned int index5 = numbers::invalid_unsigned_int, - const unsigned int index6 = numbers::invalid_unsigned_int, - const unsigned int index7 = numbers::invalid_unsigned_int); -}; + Assert (N != 0, ExcMessage("Cannot create a TableIndices object of size 0")); + // Always access "indices" with indices modulo N to avoid bogus compiler + // warnings (although such access is always in dead code... + switch (N) + { + case 9: + indices[8 % N] = index8; + case 8: // fallthrough + indices[7 % N] = index7; + case 7: // fallthrough + indices[6 % N] = index6; + case 6: // fallthrough + indices[5 % N] = index5; + case 5: // fallthrough + indices[4 % N] = index4; + case 4: // fallthrough + indices[3 % N] = index3; + case 3: // fallthrough + indices[2 % N] = index2; + case 2: // fallthrough + indices[1 % N] = index1; + case 1: // fallthrough + indices[0 % N] = index0; + } -/* --------------------- Template and inline functions ---------------- */ + // For TableIndices of size 10 or larger als default initialize the + // remaining indices to numbers::invalid_unsigned_int: + if (N > 9) + for (unsigned int i=0; i inline unsigned int -TableIndicesBase::operator [] (const unsigned int i) const +TableIndices::operator [] (const unsigned int i) const { Assert (i < N, ExcIndexRange (i, 0, N)); return indices[i]; } + template inline unsigned int & -TableIndicesBase::operator [] (const unsigned int i) +TableIndices::operator [] (const unsigned int i) { Assert (i < N, ExcIndexRange (i, 0, N)); return indices[i]; @@ -378,7 +191,7 @@ TableIndicesBase::operator [] (const unsigned int i) template inline bool -TableIndicesBase::operator == (const TableIndicesBase &other) const +TableIndices::operator == (const TableIndices &other) const { for (unsigned int i=0; i::operator == (const TableIndicesBase &other) const } - template inline bool -TableIndicesBase::operator != (const TableIndicesBase &other) const +TableIndices::operator != (const TableIndices &other) const { return !(*this == other); } - template -template inline void -TableIndicesBase::serialize (Archive &ar, const unsigned int) +TableIndices::sort () { - ar &indices; + std::sort(std_cxx11::begin(indices), std_cxx11::end(indices)); } - -template <> -inline -void -TableIndicesBase<1>::sort () -{} - - - -template <> -inline -void -TableIndicesBase<2>::sort () -{ - if (indices[1] < indices[0]) - std::swap (indices[0], indices[1]); -} - - - -template <> +template +template inline void -TableIndicesBase<3>::sort () -{ - // bubble sort for 3 elements - if (indices[1] < indices[0]) - std::swap (indices[0], indices[1]); - if (indices[2] < indices[1]) - std::swap (indices[1], indices[2]); - if (indices[1] < indices[0]) - std::swap (indices[0], indices[1]); -} - - - - -inline -TableIndices<1>::TableIndices () -{ - this->indices[0] = 0; -} - - - -inline -TableIndices<1>::TableIndices (const unsigned int index1) -{ - this->indices[0] = index1; -} - - - -inline -TableIndices<2>::TableIndices () -{ - this->indices[0] = this->indices[1] = 0; -} - - - -inline -TableIndices<2>::TableIndices (const unsigned int index1, - const unsigned int index2) -{ - this->indices[0] = index1; - this->indices[1] = index2; -} - - - -inline -TableIndices<3>::TableIndices () -{ - this->indices[0] = this->indices[1] = this->indices[2] = 0; -} - - - -inline -TableIndices<3>::TableIndices (const unsigned int index1, - const unsigned int index2, - const unsigned int index3) -{ - this->indices[0] = index1; - this->indices[1] = index2; - this->indices[2] = index3; -} - - - -inline -TableIndices<4>::TableIndices () -{ - this->indices[0] = this->indices[1] = this->indices[2] = this->indices[3] = 0; -} - - - -inline -TableIndices<4>::TableIndices (const unsigned int index1, - const unsigned int index2, - const unsigned int index3, - const unsigned int index4) +TableIndices::serialize (Archive &ar, const unsigned int) { - this->indices[0] = index1; - this->indices[1] = index2; - this->indices[2] = index3; - this->indices[3] = index4; -} - - - -inline -TableIndices<5>::TableIndices () -{ - this->indices[0] = this->indices[1] - = this->indices[2] - = this->indices[3] - = this->indices[4] = 0; -} - - - -inline -TableIndices<5>::TableIndices (const unsigned int index1, - const unsigned int index2, - const unsigned int index3, - const unsigned int index4, - const unsigned int index5) -{ - this->indices[0] = index1; - this->indices[1] = index2; - this->indices[2] = index3; - this->indices[3] = index4; - this->indices[4] = index5; -} - - - -inline -TableIndices<6>::TableIndices () -{ - this->indices[0] = this->indices[1] = this->indices[2] - = this->indices[3] = this->indices[4] - = this->indices[5] = 0; -} - - - -inline -TableIndices<6>::TableIndices (const unsigned int index1, - const unsigned int index2, - const unsigned int index3, - const unsigned int index4, - const unsigned int index5, - const unsigned int index6) -{ - this->indices[0] = index1; - this->indices[1] = index2; - this->indices[2] = index3; - this->indices[3] = index4; - this->indices[4] = index5; - this->indices[5] = index6; -} - - - -inline -TableIndices<7>::TableIndices () -{ - this->indices[0] = this->indices[1] = this->indices[2] - = this->indices[3] = this->indices[4] - = this->indices[5] = this->indices[6] = 0; -} - - - -inline -TableIndices<7>::TableIndices (const unsigned int index1, - const unsigned int index2, - const unsigned int index3, - const unsigned int index4, - const unsigned int index5, - const unsigned int index6, - const unsigned int index7) -{ - this->indices[0] = index1; - this->indices[1] = index2; - this->indices[2] = index3; - this->indices[3] = index4; - this->indices[4] = index5; - this->indices[5] = index6; - this->indices[6] = index7; + ar &indices; } - /** - * Output operator for indices; reports them in a list like this: - * [i1,i2,...]. + * Output operator for TableIndices objects; reports them in a list like + * this: [i1,i2,...]. + * + * @relates TableIndices */ template std::ostream & -operator << (std::ostream &o, +operator << (std::ostream &out, const TableIndices &indices) { - o << '['; + out << '['; for (unsigned int i=0; i