diff --git a/applications/test/Tuple2/Test-Tuple2.C b/applications/test/Tuple2/Test-Tuple2.C
index 27b0fbf6d0b117d19e2a74f6c84c7dbfe28d6415..4f02359f032684c0c611a793c962e31d5c3daf78 100644
--- a/applications/test/Tuple2/Test-Tuple2.C
+++ b/applications/test/Tuple2/Test-Tuple2.C
@@ -39,6 +39,7 @@ Description
 #include "List.H"
 #include "ListOps.H"
 #include "ops.H"
+#include "PstreamCombineReduceOps.H"
 #include <functional>
 
 using namespace Foam;
@@ -121,6 +122,43 @@ int main()
 
     Info<< "Unsorted tuples:" << nl << list1 << nl;
 
+    // Test minFirst, maxFirst functors
+    {
+        indexedScalar minIndexed(labelMax, Zero);
+        indexedScalar maxIndexed(labelMin, Zero);
+
+        for (const auto& item : list1)
+        {
+            minFirstEqOp<label>()(minIndexed, item);
+            maxFirstEqOp<label>()(maxIndexed, item);
+        }
+
+        Foam::combineReduce(minIndexed, minFirstEqOp<label>());
+        Foam::combineReduce(maxIndexed, maxFirstEqOp<label>());
+
+        Info<< "Min indexed: " << minIndexed << nl
+            << "Max indexed: " << maxIndexed << nl;
+    }
+
+    // Test minFirst, maxFirst functors
+    {
+        indexedScalar minIndexed(labelMax, Zero);
+        indexedScalar maxIndexed(labelMin, Zero);
+
+        for (const auto& item : list1)
+        {
+            minIndexed = minFirstOp<label>()(minIndexed, item);
+            maxIndexed = maxFirstOp<label>()(maxIndexed, item);
+        }
+
+        Foam::combineReduce(minIndexed, minFirstEqOp<label>());
+        Foam::combineReduce(maxIndexed, maxFirstEqOp<label>());
+
+        Info<< "Min indexed: " << minIndexed << nl
+            << "Max indexed: " << maxIndexed << nl;
+    }
+
+
     Foam::sort(list1, std::less<indexedScalar>());
 
     Info<< "sorted tuples:" << nl << list1 << nl;
diff --git a/src/OpenFOAM/primitives/Tuple2/Tuple2.H b/src/OpenFOAM/primitives/Tuple2/Tuple2.H
index c8e4342af7fc757956c30e785a2787505585fd70..35875938080f86a5f66a3fdb524afc7cbb7a3722 100644
--- a/src/OpenFOAM/primitives/Tuple2/Tuple2.H
+++ b/src/OpenFOAM/primitives/Tuple2/Tuple2.H
@@ -42,6 +42,7 @@ See also
 
 #include "Istream.H"
 #include "Ostream.H"
+#include "Pair.H"
 #include <utility>
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@@ -140,6 +141,8 @@ public:
 };
 
 
+// * * * * * * * * * * * * * * Global Functions  * * * * * * * * * * * * * * //
+
 //- Return reverse of a Tuple2
 template<class T1, class T2>
 inline Tuple2<T2, T1> reverse(const Tuple2<T1,T2>& t)
@@ -148,6 +151,8 @@ inline Tuple2<T2, T1> reverse(const Tuple2<T1,T2>& t)
 }
 
 
+// * * * * * * * * * * * * * * Global Operators  * * * * * * * * * * * * * * //
+
 template<class T1, class T2>
 inline bool operator==(const Tuple2<T1,T2>& a, const Tuple2<T1,T2>& b)
 {
@@ -173,7 +178,6 @@ inline bool operator<(const Tuple2<T1,T2>& a, const Tuple2<T1,T2>& b)
 }
 
 
-
 template<class T1, class T2>
 inline bool operator<=(const Tuple2<T1,T2>& a, const Tuple2<T1,T2>& b)
 {
@@ -195,7 +199,83 @@ inline bool operator>=(const Tuple2<T1,T2>& a, const Tuple2<T1,T2>& b)
 }
 
 
-// IOstream Operators
+// * * * * * * * * * * * * * * Global Functions  * * * * * * * * * * * * * * //
+
+// Comparing first only
+
+//- Compare tuple-like containers
+//  \return reference to the container with the smaller value of first
+template<class T1>
+struct minFirstOp
+{
+    const Pair<T1>& operator()(const Pair<T1>& a, const Pair<T1>& b) const
+    {
+        return (b.first() < a.first()) ? b : a;
+    }
+
+    template<class T2>
+    const Tuple2<T1,T2>&
+    operator()(const Tuple2<T1,T2>& a, const Tuple2<T1,T2>& b) const
+    {
+        return (b.first() < a.first()) ? b : a;
+    }
+};
+
+
+//- Assign tuple-like container to use the one with the smaller value of first
+template<class T1>
+struct minFirstEqOp
+{
+    void operator()(Pair<T1>& x, const Pair<T1>& y) const
+    {
+        if (y.first() < x.first()) x = y;
+    }
+
+    template<class T2>
+    void operator()(Tuple2<T1,T2>& x, const Tuple2<T1,T2>& y) const
+    {
+        if (y.first() < x.first()) x = y;
+    }
+};
+
+
+//- Compare tuple-like containers
+//  \return reference to the container with the larger value of first
+template<class T1>
+struct maxFirstOp
+{
+    const Pair<T1>& operator()(const Pair<T1>& a, const Pair<T1>& b) const
+    {
+        return (a.first() < b.first()) ? b : a;
+    }
+
+    template<class T2>
+    const Tuple2<T1,T2>&
+    operator()(const Tuple2<T1,T2>& a, const Tuple2<T1,T2>& b) const
+    {
+        return (a.first() < b.first()) ? b : a;
+    }
+};
+
+
+//- Assign tuple-like container to use the one with the larger value of first
+template<class T1>
+struct maxFirstEqOp
+{
+    void operator()(Pair<T1>& x, const Pair<T1>& y) const
+    {
+        if (x.first() < y.first()) x = y;
+    }
+
+    template<class T2>
+    void operator()(Tuple2<T1,T2>& x, const Tuple2<T1,T2>& y) const
+    {
+        if (x.first() < y.first()) x = y;
+    }
+};
+
+
+// * * * * * * * * * * * * * * * IOstream Operators  * * * * * * * * * * * * //
 
 //- Read Tuple2 from Istream, discarding contents of existing Tuple2.
 template<class T1, class T2>