From 360c8116e41b3535bb3349e4c74d758c6202c7c6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Oberhuber?= <oberhuber.tomas@gmail.com>
Date: Tue, 2 Jul 2019 21:58:43 +0200
Subject: [PATCH] Implementing comparison of static vector expressions and
 numbers.

---
 src/TNL/Containers/Expressions/Comparison.h   | 197 +++++++---
 .../Expressions/StaticExpressionTemplates.h   | 335 ++++++++++++++++--
 src/TNL/Containers/StaticVectorExpressions.h  |  36 +-
 src/UnitTests/Containers/StaticVectorTest.cpp |  53 +++
 4 files changed, 527 insertions(+), 94 deletions(-)

diff --git a/src/TNL/Containers/Expressions/Comparison.h b/src/TNL/Containers/Expressions/Comparison.h
index a39c82a4ae..6719867ebd 100644
--- a/src/TNL/Containers/Expressions/Comparison.h
+++ b/src/TNL/Containers/Expressions/Comparison.h
@@ -18,64 +18,175 @@ namespace TNL {
       namespace Expressions {
 
 template< typename T1,
-          typename T2 >
-__cuda_callable__
-bool StaticComparisonEQ( const T1& a, const T2& b )
+          typename T2,
+          ExpressionVariableType T1Type = ExpressionVariableTypeGetter< T1 >::value,
+          ExpressionVariableType T2Type = ExpressionVariableTypeGetter< T2 >::value >
+struct StaticComparison
 {
-   TNL_ASSERT_EQ( a.getSize(), b.getSize(), "Sizes of expressions to be compared do not fit." );
-   for( int i = 0; i < a.getSize(); i++ )
-      if( a[ i ] != b[ i ] )
-         return false;
-   return true;
-}
+};
 
+/////
+// Static comparison of vector expressions
 template< typename T1,
           typename T2 >
-__cuda_callable__
-bool StaticComparisonNE( const T1& a, const T2& b )
+struct StaticComparison< T1, T2, VectorVariable, VectorVariable >
 {
-   return ! StaticComparisonEQ( a, b );
-}
 
-template< typename T1,
-          typename T2 >
-__cuda_callable__
-bool StaticComparisonGT( const T1& a, const T2& b )
-{
-   TNL_ASSERT_EQ( a.getSize(), b.getSize(), "Sizes of expressions to be compared do not fit." );
-   for( int i = 0; i < a.getSize(); i++ )
-      if( a[ i ] <= b[ i ] )
-         return false;
-   return true;
-}
+   __cuda_callable__
+   static bool EQ( const T1& a, const T2& b )
+   {
+      static_assert( a.getSize() == b.getSize(), "Sizes of expressions to be compared do not fit." );
+      for( int i = 0; i < a.getSize(); i++ )
+         if( a[ i ] != b[ i ] )
+            return false;
+      return true;
+   }
 
-template< typename T1,
-          typename T2 >
-__cuda_callable__
-bool StaticComparisonLE( const T1& a, const T2& b )
-{
-   return ! StaticComparisonGT( a, b );
-}
+   __cuda_callable__
+   static bool NE( const T1& a, const T2& b )
+   {
+      return ! EQ( a, b );
+   }
+
+   __cuda_callable__
+   static bool GT( const T1& a, const T2& b )
+   {
+      static_assert( a.getSize() == b.getSize(), "Sizes of expressions to be compared do not fit." );
+      for( int i = 0; i < a.getSize(); i++ )
+         if( a[ i ] <= b[ i ] )
+            return false;
+      return true;
+   }
+
+   __cuda_callable__
+   static bool LE( const T1& a, const T2& b )
+   {
+      return ! GT( a, b );
+   }
+
+   __cuda_callable__
+   static bool LT( const T1& a, const T2& b )
+   {
+      static_assert( a.getSize() == b.getSize(), "Sizes of expressions to be compared do not fit." );
+      for( int i = 0; i < a.getSize(); i++ )
+         if( a[ i ] >= b[ i ] )
+            return false;
+      return true;
+   }
+
+   __cuda_callable__
+   static bool GE( const T1& a, const T2& b )
+   {
+      return ! LT( a, b );
+   }
+};
 
+/////
+// Static comparison of number and vector expressions
 template< typename T1,
           typename T2 >
