From 903ced5261675e90313e6902e27361b552405e7f Mon Sep 17 00:00:00 2001 From: Wolfgang Bangerth Date: Mon, 24 Jul 2000 07:45:09 +0000 Subject: [PATCH] Implement the ability to check bounds for integer and double parameters. git-svn-id: https://svn.dealii.org/trunk@3192 0785d39b-7218-0410-832d-ea1e28bc413d --- deal.II/base/Todo | 7 +- deal.II/base/include/base/parameter_handler.h | 409 ++++++++++++++++-- .../source/data_out_base.all_dimensions.cc | 4 +- deal.II/base/source/parameter_handler.cc | 394 ++++++++++------- 4 files changed, 613 insertions(+), 201 deletions(-) diff --git a/deal.II/base/Todo b/deal.II/base/Todo index d8e779b064..c6410e8ebc 100644 --- a/deal.II/base/Todo +++ b/deal.II/base/Todo @@ -34,8 +34,9 @@ Change to in grid/point.h and grid/tria_iterator.h when this becomes possible. -Add support for void member functions also for Mem_Fun_Data[5-*] and - Mem_Fun*. +Document the JobIdentifier class members. -Document the JobIdentifier class members. +Use numeric_limits to designate the default values of bounds + parameters of Patterns::Integer and Patterns::Double. This would then + allow to use half-open intervals as well, amoung other advantages. diff --git a/deal.II/base/include/base/parameter_handler.h b/deal.II/base/include/base/parameter_handler.h index 7b3fd040d1..df5a6535e9 100644 --- a/deal.II/base/include/base/parameter_handler.h +++ b/deal.II/base/include/base/parameter_handler.h @@ -40,9 +40,8 @@ enum OutputStyle { * Declare some regexps which * may be used to define patterns. */ -struct Patterns +namespace Patterns { - public: /** * Base class to declare common * interface. @@ -69,102 +68,415 @@ struct Patterns virtual string description () const = 0; /** - * Return a pointer to an exact - * copy of the object. This is - * necessary since we want to store + * Return a pointer to an + * exact copy of the + * object. This is necessary + * since we want to store * objects of this type in - * containers. + * containers, were we need + * to copy objects without + * knowledge of their actual + * data type (we only have + * pointers to the base + * class). + * + * Ownership of the objects + * returned by this function + * is passed to the caller of + * this function. */ virtual PatternBase * clone () const = 0; }; /** * Test for the string being an - * integer. + * integer. If bounds are given + * to the constructor, then the + * integer given also needs to be + * withing the interval specified + * by these bounds. Note that + * unlike common convention in + * the C++ standard library, both + * bounds of this interval are + * inclusive; the reason is that + * in practice in most cases, one + * needs closed intervals, but + * these can only be realized + * with inclusive bounds for + * non-integer values. We thus + * stay consistent by always + * using closed intervals. + * + * If the upper bound given to + * the constructor is smaller + * than the lower bound, then the + * infinite interval is implied, + * i.e. every integer is allowed. + * + * Giving bounds may be useful if + * for example a value can only + * be positive and less than a + * reasonable upper bound (for + * example the number of + * refinement steps to be + * performed), or in many other + * cases. */ class Integer : public PatternBase { public: + /** + * Constructor. Bounds can be + * specified within which a + * valid parameter has to + * be. If the upper bound is + * smaller than the lower + * bound, then the infinite + * interval is meant. The + * default values are chosen + * such that no bounds are + * enforced on parameters. + */ + Integer (const int lower_bound = 1, + const int upper_bound = 0); + + /** + * Return @p{true} if the + * string is an integer and + * its value is within the + * specified range. + */ virtual bool match (const string &test_string) const; + + /** + * Return a description of + * the pattern that valid + * string are expected to + * match. If bounds were + * specified to the + * constructor, then include + * them into this + * description. + */ virtual string description () const; + + /** + * Return a copy of the + * present object, which is + * newly allocated on the + * heap. Ownership of that + * object is transferred to + * the caller of this + * function. + */ virtual PatternBase * clone () const; + + private: + /** + * Value of the lower + * bound. A number that + * satisfies the @p{match} + * operation of this class + * must be equal to this + * value or larger, if the + * bounds of the interval for + * a valid range. + */ + const int lower_bound; + + /** + * Value of the upper + * bound. A number that + * satisfies the @p{match} + * operation of this class + * must be equal to this + * value or less, if the + * bounds of the interval for + * a valid range. + */ + const int upper_bound; }; /** - * Test for the string being a double. + * Test for the string being a + * @p{double}. If bounds are + * given to the constructor, then + * the integer given also needs + * to be withing the interval + * specified by these + * bounds. Note that unlike + * common convention in the C++ + * standard library, both bounds + * of this interval are + * inclusive; the reason is that + * in practice in most cases, one + * needs closed intervals, but + * these can only be realized + * with inclusive bounds for + * non-integer values. We thus + * stay consistent by always + * using closed intervals. + * + * If the upper bound given to + * the constructor is smaller + * than the lower bound, then the + * infinite interval is implied, + * i.e. every integer is allowed. + * + * Giving bounds may be useful if + * for example a value can only + * be positive and less than a + * reasonable upper bound (for + * example damping parameters are + * frequently only reasonable if + * between zero and one), or in + * many other cases. */ class Double : public PatternBase { public: + /** + * Constructor. Bounds can be + * specified within which a + * valid parameter has to + * be. If the upper bound is + * smaller than the lower + * bound, then the infinite + * interval is meant. The + * default values are chosen + * such that no bounds are + * enforced on parameters. + */ + Double (const int lower_bound = 1, + const int upper_bound = 0); + + /** + * Return @p{true} if the + * string is a number and its + * value is within the + * specified range. + */ virtual bool match (const string &test_string) const; + + /** + * Return a description of + * the pattern that valid + * string are expected to + * match. If bounds were + * specified to the + * constructor, then include + * them into this + * description. + */ virtual string description () const; + + /** + * Return a copy of the + * present object, which is + * newly allocated on the + * heap. Ownership of that + * object is transferred to + * the caller of this + * function. + */ virtual PatternBase * clone () const; + + private: + /** + * Value of the lower + * bound. A number that + * satisfies the @p{match} + * operation of this class + * must be equal to this + * value or larger, if the + * bounds of the interval for + * a valid range. + */ + const int lower_bound; + + /** + * Value of the upper + * bound. A number that + * satisfies the @p{match} + * operation of this class + * must be equal to this + * value or less, if the + * bounds of the interval for + * a valid range. + */ + const int upper_bound; }; /** - * Test for the string being one of - * a sequence of values given like a - * regular expression. For example, if - * the string given to the constructor - * is "red|blue|black", then the @p{match} - * function returns @p{true} exactly if - * the string is either "red" or "blue" - * or "black". Spaces around the pipe - * signs do not matter and are - * eliminated. + * Test for the string being one + * of a sequence of values given + * like a regular expression. For + * example, if the string given + * to the constructor is + * @p{"red|blue|black"}, then the + * @p{match} function returns + * @p{true} exactly if the string + * is either "red" or "blue" or + * "black". Spaces around the + * pipe signs do not matter and + * are eliminated. */ class Selection : public PatternBase { public: + /** + * Constructor. Take the + * given parameter as the + * specification of valid + * strings. + */ Selection (const string &seq); + + /** + * Return @p{true} if the + * string is an element of + * the description list + * passed to the constructor. + */ virtual bool match (const string &test_string) const; + + /** + * Return a description of + * the pattern that valid + * string are expected to + * match. Here, this is the + * list of valid strings + * passed to the constructor. + */ virtual string description () const; + + /** + * Return a copy of the + * present object, which is + * newly allocated on the + * heap. Ownership of that + * object is transferred to + * the caller of this + * function. + */ virtual PatternBase * clone () const; + private: + /** + * List of valid strings as + * passed to the + * constructor. We don't make + * this string constant, as + * we process it somewhat in + * the constructor. + */ string sequence; }; /** - * This class is much like the @p{Selection} - * class, but it allows the input to be - * a comma-separated list of values which - * each have to be given in the constructor - * argument. For example, if the string to - * the constructor was @p{"ucd|gmv|eps"}, then - * the following would be legal input: - * @p{eps, gmv}. You may give an arbitrarily - * long list of values, where there may be - * as many spaces around commas as you like. - * However, commas are not allowed inside - * the values given to the constructor. + * This class is much like the + * @p{Selection} class, but it + * allows the input to be a + * comma-separated list of values + * which each have to be given in + * the constructor argument. For + * example, if the string to the + * constructor was + * @p{"ucd|gmv|eps"}, then the + * following would be legal + * input: @p{eps, gmv}. You may + * give an arbitrarily long list + * of values, where there may be + * as many spaces around commas + * as you like. However, commas + * are not allowed inside the + * values given to the + * constructor. */ class MultipleSelection : public PatternBase { public: + /** + * Constructor. Take the + * given parameter as the + * specification of valid + * strings. + */ MultipleSelection (const string &seq); + + /** + * Return @p{true} if the + * string is an element of + * the description list + * passed to the constructor. + */ virtual bool match (const string &test_string) const; + + /** + * Return a description of + * the pattern that valid + * string are expected to + * match. Here, this is the + * list of valid strings + * passed to the constructor. + */ virtual string description () const; + + /** + * Return a copy of the + * present object, which is + * newly allocated on the + * heap. Ownership of that + * object is transferred to + * the caller of this + * function. + */ virtual PatternBase * clone () const; + /** + * Exception. + */ DeclException1 (ExcCommasNotAllowed, int, << "A comma was found at position " << arg1 << " of your input string, but commas are not allowed here."); private: + /** + * List of valid strings as + * passed to the + * constructor. We don't make + * this string constant, as + * we process it somewhat in + * the constructor. + */ string sequence; }; /** - * Test for the string being either - * "true" or "false". This is mapped - * to the @p{Selection} class. + * Test for the string being + * either "true" or "false". This + * is mapped to the @p{Selection} + * class. */ class Bool : public Selection { public: + /** + * Constrcuctor. + */ Bool (); + + /** + * Return a copy of the + * present object, which is + * newly allocated on the + * heap. Ownership of that + * object is transferred to + * the caller of this + * function. + */ virtual PatternBase * clone () const; }; @@ -176,14 +488,39 @@ struct Patterns { public: /** - * Allow for at least one non-virtual + * Constructor. (Allow for at + * least one non-virtual * function in this class, as - * otherwise sometimes no virtual - * table is emitted. + * otherwise sometimes no + * virtual table is emitted.) */ Anything (); + + /** + * Return @p{true} if the + * string matches its + * constraints, i.e. always. + */ virtual bool match (const string &test_string) const; + + /** + * Return a description of + * the pattern that valid + * string are expected to + * match. Here, this is the + * string @p{"[Anything]"}. + */ virtual string description () const; + + /** + * Return a copy of the + * present object, which is + * newly allocated on the + * heap. Ownership of that + * object is transferred to + * the caller of this + * function. + */ virtual PatternBase * clone () const; }; }; diff --git a/deal.II/base/source/data_out_base.all_dimensions.cc b/deal.II/base/source/data_out_base.all_dimensions.cc index 1467e4097f..9c85ace5ee 100644 --- a/deal.II/base/source/data_out_base.all_dimensions.cc +++ b/deal.II/base/source/data_out_base.all_dimensions.cc @@ -217,9 +217,9 @@ void DataOutBase::EpsFlags::declare_parameters (ParameterHandler &prm) prm.declare_entry ("Line widths in eps units", "0.5", Patterns::Double()); prm.declare_entry ("Azimut angle", "60", - Patterns::Double()); + Patterns::Double(0,180)); prm.declare_entry ("Turn angle", "30", - Patterns::Double()); + Patterns::Double(0,360)); prm.declare_entry ("Scaling for z-axis", "1", Patterns::Double ()); prm.declare_entry ("Draw mesh lines", "true", diff --git a/deal.II/base/source/parameter_handler.cc b/deal.II/base/source/parameter_handler.cc index 9c307444da..604e74b0bf 100644 --- a/deal.II/base/source/parameter_handler.cc +++ b/deal.II/base/source/parameter_handler.cc @@ -22,238 +22,311 @@ -Patterns::PatternBase::~PatternBase () -{}; +namespace Patterns +{ + PatternBase::~PatternBase () + {}; -bool Patterns::Integer::match (const string &test_string) const -{ - istrstream str(test_string.c_str()); - int i; - if (str >> i) return true; - return false; -}; + Integer::Integer (const int lower_bound, + const int upper_bound) : + lower_bound (lower_bound), + upper_bound (upper_bound) + {}; -string Patterns::Integer::description () const -{ - return "[Integer]"; -}; + bool Integer::match (const string &test_string) const + { + istrstream str(test_string.c_str()); + int i; + if (str >> i) + { + // check whether valid bounds + // were specified, and if so + // enforce their values + if (lower_bound <= upper_bound) + return ((lower_bound <= i) && + (upper_bound >= i)); + else + return true; + }; + + return false; + }; -Patterns::PatternBase * -Patterns::Integer::clone () const -{ - return new Patterns::Integer(); -}; + string Integer::description () const + { + // check whether valid bounds + // were specified, and if so + // output their values + if (lower_bound <= upper_bound) + { + ostrstream description; + description << "[Integer range " + << lower_bound << "..." << upper_bound + << " (inclusive)]" + << ends; + return description.str(); + } + else + // if no bounds were given, then + // return generic string + return "[Integer]"; + }; -bool Patterns::Double::match (const string &test_string) const -{ - istrstream str(test_string.c_str()); - double d; - if (str >> d) return true; - return false; -}; + PatternBase * + Integer::clone () const + { + return new Integer(lower_bound, upper_bound); + }; -string Patterns::Double::description () const -{ - return "[Integer]"; -}; + Double::Double (const int lower_bound, + const int upper_bound) : + lower_bound (lower_bound), + upper_bound (upper_bound) + {}; -Patterns::PatternBase * -Patterns::Double::clone () const { - return new Patterns::Double(); -}; + bool Double::match (const string &test_string) const + { + istrstream str(test_string.c_str()); + double d; + if (str >> d) + { + // check whether valid bounds + // were specified, and if so + // enforce their values + if (lower_bound <= upper_bound) + return ((lower_bound <= d) && + (upper_bound >= d)); + else + return true; + }; + return false; + }; -Patterns::Selection::Selection (const string &seq) -{ - sequence = seq; - while (sequence.find(" |") != string::npos) - sequence.replace (sequence.find(" |"), 2, '|'); - while (sequence.find("| ") != string::npos) - sequence.replace (sequence.find("| "), 2, '|'); -}; + string Double::description () const + { + // check whether valid bounds + // were specified, and if so + // output their values + if (lower_bound <= upper_bound) + { + ostrstream description; + description << "[Floating point range " + << lower_bound << "..." << upper_bound + << " (inclusive)]" + << ends; + return description.str(); + } + else + // if no bounds were given, then + // return generic string + return "[Double]"; + }; -bool Patterns::Selection::match (const string &test_string) const -{ - vector choices; - string tmp(sequence); - // check the different possibilities - while (tmp.find('|') != string::npos) - { - if (test_string == string(tmp, 0, tmp.find('|'))) - return true; + PatternBase * + Double::clone () const + { + return new Double(lower_bound, upper_bound); + }; + + + + Selection::Selection (const string &seq) + { + sequence = seq; + + while (sequence.find(" |") != string::npos) + sequence.replace (sequence.find(" |"), 2, '|'); + while (sequence.find("| ") != string::npos) + sequence.replace (sequence.find("| "), 2, '|'); + }; + + + + bool Selection::match (const string &test_string) const + { + vector choices; + string tmp(sequence); + // check the different possibilities + while (tmp.find('|') != string::npos) + { + if (test_string == string(tmp, 0, tmp.find('|'))) + return true; - tmp.erase (0, tmp.find('|')+1); - }; - // check last choice, not finished by | - if (test_string == tmp) - return true; + tmp.erase (0, tmp.find('|')+1); + }; + // check last choice, not finished by | + if (test_string == tmp) + return true; - // not found - return false; -}; + // not found + return false; + }; -string Patterns::Selection::description () const -{ - return sequence; -}; + string Selection::description () const + { + return sequence; + }; -Patterns::PatternBase * -Patterns::Selection::clone () const -{ - return new Patterns::Selection(sequence); -}; + PatternBase * + Selection::clone () const + { + return new Selection(sequence); + }; -Patterns::MultipleSelection::MultipleSelection (const string &seq) -{ - Assert (seq.find (",") == string::npos, ExcCommasNotAllowed(seq.find(","))); + MultipleSelection::MultipleSelection (const string &seq) + { + Assert (seq.find (",") == string::npos, ExcCommasNotAllowed(seq.find(","))); - sequence = seq; - while (sequence.find(" |") != string::npos) - sequence.replace (sequence.find(" |"), 2, '|'); - while (sequence.find("| ") != string::npos) - sequence.replace (sequence.find("| "), 2, '|'); -}; + sequence = seq; + while (sequence.find(" |") != string::npos) + sequence.replace (sequence.find(" |"), 2, '|'); + while (sequence.find("| ") != string::npos) + sequence.replace (sequence.find("| "), 2, '|'); + }; -bool Patterns::MultipleSelection::match (const string &test_string_list) const -{ - string tmp = test_string_list; - list split_list; + bool MultipleSelection::match (const string &test_string_list) const + { + string tmp = test_string_list; + list split_list; - // first split the input list - while (tmp.length() != 0) - { - string name; - name = tmp; + // first split the input list + while (tmp.length() != 0) + { + string name; + name = tmp; - if (name.find(",") != string::npos) - { - name.erase (name.find(","), string::npos); - tmp.erase (0, test_string_list.find(",")+1); - } - else - tmp = ""; + if (name.find(",") != string::npos) + { + name.erase (name.find(","), string::npos); + tmp.erase (0, test_string_list.find(",")+1); + } + else + tmp = ""; - while ((name.length() != 0) && - (name[0] == ' ')) - name.erase (0,1); - while (name[name.length()-1] == ' ') - name.erase (name.length()-1, 1); + while ((name.length() != 0) && + (name[0] == ' ')) + name.erase (0,1); + while (name[name.length()-1] == ' ') + name.erase (name.length()-1, 1); - split_list.push_back (name); - }; + split_list.push_back (name); + }; - // check the different possibilities - for (list::const_iterator test_string = split_list.begin(); - test_string != split_list.end(); ++test_string) - { - bool string_found = false; + // check the different possibilities + for (list::const_iterator test_string = split_list.begin(); + test_string != split_list.end(); ++test_string) + { + bool string_found = false; - tmp = sequence; - while (tmp.find('|') != string::npos) - { - if (*test_string == string(tmp, 0, tmp.find('|'))) - { - // string found, quit - // loop. don't change - // tmp, since we don't - // need it anymore. - string_found = true; - break; - }; + tmp = sequence; + while (tmp.find('|') != string::npos) + { + if (*test_string == string(tmp, 0, tmp.find('|'))) + { + // string found, quit + // loop. don't change + // tmp, since we don't + // need it anymore. + string_found = true; + break; + }; - tmp.erase (0, tmp.find('|')+1); - }; - // check last choice, not finished by | - if (!string_found) - if (*test_string == tmp) - string_found = true; + tmp.erase (0, tmp.find('|')+1); + }; + // check last choice, not finished by | + if (!string_found) + if (*test_string == tmp) + string_found = true; - if (!string_found) - return false; - }; + if (!string_found) + return false; + }; - return true; -}; + return true; + }; -string Patterns::MultipleSelection::description () const -{ - return sequence; -}; + string MultipleSelection::description () const + { + return sequence; + }; -Patterns::PatternBase * -Patterns::MultipleSelection::clone () const -{ - return new Patterns::MultipleSelection(sequence); -}; + PatternBase * + MultipleSelection::clone () const + { + return new MultipleSelection(sequence); + }; -Patterns::Bool::Bool () : - Selection ("true|false") -{}; + Bool::Bool () : + Selection ("true|false") + {}; -Patterns::PatternBase * -Patterns::Bool::clone () const -{ - return new Patterns::Bool(); -}; + PatternBase * + Bool::clone () const + { + return new Bool(); + }; -Patterns::Anything::Anything () -{}; + Anything::Anything () + {}; -bool Patterns::Anything::match (const string &) const -{ - return true; -}; + bool Anything::match (const string &) const + { + return true; + }; -string Patterns::Anything::description () const -{ - return "[Anything]"; -}; + string Anything::description () const + { + return "[Anything]"; + }; -Patterns::PatternBase * -Patterns::Anything::clone () const -{ - return new Patterns::Anything(); -}; + PatternBase * + Anything::clone () const + { + return new Anything(); + }; + +} // end namespace Patterns @@ -380,7 +453,8 @@ bool ParameterHandler::declare_entry (const string &entry, ExcEntryAlreadyExists (entry)); // Default must match Pattern Assert (pattern.match (default_value), - ExcDefaultDoesNotMatchPattern(default_value, pattern.description())); + ExcDefaultDoesNotMatchPattern(default_value, + pattern.description())); // does entry already exist? if (p->entries.find (entry) != p->entries.end()) -- 2.39.5