ENH: improvements to label/scalar ranges

- construct from MinMax, optional start index for identity factory
  method to match Foam::identity()

- use GREAT instead of VGREAT in inverted scalarRange.
  Consistent with boundBox - to reduce the potential of overflow
  if calculating the span.

- add min()/max() methods to labelRange
This commit is contained in:
Mark Olesen 2019-02-16 16:08:43 +01:00 committed by Andrew Heather
parent 17a579bf92
commit 041be829fc
9 changed files with 225 additions and 85 deletions

View File

@ -114,25 +114,25 @@ public:
// Member Functions
//- Return first
inline const T1& first() const
inline const T1& first() const noexcept
{
return f_;
}
//- Return first
inline T1& first()
inline T1& first() noexcept
{
return f_;
}
//- Return second
inline const T2& second() const
inline const T2& second() const noexcept
{
return s_;
}
//- Return second
inline T2& second()
inline T2& second() noexcept
{
return s_;
}

View File

@ -112,8 +112,8 @@ template<class T> class MinMax;
class zero;
// Common min/max types
typedef MinMax<label> labelMinMax;
typedef MinMax<scalar> scalarMinMax;
typedef MinMax<label> labelMinMax; //!< A label min/max range
typedef MinMax<scalar> scalarMinMax; //!< A scalar min/max range
/*---------------------------------------------------------------------------*\
@ -164,16 +164,16 @@ public:
// Access
//- The min value (first)
inline const T& min() const;
inline const T& min() const noexcept;
//- The min value (first)
inline T& min();
inline T& min() noexcept;
//- The max value (second)
inline const T& max() const;
inline const T& max() const noexcept;
//- The max value (second)
inline T& max();
inline T& max() noexcept;
//- The min/max average value
inline T centre() const;

View File

@ -79,28 +79,28 @@ inline Foam::MinMax<T>::MinMax(const UList<T>& vals)
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class T>
inline const T& Foam::MinMax<T>::min() const
inline const T& Foam::MinMax<T>::min() const noexcept
{
return this->first();
}
template<class T>
inline T& Foam::MinMax<T>::min()
inline T& Foam::MinMax<T>::min() noexcept
{
return this->first();
}
template<class T>
inline const T& Foam::MinMax<T>::max() const
inline const T& Foam::MinMax<T>::max() const noexcept
{
return this->second();
}
template<class T>
inline T& Foam::MinMax<T>::max()
inline T& Foam::MinMax<T>::max() noexcept
{
return this->second();
}

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2017-2018 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2017-2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
| Copyright (C) 2011 OpenFOAM Foundation
@ -26,6 +26,7 @@ License
\*---------------------------------------------------------------------------*/
#include "labelRange.H"
#include "MinMax.H"
#include "List.H"
#include "token.H"
#include <numeric>
@ -42,6 +43,19 @@ const Foam::labelRange Foam::labelRange::null;
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::labelRange::labelRange(const MinMax<label>& range) noexcept
:
start_(0),
size_(0)
{
if (range.min() < range.max())
{
start_ = range.min();
size_ = (range.max() - range.min()); // Hope for no overflow?
}
}
Foam::labelRange::labelRange(Istream& is)
:
start_(0),

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2017-2018 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2017-2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
| Copyright (C) 2011 OpenFOAM Foundation
@ -44,11 +44,12 @@ SourceFiles
namespace Foam
{
// Forward declarations
// Forward Declarations
class labelRange;
class Istream;
class Ostream;
template<class T> class List;
template<class T> class MinMax;
Istream& operator>>(Istream& is, labelRange& range);
Ostream& operator<<(Ostream& os, const labelRange& range);
@ -67,6 +68,7 @@ class labelRange
//- The length of the interval
label size_;
public:
// STL type definitions
@ -83,6 +85,7 @@ public:
// Static Data Members
//- Debugging
static int debug;
//- An empty range with start=0, size=0.
@ -106,14 +109,25 @@ public:
const bool adjustStart
) noexcept;
//- Construct from a min/max range, enforcing non-negative size.
//- Does not adjust the start.
// Passing an invalid min/max range results in an empty labelRange
explicit labelRange(const MinMax<label>& range) noexcept;
//- Construct from Istream.
labelRange(Istream& is);
explicit labelRange(Istream& is);
// Static Member Functions
//- An identity range with range[i] == i.
inline static labelRange identity(const label len) noexcept;
//- An identity range corresponding to (map[i] == i), or with
//- an optional start index, so that (map[i] == i+start)
// The order of parameters is as per the Foam::identity() function.
inline static labelRange identity
(
const label len,
const label start=0
) noexcept;
// Member Functions
@ -157,10 +171,16 @@ public:
//- The effective size of the range
inline label size() const noexcept;
//- The (inclusive) lower value of the range - same as start
//- The (inclusive) lower value of the range - same as start(), first()
inline label min() const noexcept;
//- The (inclusive) upper value of the range - same as last()
inline label max() const noexcept;
//- The (inclusive) lower value of the range - same as start()
inline label first() const noexcept;
//- The (inclusive) upper value of the range
//- The (inclusive) upper value of the range - same as max()
inline label last() const noexcept;
//- The value before the start of the range