-__cuda_callable__
-bool StaticComparisonLT( const T1& a, const T2& b )
+struct StaticComparison< T1, T2, ArithmeticVariable, VectorVariable >
 {
-   TNL_ASSERT_EQ( a.getSize(), b.getSize(), "Sizes of expressions to be compared do not fit." );
-   for( int i = 0; i < a.getSize(); i++ )
-      if( a[ i ] >= b[ i ] )
-         return false;
-   return true;
-}
 
+   __cuda_callable__
+   static bool EQ( const T1& a, const T2& b )
+   {
+      for( int i = 0; i < a.getSize(); i++ )
+         if( a != b[ i ] )
+            return false;
+      return true;
+   }
+
+   __cuda_callable__
+   static bool NE( const T1& a, const T2& b )
+   {
+      return ! EQ( a, b );
+   }
+
+   __cuda_callable__
+   static bool GT( const T1& a, const T2& b )
+   {
+      for( int i = 0; i < a.getSize(); i++ )
+         if( a <= b[ i ] )
+            return false;
+      return true;
+   }
+
+   __cuda_callable__
+   static bool LE( const T1& a, const T2& b )
+   {
+      return ! GT( a, b );
+   }
+
+   __cuda_callable__
+   static bool LT( const T1& a, const T2& b )
+   {
+      for( int i = 0; i < a.getSize(); i++ )
+         if( a >= b[ i ] )
+            return false;
+      return true;
+   }
+
+   __cuda_callable__
+   static bool GE( const T1& a, const T2& b )
+   {
+      return ! LT( a, b );
+   }
+};
+
+/////
+// Static comparison of vector expressions and number
 template< typename T1,
           typename T2 >
-__cuda_callable__
-bool StaticComparisonGE( const T1& a, const T2& b )
+struct StaticComparison< T1, T2, VectorVariable, ArithmeticVariable >
 {
-   return ! StaticComparisonLT( a, b );
-}
+
+   __cuda_callable__
+   static bool EQ( const T1& a, const T2& b )
+   {
+      for( int i = 0; i < a.getSize(); i++ )
+         if( a[ i ] != b )
+            return false;
+      return true;
+   }
+
+   __cuda_callable__
+   static bool NE( const T1& a, const T2& b )
+   {
+      return ! EQ( a, b );
+   }
+
+   __cuda_callable__
+   static bool GT( const T1& a, const T2& b )
+   {
+      for( int i = 0; i < a.getSize(); i++ )
+         if( a[ i ] <= b )
+            return false;
+      return true;
+   }
+
+   __cuda_callable__
+   static bool LE( const T1& a, const T2& b )
+   {
+      return ! GT( a, b );
+   }
+
+   __cuda_callable__
+   static bool LT( const T1& a, const T2& b )
+   {
+      for( int i = 0; i < a.getSize(); i++ )
+         if( a[ i ] >= b )
+            return false;
+      return true;
+   }
+
+   __cuda_callable__
+   static bool GE( const T1& a, const T2& b )
+   {
+      return ! LT( a, b );
+   }
+};
+
 
 ////
 // Non-static comparison
diff --git a/src/TNL/Containers/Expressions/StaticExpressionTemplates.h b/src/TNL/Containers/Expressions/StaticExpressionTemplates.h
index 967de900dd..d9e5c655c4 100644
--- a/src/TNL/Containers/Expressions/StaticExpressionTemplates.h
+++ b/src/TNL/Containers/Expressions/StaticExpressionTemplates.h
@@ -1228,7 +1228,9 @@ bool
 operator == ( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a,
              const Containers::Expressions::StaticBinaryExpressionTemplate< R1, R2, ROperation >& b )
 {
-   return Containers::Expressions::StaticComparisonEQ( a, b );
+   using Left = Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >;
+   using Right = Containers::Expressions::StaticBinaryExpressionTemplate< R1, R2, ROperation >;
+   return Containers::Expressions::StaticComparison< Left, Right >::EQ( a, b );
 }
 
 template< typename T1,
