From f55a42a835b638ae82803d22e0a59a865dde208d Mon Sep 17 00:00:00 2001 From: Mark Olesen Date: Mon, 8 Jan 2018 09:59:04 +0100 Subject: [PATCH] ENH: improve robustness of scalarRanges from string (fixes #673) - now avoid Istream and token mechanism in favour of a simpler string parser. This makes the code clearer, smaller, robuster. - provide convenience ge/gt/le/lt static constructors for scalarRange for using bounds directly with specifying via a string parameter. - scalarRange, scalarRanges now follow the unary predicate pattern (using an operator() for testing). This allows their reuse in other contexts. Eg, for filtering operations: myHash.filterValues(scalarRange::ge(100)); - remove unused scalarRanges methods that were specific to handling lists of time values. These were superseded by timeSelector methods several versions ago. --- applications/test/scalarRanges/Make/files | 3 + applications/test/scalarRanges/Make/options | 0 .../test/scalarRanges/Test-scalarRanges.C | 112 ++++++ etc/controlDict | 1 - src/OpenFOAM/db/Time/timeSelector.C | 21 +- src/OpenFOAM/db/Time/timeSelector.H | 10 +- .../ranges/scalarRange/scalarRange.C | 354 ++++-------------- .../ranges/scalarRange/scalarRange.H | 139 ++++--- .../ranges/scalarRange/scalarRangeI.H | 184 +++++++++ .../ranges/scalarRange/scalarRanges.C | 117 +----- .../ranges/scalarRange/scalarRanges.H | 31 +- .../ranges/scalarRange/scalarRangesI.H | 50 +++ 12 files changed, 540 insertions(+), 482 deletions(-) create mode 100644 applications/test/scalarRanges/Make/files create mode 100644 applications/test/scalarRanges/Make/options create mode 100644 applications/test/scalarRanges/Test-scalarRanges.C create mode 100644 src/OpenFOAM/primitives/ranges/scalarRange/scalarRangeI.H create mode 100644 src/OpenFOAM/primitives/ranges/scalarRange/scalarRangesI.H diff --git a/applications/test/scalarRanges/Make/files b/applications/test/scalarRanges/Make/files new file mode 100644 index 0000000000..1ec0f43818 --- /dev/null +++ b/applications/test/scalarRanges/Make/files @@ -0,0 +1,3 @@ +Test-scalarRanges.C + +EXE = $(FOAM_USER_APPBIN)/Test-scalarRanges diff --git a/applications/test/scalarRanges/Make/options b/applications/test/scalarRanges/Make/options new file mode 100644 index 0000000000..e69de29bb2 diff --git a/applications/test/scalarRanges/Test-scalarRanges.C b/applications/test/scalarRanges/Test-scalarRanges.C new file mode 100644 index 0000000000..b9b755b2fa --- /dev/null +++ b/applications/test/scalarRanges/Test-scalarRanges.C @@ -0,0 +1,112 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2018 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM 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. + + OpenFOAM 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 OpenFOAM. If not, see . + +Description + Test scalar ranges +\*---------------------------------------------------------------------------*/ + +#include "argList.H" +#include "scalarRanges.H" + +using namespace Foam; + + +template +Ostream& printHash(const HTable& h) +{ + const auto keys = h.sortedToc(); + + Info<<"keys: " << keys.size() << "("; + for (const auto& k : keys) + { + Info<<" " << k; + } + Info<< " )" << nl; + + Info<<"vals: " << keys.size() << "("; + for (const auto& k : keys) + { + Info<<" " << h[k]; + } + Info<< " )" << nl; + + return Info; +} + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +// Main program: + +int main(int argc, char *argv[]) +{ + argList::noParallel(); + argList::noFunctionObjects(); + argList::addArgument("range,range range,range"); + argList::addNote + ( + "Test parsing of comma-separated ranges\n\n" + "Eg, ':10,20,40:70,1000:'" + ); + + argList args(argc, argv, false, true); + + HashTable testHash; + for (label i = 0; i < 26; ++i) + { + word key("X"); + key[0] = 'a' + i; + testHash.insert(key, i); + + key[0] = 'A' + i; + testHash.insert(key, 100 + i); + } + + printHash(testHash) + << nl; + + for (int argi = 1; argi < argc; ++argi) + { + Info<<"tokenize " << args[argi] << nl; + + scalarRanges ranges(args[argi]); + Info<<"=> " << ranges << endl; + + HashTable subHash(testHash); + subHash.filterValues(ranges); + + Info<<"filtered:" << nl; + + printHash(subHash) + << nl; + + subHash.filterValues(scalarRange::le(8)); + Info<<"filtered <= 8:" << nl; + + printHash(subHash) + << nl; + } + + return 0; +} + +// ************************************************************************* // diff --git a/etc/controlDict b/etc/controlDict index 672363c30f..2be965fb94 100644 --- a/etc/controlDict +++ b/etc/controlDict @@ -813,7 +813,6 @@ DebugSwitches saturateEvaporationModel 0; scalarAverageField 0; scalarField 0; - scalarRange 0; scaleSimilarity 0; scatterModel 0; searchableBox 0; diff --git a/src/OpenFOAM/db/Time/timeSelector.C b/src/OpenFOAM/db/Time/timeSelector.C index fc5185b31c..7a215e1eaa 100644 --- a/src/OpenFOAM/db/Time/timeSelector.C +++ b/src/OpenFOAM/db/Time/timeSelector.C @@ -3,7 +3,7 @@ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation - \\/ M anipulation | + \\/ M anipulation | Copyright (C) 2018 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -27,7 +27,6 @@ License #include "ListOps.H" #include "argList.H" #include "Time.H" -#include "StringStream.H" // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // @@ -37,9 +36,9 @@ Foam::timeSelector::timeSelector() {} -Foam::timeSelector::timeSelector(Istream& is) +Foam::timeSelector::timeSelector(const std::string& str) : - scalarRanges(is) + scalarRanges(str) {} @@ -47,7 +46,7 @@ Foam::timeSelector::timeSelector(Istream& is) bool Foam::timeSelector::selected(const instant& value) const { - return scalarRanges::selected(value.value()); + return scalarRanges::operator()(value.value()); } @@ -67,7 +66,7 @@ Foam::List Foam::timeSelector::selected(const instantList& times) const // Check specific values for (const scalarRange& range : *this) { - if (range.isExact()) + if (range.single()) { const scalar target = range.value(); @@ -97,8 +96,7 @@ Foam::List Foam::timeSelector::selected(const instantList& times) const } -Foam::instantList Foam::timeSelector::select(const instantList& times) -const +Foam::instantList Foam::timeSelector::select(const instantList& times) const { return subset(selected(times), times); } @@ -211,10 +209,7 @@ Foam::instantList Foam::timeSelector::select if (args.optionFound("time")) { // Can match 0/, but can never match constant/ - selectTimes = timeSelector - ( - args.optionLookup("time")() - ).selected(times); + selectTimes = timeSelector(args["time"]).selected(times); } // Add in latestTime (if selected) @@ -301,7 +296,7 @@ Foam::instantList Foam::timeSelector::selectIfPresent } // No timeSelector option specified. Do not change runTime. - return instantList(1, instant(runTime.value(), runTime.timeName())); + return instantList{ instant(runTime.value(), runTime.timeName()) }; } diff --git a/src/OpenFOAM/db/Time/timeSelector.H b/src/OpenFOAM/db/Time/timeSelector.H index 597790892c..e93d3cd5ee 100644 --- a/src/OpenFOAM/db/Time/timeSelector.H +++ b/src/OpenFOAM/db/Time/timeSelector.H @@ -3,7 +3,7 @@ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011-2015 OpenFOAM Foundation - \\/ M anipulation | + \\/ M anipulation | Copyright (C) 2018 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -89,17 +89,17 @@ class Time; class timeSelector : - public scalarRanges + private scalarRanges { public: // Constructors - //- Construct Null + //- Construct null timeSelector(); - //- Construct from Istream - timeSelector(Istream& is); + //- Construct by parsing string for time ranges + timeSelector(const std::string& str); // Member Functions diff --git a/src/OpenFOAM/primitives/ranges/scalarRange/scalarRange.C b/src/OpenFOAM/primitives/ranges/scalarRange/scalarRange.C index 83a946bf77..a77bdc2a95 100644 --- a/src/OpenFOAM/primitives/ranges/scalarRange/scalarRange.C +++ b/src/OpenFOAM/primitives/ranges/scalarRange/scalarRange.C @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation + \\ / A nd | Copyright (C) 2018 OpenCFD Ltd. \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -24,334 +24,106 @@ License \*---------------------------------------------------------------------------*/ #include "scalarRange.H" -#include "token.H" +#include "string.H" +#include "error.H" -// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // +// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * // -namespace Foam +bool Foam::scalarRange::parse(const std::string& str, scalarRange& range) { -int scalarRange::debug(debug::debugSwitch("scalarRange", 0)); -} + range.clear(); + const auto colon = str.find(':'); -// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // - -Foam::scalarRange::scalarRange() -: - type_(EMPTY), - value_(0), - value2_(0) -{} - - -Foam::scalarRange::scalarRange(const scalar lower, const scalar upper) -: - type_(RANGE), - value_(lower), - value2_(upper) -{ - if (lower > upper) + if (colon == std::string::npos) { - clear(); // Mark invalid range as empty + // "VALUE" + scalar val; + if (readScalar(str, val)) + { + range = scalarRange(val); + } } -} - - -Foam::scalarRange::scalarRange(Istream& is) -: - type_(EXACT), - value_(0), - value2_(0) -{ - is >> *this; - - if (scalarRange::debug) + else if (str.find(':', colon+1) != std::string::npos) { - Info<<"constructed scalarRange: " << *this << endl; + // A second colon is a syntax error + return false; } -} - - -// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // - -void Foam::scalarRange::clear() -{ - type_ = scalarRange::EMPTY; - value_ = 0; - value2_ = 0; -} - - -bool Foam::scalarRange::empty() const -{ - return type_ == EMPTY; -} - - -bool Foam::scalarRange::valid() const -{ - return type_ != EMPTY; -} - - -bool Foam::scalarRange::isExact() const -{ - return type_ == EXACT; -} - - -Foam::scalar Foam::scalarRange::value() const -{ - return value_; -} - - -Foam::scalar Foam::scalarRange::lower() const -{ - if (type_ == UPPER) + else if (colon == 0) { - return -Foam::GREAT; + // ":MAX" + scalar val; + if (readScalar(str.substr(1), val)) + { + range = scalarRange::le(val); + } + } + else if (colon == str.size()-1) + { + // "MIN:" + scalar val; + if (readScalar(str.substr(0, colon), val)) + { + range = scalarRange::ge(val); + } } else { - return value_; + // "MIN:MAX" + scalar minVal, maxVal; + if + ( + readScalar(str.substr(0, colon), minVal) + && readScalar(str.substr(colon+1), maxVal) + ) + { + range = scalarRange(minVal, maxVal); + } } + + return range.valid(); } -Foam::scalar Foam::scalarRange::upper() const + +Foam::scalarRange Foam::scalarRange::parse(const std::string& str) { - switch (type_) + scalarRange range; + + if (!parse(str, range)) { - case LOWER: - return Foam::GREAT; - break; - - case RANGE: - return value2_; - break; - - default: - return value_; - break; + Info<< "Bad scalar-range while parsing: " << str << endl; } -} - -bool Foam::scalarRange::selected(const scalar value) const -{ - switch (type_) - { - case LOWER: - return value >= value_; - - case UPPER: - return value <= value_; - - case RANGE: - return value >= value_ && value <= value2_; - - case EXACT: - return value == value_; - - default: - return false; - } -} - - - -// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * // - -bool Foam::scalarRange::operator==(const scalarRange& range) const -{ - return - ( - type_ == range.type_ - && value_ == range.value_ - && value2_ == range.value2_ - ); -} - - -bool Foam::scalarRange::operator!=(const scalarRange& range) const -{ - return !(operator==(range)); + return range; } // * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * // -Foam::Istream& Foam::operator>>(Istream& is, scalarRange& range) -{ - range.type_ = scalarRange::EXACT; - range.value_ = 0; - range.value2_ = 0; - - List toks(4); - label nTok = 0; - - // skip leading ',' - do - { - is.read(toks[nTok]); - is.check("scalarRange token read"); - } - while - ( - toks[nTok].isPunctuation() - && toks[nTok].pToken() == token::COMMA - ); - - ++nTok; - - // looks like ':VALUE' - if - ( - toks[nTok-1].isPunctuation() - && toks[nTok-1].pToken() == token::COLON - ) - { - range.type_ = scalarRange::UPPER; - is.read(toks[nTok++]); - is.check("scalarRange token read"); - } - - // a number is now required - if (!toks[nTok-1].isNumber()) - { - range.clear(); // Mark invalid range as empty - Info<< "rejected ill-formed or empty range:"; - for (label i=0; i Inf"; + case scalarRange::EQ: + os << range.min_; break; - case scalarRange::UPPER: - os << "-Inf <=> " << range.value_; + case scalarRange::GE: + case scalarRange::GT: + os << range.min_ << ":Inf"; break; - case scalarRange::RANGE: - os << range.value_ << " <=> " << range.value2_; + case scalarRange::LE: + case scalarRange::LT: + os << "-Inf:" << range.max_; break; - case scalarRange::EXACT: - os << range.value_; + case scalarRange::GE_LE: + os << range.min_ << ":" << range.max_; break; default: - os << "empty"; + os << "false"; break; } diff --git a/src/OpenFOAM/primitives/ranges/scalarRange/scalarRange.H b/src/OpenFOAM/primitives/ranges/scalarRange/scalarRange.H index 71d855e766..415673ad99 100644 --- a/src/OpenFOAM/primitives/ranges/scalarRange/scalarRange.H +++ b/src/OpenFOAM/primitives/ranges/scalarRange/scalarRange.H @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation + \\ / A nd | Copyright (C) 2018 OpenCFD Ltd. \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -25,12 +25,10 @@ Class Foam::scalarRange Description - A scalar range specifier. + Scalar bounds to be used as a unary predicate. - The range selector can be specified as an "LOWER:UPPER" range, as a - "LOWER:" bound, as an ":UPPER" bound or simply as an "EXACT" value. - The read constructor uses a colon (:) as a range marker and a comma (,) - to delimit the next possible range selector. + The bound can be specified as an "MIN:MAX" range, as a "MIN:" or ":MAX" + bound or simply as a single "VALUE". SourceFiles scalarRange.C @@ -46,96 +44,125 @@ SourceFiles namespace Foam { -// Forward declaration of classes -class Istream; -class Ostream; - -// Forward declaration of friend functions and operators +// Forward declarations class scalarRange; -Istream& operator>>(Istream& is, scalarRange& range); +class Ostream; Ostream& operator<<(Ostream& os, const scalarRange& range); /*---------------------------------------------------------------------------*\ - Class scalarRange Declaration + Class scalarRange Declaration \*---------------------------------------------------------------------------*/ class scalarRange { - //- Enumeration defining the types of token - enum rangeType + //- Enumeration defining type of range test to use + enum testType { - EMPTY = 0, - EXACT, - LOWER, - UPPER, - RANGE + NONE = 0, //!< An empty, invalid (inverse) range. Never matches. + EQ, //!< A single value test. + GE, //!< Greater-than-equal. + GT, //!< Greater-than. + LE, //!< Less-than-equal. + LT, //!< Less-than. + GE_LE //!< An inclusive range. }; // Private Member Data - enum rangeType type_; - scalar value_; - scalar value2_; + //- The type of range test + enum testType type_; + + //- The min value of the range + scalar min_; + + //- The max value of the range + scalar max_; + + //- Construct from components without sanity checking + inline scalarRange(const testType type, scalar minVal, scalar maxVal); public: - static int debug; - - // Constructors - //- Construct an empty range - scalarRange(); + //- Construct an empty (inverse) range + inline scalarRange(); - //- Construct a range from lower to upper - scalarRange(const scalar lower, const scalar upper); + //- Construct an exact value matcher + explicit inline scalarRange(const scalar value); - //- Construct from Istream. - // Since commas can be used as list delimiters, - // leading and trailing commas are ignored. - scalarRange(Istream& is); + //- Construct a range from min-value to max-value + inline scalarRange(const scalar minVal, const scalar maxVal); + + + // Static Constructors + + //- Construct by parsing string content. + // A colon (:) is used as a range marker or when specifying + // greater-than or less-than bounds. + // \return True if no parse problems were encountered. + static bool parse(const std::string& str, scalarRange& range); + + //- Construct by parsing string content. + // Any parse problems are emitted as information and the returned + // range is of type empty(). + // \return The parsed range, which is empty() on any problems + static scalarRange parse(const std::string& str); + + + //- Construct a greater-than-equals bound + inline static scalarRange ge(const scalar minVal); + + //- Construct a greater-than bound + inline static scalarRange gt(const scalar minVal); + + //- Construct a less-than-equals bound + inline static scalarRange le(const scalar maxVal); + + //- Construct a less-than bound + inline static scalarRange lt(const scalar maxVal); // Member Functions - //- Reset to an empty range. - void clear(); + //- Reset to an empty (inverse) range. + inline void clear(); - //- Is the range empty? - bool empty() const; + //- True if bounds are empty (eg, inverted) + inline bool empty() const; - //- Is the range non-empty? - bool valid() const; + //- True if bounds are non-empty. + inline bool valid() const; - //- Is the range 'EXACT'? - bool isExact() const; + //- True if the bounds represents a single value. + inline bool single() const; - //- The value constituting an 'EXACT' match - // or the values for 'UPPER' or 'LOWER' limits - scalar value() const; + //- The min value of the range. + inline scalar min() const; - //- The lower limit - scalar lower() const; + //- The max value of the range. + inline scalar max() const; - //- The upper limit - scalar upper() const; - - //- Return true if the value is within the range - bool selected(const scalar value) const; + //- A representative (average) value for the range. + // For GE, LE bounds it is the min/max value, respectively. + inline scalar value() const; // Member Operators - bool operator==(const scalarRange& range) const; - bool operator!=(const scalarRange& range) const; + //- Unary predicate to test if the value is within the bounds + inline bool operator()(const scalar& value) const; + + inline bool operator==(const scalarRange& rhs) const; + inline bool operator!=(const scalarRange& rhs) const; // IOstream Operators - friend Istream& operator>>(Istream& is, scalarRange& range); + //- Print information about the bounds. friend Ostream& operator<<(Ostream& os, const scalarRange& range); }; @@ -146,6 +173,8 @@ public: // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +#include "scalarRangeI.H" + #endif // ************************************************************************* // diff --git a/src/OpenFOAM/primitives/ranges/scalarRange/scalarRangeI.H b/src/OpenFOAM/primitives/ranges/scalarRange/scalarRangeI.H new file mode 100644 index 0000000000..18cd09d2fe --- /dev/null +++ b/src/OpenFOAM/primitives/ranges/scalarRange/scalarRangeI.H @@ -0,0 +1,184 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2018 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM 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. + + OpenFOAM 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 OpenFOAM. If not, see . + +\*---------------------------------------------------------------------------*/ + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +inline Foam::scalarRange::scalarRange +( + const scalarRange::testType type, + const scalar minVal, + const scalar maxVal +) +: + type_(type), + min_(minVal), + max_(maxVal) +{} + + +inline Foam::scalarRange::scalarRange() +: + scalarRange(NONE, Foam::VGREAT, -Foam::VGREAT) +{} + + +inline Foam::scalarRange::scalarRange(const scalar value) +: + scalarRange(EQ, value, value) +{} + + +inline Foam::scalarRange::scalarRange(const scalar minVal, const scalar maxVal) +: + scalarRange(GE_LE, minVal, maxVal) +{ + if (minVal > maxVal) + { + clear(); // Inverted - explicitly mark as such + } + else if (minVal == maxVal) + { + type_ = EQ; + } +} + + +inline Foam::scalarRange Foam::scalarRange::ge(const scalar minVal) +{ + return scalarRange(GE, minVal, Foam::VGREAT); +} + + +inline Foam::scalarRange Foam::scalarRange::gt(const scalar minVal) +{ + return scalarRange(GT, minVal, Foam::VGREAT); +} + + +inline Foam::scalarRange Foam::scalarRange::le(const scalar maxVal) +{ + return scalarRange(LE, -Foam::VGREAT, maxVal); +} + +inline Foam::scalarRange Foam::scalarRange::lt(const scalar maxVal) +{ + return scalarRange(LT, -Foam::VGREAT, maxVal); +} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +inline void Foam::scalarRange::clear() +{ + type_ = scalarRange::NONE; + min_ = Foam::VGREAT; + max_ = -Foam::VGREAT; +} + + +inline bool Foam::scalarRange::empty() const +{ + return type_ == NONE; +} + + +inline bool Foam::scalarRange::valid() const +{ + return type_; +} + + +inline bool Foam::scalarRange::single() const +{ + return type_ == EQ; +} + + +inline Foam::scalar Foam::scalarRange::min() const +{ + return min_; +} + + +inline Foam::scalar Foam::scalarRange::max() const +{ + return max_; +} + + +inline Foam::scalar Foam::scalarRange::value() const +{ + switch (type_) + { + case EQ: + return min_; // For equals, min and max are identical + + case GE: + case GT: + return min_; + + case LE: + case LT: + return max_; + + case GE_LE: + return 0.5*(min_ + max_); + + default: + return 0; + } +} + + +// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * // + +inline bool Foam::scalarRange::operator()(const scalar& value) const +{ + switch (type_) + { + case EQ: return equal(value, min_); + case GE: return value >= min_; + case GT: return value > min_; + case LE: return value <= max_; + case LT: return value < max_; + case GE_LE: return value >= min_ && value <= max_; + default: return false; + } +} + + +inline bool Foam::scalarRange::operator==(const scalarRange& rhs) const +{ + return (type_ == rhs.type_ && min_ == rhs.min_ && max_ == rhs.max_); +} + + +inline bool Foam::scalarRange::operator!=(const scalarRange& rhs) const +{ + return !(operator==(rhs)); +} + + +// ************************************************************************* // diff --git a/src/OpenFOAM/primitives/ranges/scalarRange/scalarRanges.C b/src/OpenFOAM/primitives/ranges/scalarRange/scalarRanges.C index 429efdca0a..186efd781a 100644 --- a/src/OpenFOAM/primitives/ranges/scalarRange/scalarRanges.C +++ b/src/OpenFOAM/primitives/ranges/scalarRange/scalarRanges.C @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation + \\ / A nd | Copyright (C) 2018 OpenCFD Ltd. \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -24,114 +24,35 @@ License \*---------------------------------------------------------------------------*/ #include "scalarRanges.H" -#include "DynamicList.H" -#include "ListOps.H" +#include "stringOps.H" // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // -Foam::scalarRanges::scalarRanges() +Foam::scalarRanges::scalarRanges(const std::string& str) : - List(0) -{} - - -Foam::scalarRanges::scalarRanges(Istream& is) -: - List(0) + List() { - DynamicList lst; + const SubStrings items = stringOps::splitAny(str, " ,;"); - while (is.good()) + setSize(items.size()); + + label nItems = 0; + + for (const auto& item : items) { - scalarRange sr(is); - if (sr.valid()) + const std::string s = item.str(); + + if (scalarRange::parse(s, operator[](nItems))) { - lst.append(sr); + ++nItems; + } + else + { + Info<< "Bad scalar-range while parsing: " << s << endl; } } - transfer(lst); -} - - -// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // - -bool Foam::scalarRanges::selected(const scalar value) const -{ - forAll(*this, i) - { - if (operator[](i).selected(value)) - { - return true; - } - } - - return false; -} - - -Foam::List Foam::scalarRanges::selected -( - const UList& values -) const -{ - List lst(values.size(), false); - - // check ranges - forAll(values, i) - { - if (selected(values[i])) - { - lst[i] = true; - } - } - - // check specific values - forAll(*this, rangeI) - { - if (operator[](rangeI).isExact()) - { - scalar target = operator[](rangeI).value(); - - int nearestIndex = -1; - scalar nearestDiff = Foam::GREAT; - - forAll(values, timeIndex) - { - scalar diff = fabs(values[timeIndex] - target); - if (diff < nearestDiff) - { - nearestDiff = diff; - nearestIndex = timeIndex; - } - } - - if (nearestIndex >= 0) - { - lst[nearestIndex] = true; - } - } - } - - return lst; -} - - -Foam::List Foam::scalarRanges::select -( - const List& values -) const -{ - return subset(selected(values), values); -} - - -void Foam::scalarRanges::inplaceSelect -( - List& values -) const -{ - inplaceSubset(selected(values), values); + setSize(nItems); } diff --git a/src/OpenFOAM/primitives/ranges/scalarRange/scalarRanges.H b/src/OpenFOAM/primitives/ranges/scalarRange/scalarRanges.H index f82312b612..89e9f24d9e 100644 --- a/src/OpenFOAM/primitives/ranges/scalarRange/scalarRanges.H +++ b/src/OpenFOAM/primitives/ranges/scalarRange/scalarRanges.H @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation + \\ / A nd | Copyright (C) 2018 OpenCFD Ltd. \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -25,7 +25,7 @@ Class Foam::scalarRanges Description - A List of scalarRange. + A collection of scalar bounds to be used as a unary predicate. SourceFiles scalarRanges.C @@ -44,7 +44,7 @@ namespace Foam { /*---------------------------------------------------------------------------*\ - Class scalarRanges Declaration + Class scalarRanges Declaration \*---------------------------------------------------------------------------*/ class scalarRanges @@ -56,27 +56,18 @@ public: // Constructors //- Construct null - scalarRanges(); + inline scalarRanges(); - //- Construct from Istream. - // The list items are comma-delimited. - scalarRanges(Istream& is); + //- Construct by parsing a string for scalar ranges + // The individual items are space, comma or semicolon delimited. + scalarRanges(const std::string& str); - // Member Functions + // Member Operators - //- Return true if the given value is within the ranges - bool selected(const scalar value) const; + //- Unary predicate to test if the value is within any of the ranges + inline bool operator()(const scalar& value) const; - //- Return the set of selected entries in the given list - // that are within the ranges - List selected(const UList& values) const; - - //- Select a list of values that are within the ranges - List select(const List& values) const; - - //- Select a list of values that are within the ranges - void inplaceSelect(List& values) const; }; @@ -86,6 +77,8 @@ public: // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +#include "scalarRangesI.H" + #endif // ************************************************************************* // diff --git a/src/OpenFOAM/primitives/ranges/scalarRange/scalarRangesI.H b/src/OpenFOAM/primitives/ranges/scalarRange/scalarRangesI.H new file mode 100644 index 0000000000..edc45f84c3 --- /dev/null +++ b/src/OpenFOAM/primitives/ranges/scalarRange/scalarRangesI.H @@ -0,0 +1,50 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2018 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM 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. + + OpenFOAM 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 OpenFOAM. If not, see . + +\*---------------------------------------------------------------------------*/ + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +inline Foam::scalarRanges::scalarRanges() +: + List() +{} + + +// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * // + +inline bool Foam::scalarRanges::operator()(const scalar& value) const +{ + for (const scalarRange& range : *this) + { + if (range(value)) + { + return true; + } + } + + return false; +} + + +// ************************************************************************* //