ENH: update MinMax to accept multiple values for add()

- now also provide its own member data (previously inherited from
  Tuple2) to provide better isolation from future changes
This commit is contained in:
Mark Olesen 2025-02-20 13:54:40 +01:00
parent 14b2302b38
commit 0aecb25024
7 changed files with 147 additions and 111 deletions

View File

@ -170,8 +170,19 @@ int main(int argc, char *argv[])
values1 *= (Pstream::myProcNo()+1);
Pout<<"min-max of " << flatOutput(values1) << " = "
<< minMax(values1) << endl;
{
auto limits = minMax(values1);
Pout<<"min-max of " << flatOutput(values1) << " = "
<< limits << endl;
// add in some more values
limits.add(-100, 10, 1000, 500, 800);
limits.add(-120, 1200);
Pout<<"with more values: " << limits << endl;
}
// Construct from values
MinMax<scalar> minmax1(values1);

View File

@ -1,3 +1,3 @@
Test-minMax2.C
Test-minMax2.cxx
EXE = $(FOAM_USER_APPBIN)/Test-minMax2

View File

@ -110,9 +110,15 @@ typedef MinMax<scalar> scalarMinMax; //!< A scalar min/max range
template<class T>
class MinMax
:
public Tuple2<T,T>
{
// Private Data
//- Min value
T min_;
//- Max value
T max_;
public:
// Typedefs
@ -126,23 +132,26 @@ public:
// Constructors
//- Construct inverted range
//- Default construct: an inverted range
inline MinMax();
//- Copy construct from components
//- Construct from min/max limits
inline MinMax(const T& minVal, const T& maxVal);
//- Copy construct from components
//- Implicit construct from min/max limits
inline MinMax(const std::pair<T,T>& range);
//- Copy construct from components
//- Implicit construct from min/max limits
inline MinMax(const Pair<T>& range);
//- Implicit construct from min/max limits
inline MinMax(const Tuple2<T,T>& range);
//- Construct with a single zero value
inline explicit MinMax(const Foam::zero);
inline explicit MinMax(Foam::zero);
//- Implicit construct from zero_one as 0-1 range (pTraits zero, one)
inline MinMax(const Foam::zero_one);
inline MinMax(Foam::zero_one);
//- Construct with a single initial value
inline explicit MinMax(const T& val);
@ -167,25 +176,25 @@ public:
// Access
//- The min value (first)
inline const T& min() const noexcept;
//- The min value
const T& min() const noexcept { return min_; }
//- The min value (first)
inline T& min() noexcept;
//- The min value
T& min() noexcept { return min_; }
//- The max value (second)
inline const T& max() const noexcept;
//- The max value
const T& max() const noexcept { return max_; }
//- The max value (second)
inline T& max() noexcept;
//- The max value
T& max() noexcept { return max_; }
//- The min/max average value
inline T centre() const;
//- The min to max span. Zero if the range is invalid.
//- The min to max span. Zero for invalid range.
inline T span() const;
//- The magnitude of the min to max span. Zero if the range is invalid.
//- The magnitude of the min to max span. Zero for invalid range.
inline scalar mag() const;
//- Range is empty if it is inverted
@ -194,9 +203,6 @@ public:
//- Range is non-inverted
inline bool good() const;
//- Range is non-inverted
bool valid() const { return good(); }
//- Reset to an inverted (invalid) range
inline void reset();
@ -244,6 +250,11 @@ public:
//- Include the values into the range
inline MinMax<T>& add(const UList<T>& vals);
//- Include two or more values into the range.
// All values must be similar types
template<class... Args>
inline MinMax<T>& add(const T& val0, const T& val1, Args&&... values);
// Member Operators
@ -264,19 +275,19 @@ public:
inline MinMax<T>& operator+=(const UList<T>& vals);
//- Multiply range by scalar factor
inline MinMax<T>& operator*=(const scalar& s);
inline MinMax<T>& operator*=(scalar s);
//- Divide range by scalar factor
inline MinMax<T>& operator/=(const scalar& s);
inline MinMax<T>& operator/=(scalar s);
// Housekeeping
//- Range is non-inverted. Same as good (2022-10)
bool valid() const { return good(); }
//- Old method name. Same as clamp (2023-01)
T clip(const T& val) const { return this->clamp(val); }
//- Old method (2023-01)
void inplaceClip(T& val) const { val = this->clamp(val); }
};
@ -299,6 +310,30 @@ word name(const MinMax<T>& range)
return '(' + Foam::name(range.min()) + ',' + Foam::name(range.max()) + ')';
}
// * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * //
//- Read min/max range as (min max) tuple from Istream
template<class T>
inline Istream& operator>>(Istream& is, MinMax<T>& range)
{
is.readBegin("min.max");
is >> range.min() >> range.max();
is.readEnd("min.max");
is.check(FUNCTION_NAME);
return is;
}
//- Write min/max range as (min max) tuple to Ostream
template<class T>
inline Ostream& operator<<(Ostream& os, const MinMax<T>& range)
{
os << token::BEGIN_LIST
<< range.min() << token::SPACE << range.max()
<< token::END_LIST;
return os;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2019-2023 OpenCFD Ltd.
Copyright (C) 2019-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -53,49 +53,65 @@ inline Foam::MinMax<T> Foam::MinMax<T>::zero_one()
template<class T>
inline Foam::MinMax<T>::MinMax()
:
Tuple2<T,T>(pTraits<T>::max, pTraits<T>::min)
// An inverted range
min_(pTraits<T>::max),
max_(pTraits<T>::min)
{}
template<class T>
inline Foam::MinMax<T>::MinMax(const T& minVal, const T& maxVal)
:
Tuple2<T,T>(minVal, maxVal)
min_(minVal),
max_(maxVal)
{}
template<class T>
inline Foam::MinMax<T>::MinMax(const std::pair<T,T>& range)
:
Tuple2<T,T>(range.first, range.second)
min_(range.first),
max_(range.second)
{}
template<class T>
inline Foam::MinMax<T>::MinMax(const Pair<T>& range)
:
Tuple2<T,T>(range.first(), range.second())
min_(range.first()),
max_(range.second())
{}
template<class T>
inline Foam::MinMax<T>::MinMax(const Foam::zero)
inline Foam::MinMax<T>::MinMax(const Tuple2<T,T>& range)
:
Tuple2<T,T>(pTraits<T>::zero, pTraits<T>::zero)
min_(range.first()),
max_(range.second())
{}
template<class T>
inline Foam::MinMax<T>::MinMax(const Foam::zero_one)
inline Foam::MinMax<T>::MinMax(Foam::zero)
:
Tuple2<T,T>(pTraits<T>::zero, pTraits<T>::one)
min_(pTraits<T>::zero),
max_(pTraits<T>::zero)
{}
template<class T>
inline Foam::MinMax<T>::MinMax(Foam::zero_one)
:
min_(pTraits<T>::zero),
max_(pTraits<T>::one)
{}
template<class T>
inline Foam::MinMax<T>::MinMax(const T& val)
:
Tuple2<T,T>(val, val)
min_(val),
max_(val)
{}
@ -110,34 +126,6 @@ inline Foam::MinMax<T>::MinMax(const UList<T>& vals)
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class T>
inline const T& Foam::MinMax<T>::min() const noexcept
{
return this->first();
}
template<class T>
inline T& Foam::MinMax<T>::min() noexcept
{
return this->first();
}
template<class T>
inline const T& Foam::MinMax<T>::max() const noexcept
{
return this->second();
}
template<class T>
inline T& Foam::MinMax<T>::max() noexcept
{
return this->second();
}
template<class T>
inline T Foam::MinMax<T>::centre() const
{
@ -156,7 +144,7 @@ inline T Foam::MinMax<T>::span() const
template<class T>
inline Foam::scalar Foam::MinMax<T>::mag() const
{
return ::Foam::mag(span());
return (empty() ? scalar(0) : ::Foam::mag(max() - min()));
}
@ -171,31 +159,32 @@ inline bool Foam::MinMax<T>::empty() const
template<class T>
inline bool Foam::MinMax<T>::good() const
{
return !empty();
return !(max() < min());
}
template<class T>
inline void Foam::MinMax<T>::reset()
{
min() = pTraits<T>::max;
max() = pTraits<T>::min;
// An inverted range
min_ = pTraits<T>::max;
max_ = pTraits<T>::min;
}
template<class T>
inline void Foam::MinMax<T>::reset(const T& val)
{
min() = val;
max() = val;
min_ = val;
max_ = val;
}
template<class T>
inline void Foam::MinMax<T>::reset(const T& minVal, const T& maxVal)
{
min() = minVal;
max() = maxVal;
min_ = minVal;
max_ = maxVal;
}
@ -246,6 +235,7 @@ inline T Foam::MinMax<T>::clamp(const T& val) const
{
if (good())
{
// Uses Foam::min/Foam::max for component-wise handling
return Foam::min(Foam::max(val, min()), max());
}
@ -256,6 +246,7 @@ inline T Foam::MinMax<T>::clamp(const T& val) const
template<class T>
inline Foam::MinMax<T>& Foam::MinMax<T>::add(const MinMax& other)
{
// Uses Foam::min/Foam::max for component-wise handling
min() = Foam::min(min(), other.min());
max() = Foam::max(max(), other.max());
return *this;
@ -265,6 +256,7 @@ inline Foam::MinMax<T>& Foam::MinMax<T>::add(const MinMax& other)
template<class T>
inline Foam::MinMax<T>& Foam::MinMax<T>::add(const T& val)
{
// Uses Foam::min/Foam::max for component-wise handling
min() = Foam::min(min(), val);
max() = Foam::max(max(), val);
return *this;
@ -282,6 +274,25 @@ inline Foam::MinMax<T>& Foam::MinMax<T>::add(const UList<T>& vals)
}
template<class T>
template<class... Args>
inline Foam::MinMax<T>& Foam::MinMax<T>::add
(
const T& val0,
const T& val1,
Args&&... values
)
{
add(val0);
add(val1);
// Add multiple values via fold expression
((*this += std::forward<Args>(values)), ...);
return *this;
}
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
template<class T>
@ -325,6 +336,7 @@ inline bool Foam::MinMax<T>::operator()(const T& val) const
template<class T>
inline Foam::MinMax<T>& Foam::MinMax<T>::operator&=(const MinMax<T>& b)
{
// Uses Foam::min/Foam::max for component-wise handling
min() = ::Foam::max(min(), b.min());
max() = ::Foam::min(max(), b.max());
@ -354,7 +366,7 @@ inline Foam::MinMax<T>& Foam::MinMax<T>::operator+=(const UList<T>& vals)
template<class T>
inline Foam::MinMax<T>& Foam::MinMax<T>::operator*=(const scalar& s)
inline Foam::MinMax<T>& Foam::MinMax<T>::operator*=(scalar s)
{
min() *= s;
max() *= s;
@ -363,7 +375,7 @@ inline Foam::MinMax<T>& Foam::MinMax<T>::operator*=(const scalar& s)
template<class T>
inline Foam::MinMax<T>& Foam::MinMax<T>::operator/=(const scalar& s)
inline Foam::MinMax<T>& Foam::MinMax<T>::operator/=(scalar s)
{
min() /= s;
max() /= s;

View File

@ -44,7 +44,7 @@ Description
namespace Foam
{
// Global Functions
// * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * //
//- The mag() function for min/max range
template<class T>
@ -156,7 +156,7 @@ inline scalarMinMax minMaxMag(const UList<T>& vals)
scalarMinMax result;
for (const T& val : vals)
{
result += Foam::mag(val);
result.add(Foam::mag(val));
}
return result;
@ -174,38 +174,20 @@ inline scalarMinMax minMaxMag(const MinMax<T>& range)
}
//- Combine the magitude of two values to create a min/max range.
//- Order is unimportant.
template<class T>
inline scalarMinMax minMaxMag(const T& x, const T& y)
//- Combine the magitude of two values (similar or dissimilar types)
//- to create a min/max range. Order is unimportant.
template<class T1, class T2>
inline scalarMinMax minMaxMag(const T1& x, const T2& y)
{
return minMaxMag(x).add(Foam::mag(y));
}
//- Scalar combine two MinMax ranges of same type
template<class T>
inline scalarMinMax minMaxMag(const MinMax<T>& x, const MinMax<T>& y)
{
return
(
minMaxMag(x)
.add(Foam::mag(y.min()))
.add(Foam::mag(y.max()))
);
}
//- Scalar combine two MinMax ranges of dissimilar types
//- Scalar combine two MinMax ranges (same or dissimilar types)
template<class T1, class T2>
inline scalarMinMax minMaxMag(const MinMax<T1>& x, const MinMax<T2>& y)
{
return
(
minMaxMag(x)
.add(Foam::mag(y.min()))
.add(Foam::mag(y.max()))
);
return minMaxMag(x).add(Foam::mag(y.min()), Foam::mag(y.max()));
}
@ -309,7 +291,7 @@ inline MinMax<T> operator+(const MinMax<T>& x, const MinMax<T>& y)
//- Multiply range by scalar factor
template<class T>
inline MinMax<T> operator*(const MinMax<T>& x, const scalar& s)
inline MinMax<T> operator*(const MinMax<T>& x, scalar s)
{
return MinMax<T>(x.min()*s, x.max()*s);
}
@ -317,7 +299,7 @@ inline MinMax<T> operator*(const MinMax<T>& x, const scalar& s)
//- Divide range by scalar factor
template<class T>
inline MinMax<T> operator/(const MinMax<T>& x, const scalar& s)
inline MinMax<T> operator/(const MinMax<T>& x, scalar s)
{
return MinMax<T>(x.min()/s, x.max()/s);
}

View File

@ -58,9 +58,7 @@ void Foam::binModels::uniformBin::initialise()
);
MinMax<vector> limits(pts);
geomLimits.add(limits.min());
geomLimits.add(limits.max());
geomLimits.add(limits.min(), limits.max());
}
for (const label zonei : cellZoneIDs_)
@ -72,9 +70,7 @@ void Foam::binModels::uniformBin::initialise()
);
MinMax<vector> limits(pts);
geomLimits.add(limits.min());
geomLimits.add(limits.max());
geomLimits.add(limits.min(), limits.max());
}
// Globally consistent