@@ -1239,7 +1241,46 @@ bool
 operator == ( const Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >& a,
               const typename Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
 {
-   return Containers::Expressions::StaticComparisonEQ( a, b );
+   using Left = Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >;
+   using Right = typename Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType;
+   return Containers::Expressions::StaticComparison< Left, Right >::EQ( a, b );
+}
+
+template< typename T1,
+          template< typename > class Operation >
+__cuda_callable__
+bool
+operator == ( const Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >& a,
+              const typename Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >::RealType& b )
+{
+   using Left = Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >;
+   using Right = typename Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >::RealType;
+   return Containers::Expressions::StaticComparison< Left, Right >::EQ( a, b );
+}
+
+template< typename T1,
+          typename T2,
+          template< typename, typename > class Operation >
+__cuda_callable__
+bool
+operator == ( const typename Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
+              const Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >& b )
+{
+   using Left = typename Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType;
+   using Right = Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >;
+   return Containers::Expressions::StaticComparison< Left, Right >::EQ( a, b );
+}
+
+template< typename T1,
+          template< typename > class Operation >
+__cuda_callable__
+bool
+operator == ( const typename Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >::RealType& a,
+              const Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >& b )
+{
+   using Left = typename Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >::RealType;
+   using Right = Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >;
+   return Containers::Expressions::StaticComparison< Left, Right >::EQ( a, b );
 }
 
 template< typename L1,
@@ -1252,7 +1293,9 @@ bool
 operator == ( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a,
               const typename Containers::Expressions::StaticBinaryExpressionTemplate< R1, R2, ROperation >& b )
 {
-   return Containers::Expressions::StaticComparisonEQ( a, b );
+   using Left = Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >;
+   using Right = Containers::Expressions::StaticBinaryExpressionTemplate< R1, R2, ROperation >;
+   return Containers::Expressions::StaticComparison< Left, Right >::EQ( a, b );
 }
 
 template< typename L1,
@@ -1265,7 +1308,9 @@ bool
 operator == ( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a,
              const typename Containers::Expressions::StaticUnaryExpressionTemplate< R1,ROperation >& b )
 {
-   return Containers::Expressions::StaticComparisonEQ( a, b );
+   using Left = Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >;
+   using Right = Containers::Expressions::StaticUnaryExpressionTemplate< R1, ROperation >;
+   return Containers::Expressions::StaticComparison< Left, Right >::EQ( a, b );
 }
 
 ////
@@ -1281,7 +1326,9 @@ bool
 operator != ( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a,
              const Containers::Expressions::StaticBinaryExpressionTemplate< R1, R2, ROperation >& b )
 {
-   return Containers::Expressions::StaticComparisonNE( a, b );
+   using Left = Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >;
+   using Right = Containers::Expressions::StaticBinaryExpressionTemplate< R1, R2, ROperation >;
+   return Containers::Expressions::StaticComparison< Left, Right >::NE( a, b );
 }
 
 template< typename T1,
@@ -1292,7 +1339,46 @@ bool
 operator != ( const Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >& a,
               const typename Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
 {
-   return Containers::Expressions::StaticComparisonNE( a, b );
+   using Left = Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >;
+   using Right = typename Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType;
+   return Containers::Expressions::StaticComparison< Left, Right >::NE( a, b );
+}
+
+template< typename T1,
+          template< typename > class Operation >
+__cuda_callable__
+bool
+operator != ( const Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >& a,
+              const typename Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >::RealType& b )
+{
+   using Left = Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >;
+   using Right = typename Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >::RealType;
+   return Containers::Expressions::StaticComparison< Left, Right >::NE( a, b );
+}
+
+template< typename T1,
+          typename T2,
+          template< typename, typename > class Operation >
+__cuda_callable__
+bool
+operator != ( const typename Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
+              const Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >& b )
+{
+   using Left = typename Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType;
+   using Right = Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >;
+   return Containers::Expressions::StaticComparison< Left, Right >::NE( a, b );
+}
+
+template< typename T1,
+          template< typename > class Operation >
+__cuda_callable__
+bool
+operator != ( const typename Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >::RealType& a,
+              const Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >& b )
+{
+   using Left = typename Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >::RealType;
+   using Right = Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >;
+   return Containers::Expressions::StaticComparison< Left, Right >::NE( a, b );
 }
 
 template< typename L1,
@@ -1305,7 +1391,9 @@ bool
 operator != ( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a,
               const typename Containers::Expressions::StaticBinaryExpressionTemplate< R1, R2, ROperation >& b )
 {
-   return Containers::Expressions::StaticComparisonNE( a, b );
+   using Left = Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >;
+   using Right = Containers::Expressions::StaticBinaryExpressionTemplate< R1, R2, ROperation >;
+   return Containers::Expressions::StaticComparison< Left, Right >::NE( a, b );
 }
 
 template< typename L1,
@@ -1316,9 +1404,11 @@ template< typename L1,
 __cuda_callable__
 bool
 operator != ( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a,
-              const typename Containers::Expressions::StaticUnaryExpressionTemplate< R1, ROperation >& b )
+             const typename Containers::Expressions::StaticUnaryExpressionTemplate< R1,ROperation >& b )
 {
-   return Containers::Expressions::StaticComparisonNE( a, b );
+   using Left = Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >;
+   using Right = Containers::Expressions::StaticUnaryExpressionTemplate< R1, ROperation >;
+   return Containers::Expressions::StaticComparison< Left, Right >::NE( a, b );
 }
 
 ////
@@ -1334,7 +1424,9 @@ bool
 operator < ( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a,
              const Containers::Expressions::StaticBinaryExpressionTemplate< R1, R2, ROperation >& b )
 {
-   return Containers::Expressions::StaticComparisonLT( a, b );
+   using Left = Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >;
+   using Right = Containers::Expressions::StaticBinaryExpressionTemplate< R1, R2, ROperation >;
+   return Containers::Expressions::StaticComparison< Left, Right >::LT( a, b );
 }
 
 template< typename T1,
@@ -1345,7 +1437,46 @@ bool
 operator < ( const Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >& a,
              const typename Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
 {
-   return Containers::Expressions::StaticComparisonLT( a, b );
+   using Left = Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >;
+   using Right = typename Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType;
+   return Containers::Expressions::StaticComparison< Left, Right >::LT( a, b );
+}
+
+template< typename T1,
+          template< typename > class Operation >
+__cuda_callable__
+bool
+operator < ( const Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >& a,
+             const typename Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >::RealType& b )
+{
+   using Left = Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >;
+   using Right = typename Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >::RealType;
+   return Containers::Expressions::StaticComparison< Left, Right >::LT( a, b );
+}
+
+template< typename T1,
+          typename T2,
+          template< typename, typename > class Operation >
+__cuda_callable__
+bool
+operator < ( const typename Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
+             const Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >& b )
+{
+   using Left = typename Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType;
+   using Right = Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >;
+   return Containers::Expressions::StaticComparison< Left, Right >::LT( a, b );
+}
+
+template< typename T1,
+          template< typename > class Operation >
+__cuda_callable__
+bool
+operator < ( const typename Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >::RealType& a,
+             const Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >& b )
+{
+   using Left = typename Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >::RealType;
+   using Right = Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >;
+   return Containers::Expressions::StaticComparison< Left, Right >::LT( a, b );
 }
 
 template< typename L1,
@@ -1356,9 +1487,11 @@ template< typename L1,
 __cuda_callable__
 bool
 operator < ( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a,
-              const typename Containers::Expressions::StaticBinaryExpressionTemplate< R1, R2, ROperation >& b )
+             const typename Containers::Expressions::StaticBinaryExpressionTemplate< R1, R2, ROperation >& b )
 {
-   return Containers::Expressions::StaticComparisonLT( a, b );
+   using Left = Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >;
+   using Right = Containers::Expressions::StaticBinaryExpressionTemplate< R1, R2, ROperation >;
+   return Containers::Expressions::StaticComparison< Left, Right >::LT( a, b );
 }
 
 template< typename L1,
@@ -1369,9 +1502,11 @@ template< typename L1,
 __cuda_callable__
 bool
 operator < ( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a,
-              const typename Containers::Expressions::StaticUnaryExpressionTemplate< R1, ROperation >& b )
+             const typename Containers::Expressions::StaticUnaryExpressionTemplate< R1,ROperation >& b )
 {
-   return Containers::Expressions::StaticComparisonLT( a, b );
+   using Left = Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >;
+   using Right = Containers::Expressions::StaticUnaryExpressionTemplate< R1, ROperation >;
+   return Containers::Expressions::StaticComparison< Left, Right >::LT( a, b );
 }
 
 ////