View File

@ -161,9 +161,13 @@ inline const Foam::labelRange::const_iterator Foam::labelRange::cend() const
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
inline Foam::labelRange Foam::labelRange::identity(const label len) noexcept
inline Foam::labelRange Foam::labelRange::identity
(
const label len,
const label start
) noexcept
{
return labelRange(0, len);
return labelRange(start, len);
}
@ -230,6 +234,18 @@ inline Foam::label Foam::labelRange::start() const noexcept
}
inline Foam::label Foam::labelRange::min() const noexcept
{
return start_;
}
inline Foam::label Foam::labelRange::max() const noexcept
{
return start_ + size_ - 1;
}
inline Foam::label Foam::labelRange::first() const noexcept
{
return start_;

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2018 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2018-2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -25,8 +25,22 @@ License
#include "scalarRange.H"
#include "string.H"
#include "Switch.H"
#include "MinMax.H"
#include "error.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
const Foam::scalarRange Foam::scalarRange::null;
const Foam::scalarRange Foam::scalarRange::always
(
scalarRange::ALWAYS,
-Foam::GREAT,
Foam::GREAT
);
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
bool Foam::scalarRange::parse(const std::string& str, scalarRange& range)
@ -39,10 +53,23 @@ bool Foam::scalarRange::parse(const std::string& str, scalarRange& range)
{
// No colon
if (str == "none")
// Use Switch to accept none/true/false.
// Do not accept shorter ones though (f|n|t|y) or (on|off|yes|no)
// since these are not really appropriate here.
if (str.size() >= 4)
{
// "none" is an empty (inverse) range
return true;
Switch sw(str, true);
if (sw.valid())
{
if (sw)
{
range = scalarRange::always;
}
return true; // parsed ok
}
}
// "VALUE"
@ -106,6 +133,24 @@ Foam::scalarRange Foam::scalarRange::parse(const std::string& str)
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::scalarRange::scalarRange(const MinMax<label>& range) noexcept
:
min_(range.min()),
max_(range.max()),
type_(max_ < min_ ? scalarRange::NONE : scalarRange::GE_LE)
{}
Foam::scalarRange::scalarRange(const MinMax<scalar>& range) noexcept
:
min_(range.min()),
max_(range.max()),
type_(max_ < min_ ? scalarRange::NONE : scalarRange::GE_LE)
{}
// * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
Foam::Ostream& Foam::operator<<(Ostream& os, const scalarRange& range)
@ -130,6 +175,10 @@ Foam::Ostream& Foam::operator<<(Ostream& os, const scalarRange& range)
os << range.min_ << ':' << range.max_;
break;
case scalarRange::ALWAYS:
os << "true";
break;
default:
os << "none";
break;

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2018 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2018-2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -50,9 +50,11 @@ SourceFiles
namespace Foam
{
// Forward declarations
// Forward Declarations
class scalarRange;
class Ostream;
template<class T> class MinMax;
Ostream& operator<<(Ostream& os, const scalarRange& range);
@ -65,43 +67,72 @@ class scalarRange
//- Enumeration defining type of range test to use
enum testType
{
NONE = 0, //!< An empty, invalid (inverse) range. Never matches.
NONE = 0, //!< Empty or 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.
GE_LE, //!< An inclusive range.
ALWAYS //!< Placeholder range that always matches
};
// Private Member Data
//- The type of range test
enum testType type_;
//- The min value of the range
scalar min_;
//- The max value of the range
scalar max_;
//- The type of range test
enum testType type_;
//- Construct from components without sanity checking
inline scalarRange(const testType type, scalar minVal, scalar maxVal);
inline scalarRange
(
const testType type,
const scalar minVal,
const scalar maxVal
) noexcept;
public:
// STL type definitions
//- Type of values the range contains
typedef scalar value_type;
// Static Data Members
//- An empty/inverted range that never matches
static const scalarRange null;
//- A range that always matches
static const scalarRange always;
// Constructors
//- Construct an empty (inverse) range
inline scalarRange();
inline scalarRange() noexcept;
//- Construct an exact value matcher
inline explicit scalarRange(const scalar value);
inline explicit scalarRange(const scalar value) noexcept;
//- Construct a range from min-value to max-value
inline scalarRange(const scalar minVal, const scalar maxVal);
inline scalarRange(const scalar minVal, const scalar maxVal) noexcept;
//- Copy construct from a min/max range.
// Automatically decides if this is a GE_LE or NONE range
explicit scalarRange(const MinMax<label>& range) noexcept;
//- Copy construct from a min/max range.
// Automatically decides if this is a GE_LE or NONE range
explicit scalarRange(const MinMax<scalar>& range) noexcept;
// Static Constructors
@ -124,37 +155,37 @@ public:
//- Construct a greater-than-equals bound
inline static scalarRange ge(const scalar minVal);
inline static scalarRange ge(const scalar minVal) noexcept;
//- Construct a greater-than bound
inline static scalarRange gt(const scalar minVal);
inline static scalarRange gt(const scalar minVal) noexcept;
//- Construct a less-than-equals bound
inline static scalarRange le(const scalar maxVal);
inline static scalarRange le(const scalar maxVal) noexcept;
//- Construct a less-than bound
inline static scalarRange lt(const scalar maxVal);
inline static scalarRange lt(const scalar maxVal) noexcept;
// Member Functions
//- Reset to an empty (inverse) range.
inline void clear();
inline void clear() noexcept;
//- True if bounds are empty (eg, inverted)
inline bool empty() const;
//- True if range is empty (eg, inverted)
inline bool empty() const noexcept;
//- True if bounds are non-empty.
inline bool valid() const;
//- True if range is non-empty.
inline bool valid() const noexcept;
//- True if the bounds represents a single value.
inline bool single() const;
//- True if the range bounds represent a single value.
inline bool single() const noexcept;
//- The min value of the range.
inline scalar min() const;
inline scalar min() const noexcept;
//- The max value of the range.
inline scalar max() const;
inline scalar max() const noexcept;
//- A representative (average) value for the range.
// For GE, LE bounds it is the min/max value, respectively.
@ -169,13 +200,13 @@ public:
//- Identical to match(), for use as a predicate.
inline bool operator()(const scalar& value) const;
inline bool operator==(const scalarRange& rhs) const;
inline bool operator!=(const scalarRange& rhs) const;
inline bool operator==(const scalarRange& rhs) const noexcept;
inline bool operator!=(const scalarRange& rhs) const noexcept;
// IOstream Operators
//- Print information about the bounds.
//- Print information about the range.
friend Ostream& operator<<(Ostream& os, const scalarRange& range);
};

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2018 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2018-2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -30,29 +30,33 @@ inline Foam::scalarRange::scalarRange
const scalarRange::testType type,
const scalar minVal,
const scalar maxVal
)
) noexcept
:
type_(type),
min_(minVal),
max_(maxVal)
max_(maxVal),
type_(type)
{}
inline Foam::scalarRange::scalarRange()
inline Foam::scalarRange::scalarRange() noexcept
:
scalarRange(NONE, Foam::VGREAT, -Foam::VGREAT)
scalarRange(scalarRange::NONE, Foam::GREAT, -Foam::GREAT)
{}
inline Foam::scalarRange::scalarRange(const scalar value)
inline Foam::scalarRange::scalarRange(const scalar value) noexcept
:
scalarRange(EQ, value, value)
scalarRange(scalarRange::EQ, value, value)
{}
inline Foam::scalarRange::scalarRange(const scalar minVal, const scalar maxVal)
inline Foam::scalarRange::scalarRange
(
const scalar minVal,
const scalar maxVal
) noexcept
:
scalarRange(GE_LE, minVal, maxVal)
scalarRange(scalarRange::GE_LE, minVal, maxVal)
{
if (minVal > maxVal)
{
@ -65,24 +69,24 @@ inline Foam::scalarRange::scalarRange(const scalar minVal, const scalar maxVal)
}
inline Foam::scalarRange Foam::scalarRange::ge(const scalar minVal)
inline Foam::scalarRange Foam::scalarRange::ge(const scalar minVal) noexcept
{
return scalarRange(GE, minVal, Foam::VGREAT);
}
inline Foam::scalarRange Foam::scalarRange::gt(const scalar minVal)
inline Foam::scalarRange Foam::scalarRange::gt(const scalar minVal) noexcept
{
return scalarRange(GT, minVal, Foam::VGREAT);
}
inline Foam::scalarRange Foam::scalarRange::le(const scalar maxVal)
inline Foam::scalarRange Foam::scalarRange::le(const scalar maxVal) noexcept
{
return scalarRange(LE, -Foam::VGREAT, maxVal);
}
inline Foam::scalarRange Foam::scalarRange::lt(const scalar maxVal)
inline Foam::scalarRange Foam::scalarRange::lt(const scalar maxVal) noexcept
{
return scalarRange(LT, -Foam::VGREAT, maxVal);
}
@ -90,39 +94,39 @@ inline Foam::scalarRange Foam::scalarRange::lt(const scalar maxVal)
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
inline void Foam::scalarRange::clear()
inline void Foam::scalarRange::clear() noexcept
{
min_ = Foam::GREAT;
max_ = -Foam::GREAT;
type_ = scalarRange::NONE;
min_ = Foam::VGREAT;
max_ = -Foam::VGREAT;
}
inline bool Foam::scalarRange::empty() const
inline bool Foam::scalarRange::empty() const noexcept
{
return type_ == NONE;
}
inline bool Foam::scalarRange::valid() const
inline bool Foam::scalarRange::valid() const noexcept
{
return type_;
}
inline bool Foam::scalarRange::single() const
inline bool Foam::scalarRange::single() const noexcept
{
return type_ == EQ;
return type_ == scalarRange::EQ;
}
inline Foam::scalar Foam::scalarRange::min() const
inline Foam::scalar Foam::scalarRange::min() const noexcept
{
return min_;
}
inline Foam::scalar Foam::scalarRange::max() const
inline Foam::scalar Foam::scalarRange::max() const noexcept
{
return max_;
}
@ -132,9 +136,7 @@ inline Foam::scalar Foam::scalarRange::value() const
{
switch (type_)
{
case EQ:
return min_; // For equals, min and max are identical
case EQ: // For equals, min and max are identical
case GE:
case GT:
return min_;
@ -144,9 +146,10 @@ inline Foam::scalar Foam::scalarRange::value() const
return max_;
case GE_LE:
return 0.5*(min_ + max_);
// Multiply before adding to avoid possible overflow
return (0.5 * min_) + (0.5 * max_);
default:
default: // NONE or ALWAYS. Zero is reasonable dummy value.
return 0;
}
}
@ -162,6 +165,7 @@ inline bool Foam::scalarRange::match(const scalar& value) const
case LE: return (value <= max_);
case LT: return (value < max_);
case GE_LE: return (value >= min_ && value <= max_);
case ALWAYS: return true;
default: return false;
}
}
@ -175,13 +179,19 @@ inline bool Foam::scalarRange::operator()(const scalar& value) const
}
inline bool Foam::scalarRange::operator==(const scalarRange& rhs) const
inline bool Foam::scalarRange::operator==
(
const scalarRange& rhs
) const noexcept
{
return (type_ == rhs.type_ && min_ == rhs.min_ && max_ == rhs.max_);
}
inline bool Foam::scalarRange::operator!=(const scalarRange& rhs) const
inline bool Foam::scalarRange::operator!=
(
const scalarRange& rhs
) const noexcept
{
return !(operator==(rhs));
}