diff --git a/applications/test/Tuple2/Test-Tuple2.C b/applications/test/Tuple2/Test-Tuple2.C index f505554c79b3b5968cd2b2cdff67156536bc213f..31b6ab008dc4fe87fff14cf053f61ed493895698 100644 --- a/applications/test/Tuple2/Test-Tuple2.C +++ b/applications/test/Tuple2/Test-Tuple2.C @@ -32,9 +32,39 @@ Description #include "label.H" #include "scalar.H" #include "List.H" +#include "ops.H" +#include <functional> using namespace Foam; +// Test for special comparison operation using compareOp +// Normal sort on label, reverse sort on scalar +struct special1 +{ + typedef Tuple2<label, scalar> type; + + bool operator()(const type& a, const type& b) const + { + int val = compareOp<label>()(a.first(), b.first()); + return (val == 0) ? (b.second() < a.second()) : (val < 0); + } +}; + + +// Test for special comparison operation using compareOp +// Normal sort on scalar, reverse sort on label +struct special2 +{ + typedef Tuple2<label, scalar> type; + + bool operator()(const type& a, const type& b) const + { + scalar val = compareOp<scalar>()(a.second(), b.second()); + return (val == 0) ? (b.first() < a.first()) : (val < 0); + } +}; + + // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // Main program: @@ -46,19 +76,39 @@ int main() Info<< "tuple: " << t2 << " " - << t2.first() << " " << t2.second() << endl; + << t2.first() << " " << t2.second() << nl; - List<indexedScalar> list1(10); - forAll(list1, i) + // As list. Generated so that we have duplicate indices + List<indexedScalar> list1(3*4); + for (label i = 0; i < 4; ++i) { - list1[i] = indexedScalar(-i, i*i); + const label j = (i+1); + const label idx = ((i % 2) ? -1 : 1) * (j); + + list1[i] = indexedScalar(idx, (j*j)); + list1[i+4] = indexedScalar(idx, 2*j); // duplicate index + list1[i+8] = indexedScalar(idx+12, 2*j); // duplicate value } - sort(list1); + Info<< "Unsorted tuples:" << nl << list1 << nl; + + Foam::sort(list1, std::less<indexedScalar>()); + + Info<< "sorted tuples:" << nl << list1 << nl; + + Foam::sort(list1, std::greater<indexedScalar>()); + + Info<< "reverse sorted tuples:" << nl << list1 << nl; + + Foam::sort(list1, special1()); + + Info<< "special sorted tuples - sort on index, reverse on value:" + << nl << list1 << nl; + + Foam::sort(list1, special2()); - Info<< "tuples:" << nl - << list1 - << endl; + Info<< "special sorted tuples - sort on value, reverse on index:" + << nl << list1 << nl; Info<< "End\n" << endl; diff --git a/src/OpenFOAM/primitives/Scalar/Scalar.H b/src/OpenFOAM/primitives/Scalar/Scalar.H index ffb97436b8d78694c5ce62c9a2b2ec42a8c2ece1..c21d99d543102942ac65a17866dd5268f2070c37 100644 --- a/src/OpenFOAM/primitives/Scalar/Scalar.H +++ b/src/OpenFOAM/primitives/Scalar/Scalar.H @@ -405,6 +405,28 @@ inline Scalar stabilise(const Scalar s, const Scalar tol) // Specializations +// Default definition in ops.H +template<class T> struct compareOp; + +//- Compare scalar values +template<> +struct compareOp<Scalar> +{ + const Scalar tolerance; + + //- Construct with specified tolerance (non-negative value) + compareOp(Scalar tol = ScalarVSMALL) + : + tolerance(tol) + {} + + Scalar operator()(const Scalar& a, const Scalar& b) const + { + return (mag(a - b) <= tolerance) ? 0 : (a - b); + } +}; + + // Default definition in ops.H template<class T> struct equalOp; diff --git a/src/OpenFOAM/primitives/ops/ops.H b/src/OpenFOAM/primitives/ops/ops.H index c179d716b95c5a10e93df5934f3386e791e7e3dc..fd069ad4b066b62ca0b560d6184595635b867d22 100644 --- a/src/OpenFOAM/primitives/ops/ops.H +++ b/src/OpenFOAM/primitives/ops/ops.H @@ -216,6 +216,21 @@ WeightedOp(multiply, (weight*y)) // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +//- Three-way comparison operation of two parameters, +// similar to the \c <=> operator in C++20. +// +// \return a negative value for less, a positive value for greater, +// and zero for equal value. +template<class T> +struct compareOp +{ + int operator()(const T& a, const T& b) const WARNRETURN + { + return (a < b) ? -1 : (b < a) ? 1 : 0; + } +}; + + //- General get operation to extract the 'name' from an object as a word. // The default implementation uses the 'name()' method commonly used within // OpenFOAM.