@@ -1385,9 +1520,11 @@ template< typename L1,
 __cuda_callable__
 bool
 operator <= ( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a,
-             const Containers::Expressions::StaticBinaryExpressionTemplate< R1, R2, ROperation >& b )
+              const Containers::Expressions::StaticBinaryExpressionTemplate< R1, R2, ROperation >& b )
 {
-   return Containers::Expressions::StaticComparisonLE( a, b );
+   using Left = Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >;
+   using Right = Containers::Expressions::StaticBinaryExpressionTemplate< R1, R2, ROperation >;
+   return Containers::Expressions::StaticComparison< Left, Right >::LE( a, b );
 }
 
 template< typename T1,
@@ -1396,9 +1533,48 @@ template< typename T1,
 __cuda_callable__
 bool
 operator <= ( const Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >& a,
-             const typename Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
+              const typename Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
+{
+   using Left = Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >;
+   using Right = typename Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType;
+   return Containers::Expressions::StaticComparison< Left, Right >::LE( a, b );
+}
+
+template< typename T1,
+          template< typename > class Operation >
+__cuda_callable__
+bool
+operator <= ( const Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >& a,
+              const typename Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >::RealType& b )
+{
+   using Left = Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >;
+   using Right = typename Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >::RealType;
+   return Containers::Expressions::StaticComparison< Left, Right >::LE( a, b );
+}
+
+template< typename T1,
+          typename T2,
+          template< typename, typename > class Operation >
+__cuda_callable__
+bool
+operator <= ( const typename Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
+              const Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >& b )
+{
+   using Left = typename Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType;
+   using Right = Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >;
+   return Containers::Expressions::StaticComparison< Left, Right >::LE( a, b );
+}
+
+template< typename T1,
+          template< typename > class Operation >
+__cuda_callable__
+bool
+operator <= ( const typename Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >::RealType& a,
+              const Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >& b )
 {
-   return Containers::Expressions::StaticComparisonLE( a, b );
+   using Left = typename Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >::RealType;
+   using Right = Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >;
+   return Containers::Expressions::StaticComparison< Left, Right >::LE( a, b );
 }
 
 template< typename L1,
@@ -1411,7 +1587,9 @@ bool
 operator <= ( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a,
               const typename Containers::Expressions::StaticBinaryExpressionTemplate< R1, R2, ROperation >& b )
 {
-   return Containers::Expressions::StaticComparisonLE( a, b );
+   using Left = Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >;
+   using Right = Containers::Expressions::StaticBinaryExpressionTemplate< R1, R2, ROperation >;
+   return Containers::Expressions::StaticComparison< Left, Right >::LE( a, b );
 }
 
 template< typename L1,
@@ -1422,9 +1600,11 @@ template< typename L1,
 __cuda_callable__
 bool
 operator <= ( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a,
-              const typename Containers::Expressions::StaticUnaryExpressionTemplate< R1, ROperation >& b )
+             const typename Containers::Expressions::StaticUnaryExpressionTemplate< R1,ROperation >& b )
 {
-   return Containers::Expressions::StaticComparisonLE( a, b );
+   using Left = Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >;
+   using Right = Containers::Expressions::StaticUnaryExpressionTemplate< R1, ROperation >;
+   return Containers::Expressions::StaticComparison< Left, Right >::LE( a, b );
 }
 
 ////
@@ -1440,7 +1620,9 @@ bool
 operator > ( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a,
              const Containers::Expressions::StaticBinaryExpressionTemplate< R1, R2, ROperation >& b )
 {
-   return Containers::Expressions::StaticComparisonGT( a, b );
+   using Left = Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >;
+   using Right = Containers::Expressions::StaticBinaryExpressionTemplate< R1, R2, ROperation >;
+   return Containers::Expressions::StaticComparison< Left, Right >::GT( a, b );
 }
 
 template< typename T1,
@@ -1451,7 +1633,46 @@ bool
 operator > ( const Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >& a,
              const typename Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
 {
-   return Containers::Expressions::StaticComparisonGT( a, b );
+   using Left = Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >;
+   using Right = typename Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType;
+   return Containers::Expressions::StaticComparison< Left, Right >::GT( a, b );
+}
+
+template< typename T1,
+          template< typename > class Operation >
+__cuda_callable__
+bool
+operator > ( const Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >& a,
+             const typename Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >::RealType& b )
+{
+   using Left = Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >;
+   using Right = typename Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >::RealType;
+   return Containers::Expressions::StaticComparison< Left, Right >::GT( a, b );
+}
+
+template< typename T1,
+          typename T2,
+          template< typename, typename > class Operation >
+__cuda_callable__
+bool
+operator > ( const typename Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
+             const Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >& b )
+{
+   using Left = typename Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType;
+   using Right = Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >;
+   return Containers::Expressions::StaticComparison< Left, Right >::GT( a, b );
+}
+
+template< typename T1,
+          template< typename > class Operation >
+__cuda_callable__
+bool
+operator > ( const typename Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >::RealType& a,
+             const Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >& b )
+{
+   using Left = typename Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >::RealType;
+   using Right = Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >;
+   return Containers::Expressions::StaticComparison< Left, Right >::GT( a, b );
 }
 
 template< typename L1,
@@ -1464,7 +1685,9 @@ bool
 operator > ( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a,
              const typename Containers::Expressions::StaticBinaryExpressionTemplate< R1, R2, ROperation >& b )
 {
-   return Containers::Expressions::StaticComparisonGT( a, b );
+   using Left = Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >;
+   using Right = Containers::Expressions::StaticBinaryExpressionTemplate< R1, R2, ROperation >;
+   return Containers::Expressions::StaticComparison< Left, Right >::GT( a, b );
 }
 
 template< typename L1,
@@ -1475,9 +1698,11 @@ template< typename L1,
 __cuda_callable__
 bool
 operator > ( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a,
-             const typename Containers::Expressions::StaticUnaryExpressionTemplate< R1, ROperation >& b )
+             const typename Containers::Expressions::StaticUnaryExpressionTemplate< R1,ROperation >& b )
 {
-   return Containers::Expressions::StaticComparisonGT( a, b );
+   using Left = Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >;
+   using Right = Containers::Expressions::StaticUnaryExpressionTemplate< R1, ROperation >;
+   return Containers::Expressions::StaticComparison< Left, Right >::GT( a, b );
 }
 
 ////
@@ -1493,7 +1718,9 @@ bool
 operator >= ( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a,
               const Containers::Expressions::StaticBinaryExpressionTemplate< R1, R2, ROperation >& b )
 {
-   return Containers::Expressions::StaticComparisonGE( a, b );
+   using Left = Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >;
+   using Right = Containers::Expressions::StaticBinaryExpressionTemplate< R1, R2, ROperation >;
+   return Containers::Expressions::StaticComparison< Left, Right >::GE( a, b );
 }
 
 template< typename T1,
@@ -1504,7 +1731,46 @@ bool
 operator >= ( const Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >& a,
               const typename Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
 {
-   return Containers::Expressions::StaticComparisonGE( a, b );
+   using Left = Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >;
+   using Right = typename Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType;
+   return Containers::Expressions::StaticComparison< Left, Right >::GE( a, b );
+}
+
+template< typename T1,
+          template< typename > class Operation >
+__cuda_callable__
+bool
+operator >= ( const Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >& a,
+              const typename Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >::RealType& b )
+{
+   using Left = Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >;
+   using Right = typename Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >::RealType;
+   return Containers::Expressions::StaticComparison< Left, Right >::GE( a, b );
+}
+
+template< typename T1,
+          typename T2,
+          template< typename, typename > class Operation >
+__cuda_callable__
+bool
+operator >= ( const typename Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
+              const Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >& b )
+{
+   using Left = typename Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType;
+   using Right = Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >;
+   return Containers::Expressions::StaticComparison< Left, Right >::GE( a, b );
+}
+
+template< typename T1,
+          template< typename > class Operation >
+__cuda_callable__
+bool
+operator >= ( const typename Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >::RealType& a,
+              const Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >& b )
+{
+   using Left = typename Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >::RealType;
+   using Right = Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >;
+   return Containers::Expressions::StaticComparison< Left, Right >::GE( a, b );
 }
 
 template< typename L1,
@@ -1517,7 +1783,9 @@ bool
 operator >= ( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a,
               const typename Containers::Expressions::StaticBinaryExpressionTemplate< R1, R2, ROperation >& b )
 {
-   return Containers::Expressions::StaticComparisonGE( a, b );
+   using Left = Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >;
+   using Right = Containers::Expressions::StaticBinaryExpressionTemplate< R1, R2, ROperation >;
+   return Containers::Expressions::StaticComparison< Left, Right >::GE( a, b );
 }
 
 template< typename L1,
@@ -1528,15 +1796,16 @@ template< typename L1,
 __cuda_callable__
 bool
 operator >= ( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a,
-              const typename Containers::Expressions::StaticUnaryExpressionTemplate< R1, ROperation >& b )
+             const typename Containers::Expressions::StaticUnaryExpressionTemplate< R1,ROperation >& b )
 {
-   return Containers::Expressions::StaticComparisonGE( a, b );
+   using Left = Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >;
+   using Right = Containers::Expressions::StaticUnaryExpressionTemplate< R1, ROperation >;
+   return Containers::Expressions::StaticComparison< Left, Right >::GE( a, b );
 }
 
 ////
 // Unary operations
 
-
 ////
 // Minus
 template< typename L1,
diff --git a/src/TNL/Containers/StaticVectorExpressions.h b/src/TNL/Containers/StaticVectorExpressions.h
index fcf8304fe8..60cc396d14 100644
--- a/src/TNL/Containers/StaticVectorExpressions.h
+++ b/src/TNL/Containers/StaticVectorExpressions.h
@@ -130,21 +130,21 @@ template< int Size, typename Real, typename ET >
 __cuda_callable__
 bool operator==( const StaticVector< Size, Real >& a, const ET& b )
 {
-   return Expressions::StaticComparisonEQ( a, b );
+   return Expressions::StaticComparison< StaticVector< Size, Real >, ET >::EQ( a, b );
 }
 
 template< typename ET, int Size, typename Real >
 __cuda_callable__
 bool operator==( const ET& a, const StaticVector< Size, Real >& b )
 {
-   return Expressions::StaticComparisonEQ( a, b );
+   return Expressions::StaticComparison< ET, StaticVector< Size, Real > >::EQ( a, b );
 }
 
 template< int Size, typename Real1, typename Real2 >
 __cuda_callable__
 bool operator==( const StaticVector< Size, Real1 >& a, const StaticVector< Size, Real2 >& b )
 {
-   return Expressions::StaticComparisonEQ( a, b );
+   return Expressions::StaticComparison< StaticVector< Size, Real1 >, StaticVector< Size, Real2 > >::EQ( a, b );
 }
 
 ////
@@ -153,21 +153,21 @@ template< int Size, typename Real, typename ET >
 __cuda_callable__
 bool operator!=( const StaticVector< Size, Real >& a, const ET& b )
 {
-   return Expressions::StaticComparisonNE( a, b );
+   return Expressions::StaticComparison< StaticVector< Size, Real >, ET >::NE( a, b );
 }
 
 template< typename ET, int Size, typename Real >
 __cuda_callable__
 bool operator!=( const ET& a, const StaticVector< Size, Real >& b )
 {
-   return Expressions::StaticComparisonNE( a, b );
+   return Expressions::StaticComparison< ET, StaticVector< Size, Real > >::NE( a, b );
 }
 
 template< int Size, typename Real1, typename Real2 >
 __cuda_callable__
 bool operator!=( const StaticVector< Size, Real1 >& a, const StaticVector< Size, Real2 >& b )
 {
-   return Expressions::StaticComparisonNE( a, b );
+   return Expressions::StaticComparison< StaticVector< Size, Real1 >, StaticVector< Size, Real2 > >::NE( a, b );
 }
 
 ////
@@ -176,21 +176,21 @@ template< int Size, typename Real, typename ET >
 __cuda_callable__
 bool operator<( const StaticVector< Size, Real >& a, const ET& b )
 {
-   return Expressions::StaticComparisonLT( a, b );
+   return Expressions::StaticComparison< StaticVector< Size, Real >, ET >::LT( a, b );
 }
 
 template< typename ET, int Size, typename Real >
 __cuda_callable__
 bool operator<( const ET& a, const StaticVector< Size, Real >& b )
 {
-   return Expressions::StaticComparisonLT( a, b );
+   return Expressions::StaticComparison< ET, StaticVector< Size, Real > >::LT( a, b );
 }
 
 template< int Size, typename Real1, typename Real2 >
 __cuda_callable__
 bool operator<( const StaticVector< Size, Real1 >& a, const StaticVector< Size, Real2 >& b )
 {
-   return Expressions::StaticComparisonLT( a, b );
+   return Expressions::StaticComparison< StaticVector< Size, Real1 >, StaticVector< Size, Real2 > >::LT( a, b );
 }
 
 ////
@@ -199,21 +199,21 @@ template< int Size, typename Real, typename ET >
 __cuda_callable__
 bool operator<=( const StaticVector< Size, Real >& a, const ET& b )
 {
-   return Expressions::StaticComparisonLE( a, b );
+   return Expressions::StaticComparison< StaticVector< Size, Real >, ET >::LE( a, b );
 }
 
 template< typename ET, int Size, typename Real >
 __cuda_callable__
 bool operator<=( const ET& a, const StaticVector< Size, Real >& b )
 {
-   return Expressions::StaticComparisonLE( a, b );
+   return Expressions::StaticComparison< ET, StaticVector< Size, Real > >::LE( a, b );
 }
 
 template< int Size, typename Real1, typename Real2 >
 __cuda_callable__
 bool operator<=( const StaticVector< Size, Real1 >& a, const StaticVector< Size, Real2 >& b )
 {
-   return Expressions::StaticComparisonLE( a, b );
+   return Expressions::StaticComparison< StaticVector< Size, Real1 >, StaticVector< Size, Real2 > >::LE( a, b );
 }
 
 ////
@@ -222,21 +222,21 @@ template< int Size, typename Real, typename ET >
 __cuda_callable__
 bool operator>( const StaticVector< Size, Real >& a, const ET& b )
 {
-   return Expressions::StaticComparisonGT( a, b );
+   return Expressions::StaticComparison< StaticVector< Size, Real >, ET >::GT( a, b );
 }
 
 template< typename ET, int Size, typename Real >
 __cuda_callable__
 bool operator>( const ET& a, const StaticVector< Size, Real >& b )
 {
-   return Expressions::StaticComparisonGT( a, b );
+   return Expressions::StaticComparison< ET, StaticVector< Size, Real > >::GT( a, b );
 }
 
 template< int Size, typename Real1, typename Real2 >
 __cuda_callable__
 bool operator>( const StaticVector< Size, Real1 >& a, const StaticVector< Size, Real2 >& b )
 {
-   return Expressions::StaticComparisonGT( a, b );
+   return Expressions::StaticComparison< StaticVector< Size, Real1 >, StaticVector< Size, Real2 > >::GT( a, b );
 }
 
 ////
@@ -245,21 +245,21 @@ template< int Size, typename Real, typename ET >
 __cuda_callable__
 bool operator>=( const StaticVector< Size, Real >& a, const ET& b )
 {
-   return Expressions::StaticComparisonGE( a, b );
+   return Expressions::StaticComparison< StaticVector< Size, Real >, ET >::GE( a, b );
 }
 
 template< typename ET, int Size, typename Real >
 __cuda_callable__
 bool operator>=( const ET& a, const StaticVector< Size, Real >& b )
 {
-   return Expressions::StaticComparisonGE( a, b );
+   return Expressions::StaticComparison< ET, StaticVector< Size, Real > >::GE( a, b );
 }
 
 template< int Size, typename Real1, typename Real2 >
 __cuda_callable__
 bool operator>=( const StaticVector< Size, Real1 >& a, const StaticVector< Size, Real2 >& b )
 {
-   return Expressions::StaticComparisonGE( a, b );
+   return Expressions::StaticComparison< StaticVector< Size, Real1 >, StaticVector< Size, Real2 > >::GE( a, b );
 }
 
 ////
diff --git a/src/UnitTests/Containers/StaticVectorTest.cpp b/src/UnitTests/Containers/StaticVectorTest.cpp
index 2282118433..5e3b15438a 100644
--- a/src/UnitTests/Containers/StaticVectorTest.cpp
+++ b/src/UnitTests/Containers/StaticVectorTest.cpp
@@ -568,6 +568,59 @@ TYPED_TEST( StaticVectorTest, verticalOperations )
    EXPECT_NEAR( lpNorm( u - v, 2.0 ), l2NormDiff, 2.0e-5 );
 }
 
+TYPED_TEST( StaticVectorTest, comparisonOperators )
+{
+   using VectorType = typename TestFixture::VectorType;
+
+   using RealType = typename VectorType::RealType;
+   constexpr int size = VectorType::size;
+
+   VectorType u, v, w;
+   u = 1.0;
+   v = 2.0;
+   w = 4.0;
+
+   EXPECT_EQ( u, u );
+   EXPECT_EQ( u, 1.0 );
+   EXPECT_EQ( 1.0, u );
+   EXPECT_EQ( w, u + v );
+   EXPECT_EQ( u + v, w );
+   EXPECT_EQ( abs( w ), u + v );
+   EXPECT_EQ( u + v, abs( w ) );
+
+   EXPECT_NE( u, v );
+   EXPECT_NE( u, 2.0 );
+   EXPECT_NE( 2.0, u );
+   EXPECT_NE( u, w + w );
+   EXPECT_NE( w + v, u );
+   EXPECT_NE( abs( u ), w + w );
+   EXPECT_NE( w + v, abs( u ) );
+
+   EXPECT_LT( u, v );
+   EXPECT_LT( u, 2.0 );
+   EXPECT_LT( 0.0, u );
+   EXPECT_LT( u, v + w );
+   EXPECT_LT( u + v, w );
+   EXPECT_LT( abs( u ), v + w );
+   EXPECT_LT( u + v, abs( w ) );
+
+   EXPECT_LE( u, v );
+   EXPECT_LE( u, 2.0 );
+   EXPECT_LE( 0.0, u );
+   EXPECT_LE( u, v + w );
+   EXPECT_LE( u + v, w );
+   EXPECT_LE( abs( u ), v + w );
+   EXPECT_LE( u + v, abs( w ) );
+
+   EXPECT_GT( v, u );
+   EXPECT_GT( v, 1.0 );
+   EXPECT_GT( 3.0, v );
+   EXPECT_GT( w, u + v );
+   EXPECT_GT( v + w, u );
+   EXPECT_GT( abs( w ), u + v );
+   EXPECT_GT( v + w, abs( u ) );
+}
+
 #endif
 
 
-- 
GitLab