diff --git a/src/TNL/Assert.h b/src/TNL/Assert.h
index df862956219ac03e1d1e1fa27e1c67a0e1035ad5..dc4ba7cf439d4ea25576d75fd1605c4400f6fa23 100644
--- a/src/TNL/Assert.h
+++ b/src/TNL/Assert.h
@@ -376,6 +376,12 @@ TNL_IMPL_CMP_HELPER_( GT, > );
     #define __TNL_PRETTY_FUNCTION __PRETTY_FUNCTION__
 #endif
 
+// On Linux, __STRING is defined in glibc's sys/cdefs.h, but there is no such
+// header on Windows and possibly other platforms.
+#ifndef __STRING
+   #define __STRING(arg) #arg
+#endif
+
 // Internal macro to compose the string representing the assertion.
 // We can't do it easily at runtime, because we have to support assertions
 // in CUDA kernels, which can't use std::string objects. Instead, we do it
diff --git a/src/TNL/Config/ParameterContainer.h b/src/TNL/Config/ParameterContainer.h
index 734db27f512a11124ef512b55ce578301d4c790c..79a50e151063cd9b5358add30422d713e40a0cc8 100644
--- a/src/TNL/Config/ParameterContainer.h
+++ b/src/TNL/Config/ParameterContainer.h
@@ -82,7 +82,7 @@ public:
    }
 
    /**
-    * \brief Checks whether the parameter \e name already exists in ParameterContainer.
+    * \brief Checks if the ParameterContainer contains a parameter specified by its name.
     *
     * \param name Name of the parameter.
     */
@@ -95,6 +95,19 @@ public:
       return false;
    }
 
+   /**
+    * \brief Checks whether the ParameterContainer contains all specified parameter names.
+    *
+    * \param name Name of the parameter.
+    */
+   bool checkParameters( std::initializer_list< String > names ) const
+   {
+      for( auto name : names )
+         if( ! checkParameter( name ) )
+            return false;
+      return true;
+   }
+
    /**
     * \brief Assigns new \e value to the parameter \e name.
     *
diff --git a/src/TNL/Containers/DistributedVector.h b/src/TNL/Containers/DistributedVector.h
index db4e46e68616244399e85fa7903ebe53a1e30585..be9ff657f1cd3c8ad49bf6af8a0aa09fc9242c6a 100644
--- a/src/TNL/Containers/DistributedVector.h
+++ b/src/TNL/Containers/DistributedVector.h
@@ -134,8 +134,15 @@ public:
    void scan( IndexType begin = 0, IndexType end = 0 );
 };
 
+// Enable expression templates for DistributedVector
+namespace Expressions {
+   template< typename Real, typename Device, typename Index, typename Communicator >
+   struct HasEnabledDistributedExpressionTemplates< DistributedVector< Real, Device, Index, Communicator > >
+   : std::true_type
+   {};
+} // namespace Expressions
+
 } // namespace Containers
 } // namespace TNL
 
 #include <TNL/Containers/DistributedVector.hpp>
-#include <TNL/Containers/DistributedVectorExpressions.h>
diff --git a/src/TNL/Containers/DistributedVectorExpressions.h b/src/TNL/Containers/DistributedVectorExpressions.h
deleted file mode 100644
index 0d6d73e670eb2c745d6b4158da8cb8ec1ab165a7..0000000000000000000000000000000000000000
--- a/src/TNL/Containers/DistributedVectorExpressions.h
+++ /dev/null
@@ -1,936 +0,0 @@
-/***************************************************************************
-                          DistributedVectorExpressions.h  -  description
-                             -------------------
-    begin                : Jul 1, 2019
-    copyright            : (C) 2019 by Tomas Oberhuber et al.
-    email                : tomas.oberhuber@fjfi.cvut.cz
- ***************************************************************************/
-
-/* See Copyright Notice in tnl/Copyright */
-
-#pragma once
-#ifndef DOXYGEN_ONLY
-
-#include <TNL/Containers/Expressions/DistributedExpressionTemplates.h>
-
-#include "DistributedVector.h"
-
-namespace TNL {
-namespace Containers {
-
-////
-// Addition
-template< typename Real, typename Device, typename Index, typename Communicator, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-auto
-operator+( const DistributedVector< Real, Device, Index, Communicator >& a, const ET& b )
-{
-   return Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, ET, Expressions::Addition >( a, b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Communicator,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-auto
-operator+( const ET& a, const DistributedVector< Real, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedBinaryExpressionTemplate< ET, std::decay_t<decltype(b)>, Expressions::Addition >( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-auto
-operator+( const DistributedVector< Real1, Device, Index, Communicator >& a, const DistributedVector< Real2, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Expressions::Addition >( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-auto
-operator+( const DistributedVectorView< Real1, Device, Index, Communicator >& a, const DistributedVector< Real2, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Expressions::Addition >( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-auto
-operator+( const DistributedVector< Real1, Device, Index, Communicator >& a, const DistributedVectorView< Real2, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Expressions::Addition >( a, b );
-}
-
-////
-// Subtraction
-template< typename Real, typename Device, typename Index, typename Communicator, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-auto
-operator-( const DistributedVector< Real, Device, Index, Communicator >& a, const ET& b )
-{
-   return Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, ET, Expressions::Subtraction >( a, b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Communicator,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-auto
-operator-( const ET& a, const DistributedVector< Real, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedBinaryExpressionTemplate< ET, std::decay_t<decltype(b)>, Expressions::Subtraction >( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-auto
-operator-( const DistributedVector< Real1, Device, Index, Communicator >& a, const DistributedVector< Real2, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Expressions::Subtraction >( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-auto
-operator-( const DistributedVectorView< Real1, Device, Index, Communicator >& a, const DistributedVector< Real2, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Expressions::Subtraction >( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-auto
-operator-( const DistributedVector< Real1, Device, Index, Communicator >& a, const DistributedVectorView< Real2, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Expressions::Subtraction >( a, b );
-}
-
-////
-// Multiplication
-template< typename Real, typename Device, typename Index, typename Communicator, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-auto
-operator*( const DistributedVector< Real, Device, Index, Communicator >& a, const ET& b )
-{
-   return Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, ET, Expressions::Multiplication >( a, b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Communicator,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-auto
-operator*( const ET& a, const DistributedVector< Real, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedBinaryExpressionTemplate< ET, std::decay_t<decltype(b)>, Expressions::Multiplication >( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-auto
-operator*( const DistributedVector< Real1, Device, Index, Communicator >& a, const DistributedVector< Real2, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Expressions::Multiplication >( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-auto
-operator*( const DistributedVectorView< Real1, Device, Index, Communicator >& a, const DistributedVector< Real2, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Expressions::Multiplication >( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-auto
-operator*( const DistributedVector< Real1, Device, Index, Communicator >& a, const DistributedVectorView< Real2, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Expressions::Multiplication >( a, b );
-}
-
-////
-// Division
-template< typename Real, typename Device, typename Index, typename Communicator, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-auto
-operator/( const DistributedVector< Real, Device, Index, Communicator >& a, const ET& b )
-{
-   return Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, ET, Expressions::Division >( a, b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Communicator,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-auto
-operator/( const ET& a, const DistributedVector< Real, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedBinaryExpressionTemplate< ET, std::decay_t<decltype(b)>, Expressions::Division >( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-auto
-operator/( const DistributedVector< Real1, Device, Index, Communicator >& a, const DistributedVector< Real2, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Expressions::Division >( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-auto
-operator/( const DistributedVectorView< Real1, Device, Index, Communicator >& a, const DistributedVector< Real2, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Expressions::Division >( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-auto
-operator/( const DistributedVector< Real1, Device, Index, Communicator >& a, const DistributedVectorView< Real2, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Expressions::Division >( a, b );
-}
-
-////
-// Comparison operations - operator ==
-template< typename Real, typename Device, typename Index, typename Communicator, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator==( const DistributedVector< Real, Device, Index, Communicator >& a, const ET& b )
-{
-   return Expressions::DistributedComparison< std::decay_t<decltype(a)>, ET >::EQ( a, b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Communicator,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator==( const ET& a, const DistributedVector< Real, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedComparison< ET, std::decay_t<decltype(b)> >::EQ( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device1, typename Device2, typename Index, typename Communicator >
-bool
-operator==( const DistributedVector< Real1, Device1, Index, Communicator >& a, const DistributedVector< Real2, Device2, Index, Communicator >& b )
-{
-   return Expressions::DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::EQ( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device1, typename Device2, typename Index, typename Communicator >
-bool
-operator==( const DistributedVectorView< Real1, Device1, Index, Communicator >& a, const DistributedVector< Real2, Device2, Index, Communicator >& b )
-{
-   return Expressions::DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::EQ( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device1, typename Device2, typename Index, typename Communicator >
-bool
-operator==( const DistributedVector< Real1, Device1, Index, Communicator >& a, const DistributedVectorView< Real2, Device2, Index, Communicator >& b )
-{
-   return Expressions::DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::EQ( a, b );
-}
-
-////
-// Comparison operations - operator !=
-template< typename Real, typename Device, typename Index, typename Communicator, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator!=( const DistributedVector< Real, Device, Index, Communicator >& a, const ET& b )
-{
-   return Expressions::DistributedComparison< std::decay_t<decltype(a)>, ET >::NE( a, b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Communicator,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator!=( const ET& a, const DistributedVector< Real, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedComparison< ET, std::decay_t<decltype(b)> >::NE( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device1, typename Device2, typename Index, typename Communicator >
-bool
-operator!=( const DistributedVector< Real1, Device1, Index, Communicator >& a, const DistributedVector< Real2, Device2, Index, Communicator >& b )
-{
-   return Expressions::DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device1, typename Device2, typename Index, typename Communicator >
-bool
-operator!=( const DistributedVectorView< Real1, Device1, Index, Communicator >& a, const DistributedVector< Real2, Device2, Index, Communicator >& b )
-{
-   return Expressions::DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device1, typename Device2, typename Index, typename Communicator >
-bool
-operator!=( const DistributedVector< Real1, Device1, Index, Communicator >& a, const DistributedVectorView< Real2, Device2, Index, Communicator >& b )
-{
-   return Expressions::DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b );
-}
-
-////
-// Comparison operations - operator <
-template< typename Real, typename Device, typename Index, typename Communicator, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator<( const DistributedVector< Real, Device, Index, Communicator >& a, const ET& b )
-{
-   return Expressions::DistributedComparison< std::decay_t<decltype(a)>, ET >::LT( a, b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Communicator,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator<( const ET& a, const DistributedVector< Real, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedComparison< ET, std::decay_t<decltype(b)> >::LT( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-bool
-operator<( const DistributedVector< Real1, Device, Index, Communicator >& a, const DistributedVector< Real2, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-bool
-operator<( const DistributedVectorView< Real1, Device, Index, Communicator >& a, const DistributedVector< Real2, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-bool
-operator<( const DistributedVector< Real1, Device, Index, Communicator >& a, const DistributedVectorView< Real2, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b );
-}
-
-////
-// Comparison operations - operator <=
-template< typename Real, typename Device, typename Index, typename Communicator, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator<=( const DistributedVector< Real, Device, Index, Communicator >& a, const ET& b )
-{
-   return Expressions::DistributedComparison< std::decay_t<decltype(a)>, ET >::LE( a, b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Communicator,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator<=( const ET& a, const DistributedVector< Real, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedComparison< ET, std::decay_t<decltype(b)> >::LE( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-bool
-operator<=( const DistributedVector< Real1, Device, Index, Communicator >& a, const DistributedVector< Real2, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-bool
-operator<=( const DistributedVectorView< Real1, Device, Index, Communicator >& a, const DistributedVector< Real2, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-bool
-operator<=( const DistributedVector< Real1, Device, Index, Communicator >& a, const DistributedVectorView< Real2, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b );
-}
-
-////
-// Comparison operations - operator >
-template< typename Real, typename Device, typename Index, typename Communicator, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator>( const DistributedVector< Real, Device, Index, Communicator >& a, const ET& b )
-{
-   return Expressions::DistributedComparison< std::decay_t<decltype(a)>, ET >::GT( a, b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Communicator,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator>( const ET& a, const DistributedVector< Real, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedComparison< ET, std::decay_t<decltype(b)> >::GT( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-bool
-operator>( const DistributedVector< Real1, Device, Index, Communicator >& a, const DistributedVector< Real2, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GT( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-bool
-operator>( const DistributedVectorView< Real1, Device, Index, Communicator >& a, const DistributedVector< Real2, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GT( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-bool
-operator>( const DistributedVector< Real1, Device, Index, Communicator >& a, const DistributedVectorView< Real2, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GT( a, b );
-}
-
-////
-// Comparison operations - operator >=
-template< typename Real, typename Device, typename Index, typename Communicator, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator>=( const DistributedVector< Real, Device, Index, Communicator >& a, const ET& b )
-{
-   return Expressions::DistributedComparison< std::decay_t<decltype(a)>, ET >::GE( a, b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Communicator,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator>=( const ET& a, const DistributedVector< Real, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedComparison< ET, std::decay_t<decltype(b)> >::GE( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-bool
-operator>=( const DistributedVector< Real1, Device, Index, Communicator >& a, const DistributedVector< Real2, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GE( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-bool
-operator>=( const DistributedVectorView< Real1, Device, Index, Communicator >& a, const DistributedVector< Real2, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GE( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-bool
-operator>=( const DistributedVector< Real1, Device, Index, Communicator >& a, const DistributedVectorView< Real2, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GE( a, b );
-}
-
-////
-// Minus
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-operator-( const DistributedVector< Real, Device, Index, Communicator >& a )
-{
-   return Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Expressions::Minus >( a );
-}
-
-////
-// Scalar product
-template< typename Real, typename Device, typename Index, typename Communicator, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-Real
-operator,( const DistributedVector< Real, Device, Index, Communicator >& a, const ET& b )
-{
-   return Expressions::DistributedExpressionSum( a * b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Communicator,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-Real
-operator,( const ET& a, const DistributedVector< Real, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedExpressionSum( a * b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-auto
-operator,( const DistributedVector< Real1, Device, Index, Communicator >& a, const DistributedVector< Real2, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedExpressionSum( a * b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-auto
-operator,( const DistributedVectorView< Real1, Device, Index, Communicator >& a, const DistributedVector< Real2, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedExpressionSum( a * b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-auto
-operator,( const DistributedVector< Real1, Device, Index, Communicator >& a, const DistributedVectorView< Real2, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedExpressionSum( a * b );
-}
-
-} //namespace Containers
-
-////
-// All functions are supposed to be in namespace TNL
-
-////
-// Min
-template< typename Real, typename Device, typename Index, typename Communicator, typename ET,
-          typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > >
-auto
-min( const Containers::DistributedVector< Real, Device, Index, Communicator >& a, const ET& b )
-{
-   return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, ET, Containers::Expressions::Min >( a, b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Communicator,
-          typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > >
-auto
-min( const ET& a, const Containers::DistributedVector< Real, Device, Index, Communicator >& b )
-{
-   return Containers::Expressions::DistributedBinaryExpressionTemplate< ET, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-auto
-min( const Containers::DistributedVector< Real1, Device, Index, Communicator >& a, const Containers::DistributedVector< Real2, Device, Index, Communicator >& b )
-{
-   return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-auto
-min( const Containers::DistributedVectorView< Real1, Device, Index, Communicator >& a, const Containers::DistributedVector< Real2, Device, Index, Communicator >& b )
-{
-   return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-auto
-min( const Containers::DistributedVector< Real1, Device, Index, Communicator >& a, const Containers::DistributedVectorView< Real2, Device, Index, Communicator >& b )
-{
-   return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b );
-}
-
-////
-// Max
-template< typename Real, typename Device, typename Index, typename Communicator, typename ET,
-          typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > >
-auto
-max( const Containers::DistributedVector< Real, Device, Index, Communicator >& a, const ET& b )
-{
-   return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, ET, Containers::Expressions::Max >( a, b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Communicator,
-          typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > >
-auto
-max( const ET& a, const Containers::DistributedVector< Real, Device, Index, Communicator >& b )
-{
-   return Containers::Expressions::DistributedBinaryExpressionTemplate< ET, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-auto
-max( const Containers::DistributedVector< Real1, Device, Index, Communicator >& a, const Containers::DistributedVector< Real2, Device, Index, Communicator >& b )
-{
-   return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-auto
-max( const Containers::DistributedVectorView< Real1, Device, Index, Communicator >& a, const Containers::DistributedVector< Real2, Device, Index, Communicator >& b )
-{
-   return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-auto
-max( const Containers::DistributedVector< Real1, Device, Index, Communicator >& a, const Containers::DistributedVectorView< Real2, Device, Index, Communicator >& b )
-{
-   return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b );
-}
-
-////
-// Dot product - the same as scalar product, just for convenience
-template< typename Real, typename Device, typename Index, typename Communicator, typename ET,
-          typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > >
-auto
-dot( const Containers::DistributedVector< Real, Device, Index, Communicator >& a, const ET& b )
-{
-   return (a, b);
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Communicator,
-          typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > >
-auto
-dot( const ET& a, const Containers::DistributedVector< Real, Device, Index, Communicator >& b )
-{
-   return (a, b);
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-auto
-dot( const Containers::DistributedVector< Real1, Device, Index, Communicator >& a, const Containers::DistributedVector< Real2, Device, Index, Communicator >& b )
-{
-   return (a, b);
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-auto
-dot( const Containers::DistributedVectorView< Real1, Device, Index, Communicator >& a, const Containers::DistributedVector< Real2, Device, Index, Communicator >& b )
-{
-   return (a, b);
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-auto
-dot( const Containers::DistributedVector< Real1, Device, Index, Communicator >& a, const Containers::DistributedVectorView< Real2, Device, Index, Communicator >& b )
-{
-   return (a, b);
-}
-
-
-////
-// Abs
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-abs( const Containers::DistributedVector< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Abs >( a );
-}
-
-////
-// Power
-template< typename Real, typename Device, typename Index, typename Communicator, typename ExpType >
-auto
-pow( const Containers::DistributedVector< Real, Device, Index, Communicator >& a, const ExpType& exp )
-{
-   return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, ExpType, Containers::Expressions::Pow >( a, exp );
-}
-
-////
-// Exp
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-exp( const Containers::DistributedVector< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Exp >( a );
-}
-
-////
-// Sqrt
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-sqrt( const Containers::DistributedVector< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sqrt >( a );
-}
-
-////
-// Cbrt
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-cbrt( const Containers::DistributedVector< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Cbrt >( a );
-}
-
-////
-// Log
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-log( const Containers::DistributedVector< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Log >( a );
-}
-
-////
-// Log10
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-log10( const Containers::DistributedVector< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Log10 >( a );
-}
-
-////
-// Log2
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-log2( const Containers::DistributedVector< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Log2 >( a );
-}
-
-////
-// Sine
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-sin( const Containers::DistributedVector< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sin >( a );
-}
-
-////
-// Cosine
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-cos( const Containers::DistributedVector< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Cos >( a );
-}
-
-////
-// Tangent
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-tan( const Containers::DistributedVector< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Tan >( a );
-}
-
-////
-// Asin
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-asin( const Containers::DistributedVector< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Asin >( a );
-}
-
-////
-// Acos
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-acos( const Containers::DistributedVector< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Acos >( a );
-}
-
-////
-// Atan
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-atan( const Containers::DistributedVector< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Atan >( a );
-}
-
-////
-// Sinh
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-sinh( const Containers::DistributedVector< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sinh >( a );
-}
-
-////
-// Cosh
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-cosh( const Containers::DistributedVector< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Cosh >( a );
-}
-
-////
-// Tanh
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-tanh( const Containers::DistributedVector< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Tanh >( a );
-}
-
-////
-// Asinh
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-asinh( const Containers::DistributedVector< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Asinh >( a );
-}
-
-////
-// Acosh
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-acosh( const Containers::DistributedVector< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Acosh >( a );
-}
-
-////
-// Atanh
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-atanh( const Containers::DistributedVector< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Atanh >( a );
-}
-
-////
-// Floor
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-floor( const Containers::DistributedVector< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Floor >( a );
-}
-
-////
-// Ceil
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-ceil( const Containers::DistributedVector< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Ceil >( a );
-}
-
-////
-// Sign
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-sign( const Containers::DistributedVector< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sign >( a );
-}
-
-////
-// Cast
-template< typename ResultType, typename Real, typename Device, typename Index, typename Communicator,
-          // workaround: templated type alias cannot be declared at block level
-          template<typename> class Operation = Containers::Expressions::Cast< ResultType >::template Operation >
-auto
-cast( const Containers::DistributedVector< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Operation >( a );
-}
-
-////
-// Vertical operations - min
-template< typename Real,
-          typename Device,
-          typename Index, typename Communicator >
-Real
-min( const Containers::DistributedVector< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedExpressionMin( a );
-}
-
-template< typename Real,
-          typename Device,
-          typename Index, typename Communicator >
-std::pair< Index, std::decay_t< Real > >
-argMin( const Containers::DistributedVector< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedExpressionArgMin( a );
-}
-
-template< typename Real,
-          typename Device,
-          typename Index, typename Communicator >
-Real
-max( const Containers::DistributedVector< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedExpressionMax( a );
-}
-
-template< typename Real,
-          typename Device,
-          typename Index, typename Communicator >
-std::pair< Index, std::decay_t< Real > >
-argMax( const Containers::DistributedVector< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedExpressionArgMax( a );
-}
-
-template< typename Real,
-          typename Device,
-          typename Index, typename Communicator >
-auto
-sum( const Containers::DistributedVector< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedExpressionSum( a );
-}
-
-template< typename Real,
-          typename Device,
-          typename Index, typename Communicator >
-auto
-maxNorm( const Containers::DistributedVector< Real, Device, Index, Communicator >& a )
-{
-   return max( abs( a ) );
-}
-
-template< typename Real,
-          typename Device,
-          typename Index, typename Communicator >
-auto
-l1Norm( const Containers::DistributedVector< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedExpressionL1Norm( a );
-}
-
-template< typename Real,
-          typename Device,
-          typename Index, typename Communicator >
-auto
-l2Norm( const Containers::DistributedVector< Real, Device, Index, Communicator >& a )
-{
-   return TNL::sqrt( Containers::Expressions::DistributedExpressionL2Norm( a ) );
-}
-
-template< typename Real,
-          typename Device,
-          typename Index, typename Communicator,
-          typename Real2 >
-auto
-lpNorm( const Containers::DistributedVector< Real, Device, Index, Communicator >& a, const Real2& p )
-// since (1.0 / p) has type double, TNL::pow returns double
--> double
-{
-   if( p == 1.0 )
-      return l1Norm( a );
-   if( p == 2.0 )
-      return l2Norm( a );
-   return TNL::pow( Containers::Expressions::DistributedExpressionLpNorm( a, p ), 1.0 / p );
-}
-
-template< typename Real,
-          typename Device,
-          typename Index, typename Communicator >
-auto
-product( const Containers::DistributedVector< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedExpressionProduct( a );
-}
-
-template< typename Real,
-          typename Device,
-          typename Index, typename Communicator >
-auto
-logicalOr( const Containers::DistributedVector< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedExpressionLogicalOr( a );
-}
-
-template< typename Real,
-          typename Device,
-          typename Index, typename Communicator >
-auto
-binaryOr( const Containers::DistributedVector< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedExpressionBinaryOr( a );
-}
-
-template< typename Real,
-          typename Device,
-          typename Index, typename Communicator >
-auto
-logicalAnd( const Containers::DistributedVector< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedExpressionLogicalAnd( a );
-}
-
-template< typename Real,
-          typename Device,
-          typename Index, typename Communicator >
-auto
-binaryAnd( const Containers::DistributedVector< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedExpressionBinaryAnd( a );
-}
-
-} // namespace TNL
-#endif // DOXYGEN_ONLY
diff --git a/src/TNL/Containers/DistributedVectorView.h b/src/TNL/Containers/DistributedVectorView.h
index 70452c50d17b8a08004a3ad162005154eb228ba8..72bc7588120d0527f6d4505a231fe37b33ba2dce 100644
--- a/src/TNL/Containers/DistributedVectorView.h
+++ b/src/TNL/Containers/DistributedVectorView.h
@@ -13,6 +13,7 @@
 #pragma once
 
 #include <TNL/Containers/DistributedArrayView.h>
+#include <TNL/Containers/Expressions/DistributedExpressionTemplates.h>
 #include <TNL/Containers/VectorView.h>
 
 namespace TNL {
@@ -137,8 +138,15 @@ public:
    void scan( IndexType begin = 0, IndexType end = 0 );
 };
 
+// Enable expression templates for DistributedVector
+namespace Expressions {
+   template< typename Real, typename Device, typename Index, typename Communicator >
+   struct HasEnabledDistributedExpressionTemplates< DistributedVectorView< Real, Device, Index, Communicator > >
+   : std::true_type
+   {};
+} // namespace Expressions
+
 } // namespace Containers
 } // namespace TNL
 
 #include <TNL/Containers/DistributedVectorView.hpp>
-#include <TNL/Containers/DistributedVectorViewExpressions.h>
diff --git a/src/TNL/Containers/DistributedVectorViewExpressions.h b/src/TNL/Containers/DistributedVectorViewExpressions.h
deleted file mode 100644
index 27936df1021412705a0728c38e0ed2b82b73231b..0000000000000000000000000000000000000000
--- a/src/TNL/Containers/DistributedVectorViewExpressions.h
+++ /dev/null
@@ -1,718 +0,0 @@
-/***************************************************************************
-                          DistributedVectorViewExpressions.h  -  description
-                             -------------------
-    begin                : Jun 28, 2019
-    copyright            : (C) 2019 by Tomas Oberhuber et al.
-    email                : tomas.oberhuber@fjfi.cvut.cz
- ***************************************************************************/
-
-/* See Copyright Notice in tnl/Copyright */
-
-#pragma once
-#ifndef DOXYGEN_ONLY
-
-#include <TNL/Containers/Expressions/DistributedExpressionTemplates.h>
-#include <TNL/Exceptions/NotImplementedError.h>
-
-#include "DistributedVectorView.h"
-
-namespace TNL {
-namespace Containers {
-
-////
-// Addition
-template< typename Real, typename Device, typename Index, typename Communicator, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-auto
-operator+( const DistributedVectorView< Real, Device, Index, Communicator >& a, const ET& b )
-{
-   return Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, ET, Expressions::Addition >( a, b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Communicator,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-auto
-operator+( const ET& a, const DistributedVectorView< Real, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedBinaryExpressionTemplate< ET, std::decay_t<decltype(b)>, Expressions::Addition >( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-auto
-operator+( const DistributedVectorView< Real1, Device, Index, Communicator >& a, const DistributedVectorView< Real2, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Expressions::Addition >( a, b );
-}
-
-////
-// Subtraction
-template< typename Real, typename Device, typename Index, typename Communicator, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-auto
-operator-( const DistributedVectorView< Real, Device, Index, Communicator >& a, const ET& b )
-{
-   return Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, ET, Expressions::Subtraction >( a, b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Communicator,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-auto
-operator-( const ET& a, const DistributedVectorView< Real, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedBinaryExpressionTemplate< ET, std::decay_t<decltype(b)>, Expressions::Subtraction >( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-auto
-operator-( const DistributedVectorView< Real1, Device, Index, Communicator >& a, const DistributedVectorView< Real2, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Expressions::Subtraction >( a, b );
-}
-
-////
-// Multiplication
-template< typename Real, typename Device, typename Index, typename Communicator, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-auto
-operator*( const DistributedVectorView< Real, Device, Index, Communicator >& a, const ET& b )
-{
-   return Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, ET, Expressions::Multiplication >( a, b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Communicator,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-auto
-operator*( const ET& a, const DistributedVectorView< Real, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedBinaryExpressionTemplate< ET, std::decay_t<decltype(b)>, Expressions::Multiplication >( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-auto
-operator*( const DistributedVectorView< Real1, Device, Index, Communicator >& a, const DistributedVectorView< Real2, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Expressions::Multiplication >( a, b );
-}
-
-////
-// Division
-template< typename Real, typename Device, typename Index, typename Communicator, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-auto
-operator/( const DistributedVectorView< Real, Device, Index, Communicator >& a, const ET& b )
-{
-   return Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, ET, Expressions::Division >( a, b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Communicator,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-auto
-operator/( const ET& a, const DistributedVectorView< Real, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedBinaryExpressionTemplate< ET, std::decay_t<decltype(b)>, Expressions::Division >( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-auto
-operator/( const DistributedVectorView< Real1, Device, Index, Communicator >& a, const DistributedVectorView< Real2, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Expressions::Division >( a, b );
-}
-
-////
-// Comparison operations - operator ==
-template< typename Real, typename Device, typename Index, typename Communicator, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator==( const DistributedVectorView< Real, Device, Index, Communicator >& a, const ET& b )
-{
-   return Expressions::DistributedComparison< std::decay_t<decltype(a)>, ET >::EQ( a, b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Communicator,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator==( const ET& a, const DistributedVectorView< Real, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedComparison< ET, std::decay_t<decltype(b)> >::EQ( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device1, typename Device2, typename Index, typename Communicator >
-bool
-operator==( const DistributedVectorView< Real1, Device1, Index, Communicator >& a, const DistributedVectorView< Real2, Device2, Index, Communicator >& b )
-{
-   return Expressions::DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::EQ( a, b );
-}
-
-////
-// Comparison operations - operator !=
-template< typename Real, typename Device, typename Index, typename Communicator, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator!=( const DistributedVectorView< Real, Device, Index, Communicator >& a, const ET& b )
-{
-   return Expressions::DistributedComparison< std::decay_t<decltype(a)>, ET >::NE( a, b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Communicator,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator!=( const ET& a, const DistributedVectorView< Real, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedComparison< ET, std::decay_t<decltype(b)> >::NE( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device1, typename Device2, typename Index, typename Communicator >
-bool
-operator!=( const DistributedVectorView< Real1, Device1, Index, Communicator >& a, const DistributedVectorView< Real2, Device2, Index, Communicator >& b )
-{
-   return Expressions::DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b );
-}
-
-////
-// Comparison operations - operator <
-template< typename Real, typename Device, typename Index, typename Communicator, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator<( const DistributedVectorView< Real, Device, Index, Communicator >& a, const ET& b )
-{
-   return Expressions::DistributedComparison< std::decay_t<decltype(a)>, ET >::LT( a, b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Communicator,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator<( const ET& a, const DistributedVectorView< Real, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedComparison< ET, std::decay_t<decltype(b)> >::LT( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-bool
-operator<( const DistributedVectorView< Real1, Device, Index, Communicator >& a, const DistributedVectorView< Real2, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b );
-}
-
-////
-// Comparison operations - operator <=
-template< typename Real, typename Device, typename Index, typename Communicator, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator<=( const DistributedVectorView< Real, Device, Index, Communicator >& a, const ET& b )
-{
-   return Expressions::DistributedComparison< std::decay_t<decltype(a)>, ET >::LE( a, b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Communicator,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator<=( const ET& a, const DistributedVectorView< Real, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedComparison< ET, std::decay_t<decltype(b)> >::LE( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-bool
-operator<=( const DistributedVectorView< Real1, Device, Index, Communicator >& a, const DistributedVectorView< Real2, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b );
-}
-
-////
-// Comparison operations - operator >
-template< typename Real, typename Device, typename Index, typename Communicator, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator>( const DistributedVectorView< Real, Device, Index, Communicator >& a, const ET& b )
-{
-   return Expressions::DistributedComparison< std::decay_t<decltype(a)>, ET >::GT( a, b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Communicator,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator>( const ET& a, const DistributedVectorView< Real, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedComparison< ET, std::decay_t<decltype(b)> >::GT( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-bool
-operator>( const DistributedVectorView< Real1, Device, Index, Communicator >& a, const DistributedVectorView< Real2, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GT( a, b );
-}
-
-////
-// Comparison operations - operator >=
-template< typename Real, typename Device, typename Index, typename Communicator, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator>=( const DistributedVectorView< Real, Device, Index, Communicator >& a, const ET& b )
-{
-   return Expressions::DistributedComparison< std::decay_t<decltype(a)>, ET >::GE( a, b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Communicator,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator>=( const ET& a, const DistributedVectorView< Real, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedComparison< ET, std::decay_t<decltype(b)> >::GE( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-bool
-operator>=( const DistributedVectorView< Real1, Device, Index, Communicator >& a, const DistributedVectorView< Real2, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GE( a, b );
-}
-
-////
-// Minus
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-operator-( const DistributedVectorView< Real, Device, Index, Communicator >& a )
-{
-   return Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Expressions::Minus >( a );
-}
-
-////
-// Scalar product
-template< typename Real, typename Device, typename Index, typename Communicator, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-auto
-operator,( const DistributedVectorView< Real, Device, Index, Communicator >& a, const ET& b )
-{
-   return Expressions::DistributedExpressionSum( a * b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Communicator,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-auto
-operator,( const ET& a, const DistributedVectorView< Real, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedExpressionSum( a * b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-auto
-operator,( const DistributedVectorView< Real1, Device, Index, Communicator >& a, const DistributedVectorView< Real2, Device, Index, Communicator >& b )
-{
-   return Expressions::DistributedExpressionSum( a * b );
-}
-
-} // namespace Containers
-
-////
-// All functions are supposed to be in namespace TNL
-
-////
-// Min
-template< typename Real, typename Device, typename Index, typename Communicator, typename ET,
-          typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > >
-auto
-min( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a, const ET& b )
-{
-   return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, ET, Containers::Expressions::Min >( a, b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Communicator,
-          typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > >
-auto
-min( const ET& a, const Containers::DistributedVectorView< Real, Device, Index, Communicator >& b )
-{
-   return Containers::Expressions::DistributedBinaryExpressionTemplate< ET, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-auto
-min( const Containers::DistributedVectorView< Real1, Device, Index, Communicator >& a, const Containers::DistributedVectorView< Real2, Device, Index, Communicator >& b )
-{
-   return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b );
-}
-
-////
-// Max
-template< typename Real, typename Device, typename Index, typename Communicator, typename ET,
-          typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > >
-auto
-max( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a, const ET& b )
-{
-   return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, ET, Containers::Expressions::Max >( a, b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Communicator,
-          typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > >
-auto
-max( const ET& a, const Containers::DistributedVectorView< Real, Device, Index, Communicator >& b )
-{
-   return Containers::Expressions::DistributedBinaryExpressionTemplate< ET, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator >
-auto
-max( const Containers::DistributedVectorView< Real1, Device, Index, Communicator >& a, const Containers::DistributedVectorView< Real2, Device, Index, Communicator >& b )
-{
-   return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b );
-}
-
-////
-// Dot product - the same as scalar product, just for convenience
-template< typename Real, typename Device, typename Index, typename Communicator, typename ET,
-          typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > >
-auto
-dot( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a, const ET& b )
-{
-   return (a, b);
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Communicator,
-          typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > >
-auto
-dot( const ET& a, const Containers::DistributedVectorView< Real, Device, Index, Communicator >& b )
-{
-   return (a, b);
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index1, typename Index2, typename Communicator >
-auto
-dot( const Containers::DistributedVectorView< Real1, Device, Index1, Communicator >& a, const Containers::DistributedVectorView< Real2, Device, Index2, Communicator >& b )
-{
-   return (a, b);
-}
-
-////
-// Abs
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-abs( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Abs >( a );
-}
-
-
-////
-// Power
-template< typename Real, typename Device, typename Index, typename Communicator, typename ExpType >
-auto
-pow( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a, const ExpType& exp )
-{
-   return Containers::Expressions::DistributedBinaryExpressionTemplate< Containers::DistributedVectorView< Real, Device, Index, Communicator >, ExpType, Containers::Expressions::Pow >( a, exp );
-}
-
-////
-// Exp
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-exp( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Exp >( a );
-}
-
-////
-// Sqrt
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-sqrt( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sqrt >( a );
-}
-
-////
-// Cbrt
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-cbrt( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Cbrt >( a );
-}
-
-////
-// Log
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-log( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Log >( a );
-}
-
-////
-// Log10
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-log10( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Log10 >( a );
-}
-
-////
-// Log2
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-log2( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Log2 >( a );
-}
-
-////
-// Sine
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-sin( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sin >( a );
-}
-
-////
-// Cosine
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-cos( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Cos >( a );
-}
-
-////
-// Tangent
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-tan( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Tan >( a );
-}
-
-////
-// Asin
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-asin( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Asin >( a );
-}
-
-////
-// Acos
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-acos( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Acos >( a );
-}
-
-////
-// Atan
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-atan( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Atan >( a );
-}
-
-////
-// Sinh
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-sinh( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sinh >( a );
-}
-
-////
-// Cosh
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-cosh( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Cosh >( a );
-}
-
-////
-// Tanh
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-tanh( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Tanh >( a );
-}
-
-////
-// Asinh
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-asinh( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Asinh >( a );
-}
-
-////
-// Acosh
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-acosh( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Acosh >( a );
-}
-
-////
-// Atanh
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-atanh( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Atanh >( a );
-}
-
-////
-// Floor
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-floor( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Floor >( a );
-}
-
-////
-// Ceil
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-ceil( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Ceil >( a );
-}
-
-////
-// Sign
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-sign( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sign >( a );
-}
-
-////
-// Cast
-template< typename ResultType, typename Real, typename Device, typename Index, typename Communicator,
-          // workaround: templated type alias cannot be declared at block level
-          template<typename> class Operation = Containers::Expressions::Cast< ResultType >::template Operation >
-auto
-cast( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Operation >( a );
-}
-
-////
-// Vertical operations - min
-template< typename Real, typename Device, typename Index, typename Communicator >
-Real
-min( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedExpressionMin( a );
-}
-
-template< typename Real, typename Device, typename Index, typename Communicator >
-std::pair< Index, std::decay_t< Real > >
-argMin( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedExpressionArgMin( a );
-}
-
-template< typename Real, typename Device, typename Index, typename Communicator >
-Real
-max( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedExpressionMax( a );
-}
-
-template< typename Real, typename Device, typename Index, typename Communicator >
-std::pair< Index, std::decay_t< Real > >
-argMax( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedExpressionArgMax( a );
-}
-
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-sum( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedExpressionSum( a );
-}
-
-template< typename Real,
-          typename Device,
-          typename Index, typename Communicator >
-auto
-maxNorm( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a )
-{
-   return max( abs( a ) );
-}
-
-template< typename Real,
-          typename Device,
-          typename Index, typename Communicator >
-auto
-l1Norm( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedExpressionL1Norm( a );
-}
-
-template< typename Real,
-          typename Device,
-          typename Index, typename Communicator >
-auto
-l2Norm( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a )
-{
-   return TNL::sqrt( Containers::Expressions::DistributedExpressionL2Norm( a ) );
-}
-
-template< typename Real, typename Device, typename Index, typename Communicator, typename Real2 >
-auto
-lpNorm( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a, const Real2& p )
-// since (1.0 / p) has type double, TNL::pow returns double
--> double
-{
-   if( p == 1.0 )
-      return l1Norm( a );
-   if( p == 2.0 )
-      return l2Norm( a );
-   return TNL::pow( Containers::Expressions::DistributedExpressionLpNorm( a, p ), 1.0 / p );
-}
-
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-product( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedExpressionProduct( a );
-}
-
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-logicalOr( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedExpressionLogicalOr( a );
-}
-
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-binaryOr( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedExpressionBinaryOr( a );
-}
-
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-logicalAnd( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedExpressionLogicalAnd( a );
-}
-
-template< typename Real, typename Device, typename Index, typename Communicator >
-auto
-binaryAnd( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a )
-{
-   return Containers::Expressions::DistributedExpressionBinaryAnd( a );
-}
-
-} // namespace TNL
-#endif // DOXYGEN_ONLY
diff --git a/src/TNL/Containers/Expressions/Comparison.h b/src/TNL/Containers/Expressions/Comparison.h
index 98e39ad8c561240f2ac0522844dd362059ebf710..40b823a1840e6b5d5458f18bbf3e2e9341b2403c 100644
--- a/src/TNL/Containers/Expressions/Comparison.h
+++ b/src/TNL/Containers/Expressions/Comparison.h
@@ -25,13 +25,14 @@ namespace Expressions {
 // Non-static comparison
 template< typename T1,
           typename T2,
-          ExpressionVariableType T1Type = ExpressionVariableTypeGetter< T1 >::value,
-          ExpressionVariableType T2Type = ExpressionVariableTypeGetter< T2 >::value >
+          ExpressionVariableType T1Type = getExpressionVariableType< T1, T2 >(),
+          ExpressionVariableType T2Type = getExpressionVariableType< T2, T1 >() >
 struct Comparison;
 
 template< typename T1,
           typename T2,
-          bool BothAreVectors = IsArrayType< T1 >::value && IsArrayType< T2 >::value >
+          bool BothAreNonstaticVectors = IsArrayType< T1 >::value && IsArrayType< T2 >::value &&
+                                       ! IsStaticArrayType< T1 >::value && ! IsStaticArrayType< T2 >::value >
 struct VectorComparison;
 
 // If both operands are vectors we compare them using array operations.
@@ -64,7 +65,9 @@ struct VectorComparison< T1, T2, false >
       using DeviceType = typename T1::DeviceType;
       using IndexType = typename T1::IndexType;
 
-      auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return a[ i ] == b[ i ]; };
+      const auto view_a = a.getConstView();
+      const auto view_b = b.getConstView();
+      auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return view_a[ i ] == view_b[ i ]; };
       return Algorithms::Reduction< DeviceType >::reduce( a.getSize(), std::logical_and<>{}, fetch, true );
    }
 };
@@ -94,7 +97,9 @@ struct Comparison< T1, T2, VectorExpressionVariable, VectorExpressionVariable >
       using DeviceType = typename T1::DeviceType;
       using IndexType = typename T1::IndexType;
 
-      auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return a[ i ] > b[ i ]; };
+      const auto view_a = a.getConstView();
+      const auto view_b = b.getConstView();
+      auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return view_a[ i ] > view_b[ i ]; };
       return Algorithms::Reduction< DeviceType >::reduce( a.getSize(), std::logical_and<>{}, fetch, true );
    }
 
@@ -107,7 +112,9 @@ struct Comparison< T1, T2, VectorExpressionVariable, VectorExpressionVariable >
       using DeviceType = typename T1::DeviceType;
       using IndexType = typename T1::IndexType;
 
-      auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return a[ i ] >= b[ i ]; };
+      const auto view_a = a.getConstView();
+      const auto view_b = b.getConstView();
+      auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return view_a[ i ] >= view_b[ i ]; };
       return Algorithms::Reduction< DeviceType >::reduce( a.getSize(), std::logical_and<>{}, fetch, true );
    }
 
@@ -120,7 +127,9 @@ struct Comparison< T1, T2, VectorExpressionVariable, VectorExpressionVariable >
       using DeviceType = typename T1::DeviceType;
       using IndexType = typename T1::IndexType;
 
-      auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return a[ i ] < b[ i ]; };
+      const auto view_a = a.getConstView();
+      const auto view_b = b.getConstView();
+      auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return view_a[ i ] < view_b[ i ]; };
       return Algorithms::Reduction< DeviceType >::reduce( a.getSize(), std::logical_and<>{}, fetch, true );
    }
 
@@ -133,7 +142,9 @@ struct Comparison< T1, T2, VectorExpressionVariable, VectorExpressionVariable >
       using DeviceType = typename T1::DeviceType;
       using IndexType = typename T1::IndexType;
 
-      auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return a[ i ] <= b[ i ]; };
+      const auto view_a = a.getConstView();
+      const auto view_b = b.getConstView();
+      auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return view_a[ i ] <= view_b[ i ]; };
       return Algorithms::Reduction< DeviceType >::reduce( a.getSize(), std::logical_and<>{}, fetch, true );
    }
 };
@@ -149,7 +160,8 @@ struct Comparison< T1, T2, ArithmeticVariable, VectorExpressionVariable >
       using DeviceType = typename T2::DeviceType;
       using IndexType = typename T2::IndexType;
 
-      auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return a == b[ i ]; };
+      const auto view_b = b.getConstView();
+      auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return a == view_b[ i ]; };
       return Algorithms::Reduction< DeviceType >::reduce( b.getSize(), std::logical_and<>{}, fetch, true );
    }
 
@@ -163,7 +175,8 @@ struct Comparison< T1, T2, ArithmeticVariable, VectorExpressionVariable >
       using DeviceType = typename T2::DeviceType;
       using IndexType = typename T2::IndexType;
 
-      auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return a > b[ i ]; };
+      const auto view_b = b.getConstView();
+      auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return a > view_b[ i ]; };
       return Algorithms::Reduction< DeviceType >::reduce( b.getSize(), std::logical_and<>{}, fetch, true );
    }
 
@@ -172,7 +185,8 @@ struct Comparison< T1, T2, ArithmeticVariable, VectorExpressionVariable >
       using DeviceType = typename T2::DeviceType;
       using IndexType = typename T2::IndexType;
 
-      auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return a >= b[ i ]; };
+      const auto view_b = b.getConstView();
+      auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return a >= view_b[ i ]; };
       return Algorithms::Reduction< DeviceType >::reduce( b.getSize(), std::logical_and<>{}, fetch, true );
    }
 
@@ -181,7 +195,8 @@ struct Comparison< T1, T2, ArithmeticVariable, VectorExpressionVariable >
       using DeviceType = typename T2::DeviceType;
       using IndexType = typename T2::IndexType;
 
-      auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return a < b[ i ]; };
+      const auto view_b = b.getConstView();
+      auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return a < view_b[ i ]; };
       return Algorithms::Reduction< DeviceType >::reduce( b.getSize(), std::logical_and<>{}, fetch, true );
    }
 
@@ -190,7 +205,8 @@ struct Comparison< T1, T2, ArithmeticVariable, VectorExpressionVariable >
       using DeviceType = typename T2::DeviceType;
       using IndexType = typename T2::IndexType;
 
-      auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return a <= b[ i ]; };
+      const auto view_b = b.getConstView();
+      auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return a <= view_b[ i ]; };
       return Algorithms::Reduction< DeviceType >::reduce( b.getSize(), std::logical_and<>{}, fetch, true );
    }
 };
@@ -206,7 +222,8 @@ struct Comparison< T1, T2, VectorExpressionVariable, ArithmeticVariable >
       using DeviceType = typename T1::DeviceType;
       using IndexType = typename T1::IndexType;
 
-      auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return a[ i ] == b; };
+      const auto view_a = a.getConstView();
+      auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return view_a[ i ] == b; };
       return Algorithms::Reduction< DeviceType >::reduce( a.getSize(), std::logical_and<>{}, fetch, true );
    }
 
@@ -220,7 +237,8 @@ struct Comparison< T1, T2, VectorExpressionVariable, ArithmeticVariable >
       using DeviceType = typename T1::DeviceType;
       using IndexType = typename T1::IndexType;
 
-      auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return a[ i ] > b; };
+      const auto view_a = a.getConstView();
+      auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return view_a[ i ] > b; };
       return Algorithms::Reduction< DeviceType >::reduce( a.getSize(), std::logical_and<>{}, fetch, true );
    }
 
@@ -229,7 +247,8 @@ struct Comparison< T1, T2, VectorExpressionVariable, ArithmeticVariable >
       using DeviceType = typename T1::DeviceType;
       using IndexType = typename T1::IndexType;
 
-      auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return a[ i ] >= b; };
+      const auto view_a = a.getConstView();
+      auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return view_a[ i ] >= b; };
       return Algorithms::Reduction< DeviceType >::reduce( a.getSize(), std::logical_and<>{}, fetch, true );
    }
 
@@ -238,7 +257,8 @@ struct Comparison< T1, T2, VectorExpressionVariable, ArithmeticVariable >
       using DeviceType = typename T1::DeviceType;
       using IndexType = typename T1::IndexType;
 
-      auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return a[ i ] < b; };
+      const auto view_a = a.getConstView();
+      auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return view_a[ i ] < b; };
       return Algorithms::Reduction< DeviceType >::reduce( a.getSize(), std::logical_and<>{}, fetch, true );
    }
 
@@ -247,7 +267,8 @@ struct Comparison< T1, T2, VectorExpressionVariable, ArithmeticVariable >
       using DeviceType = typename T1::DeviceType;
       using IndexType = typename T1::IndexType;
 
-      auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return a[ i ] <= b; };
+      const auto view_a = a.getConstView();
+      auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return view_a[ i ] <= b; };
       return Algorithms::Reduction< DeviceType >::reduce( a.getSize(), std::logical_and<>{}, fetch, true );
    }
 };
diff --git a/src/TNL/Containers/Expressions/DistributedComparison.h b/src/TNL/Containers/Expressions/DistributedComparison.h
index b5e0e96a9d756f55edb7bf15652ad1d0d34bc5d6..4cecc92bb9b3823db92df893c289c0233d26bb14 100644
--- a/src/TNL/Containers/Expressions/DistributedComparison.h
+++ b/src/TNL/Containers/Expressions/DistributedComparison.h
@@ -21,8 +21,8 @@ namespace Expressions {
 // Non-static comparison
 template< typename T1,
           typename T2,
-          ExpressionVariableType T1Type = ExpressionVariableTypeGetter< T1 >::value,
-          ExpressionVariableType T2Type = ExpressionVariableTypeGetter< T2 >::value >
+          ExpressionVariableType T1Type = getExpressionVariableType< T1, T2 >(),
+          ExpressionVariableType T2Type = getExpressionVariableType< T2, T1 >() >
 struct DistributedComparison;
 
 /////
diff --git a/src/TNL/Containers/Expressions/DistributedExpressionTemplates.h b/src/TNL/Containers/Expressions/DistributedExpressionTemplates.h
index 355689039884e8e05caff040e232ffbcf26119ba..1802dcc9553e81c7b31c0e792d6d368a4e743c8d 100644
--- a/src/TNL/Containers/Expressions/DistributedExpressionTemplates.h
+++ b/src/TNL/Containers/Expressions/DistributedExpressionTemplates.h
@@ -22,15 +22,12 @@ namespace Expressions {
 ////
 // Distributed unary expression template
 template< typename T1,
-          template< typename > class Operation,
-          ExpressionVariableType T1Type = ExpressionVariableTypeGetter< T1 >::value >
-struct DistributedUnaryExpressionTemplate
-{};
+          typename Operation >
+struct DistributedUnaryExpressionTemplate;
 
 template< typename T1,
-          template< typename > class Operation,
-          ExpressionVariableType T1Type >
-struct IsExpressionTemplate< DistributedUnaryExpressionTemplate< T1, Operation, T1Type > >
+          typename Operation >
+struct HasEnabledDistributedExpressionTemplates< DistributedUnaryExpressionTemplate< T1, Operation > >
 : std::true_type
 {};
 
@@ -38,28 +35,27 @@ struct IsExpressionTemplate< DistributedUnaryExpressionTemplate< T1, Operation,
 // Distributed binary expression template
 template< typename T1,
           typename T2,
-          template< typename, typename > class Operation,
-          ExpressionVariableType T1Type = ExpressionVariableTypeGetter< T1 >::value,
-          ExpressionVariableType T2Type = ExpressionVariableTypeGetter< T2 >::value >
+          typename Operation,
+          ExpressionVariableType T1Type = getExpressionVariableType< T1, T2 >(),
+          ExpressionVariableType T2Type = getExpressionVariableType< T2, T1 >() >
 struct DistributedBinaryExpressionTemplate
 {};
 
 template< typename T1,
           typename T2,
-          template< typename, typename > class Operation,
+          typename Operation,
           ExpressionVariableType T1Type,
           ExpressionVariableType T2Type >
-struct IsExpressionTemplate< DistributedBinaryExpressionTemplate< T1, T2, Operation, T1Type, T2Type > >
+struct HasEnabledDistributedExpressionTemplates< DistributedBinaryExpressionTemplate< T1, T2, Operation, T1Type, T2Type > >
 : std::true_type
 {};
 
 template< typename T1,
           typename T2,
-          template< typename, typename > class Operation >
+          typename Operation >
 struct DistributedBinaryExpressionTemplate< T1, T2, Operation, VectorExpressionVariable, VectorExpressionVariable >
 {
-   using RealType = decltype( Operation< typename T1::RealType, typename T2::RealType >::
-                              evaluate( std::declval<T1>()[0], std::declval<T2>()[0] ) );
+   using RealType = decltype( Operation::evaluate( std::declval<T1>()[0], std::declval<T2>()[0] ) );
    using DeviceType = typename T1::DeviceType;
    using IndexType = typename T1::IndexType;
    using CommunicatorType = typename T1::CommunicatorType;
@@ -69,10 +65,12 @@ struct DistributedBinaryExpressionTemplate< T1, T2, Operation, VectorExpressionV
                                                         typename T2::ConstLocalViewType,
                                                         Operation >;
 
+   static_assert( HasEnabledDistributedExpressionTemplates< T1 >::value,
+                  "Invalid operand in distributed binary expression templates - distributed expression templates are not enabled for the left operand." );
+   static_assert( HasEnabledDistributedExpressionTemplates< T2 >::value,
+                  "Invalid operand in distributed binary expression templates - distributed expression templates are not enabled for the right operand." );
    static_assert( std::is_same< typename T1::DeviceType, typename T2::DeviceType >::value,
                   "Attempt to mix operands which have different DeviceType." );
-   static_assert( IsStaticArrayType< T1 >::value == IsStaticArrayType< T2 >::value,
-                  "Attempt to mix static and non-static operands in binary expression templates." );
 
    DistributedBinaryExpressionTemplate( const T1& a, const T2& b )
    : op1( a ), op2( b )
@@ -124,11 +122,10 @@ protected:
 
 template< typename T1,
           typename T2,
-          template< typename, typename > class Operation >
+          typename Operation >
 struct DistributedBinaryExpressionTemplate< T1, T2, Operation, VectorExpressionVariable, ArithmeticVariable >
 {
-   using RealType = decltype( Operation< typename T1::RealType, T2 >::
-                              evaluate( std::declval<T1>()[0], std::declval<T2>() ) );
+   using RealType = decltype( Operation::evaluate( std::declval<T1>()[0], std::declval<T2>() ) );
    using DeviceType = typename T1::DeviceType;
    using IndexType = typename T1::IndexType;
    using CommunicatorType = typename T1::CommunicatorType;
@@ -136,6 +133,9 @@ struct DistributedBinaryExpressionTemplate< T1, T2, Operation, VectorExpressionV
    using LocalRangeType = typename T1::LocalRangeType;
    using ConstLocalViewType = BinaryExpressionTemplate< typename T1::ConstLocalViewType, T2, Operation >;
 
+   static_assert( HasEnabledDistributedExpressionTemplates< T1 >::value,
+                  "Invalid operand in distributed binary expression templates - distributed expression templates are not enabled for the left operand." );
+
    DistributedBinaryExpressionTemplate( const T1& a, const T2& b )
    : op1( a ), op2( b ) {}
 
@@ -178,11 +178,10 @@ protected:
 
 template< typename T1,
           typename T2,
-          template< typename, typename > class Operation >
+          typename Operation >
 struct DistributedBinaryExpressionTemplate< T1, T2, Operation, ArithmeticVariable, VectorExpressionVariable >
 {
-   using RealType = decltype( Operation< T1, typename T2::RealType >::
-                              evaluate( std::declval<T1>(), std::declval<T2>()[0] ) );
+   using RealType = decltype( Operation::evaluate( std::declval<T1>(), std::declval<T2>()[0] ) );
    using DeviceType = typename T2::DeviceType;
    using IndexType = typename T2::IndexType;
    using CommunicatorType = typename T2::CommunicatorType;
@@ -190,6 +189,9 @@ struct DistributedBinaryExpressionTemplate< T1, T2, Operation, ArithmeticVariabl
    using LocalRangeType = typename T2::LocalRangeType;
    using ConstLocalViewType = BinaryExpressionTemplate< T1, typename T2::ConstLocalViewType, Operation >;
 
+   static_assert( HasEnabledDistributedExpressionTemplates< T2 >::value,
+                  "Invalid operand in distributed binary expression templates - distributed expression templates are not enabled for the right operand." );
+
    DistributedBinaryExpressionTemplate( const T1& a, const T2& b )
    : op1( a ), op2( b ) {}
 
@@ -233,11 +235,10 @@ protected:
 ////
 // Distributed unary expression template
 template< typename T1,
-          template< typename > class Operation >
-struct DistributedUnaryExpressionTemplate< T1, Operation, VectorExpressionVariable >
+          typename Operation >
+struct DistributedUnaryExpressionTemplate
 {
-   using RealType = decltype( Operation< typename T1::RealType >::
-                              evaluate( std::declval<T1>()[0] ) );
+   using RealType = decltype( Operation::evaluate( std::declval<T1>()[0] ) );
    using DeviceType = typename T1::DeviceType;
    using IndexType = typename T1::IndexType;
    using CommunicatorType = typename T1::CommunicatorType;
@@ -245,6 +246,9 @@ struct DistributedUnaryExpressionTemplate< T1, Operation, VectorExpressionVariab
    using LocalRangeType = typename T1::LocalRangeType;
    using ConstLocalViewType = UnaryExpressionTemplate< typename T1::ConstLocalViewType, Operation >;
 
+   static_assert( HasEnabledDistributedExpressionTemplates< T1 >::value,
+                  "Invalid operand in distributed unary expression templates - distributed expression templates are not enabled for the operand." );
+
    DistributedUnaryExpressionTemplate( const T1& a )
    : operand( a ) {}
 
@@ -284,1916 +288,656 @@ protected:
    const T1& operand;
 };
 
-////
-// Output stream
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-std::ostream& operator<<( std::ostream& str, const DistributedBinaryExpressionTemplate< T1, T2, Operation >& expression )
-{
-   str << "[ ";
-   for( int i = 0; i < expression.getSize() - 1; i++ )
-      str << expression.getElement( i ) << ", ";
-   str << expression.getElement( expression.getSize() - 1 ) << " ]";
-   return str;
-}
-
-template< typename T,
-          template< typename > class Operation >
-std::ostream& operator<<( std::ostream& str, const DistributedUnaryExpressionTemplate< T, Operation >& expression )
-{
-   str << "[ ";
-   for( int i = 0; i < expression.getSize() - 1; i++ )
-      str << expression.getElement( i ) << ", ";
-   str << expression.getElement( expression.getSize() - 1 ) << " ]";
-   return str;
-}
-
-////
-// Operators are supposed to be in the same namespace as the expression templates
-
 #ifndef DOXYGEN_ONLY
 
 ////
 // Binary expressions addition
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfDistributedBinaryExpression_t< ET1, ET2 >, typename = void, typename = void >
 auto
-operator+( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b )
+operator+( const ET1& a, const ET2& b )
 {
-   return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Addition >( a, b );
+   return DistributedBinaryExpressionTemplate< ET1, ET2, Addition >( a, b );
 }
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
+////
+// Binary expression subtraction
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfDistributedBinaryExpression_t< ET1, ET2 >, typename = void, typename = void >
 auto
-operator+( const DistributedBinaryExpressionTemplate< T1, T2, Operation >& a,
-           const typename DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
+operator-( const ET1& a, const ET2& b )
 {
-   return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Addition >( a, b );
+   return DistributedBinaryExpressionTemplate< ET1, ET2, Subtraction >( a, b );
 }
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
+////
+// Binary expression multiplication
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfDistributedBinaryExpression_t< ET1, ET2 >, typename = void, typename = void >
 auto
-operator+( const typename DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-           const DistributedBinaryExpressionTemplate< T1, T2, Operation >& b )
+operator*( const ET1& a, const ET2& b )
 {
-   return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Addition >( a, b );
+   return DistributedBinaryExpressionTemplate< ET1, ET2, Multiplication >( a, b );
 }
 
-template< typename T1,
-          template< typename > class Operation >
+////
+// Binary expression division
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfDistributedBinaryExpression_t< ET1, ET2 >, typename = void, typename = void >
 auto
-operator+( const DistributedUnaryExpressionTemplate< T1, Operation >& a,
-           const typename DistributedUnaryExpressionTemplate< T1, Operation >::RealType& b )
+operator/( const ET1& a, const ET2& b )
 {
-   return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Addition >( a, b );
+   return DistributedBinaryExpressionTemplate< ET1, ET2, Division >( a, b );
 }
 
-template< typename T1,
-          template< typename > class Operation >
-auto
-operator+( const typename DistributedUnaryExpressionTemplate< T1, Operation >::RealType& a,
-           const DistributedUnaryExpressionTemplate< T1, Operation >& b )
+////
+// Comparison operator ==
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfDistributedBinaryExpression_t< ET1, ET2 >, typename = void, typename = void >
+bool
+operator==( const ET1& a, const ET2& b )
 {
-   return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Addition >( a, b );
+   return DistributedComparison< ET1, ET2 >::EQ( a, b );
 }
 
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-auto
-operator+( const DistributedUnaryExpressionTemplate< L1, LOperation >& a,
-           const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b )
+////
+// Comparison operator !=
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfDistributedBinaryExpression_t< ET1, ET2 >, typename = void, typename = void >
+bool
+operator!=( const ET1& a, const ET2& b )
 {
-   return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Addition >( a, b );
+   return DistributedComparison< ET1, ET2 >::NE( a, b );
 }
 
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-auto
-operator+( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const DistributedUnaryExpressionTemplate< R1,ROperation >& b )
+////
+// Comparison operator <
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfDistributedBinaryExpression_t< ET1, ET2 >, typename = void, typename = void >
+bool
+operator<( const ET1& a, const ET2& b )
 {
-   return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Addition >( a, b );
+   return DistributedComparison< ET1, ET2 >::LT( a, b );
 }
 
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-auto
-operator+( const DistributedUnaryExpressionTemplate< L1,LOperation >& a,
-           const DistributedUnaryExpressionTemplate< R1,ROperation >& b )
+////
+// Comparison operator <=
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfDistributedBinaryExpression_t< ET1, ET2 >, typename = void, typename = void >
+bool
+operator<=( const ET1& a, const ET2& b )
 {
-   return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Addition >( a, b );
+   return DistributedComparison< ET1, ET2 >::LE( a, b );
 }
 
 ////
-// Binary expression subtraction
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-auto
-operator-( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b )
+// Comparison operator >
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfDistributedBinaryExpression_t< ET1, ET2 >, typename = void, typename = void >
+bool
+operator>( const ET1& a, const ET2& b )
 {
-   return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Subtraction >( a, b );
+   return DistributedComparison< ET1, ET2 >::GT( a, b );
 }
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-auto
-operator-( const DistributedBinaryExpressionTemplate< T1, T2, Operation >& a,
-           const typename DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
+////
+// Comparison operator >=
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfDistributedBinaryExpression_t< ET1, ET2 >, typename = void, typename = void >
+bool
+operator>=( const ET1& a, const ET2& b )
 {
-   return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Subtraction >( a, b );
+   return DistributedComparison< ET1, ET2 >::GE( a, b );
 }
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
+////
+// Scalar product
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfDistributedBinaryExpression_t< ET1, ET2 >, typename = void, typename = void >
 auto
-operator-( const typename DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-           const DistributedBinaryExpressionTemplate< T1, T2, Operation >& b )
+operator,( const ET1& a, const ET2& b )
 {
-   return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Subtraction >( a, b );
+   return DistributedExpressionSum( a * b );
 }
 
-template< typename T1,
-          template< typename > class Operation >
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfDistributedBinaryExpression_t< ET1, ET2 >, typename = void, typename = void >
 auto
-operator-( const DistributedUnaryExpressionTemplate< T1, Operation >& a,
-           const typename DistributedUnaryExpressionTemplate< T1, Operation >::RealType& b )
+dot( const ET1& a, const ET2& b )
 {
-   return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Subtraction >( a, b );
+   return (a, b);
 }
 
-template< typename T1,
-          template< typename > class Operation >
+////
+// Unary expression minus
+template< typename ET1,
+          typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void >
 auto
-operator-( const typename DistributedUnaryExpressionTemplate< T1, Operation >::RealType& a,
-           const DistributedUnaryExpressionTemplate< T1, Operation >& b )
+operator-( const ET1& a )
 {
-   return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Subtraction >( a, b );
+   return DistributedUnaryExpressionTemplate< ET1, Minus >( a );
 }
 
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
+////
+// Binary expression min
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfDistributedBinaryExpression_t< ET1, ET2 >, typename = void, typename = void >
 auto
-operator-( const DistributedUnaryExpressionTemplate< L1, LOperation >& a,
-           const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b )
+min( const ET1& a, const ET2& b )
 {
-   return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Subtraction >( a, b );
+   return DistributedBinaryExpressionTemplate< ET1, ET2, Min >( a, b );
 }
 
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
+////
+// Binary expression max
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfDistributedBinaryExpression_t< ET1, ET2 >, typename = void, typename = void >
 auto
-operator-( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const DistributedUnaryExpressionTemplate< R1,ROperation >& b )
+max( const ET1& a, const ET2& b )
 {
-   return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Subtraction >( a, b );
+   return DistributedBinaryExpressionTemplate< ET1, ET2, Max >( a, b );
 }
 
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
+////
+// Abs
+template< typename ET1,
+          typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void >
 auto
-operator-( const DistributedUnaryExpressionTemplate< L1,LOperation >& a,
-           const DistributedUnaryExpressionTemplate< R1,ROperation >& b )
+abs( const ET1& a )
 {
-   return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Subtraction >( a, b );
+   return DistributedUnaryExpressionTemplate< ET1, Abs >( a );
 }
 
 ////
-// Binary expression multiplication
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
+// Pow
+template< typename ET1, typename Real,
+          typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void >
 auto
-operator*( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b )
+pow( const ET1& a, const Real& exp )
 {
-   return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Multiplication >( a, b );
+   return DistributedBinaryExpressionTemplate< ET1, Real, Pow >( a, exp );
 }
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
+////
+// Exp
+template< typename ET1,
+          typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void >
 auto
-operator*( const DistributedBinaryExpressionTemplate< T1, T2, Operation >& a,
-           const typename DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
+exp( const ET1& a )
 {
-   return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Multiplication >( a, b );
+   return DistributedUnaryExpressionTemplate< ET1, Exp >( a );
 }
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
+////
+// Sqrt
+template< typename ET1,
+          typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void >
 auto
-operator*( const typename DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-           const DistributedBinaryExpressionTemplate< T1, T2, Operation >& b )
+sqrt( const ET1& a )
 {
-   return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Multiplication >( a, b );
+   return DistributedUnaryExpressionTemplate< ET1, Sqrt >( a );
 }
 
-template< typename T1,
-          template< typename > class Operation >
+////
+// Cbrt
+template< typename ET1,
+          typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void >
 auto
-operator*( const DistributedUnaryExpressionTemplate< T1, Operation >& a,
-           const typename DistributedUnaryExpressionTemplate< T1, Operation >::RealType& b )
+cbrt( const ET1& a )
 {
-   return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Multiplication >( a, b );
+   return DistributedUnaryExpressionTemplate< ET1, Cbrt >( a );
 }
 
-template< typename T1,
-          template< typename > class Operation >
+////
+// Log
+template< typename ET1,
+          typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void >
 auto
-operator*( const typename DistributedUnaryExpressionTemplate< T1, Operation >::RealType& a,
-           const DistributedUnaryExpressionTemplate< T1, Operation >& b )
+log( const ET1& a )
 {
-   return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Multiplication >( a, b );
+   return DistributedUnaryExpressionTemplate< ET1, Log >( a );
 }
 
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
+////
+// Log10
+template< typename ET1,
+          typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void >
 auto
-operator*( const DistributedUnaryExpressionTemplate< L1, LOperation >& a,
-           const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b )
+log10( const ET1& a )
 {
-   return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Multiplication >( a, b );
+   return DistributedUnaryExpressionTemplate< ET1, Log10 >( a );
 }
 
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
+////
+// Log2
+template< typename ET1,
+          typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void >
 auto
-operator*( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const DistributedUnaryExpressionTemplate< R1, ROperation >& b )
+log2( const ET1& a )
 {
-   return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Multiplication >( a, b );
+   return DistributedUnaryExpressionTemplate< ET1, Log2 >( a );
 }
 
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
+////
+// Sin
+template< typename ET1,
+          typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void >
 auto
-operator*( const DistributedUnaryExpressionTemplate< L1,LOperation >& a,
-           const DistributedUnaryExpressionTemplate< R1,ROperation >& b )
+sin( const ET1& a )
 {
-   return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Multiplication >( a, b );
+   return DistributedUnaryExpressionTemplate< ET1, Sin >( a );
 }
 
 ////
-// Binary expression division
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
+// Cos
+template< typename ET1,
+          typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void >
 auto
-operator/( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b )
+cos( const ET1& a )
 {
-   return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Division >( a, b );
+   return DistributedUnaryExpressionTemplate< ET1, Cos >( a );
 }
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
+////
+// Tan
+template< typename ET1,
+          typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void >
 auto
-operator/( const DistributedBinaryExpressionTemplate< T1, T2, Operation >& a,
-           const typename DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
+tan( const ET1& a )
 {
-   return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Division >( a, b );
+   return DistributedUnaryExpressionTemplate< ET1, Tan >( a );
 }
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
+////
+// Asin
+template< typename ET1,
+          typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void >
 auto
-operator/( const typename DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-           const DistributedBinaryExpressionTemplate< T1, T2, Operation >& b )
+asin( const ET1& a )
 {
-   return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Division >( a, b );
+   return DistributedUnaryExpressionTemplate< ET1, Asin >( a );
 }
 
-template< typename T1,
-          template< typename > class Operation >
+////
+// Acos
+template< typename ET1,
+          typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void >
 auto
-operator/( const DistributedUnaryExpressionTemplate< T1, Operation >& a,
-           const typename DistributedUnaryExpressionTemplate< T1, Operation >::RealType& b )
+acos( const ET1& a )
 {
-   return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Division >( a, b );
+   return DistributedUnaryExpressionTemplate< ET1, Acos >( a );
 }
 
-template< typename T1,
-          template< typename > class Operation >
+////
+// Atan
+template< typename ET1,
+          typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void >
 auto
-operator/( const typename DistributedUnaryExpressionTemplate< T1, Operation >::RealType& a,
-           const DistributedUnaryExpressionTemplate< T1, Operation >& b )
+atan( const ET1& a )
 {
-   return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Division >( a, b );
+   return DistributedUnaryExpressionTemplate< ET1, Atan >( a );
 }
 
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
+////
+// Sinh
+template< typename ET1,
+          typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void >
 auto
-operator/( const DistributedUnaryExpressionTemplate< L1, LOperation >& a,
-           const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b )
+sinh( const ET1& a )
 {
-   return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Division >( a, b );
+   return DistributedUnaryExpressionTemplate< ET1, Sinh >( a );
 }
 
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
+////
+// Cosh
+template< typename ET1,
+          typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void >
 auto
-operator/( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const DistributedUnaryExpressionTemplate< R1,ROperation >& b )
+cosh( const ET1& a )
 {
-   return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Division >( a, b );
+   return DistributedUnaryExpressionTemplate< ET1, Cosh >( a );
 }
 
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
+////
+// Tanh
+template< typename ET1,
+          typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void >
 auto
-operator/( const DistributedUnaryExpressionTemplate< L1,LOperation >& a,
-           const DistributedUnaryExpressionTemplate< R1,ROperation >& b )
+tanh( const ET1& a )
 {
-   return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Division >( a, b );
+   return DistributedUnaryExpressionTemplate< ET1, Tanh >( a );
 }
 
 ////
-// Comparison operator ==
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-bool
-operator==( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a,
-            const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::EQ( a, b );
-}
-
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-bool
-operator==( const DistributedBinaryExpressionTemplate< T1, T2, Operation >& a,
-            const typename DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
-{
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::EQ( a, b );
-}
-
-template< typename T1,
-          template< typename > class Operation >
-bool
-operator==( const DistributedUnaryExpressionTemplate< T1, Operation >& a,
-            const typename DistributedUnaryExpressionTemplate< T1, Operation >::RealType& b )
+// Asinh
+template< typename ET1,
+          typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void >
+auto
+asinh( const ET1& a )
 {
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::EQ( a, b );
+   return DistributedUnaryExpressionTemplate< ET1, Asinh >( a );
 }
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-bool
-operator==( const typename DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-            const DistributedBinaryExpressionTemplate< T1, T2, Operation >& b )
+////
+// Acosh
+template< typename ET1,
+          typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void >
+auto
+acosh( const ET1& a )
 {
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::EQ( a, b );
+   return DistributedUnaryExpressionTemplate< ET1, Acosh >( a );
 }
 
-template< typename T1,
-          template< typename > class Operation >
-bool
-operator==( const typename DistributedUnaryExpressionTemplate< T1, Operation >::RealType& a,
-            const DistributedUnaryExpressionTemplate< T1, Operation >& b )
+////
+// Atanh
+template< typename ET1,
+          typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void >
+auto
+atanh( const ET1& a )
 {
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::EQ( a, b );
+   return DistributedUnaryExpressionTemplate< ET1, Atanh >( a );
 }
 
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-bool
-operator==( const DistributedUnaryExpressionTemplate< L1, LOperation >& a,
-            const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b )
+////
+// Floor
+template< typename ET1,
+          typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void >
+auto
+floor( const ET1& a )
 {
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::EQ( a, b );
+   return DistributedUnaryExpressionTemplate< ET1, Floor >( a );
 }
 
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-bool
-operator==( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a,
-            const DistributedUnaryExpressionTemplate< R1,ROperation >& b )
+////
+// Ceil
+template< typename ET1,
+          typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void >
+auto
+ceil( const ET1& a )
 {
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::EQ( a, b );
+   return DistributedUnaryExpressionTemplate< ET1, Ceil >( a );
 }
 
 ////
-// Comparison operator !=
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-bool
-operator!=( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a,
-            const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b )
+// Sign
+template< typename ET1,
+          typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void >
+auto
+sign( const ET1& a )
 {
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b );
+   return DistributedUnaryExpressionTemplate< ET1, Sign >( a );
 }
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-bool
-operator!=( const DistributedBinaryExpressionTemplate< T1, T2, Operation >& a,
-            const typename DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
+////
+// Cast
+template< typename ResultType,
+          typename ET1,
+          typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >,
+          // workaround: templated type alias cannot be declared at block level
+          typename CastOperation = typename Cast< ResultType >::Operation,
+          typename = void, typename = void >
+auto
+cast( const ET1& a )
 {
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b );
+   return DistributedUnaryExpressionTemplate< ET1, CastOperation >( a );
 }
 
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-bool
-operator!=( const DistributedUnaryExpressionTemplate< L1, LOperation >& a,
-            const DistributedUnaryExpressionTemplate< R1, ROperation >& b )
+////
+// Vertical operations
+template< typename ET1,
+          typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void >
+auto
+min( const ET1& a )
 {
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b );
+   return DistributedExpressionMin( a );
 }
 
-template< typename T1,
-          template< typename > class Operation >
-bool
-operator!=( const DistributedUnaryExpressionTemplate< T1, Operation >& a,
-            const typename DistributedUnaryExpressionTemplate< T1, Operation >::RealType& b )
+template< typename ET1,
+          typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void >
+auto
+argMin( const ET1& a )
 {
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b );
+   return DistributedExpressionArgMin( a );
 }
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-bool
-operator!=( const typename DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-            const DistributedBinaryExpressionTemplate< T1, T2, Operation >& b )
+template< typename ET1,
+          typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void >
+auto
+max( const ET1& a )
 {
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b );
+   return DistributedExpressionMax( a );
 }
 
-template< typename T1,
-          template< typename > class Operation >
-bool
-operator!=( const typename DistributedUnaryExpressionTemplate< T1, Operation >::RealType& a,
-            const DistributedUnaryExpressionTemplate< T1, Operation >& b )
+template< typename ET1,
+          typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void >
+auto
+argMax( const ET1& a )
 {
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b );
+   return DistributedExpressionArgMax( a );
 }
 
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-bool
-operator!=( const DistributedUnaryExpressionTemplate< L1, LOperation >& a,
-            const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b )
+template< typename ET1,
+          typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void >
+auto
+sum( const ET1& a )
 {
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b );
+   return DistributedExpressionSum( a );
 }
 
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-bool
-operator!=( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a,
-            const DistributedUnaryExpressionTemplate< R1,ROperation >& b )
+template< typename ET1,
+          typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void >
+auto
+maxNorm( const ET1& a )
 {
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b );
+   return max( abs( a ) );
 }
 
-////
-// Comparison operator <
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-bool
-operator<( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b )
+template< typename ET1,
+          typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void >
+auto
+l1Norm( const ET1& a )
 {
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b );
+   return sum( abs( a ) );
 }
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-bool
-operator<( const DistributedBinaryExpressionTemplate< T1, T2, Operation >& a,
-           const typename DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
+template< typename ET1,
+          typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void >
+auto
+l2Norm( const ET1& a )
 {
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b );
+   using TNL::sqrt;
+   return sqrt( sum( a * a ) );
 }
 
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-bool
-operator<( const DistributedUnaryExpressionTemplate< L1, LOperation >& a,
-           const DistributedUnaryExpressionTemplate< R1, ROperation >& b )
+template< typename ET1,
+          typename Real,
+          typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void >
+auto
+lpNorm( const ET1& a, const Real& p )
+// since (1.0 / p) has type double, TNL::pow returns double
+-> double
 {
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b );
+   if( p == 1.0 )
+      return l1Norm( a );
+   if( p == 2.0 )
+      return l2Norm( a );
+   using TNL::pow;
+   return pow( sum( pow( abs( a ), p ) ), 1.0 / p );
 }
 
-template< typename T1,
-          template< typename > class Operation >
-bool
-operator<( const DistributedUnaryExpressionTemplate< T1, Operation >& a,
-           const typename DistributedUnaryExpressionTemplate< T1, Operation >::RealType& b )
+template< typename ET1,
+          typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void >
+auto
+product( const ET1& a )
 {
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b );
+   return DistributedExpressionProduct( a );
 }
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-bool
-operator<( const typename DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-           const DistributedBinaryExpressionTemplate< T1, T2, Operation >& b )
+template< typename ET1,
+          typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void >
+auto
+logicalOr( const ET1& a )
 {
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b );
+   return DistributedExpressionLogicalOr( a );
 }
 
-template< typename T1,
-          template< typename > class Operation >
-bool
-operator<( const typename DistributedUnaryExpressionTemplate< T1, Operation >::RealType& a,
-           const DistributedUnaryExpressionTemplate< T1, Operation >& b )
+template< typename ET1,
+          typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void >
+auto
+logicalAnd( const ET1& a )
 {
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b );
+   return DistributedExpressionLogicalAnd( a );
 }
 
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-bool
-operator<( const DistributedUnaryExpressionTemplate< L1, LOperation >& a,
-           const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b )
+template< typename ET1,
+          typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void >
+auto
+binaryOr( const ET1& a )
 {
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b );
+   return DistributedExpressionBinaryOr( a );
 }
 
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-bool
-operator<( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const DistributedUnaryExpressionTemplate< R1,ROperation >& b )
+template< typename ET1,
+          typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void >
+auto
+binaryAnd( const ET1& a )
 {
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b );
+   return DistributedExpressionBinaryAnd( a );
 }
 
 ////
-// Comparison operator <=
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-bool
-operator<=( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a,
-            const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b );
-}
-
+// Output stream
 template< typename T1,
           typename T2,
-          template< typename, typename > class Operation >
-bool
-operator<=( const DistributedBinaryExpressionTemplate< T1, T2, Operation >& a,
-            const typename DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
+          typename Operation >
+std::ostream& operator<<( std::ostream& str, const DistributedBinaryExpressionTemplate< T1, T2, Operation >& expression )
 {
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b );
+   str << "[ ";
+   for( int i = 0; i < expression.getSize() - 1; i++ )
+      str << expression.getElement( i ) << ", ";
+   str << expression.getElement( expression.getSize() - 1 ) << " ]";
+   return str;
 }
 
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-bool
-operator<=( const DistributedUnaryExpressionTemplate< L1, LOperation >& a,
-            const DistributedUnaryExpressionTemplate< R1, ROperation >& b )
+template< typename T,
+          typename Operation >
+std::ostream& operator<<( std::ostream& str, const DistributedUnaryExpressionTemplate< T, Operation >& expression )
 {
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b );
-}
-
-template< typename T1,
-          template< typename > class Operation >
-bool
-operator<=( const DistributedUnaryExpressionTemplate< T1, Operation >& a,
-            const typename DistributedUnaryExpressionTemplate< T1, Operation >::RealType& b )
-{
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b );
-}
-
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-bool
-operator<=( const typename DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-            const DistributedBinaryExpressionTemplate< T1, T2, Operation >& b )
-{
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b );
-}
-
-template< typename T1,
-          template< typename > class Operation >
-bool
-operator<=( const typename DistributedUnaryExpressionTemplate< T1, Operation >::RealType& a,
-            const DistributedUnaryExpressionTemplate< T1, Operation >& b )
-{
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b );
-}
-
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-bool
-operator<=( const DistributedUnaryExpressionTemplate< L1, LOperation >& a,
-            const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-bool
-operator<=( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a,
-            const DistributedUnaryExpressionTemplate< R1,ROperation >& b )
-{
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b );
-}
-
-////
-// Comparison operator >
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-bool
-operator>( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GT( a, b );
-}
-
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-bool
-operator>( const DistributedBinaryExpressionTemplate< T1, T2, Operation >& a,
-           const typename DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
-{
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GT( a, b );
-}
-
-template< typename T1,
-          template< typename > class Operation >
-bool
-operator>( const DistributedUnaryExpressionTemplate< T1, Operation >& a,
-           const typename DistributedUnaryExpressionTemplate< T1, Operation >::RealType& b )
-{
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GT( a, b );
-}
-
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-bool
-operator>( const typename DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-           const DistributedBinaryExpressionTemplate< T1, T2, Operation >& b )
-{
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GT( a, b );
-}
-
-template< typename T1,
-          template< typename > class Operation >
-bool
-operator>( const typename DistributedUnaryExpressionTemplate< T1, Operation >::RealType& a,
-           const DistributedUnaryExpressionTemplate< T1, Operation >& b )
-{
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GT( a, b );
-}
-
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-bool
-operator>( const DistributedUnaryExpressionTemplate< L1, LOperation >& a,
-           const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GT( a, b );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-bool
-operator>( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const DistributedUnaryExpressionTemplate< R1,ROperation >& b )
-{
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GT( a, b );
-}
-
-////
-// Comparison operator >=
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-bool
-operator>=( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a,
-            const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GE( a, b );
-}
-
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-bool
-operator>=( const DistributedBinaryExpressionTemplate< T1, T2, Operation >& a,
-            const typename DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
-{
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GE( a, b );
-}
-
-template< typename T1,
-          template< typename > class Operation >
-bool
-operator>=( const DistributedUnaryExpressionTemplate< T1, Operation >& a,
-            const typename DistributedUnaryExpressionTemplate< T1, Operation >::RealType& b )
-{
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GE( a, b );
-}
-
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-bool
-operator>=( const typename DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-            const DistributedBinaryExpressionTemplate< T1, T2, Operation >& b )
-{
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GE( a, b );
-}
-
-template< typename T1,
-          template< typename > class Operation >
-bool
-operator>=( const typename DistributedUnaryExpressionTemplate< T1, Operation >::RealType& a,
-            const DistributedUnaryExpressionTemplate< T1, Operation >& b )
-{
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GE( a, b );
-}
-
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-bool
-operator>=( const DistributedUnaryExpressionTemplate< L1, LOperation >& a,
-            const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GE( a, b );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-bool
-operator>=( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a,
-            const DistributedUnaryExpressionTemplate< R1,ROperation >& b )
-{
-   return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GE( a, b );
-}
-
-////
-// Unary operations
-
-////
-// Minus
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-operator-( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Minus >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-operator-( const DistributedUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Minus >( a );
-}
-
-////
-// Scalar product
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-auto
-operator,( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return DistributedExpressionSum( a * b );
-}
-
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-auto
-operator,( const DistributedUnaryExpressionTemplate< L1, LOperation >& a,
-           const DistributedUnaryExpressionTemplate< R1, ROperation >& b )
-{
-   return DistributedExpressionSum( a * b );
-}
-
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-auto
-operator,( const DistributedUnaryExpressionTemplate< L1, LOperation >& a,
-           const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return DistributedExpressionSum( a * b );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-auto
-operator,( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const DistributedUnaryExpressionTemplate< R1,ROperation >& b )
-{
-   return DistributedExpressionSum( a * b );
+   str << "[ ";
+   for( int i = 0; i < expression.getSize() - 1; i++ )
+      str << expression.getElement( i ) << ", ";
+   str << expression.getElement( expression.getSize() - 1 ) << " ]";
+   return str;
 }
 
 #endif // DOXYGEN_ONLY
 
 } // namespace Expressions
-} // namespace Containers
-
-////
-// All operations are supposed to be in namespace TNL
-
-#ifndef DOXYGEN_ONLY
-
-////
-// Binary expression min
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-auto
-min( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a,
-     const Containers::Expressions::DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b );
-}
-
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-auto
-min( const Containers::Expressions::DistributedBinaryExpressionTemplate< T1, T2, Operation >& a,
-     const typename Containers::Expressions::DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
-{
-   return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b );
-}
-
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-auto
-min( const typename Containers::Expressions::DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-     const Containers::Expressions::DistributedBinaryExpressionTemplate< T1, T2, Operation >& b )
-{
-   return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b );
-}
-
-template< typename T1,
-          template< typename > class Operation >
-auto
-min( const Containers::Expressions::DistributedUnaryExpressionTemplate< T1, Operation >& a,
-     const typename Containers::Expressions::DistributedUnaryExpressionTemplate< T1, Operation >::RealType& b )
-{
-   return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b );
-}
-
-template< typename T1,
-          template< typename > class Operation >
-auto
-min( const typename Containers::Expressions::DistributedUnaryExpressionTemplate< T1, Operation >::RealType& a,
-     const Containers::Expressions::DistributedUnaryExpressionTemplate< T1, Operation >& b )
-{
-   return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b );
-}
-
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-auto
-min( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a,
-     const typename Containers::Expressions::DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-auto
-min( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a,
-     const Containers::Expressions::DistributedUnaryExpressionTemplate< R1,ROperation >& b )
-{
-   return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b );
-}
-
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-auto
-min( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1,LOperation >& a,
-     const Containers::Expressions::DistributedUnaryExpressionTemplate< R1,ROperation >& b )
-{
-   return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b );
-}
-
-////
-// Binary expression max
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-auto
-max( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a,
-     const Containers::Expressions::DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b );
-}
-
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-auto
-max( const Containers::Expressions::DistributedBinaryExpressionTemplate< T1, T2, Operation >& a,
-     const typename Containers::Expressions::DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
-{
-   return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b );
-}
-
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-auto
-max( const typename Containers::Expressions::DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-     const Containers::Expressions::DistributedBinaryExpressionTemplate< T1, T2, Operation >& b )
-{
-   return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b );
-}
-
-template< typename T1,
-          template< typename > class Operation >
-auto
-max( const Containers::Expressions::DistributedUnaryExpressionTemplate< T1, Operation >& a,
-     const typename Containers::Expressions::DistributedUnaryExpressionTemplate< T1, Operation >::RealType& b )
-{
-   return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b );
-}
-
-template< typename T1,
-          template< typename > class Operation >
-auto
-max( const typename Containers::Expressions::DistributedUnaryExpressionTemplate< T1, Operation >::RealType& a,
-     const Containers::Expressions::DistributedUnaryExpressionTemplate< T1, Operation >& b )
-{
-   return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b );
-}
-
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-auto
-max( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a,
-     const Containers::Expressions::DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-auto
-max( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a,
-     const Containers::Expressions::DistributedUnaryExpressionTemplate< R1,ROperation >& b )
-{
-   return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b );
-}
-
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-auto
-max( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1,LOperation >& a,
-     const Containers::Expressions::DistributedUnaryExpressionTemplate< R1,ROperation >& b )
-{
-   return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b );
-}
-
-////
-// Abs
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-abs( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Abs >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-abs( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Abs >( a );
-}
-
-////
-// Pow
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename Real >
-auto
-pow( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a, const Real& exp )
-{
-   return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, Real, Containers::Expressions::Pow >( a, exp );
-}
-
-template< typename L1,
-          template< typename > class LOperation,
-          typename Real >
-auto
-pow( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a, const Real& exp )
-{
-   return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, Real, Containers::Expressions::Pow >( a, exp );
-}
-
-////
-// Exp
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-exp( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Exp >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-exp( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Exp >( a );
-}
-
-////
-// Sqrt
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-sqrt( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sqrt >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-sqrt( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sqrt >( a );
-}
 
-////
-// Cbrt
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-cbrt( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Cbrt >( a );
-}
+// Make all operators visible in the TNL::Containers namespace to be considered
+// even for DistributedVector and DistributedVectorView
+using Expressions::operator+;
+using Expressions::operator-;
+using Expressions::operator*;
+using Expressions::operator/;
+using Expressions::operator,;
+using Expressions::operator==;
+using Expressions::operator!=;
+using Expressions::operator<;
+using Expressions::operator<=;
+using Expressions::operator>;
+using Expressions::operator>=;
+
+// Make all functions visible in the TNL::Containers namespace
+using Expressions::dot;
+using Expressions::min;
+using Expressions::max;
+using Expressions::abs;
+using Expressions::pow;
+using Expressions::exp;
+using Expressions::sqrt;
+using Expressions::cbrt;
+using Expressions::log;
+using Expressions::log10;
+using Expressions::log2;
+using Expressions::sin;
+using Expressions::cos;
+using Expressions::tan;
+using Expressions::asin;
+using Expressions::acos;
+using Expressions::atan;
+using Expressions::sinh;
+using Expressions::cosh;
+using Expressions::tanh;
+using Expressions::asinh;
+using Expressions::acosh;
+using Expressions::atanh;
+using Expressions::floor;
+using Expressions::ceil;
+using Expressions::sign;
+using Expressions::cast;
+using Expressions::argMin;
+using Expressions::argMax;
+using Expressions::sum;
+using Expressions::maxNorm;
+using Expressions::l1Norm;
+using Expressions::l2Norm;
+using Expressions::lpNorm;
+using Expressions::product;
+using Expressions::logicalAnd;
+using Expressions::logicalOr;
+using Expressions::binaryAnd;
+using Expressions::binaryOr;
 
-template< typename L1,
-          template< typename > class LOperation >
-auto
-cbrt( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Cbrt >( a );
-}
-
-////
-// Log
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-log( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Log >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-log( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Log >( a );
-}
-
-////
-// Log10
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-log10( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Log10 >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-log10( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Log10 >( a );
-}
-
-////
-// Log2
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-log2( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Log2 >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-log2( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Log2 >( a );
-}
-
-////
-// Sin
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-sin( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sin >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-sin( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sin >( a );
-}
-
-////
-// Cos
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-cos( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Cos >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-cos( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Cos >( a );
-}
-
-////
-// Tan
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-tan( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Tan >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-tan( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Tan >( a );
-}
-
-////
-// Asin
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-asin( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Asin >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-asin( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Asin >( a );
-}
-
-////
-// Acos
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-acos( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Acos >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-acos( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Acos >( a );
-}
-
-////
-// Atan
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-atan( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Atan >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-atan( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Atan >( a );
-}
-
-////
-// Sinh
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-sinh( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sinh >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-sinh( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sinh >( a );
-}
-
-////
-// Cosh
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-cosh( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Cosh >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-cosh( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Cosh >( a );
-}
-
-////
-// Tanh
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-tanh( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Tanh >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-tanh( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Tanh >( a );
-}
-
-////
-// Asinh
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-asinh( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Asinh >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-asinh( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Asinh >( a );
-}
-
-////
-// Acosh
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-acosh( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Acosh >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-acosh( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Acosh >( a );
-}
-
-////
-// Atanh
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-atanh( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Atanh >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-atanh( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Atanh >( a );
-}
-
-////
-// Floor
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-floor( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Floor >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-floor( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Floor >( a );
-}
-
-////
-// Ceil
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-ceil( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Ceil >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-ceil( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Ceil >( a );
-}
-
-////
-// Sign
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-sign( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sign >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-sign( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sign >( a );
-}
-
-////
-// Cast
-template< typename ResultType,
-          typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          // workaround: templated type alias cannot be declared at block level
-          template<typename> class CastOperation = Containers::Expressions::Cast< ResultType >::template Operation >
-auto
-cast( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, CastOperation >( a );
-}
-
-template< typename ResultType,
-          typename L1,
-          template< typename > class LOperation,
-          // workaround: templated type alias cannot be declared at block level
-          template<typename> class CastOperation = Containers::Expressions::Cast< ResultType >::template Operation >
-auto
-cast( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, CastOperation >( a );
-}
-
-////
-// Vertical operations - min
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-min( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return DistributedExpressionMin( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-min( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return DistributedExpressionMin( a );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-argMin( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return DistributedExpressionArgMin( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-argMin( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return DistributedExpressionArgMin( a );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-max( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return DistributedExpressionMax( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-max( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return DistributedExpressionMax( a );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-argMax( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return DistributedExpressionArgMax( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-argMax( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return DistributedExpressionArgMax( a );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-sum( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return DistributedExpressionSum( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-sum( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return DistributedExpressionSum( a );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-maxNorm( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return max( abs( a ) );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-maxNorm( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return max( abs( a ) );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-l1Norm( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return DistributedExpressionL1Norm( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-l1Norm( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return DistributedExpressionL1Norm( a );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-l2Norm( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return TNL::sqrt( DistributedExpressionL2Norm( a ) );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-l2Norm( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return TNL::sqrt( DistributedExpressionL2Norm( a ) );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename Real >
-auto
-lpNorm( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a, const Real& p )
-// since (1.0 / p) has type double, TNL::pow returns double
--> double
-{
-   if( p == 1.0 )
-      return l1Norm( a );
-   if( p == 2.0 )
-      return l2Norm( a );
-   return TNL::pow( DistributedExpressionLpNorm( a, p ), 1.0 / p );
-}
-
-template< typename L1,
-          template< typename > class LOperation,
-          typename Real >
-auto
-lpNorm( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a, const Real& p )
-// since (1.0 / p) has type double, TNL::pow returns double
--> double
-{
-   if( p == 1.0 )
-      return l1Norm( a );
-   if( p == 2.0 )
-      return l2Norm( a );
-   return TNL::pow( DistributedExpressionLpNorm( a, p ), 1.0 / p );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-product( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return DistributedExpressionProduct( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-product( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return DistributedExpressionProduct( a );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-logicalOr( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return DistributedExpressionLogicalOr( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-logicalOr( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return DistributedExpressionLogicalOr( a );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-logicalAnd( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return DistributedExpressionLogicalAnd( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-logicalAnd( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return DistributedExpressionLogicalAnd( a );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-binaryOr( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return DistributedExpressionBinaryOr( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-binaryOr( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return DistributedExpressionBinaryOr( a );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-binaryAnd( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return DistributedExpressionBinaryAnd( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-binaryAnd( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return DistributedExpressionBinaryAnd( a );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-auto
-dot( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a,
-     const Containers::Expressions::DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return (a, b);
-}
-
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-auto
-dot( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a,
-     const Containers::Expressions::DistributedUnaryExpressionTemplate< R1, ROperation >& b )
-{
-   return (a, b);
-}
-
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-auto
-dot( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a,
-     const Containers::Expressions::DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return (a, b);
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-auto
-dot( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a,
-     const Containers::Expressions::DistributedUnaryExpressionTemplate< R1, ROperation >& b )
-{
-   return (a, b);
-}
-
-#endif // DOXYGEN_ONLY
+} // namespace Containers
 
+// Make all functions visible in the main TNL namespace
+using Containers::dot;
+using Containers::min;
+using Containers::max;
+using Containers::abs;
+using Containers::pow;
+using Containers::exp;
+using Containers::sqrt;
+using Containers::cbrt;
+using Containers::log;
+using Containers::log10;
+using Containers::log2;
+using Containers::sin;
+using Containers::cos;
+using Containers::tan;
+using Containers::asin;
+using Containers::acos;
+using Containers::atan;
+using Containers::sinh;
+using Containers::cosh;
+using Containers::tanh;
+using Containers::asinh;
+using Containers::acosh;
+using Containers::atanh;
+using Containers::floor;
+using Containers::ceil;
+using Containers::sign;
+using Containers::cast;
+using Containers::argMin;
+using Containers::argMax;
+using Containers::sum;
+using Containers::maxNorm;
+using Containers::l1Norm;
+using Containers::l2Norm;
+using Containers::lpNorm;
+using Containers::product;
+using Containers::logicalAnd;
+using Containers::logicalOr;
+using Containers::binaryAnd;
+using Containers::binaryOr;
 
 ////
 // Evaluation with reduction
 template< typename Vector,
    typename T1,
    typename T2,
-   template< typename, typename > class Operation,
+   typename Operation,
    typename Reduction,
    typename Result >
 Result evaluateAndReduce( Vector& lhs,
@@ -2212,7 +956,7 @@ Result evaluateAndReduce( Vector& lhs,
 
 template< typename Vector,
    typename T1,
-   template< typename > class Operation,
+   typename Operation,
    typename Reduction,
    typename Result >
 Result evaluateAndReduce( Vector& lhs,
@@ -2234,7 +978,7 @@ Result evaluateAndReduce( Vector& lhs,
 template< typename Vector,
    typename T1,
    typename T2,
-   template< typename, typename > class Operation,
+   typename Operation,
    typename Reduction,
    typename Result >
 Result addAndReduce( Vector& lhs,
@@ -2257,7 +1001,7 @@ Result addAndReduce( Vector& lhs,
 
 template< typename Vector,
    typename T1,
-   template< typename > class Operation,
+   typename Operation,
    typename Reduction,
    typename Result >
 Result addAndReduce( Vector& lhs,
@@ -2283,7 +1027,7 @@ Result addAndReduce( Vector& lhs,
 template< typename Vector,
    typename T1,
    typename T2,
-   template< typename, typename > class Operation,
+   typename Operation,
    typename Reduction,
    typename Result >
 Result addAndReduceAbs( Vector& lhs,
@@ -2306,7 +1050,7 @@ Result addAndReduceAbs( Vector& lhs,
 
 template< typename Vector,
    typename T1,
-   template< typename > class Operation,
+   typename Operation,
    typename Reduction,
    typename Result >
 Result addAndReduceAbs( Vector& lhs,
diff --git a/src/TNL/Containers/Expressions/DistributedVerticalOperations.h b/src/TNL/Containers/Expressions/DistributedVerticalOperations.h
index 43940417bb0aa7fa97afe17e4fee3e4ce703a819..178a5c03c50a36ff9c62e35e38a4a0aa68860532 100644
--- a/src/TNL/Containers/Expressions/DistributedVerticalOperations.h
+++ b/src/TNL/Containers/Expressions/DistributedVerticalOperations.h
@@ -148,51 +148,6 @@ auto DistributedExpressionSum( const Expression& expression ) -> std::decay_t< d
    return result;
 }
 
-template< typename Expression >
-auto DistributedExpressionL1Norm( const Expression& expression ) -> std::decay_t< decltype( expression[0] ) >
-{
-   using ResultType = std::decay_t< decltype( expression[0] ) >;
-   using IndexType = typename Expression::IndexType;
-   using CommunicatorType = typename Expression::CommunicatorType;
-
-   ResultType result = 0;
-   if( expression.getCommunicationGroup() != CommunicatorType::NullGroup ) {
-      const ResultType localResult = ExpressionL1Norm( expression.getConstLocalView() );
-      CommunicatorType::Allreduce( &localResult, &result, 1, MPI_SUM, expression.getCommunicationGroup() );
-   }
-   return result;
-}
-
-template< typename Expression >
-auto DistributedExpressionL2Norm( const Expression& expression ) -> std::decay_t< decltype( expression[0] * expression[0] ) >
-{
-   using ResultType = std::decay_t< decltype( expression[0] * expression[0] ) >;
-   using IndexType = typename Expression::IndexType;
-   using CommunicatorType = typename Expression::CommunicatorType;
-
-   ResultType result = 0;
-   if( expression.getCommunicationGroup() != CommunicatorType::NullGroup ) {
-      const ResultType localResult = ExpressionL2Norm( expression.getConstLocalView() );
-      CommunicatorType::Allreduce( &localResult, &result, 1, MPI_SUM, expression.getCommunicationGroup() );
-   }
-   return result;
-}
-
-template< typename Expression, typename Real >
-auto DistributedExpressionLpNorm( const Expression& expression, const Real& p ) -> std::decay_t< decltype( TNL::pow( expression[0], p ) ) >
-{
-   using ResultType = std::decay_t< decltype( TNL::pow( expression[0], p ) ) >;
-   using IndexType = typename Expression::IndexType;
-   using CommunicatorType = typename Expression::CommunicatorType;
-
-   ResultType result = 0;
-   if( expression.getCommunicationGroup() != CommunicatorType::NullGroup ) {
-      const ResultType localResult = ExpressionLpNorm( expression.getConstLocalView(), p );
-      CommunicatorType::Allreduce( &localResult, &result, 1, MPI_SUM, expression.getCommunicationGroup() );
-   }
-   return result;
-}
-
 template< typename Expression >
 auto DistributedExpressionProduct( const Expression& expression ) -> std::decay_t< decltype( expression[0] * expression[0] ) >
 {
diff --git a/src/TNL/Containers/Expressions/ExpressionTemplates.h b/src/TNL/Containers/Expressions/ExpressionTemplates.h
index a0980baf6cf8ee751444df7d27205dfa9260f593..eb9684cafe77f659456e2b930c0ff13daab4f429 100644
--- a/src/TNL/Containers/Expressions/ExpressionTemplates.h
+++ b/src/TNL/Containers/Expressions/ExpressionTemplates.h
@@ -24,57 +24,54 @@ namespace TNL {
 namespace Containers {
 namespace Expressions {
 
-////
-// Non-static unary expression template
 template< typename T1,
-          template< typename > class Operation,
-          ExpressionVariableType T1Type = ExpressionVariableTypeGetter< T1 >::value >
-struct UnaryExpressionTemplate
-{};
+          typename Operation >
+struct UnaryExpressionTemplate;
 
 template< typename T1,
-          template< typename > class Operation,
-          ExpressionVariableType T1Type >
-struct IsExpressionTemplate< UnaryExpressionTemplate< T1, Operation, T1Type > >
+          typename Operation >
+struct HasEnabledExpressionTemplates< UnaryExpressionTemplate< T1, Operation > >
 : std::true_type
 {};
 
-////
-// Non-static binary expression template
 template< typename T1,
           typename T2,
-          template< typename, typename > class Operation,
-          ExpressionVariableType T1Type = ExpressionVariableTypeGetter< T1 >::value,
-          ExpressionVariableType T2Type = ExpressionVariableTypeGetter< T2 >::value >
-struct BinaryExpressionTemplate
-{};
+          typename Operation,
+          ExpressionVariableType T1Type = getExpressionVariableType< T1, T2 >(),
+          ExpressionVariableType T2Type = getExpressionVariableType< T2, T1 >() >
+struct BinaryExpressionTemplate;
 
 template< typename T1,
           typename T2,
-          template< typename, typename > class Operation,
+          typename Operation,
           ExpressionVariableType T1Type,
           ExpressionVariableType T2Type >
-struct IsExpressionTemplate< BinaryExpressionTemplate< T1, T2, Operation, T1Type, T2Type > >
+struct HasEnabledExpressionTemplates< BinaryExpressionTemplate< T1, T2, Operation, T1Type, T2Type > >
 : std::true_type
 {};
 
+
+////
+// Non-static binary expression template
 template< typename T1,
           typename T2,
-          template< typename, typename > class Operation >
+          typename Operation >
 struct BinaryExpressionTemplate< T1, T2, Operation, VectorExpressionVariable, VectorExpressionVariable >
 {
-   using RealType = decltype( Operation< typename T1::RealType, typename T2::RealType >::
-                              evaluate( std::declval<T1>()[0], std::declval<T2>()[0] ) );
+   using RealType = decltype( Operation::evaluate( std::declval<T1>()[0], std::declval<T2>()[0] ) );
    using DeviceType = typename T1::DeviceType;
    using IndexType = typename T1::IndexType;
+   using ConstViewType = BinaryExpressionTemplate;
 
+   static_assert( HasEnabledExpressionTemplates< T1 >::value,
+                  "Invalid operand in binary expression templates - expression templates are not enabled for the left operand." );
+   static_assert( HasEnabledExpressionTemplates< T2 >::value,
+                  "Invalid operand in binary expression templates - expression templates are not enabled for the right operand." );
    static_assert( std::is_same< typename T1::DeviceType, typename T2::DeviceType >::value,
                   "Attempt to mix operands which have different DeviceType." );
-   static_assert( IsStaticArrayType< T1 >::value == IsStaticArrayType< T2 >::value,
-                  "Attempt to mix static and non-static operands in binary expression templates." );
 
    BinaryExpressionTemplate( const T1& a, const T2& b )
-   : op1( a ), op2( b )
+   : op1( a.getConstView() ), op2( b.getConstView() )
    {
       TNL_ASSERT_EQ( op1.getSize(), op2.getSize(),
                      "Attempt to mix operands with different sizes." );
@@ -82,13 +79,13 @@ struct BinaryExpressionTemplate< T1, T2, Operation, VectorExpressionVariable, Ve
 
    RealType getElement( const IndexType i ) const
    {
-      return Operation< typename T1::RealType, typename T2::RealType >::evaluate( op1.getElement( i ), op2.getElement( i ) );
+      return Operation::evaluate( op1.getElement( i ), op2.getElement( i ) );
    }
 
    __cuda_callable__
    RealType operator[]( const IndexType i ) const
    {
-      return Operation< typename T1::RealType, typename T2::RealType >::evaluate( op1[ i ], op2[ i ] );
+      return Operation::evaluate( op1[ i ], op2[ i ] );
    }
 
    __cuda_callable__
@@ -97,33 +94,41 @@ struct BinaryExpressionTemplate< T1, T2, Operation, VectorExpressionVariable, Ve
       return op1.getSize();
    }
 
+   ConstViewType getConstView() const
+   {
+      return *this;
+   }
+
 protected:
-   const T1 op1;
-   const T2 op2;
+   const typename T1::ConstViewType op1;
+   const typename T2::ConstViewType op2;
 };
 
 template< typename T1,
           typename T2,
-          template< typename, typename > class Operation >
+          typename Operation >
 struct BinaryExpressionTemplate< T1, T2, Operation, VectorExpressionVariable, ArithmeticVariable >
 {
-   using RealType = decltype( Operation< typename T1::RealType, T2 >::
-                              evaluate( std::declval<T1>()[0], std::declval<T2>() ) );
+   using RealType = decltype( Operation::evaluate( std::declval<T1>()[0], std::declval<T2>() ) );
    using DeviceType = typename T1::DeviceType;
    using IndexType = typename T1::IndexType;
+   using ConstViewType = BinaryExpressionTemplate;
+
+   static_assert( HasEnabledExpressionTemplates< T1 >::value,
+                  "Invalid operand in binary expression templates - expression templates are not enabled for the left operand." );
 
    BinaryExpressionTemplate( const T1& a, const T2& b )
-   : op1( a ), op2( b ) {}
+   : op1( a.getConstView() ), op2( b ) {}
 
    RealType getElement( const IndexType i ) const
    {
-      return Operation< typename T1::RealType, T2 >::evaluate( op1.getElement( i ), op2 );
+      return Operation::evaluate( op1.getElement( i ), op2 );
    }
 
    __cuda_callable__
    RealType operator[]( const IndexType i ) const
    {
-      return Operation< typename T1::RealType, T2 >::evaluate( op1[ i ], op2 );
+      return Operation::evaluate( op1[ i ], op2 );
    }
 
    __cuda_callable__
@@ -132,33 +137,41 @@ struct BinaryExpressionTemplate< T1, T2, Operation, VectorExpressionVariable, Ar
       return op1.getSize();
    }
 
+   ConstViewType getConstView() const
+   {
+      return *this;
+   }
+
 protected:
-   const T1 op1;
+   const typename T1::ConstViewType op1;
    const T2 op2;
 };
 
 template< typename T1,
           typename T2,
-          template< typename, typename > class Operation >
+          typename Operation >
 struct BinaryExpressionTemplate< T1, T2, Operation, ArithmeticVariable, VectorExpressionVariable >
 {
-   using RealType = decltype( Operation< T1, typename T2::RealType >::
-                              evaluate( std::declval<T1>(), std::declval<T2>()[0] ) );
+   using RealType = decltype( Operation::evaluate( std::declval<T1>(), std::declval<T2>()[0] ) );
    using DeviceType = typename T2::DeviceType;
    using IndexType = typename T2::IndexType;
+   using ConstViewType = BinaryExpressionTemplate;
+
+   static_assert( HasEnabledExpressionTemplates< T2 >::value,
+                  "Invalid operand in binary expression templates - expression templates are not enabled for the right operand." );
 
    BinaryExpressionTemplate( const T1& a, const T2& b )
-   : op1( a ), op2( b ) {}
+   : op1( a ), op2( b.getConstView() ) {}
 
    RealType getElement( const IndexType i ) const
    {
-      return Operation< T1, typename T2::RealType >::evaluate( op1, op2.getElement( i ) );
+      return Operation::evaluate( op1, op2.getElement( i ) );
    }
 
    __cuda_callable__
    RealType operator[]( const IndexType i ) const
    {
-      return Operation< T1, typename T2::RealType >::evaluate( op1, op2[ i ] );
+      return Operation::evaluate( op1, op2[ i ] );
    }
 
    __cuda_callable__
@@ -167,34 +180,42 @@ struct BinaryExpressionTemplate< T1, T2, Operation, ArithmeticVariable, VectorEx
       return op2.getSize();
    }
 
+   ConstViewType getConstView() const
+   {
+      return *this;
+   }
+
 protected:
    const T1 op1;
-   const T2 op2;
+   const typename T2::ConstViewType op2;
 };
 
 ////
 // Non-static unary expression template
 template< typename T1,
-          template< typename > class Operation >
-struct UnaryExpressionTemplate< T1, Operation, VectorExpressionVariable >
+          typename Operation >
+struct UnaryExpressionTemplate
 {
-   using RealType = decltype( Operation< typename T1::RealType >::
-                              evaluate( std::declval<T1>()[0] ) );
+   using RealType = decltype( Operation::evaluate( std::declval<T1>()[0] ) );
    using DeviceType = typename T1::DeviceType;
    using IndexType = typename T1::IndexType;
+   using ConstViewType = UnaryExpressionTemplate;
+
+   static_assert( HasEnabledExpressionTemplates< T1 >::value,
+                  "Invalid operand in unary expression templates - expression templates are not enabled for the operand." );
 
    UnaryExpressionTemplate( const T1& a )
-   : operand( a ) {}
+   : operand( a.getConstView() ) {}
 
    RealType getElement( const IndexType i ) const
    {
-      return Operation< typename T1::RealType >::evaluate( operand.getElement( i ) );
+      return Operation::evaluate( operand.getElement( i ) );
    }
 
    __cuda_callable__
    RealType operator[]( const IndexType i ) const
    {
-      return Operation< typename T1::RealType >::evaluate( operand[ i ] );
+      return Operation::evaluate( operand[ i ] );
    }
 
    __cuda_callable__
@@ -203,1920 +224,665 @@ struct UnaryExpressionTemplate< T1, Operation, VectorExpressionVariable >
       return operand.getSize();
    }
 
+   ConstViewType getConstView() const
+   {
+      return *this;
+   }
+
 protected:
-   const T1 operand;
+   const typename T1::ConstViewType operand;
 };
 
-////
-// Output stream
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-std::ostream& operator<<( std::ostream& str, const BinaryExpressionTemplate< T1, T2, Operation >& expression )
-{
-   str << "[ ";
-   for( int i = 0; i < expression.getSize() - 1; i++ )
-      str << expression.getElement( i ) << ", ";
-   str << expression.getElement( expression.getSize() - 1 ) << " ]";
-   return str;
-}
-
-template< typename T,
-          template< typename > class Operation >
-std::ostream& operator<<( std::ostream& str, const UnaryExpressionTemplate< T, Operation >& expression )
-{
-   str << "[ ";
-   for( int i = 0; i < expression.getSize() - 1; i++ )
-      str << expression.getElement( i ) << ", ";
-   str << expression.getElement( expression.getSize() - 1 ) << " ]";
-   return str;
-}
-
-////
-// Operators are supposed to be in the same namespace as the expression templates
-
 #ifndef DOXYGEN_ONLY
 
 ////
 // Binary expressions addition
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfBinaryExpression_t< ET1, ET2 >, typename = void >
 auto
-operator+( const BinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const BinaryExpressionTemplate< R1, R2, ROperation >& b )
+operator+( const ET1& a, const ET2& b )
 {
-   return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Addition >( a, b );
+   return BinaryExpressionTemplate< ET1, ET2, Addition >( a, b );
 }
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
+////
+// Binary expression subtraction
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfBinaryExpression_t< ET1, ET2 >, typename = void >
 auto
-operator+( const BinaryExpressionTemplate< T1, T2, Operation >& a,
-           const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
+operator-( const ET1& a, const ET2& b )
 {
-   return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Addition >( a, b );
+   return BinaryExpressionTemplate< ET1, ET2, Subtraction >( a, b );
 }
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
+////
+// Binary expression multiplication
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfBinaryExpression_t< ET1, ET2 >, typename = void >
 auto
-operator+( const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-           const BinaryExpressionTemplate< T1, T2, Operation >& b )
+operator*( const ET1& a, const ET2& b )
 {
-   return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Addition >( a, b );
+   return BinaryExpressionTemplate< ET1, ET2, Multiplication >( a, b );
 }
 
-template< typename T1,
-          template< typename > class Operation >
+////
+// Binary expression division
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfBinaryExpression_t< ET1, ET2 >, typename = void >
 auto
-operator+( const UnaryExpressionTemplate< T1, Operation >& a,
-           const typename UnaryExpressionTemplate< T1, Operation >::RealType& b )
+operator/( const ET1& a, const ET2& b )
 {
-   return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Addition >( a, b );
+   return BinaryExpressionTemplate< ET1, ET2, Division >( a, b );
 }
 
-template< typename T1,
-          template< typename > class Operation >
-auto
-operator+( const typename UnaryExpressionTemplate< T1, Operation >::RealType& a,
-           const UnaryExpressionTemplate< T1, Operation >& b )
+////
+// Comparison operator ==
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfBinaryExpression_t< ET1, ET2 >, typename = void >
+bool
+operator==( const ET1& a, const ET2& b )
 {
-   return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Addition >( a, b );
+   return Comparison< ET1, ET2 >::EQ( a, b );
 }
 
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-auto
-operator+( const UnaryExpressionTemplate< L1, LOperation >& a,
-           const BinaryExpressionTemplate< R1, R2, ROperation >& b )
+////
+// Comparison operator !=
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfBinaryExpression_t< ET1, ET2 >, typename = void >
+bool
+operator!=( const ET1& a, const ET2& b )
 {
-   return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Addition >( a, b );
+   return Comparison< ET1, ET2 >::NE( a, b );
 }
 
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-auto
-operator+( const BinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const UnaryExpressionTemplate< R1,ROperation >& b )
+////
+// Comparison operator <
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfBinaryExpression_t< ET1, ET2 >, typename = void >
+bool
+operator<( const ET1& a, const ET2& b )
 {
-   return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Addition >( a, b );
+   return Comparison< ET1, ET2 >::LT( a, b );
 }
 
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-auto
-operator+( const UnaryExpressionTemplate< L1,LOperation >& a,
-           const UnaryExpressionTemplate< R1,ROperation >& b )
+////
+// Comparison operator <=
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfBinaryExpression_t< ET1, ET2 >, typename = void >
+bool
+operator<=( const ET1& a, const ET2& b )
 {
-   return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Addition >( a, b );
+   return Comparison< ET1, ET2 >::LE( a, b );
 }
 
 ////
-// Binary expression subtraction
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-auto
-operator-( const BinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const BinaryExpressionTemplate< R1, R2, ROperation >& b )
+// Comparison operator >
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfBinaryExpression_t< ET1, ET2 >, typename = void >
+bool
+operator>( const ET1& a, const ET2& b )
 {
-   return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Subtraction >( a, b );
+   return Comparison< ET1, ET2 >::GT( a, b );
 }
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-auto
-operator-( const BinaryExpressionTemplate< T1, T2, Operation >& a,
-           const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
+////
+// Comparison operator >=
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfBinaryExpression_t< ET1, ET2 >, typename = void >
+bool
+operator>=( const ET1& a, const ET2& b )
 {
-   return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Subtraction >( a, b );
+   return Comparison< ET1, ET2 >::GE( a, b );
 }
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
+////
+// Scalar product
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfBinaryExpression_t< ET1, ET2 >, typename = void >
 auto
-operator-( const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-           const BinaryExpressionTemplate< T1, T2, Operation >& b )
+operator,( const ET1& a, const ET2& b )
 {
-   return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Subtraction >( a, b );
+   return ExpressionSum( a * b );
 }
 
-template< typename T1,
-          template< typename > class Operation >
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfBinaryExpression_t< ET1, ET2 >, typename = void >
 auto
-operator-( const UnaryExpressionTemplate< T1, Operation >& a,
-           const typename UnaryExpressionTemplate< T1, Operation >::RealType& b )
+dot( const ET1& a, const ET2& b )
 {
-   return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Subtraction >( a, b );
+   return (a, b);
 }
 
-template< typename T1,
-          template< typename > class Operation >
+////
+// Unary expression minus
+template< typename ET1,
+          typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void >
 auto
-operator-( const typename UnaryExpressionTemplate< T1, Operation >::RealType& a,
-           const UnaryExpressionTemplate< T1, Operation >& b )
+operator-( const ET1& a )
 {
-   return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Subtraction >( a, b );
+   return UnaryExpressionTemplate< ET1, Minus >( a );
 }
 
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
+////
+// Binary expression min
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfBinaryExpression_t< ET1, ET2 >, typename = void >
 auto
-operator-( const UnaryExpressionTemplate< L1, LOperation >& a,
-           const BinaryExpressionTemplate< R1, R2, ROperation >& b )
+min( const ET1& a, const ET2& b )
 {
-   return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Subtraction >( a, b );
+   return BinaryExpressionTemplate< ET1, ET2, Min >( a, b );
 }
 
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
+////
+// Binary expression max
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfBinaryExpression_t< ET1, ET2 >, typename = void >
 auto
-operator-( const BinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const UnaryExpressionTemplate< R1,ROperation >& b )
+max( const ET1& a, const ET2& b )
 {
-   return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Subtraction >( a, b );
+   return BinaryExpressionTemplate< ET1, ET2, Max >( a, b );
 }
 
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
+////
+// Abs
+template< typename ET1,
+          typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void >
 auto
-operator-( const UnaryExpressionTemplate< L1,LOperation >& a,
-           const UnaryExpressionTemplate< R1,ROperation >& b )
+abs( const ET1& a )
 {
-   return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Subtraction >( a, b );
+   return UnaryExpressionTemplate< ET1, Abs >( a );
 }
 
 ////
-// Binary expression multiplication
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
+// Pow
+template< typename ET1, typename Real,
+          typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void >
 auto
-operator*( const BinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const BinaryExpressionTemplate< R1, R2, ROperation >& b )
+pow( const ET1& a, const Real& exp )
 {
-   return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Multiplication >( a, b );
+   return BinaryExpressionTemplate< ET1, Real, Pow >( a, exp );
 }
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
+////
+// Exp
+template< typename ET1,
+          typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void >
 auto
-operator*( const BinaryExpressionTemplate< T1, T2, Operation >& a,
-           const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
+exp( const ET1& a )
 {
-   return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Multiplication >( a, b );
+   return UnaryExpressionTemplate< ET1, Exp >( a );
 }
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
+////
+// Sqrt
+template< typename ET1,
+          typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void >
 auto
-operator*( const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-           const BinaryExpressionTemplate< T1, T2, Operation >& b )
+sqrt( const ET1& a )
 {
-   return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Multiplication >( a, b );
+   return UnaryExpressionTemplate< ET1, Sqrt >( a );
 }
 
-template< typename T1,
-          template< typename > class Operation >
+////
+// Cbrt
+template< typename ET1,
+          typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void >
 auto
-operator*( const UnaryExpressionTemplate< T1, Operation >& a,
-           const typename UnaryExpressionTemplate< T1, Operation >::RealType& b )
+cbrt( const ET1& a )
 {
-   return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Multiplication >( a, b );
+   return UnaryExpressionTemplate< ET1, Cbrt >( a );
 }
 
-template< typename T1,
-          template< typename > class Operation >
+////
+// Log
+template< typename ET1,
+          typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void >
 auto
-operator*( const typename UnaryExpressionTemplate< T1, Operation >::RealType& a,
-           const UnaryExpressionTemplate< T1, Operation >& b )
+log( const ET1& a )
 {
-   return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Multiplication >( a, b );
+   return UnaryExpressionTemplate< ET1, Log >( a );
 }
 
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
+////
+// Log10
+template< typename ET1,
+          typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void >
 auto
-operator*( const UnaryExpressionTemplate< L1, LOperation >& a,
-           const BinaryExpressionTemplate< R1, R2, ROperation >& b )
+log10( const ET1& a )
 {
-   return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Multiplication >( a, b );
+   return UnaryExpressionTemplate< ET1, Log10 >( a );
 }
 
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
+////
+// Log2
+template< typename ET1,
+          typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void >
 auto
-operator*( const BinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const UnaryExpressionTemplate< R1, ROperation >& b )
+log2( const ET1& a )
 {
-   return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Multiplication >( a, b );
+   return UnaryExpressionTemplate< ET1, Log2 >( a );
 }
 
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
+////
+// Sin
+template< typename ET1,
+          typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void >
 auto
-operator*( const UnaryExpressionTemplate< L1,LOperation >& a,
-           const UnaryExpressionTemplate< R1,ROperation >& b )
+sin( const ET1& a )
 {
-   return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Multiplication >( a, b );
+   return UnaryExpressionTemplate< ET1, Sin >( a );
 }
 
 ////
-// Binary expression division
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
+// Cos
+template< typename ET1,
+          typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void >
 auto
-operator/( const BinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const BinaryExpressionTemplate< R1, R2, ROperation >& b )
+cos( const ET1& a )
 {
-   return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Division >( a, b );
+   return UnaryExpressionTemplate< ET1, Cos >( a );
 }
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
+////
+// Tan
+template< typename ET1,
+          typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void >
 auto
-operator/( const BinaryExpressionTemplate< T1, T2, Operation >& a,
-           const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
+tan( const ET1& a )
 {
-   return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Division >( a, b );
+   return UnaryExpressionTemplate< ET1, Tan >( a );
 }
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
+////
+// Asin
+template< typename ET1,
+          typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void >
 auto
-operator/( const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-           const BinaryExpressionTemplate< T1, T2, Operation >& b )
+asin( const ET1& a )
 {
-   return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Division >( a, b );
+   return UnaryExpressionTemplate< ET1, Asin >( a );
 }
 
-template< typename T1,
-          template< typename > class Operation >
+////
+// Acos
+template< typename ET1,
+          typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void >
 auto
-operator/( const UnaryExpressionTemplate< T1, Operation >& a,
-           const typename UnaryExpressionTemplate< T1, Operation >::RealType& b )
+acos( const ET1& a )
 {
-   return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Division >( a, b );
+   return UnaryExpressionTemplate< ET1, Acos >( a );
 }
 
-template< typename T1,
-          template< typename > class Operation >
+////
+// Atan
+template< typename ET1,
+          typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void >
 auto
-operator/( const typename UnaryExpressionTemplate< T1, Operation >::RealType& a,
-           const UnaryExpressionTemplate< T1, Operation >& b )
+atan( const ET1& a )
 {
-   return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Division >( a, b );
+   return UnaryExpressionTemplate< ET1, Atan >( a );
 }
 
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
+////
+// Sinh
+template< typename ET1,
+          typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void >
 auto
-operator/( const UnaryExpressionTemplate< L1, LOperation >& a,
-           const BinaryExpressionTemplate< R1, R2, ROperation >& b )
+sinh( const ET1& a )
 {
-   return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Division >( a, b );
+   return UnaryExpressionTemplate< ET1, Sinh >( a );
 }
 
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
+////
+// Cosh
+template< typename ET1,
+          typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void >
 auto
-operator/( const BinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const UnaryExpressionTemplate< R1,ROperation >& b )
+cosh( const ET1& a )
 {
-   return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Division >( a, b );
+   return UnaryExpressionTemplate< ET1, Cosh >( a );
 }
 
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
+////
+// Tanh
+template< typename ET1,
+          typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void >
 auto
-operator/( const UnaryExpressionTemplate< L1,LOperation >& a,
-           const UnaryExpressionTemplate< R1,ROperation >& b )
+tanh( const ET1& a )
 {
-   return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Division >( a, b );
+   return UnaryExpressionTemplate< ET1, Tanh >( a );
 }
 
 ////
-// Comparison operator ==
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-bool
-operator==( const BinaryExpressionTemplate< L1, L2, LOperation >& a,
-            const BinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::EQ( a, b );
-}
-
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-bool
-operator==( const BinaryExpressionTemplate< T1, T2, Operation >& a,
-            const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
+// Asinh
+template< typename ET1,
+          typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void >
+auto
+asinh( const ET1& a )
 {
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::EQ( a, b );
+   return UnaryExpressionTemplate< ET1, Asinh >( a );
 }
 
-template< typename T1,
-          template< typename > class Operation >
-bool
-operator==( const UnaryExpressionTemplate< T1, Operation >& a,
-            const typename UnaryExpressionTemplate< T1, Operation >::RealType& b )
+////
+// Acosh
+template< typename ET1,
+          typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void >
+auto
+acosh( const ET1& a )
 {
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::EQ( a, b );
+   return UnaryExpressionTemplate< ET1, Acosh >( a );
 }
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-bool
-operator==( const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-            const BinaryExpressionTemplate< T1, T2, Operation >& b )
+////
+// Atanh
+template< typename ET1,
+          typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void >
+auto
+atanh( const ET1& a )
 {
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::EQ( a, b );
+   return UnaryExpressionTemplate< ET1, Atanh >( a );
 }
 
-template< typename T1,
-          template< typename > class Operation >
-bool
-operator==( const typename UnaryExpressionTemplate< T1, Operation >::RealType& a,
-            const UnaryExpressionTemplate< T1, Operation >& b )
+////
+// Floor
+template< typename ET1,
+          typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void >
+auto
+floor( const ET1& a )
 {
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::EQ( a, b );
+   return UnaryExpressionTemplate< ET1, Floor >( a );
 }
 
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-bool
-operator==( const UnaryExpressionTemplate< L1, LOperation >& a,
-            const BinaryExpressionTemplate< R1, R2, ROperation >& b )
+////
+// Ceil
+template< typename ET1,
+          typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void >
+auto
+ceil( const ET1& a )
 {
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::EQ( a, b );
+   return UnaryExpressionTemplate< ET1, Ceil >( a );
 }
 
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-bool
-operator==( const BinaryExpressionTemplate< L1, L2, LOperation >& a,
-            const UnaryExpressionTemplate< R1,ROperation >& b )
+////
+// Sign
+template< typename ET1,
+          typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void >
+auto
+sign( const ET1& a )
 {
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::EQ( a, b );
+   return UnaryExpressionTemplate< ET1, Sign >( a );
 }
 
 ////
-// Comparison operator !=
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-bool
-operator!=( const BinaryExpressionTemplate< L1, L2, LOperation >& a,
-            const BinaryExpressionTemplate< R1, R2, ROperation >& b )
+// Cast
+template< typename ResultType,
+          typename ET1,
+          typename..., typename = EnableIfUnaryExpression_t< ET1 >,
+          // workaround: templated type alias cannot be declared at block level
+          typename CastOperation = typename Cast< ResultType >::Operation,
+          typename = void >
+auto
+cast( const ET1& a )
 {
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b );
+   return UnaryExpressionTemplate< ET1, CastOperation >( a );
 }
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-bool
-operator!=( const BinaryExpressionTemplate< T1, T2, Operation >& a,
-            const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
+////
+// Vertical operations
+template< typename ET1,
+          typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void >
+auto
+min( const ET1& a )
 {
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b );
+   return ExpressionMin( a );
 }
 
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-bool
-operator!=( const UnaryExpressionTemplate< L1, LOperation >& a,
-            const UnaryExpressionTemplate< R1, ROperation >& b )
+template< typename ET1,
+          typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void >
+auto
+argMin( const ET1& a )
 {
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b );
+   return ExpressionArgMin( a );
 }
 
-template< typename T1,
-          template< typename > class Operation >
-bool
-operator!=( const UnaryExpressionTemplate< T1, Operation >& a,
-            const typename UnaryExpressionTemplate< T1, Operation >::RealType& b )
+template< typename ET1,
+          typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void >
+auto
+max( const ET1& a )
 {
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b );
+   return ExpressionMax( a );
 }
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-bool
-operator!=( const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-            const BinaryExpressionTemplate< T1, T2, Operation >& b )
+template< typename ET1,
+          typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void >
+auto
+argMax( const ET1& a )
 {
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b );
+   return ExpressionArgMax( a );
 }
 
-template< typename T1,
-          template< typename > class Operation >
-bool
-operator!=( const typename UnaryExpressionTemplate< T1, Operation >::RealType& a,
-            const UnaryExpressionTemplate< T1, Operation >& b )
+template< typename ET1,
+          typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void >
+auto
+sum( const ET1& a )
 {
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b );
+   return ExpressionSum( a );
 }
 
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-bool
-operator!=( const UnaryExpressionTemplate< L1, LOperation >& a,
-            const BinaryExpressionTemplate< R1, R2, ROperation >& b )
+template< typename ET1,
+          typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void >
+auto
+maxNorm( const ET1& a )
 {
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b );
+   return max( abs( a ) );
 }
 
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-bool
-operator!=( const BinaryExpressionTemplate< L1, L2, LOperation >& a,
-            const UnaryExpressionTemplate< R1,ROperation >& b )
+template< typename ET1,
+          typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void >
+auto
+l1Norm( const ET1& a )
 {
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b );
+   return sum( abs( a ) );
 }
 
-////
-// Comparison operator <
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-bool
-operator<( const BinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const BinaryExpressionTemplate< R1, R2, ROperation >& b )
+template< typename ET1,
+          typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void >
+auto
+l2Norm( const ET1& a )
 {
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b );
+   using TNL::sqrt;
+   return sqrt( sum( a * a ) );
 }
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-bool
-operator<( const BinaryExpressionTemplate< T1, T2, Operation >& a,
-           const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
+template< typename ET1,
+          typename Real,
+          typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void >
+auto
+lpNorm( const ET1& a, const Real& p )
+// since (1.0 / p) has type double, TNL::pow returns double
+-> double
 {
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b );
+   if( p == 1.0 )
+      return l1Norm( a );
+   if( p == 2.0 )
+      return l2Norm( a );
+   using TNL::pow;
+   return pow( sum( pow( abs( a ), p ) ), 1.0 / p );
 }
 
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-bool
-operator<( const UnaryExpressionTemplate< L1, LOperation >& a,
-           const UnaryExpressionTemplate< R1, ROperation >& b )
+template< typename ET1,
+          typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void >
+auto
+product( const ET1& a )
 {
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b );
+   return ExpressionProduct( a );
 }
 
-template< typename T1,
-          template< typename > class Operation >
-bool
-operator<( const UnaryExpressionTemplate< T1, Operation >& a,
-           const typename UnaryExpressionTemplate< T1, Operation >::RealType& b )
+template< typename ET1,
+          typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void >
+auto
+logicalAnd( const ET1& a )
 {
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b );
+   return ExpressionLogicalAnd( a );
 }
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-bool
-operator<( const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-           const BinaryExpressionTemplate< T1, T2, Operation >& b )
+template< typename ET1,
+          typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void >
+auto
+logicalOr( const ET1& a )
 {
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b );
+   return ExpressionLogicalOr( a );
 }
 
-template< typename T1,
-          template< typename > class Operation >
-bool
-operator<( const typename UnaryExpressionTemplate< T1, Operation >::RealType& a,
-           const UnaryExpressionTemplate< T1, Operation >& b )
+template< typename ET1,
+          typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void >
+auto
+binaryAnd( const ET1& a )
 {
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b );
+   return ExpressionBinaryAnd( a );
 }
 
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-bool
-operator<( const UnaryExpressionTemplate< L1, LOperation >& a,
-           const BinaryExpressionTemplate< R1, R2, ROperation >& b )
+template< typename ET1,
+          typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void >
+auto
+binaryOr( const ET1& a )
 {
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b );
+   return ExpressionBinaryOr( a );
 }
 
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-bool
-operator<( const BinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const UnaryExpressionTemplate< R1,ROperation >& b )
-{
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b );
-}
+#endif // DOXYGEN_ONLY
 
 ////
-// Comparison operator <=
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-bool
-operator<=( const BinaryExpressionTemplate< L1, L2, LOperation >& a,
-            const BinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b );
-}
-
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-bool
-operator<=( const BinaryExpressionTemplate< T1, T2, Operation >& a,
-            const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
-{
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b );
-}
-
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-bool
-operator<=( const UnaryExpressionTemplate< L1, LOperation >& a,
-            const UnaryExpressionTemplate< R1, ROperation >& b )
-{
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b );
-}
-
-template< typename T1,
-          template< typename > class Operation >
-bool
-operator<=( const UnaryExpressionTemplate< T1, Operation >& a,
-            const typename UnaryExpressionTemplate< T1, Operation >::RealType& b )
-{
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b );
-}
-
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-bool
-operator<=( const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-            const BinaryExpressionTemplate< T1, T2, Operation >& b )
-{
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b );
-}
-
-template< typename T1,
-          template< typename > class Operation >
-bool
-operator<=( const typename UnaryExpressionTemplate< T1, Operation >::RealType& a,
-            const UnaryExpressionTemplate< T1, Operation >& b )
-{
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b );
-}
-
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-bool
-operator<=( const UnaryExpressionTemplate< L1, LOperation >& a,
-            const BinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-bool
-operator<=( const BinaryExpressionTemplate< L1, L2, LOperation >& a,
-            const UnaryExpressionTemplate< R1,ROperation >& b )
-{
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b );
-}
-
-////
-// Comparison operator >
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-bool
-operator>( const BinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const BinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GT( a, b );
-}
-
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-bool
-operator>( const BinaryExpressionTemplate< T1, T2, Operation >& a,
-           const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
-{
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GT( a, b );
-}
-
-template< typename T1,
-          template< typename > class Operation >
-bool
-operator>( const UnaryExpressionTemplate< T1, Operation >& a,
-           const typename UnaryExpressionTemplate< T1, Operation >::RealType& b )
-{
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GT( a, b );
-}
-
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-bool
-operator>( const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-           const BinaryExpressionTemplate< T1, T2, Operation >& b )
-{
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GT( a, b );
-}
-
-template< typename T1,
-          template< typename > class Operation >
-bool
-operator>( const typename UnaryExpressionTemplate< T1, Operation >::RealType& a,
-           const UnaryExpressionTemplate< T1, Operation >& b )
-{
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GT( a, b );
-}
-
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-bool
-operator>( const UnaryExpressionTemplate< L1, LOperation >& a,
-           const BinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GT( a, b );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-bool
-operator>( const BinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const UnaryExpressionTemplate< R1,ROperation >& b )
-{
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GT( a, b );
-}
-
-////
-// Comparison operator >=
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-bool
-operator>=( const BinaryExpressionTemplate< L1, L2, LOperation >& a,
-            const BinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GE( a, b );
-}
-
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-bool
-operator>=( const BinaryExpressionTemplate< T1, T2, Operation >& a,
-            const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
-{
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GE( a, b );
-}
-
-template< typename T1,
-          template< typename > class Operation >
-bool
-operator>=( const UnaryExpressionTemplate< T1, Operation >& a,
-            const typename UnaryExpressionTemplate< T1, Operation >::RealType& b )
-{
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GE( a, b );
-}
-
+// Output stream
 template< typename T1,
           typename T2,
-          template< typename, typename > class Operation >
-bool
-operator>=( const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-            const BinaryExpressionTemplate< T1, T2, Operation >& b )
-{
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GE( a, b );
-}
-
-template< typename T1,
-          template< typename > class Operation >
-bool
-operator>=( const typename UnaryExpressionTemplate< T1, Operation >::RealType& a,
-            const UnaryExpressionTemplate< T1, Operation >& b )
-{
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GE( a, b );
-}
-
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-bool
-operator>=( const UnaryExpressionTemplate< L1, LOperation >& a,
-            const BinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GE( a, b );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-bool
-operator>=( const BinaryExpressionTemplate< L1, L2, LOperation >& a,
-            const UnaryExpressionTemplate< R1,ROperation >& b )
-{
-   return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GE( a, b );
-}
-
-////
-// Unary operations
-
-////
-// Minus
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-operator-( const BinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return UnaryExpressionTemplate< std::decay_t<decltype(a)>, Minus >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-operator-( const UnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return UnaryExpressionTemplate< std::decay_t<decltype(a)>, Minus >( a );
-}
-
-////
-// Scalar product
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-auto
-operator,( const BinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const BinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return ExpressionSum( a * b );
-}
-
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-auto
-operator,( const UnaryExpressionTemplate< L1, LOperation >& a,
-           const UnaryExpressionTemplate< R1, ROperation >& b )
-{
-   return ExpressionSum( a * b );
-}
-
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-auto
-operator,( const UnaryExpressionTemplate< L1, LOperation >& a,
-           const BinaryExpressionTemplate< R1, R2, ROperation >& b )
+          typename Operation >
+std::ostream& operator<<( std::ostream& str, const BinaryExpressionTemplate< T1, T2, Operation >& expression )
 {
-   return ExpressionSum( a * b );
+   str << "[ ";
+   for( int i = 0; i < expression.getSize() - 1; i++ )
+      str << expression.getElement( i ) << ", ";
+   str << expression.getElement( expression.getSize() - 1 ) << " ]";
+   return str;
 }
 
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-auto
-operator,( const BinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const UnaryExpressionTemplate< R1,ROperation >& b )
+template< typename T,
+          typename Operation >
+std::ostream& operator<<( std::ostream& str, const UnaryExpressionTemplate< T, Operation >& expression )
 {
-   return ExpressionSum( a * b );
+   str << "[ ";
+   for( int i = 0; i < expression.getSize() - 1; i++ )
+      str << expression.getElement( i ) << ", ";
+   str << expression.getElement( expression.getSize() - 1 ) << " ]";
+   return str;
 }
 
-#endif // DOXYGEN_ONLY
-
 } // namespace Expressions
-} // namespace Containers
-
-////
-// All operations are supposed to be in namespace TNL
-
-#ifndef DOXYGEN_ONLY
-
-////
-// Binary expression min
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-auto
-min( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a,
-     const Containers::Expressions::BinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return Containers::Expressions::BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b );
-}
-
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-auto
-min( const Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >& a,
-     const typename Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
-{
-   return Containers::Expressions::BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b );
-}
-
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-auto
-min( const typename Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-     const Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >& b )
-{
-   return Containers::Expressions::BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b );
-}
-
-template< typename T1,
-          template< typename > class Operation >
-auto
-min( const Containers::Expressions::UnaryExpressionTemplate< T1, Operation >& a,
-     const typename Containers::Expressions::UnaryExpressionTemplate< T1, Operation >::RealType& b )
-{
-   return Containers::Expressions::BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b );
-}
-
-template< typename T1,
-          template< typename > class Operation >
-auto
-min( const typename Containers::Expressions::UnaryExpressionTemplate< T1, Operation >::RealType& a,
-     const Containers::Expressions::UnaryExpressionTemplate< T1, Operation >& b )
-{
-   return Containers::Expressions::BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b );
-}
-
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-auto
-min( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a,
-     const typename Containers::Expressions::BinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return Containers::Expressions::BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-auto
-min( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a,
-     const Containers::Expressions::UnaryExpressionTemplate< R1,ROperation >& b )
-{
-   return Containers::Expressions::BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b );
-}
-
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-auto
-min( const Containers::Expressions::UnaryExpressionTemplate< L1,LOperation >& a,
-     const Containers::Expressions::UnaryExpressionTemplate< R1,ROperation >& b )
-{
-   return Containers::Expressions::BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b );
-}
-
-////
-// Binary expression max
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-auto
-max( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a,
-     const Containers::Expressions::BinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return Containers::Expressions::BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b );
-}
-
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-auto
-max( const Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >& a,
-     const typename Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
-{
-   return Containers::Expressions::BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b );
-}
-
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-auto
-max( const typename Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-     const Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >& b )
-{
-   return Containers::Expressions::BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b );
-}
-
-template< typename T1,
-          template< typename > class Operation >
-auto
-max( const Containers::Expressions::UnaryExpressionTemplate< T1, Operation >& a,
-     const typename Containers::Expressions::UnaryExpressionTemplate< T1, Operation >::RealType& b )
-{
-   return Containers::Expressions::BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b );
-}
-
-template< typename T1,
-          template< typename > class Operation >
-auto
-max( const typename Containers::Expressions::UnaryExpressionTemplate< T1, Operation >::RealType& a,
-     const Containers::Expressions::UnaryExpressionTemplate< T1, Operation >& b )
-{
-   return Containers::Expressions::BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b );
-}
-
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-auto
-max( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a,
-     const Containers::Expressions::BinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return Containers::Expressions::BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-auto
-max( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a,
-     const Containers::Expressions::UnaryExpressionTemplate< R1,ROperation >& b )
-{
-   return Containers::Expressions::BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b );
-}
-
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-auto
-max( const Containers::Expressions::UnaryExpressionTemplate< L1,LOperation >& a,
-     const Containers::Expressions::UnaryExpressionTemplate< R1,ROperation >& b )
-{
-   return Containers::Expressions::BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b );
-}
-
-////
-// Abs
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-abs( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Abs >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-abs( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Abs >( a );
-}
-
-////
-// Pow
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename Real >
-auto
-pow( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a, const Real& exp )
-{
-   return Containers::Expressions::BinaryExpressionTemplate< std::decay_t<decltype(a)>, Real, Containers::Expressions::Pow >( a, exp );
-}
 
-template< typename L1,
-          template< typename > class LOperation,
-          typename Real >
-auto
-pow( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a, const Real& exp )
-{
-   return Containers::Expressions::BinaryExpressionTemplate< std::decay_t<decltype(a)>, Real, Containers::Expressions::Pow >( a, exp );
-}
+// Make all operators visible in the TNL::Containers namespace to be considered
+// even for Vector and VectorView
+using Expressions::operator+;
+using Expressions::operator-;
+using Expressions::operator*;
+using Expressions::operator/;
+using Expressions::operator,;
+using Expressions::operator==;
+using Expressions::operator!=;
+using Expressions::operator<;
+using Expressions::operator<=;
+using Expressions::operator>;
+using Expressions::operator>=;
+
+// Make all functions visible in the TNL::Containers namespace
+using Expressions::dot;
+using Expressions::min;
+using Expressions::max;
+using Expressions::abs;
+using Expressions::pow;
+using Expressions::exp;
+using Expressions::sqrt;
+using Expressions::cbrt;
+using Expressions::log;
+using Expressions::log10;
+using Expressions::log2;
+using Expressions::sin;
+using Expressions::cos;
+using Expressions::tan;
+using Expressions::asin;
+using Expressions::acos;
+using Expressions::atan;
+using Expressions::sinh;
+using Expressions::cosh;
+using Expressions::tanh;
+using Expressions::asinh;
+using Expressions::acosh;
+using Expressions::atanh;
+using Expressions::floor;
+using Expressions::ceil;
+using Expressions::sign;
+using Expressions::cast;
+using Expressions::argMin;
+using Expressions::argMax;
+using Expressions::sum;
+using Expressions::maxNorm;
+using Expressions::l1Norm;
+using Expressions::l2Norm;
+using Expressions::lpNorm;
+using Expressions::product;
+using Expressions::logicalAnd;
+using Expressions::logicalOr;
+using Expressions::binaryAnd;
+using Expressions::binaryOr;
 
-////
-// Exp
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-exp( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Exp >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-exp( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Exp >( a );
-}
-
-////
-// Sqrt
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-sqrt( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sqrt >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-sqrt( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sqrt >( a );
-}
-
-////
-// Cbrt
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-cbrt( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Cbrt >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-cbrt( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Cbrt >( a );
-}
-
-////
-// Log
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-log( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Log >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-log( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Log >( a );
-}
-
-////
-// Log10
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-log10( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Log10 >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-log10( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Log10 >( a );
-}
-
-////
-// Log2
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-log2( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Log2 >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-log2( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Log2 >( a );
-}
-
-////
-// Sin
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-sin( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sin >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-sin( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sin >( a );
-}
-
-////
-// Cos
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-cos( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Cos >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-cos( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Cos >( a );
-}
-
-////
-// Tan
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-tan( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Tan >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-tan( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Tan >( a );
-}
-
-////
-// Asin
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-asin( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Asin >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-asin( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Asin >( a );
-}
-
-////
-// Acos
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-acos( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Acos >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-acos( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Acos >( a );
-}
-
-////
-// Atan
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-atan( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Atan >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-atan( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Atan >( a );
-}
-
-////
-// Sinh
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-sinh( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sinh >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-sinh( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sinh >( a );
-}
-
-////
-// Cosh
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-cosh( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Cosh >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-cosh( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Cosh >( a );
-}
-
-////
-// Tanh
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-tanh( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Tanh >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-tanh( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Tanh >( a );
-}
-
-////
-// Asinh
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-asinh( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Asinh >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-asinh( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Asinh >( a );
-}
-
-////
-// Acosh
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-acosh( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Acosh >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-acosh( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Acosh >( a );
-}
-
-////
-// Atanh
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-atanh( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Atanh >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-atanh( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Atanh >( a );
-}
-
-////
-// Floor
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-floor( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Floor >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-floor( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Floor >( a );
-}
-
-////
-// Ceil
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-ceil( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Ceil >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-ceil( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Ceil >( a );
-}
-
-////
-// Sign
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-sign( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sign >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-sign( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sign >( a );
-}
-
-////
-// Cast
-template< typename ResultType,
-          typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          // workaround: templated type alias cannot be declared at block level
-          template<typename> class CastOperation = Containers::Expressions::Cast< ResultType >::template Operation >
-auto
-cast( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, CastOperation >( a );
-}
-
-template< typename ResultType,
-          typename L1,
-          template< typename > class LOperation,
-          // workaround: templated type alias cannot be declared at block level
-          template<typename> class CastOperation = Containers::Expressions::Cast< ResultType >::template Operation >
-auto
-cast( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, CastOperation >( a );
-}
-
-////
-// Vertical operations - min
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-min( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return ExpressionMin( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-min( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return ExpressionMin( a );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-argMin( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return ExpressionArgMin( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-argMin( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return ExpressionArgMin( a );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-max( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return ExpressionMax( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-max( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return ExpressionMax( a );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-argMax( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return ExpressionArgMax( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-argMax( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return ExpressionArgMax( a );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-sum( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return ExpressionSum( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-sum( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return ExpressionSum( a );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-maxNorm( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return max( abs( a ) );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-maxNorm( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return max( abs( a ) );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-l1Norm( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return ExpressionL1Norm( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-l1Norm( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return ExpressionL1Norm( a );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-l2Norm( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return TNL::sqrt( ExpressionL2Norm( a ) );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-l2Norm( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return TNL::sqrt( ExpressionL2Norm( a ) );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename Real >
-auto
-lpNorm( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a, const Real& p )
-// since (1.0 / p) has type double, TNL::pow returns double
--> double
-{
-   if( p == 1.0 )
-      return l1Norm( a );
-   if( p == 2.0 )
-      return l2Norm( a );
-   return TNL::pow( ExpressionLpNorm( a, p ), 1.0 / p );
-}
-
-template< typename L1,
-          template< typename > class LOperation,
-          typename Real >
-auto
-lpNorm( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a, const Real& p )
-// since (1.0 / p) has type double, TNL::pow returns double
--> double
-{
-   if( p == 1.0 )
-      return l1Norm( a );
-   if( p == 2.0 )
-      return l2Norm( a );
-   return TNL::pow( ExpressionLpNorm( a, p ), 1.0 / p );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-product( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return ExpressionProduct( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-product( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return ExpressionProduct( a );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-logicalOr( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return ExpressionLogicalOr( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-logicalOr( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return ExpressionLogicalOr( a );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-logicalAnd( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return ExpressionLogicalAnd( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-logicalAnd( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return ExpressionLogicalAnd( a );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-binaryOr( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return ExpressionBinaryOr( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-binaryOr( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return ExpressionBinaryOr( a );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-binaryAnd( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return ExpressionBinaryAnd( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-binaryAnd( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return ExpressionBinaryAnd( a );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-auto
-dot( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a,
-     const Containers::Expressions::BinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return (a, b);
-}
-
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-auto
-dot( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a,
-     const Containers::Expressions::UnaryExpressionTemplate< R1, ROperation >& b )
-{
-   return (a, b);
-}
-
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-auto
-dot( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a,
-     const Containers::Expressions::BinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return (a, b);
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-auto
-dot( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a,
-     const Containers::Expressions::UnaryExpressionTemplate< R1, ROperation >& b )
-{
-   return (a, b);
-}
-
-#endif // DOXYGEN_ONLY
+} // namespace Containers
 
+// Make all functions visible in the main TNL namespace
+using Containers::dot;
+using Containers::min;
+using Containers::max;
+using Containers::abs;
+using Containers::pow;
+using Containers::exp;
+using Containers::sqrt;
+using Containers::cbrt;
+using Containers::log;
+using Containers::log10;
+using Containers::log2;
+using Containers::sin;
+using Containers::cos;
+using Containers::tan;
+using Containers::asin;
+using Containers::acos;
+using Containers::atan;
+using Containers::sinh;
+using Containers::cosh;
+using Containers::tanh;
+using Containers::asinh;
+using Containers::acosh;
+using Containers::atanh;
+using Containers::floor;
+using Containers::ceil;
+using Containers::sign;
+using Containers::cast;
+using Containers::argMin;
+using Containers::argMax;
+using Containers::sum;
+using Containers::maxNorm;
+using Containers::l1Norm;
+using Containers::l2Norm;
+using Containers::lpNorm;
+using Containers::product;
+using Containers::logicalAnd;
+using Containers::logicalOr;
+using Containers::binaryAnd;
+using Containers::binaryOr;
 
 ////
 // Evaluation with reduction
 template< typename Vector,
    typename T1,
    typename T2,
-   template< typename, typename > class Operation,
+   typename Operation,
    typename Reduction,
    typename Result >
 Result evaluateAndReduce( Vector& lhs,
@@ -2135,7 +901,7 @@ Result evaluateAndReduce( Vector& lhs,
 
 template< typename Vector,
    typename T1,
-   template< typename > class Operation,
+   typename Operation,
    typename Reduction,
    typename Result >
 Result evaluateAndReduce( Vector& lhs,
@@ -2157,7 +923,7 @@ Result evaluateAndReduce( Vector& lhs,
 template< typename Vector,
    typename T1,
    typename T2,
-   template< typename, typename > class Operation,
+   typename Operation,
    typename Reduction,
    typename Result >
 Result addAndReduce( Vector& lhs,
@@ -2180,7 +946,7 @@ Result addAndReduce( Vector& lhs,
 
 template< typename Vector,
    typename T1,
-   template< typename > class Operation,
+   typename Operation,
    typename Reduction,
    typename Result >
 Result addAndReduce( Vector& lhs,
@@ -2206,7 +972,7 @@ Result addAndReduce( Vector& lhs,
 template< typename Vector,
    typename T1,
    typename T2,
-   template< typename, typename > class Operation,
+   typename Operation,
    typename Reduction,
    typename Result >
 Result addAndReduceAbs( Vector& lhs,
@@ -2229,7 +995,7 @@ Result addAndReduceAbs( Vector& lhs,
 
 template< typename Vector,
    typename T1,
-   template< typename > class Operation,
+   typename Operation,
    typename Reduction,
    typename Result >
 Result addAndReduceAbs( Vector& lhs,
diff --git a/src/TNL/Containers/Expressions/ExpressionVariableType.h b/src/TNL/Containers/Expressions/ExpressionVariableType.h
index ad9ab830ed30f1cbfc4f2701140ffb1efcb819e7..2095a4352c9874f6315f01dbaf475be2f1a66006 100644
--- a/src/TNL/Containers/Expressions/ExpressionVariableType.h
+++ b/src/TNL/Containers/Expressions/ExpressionVariableType.h
@@ -10,8 +10,7 @@
 
 #pragma once
 
-#include <TNL/TypeTraits.h>
-#include <TNL/Devices/Host.h>
+#include <TNL/Containers/Expressions/TypeTraits.h>
 
 namespace TNL {
 namespace Containers {
@@ -19,41 +18,24 @@ namespace Expressions {
 
 enum ExpressionVariableType { ArithmeticVariable, VectorExpressionVariable, OtherVariable };
 
-template< typename T,
-          bool IsArithmetic = std::is_arithmetic< T >::value,
-          bool IsVector = HasSubscriptOperator< T >::value >
-struct ExpressionVariableTypeGetter
+template< typename T, typename V = T >
+constexpr ExpressionVariableType
+getExpressionVariableType()
 {
-   static constexpr ExpressionVariableType value = OtherVariable;
-};
-
-template< typename T >
-struct  ExpressionVariableTypeGetter< T, true, false >
-{
-   static constexpr ExpressionVariableType value = ArithmeticVariable;
-};
-
-template< typename T >
-struct ExpressionVariableTypeGetter< T, false, true >
-{
-   static constexpr ExpressionVariableType value = VectorExpressionVariable;
-};
-
-////
-// Non-static expression templates might be passed on GPU, for example. In this
-// case, we cannot store ET operands using references but we need to make copies.
-template< typename T,
-          typename Device >
-struct OperandType
-{
-   using type = std::add_const_t< std::remove_reference_t< T > >;
-};
-
-template< typename T >
-struct OperandType< T, Devices::Host >
-{
-   using type = std::add_const_t< std::add_lvalue_reference_t< T > >;
-};
+   if( std::is_arithmetic< std::decay_t< T > >::value )
+      return ArithmeticVariable;
+   // vectors must be considered as an arithmetic type when used as RealType in another vector
+   if( IsArithmeticSubtype< T, V >::value )
+      return ArithmeticVariable;
+   if( HasEnabledExpressionTemplates< T >::value ||
+       HasEnabledStaticExpressionTemplates< T >::value ||
+       HasEnabledDistributedExpressionTemplates< T >::value
+   )
+      return VectorExpressionVariable;
+   if( IsArrayType< T >::value || IsStaticArrayType< T >::value )
+      return VectorExpressionVariable;
+   return OtherVariable;
+}
 
 } // namespace Expressions
 } // namespace Containers
diff --git a/src/TNL/Containers/Expressions/HorizontalOperations.h b/src/TNL/Containers/Expressions/HorizontalOperations.h
index 4bfe6a0146fde1f3ac52a2e2175ea56f422ad56c..cb49f7d47f35a85a35d3d8a51abb362cf793f899 100644
--- a/src/TNL/Containers/Expressions/HorizontalOperations.h
+++ b/src/TNL/Containers/Expressions/HorizontalOperations.h
@@ -16,9 +16,9 @@ namespace TNL {
 namespace Containers {
 namespace Expressions {
 
-template< typename T1, typename T2 >
 struct Addition
 {
+   template< typename T1, typename T2 >
    __cuda_callable__
    static auto evaluate( const T1& a, const T2& b ) -> decltype( a + b )
    {
@@ -26,9 +26,9 @@ struct Addition
    }
 };
 
-template< typename T1, typename T2 >
 struct Subtraction
 {
+   template< typename T1, typename T2 >
    __cuda_callable__
    static auto evaluate( const T1& a, const T2& b ) -> decltype( a - b )
    {
@@ -36,9 +36,9 @@ struct Subtraction
    }
 };
 
-template< typename T1, typename T2 >
 struct Multiplication
 {
+   template< typename T1, typename T2 >
    __cuda_callable__
    static auto evaluate( const T1& a, const T2& b ) -> decltype( a * b )
    {
@@ -46,9 +46,9 @@ struct Multiplication
    }
 };
 
-template< typename T1, typename T2 >
 struct Division
 {
+   template< typename T1, typename T2 >
    __cuda_callable__
    static auto evaluate( const T1& a, const T2& b ) -> decltype( a / b )
    {
@@ -56,272 +56,272 @@ struct Division
    }
 };
 
-template< typename T1, typename T2 >
 struct Min
 {
+   template< typename T1, typename T2 >
    __cuda_callable__
-   static auto evaluate( const T1& a, const T2& b ) -> decltype( TNL::min( a , b ) )
+   static auto evaluate( const T1& a, const T2& b ) -> decltype( min( a , b ) )
    {
-      return TNL::min( a, b );
+      return min( a, b );
    }
 };
 
-template< typename T1, typename T2 >
 struct Max
 {
+   template< typename T1, typename T2 >
    __cuda_callable__
-   static auto evaluate( const T1& a, const T2& b ) -> decltype( TNL::max( a, b ) )
+   static auto evaluate( const T1& a, const T2& b ) -> decltype( max( a, b ) )
    {
-      return TNL::max( a, b );
+      return max( a, b );
    }
 };
 
-template< typename T1 >
 struct Minus
 {
+   template< typename T1 >
    __cuda_callable__
-   static T1 evaluate( const T1& a )
+   static auto evaluate( const T1& a ) -> decltype( -a )
    {
       return -a;
    }
 };
 
-template< typename T1 >
 struct Abs
 {
+   template< typename T1 >
    __cuda_callable__
-   static auto evaluate( const T1& a ) -> decltype( TNL::abs( a ) )
+   static auto evaluate( const T1& a ) -> decltype( abs( a ) )
    {
-      return TNL::abs( a );
+      return abs( a );
    }
 };
 
-template< typename T1, typename T2 >
 struct Pow
 {
+   template< typename T1, typename T2 >
    __cuda_callable__
-   static auto evaluate( const T1& a, const T2& exp ) -> decltype( TNL::pow( a, exp ) )
+   static auto evaluate( const T1& a, const T2& exp ) -> decltype( pow( a, exp ) )
    {
-      return TNL::pow( a, exp );
+      return pow( a, exp );
    }
 };
 
-template< typename T1 >
 struct Exp
 {
+   template< typename T1 >
    __cuda_callable__
-   static auto evaluate( const T1& a ) -> decltype( TNL::exp( a ) )
+   static auto evaluate( const T1& a ) -> decltype( exp( a ) )
    {
-      return TNL::exp( a );
+      return exp( a );
    }
 };
 
-template< typename T1 >
 struct Sqrt
 {
+   template< typename T1 >
    __cuda_callable__
-   static auto evaluate( const T1& a ) -> decltype( TNL::sqrt( a ) )
+   static auto evaluate( const T1& a ) -> decltype( sqrt( a ) )
    {
-      return TNL::sqrt( a );
+      return sqrt( a );
    }
 };
 
-template< typename T1 >
 struct Cbrt
 {
+   template< typename T1 >
    __cuda_callable__
-   static auto evaluate( const T1& a ) -> decltype( TNL::cbrt( a ) )
+   static auto evaluate( const T1& a ) -> decltype( cbrt( a ) )
    {
-      return TNL::cbrt( a );
+      return cbrt( a );
    }
 };
 
-template< typename T1 >
 struct Log
 {
+   template< typename T1 >
    __cuda_callable__
-   static auto evaluate( const T1& a ) -> decltype( TNL::log( a ) )
+   static auto evaluate( const T1& a ) -> decltype( log( a ) )
    {
-      return TNL::log( a );
+      return log( a );
    }
 };
 
-template< typename T1 >
 struct Log10
 {
+   template< typename T1 >
    __cuda_callable__
-   static auto evaluate( const T1& a ) -> decltype( TNL::log10( a ) )
+   static auto evaluate( const T1& a ) -> decltype( log10( a ) )
    {
-      return TNL::log10( a );
+      return log10( a );
    }
 };
 
-template< typename T1 >
 struct Log2
 {
+   template< typename T1 >
    __cuda_callable__
-   static auto evaluate( const T1& a ) -> decltype( TNL::log2( a ) )
+   static auto evaluate( const T1& a ) -> decltype( log2( a ) )
    {
-      return TNL::log2( a );
+      return log2( a );
    }
 };
 
-template< typename T1 >
 struct Sin
 {
+   template< typename T1 >
    __cuda_callable__
-   static auto evaluate( const T1& a ) -> decltype( TNL::sin( a ) )
+   static auto evaluate( const T1& a ) -> decltype( sin( a ) )
    {
-      return TNL::sin( a );
+      return sin( a );
    }
 };
 
-template< typename T1 >
 struct Cos
 {
+   template< typename T1 >
    __cuda_callable__
-   static auto evaluate( const T1& a ) -> decltype( TNL::cos( a ) )
+   static auto evaluate( const T1& a ) -> decltype( cos( a ) )
    {
-      return TNL::cos( a );
+      return cos( a );
    }
 };
 
-template< typename T1 >
 struct Tan
 {
+   template< typename T1 >
    __cuda_callable__
-   static auto evaluate( const T1& a ) -> decltype( TNL::tan( a ) )
+   static auto evaluate( const T1& a ) -> decltype( tan( a ) )
    {
-      return TNL::tan( a );
+      return tan( a );
    }
 };
 
-template< typename T1 >
 struct Asin
 {
+   template< typename T1 >
    __cuda_callable__
-   static auto evaluate( const T1& a ) -> decltype( TNL::asin( a ) )
+   static auto evaluate( const T1& a ) -> decltype( asin( a ) )
    {
-      return TNL::asin( a );
+      return asin( a );
    }
 };
 
-template< typename T1 >
 struct Acos
 {
+   template< typename T1 >
    __cuda_callable__
-   static auto evaluate( const T1& a ) -> decltype( TNL::acos( a ) )
+   static auto evaluate( const T1& a ) -> decltype( acos( a ) )
    {
-      return TNL::acos( a );
+      return acos( a );
    }
 };
 
-template< typename T1 >
 struct Atan
 {
+   template< typename T1 >
    __cuda_callable__
-   static auto evaluate( const T1& a ) -> decltype( TNL::atan( a ) )
+   static auto evaluate( const T1& a ) -> decltype( atan( a ) )
    {
-      return TNL::atan( a );
+      return atan( a );
    }
 };
 
-template< typename T1 >
 struct Sinh
 {
+   template< typename T1 >
    __cuda_callable__
-   static auto evaluate( const T1& a ) -> decltype( TNL::sinh( a ) )
+   static auto evaluate( const T1& a ) -> decltype( sinh( a ) )
    {
-      return TNL::sinh( a );
+      return sinh( a );
    }
 };
 
-template< typename T1 >
 struct Cosh
 {
+   template< typename T1 >
    __cuda_callable__
-   static auto evaluate( const T1& a ) -> decltype( TNL::cosh( a ) )
+   static auto evaluate( const T1& a ) -> decltype( cosh( a ) )
    {
-      return TNL::cosh( a );
+      return cosh( a );
    }
 };
 
-template< typename T1 >
 struct Tanh
 {
+   template< typename T1 >
    __cuda_callable__
-   static auto evaluate( const T1& a ) -> decltype( TNL::tanh( a ) )
+   static auto evaluate( const T1& a ) -> decltype( tanh( a ) )
    {
-      return TNL::tanh( a );
+      return tanh( a );
    }
 };
 
-template< typename T1 >
 struct Asinh
 {
+   template< typename T1 >
    __cuda_callable__
-   static auto evaluate( const T1& a ) -> decltype( TNL::asinh( a ) )
+   static auto evaluate( const T1& a ) -> decltype( asinh( a ) )
    {
-      return TNL::asinh( a );
+      return asinh( a );
    }
 };
 
-template< typename T1 >
 struct Acosh
 {
+   template< typename T1 >
    __cuda_callable__
-   static auto evaluate( const T1& a ) -> decltype( TNL::acosh( a ) )
+   static auto evaluate( const T1& a ) -> decltype( acosh( a ) )
    {
-      return TNL::acosh( a );
+      return acosh( a );
    }
 };
 
-template< typename T1 >
 struct Atanh
 {
+   template< typename T1 >
    __cuda_callable__
-   static auto evaluate( const T1& a ) -> decltype( TNL::atanh( a ) )
+   static auto evaluate( const T1& a ) -> decltype( atanh( a ) )
    {
-      return TNL::atanh( a );
+      return atanh( a );
    }
 };
 
-template< typename T1 >
 struct Floor
 {
+   template< typename T1 >
    __cuda_callable__
-   static auto evaluate( const T1& a ) -> decltype( TNL::floor( a ) )
+   static auto evaluate( const T1& a ) -> decltype( floor( a ) )
    {
-      return TNL::floor( a );
+      return floor( a );
    }
 };
 
-template< typename T1 >
 struct Ceil
 {
+   template< typename T1 >
    __cuda_callable__
-   static auto evaluate( const T1& a ) -> decltype( TNL::ceil( a ) )
+   static auto evaluate( const T1& a ) -> decltype( ceil( a ) )
    {
-      return TNL::ceil( a );
+      return ceil( a );
    }
 };
 
-template< typename T1 >
 struct Sign
 {
+   template< typename T1 >
    __cuda_callable__
-   static auto evaluate( const T1& a ) -> decltype( TNL::sign( a ) )
+   static auto evaluate( const T1& a ) -> decltype( sign( a ) )
    {
-      return TNL::sign( a );
+      return sign( a );
    }
 };
 
 template< typename ResultType >
 struct Cast
 {
-   template< typename T1 >
    struct Operation
    {
+      template< typename T1 >
       __cuda_callable__
       static auto evaluate( const T1& a ) -> ResultType
       {
diff --git a/src/TNL/Containers/Expressions/StaticComparison.h b/src/TNL/Containers/Expressions/StaticComparison.h
index d12f1c12bdd0a5a4f63f1e3f507141d675f34706..af1bf17baf52579c7a586173215e7051069e3fff 100644
--- a/src/TNL/Containers/Expressions/StaticComparison.h
+++ b/src/TNL/Containers/Expressions/StaticComparison.h
@@ -19,8 +19,8 @@ namespace Expressions {
 
 template< typename T1,
           typename T2,
-          ExpressionVariableType T1Type = ExpressionVariableTypeGetter< T1 >::value,
-          ExpressionVariableType T2Type = ExpressionVariableTypeGetter< T2 >::value >
+          ExpressionVariableType T1Type = getExpressionVariableType< T1, T2 >(),
+          ExpressionVariableType T2Type = getExpressionVariableType< T2, T1 >() >
 struct StaticComparison;
 
 /////
diff --git a/src/TNL/Containers/Expressions/StaticExpressionTemplates.h b/src/TNL/Containers/Expressions/StaticExpressionTemplates.h
index d08f2b02b76fe0c47b1ac4d141a6d6f9d85b5586..89e13d7f129fc56f9bb361cf8656f8be13a3b3ea 100644
--- a/src/TNL/Containers/Expressions/StaticExpressionTemplates.h
+++ b/src/TNL/Containers/Expressions/StaticExpressionTemplates.h
@@ -25,32 +25,28 @@ namespace Containers {
 namespace Expressions {
 
 template< typename T1,
-          template< typename > class Operation,
-          ExpressionVariableType T1Type = ExpressionVariableTypeGetter< T1 >::value >
-struct StaticUnaryExpressionTemplate
-{};
+          typename Operation >
+struct StaticUnaryExpressionTemplate;
 
 template< typename T1,
-          template< typename > class Operation,
-          ExpressionVariableType T1Type >
-struct IsExpressionTemplate< StaticUnaryExpressionTemplate< T1, Operation, T1Type > >
+          typename Operation >
+struct HasEnabledStaticExpressionTemplates< StaticUnaryExpressionTemplate< T1, Operation > >
 : std::true_type
 {};
 
 template< typename T1,
           typename T2,
-          template< typename, typename > class Operation,
-          ExpressionVariableType T1Type = ExpressionVariableTypeGetter< T1 >::value,
-          ExpressionVariableType T2Type = ExpressionVariableTypeGetter< T2 >::value >
-struct StaticBinaryExpressionTemplate
-{};
+          typename Operation,
+          ExpressionVariableType T1Type = getExpressionVariableType< T1, T2 >(),
+          ExpressionVariableType T2Type = getExpressionVariableType< T2, T1 >() >
+struct StaticBinaryExpressionTemplate;
 
 template< typename T1,
           typename T2,
-          template< typename, typename > class Operation,
+          typename Operation,
           ExpressionVariableType T1Type,
           ExpressionVariableType T2Type >
-struct IsExpressionTemplate< StaticBinaryExpressionTemplate< T1, T2, Operation, T1Type, T2Type > >
+struct HasEnabledStaticExpressionTemplates< StaticBinaryExpressionTemplate< T1, T2, Operation, T1Type, T2Type > >
 : std::true_type
 {};
 
@@ -59,16 +55,20 @@ struct IsExpressionTemplate< StaticBinaryExpressionTemplate< T1, T2, Operation,
 // Static binary expression template
 template< typename T1,
           typename T2,
-          template< typename, typename > class Operation >
+          typename Operation >
 struct StaticBinaryExpressionTemplate< T1, T2, Operation, VectorExpressionVariable, VectorExpressionVariable >
 {
-   using RealType = decltype( Operation< typename T1::RealType, typename T2::RealType >::
-                              evaluate( std::declval<T1>()[0], std::declval<T2>()[0] ) );
+   using VectorOperandType = T1;
+   using RealType = decltype( Operation::evaluate( std::declval<T1>()[0], std::declval<T2>()[0] ) );
 
    static_assert( IsStaticArrayType< T1 >::value,
                   "Left-hand side operand of static expression is not static, i.e. based on static vector." );
    static_assert( IsStaticArrayType< T2 >::value,
                   "Right-hand side operand of static expression is not static, i.e. based on static vector." );
+   static_assert( HasEnabledStaticExpressionTemplates< T1 >::value,
+                  "Invalid operand in static binary expression templates - static expression templates are not enabled for the left operand." );
+   static_assert( HasEnabledStaticExpressionTemplates< T2 >::value,
+                  "Invalid operand in static binary expression templates - static expression templates are not enabled for the right operand." );
    static_assert( T1::getSize() == T2::getSize(),
                   "Attempt to mix static operands with different sizes." );
 
@@ -81,7 +81,7 @@ struct StaticBinaryExpressionTemplate< T1, T2, Operation, VectorExpressionVariab
    __cuda_callable__
    RealType operator[]( const int i ) const
    {
-      return Operation< typename T1::RealType, typename T2::RealType >::evaluate( op1[ i ], op2[ i ] );
+      return Operation::evaluate( op1[ i ], op2[ i ] );
    }
 
    __cuda_callable__
@@ -109,14 +109,16 @@ protected:
 
 template< typename T1,
           typename T2,
-          template< typename, typename > class Operation >
+          typename Operation >
 struct StaticBinaryExpressionTemplate< T1, T2, Operation, VectorExpressionVariable, ArithmeticVariable  >
 {
+   using VectorOperandType = T1;
+   using RealType = decltype( Operation::evaluate( std::declval<T1>()[0], std::declval<T2>() ) );
+
    static_assert( IsStaticArrayType< T1 >::value,
                   "Left-hand side operand of static expression is not static, i.e. based on static vector." );
-
-   using RealType = decltype( Operation< typename T1::RealType, T2 >::
-                              evaluate( std::declval<T1>()[0], std::declval<T2>() ) );
+   static_assert( HasEnabledStaticExpressionTemplates< T1 >::value,
+                  "Invalid operand in static binary expression templates - static expression templates are not enabled for the left operand." );
 
    static constexpr int getSize() { return T1::getSize(); };
 
@@ -127,7 +129,7 @@ struct StaticBinaryExpressionTemplate< T1, T2, Operation, VectorExpressionVariab
    __cuda_callable__
    RealType operator[]( const int i ) const
    {
-      return Operation< typename T1::RealType, T2 >::evaluate( op1[ i ], op2 );
+      return Operation::evaluate( op1[ i ], op2 );
    }
 
    __cuda_callable__
@@ -150,19 +152,21 @@ struct StaticBinaryExpressionTemplate< T1, T2, Operation, VectorExpressionVariab
 
 protected:
    const T1& op1;
-   const T2& op2;
+   const T2 op2;
 };
 
 template< typename T1,
           typename T2,
-          template< typename, typename > class Operation >
+          typename Operation >
 struct StaticBinaryExpressionTemplate< T1, T2, Operation, ArithmeticVariable, VectorExpressionVariable  >
 {
+   using VectorOperandType = T2;
+   using RealType = decltype( Operation::evaluate( std::declval<T1>(), std::declval<T2>()[0] ) );
+
    static_assert( IsStaticArrayType< T2 >::value,
                   "Right-hand side operand of static expression is not static, i.e. based on static vector." );
-
-   using RealType = decltype( Operation< T1, typename T2::RealType >::
-                              evaluate( std::declval<T1>(), std::declval<T2>()[0] ) );
+   static_assert( HasEnabledStaticExpressionTemplates< T2 >::value,
+                  "Invalid operand in static binary expression templates - static expression templates are not enabled for the right operand." );
 
    static constexpr int getSize() { return T2::getSize(); };
 
@@ -173,7 +177,7 @@ struct StaticBinaryExpressionTemplate< T1, T2, Operation, ArithmeticVariable, Ve
    __cuda_callable__
    RealType operator[]( const int i ) const
    {
-      return Operation< T1, typename T2::RealType >::evaluate( op1, op2[ i ] );
+      return Operation::evaluate( op1, op2[ i ] );
    }
 
    __cuda_callable__
@@ -195,18 +199,23 @@ struct StaticBinaryExpressionTemplate< T1, T2, Operation, ArithmeticVariable, Ve
    }
 
 protected:
-   const T1& op1;
+   const T1 op1;
    const T2& op2;
 };
 
 ////
 // Static unary expression template
 template< typename T1,
-          template< typename > class Operation >
-struct StaticUnaryExpressionTemplate< T1, Operation, VectorExpressionVariable >
+          typename Operation >
+struct StaticUnaryExpressionTemplate
 {
-   using RealType = decltype( Operation< typename T1::RealType >::
-                              evaluate( std::declval<T1>()[0] ) );
+   using VectorOperandType = T1;
+   using RealType = decltype( Operation::evaluate( std::declval<T1>()[0] ) );
+
+   static_assert( IsStaticArrayType< T1 >::value,
+                  "The operand of static expression is not static, i.e. based on static vector." );
+   static_assert( HasEnabledStaticExpressionTemplates< T1 >::value,
+                  "Invalid operand in static unary expression templates - static expression templates are not enabled for the operand." );
 
    static constexpr int getSize() { return T1::getSize(); };
 
@@ -217,7 +226,7 @@ struct StaticUnaryExpressionTemplate< T1, Operation, VectorExpressionVariable >
    __cuda_callable__
    RealType operator[]( const int i ) const
    {
-      return Operation< typename T1::RealType >::evaluate( operand[ i ] );
+      return Operation::evaluate( operand[ i ] );
    }
 
    __cuda_callable__
@@ -246,2043 +255,705 @@ protected:
 
 ////
 // Binary expressions addition
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfStaticBinaryExpression_t< ET1, ET2 > >
 __cuda_callable__
 auto
-operator+( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b )
+operator+( const ET1& a, const ET2& b )
 {
-   return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Addition >( a, b );
+   return StaticBinaryExpressionTemplate< ET1, ET2, Addition >( a, b );
 }
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
+////
+// Binary expression subtraction
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfStaticBinaryExpression_t< ET1, ET2 > >
 __cuda_callable__
 auto
-operator+( const StaticBinaryExpressionTemplate< T1, T2, Operation >& a,
-           const typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
+operator-( const ET1& a, const ET2& b )
 {
-   return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Addition >( a, b );
+   return StaticBinaryExpressionTemplate< ET1, ET2, Subtraction >( a, b );
 }
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
+////
+// Binary expression multiplication
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfStaticBinaryExpression_t< ET1, ET2 > >
 __cuda_callable__
 auto
-operator+( const typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-           const StaticBinaryExpressionTemplate< T1, T2, Operation >& b )
+operator*( const ET1& a, const ET2& b )
 {
-   return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Addition >( a, b );
+   return StaticBinaryExpressionTemplate< ET1, ET2, Multiplication >( a, b );
 }
 
-template< typename T1,
-          template< typename > class Operation >
+////
+// Binary expression division
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfStaticBinaryExpression_t< ET1, ET2 > >
 __cuda_callable__
 auto
-operator+( const StaticUnaryExpressionTemplate< T1, Operation >& a,
-           const typename StaticUnaryExpressionTemplate< T1, Operation >::RealType& b )
+operator/( const ET1& a, const ET2& b )
 {
-   return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Addition >( a, b );
+   return StaticBinaryExpressionTemplate< ET1, ET2, Division >( a, b );
 }
 
-template< typename T1,
-          template< typename > class Operation >
+////
+// Comparison operator ==
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfStaticBinaryExpression_t< ET1, ET2 > >
 __cuda_callable__
-auto
-operator+( const typename StaticUnaryExpressionTemplate< T1, Operation >::RealType& a,
-           const StaticUnaryExpressionTemplate< T1, Operation >& b )
+bool
+operator==( const ET1& a, const ET2& b )
 {
-   return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Addition >( a, b );
+   return StaticComparison< ET1, ET2 >::EQ( a, b );
 }
 
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
+////
+// Comparison operator !=
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfStaticBinaryExpression_t< ET1, ET2 > >
 __cuda_callable__
-auto
-operator+( const StaticUnaryExpressionTemplate< L1, LOperation >& a,
-           const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b )
+bool
+operator!=( const ET1& a, const ET2& b )
 {
-   return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Addition >( a, b );
+   return StaticComparison< ET1, ET2 >::NE( a, b );
 }
 
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
+////
+// Comparison operator <
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfStaticBinaryExpression_t< ET1, ET2 > >
 __cuda_callable__
-auto
-operator+( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const StaticUnaryExpressionTemplate< R1, ROperation >& b )
+bool
+operator<( const ET1& a, const ET2& b )
 {
-   return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Addition >( a, b );
+   return StaticComparison< ET1, ET2 >::LT( a, b );
 }
 
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
+////
+// Comparison operator <=
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfStaticBinaryExpression_t< ET1, ET2 > >
 __cuda_callable__
-auto
-operator+( const StaticUnaryExpressionTemplate< L1,LOperation >& a,
-           const StaticUnaryExpressionTemplate< R1,ROperation >& b )
+bool
+operator<=( const ET1& a, const ET2& b )
 {
-   return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Addition >( a, b );
+   return StaticComparison< ET1, ET2 >::LE( a, b );
 }
 
 ////
-// Binary expression subtraction
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
+// Comparison operator >
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfStaticBinaryExpression_t< ET1, ET2 > >
 __cuda_callable__
-auto
-operator-( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b )
+bool
+operator>( const ET1& a, const ET2& b )
 {
-   return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Subtraction >( a, b );
+   return StaticComparison< ET1, ET2 >::GT( a, b );
 }
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
+////
+// Comparison operator >=
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfStaticBinaryExpression_t< ET1, ET2 > >
 __cuda_callable__
-auto
-operator-( const StaticBinaryExpressionTemplate< T1, T2, Operation >& a,
-           const typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
+bool
+operator>=( const ET1& a, const ET2& b )
 {
-   return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Subtraction >( a, b );
+   return Expressions::StaticComparison< ET1, ET2 >::GE( a, b );
 }
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
+////
+// Scalar product
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfStaticBinaryExpression_t< ET1, ET2 > >
 __cuda_callable__
 auto
-operator-( const typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-           const StaticBinaryExpressionTemplate< T1, T2, Operation >& b )
+operator,( const ET1& a, const ET2& b )
 {
-   return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Subtraction >( a, b );
+   return StaticExpressionSum( a * b );
 }
 
-template< typename T1,
-          template< typename > class Operation >
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfStaticBinaryExpression_t< ET1, ET2 > >
 __cuda_callable__
 auto
-operator-( const StaticUnaryExpressionTemplate< T1, Operation >& a,
-           const typename StaticUnaryExpressionTemplate< T1, Operation >::RealType& b )
+dot( const ET1& a, const ET2& b )
 {
-   return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Subtraction >( a, b );
+   return (a, b);
 }
 
-template< typename T1,
-          template< typename > class Operation >
+////
+// Unary expression minus
+template< typename ET1,
+          typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > >
 __cuda_callable__
 auto
-operator-( const typename StaticUnaryExpressionTemplate< T1, Operation >::RealType& a,
-           const StaticUnaryExpressionTemplate< T1, Operation >& b )
+operator-( const ET1& a )
 {
-   return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Subtraction >( a, b );
+   return StaticUnaryExpressionTemplate< ET1, Minus >( a );
 }
 
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
+////
+// Binary expression min
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfStaticBinaryExpression_t< ET1, ET2 > >
 __cuda_callable__
 auto
-operator-( const StaticUnaryExpressionTemplate< L1, LOperation >& a,
-           const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b )
+min( const ET1& a, const ET2& b )
 {
-   return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Subtraction >( a, b );
+   return StaticBinaryExpressionTemplate< ET1, ET2, Min >( a, b );
 }
 
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
+////
+// Binary expression max
+template< typename ET1, typename ET2,
+          typename..., typename = EnableIfStaticBinaryExpression_t< ET1, ET2 > >
 __cuda_callable__
 auto
-operator-( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const StaticUnaryExpressionTemplate< R1,ROperation >& b )
+max( const ET1& a, const ET2& b )
 {
-   return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Subtraction >( a, b );
+   return StaticBinaryExpressionTemplate< ET1, ET2, Max >( a, b );
 }
 
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
+////
+// Abs
+template< typename ET1,
+          typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > >
 __cuda_callable__
 auto
-operator-( const StaticUnaryExpressionTemplate< L1,LOperation >& a,
-           const StaticUnaryExpressionTemplate< R1,ROperation >& b )
+abs( const ET1& a )
 {
-   return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Subtraction >( a, b );
+   return StaticUnaryExpressionTemplate< ET1, Abs >( a );
 }
 
 ////
-// Binary expression multiplication
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
+// Pow
+template< typename ET1, typename Real,
+          typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > >
 __cuda_callable__
 auto
-operator*( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b )
+pow( const ET1& a, const Real& exp )
 {
-   return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Multiplication >( a, b );
+   return StaticBinaryExpressionTemplate< ET1, Real, Pow >( a, exp );
 }
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
+////
+// Exp
+template< typename ET1,
+          typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > >
 __cuda_callable__
 auto
-operator*( const StaticBinaryExpressionTemplate< T1, T2, Operation >& a,
-           const typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
+exp( const ET1& a )
 {
-   return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Multiplication >( a, b );
+   return StaticUnaryExpressionTemplate< ET1, Exp >( a );
 }
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
+////
+// Sqrt
+template< typename ET1,
+          typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > >
 __cuda_callable__
 auto
-operator*( const typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-           const StaticBinaryExpressionTemplate< T1, T2, Operation >& b )
+sqrt( const ET1& a )
 {
-   return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Multiplication >( a, b );
+   return StaticUnaryExpressionTemplate< ET1, Sqrt >( a );
 }
 
-template< typename T1,
-          template< typename > class Operation >
+////
+// Cbrt
+template< typename ET1,
+          typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > >
 __cuda_callable__
 auto
-operator*( const StaticUnaryExpressionTemplate< T1, Operation >& a,
-           const typename StaticUnaryExpressionTemplate< T1, Operation >::RealType& b )
+cbrt( const ET1& a )
 {
-   return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Multiplication >( a, b );
+   return StaticUnaryExpressionTemplate< ET1, Cbrt >( a );
 }
 
-template< typename T1,
-          template< typename > class Operation >
+////
+// Log
+template< typename ET1,
+          typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > >
 __cuda_callable__
 auto
-operator*( const typename StaticUnaryExpressionTemplate< T1, Operation >::RealType& a,
-           const StaticUnaryExpressionTemplate< T1, Operation >& b )
+log( const ET1& a )
 {
-   return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Multiplication >( a, b );
+   return StaticUnaryExpressionTemplate< ET1, Log >( a );
 }
 
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
+////
+// Log10
+template< typename ET1,
+          typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > >
 __cuda_callable__
 auto
-operator*( const StaticUnaryExpressionTemplate< L1, LOperation >& a,
-           const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b )
+log10( const ET1& a )
 {
-   return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Multiplication >( a, b );
+   return StaticUnaryExpressionTemplate< ET1, Log10 >( a );
 }
 
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
+////
+// Log2
+template< typename ET1,
+          typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > >
 __cuda_callable__
 auto
-operator*( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const StaticUnaryExpressionTemplate< R1, ROperation >& b )
+log2( const ET1& a )
 {
-   return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Multiplication >( a, b );
+   return StaticUnaryExpressionTemplate< ET1, Log2 >( a );
 }
 
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
+////
+// Sin
+template< typename ET1,
+          typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > >
 __cuda_callable__
 auto
-operator*( const StaticUnaryExpressionTemplate< L1,LOperation >& a,
-           const StaticUnaryExpressionTemplate< R1,ROperation >& b )
+sin( const ET1& a )
 {
-   return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Multiplication >( a, b );
+   return StaticUnaryExpressionTemplate< ET1, Sin >( a );
 }
 
 ////
-// Binary expression division
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
+// Cos
+template< typename ET1,
+          typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > >
 __cuda_callable__
 auto
-operator/( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b )
+cos( const ET1& a )
 {
-   return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Division >( a, b );
+   return StaticUnaryExpressionTemplate< ET1, Cos >( a );
 }
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
+////
+// Tan
+template< typename ET1,
+          typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > >
 __cuda_callable__
 auto
-operator/( const StaticBinaryExpressionTemplate< T1, T2, Operation >& a,
-           const typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
+tan( const ET1& a )
 {
-   return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Division >( a, b );
+   return StaticUnaryExpressionTemplate< ET1, Tan >( a );
 }
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
+////
+// Asin
+template< typename ET1,
+          typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > >
 __cuda_callable__
 auto
-operator/( const typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-           const StaticBinaryExpressionTemplate< T1, T2, Operation >& b )
+asin( const ET1& a )
 {
-   return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Division >( a, b );
+   return StaticUnaryExpressionTemplate< ET1, Asin >( a );
 }
 
-template< typename T1,
-          template< typename > class Operation >
+////
+// Acos
+template< typename ET1,
+          typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > >
 __cuda_callable__
 auto
-operator/( const StaticUnaryExpressionTemplate< T1, Operation >& a,
-           const typename StaticUnaryExpressionTemplate< T1, Operation >::RealType& b )
+acos( const ET1& a )
 {
-   return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Division >( a, b );
+   return StaticUnaryExpressionTemplate< ET1, Acos >( a );
 }
 
-template< typename T1,
-          template< typename > class Operation >
+////
+// Atan
+template< typename ET1,
+          typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > >
 __cuda_callable__
 auto
-operator/( const typename StaticUnaryExpressionTemplate< T1, Operation >::RealType& a,
-           const StaticUnaryExpressionTemplate< T1, Operation >& b )
+atan( const ET1& a )
 {
-   return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Division >( a, b );
+   return StaticUnaryExpressionTemplate< ET1, Atan >( a );
 }
 
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
+////
+// Sinh
+template< typename ET1,
+          typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > >
 __cuda_callable__
 auto
-operator/( const StaticUnaryExpressionTemplate< L1, LOperation >& a,
-           const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b )
+sinh( const ET1& a )
 {
-   return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Division >( a, b );
+   return StaticUnaryExpressionTemplate< ET1, Sinh >( a );
 }
 
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
+////
+// Cosh
+template< typename ET1,
+          typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > >
 __cuda_callable__
 auto
-operator/( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const StaticUnaryExpressionTemplate< R1,ROperation >& b )
+cosh( const ET1& a )
 {
-   return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Division >( a, b );
+   return StaticUnaryExpressionTemplate< ET1, Cosh >( a );
 }
 
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
+////
+// Tanh
+template< typename ET1,
+          typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > >
 __cuda_callable__
 auto
-operator/( const StaticUnaryExpressionTemplate< L1,LOperation >& a,
-           const StaticUnaryExpressionTemplate< R1,ROperation >& b )
+tanh( const ET1& a )
 {
-   return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Division >( a, b );
+   return StaticUnaryExpressionTemplate< ET1, Tanh >( a );
 }
 
 ////
-// Comparison operator ==
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-__cuda_callable__
-bool
-operator==( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a,
-            const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::EQ( a, b );
-}
-
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
+// Asinh
+template< typename ET1,
+          typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > >
 __cuda_callable__
-bool
-operator==( const StaticBinaryExpressionTemplate< T1, T2, Operation >& a,
-            const typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
+auto
+asinh( const ET1& a )
 {
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::EQ( a, b );
+   return StaticUnaryExpressionTemplate< ET1, Asinh >( a );
 }
 
-template< typename T1,
-          template< typename > class Operation >
+////
+// Acosh
+template< typename ET1,
+          typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > >
 __cuda_callable__
-bool
-operator==( const StaticUnaryExpressionTemplate< T1, Operation >& a,
-            const typename StaticUnaryExpressionTemplate< T1, Operation >::RealType& b )
+auto
+acosh( const ET1& a )
 {
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::EQ( a, b );
+   return StaticUnaryExpressionTemplate< ET1, Acosh >( a );
 }
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
+////
+// Atanh
+template< typename ET1,
+          typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > >
 __cuda_callable__
-bool
-operator==( const typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-            const StaticBinaryExpressionTemplate< T1, T2, Operation >& b )
+auto
+atanh( const ET1& a )
 {
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::EQ( a, b );
+   return StaticUnaryExpressionTemplate< ET1, Atanh >( a );
 }
 
-template< typename T1,
-          template< typename > class Operation >
+////
+// Floor
+template< typename ET1,
+          typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > >
 __cuda_callable__
-bool
-operator==( const typename StaticUnaryExpressionTemplate< T1, Operation >::RealType& a,
-            const StaticUnaryExpressionTemplate< T1, Operation >& b )
+auto
+floor( const ET1& a )
 {
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::EQ( a, b );
+   return StaticUnaryExpressionTemplate< ET1, Floor >( a );
 }
 
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
+////
+// Ceil
+template< typename ET1,
+          typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > >
 __cuda_callable__
-bool
-operator==( const StaticUnaryExpressionTemplate< L1, LOperation >& a,
-            const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b )
+auto
+ceil( const ET1& a )
 {
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::EQ( a, b );
+   return StaticUnaryExpressionTemplate< ET1, Ceil >( a );
 }
 
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
+////
+// Sign
+template< typename ET1,
+          typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > >
 __cuda_callable__
-bool
-operator==( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a,
-            const StaticUnaryExpressionTemplate< R1,ROperation >& b )
+auto
+sign( const ET1& a )
 {
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::EQ( a, b );
+   return StaticUnaryExpressionTemplate< ET1, Sign >( a );
 }
 
 ////
-// Comparison operator !=
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
+// Cast
+template< typename ResultType,
+          typename ET1,
+          typename..., typename = EnableIfStaticUnaryExpression_t< ET1 >,
+          // workaround: templated type alias cannot be declared at block level
+          typename CastOperation = typename Cast< ResultType >::Operation >
 __cuda_callable__
-bool
-operator!=( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a,
-            const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b )
+auto
+cast( const ET1& a )
 {
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b );
+   return StaticUnaryExpressionTemplate< ET1, CastOperation >( a );
 }
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
+////
+// Vertical operations
+template< typename ET1,
+          typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > >
 __cuda_callable__
-bool
-operator!=( const StaticBinaryExpressionTemplate< T1, T2, Operation >& a,
-            const typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
+auto
+min( const ET1& a )
 {
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b );
+   return StaticExpressionMin( a );
 }
 
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
+template< typename ET1,
+          typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > >
 __cuda_callable__
-bool
-operator!=( const StaticUnaryExpressionTemplate< L1, LOperation >& a,
-            const StaticUnaryExpressionTemplate< R1, ROperation >& b )
+auto
+argMin( const ET1& a )
 {
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b );
+   return StaticExpressionArgMin( a );
 }
 
-template< typename T1,
-          template< typename > class Operation >
+template< typename ET1,
+          typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > >
 __cuda_callable__
-bool
-operator!=( const StaticUnaryExpressionTemplate< T1, Operation >& a,
-            const typename StaticUnaryExpressionTemplate< T1, Operation >::RealType& b )
+auto
+max( const ET1& a )
 {
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b );
+   return StaticExpressionMax( a );
 }
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
+template< typename ET1,
+          typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > >
 __cuda_callable__
-bool
-operator!=( const typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-            const StaticBinaryExpressionTemplate< T1, T2, Operation >& b )
+auto
+argMax( const ET1& a )
 {
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b );
+   return StaticExpressionArgMax( a );
 }
 
-template< typename T1,
-          template< typename > class Operation >
+template< typename ET1,
+          typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > >
 __cuda_callable__
-bool
-operator!=( const typename StaticUnaryExpressionTemplate< T1, Operation >::RealType& a,
-            const StaticUnaryExpressionTemplate< T1, Operation >& b )
+auto
+sum( const ET1& a )
 {
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b );
+   return StaticExpressionSum( a );
 }
 
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
+template< typename ET1,
+          typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > >
 __cuda_callable__
-bool
-operator!=( const StaticUnaryExpressionTemplate< L1, LOperation >& a,
-            const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b )
+auto
+maxNorm( const ET1& a )
 {
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b );
+   return max( abs( a ) );
 }
 
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
+template< typename ET1,
+          typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > >
 __cuda_callable__
-bool
-operator!=( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a,
-            const StaticUnaryExpressionTemplate< R1,ROperation >& b )
+auto
+l1Norm( const ET1& a )
 {
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b );
+   return sum( abs( a ) );
 }
 
-////
-// Comparison operator <
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
+template< typename ET1,
+          typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > >
 __cuda_callable__
-bool
-operator<( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b )
+auto
+l2Norm( const ET1& a )
 {
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b );
+   using TNL::sqrt;
+   return sqrt( sum( a * a ) );
 }
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
+template< typename ET1,
+          typename Real,
+          typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > >
 __cuda_callable__
-bool
-operator<( const StaticBinaryExpressionTemplate< T1, T2, Operation >& a,
-           const typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
+auto
+lpNorm( const ET1& a, const Real& p )
+// since (1.0 / p) has type double, TNL::pow returns double
+-> double
+//-> RemoveET< decltype(pow( StaticExpressionLpNorm( a, p ), 1.0 / p )) >
 {
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b );
+   if( p == 1.0 )
+      return l1Norm( a );
+   if( p == 2.0 )
+      return l2Norm( a );
+   using TNL::pow;
+   return pow( sum( pow( abs( a ), p ) ), 1.0 / p );
 }
 
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
+template< typename ET1,
+          typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > >
 __cuda_callable__
-bool
-operator<( const StaticUnaryExpressionTemplate< L1, LOperation >& a,
-           const StaticUnaryExpressionTemplate< R1, ROperation >& b )
+auto
+product( const ET1& a )
 {
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b );
+   return StaticExpressionProduct( a );
 }
 
-template< typename T1,
-          template< typename > class Operation >
+template< typename ET1,
+          typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > >
 __cuda_callable__
-bool
-operator<( const StaticUnaryExpressionTemplate< T1, Operation >& a,
-           const typename StaticUnaryExpressionTemplate< T1, Operation >::RealType& b )
+auto
+logicalAnd( const ET1& a )
 {
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b );
+   return StaticExpressionLogicalAnd( a );
 }
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
+template< typename ET1,
+          typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > >
 __cuda_callable__
-bool
-operator<( const typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-           const StaticBinaryExpressionTemplate< T1, T2, Operation >& b )
+auto
+logicalOr( const ET1& a )
 {
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b );
+   return StaticExpressionLogicalOr( a );
 }
 
-template< typename T1,
-          template< typename > class Operation >
+template< typename ET1,
+          typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > >
 __cuda_callable__
-bool
-operator<( const typename StaticUnaryExpressionTemplate< T1, Operation >::RealType& a,
-           const StaticUnaryExpressionTemplate< T1, Operation >& b )
+auto
+binaryAnd( const ET1& a )
 {
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b );
+   return StaticExpressionBinaryAnd( a );
 }
 
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
+template< typename ET1,
+          typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > >
 __cuda_callable__
-bool
-operator<( const StaticUnaryExpressionTemplate< L1, LOperation >& a,
-           const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b )
+auto
+binaryOr( const ET1& a )
 {
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b );
+   return StaticExpressionBinaryOr( a );
 }
 
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-__cuda_callable__
-bool
-operator<( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const StaticUnaryExpressionTemplate< R1,ROperation >& b )
-{
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b );
-}
+#endif // DOXYGEN_ONLY
 
 ////
-// Comparison operator <=
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-__cuda_callable__
-bool
-operator<=( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a,
-            const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b );
-}
-
+// Output stream
 template< typename T1,
           typename T2,
-          template< typename, typename > class Operation >
-__cuda_callable__
-bool
-operator<=( const StaticBinaryExpressionTemplate< T1, T2, Operation >& a,
-            const typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
+          typename Operation >
+std::ostream& operator<<( std::ostream& str, const StaticBinaryExpressionTemplate< T1, T2, Operation >& expression )
 {
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b );
+   str << "[ ";
+   for( int i = 0; i < expression.getSize() - 1; i++ )
+      str << expression[ i ] << ", ";
+   str << expression[ expression.getSize() - 1 ] << " ]";
+   return str;
 }
 
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-__cuda_callable__
-bool
-operator<=( const StaticUnaryExpressionTemplate< L1, LOperation >& a,
-            const StaticUnaryExpressionTemplate< R1, ROperation >& b )
+template< typename T,
+          typename Operation >
+std::ostream& operator<<( std::ostream& str, const StaticUnaryExpressionTemplate< T, Operation >& expression )
 {
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b );
+   str << "[ ";
+   for( int i = 0; i < expression.getSize() - 1; i++ )
+      str << expression[ i ] << ", ";
+   str << expression[ expression.getSize() - 1 ] << " ]";
+   return str;
 }
 
-template< typename T1,
-          template< typename > class Operation >
-__cuda_callable__
-bool
-operator<=( const StaticUnaryExpressionTemplate< T1, Operation >& a,
-            const typename StaticUnaryExpressionTemplate< T1, Operation >::RealType& b )
-{
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b );
-}
+} // namespace Expressions
 
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-__cuda_callable__
-bool
-operator<=( const typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-            const StaticBinaryExpressionTemplate< T1, T2, Operation >& b )
-{
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b );
-}
+// Make all operators visible in the TNL::Containers namespace to be considered
+// even for StaticVector
+using Expressions::operator+;
+using Expressions::operator-;
+using Expressions::operator*;
+using Expressions::operator/;
+using Expressions::operator,;
+using Expressions::operator==;
+using Expressions::operator!=;
+using Expressions::operator<;
+using Expressions::operator<=;
+using Expressions::operator>;
+using Expressions::operator>=;
+
+// Make all functions visible in the TNL::Containers namespace
+using Expressions::dot;
+using Expressions::min;
+using Expressions::max;
+using Expressions::abs;
+using Expressions::pow;
+using Expressions::exp;
+using Expressions::sqrt;
+using Expressions::cbrt;
+using Expressions::log;
+using Expressions::log10;
+using Expressions::log2;
+using Expressions::sin;
+using Expressions::cos;
+using Expressions::tan;
+using Expressions::asin;
+using Expressions::acos;
+using Expressions::atan;
+using Expressions::sinh;
+using Expressions::cosh;
+using Expressions::tanh;
+using Expressions::asinh;
+using Expressions::acosh;
+using Expressions::atanh;
+using Expressions::floor;
+using Expressions::ceil;
+using Expressions::sign;
+using Expressions::cast;
+using Expressions::argMin;
+using Expressions::argMax;
+using Expressions::sum;
+using Expressions::maxNorm;
+using Expressions::l1Norm;
+using Expressions::l2Norm;
+using Expressions::lpNorm;
+using Expressions::product;
+using Expressions::logicalAnd;
+using Expressions::logicalOr;
+using Expressions::binaryAnd;
+using Expressions::binaryOr;
 
-template< typename T1,
-          template< typename > class Operation >
-__cuda_callable__
-bool
-operator<=( const typename StaticUnaryExpressionTemplate< T1, Operation >::RealType& a,
-            const StaticUnaryExpressionTemplate< T1, Operation >& b )
-{
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b );
-}
+} // namespace Containers
 
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-__cuda_callable__
-bool
-operator<=( const StaticUnaryExpressionTemplate< L1, LOperation >& a,
-            const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-__cuda_callable__
-bool
-operator<=( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a,
-            const StaticUnaryExpressionTemplate< R1,ROperation >& b )
-{
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b );
-}
-
-////
-// Comparison operator >
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-__cuda_callable__
-bool
-operator>( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GT( a, b );
-}
-
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-__cuda_callable__
-bool
-operator>( const StaticBinaryExpressionTemplate< T1, T2, Operation >& a,
-           const typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
-{
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GT( a, b );
-}
-
-template< typename T1,
-          template< typename > class Operation >
-__cuda_callable__
-bool
-operator>( const StaticUnaryExpressionTemplate< T1, Operation >& a,
-           const typename StaticUnaryExpressionTemplate< T1, Operation >::RealType& b )
-{
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GT( a, b );
-}
-
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-__cuda_callable__
-bool
-operator>( const typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-           const StaticBinaryExpressionTemplate< T1, T2, Operation >& b )
-{
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GT( a, b );
-}
-
-template< typename T1,
-          template< typename > class Operation >
-__cuda_callable__
-bool
-operator>( const typename StaticUnaryExpressionTemplate< T1, Operation >::RealType& a,
-           const StaticUnaryExpressionTemplate< T1, Operation >& b )
-{
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GT( a, b );
-}
-
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-__cuda_callable__
-bool
-operator>( const StaticUnaryExpressionTemplate< L1, LOperation >& a,
-           const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GT( a, b );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-__cuda_callable__
-bool
-operator>( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const StaticUnaryExpressionTemplate< R1,ROperation >& b )
-{
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GT( a, b );
-}
-
-////
-// Comparison operator >=
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-__cuda_callable__
-bool
-operator>=( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a,
-            const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GE( a, b );
-}
-
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-__cuda_callable__
-bool
-operator>=( const StaticBinaryExpressionTemplate< T1, T2, Operation >& a,
-            const typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
-{
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GE( a, b );
-}
-
-template< typename T1,
-          template< typename > class Operation >
-__cuda_callable__
-bool
-operator>=( const StaticUnaryExpressionTemplate< T1, Operation >& a,
-            const typename StaticUnaryExpressionTemplate< T1, Operation >::RealType& b )
-{
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GE( a, b );
-}
-
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-__cuda_callable__
-bool
-operator>=( const typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-            const StaticBinaryExpressionTemplate< T1, T2, Operation >& b )
-{
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GE( a, b );
-}
-
-template< typename T1,
-          template< typename > class Operation >
-__cuda_callable__
-bool
-operator>=( const typename StaticUnaryExpressionTemplate< T1, Operation >::RealType& a,
-            const StaticUnaryExpressionTemplate< T1, Operation >& b )
-{
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GE( a, b );
-}
-
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-__cuda_callable__
-bool
-operator>=( const StaticUnaryExpressionTemplate< L1, LOperation >& a,
-            const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GE( a, b );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-__cuda_callable__
-bool
-operator>=( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a,
-            const StaticUnaryExpressionTemplate< R1,ROperation >& b )
-{
-   return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GE( a, b );
-}
-
-////
-// Unary operations
-
-////
-// Minus
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-__cuda_callable__
-auto
-operator-( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Minus >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-__cuda_callable__
-auto
-operator-( const StaticUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Minus >( a );
-}
-
-////
-// Scalar product
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-__cuda_callable__
-auto
-operator,( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return StaticExpressionSum( a * b );
-}
-
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-__cuda_callable__
-auto
-operator,( const StaticUnaryExpressionTemplate< L1, LOperation >& a,
-           const StaticUnaryExpressionTemplate< R1, ROperation >& b )
-{
-   return StaticExpressionSum( a * b );
-}
-
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-__cuda_callable__
-auto
-operator,( const StaticUnaryExpressionTemplate< L1, LOperation >& a,
-           const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return StaticExpressionSum( a * b );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-__cuda_callable__
-auto
-operator,( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const StaticUnaryExpressionTemplate< R1,ROperation >& b )
-{
-   return StaticExpressionSum( a * b );
-}
-
-#endif // DOXYGEN_ONLY
-
-////
-// Output stream
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-std::ostream& operator<<( std::ostream& str, const StaticBinaryExpressionTemplate< T1, T2, Operation >& expression )
-{
-   str << "[ ";
-   for( int i = 0; i < expression.getSize() - 1; i++ )
-      str << expression[ i ] << ", ";
-   str << expression[ expression.getSize() - 1 ] << " ]";
-   return str;
-}
-
-template< typename T,
-          template< typename > class Operation >
-std::ostream& operator<<( std::ostream& str, const StaticUnaryExpressionTemplate< T, Operation >& expression )
-{
-   str << "[ ";
-   for( int i = 0; i < expression.getSize() - 1; i++ )
-      str << expression[ i ] << ", ";
-   str << expression[ expression.getSize() - 1 ] << " ]";
-   return str;
-}
-
-} // namespace Expressions
-} // namespace Containers
-
-////
-// All operations are supposed to be in namespace TNL
-
-#ifndef DOXYGEN_ONLY
-
-////
-// Binary expression min
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-__cuda_callable__
-auto
-min( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a,
-     const Containers::Expressions::StaticBinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return Containers::Expressions::StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b );
-}
-
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-__cuda_callable__
-auto
-min( const Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >& a,
-     const typename Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
-{
-   return Containers::Expressions::StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b );
-}
-
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-__cuda_callable__
-auto
-min( const typename Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-     const Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >& b )
-{
-   return Containers::Expressions::StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b );
-}
-
-template< typename T1,
-          template< typename > class Operation >
-__cuda_callable__
-auto
-min( const Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >& a,
-     const typename Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >::RealType& b )
-{
-   return Containers::Expressions::StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b );
-}
-
-template< typename T1,
-          template< typename > class Operation >
-__cuda_callable__
-auto
-min( const typename Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >::RealType& a,
-     const Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >& b )
-{
-   return Containers::Expressions::StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b );
-}
-
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-__cuda_callable__
-auto
-min( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a,
-     const Containers::Expressions::StaticBinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return Containers::Expressions::StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-__cuda_callable__
-auto
-min( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a,
-     const Containers::Expressions::StaticUnaryExpressionTemplate< R1,ROperation >& b )
-{
-   return Containers::Expressions::StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b );
-}
-
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-__cuda_callable__
-auto
-min( const Containers::Expressions::StaticUnaryExpressionTemplate< L1,LOperation >& a,
-     const Containers::Expressions::StaticUnaryExpressionTemplate< R1,ROperation >& b )
-{
-   return Containers::Expressions::StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b );
-}
-
-////
-// Binary expression max
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-__cuda_callable__
-auto
-max( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a,
-     const Containers::Expressions::StaticBinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return Containers::Expressions::StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b );
-}
-
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-__cuda_callable__
-auto
-max( const Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >& a,
-     const typename Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
-{
-   return Containers::Expressions::StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b );
-}
-
-template< typename T1,
-          typename T2,
-          template< typename, typename > class Operation >
-__cuda_callable__
-auto
-max( const typename Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-     const Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >& b )
-{
-   return Containers::Expressions::StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b );
-}
-
-template< typename T1,
-          template< typename > class Operation >
-__cuda_callable__
-auto
-max( const Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >& a,
-     const typename Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >::RealType& b )
-{
-   return Containers::Expressions::StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b );
-}
-
-template< typename T1,
-          template< typename > class Operation >
-__cuda_callable__
-auto
-max( const typename Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >::RealType& a,
-     const Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >& b )
-{
-   return Containers::Expressions::StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b );
-}
-
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-__cuda_callable__
-auto
-max( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a,
-     const Containers::Expressions::StaticBinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return Containers::Expressions::StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-__cuda_callable__
-auto
-max( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a,
-     const Containers::Expressions::StaticUnaryExpressionTemplate< R1,ROperation >& b )
-{
-   return Containers::Expressions::StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b );
-}
-
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-__cuda_callable__
-auto
-max( const Containers::Expressions::StaticUnaryExpressionTemplate< L1,LOperation >& a,
-     const Containers::Expressions::StaticUnaryExpressionTemplate< R1,ROperation >& b )
-{
-   return Containers::Expressions::StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b );
-}
-
-////
-// Abs
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-__cuda_callable__
-auto
-abs( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Abs >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-__cuda_callable__
-auto
-abs( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Abs >( a );
-}
-
-////
-// Pow
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename Real >
-__cuda_callable__
-auto
-pow( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a, const Real& exp )
-{
-   return Containers::Expressions::StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, Real, Containers::Expressions::Pow >( a, exp );
-}
-
-template< typename L1,
-          template< typename > class LOperation,
-          typename Real >
-__cuda_callable__
-auto
-pow( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a, const Real& exp )
-{
-   return Containers::Expressions::StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, Real, Containers::Expressions::Pow >( a, exp );
-}
-
-////
-// Exp
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-__cuda_callable__
-auto
-exp( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Exp >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-__cuda_callable__
-auto
-exp( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Exp >( a );
-}
-
-////
-// Sqrt
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-__cuda_callable__
-auto
-sqrt( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sqrt >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-__cuda_callable__
-auto
-sqrt( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sqrt >( a );
-}
-
-////
-// Cbrt
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-__cuda_callable__
-auto
-cbrt( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Cbrt >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-__cuda_callable__
-auto
-cbrt( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Cbrt >( a );
-}
-
-////
-// Log
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-__cuda_callable__
-auto
-log( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Log >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-__cuda_callable__
-auto
-log( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Log >( a );
-}
-
-////
-// Log10
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-__cuda_callable__
-auto
-log10( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Log10 >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-__cuda_callable__
-auto
-log10( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Log10 >( a );
-}
-
-////
-// Log2
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-__cuda_callable__
-auto
-log2( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Log2 >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-__cuda_callable__
-auto
-log2( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Log2 >( a );
-}
-
-////
-// Sin
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-__cuda_callable__
-auto
-sin( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sin >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-__cuda_callable__
-auto
-sin( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sin >( a );
-}
-
-////
-// Cos
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-__cuda_callable__
-auto
-cos( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Cos >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-__cuda_callable__
-auto
-cos( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Cos >( a );
-}
-
-////
-// Tan
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-__cuda_callable__
-auto
-tan( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Tan >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-__cuda_callable__
-auto
-tan( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Tan >( a );
-}
-
-////
-// Asin
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-__cuda_callable__
-auto
-asin( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Asin >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-__cuda_callable__
-auto
-asin( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Asin >( a );
-}
-
-////
-// Acos
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-__cuda_callable__
-auto
-acos( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Acos >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-__cuda_callable__
-auto
-acos( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Acos >( a );
-}
-
-////
-// Atan
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-__cuda_callable__
-auto
-atan( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Atan >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-__cuda_callable__
-auto
-atan( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Atan >( a );
-}
-
-////
-// Sinh
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-__cuda_callable__
-auto
-sinh( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sinh >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-__cuda_callable__
-auto
-sinh( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sinh >( a );
-}
-
-////
-// Cosh
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-__cuda_callable__
-auto
-cosh( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Cosh >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-__cuda_callable__
-auto
-cosh( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Cosh >( a );
-}
-
-////
-// Tanh
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-__cuda_callable__
-auto
-tanh( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Tanh >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-__cuda_callable__
-auto
-tanh( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Tanh >( a );
-}
-
-////
-// Asinh
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-__cuda_callable__
-auto
-asinh( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Asinh >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-__cuda_callable__
-auto
-asinh( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Asinh >( a );
-}
-
-////
-// Acosh
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-__cuda_callable__
-auto
-acosh( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Acosh >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-__cuda_callable__
-auto
-acosh( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Acosh >( a );
-}
-
-////
-// Atanh
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-__cuda_callable__
-auto
-atanh( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Atanh >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-__cuda_callable__
-auto
-atanh( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Atanh >( a );
-}
-
-////
-// Floor
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-__cuda_callable__
-auto
-floor( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Floor >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-__cuda_callable__
-auto
-floor( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Floor >( a );
-}
-
-////
-// Ceil
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-__cuda_callable__
-auto
-ceil( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Ceil >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-__cuda_callable__
-auto
-ceil( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Ceil >( a );
-}
-
-////
-// Sign
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-__cuda_callable__
-auto
-sign( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sign >( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-__cuda_callable__
-auto
-sign( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sign >( a );
-}
-
-////
-// Cast
-template< typename ResultType,
-          typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          // workaround: templated type alias cannot be declared at block level
-          template<typename> class CastOperation = Containers::Expressions::Cast< ResultType >::template Operation >
-__cuda_callable__
-auto
-cast( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, CastOperation >( a );
-}
-
-template< typename ResultType,
-          typename L1,
-          template< typename > class LOperation,
-          // workaround: templated type alias cannot be declared at block level
-          template<typename> class CastOperation = Containers::Expressions::Cast< ResultType >::template Operation >
-__cuda_callable__
-auto
-cast( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, CastOperation >( a );
-}
-
-////
-// Vertical operations - min
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-__cuda_callable__
-auto
-min( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return StaticExpressionMin( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-__cuda_callable__
-auto
-min( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return StaticExpressionMin( a );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-__cuda_callable__
-auto
-argMin( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return StaticExpressionArgMin( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-__cuda_callable__
-auto
-argMin( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return StaticExpressionArgMin( a );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-__cuda_callable__
-auto
-max( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return StaticExpressionMax( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-__cuda_callable__
-auto
-max( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return StaticExpressionMax( a );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-__cuda_callable__
-auto
-argMax( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return StaticExpressionArgMax( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-__cuda_callable__
-auto
-argMax( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return StaticExpressionArgMax( a );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-__cuda_callable__
-auto
-sum( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return StaticExpressionSum( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-__cuda_callable__
-auto
-sum( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return StaticExpressionSum( a );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-maxNorm( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return max( abs( a ) );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-maxNorm( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return max( abs( a ) );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-l1Norm( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return StaticExpressionL1Norm( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-l1Norm( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return StaticExpressionL1Norm( a );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-auto
-l2Norm( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return TNL::sqrt( StaticExpressionL2Norm( a ) );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-auto
-l2Norm( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return TNL::sqrt( StaticExpressionL2Norm( a ) );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename Real >
-__cuda_callable__
-auto
-lpNorm( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a, const Real& p )
-// since (1.0 / p) has type double, TNL::pow returns double
--> double
-{
-   if( p == 1.0 )
-      return l1Norm( a );
-   if( p == 2.0 )
-      return l2Norm( a );
-   return TNL::pow( StaticExpressionLpNorm( a, p ), 1.0 / p );
-}
-
-template< typename L1,
-          template< typename > class LOperation,
-          typename Real >
-__cuda_callable__
-auto
-lpNorm( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a, const Real& p )
-// since (1.0 / p) has type double, TNL::pow returns double
--> double
-{
-   if( p == 1.0 )
-      return l1Norm( a );
-   if( p == 2.0 )
-      return l2Norm( a );
-   return TNL::pow( StaticExpressionLpNorm( a, p ), 1.0 / p );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-__cuda_callable__
-auto
-product( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return StaticExpressionProduct( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-__cuda_callable__
-auto
-product( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return StaticExpressionProduct( a );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-__cuda_callable__
-auto
-logicalOr( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return StaticExpressionLogicalOr( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-__cuda_callable__
-auto
-logicalOr( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return StaticExpressionLogicalOr( a );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation >
-__cuda_callable__
-auto
-binaryOr( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a )
-{
-   return StaticExpressionBinaryOr( a );
-}
-
-template< typename L1,
-          template< typename > class LOperation >
-__cuda_callable__
-auto
-binaryOr( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a )
-{
-   return StaticExpressionBinaryOr( a );
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-__cuda_callable__
-auto
-dot( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a,
-     const Containers::Expressions::StaticBinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return (a, b);
-}
-
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-__cuda_callable__
-auto
-dot( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a,
-     const Containers::Expressions::StaticUnaryExpressionTemplate< R1, ROperation >& b )
-{
-   return (a, b);
-}
-
-template< typename L1,
-          template< typename > class LOperation,
-          typename R1,
-          typename R2,
-          template< typename, typename > class ROperation >
-__cuda_callable__
-auto
-dot( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a,
-     const Containers::Expressions::StaticBinaryExpressionTemplate< R1, R2, ROperation >& b )
-{
-   return (a, b);
-}
-
-template< typename L1,
-          typename L2,
-          template< typename, typename > class LOperation,
-          typename R1,
-          template< typename > class ROperation >
-__cuda_callable__
-auto
-dot( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a,
-     const Containers::Expressions::StaticUnaryExpressionTemplate< R1,ROperation >& b )
-{
-   return (a, b);
-}
-
-#endif // DOXYGEN_ONLY
+// Make all functions visible in the main TNL namespace
+using Containers::dot;
+using Containers::min;
+using Containers::max;
+using Containers::abs;
+using Containers::pow;
+using Containers::exp;
+using Containers::sqrt;
+using Containers::cbrt;
+using Containers::log;
+using Containers::log10;
+using Containers::log2;
+using Containers::sin;
+using Containers::cos;
+using Containers::tan;
+using Containers::asin;
+using Containers::acos;
+using Containers::atan;
+using Containers::sinh;
+using Containers::cosh;
+using Containers::tanh;
+using Containers::asinh;
+using Containers::acosh;
+using Containers::atanh;
+using Containers::floor;
+using Containers::ceil;
+using Containers::sign;
+using Containers::cast;
+using Containers::argMin;
+using Containers::argMax;
+using Containers::sum;
+using Containers::maxNorm;
+using Containers::l1Norm;
+using Containers::l2Norm;
+using Containers::lpNorm;
+using Containers::product;
+using Containers::logicalAnd;
+using Containers::logicalOr;
+using Containers::binaryAnd;
+using Containers::binaryOr;
 
 ////
 // Evaluation with reduction
 template< typename Vector,
    typename T1,
    typename T2,
-   template< typename, typename > class Operation,
+   typename Operation,
    typename Reduction,
    typename Result >
 __cuda_callable__
@@ -2299,7 +970,7 @@ Result evaluateAndReduce( Vector& lhs,
 
 template< typename Vector,
    typename T1,
-   template< typename > class Operation,
+   typename Operation,
    typename Reduction,
    typename Result >
 __cuda_callable__
@@ -2319,7 +990,7 @@ Result evaluateAndReduce( Vector& lhs,
 template< typename Vector,
    typename T1,
    typename T2,
-   template< typename, typename > class Operation,
+   typename Operation,
    typename Reduction,
    typename Result >
 __cuda_callable__
@@ -2339,7 +1010,7 @@ Result addAndReduce( Vector& lhs,
 
 template< typename Vector,
    typename T1,
-   template< typename > class Operation,
+   typename Operation,
    typename Reduction,
    typename Result >
 __cuda_callable__
@@ -2362,7 +1033,7 @@ Result addAndReduce( Vector& lhs,
 template< typename Vector,
    typename T1,
    typename T2,
-   template< typename, typename > class Operation,
+   typename Operation,
    typename Reduction,
    typename Result >
 __cuda_callable__
@@ -2382,7 +1053,7 @@ Result addAndReduceAbs( Vector& lhs,
 
 template< typename Vector,
    typename T1,
-   template< typename > class Operation,
+   typename Operation,
    typename Reduction,
    typename Result >
 __cuda_callable__
diff --git a/src/TNL/Containers/Expressions/StaticVerticalOperations.h b/src/TNL/Containers/Expressions/StaticVerticalOperations.h
index 7c8477f4d8068373ce99b0366192d15bc1ea6b03..7deec166d95b6f05e6ac50c8d1e1494dfd2b5e97 100644
--- a/src/TNL/Containers/Expressions/StaticVerticalOperations.h
+++ b/src/TNL/Containers/Expressions/StaticVerticalOperations.h
@@ -11,6 +11,7 @@
 #pragma once
 
 #include <TNL/Math.h>
+#include <TNL/Containers/Expressions/TypeTraits.h>
 
 ////
 // By vertical operations we mean those applied across vector elements or
@@ -24,9 +25,10 @@ template< typename Expression >
 __cuda_callable__
 auto StaticExpressionMin( const Expression& expression )
 {
-   auto aux = expression[ 0 ];
+   using ResultType = RemoveET< typename Expression::RealType >;
+   ResultType aux = expression[ 0 ];
    for( int i = 1; i < expression.getSize(); i++ )
-      aux = TNL::min( aux, expression[ i ] );
+      aux = min( aux, expression[ i ] );
    return aux;
 }
 
@@ -34,8 +36,9 @@ template< typename Expression >
 __cuda_callable__
 auto StaticExpressionArgMin( const Expression& expression )
 {
+   using ResultType = RemoveET< typename Expression::RealType >;
    int arg = 0;
-   auto value = expression[ 0 ];
+   ResultType value = expression[ 0 ];
    for( int i = 1; i < expression.getSize(); i++ )
    {
       if( expression[ i ] < value )
@@ -51,9 +54,10 @@ template< typename Expression >
 __cuda_callable__
 auto StaticExpressionMax( const Expression& expression )
 {
-   auto aux = expression[ 0 ];
+   using ResultType = RemoveET< typename Expression::RealType >;
+   ResultType aux = expression[ 0 ];
    for( int i = 1; i < expression.getSize(); i++ )
-      aux = TNL::max( aux, expression[ i ] );
+      aux = max( aux, expression[ i ] );
    return aux;
 }
 
@@ -61,8 +65,9 @@ template< typename Expression >
 __cuda_callable__
 auto StaticExpressionArgMax( const Expression& expression )
 {
+   using ResultType = RemoveET< typename Expression::RealType >;
    int arg = 0;
-   auto value = expression[ 0 ];
+   ResultType value = expression[ 0 ];
    for( int i = 1; i < expression.getSize(); i++ )
    {
       if( expression[ i ] > value )
@@ -78,47 +83,19 @@ template< typename Expression >
 __cuda_callable__
 auto StaticExpressionSum( const Expression& expression )
 {
-   auto aux = expression[ 0 ];
+   using ResultType = RemoveET< typename Expression::RealType >;
+   ResultType aux = expression[ 0 ];
    for( int i = 1; i < expression.getSize(); i++ )
       aux += expression[ i ];
    return aux;
 }
 
-template< typename Expression >
-__cuda_callable__
-auto StaticExpressionL1Norm( const Expression& expression )
-{
-   auto aux = TNL::abs( expression[ 0 ] );
-   for( int i = 1; i < expression.getSize(); i++ )
-      aux += TNL::abs( expression[ i ] );
-   return aux;
-}
-
-template< typename Expression >
-__cuda_callable__
-auto StaticExpressionL2Norm( const Expression& expression )
-{
-   auto aux = expression[ 0 ] * expression[ 0 ];
-   for( int i = 1; i < expression.getSize(); i++ )
-      aux += expression[ i ] * expression[ i ];
-   return aux;
-}
-
-template< typename Expression, typename Real >
-__cuda_callable__
-auto StaticExpressionLpNorm( const Expression& expression, const Real& p )
-{
-   auto aux = TNL::pow( TNL::abs( expression[ 0 ] ), p );
-   for( int i = 1; i < expression.getSize(); i++ )
-      aux += TNL::pow( TNL::abs( expression[ i ] ), p );
-   return aux;
-}
-
 template< typename Expression >
 __cuda_callable__
 auto StaticExpressionProduct( const Expression& expression )
 {
-   auto aux = expression[ 0 ];
+   using ResultType = RemoveET< typename Expression::RealType >;
+   ResultType aux = expression[ 0 ];
    for( int i = 1; i < expression.getSize(); i++ )
       aux *= expression[ i ];
    return aux;
diff --git a/src/TNL/Containers/Expressions/TypeTraits.h b/src/TNL/Containers/Expressions/TypeTraits.h
index 606bb337aeb3438fdce861b54e949376652b8616..1024bb4653ecd28aa577494395520991c50f7e42 100644
--- a/src/TNL/Containers/Expressions/TypeTraits.h
+++ b/src/TNL/Containers/Expressions/TypeTraits.h
@@ -10,23 +10,115 @@
 
 #pragma once
 
-#include <type_traits>
+#include <TNL/TypeTraits.h>
 
 namespace TNL {
 namespace Containers {
 namespace Expressions {
 
+// trait classes used for the enabling of expression templates
 template< typename T >
-struct IsExpressionTemplate : std::false_type
+struct HasEnabledExpressionTemplates : std::false_type
 {};
 
 template< typename T >
-struct IsNumericExpression
-: std::integral_constant< bool,
-      std::is_arithmetic< T >::value ||
-      IsExpressionTemplate< T >::value >
+struct HasEnabledStaticExpressionTemplates : std::false_type
 {};
 
+template< typename T >
+struct HasEnabledDistributedExpressionTemplates : std::false_type
+{};
+
+
+// type aliases for enabling specific operators and functions using SFINAE
+template< typename ET1 >
+using EnableIfStaticUnaryExpression_t = std::enable_if_t<
+      HasEnabledStaticExpressionTemplates< ET1 >::value >;
+
+template< typename ET1, typename ET2 >
+using EnableIfStaticBinaryExpression_t = std::enable_if_t<
+      HasEnabledStaticExpressionTemplates< ET1 >::value ||
+      HasEnabledStaticExpressionTemplates< ET2 >::value >;
+
+template< typename ET1 >
+using EnableIfUnaryExpression_t = std::enable_if_t<
+      HasEnabledExpressionTemplates< ET1 >::value >;
+
+template< typename ET1, typename ET2 >
+using EnableIfBinaryExpression_t = std::enable_if_t<
+      // we need to avoid ambiguity with operators defined in Array (e.g. Array::operator==)
+      // so the first operand must not be Array
+      (
+         HasAddAssignmentOperator< ET1 >::value ||
+         HasEnabledExpressionTemplates< ET1 >::value ||
+         std::is_arithmetic< ET1 >::value
+      ) &&
+      (
+         HasEnabledExpressionTemplates< ET2 >::value ||
+         HasEnabledExpressionTemplates< ET1 >::value
+      ) >;
+
+template< typename ET1 >
+using EnableIfDistributedUnaryExpression_t = std::enable_if_t<
+      HasEnabledDistributedExpressionTemplates< ET1 >::value >;
+
+template< typename ET1, typename ET2 >
+using EnableIfDistributedBinaryExpression_t = std::enable_if_t<
+      // we need to avoid ambiguity with operators defined in Array (e.g. Array::operator==)
+      // so the first operand must not be Array
+      (
+         HasAddAssignmentOperator< ET1 >::value ||
+         HasEnabledDistributedExpressionTemplates< ET1 >::value ||
+         std::is_arithmetic< ET1 >::value
+      ) &&
+      (
+         HasEnabledDistributedExpressionTemplates< ET2 >::value ||
+         HasEnabledDistributedExpressionTemplates< ET1 >::value
+      ) >;
+
+
+// helper trait class for proper classification of expression operands using getExpressionVariableType
+template< typename T, typename V,
+          bool enabled = IsVectorType< V >::value >
+struct IsArithmeticSubtype
+: public std::integral_constant< bool,
+            // TODO: use std::is_assignable?
+            std::is_same< T, typename V::RealType >::value >
+{};
+
+template< typename T >
+struct IsArithmeticSubtype< T, T, true >
+: public std::false_type
+{};
+
+template< typename T >
+struct IsArithmeticSubtype< T, T, false >
+: public std::false_type
+{};
+
+template< typename T, typename V >
+struct IsArithmeticSubtype< T, V, false >
+: public std::is_arithmetic< T >
+{};
+
+
+// helper trait class (used in unit tests)
+template< typename R, bool enabled = ! HasEnabledStaticExpressionTemplates< R >::value >
+struct RemoveExpressionTemplate
+{
+   using type = R;
+};
+
+template< typename R >
+struct RemoveExpressionTemplate< R, false >
+{
+//   using type = StaticVector< R::getSize(), typename RemoveExpressionTemplate< typename R::RealType >::type >;
+   using type = typename RemoveExpressionTemplate< typename R::VectorOperandType >::type;
+};
+
+template< typename R >
+using RemoveET = typename RemoveExpressionTemplate< R >::type;
+
 } // namespace Expressions
 } // namespace Containers
 } // namespace TNL
diff --git a/src/TNL/Containers/Expressions/VerticalOperations.h b/src/TNL/Containers/Expressions/VerticalOperations.h
index 84d362e8aab01b704cdefac44ae0d7e0e6a7150d..f9e184e03a326b99853136e2e6e74c0916588ed8 100644
--- a/src/TNL/Containers/Expressions/VerticalOperations.h
+++ b/src/TNL/Containers/Expressions/VerticalOperations.h
@@ -31,7 +31,8 @@ auto ExpressionMin( const Expression& expression ) -> std::decay_t< decltype( ex
    using ResultType = std::decay_t< decltype( expression[0] ) >;
    using IndexType = typename Expression::IndexType;
 
-   auto fetch = [=] __cuda_callable__ ( IndexType i ) { return expression[ i ]; };
+   const auto view = expression.getConstView();
+   auto fetch = [=] __cuda_callable__ ( IndexType i ) { return view[ i ]; };
    auto reduction = [] __cuda_callable__ ( const ResultType& a, const ResultType& b ) { return TNL::min( a, b ); };
    return Algorithms::Reduction< typename Expression::DeviceType >::reduce( expression.getSize(), reduction, fetch, std::numeric_limits< ResultType >::max() );
 }
@@ -43,7 +44,8 @@ auto ExpressionArgMin( const Expression& expression )
    using ResultType = std::decay_t< decltype( expression[0] ) >;
    using IndexType = typename Expression::IndexType;
 
-   auto fetch = [=] __cuda_callable__ ( IndexType i ) { return expression[ i ]; };
+   const auto view = expression.getConstView();
+   auto fetch = [=] __cuda_callable__ ( IndexType i ) { return view[ i ]; };
    auto reduction = [] __cuda_callable__ ( IndexType& aIdx, const IndexType& bIdx, ResultType& a, const ResultType& b ) {
       if( a > b ) {
          a = b;
@@ -61,7 +63,8 @@ auto ExpressionMax( const Expression& expression ) -> std::decay_t< decltype( ex
    using ResultType = std::decay_t< decltype( expression[0] ) >;
    using IndexType = typename Expression::IndexType;
 
-   auto fetch = [=] __cuda_callable__ ( IndexType i ) { return expression[ i ]; };
+   const auto view = expression.getConstView();
+   auto fetch = [=] __cuda_callable__ ( IndexType i ) { return view[ i ]; };
    auto reduction = [] __cuda_callable__ ( const ResultType& a, const ResultType& b ) { return TNL::max( a, b ); };
    return Algorithms::Reduction< typename Expression::DeviceType >::reduce( expression.getSize(), reduction, fetch, std::numeric_limits< ResultType >::lowest() );
 }
@@ -73,7 +76,8 @@ auto ExpressionArgMax( const Expression& expression )
    using ResultType = std::decay_t< decltype( expression[0] ) >;
    using IndexType = typename Expression::IndexType;
 
-   auto fetch = [=] __cuda_callable__ ( IndexType i ) { return expression[ i ]; };
+   const auto view = expression.getConstView();
+   auto fetch = [=] __cuda_callable__ ( IndexType i ) { return view[ i ]; };
    auto reduction = [] __cuda_callable__ ( IndexType& aIdx, const IndexType& bIdx, ResultType& a, const ResultType& b ) {
       if( a < b ) {
          a = b;
@@ -91,37 +95,8 @@ auto ExpressionSum( const Expression& expression ) -> std::decay_t< decltype( ex
    using ResultType = std::decay_t< decltype( expression[0] + expression[0] ) >;
    using IndexType = typename Expression::IndexType;
 
-   auto fetch = [=] __cuda_callable__ ( IndexType i ) { return expression[ i ]; };
-   return Algorithms::Reduction< typename Expression::DeviceType >::reduce( expression.getSize(), std::plus<>{}, fetch, (ResultType) 0 );
-}
-
-template< typename Expression >
-auto ExpressionL1Norm( const Expression& expression ) -> std::decay_t< decltype( expression[0] + expression[0] ) >
-{
-   using ResultType = std::decay_t< decltype( expression[0] + expression[0] ) >;
-   using IndexType = typename Expression::IndexType;
-
-   auto fetch = [=] __cuda_callable__ ( IndexType i ) { return TNL::abs( expression[ i ] ); };
-   return Algorithms::Reduction< typename Expression::DeviceType >::reduce( expression.getSize(), std::plus<>{}, fetch, (ResultType) 0 );
-}
-
-template< typename Expression >
-auto ExpressionL2Norm( const Expression& expression ) -> std::decay_t< decltype( expression[0] * expression[0] ) >
-{
-   using ResultType = std::decay_t< decltype( expression[0] * expression[0] ) >;
-   using IndexType = typename Expression::IndexType;
-
-   auto fetch = [=] __cuda_callable__ ( IndexType i ) { return expression[ i ] * expression[ i ]; };
-   return Algorithms::Reduction< typename Expression::DeviceType >::reduce( expression.getSize(), std::plus<>{}, fetch, (ResultType) 0 );
-}
-
-template< typename Expression, typename Real >
-auto ExpressionLpNorm( const Expression& expression, const Real& p ) -> std::decay_t< decltype( TNL::pow( expression[0], p ) ) >
-{
-   using ResultType = std::decay_t< decltype( TNL::pow( expression[0], p ) ) >;
-   using IndexType = typename Expression::IndexType;
-
-   auto fetch = [=] __cuda_callable__ ( IndexType i ) { return TNL::pow( TNL::abs( expression[ i ] ), p ); };
+   const auto view = expression.getConstView();
+   auto fetch = [=] __cuda_callable__ ( IndexType i ) { return view[ i ]; };
    return Algorithms::Reduction< typename Expression::DeviceType >::reduce( expression.getSize(), std::plus<>{}, fetch, (ResultType) 0 );
 }
 
@@ -131,7 +106,8 @@ auto ExpressionProduct( const Expression& expression ) -> std::decay_t< decltype
    using ResultType = std::decay_t< decltype( expression[0] * expression[0] ) >;
    using IndexType = typename Expression::IndexType;
 
-   auto fetch = [=] __cuda_callable__ ( IndexType i ) { return expression[ i ]; };
+   const auto view = expression.getConstView();
+   auto fetch = [=] __cuda_callable__ ( IndexType i ) { return view[ i ]; };
    return Algorithms::Reduction< typename Expression::DeviceType >::reduce( expression.getSize(), std::multiplies<>{}, fetch, (ResultType) 1 );
 }
 
@@ -141,7 +117,8 @@ auto ExpressionLogicalAnd( const Expression& expression ) -> std::decay_t< declt
    using ResultType = std::decay_t< decltype( expression[0] && expression[0] ) >;
    using IndexType = typename Expression::IndexType;
 
-   auto fetch = [=] __cuda_callable__ ( IndexType i ) { return expression[ i ]; };
+   const auto view = expression.getConstView();
+   auto fetch = [=] __cuda_callable__ ( IndexType i ) { return view[ i ]; };
    return Algorithms::Reduction< typename Expression::DeviceType >::reduce( expression.getSize(), std::logical_and<>{}, fetch, std::numeric_limits< ResultType >::max() );
 }
 
@@ -151,7 +128,8 @@ auto ExpressionLogicalOr( const Expression& expression ) -> std::decay_t< declty
    using ResultType = std::decay_t< decltype( expression[0] || expression[0] ) >;
    using IndexType = typename Expression::IndexType;
 
-   auto fetch = [=] __cuda_callable__ ( IndexType i ) { return expression[ i ]; };
+   const auto view = expression.getConstView();
+   auto fetch = [=] __cuda_callable__ ( IndexType i ) { return view[ i ]; };
    return Algorithms::Reduction< typename Expression::DeviceType >::reduce( expression.getSize(), std::logical_or<>{}, fetch, (ResultType) 0 );
 }
 
@@ -161,7 +139,8 @@ auto ExpressionBinaryAnd( const Expression& expression ) -> std::decay_t< declty
    using ResultType = std::decay_t< decltype( expression[0] & expression[0] ) >;
    using IndexType = typename Expression::IndexType;
 
-   auto fetch = [=] __cuda_callable__ ( IndexType i ) { return expression[ i ]; };
+   const auto view = expression.getConstView();
+   auto fetch = [=] __cuda_callable__ ( IndexType i ) { return view[ i ]; };
    return Algorithms::Reduction< typename Expression::DeviceType >::reduce( expression.getSize(), std::bit_and<>{}, fetch, std::numeric_limits< ResultType >::max() );
 }
 
@@ -171,7 +150,8 @@ auto ExpressionBinaryOr( const Expression& expression ) -> std::decay_t< decltyp
    using ResultType = std::decay_t< decltype( expression[0] | expression[0] ) >;
    using IndexType = typename Expression::IndexType;
 
-   auto fetch = [=] __cuda_callable__ ( IndexType i ) { return expression[ i ]; };
+   const auto view = expression.getConstView();
+   auto fetch = [=] __cuda_callable__ ( IndexType i ) { return view[ i ]; };
    return Algorithms::Reduction< typename Expression::DeviceType >::reduce( expression.getSize(), std::bit_or<>{}, fetch, (ResultType) 0 );
 }
 
diff --git a/src/TNL/Containers/StaticArray.hpp b/src/TNL/Containers/StaticArray.hpp
index c1ac8e62a7a2e8257d0824c36d7f4caaa443e661..c6af2e4edc7c0bed8347ac47403eb2a6644baad2 100644
--- a/src/TNL/Containers/StaticArray.hpp
+++ b/src/TNL/Containers/StaticArray.hpp
@@ -102,21 +102,21 @@ template< int Size, typename Value >
 __cuda_callable__
 StaticArray< Size, Value >::StaticArray( const Value v[ Size ] )
 {
-   Algorithms::StaticFor< 0, Size >::exec( detail::AssignArrayFunctor{}, data, v );
+   Algorithms::StaticFor< 0, Size >::exec( detail::AssignArrayFunctor{}, getData(), v );
 }
 
 template< int Size, typename Value >
 __cuda_callable__
 StaticArray< Size, Value >::StaticArray( const Value& v )
 {
-   Algorithms::StaticFor< 0, Size >::exec( detail::AssignValueFunctor{}, data, v );
+   Algorithms::StaticFor< 0, Size >::exec( detail::AssignValueFunctor{}, getData(), v );
 }
 
 template< int Size, typename Value >
 __cuda_callable__
 StaticArray< Size, Value >::StaticArray( const StaticArray< Size, Value >& v )
 {
-   Algorithms::StaticFor< 0, Size >::exec( detail::AssignArrayFunctor{}, data, v.getData() );
+   Algorithms::StaticFor< 0, Size >::exec( detail::AssignArrayFunctor{}, getData(), v.getData() );
 }
 
 template< int Size, typename Value >
@@ -228,7 +228,7 @@ template< int Size, typename Value >
 __cuda_callable__
 StaticArray< Size, Value >& StaticArray< Size, Value >::operator=( const StaticArray< Size, Value >& array )
 {
-   Algorithms::StaticFor< 0, Size >::exec( detail::AssignArrayFunctor{}, data, array.getData() );
+   Algorithms::StaticFor< 0, Size >::exec( detail::AssignArrayFunctor{}, getData(), array.getData() );
    return *this;
 }
 
@@ -264,7 +264,7 @@ StaticArray< Size, Value >::
 operator StaticArray< Size, OtherValue >() const
 {
    StaticArray< Size, OtherValue > aux;
-   Algorithms::StaticFor< 0, Size >::exec( detail::AssignArrayFunctor{}, aux.getData(), data );
+   Algorithms::StaticFor< 0, Size >::exec( detail::AssignArrayFunctor{}, aux.getData(), getData() );
    return aux;
 }
 
@@ -272,27 +272,27 @@ template< int Size, typename Value >
 __cuda_callable__
 void StaticArray< Size, Value >::setValue( const ValueType& val )
 {
-   Algorithms::StaticFor< 0, Size >::exec( detail::AssignValueFunctor{}, data, val );
+   Algorithms::StaticFor< 0, Size >::exec( detail::AssignValueFunctor{}, getData(), val );
 }
 
 template< int Size, typename Value >
 bool StaticArray< Size, Value >::save( File& file ) const
 {
-   file.save( data, Size );
+   file.save( getData(), Size );
    return true;
 }
 
 template< int Size, typename Value >
 bool StaticArray< Size, Value >::load( File& file)
 {
-   file.load( data, Size );
+   file.load( getData(), Size );
    return true;
 }
 
 template< int Size, typename Value >
 void StaticArray< Size, Value >::sort()
 {
-   detail::StaticArraySort< Size - 1, 0, Value >::exec( data );
+   detail::StaticArraySort< Size - 1, 0, Value >::exec( getData() );
 }
 
 template< int Size, typename Value >
diff --git a/src/TNL/Containers/StaticVector.h b/src/TNL/Containers/StaticVector.h
index 2fe136ac951d4c02bb339e4c0edcee43f3c3b7d8..86726a4d3bafa0264501be5b1394974eda977642 100644
--- a/src/TNL/Containers/StaticVector.h
+++ b/src/TNL/Containers/StaticVector.h
@@ -73,7 +73,7 @@ public:
     */
    template< typename T1,
              typename T2,
-             template< typename, typename > class Operation >
+             typename Operation >
    __cuda_callable__
    StaticVector( const Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >& expr );
 
@@ -83,7 +83,7 @@ public:
     * \param expr is unary expression
     */
    template< typename T,
-             template< typename > class Operation >
+             typename Operation >
    __cuda_callable__
    StaticVector( const Expressions::StaticUnaryExpressionTemplate< T, Operation >& expr );
 
@@ -172,11 +172,18 @@ public:
    operator StaticVector< Size, OtherReal >() const;
 };
 
+// Enable expression templates for StaticVector
+namespace Expressions {
+   template< int Size, typename Real >
+   struct HasEnabledStaticExpressionTemplates< StaticVector< Size, Real > >
+   : std::true_type
+   {};
+} // namespace Expressions
+
 } // namespace Containers
 } // namespace TNL
 
 #include <TNL/Containers/StaticVector.hpp>
-#include <TNL/Containers/StaticVectorExpressions.h>
 
 // TODO: move to some other source file
 namespace TNL {
diff --git a/src/TNL/Containers/StaticVector.hpp b/src/TNL/Containers/StaticVector.hpp
index dc97eeea99b5d551e11beb7543e5f0822f79fad4..4a1b41b2198d114bfe31fed16b3d04f37cf3ad5d 100644
--- a/src/TNL/Containers/StaticVector.hpp
+++ b/src/TNL/Containers/StaticVector.hpp
@@ -19,7 +19,7 @@ namespace Containers {
 template< int Size, typename Real >
    template< typename T1,
              typename T2,
-             template< typename, typename > class Operation >
+             typename Operation >
 __cuda_callable__
 StaticVector< Size, Real >::StaticVector( const Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >& expr )
 {
@@ -29,7 +29,7 @@ StaticVector< Size, Real >::StaticVector( const Expressions::StaticBinaryExpress
 template< int Size,
           typename Real >
    template< typename T,
-             template< typename > class Operation >
+             typename Operation >
 __cuda_callable__
 StaticVector< Size, Real >::StaticVector( const Expressions::StaticUnaryExpressionTemplate< T, Operation >& expr )
 {
diff --git a/src/TNL/Containers/StaticVectorExpressions.h b/src/TNL/Containers/StaticVectorExpressions.h
deleted file mode 100644
index fdaf7cf70fb5a894bce285bac7f4bc6a359ab878..0000000000000000000000000000000000000000
--- a/src/TNL/Containers/StaticVectorExpressions.h
+++ /dev/null
@@ -1,774 +0,0 @@
-/***************************************************************************
-                          StaticVectorExpressions.h  -  description
-                             -------------------
-    begin                : Apr 19, 2019
-    copyright            : (C) 2019 by Tomas Oberhuber
-    email                : tomas.oberhuber@fjfi.cvut.cz
- ***************************************************************************/
-
-/* See Copyright Notice in tnl/Copyright */
-
-#pragma once
-#ifndef DOXYGEN_ONLY
-
-#include <TNL/Containers/Expressions/StaticExpressionTemplates.h>
-
-#include "StaticVector.h"
-
-namespace TNL {
-namespace Containers {
-// operators must be defined in the same namespace as the first operand, otherwise
-// they may not be considered by the compiler (e.g. inside pybind11's macros)
-// namespace Containers { Overriden operators should be in namespace TNL
-
-////
-// Addition
-template< int Size, typename Real, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-__cuda_callable__
-auto
-operator+( const StaticVector< Size, Real >& a, const ET& b )
-{
-   return Expressions::StaticBinaryExpressionTemplate< StaticVector< Size, Real >, ET, Expressions::Addition >( a, b );
-}
-
-template< typename ET, int Size, typename Real,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-__cuda_callable__
-auto
-operator+( const ET& a, const StaticVector< Size, Real >& b )
-{
-   return Expressions::StaticBinaryExpressionTemplate< ET, StaticVector< Size, Real >, Expressions::Addition >( a, b );
-}
-
-template< int Size, typename Real1, typename Real2 >
-__cuda_callable__
-auto
-operator+( const StaticVector< Size, Real1 >& a, const StaticVector< Size, Real2 >& b )
-{
-   return Expressions::StaticBinaryExpressionTemplate< StaticVector< Size, Real1 >, StaticVector< Size, Real2 >, Expressions::Addition >( a, b );
-}
-
-////
-// Subtraction
-template< int Size, typename Real, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-__cuda_callable__
-auto
-operator-( const StaticVector< Size, Real >& a, const ET& b )
-{
-   return Expressions::StaticBinaryExpressionTemplate< StaticVector< Size, Real >, ET, Expressions::Subtraction >( a, b );
-}
-
-template< typename ET, int Size, typename Real,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-__cuda_callable__
-auto
-operator-( const ET& a, const StaticVector< Size, Real >& b )
-{
-   return Expressions::StaticBinaryExpressionTemplate< ET, StaticVector< Size, Real >, Expressions::Subtraction >( a, b );
-}
-
-template< int Size, typename Real1, typename Real2 >
-__cuda_callable__
-auto
-operator-( const StaticVector< Size, Real1 >& a, const StaticVector< Size, Real2 >& b )
-{
-   return Expressions::StaticBinaryExpressionTemplate< StaticVector< Size, Real1 >, StaticVector< Size, Real2 >, Expressions::Subtraction >( a, b );
-}
-
-////
-// Multiplication
-template< int Size, typename Real, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-__cuda_callable__
-auto
-operator*( const StaticVector< Size, Real >& a, const ET& b )
-{
-   return Expressions::StaticBinaryExpressionTemplate< StaticVector< Size, Real >, ET, Expressions::Multiplication >( a, b );
-}
-
-template< typename ET, int Size, typename Real,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-__cuda_callable__
-auto
-operator*( const ET& a, const StaticVector< Size, Real >& b )
-{
-   return Expressions::StaticBinaryExpressionTemplate< ET, StaticVector< Size, Real >, Expressions::Multiplication >( a, b );
-}
-
-template< int Size, typename Real1, typename Real2 >
-__cuda_callable__
-auto
-operator*( const StaticVector< Size, Real1 >& a, const StaticVector< Size, Real2 >& b )
-{
-   return Expressions::StaticBinaryExpressionTemplate< StaticVector< Size, Real1 >, StaticVector< Size, Real2 >, Expressions::Multiplication >( a, b );
-}
-
-////
-// Division
-template< int Size, typename Real, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-__cuda_callable__
-auto
-operator/( const StaticVector< Size, Real >& a, const ET& b )
-{
-   return Expressions::StaticBinaryExpressionTemplate< StaticVector< Size, Real >, ET, Expressions::Division >( a, b );
-}
-
-template< typename ET, int Size, typename Real,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-__cuda_callable__
-auto
-operator/( const ET& a, const StaticVector< Size, Real >& b )
-{
-   return Expressions::StaticBinaryExpressionTemplate< ET, StaticVector< Size, Real >, Expressions::Division >( a, b );
-}
-
-template< int Size, typename Real1, typename Real2 >
-__cuda_callable__
-auto
-operator/( const StaticVector< Size, Real1 >& a, const StaticVector< Size, Real2 >& b )
-{
-   return Expressions::StaticBinaryExpressionTemplate< StaticVector< Size, Real1 >, StaticVector< Size, Real2 >, Expressions::Division >( a, b );
-}
-
-////
-// Comparison operations - operator ==
-template< int Size, typename Real, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-__cuda_callable__
-bool operator==( const StaticVector< Size, Real >& a, const ET& b )
-{
-   return Expressions::StaticComparison< StaticVector< Size, Real >, ET >::EQ( a, b );
-}
-
-template< typename ET, int Size, typename Real,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-__cuda_callable__
-bool operator==( const ET& a, const StaticVector< Size, Real >& 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::StaticComparison< StaticVector< Size, Real1 >, StaticVector< Size, Real2 > >::EQ( a, b );
-}
-
-////
-// Comparison operations - operator !=
-template< int Size, typename Real, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-__cuda_callable__
-bool operator!=( const StaticVector< Size, Real >& a, const ET& b )
-{
-   return Expressions::StaticComparison< StaticVector< Size, Real >, ET >::NE( a, b );
-}
-
-template< typename ET, int Size, typename Real,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-__cuda_callable__
-bool operator!=( const ET& a, const StaticVector< Size, Real >& 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::StaticComparison< StaticVector< Size, Real1 >, StaticVector< Size, Real2 > >::NE( a, b );
-}
-
-////
-// Comparison operations - operator <
-template< int Size, typename Real, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-__cuda_callable__
-bool operator<( const StaticVector< Size, Real >& a, const ET& b )
-{
-   return Expressions::StaticComparison< StaticVector< Size, Real >, ET >::LT( a, b );
-}
-
-template< typename ET, int Size, typename Real,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-__cuda_callable__
-bool operator<( const ET& a, const StaticVector< Size, Real >& 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::StaticComparison< StaticVector< Size, Real1 >, StaticVector< Size, Real2 > >::LT( a, b );
-}
-
-////
-// Comparison operations - operator <=
-template< int Size, typename Real, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-__cuda_callable__
-bool operator<=( const StaticVector< Size, Real >& a, const ET& b )
-{
-   return Expressions::StaticComparison< StaticVector< Size, Real >, ET >::LE( a, b );
-}
-
-template< typename ET, int Size, typename Real,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-__cuda_callable__
-bool operator<=( const ET& a, const StaticVector< Size, Real >& 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::StaticComparison< StaticVector< Size, Real1 >, StaticVector< Size, Real2 > >::LE( a, b );
-}
-
-////
-// Comparison operations - operator >
-template< int Size, typename Real, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-__cuda_callable__
-bool operator>( const StaticVector< Size, Real >& a, const ET& b )
-{
-   return Expressions::StaticComparison< StaticVector< Size, Real >, ET >::GT( a, b );
-}
-
-template< typename ET, int Size, typename Real,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-__cuda_callable__
-bool operator>( const ET& a, const StaticVector< Size, Real >& 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::StaticComparison< StaticVector< Size, Real1 >, StaticVector< Size, Real2 > >::GT( a, b );
-}
-
-////
-// Comparison operations - operator >=
-template< int Size, typename Real, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-__cuda_callable__
-bool operator>=( const StaticVector< Size, Real >& a, const ET& b )
-{
-   return Expressions::StaticComparison< StaticVector< Size, Real >, ET >::GE( a, b );
-}
-
-template< typename ET, int Size, typename Real,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-__cuda_callable__
-bool operator>=( const ET& a, const StaticVector< Size, Real >& 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::StaticComparison< StaticVector< Size, Real1 >, StaticVector< Size, Real2 > >::GE( a, b );
-}
-
-////
-// Minus
-template< int Size, typename Real >
-__cuda_callable__
-auto
-operator-( const StaticVector< Size, Real >& a )
-{
-   return Expressions::StaticUnaryExpressionTemplate< StaticVector< Size, Real >, Expressions::Minus >( a );
-}
-
-////
-// Scalar product
-template< int Size, typename Real, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-__cuda_callable__
-auto
-operator,( const StaticVector< Size, Real >& a, const ET& b )
-{
-   return Containers::Expressions::StaticExpressionSum( a * b );
-}
-
-template< typename ET, int Size, typename Real,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-__cuda_callable__
-auto
-operator,( const ET& a, const StaticVector< Size, Real >& b )
-{
-   return Containers::Expressions::StaticExpressionSum( a * b );
-}
-
-template< typename Real1, int Size, typename Real2 >
-__cuda_callable__
-auto
-operator,( const StaticVector< Size, Real1 >& a, const StaticVector< Size, Real2 >& b )
-{
-   return Containers::Expressions::StaticExpressionSum( a * b );
-}
-
-} // namespace Containers
-
-////
-// Min
-template< int Size, typename Real, typename ET,
-          typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > >
-__cuda_callable__
-auto
-min( const Containers::StaticVector< Size, Real >& a, const ET& b )
-{
-   return Containers::Expressions::StaticBinaryExpressionTemplate< Containers::StaticVector< Size, Real >, ET, Containers::Expressions::Min >( a, b );
-}
-
-template< typename ET, int Size, typename Real,
-          typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > >
-__cuda_callable__
-auto
-min( const ET& a, const Containers::StaticVector< Size, Real >& b )
-{
-   return Containers::Expressions::StaticBinaryExpressionTemplate< ET, Containers::StaticVector< Size, Real >, Containers::Expressions::Min >( a, b );
-}
-
-template< int Size, typename Real1, typename Real2 >
-__cuda_callable__
-auto
-min( const Containers::StaticVector< Size, Real1 >& a, const Containers::StaticVector< Size, Real2 >& b )
-{
-   return Containers::Expressions::StaticBinaryExpressionTemplate< Containers::StaticVector< Size, Real1 >, Containers::StaticVector< Size, Real2 >, Containers::Expressions::Min >( a, b );
-}
-
-////
-// Max
-template< int Size, typename Real, typename ET,
-          typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > >
-__cuda_callable__
-auto
-max( const Containers::StaticVector< Size, Real >& a, const ET& b )
-{
-   return Containers::Expressions::StaticBinaryExpressionTemplate< Containers::StaticVector< Size, Real >, ET, Containers::Expressions::Max >( a, b );
-}
-
-template< typename ET, int Size, typename Real,
-          typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > >
-__cuda_callable__
-auto
-max( const ET& a, const Containers::StaticVector< Size, Real >& b )
-{
-   return Containers::Expressions::StaticBinaryExpressionTemplate< ET, Containers::StaticVector< Size, Real >, Containers::Expressions::Max >( a, b );
-}
-
-template< int Size, typename Real1, typename Real2 >
-__cuda_callable__
-auto
-max( const Containers::StaticVector< Size, Real1 >& a, const Containers::StaticVector< Size, Real2 >& b )
-{
-   return Containers::Expressions::StaticBinaryExpressionTemplate< Containers::StaticVector< Size, Real1 >, Containers::StaticVector< Size, Real2 >, Containers::Expressions::Max >( a, b );
-}
-
-////
-// Dot product - the same as scalar product, just for convenience
-template< int Size, typename Real, typename ET,
-          typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > >
-__cuda_callable__
-auto
-dot( const Containers::StaticVector< Size, Real >& a, const ET& b )
-{
-   return (a, b);
-}
-
-template< typename ET, int Size, typename Real,
-          typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > >
-__cuda_callable__
-auto
-dot( const ET& a, const Containers::StaticVector< Size, Real >& b )
-{
-   return (a, b);
-}
-
-template< typename Real1, int Size, typename Real2 >
-__cuda_callable__
-auto
-dot( const Containers::StaticVector< Size, Real1 >& a, const Containers::StaticVector< Size, Real2 >& b )
-{
-   return (a, b);
-}
-
-
-////
-// Abs
-template< int Size, typename Real >
-__cuda_callable__
-auto
-abs( const Containers::StaticVector< Size, Real >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< Containers::StaticVector< Size, Real >, Containers::Expressions::Abs >( a );
-}
-
-////
-// Power
-template< int Size, typename Real, typename ExpType >
-__cuda_callable__
-auto
-pow( const Containers::StaticVector< Size, Real >& a, const ExpType& exp )
-{
-   return Containers::Expressions::StaticBinaryExpressionTemplate< Containers::StaticVector< Size, Real >, ExpType, Containers::Expressions::Pow >( a, exp );
-}
-
-////
-// Exp
-template< int Size, typename Real >
-__cuda_callable__
-auto
-exp( const Containers::StaticVector< Size, Real >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< Containers::StaticVector< Size, Real >, Containers::Expressions::Exp >( a );
-}
-
-////
-// Sqrt
-template< int Size, typename Real >
-__cuda_callable__
-auto
-sqrt( const Containers::StaticVector< Size, Real >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< Containers::StaticVector< Size, Real >, Containers::Expressions::Sqrt >( a );
-}
-
-////
-// Cbrt
-template< int Size, typename Real >
-__cuda_callable__
-auto
-cbrt( const Containers::StaticVector< Size, Real >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< Containers::StaticVector< Size, Real >, Containers::Expressions::Cbrt >( a );
-}
-
-////
-// Log
-template< int Size, typename Real >
-__cuda_callable__
-auto
-log( const Containers::StaticVector< Size, Real >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< Containers::StaticVector< Size, Real >, Containers::Expressions::Log >( a );
-}
-
-////
-// Log10
-template< int Size, typename Real >
-__cuda_callable__
-auto
-log10( const Containers::StaticVector< Size, Real >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< Containers::StaticVector< Size, Real >, Containers::Expressions::Log10 >( a );
-}
-
-////
-// Log2
-template< int Size, typename Real >
-__cuda_callable__
-auto
-log2( const Containers::StaticVector< Size, Real >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< Containers::StaticVector< Size, Real >, Containers::Expressions::Log2 >( a );
-}
-
-////
-// Sine
-template< int Size, typename Real >
-__cuda_callable__
-auto
-sin( const Containers::StaticVector< Size, Real >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< Containers::StaticVector< Size, Real >, Containers::Expressions::Sin >( a );
-}
-
-////
-// Cosine
-template< int Size, typename Real >
-__cuda_callable__
-auto
-cos( const Containers::StaticVector< Size, Real >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< Containers::StaticVector< Size, Real >, Containers::Expressions::Cos >( a );
-}
-
-////
-// Tangent
-template< int Size, typename Real >
-__cuda_callable__
-auto
-tan( const Containers::StaticVector< Size, Real >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< Containers::StaticVector< Size, Real >, Containers::Expressions::Tan >( a );
-}
-
-////
-// Asin
-template< int Size, typename Real >
-__cuda_callable__
-auto
-asin( const Containers::StaticVector< Size, Real >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< Containers::StaticVector< Size, Real >, Containers::Expressions::Asin >( a );
-}
-
-////
-// Acos
-template< int Size, typename Real >
-__cuda_callable__
-auto
-acos( const Containers::StaticVector< Size, Real >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< Containers::StaticVector< Size, Real >, Containers::Expressions::Acos >( a );
-}
-
-////
-// Atan
-template< int Size, typename Real >
-__cuda_callable__
-auto
-atan( const Containers::StaticVector< Size, Real >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< Containers::StaticVector< Size, Real >, Containers::Expressions::Atan >( a );
-}
-
-////
-// Sinh
-template< int Size, typename Real >
-__cuda_callable__
-auto
-sinh( const Containers::StaticVector< Size, Real >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< Containers::StaticVector< Size, Real >, Containers::Expressions::Sinh >( a );
-}
-
-////
-// Cosh
-template< int Size, typename Real >
-__cuda_callable__
-auto
-cosh( const Containers::StaticVector< Size, Real >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< Containers::StaticVector< Size, Real >, Containers::Expressions::Cosh >( a );
-}
-
-////
-// Tanh
-template< int Size, typename Real >
-__cuda_callable__
-auto
-tanh( const Containers::StaticVector< Size, Real >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< Containers::StaticVector< Size, Real >, Containers::Expressions::Tanh >( a );
-}
-
-////
-// Asinh
-template< int Size, typename Real >
-__cuda_callable__
-auto
-asinh( const Containers::StaticVector< Size, Real >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< Containers::StaticVector< Size, Real >, Containers::Expressions::Asinh >( a );
-}
-
-////
-// Acosh
-template< int Size, typename Real >
-__cuda_callable__
-auto
-acosh( const Containers::StaticVector< Size, Real >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< Containers::StaticVector< Size, Real >, Containers::Expressions::Acosh >( a );
-}
-
-////
-// Atanh
-template< int Size, typename Real >
-__cuda_callable__
-auto
-atanh( const Containers::StaticVector< Size, Real >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< Containers::StaticVector< Size, Real >, Containers::Expressions::Atanh >( a );
-}
-
-////
-// Floor
-template< int Size, typename Real >
-__cuda_callable__
-auto
-floor( const Containers::StaticVector< Size, Real >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< Containers::StaticVector< Size, Real >, Containers::Expressions::Floor >( a );
-}
-
-////
-// Ceil
-template< int Size, typename Real >
-__cuda_callable__
-auto
-ceil( const Containers::StaticVector< Size, Real >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< Containers::StaticVector< Size, Real >, Containers::Expressions::Ceil >( a );
-}
-
-////
-// Sign
-template< int Size, typename Real >
-__cuda_callable__
-auto
-sign( const Containers::StaticVector< Size, Real >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< Containers::StaticVector< Size, Real >, Containers::Expressions::Sign >( a );
-}
-
-////
-// Cast
-template< typename ResultType, int Size, typename Real,
-          // workaround: templated type alias cannot be declared at block level
-          template<typename> class Operation = Containers::Expressions::Cast< ResultType >::template Operation >
-auto
-__cuda_callable__
-cast( const Containers::StaticVector< Size, Real >& a )
-{
-   return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Operation >( a );
-}
-
-////
-// Vertical operations - min
-template< int Size, typename Real >
-__cuda_callable__
-auto
-min( const Containers::StaticVector< Size, Real >& a )
-{
-   return Containers::Expressions::StaticExpressionMin( a );
-}
-
-template< int Size, typename Real >
-__cuda_callable__
-std::pair< int, Real >
-argMin( const Containers::StaticVector< Size, Real >& a )
-{
-   return Containers::Expressions::StaticExpressionArgMin( a );
-}
-
-template< int Size, typename Real >
-__cuda_callable__
-auto
-max( const Containers::StaticVector< Size, Real >& a )
-{
-   return Containers::Expressions::StaticExpressionMax( a );
-}
-
-template< int Size, typename Real >
-__cuda_callable__
-std::pair< int, Real >
-argMax( const Containers::StaticVector< Size, Real >& a )
-{
-   return Containers::Expressions::StaticExpressionArgMax( a );
-}
-
-template< int Size, typename Real >
-__cuda_callable__
-auto
-sum( const Containers::StaticVector< Size, Real >& a )
-{
-   return Containers::Expressions::StaticExpressionSum( a );
-}
-
-template< int Size, typename Real >
-__cuda_callable__
-auto
-maxNorm( const Containers::StaticVector< Size, Real >& a )
-{
-   return max( abs( a ) );
-}
-
-template< int Size, typename Real >
-__cuda_callable__
-auto
-l1Norm( const Containers::StaticVector< Size, Real >& a )
-{
-   return Containers::Expressions::StaticExpressionL1Norm( a );
-}
-
-template< int Size, typename Real >
-__cuda_callable__
-auto
-l2Norm( const Containers::StaticVector< Size, Real >& a )
-{
-   return TNL::sqrt( Containers::Expressions::StaticExpressionL2Norm( a ) );
-}
-
-template< int Size, typename Real, typename Real2 >
-__cuda_callable__
-auto
-lpNorm( const Containers::StaticVector< Size, Real >& a, const Real2& p )
-// since (1.0 / p) has type double, TNL::pow returns double
--> double
-{
-   if( p == 1.0 )
-      return l1Norm( a );
-   if( p == 2.0 )
-      return l2Norm( a );
-   return TNL::pow( Containers::Expressions::StaticExpressionLpNorm( a, p ), 1.0 / p );
-}
-
-template< int Size, typename Real >
-__cuda_callable__
-auto
-product( const Containers::StaticVector< Size, Real >& a )
-{
-   return Containers::Expressions::StaticExpressionProduct( a );
-}
-
-template< int Size, typename Real >
-__cuda_callable__
-auto
-logicalOr( const Containers::StaticVector< Size, Real >& a )
-{
-   return Containers::Expressions::StaticExpressionLogicalOr( a );
-}
-
-template< int Size, typename Real >
-__cuda_callable__
-auto
-binaryOr( const Containers::StaticVector< Size, Real >& a )
-{
-   return Containers::Expressions::StaticExpressionBinaryOr( a );
-}
-
-template< int Size, typename Real >
-__cuda_callable__
-auto
-logicalAnd( const Containers::StaticVector< Size, Real >& a )
-{
-   return Containers::Expressions::StaticExpressionLogicalAnd( a );
-}
-
-template< int Size, typename Real >
-__cuda_callable__
-auto
-binaryAnd( const Containers::StaticVector< Size, Real >& a )
-{
-   return Containers::Expressions::StaticExpressionBinaryAnd( a );
-}
-
-} // namespace TNL
-#endif // DOXYGEN_ONLY
diff --git a/src/TNL/Containers/Vector.h b/src/TNL/Containers/Vector.h
index 6bec6932115b03a47696de90a7a560c31762c4a2..259081052c1d0c1241f190cdad4002f98b3bf2d0 100644
--- a/src/TNL/Containers/Vector.h
+++ b/src/TNL/Containers/Vector.h
@@ -174,7 +174,7 @@ public:
     */
    template< typename VectorExpression,
              typename...,
-             typename = std::enable_if_t< Expressions::IsExpressionTemplate< VectorExpression >::value > >
+             typename = std::enable_if_t< Expressions::HasEnabledExpressionTemplates< VectorExpression >::value && ! IsArrayType< VectorExpression >::value > >
    Vector& operator=( const VectorExpression& expression );
 
    /**
@@ -326,8 +326,15 @@ public:
    void segmentedScan( const VectorExpression& expression, FlagsArray& flags, IndexType begin = 0, IndexType end = 0 );
 };
 
+// Enable expression templates for Vector
+namespace Expressions {
+   template< typename Real, typename Device, typename Index, typename Allocator >
+   struct HasEnabledExpressionTemplates< Vector< Real, Device, Index, Allocator > >
+   : std::true_type
+   {};
+} // namespace Expressions
+
 } // namespace Containers
 } // namespace TNL
 
 #include <TNL/Containers/Vector.hpp>
-#include <TNL/Containers/VectorExpressions.h>
diff --git a/src/TNL/Containers/VectorExpressions.h b/src/TNL/Containers/VectorExpressions.h
deleted file mode 100644
index 83d682e8bd50d38a7d16bf1b8895cb624aa021a2..0000000000000000000000000000000000000000
--- a/src/TNL/Containers/VectorExpressions.h
+++ /dev/null
@@ -1,1098 +0,0 @@
-/***************************************************************************
-                          VectorExpressions.h  -  description
-                             -------------------
-    begin                : Jun 27, 2019
-    copyright            : (C) 2019 by Tomas Oberhuber et al.
-    email                : tomas.oberhuber@fjfi.cvut.cz
- ***************************************************************************/
-
-/* See Copyright Notice in tnl/Copyright */
-
-#pragma once
-
-#include <TNL/Containers/Expressions/ExpressionTemplates.h>
-
-#include "Vector.h"
-
-namespace TNL {
-namespace Containers {
-
-/**
- * \brief Addition of vector and vector expression.
- * @param a
- * @param b
- * @return 
- */
-template< typename Real, typename Device, typename Index, typename Allocator, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-auto
-operator+( const Vector< Real, Device, Index, Allocator >& a, const ET& b )
-{
-   using ConstView = typename Vector< Real, Device, Index, Allocator >::ConstViewType;
-   return Expressions::BinaryExpressionTemplate< ConstView, ET, Expressions::Addition >( a.getConstView(), b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Allocator,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-auto
-operator+( const ET& a, const Vector< Real, Device, Index, Allocator >& b )
-{
-   using ConstView = typename Vector< Real, Device, Index, Allocator >::ConstViewType;
-   return Expressions::BinaryExpressionTemplate< ET, ConstView, Expressions::Addition >( a, b.getConstView() );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator >
-auto
-operator+( const Vector< Real1, Device, Index, Allocator >& a, const Vector< Real2, Device, Index, Allocator >& b )
-{
-   using ConstView1 = typename Vector< Real1, Device, Index, Allocator >::ConstViewType;
-   using ConstView2 = typename Vector< Real2, Device, Index, Allocator >::ConstViewType;
-   return Expressions::BinaryExpressionTemplate< ConstView1, ConstView2, Expressions::Addition >( a.getConstView(), b.getConstView() );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator >
-auto
-operator+( const VectorView< Real1, Device, Index >& a, const Vector< Real2, Device, Index, Allocator >& b )
-{
-   using ConstView1 = typename Vector< Real1, Device, Index, Allocator >::ConstViewType;
-   using ConstView2 = typename Vector< Real2, Device, Index, Allocator >::ConstViewType;
-   return Expressions::BinaryExpressionTemplate< ConstView1, ConstView2, Expressions::Addition >( a.getConstView(), b.getConstView() );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator >
-auto
-operator+( const Vector< Real1, Device, Index, Allocator >& a, const VectorView< Real2, Device, Index >& b )
-{
-   using ConstView1 = typename Vector< Real1, Device, Index, Allocator >::ConstViewType;
-   using ConstView2 = typename Vector< Real2, Device, Index, Allocator >::ConstViewType;
-   return Expressions::BinaryExpressionTemplate< ConstView1, ConstView2, Expressions::Addition >( a.getConstView(), b.getConstView() );
-}
-
-////
-// Subtraction
-template< typename Real, typename Device, typename Index, typename Allocator, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-auto
-operator-( const Vector< Real, Device, Index, Allocator >& a, const ET& b )
-{
-   using ConstView = typename Vector< Real, Device, Index, Allocator >::ConstViewType;
-   return Expressions::BinaryExpressionTemplate< ConstView, ET, Expressions::Subtraction >( a.getConstView(), b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Allocator,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-auto
-operator-( const ET& a, const Vector< Real, Device, Index, Allocator >& b )
-{
-   using ConstView = typename Vector< Real, Device, Index, Allocator >::ConstViewType;
-   return Expressions::BinaryExpressionTemplate< ET, ConstView, Expressions::Subtraction >( a, b.getConstView() );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator >
-auto
-operator-( const Vector< Real1, Device, Index, Allocator >& a, const Vector< Real2, Device, Index, Allocator >& b )
-{
-   using ConstView1 = typename Vector< Real1, Device, Index, Allocator >::ConstViewType;
-   using ConstView2 = typename Vector< Real2, Device, Index, Allocator >::ConstViewType;
-   return Expressions::BinaryExpressionTemplate< ConstView1, ConstView2, Expressions::Subtraction >( a.getConstView(), b.getConstView() );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator >
-auto
-operator-( const VectorView< Real1, Device, Index >& a, const Vector< Real2, Device, Index, Allocator >& b )
-{
-   using ConstView1 = typename Vector< Real1, Device, Index, Allocator >::ConstViewType;
-   using ConstView2 = typename Vector< Real2, Device, Index, Allocator >::ConstViewType;
-   return Expressions::BinaryExpressionTemplate< ConstView1, ConstView2, Expressions::Subtraction >( a.getConstView(), b.getConstView() );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator >
-auto
-operator-( const Vector< Real1, Device, Index, Allocator >& a, const VectorView< Real2, Device, Index >& b )
-{
-   using ConstView1 = typename Vector< Real1, Device, Index, Allocator >::ConstViewType;
-   using ConstView2 = typename Vector< Real2, Device, Index, Allocator >::ConstViewType;
-   return Expressions::BinaryExpressionTemplate< ConstView1, ConstView2, Expressions::Subtraction >( a.getConstView(), b.getConstView() );
-}
-
-////
-// Multiplication
-template< typename Real, typename Device, typename Index, typename Allocator, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-auto
-operator*( const Vector< Real, Device, Index, Allocator >& a, const ET& b )
-{
-   using ConstView = typename Vector< Real, Device, Index, Allocator >::ConstViewType;
-   return Expressions::BinaryExpressionTemplate< ConstView, ET, Expressions::Multiplication >( a.getConstView(), b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Allocator,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-auto
-operator*( const ET& a, const Vector< Real, Device, Index, Allocator >& b )
-{
-   using ConstView = typename Vector< Real, Device, Index, Allocator >::ConstViewType;
-   return Expressions::BinaryExpressionTemplate< ET, ConstView, Expressions::Multiplication >( a, b.getConstView() );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator >
-auto
-operator*( const Vector< Real1, Device, Index, Allocator >& a, const Vector< Real2, Device, Index, Allocator >& b )
-{
-   using ConstView1 = typename Vector< Real1, Device, Index, Allocator >::ConstViewType;
-   using ConstView2 = typename Vector< Real2, Device, Index, Allocator >::ConstViewType;
-   return Expressions::BinaryExpressionTemplate< ConstView1, ConstView2, Expressions::Multiplication >( a.getConstView(), b.getConstView() );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator >
-auto
-operator*( const VectorView< Real1, Device, Index >& a, const Vector< Real2, Device, Index, Allocator >& b )
-{
-   using ConstView1 = typename Vector< Real1, Device, Index, Allocator >::ConstViewType;
-   using ConstView2 = typename Vector< Real2, Device, Index, Allocator >::ConstViewType;
-   return Expressions::BinaryExpressionTemplate< ConstView1, ConstView2, Expressions::Multiplication >( a.getConstView(), b.getConstView() );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator >
-auto
-operator*( const Vector< Real1, Device, Index, Allocator >& a, const VectorView< Real2, Device, Index >& b )
-{
-   using ConstView1 = typename Vector< Real1, Device, Index, Allocator >::ConstViewType;
-   using ConstView2 = typename Vector< Real2, Device, Index, Allocator >::ConstViewType;
-   return Expressions::BinaryExpressionTemplate< ConstView1, ConstView2, Expressions::Multiplication >( a.getConstView(), b.getConstView() );
-}
-
-////
-// Division
-template< typename Real, typename Device, typename Index, typename Allocator, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-auto
-operator/( const Vector< Real, Device, Index, Allocator >& a, const ET& b )
-{
-   using ConstView = typename Vector< Real, Device, Index, Allocator >::ConstViewType;
-   return Expressions::BinaryExpressionTemplate< ConstView, ET, Expressions::Division >( a.getConstView(), b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Allocator,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-auto
-operator/( const ET& a, const Vector< Real, Device, Index, Allocator >& b )
-{
-   using ConstView = typename Vector< Real, Device, Index, Allocator >::ConstViewType;
-   return Expressions::BinaryExpressionTemplate< ET, ConstView, Expressions::Division >( a, b.getConstView() );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator >
-auto
-operator/( const Vector< Real1, Device, Index, Allocator >& a, const Vector< Real2, Device, Index, Allocator >& b )
-{
-   using ConstView1 = typename Vector< Real1, Device, Index, Allocator >::ConstViewType;
-   using ConstView2 = typename Vector< Real2, Device, Index, Allocator >::ConstViewType;
-   return Expressions::BinaryExpressionTemplate< ConstView1, ConstView2, Expressions::Division >( a.getConstView(), b.getConstView() );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator >
-auto
-operator/( const VectorView< Real1, Device, Index >& a, const Vector< Real2, Device, Index, Allocator >& b )
-{
-   using ConstView1 = typename Vector< Real1, Device, Index, Allocator >::ConstViewType;
-   using ConstView2 = typename Vector< Real2, Device, Index, Allocator >::ConstViewType;
-   return Expressions::BinaryExpressionTemplate< ConstView1, ConstView2, Expressions::Division >( a.getConstView(), b.getConstView() );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator >
-auto
-operator/( const Vector< Real1, Device, Index, Allocator >& a, const VectorView< Real2, Device, Index >& b )
-{
-   using ConstView1 = typename Vector< Real1, Device, Index, Allocator >::ConstViewType;
-   using ConstView2 = typename Vector< Real2, Device, Index, Allocator >::ConstViewType;
-   return Expressions::BinaryExpressionTemplate< ConstView1, ConstView2, Expressions::Division >( a.getConstView(), b.getConstView() );
-}
-
-////
-// Comparison operations - operator ==
-template< typename Real, typename Device, typename Index, typename Allocator, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator==( const Vector< Real, Device, Index, Allocator >& a, const ET& b )
-{
-   using ConstView = typename VectorView< Real, Device, Index >::ConstViewType;
-   return Expressions::Comparison< ConstView, ET >::EQ( a.getConstView(), b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Allocator,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator==( const ET& a, const Vector< Real, Device, Index, Allocator >& b )
-{
-   using ConstView = typename VectorView< Real, Device, Index >::ConstViewType;
-   return Expressions::Comparison< ET, ConstView >::EQ( a, b.getConstView() );
-}
-
-template< typename Real1, typename Real2, typename Device1, typename Device2, typename Index, typename Allocator >
-bool
-operator==( const Vector< Real1, Device1, Index, Allocator >& a, const Vector< Real2, Device2, Index, Allocator >& b )
-{
-   using ConstView1 = typename Vector< Real1, Device1, Index, Allocator >::ConstViewType;
-   using ConstView2 = typename Vector< Real2, Device2, Index, Allocator >::ConstViewType;
-   return Expressions::Comparison< ConstView1, ConstView2 >::EQ( a.getConstView(), b.getConstView() );
-}
-
-template< typename Real1, typename Real2, typename Device1, typename Device2, typename Index, typename Allocator >
-bool
-operator==( const VectorView< Real1, Device1, Index >& a, const Vector< Real2, Device2, Index, Allocator >& b )
-{
-   using ConstView1 = VectorView< Real1, Device1, Index >;
-   using ConstView2 = typename Vector< Real2, Device2, Index, Allocator >::ConstViewType;
-   return Expressions::Comparison< ConstView1, ConstView2 >::EQ( a, b.getConstView() );
-}
-
-template< typename Real1, typename Real2, typename Device1, typename Device2, typename Index, typename Allocator >
-bool
-operator==( const Vector< Real1, Device1, Index, Allocator >& a, const VectorView< Real2, Device2, Index >& b )
-{
-   using ConstView1 = typename Vector< Real1, Device1, Index, Allocator >::ConstViewType;
-   using ConstView2 = VectorView< Real2, Device2, Index >;
-   return Expressions::Comparison< ConstView1, ConstView2 >::EQ( a.getConstView(), b );
-}
-
-////
-// Comparison operations - operator !=
-template< typename Real, typename Device, typename Index, typename Allocator, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator!=( const Vector< Real, Device, Index, Allocator >& a, const ET& b )
-{
-   using ConstView = typename VectorView< Real, Device, Index >::ConstViewType;
-   return Expressions::Comparison< ConstView, ET >::NE( a.getConstView(), b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Allocator,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator!=( const ET& a, const Vector< Real, Device, Index, Allocator >& b )
-{
-   using ConstView = typename VectorView< Real, Device, Index >::ConstViewType;
-   return Expressions::Comparison< ET, ConstView >::NE( a, b.getConstView() );
-}
-
-template< typename Real1, typename Real2, typename Device1, typename Device2, typename Index, typename Allocator >
-bool
-operator!=( const Vector< Real1, Device1, Index, Allocator >& a, const Vector< Real2, Device2, Index, Allocator >& b )
-{
-   return ! (a == b);
-}
-
-template< typename Real1, typename Real2, typename Device1, typename Device2, typename Index, typename Allocator >
-bool
-operator!=( const VectorView< Real1, Device1, Index >& a, const Vector< Real2, Device2, Index, Allocator >& b )
-{
-   return ! (a == b);
-}
-
-template< typename Real1, typename Real2, typename Device1, typename Device2, typename Index, typename Allocator >
-bool
-operator!=( const Vector< Real1, Device1, Index, Allocator >& a, const VectorView< Real2, Device2, Index >& b )
-{
-   return ! (a == b);
-}
-
-////
-// Comparison operations - operator <
-template< typename Real, typename Device, typename Index, typename Allocator, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator<( const Vector< Real, Device, Index, Allocator >& a, const ET& b )
-{
-   using ConstView = typename VectorView< Real, Device, Index >::ConstViewType;
-   return Expressions::Comparison< ConstView, ET >::LT( a.getConstView(), b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Allocator,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator<( const ET& a, const Vector< Real, Device, Index, Allocator >& b )
-{
-   using ConstView = typename VectorView< Real, Device, Index >::ConstViewType;
-   return Expressions::Comparison< ET, ConstView >::LT( a, b.getConstView() );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator >
-bool
-operator<( const Vector< Real1, Device, Index, Allocator >& a, const Vector< Real2, Device, Index, Allocator >& b )
-{
-   using ConstView1 = typename Vector< Real1, Device, Index, Allocator >::ConstViewType;
-   using ConstView2 = typename VectorView< Real2, Device, Index >::ConstViewType;
-   return Expressions::Comparison< ConstView1, ConstView2 >::LT( a.getConstView(), b.getConstView() );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator >
-bool
-operator<( const VectorView< Real1, Device, Index >& a, const Vector< Real2, Device, Index, Allocator >& b )
-{
-   using ConstView1 = typename Vector< Real1, Device, Index, Allocator >::ConstViewType;
-   using ConstView2 = typename VectorView< Real2, Device, Index >::ConstViewType;
-   return Expressions::Comparison< ConstView1, ConstView2 >::LT( a.getConstView(), b.getConstView() );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator >
-bool
-operator<( const Vector< Real1, Device, Index, Allocator >& a, const VectorView< Real2, Device, Index >& b )
-{
-   using ConstView1 = typename Vector< Real1, Device, Index, Allocator >::ConstViewType;
-   using ConstView2 = typename VectorView< Real2, Device, Index >::ConstViewType;
-   return Expressions::Comparison< ConstView1, ConstView2 >::LT( a.getConstView(), b.getConstView() );
-}
-
-////
-// Comparison operations - operator <=
-template< typename Real, typename Device, typename Index, typename Allocator, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator<=( const Vector< Real, Device, Index, Allocator >& a, const ET& b )
-{
-   using ConstView = typename VectorView< Real, Device, Index >::ConstViewType;
-   return Expressions::Comparison< ConstView, ET >::LE( a.getConstView(), b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Allocator,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator<=( const ET& a, const Vector< Real, Device, Index, Allocator >& b )
-{
-   using ConstView = typename VectorView< Real, Device, Index >::ConstViewType;
-   return Expressions::Comparison< ET, ConstView >::LE( a, b.getConstView() );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator >
-bool
-operator<=( const Vector< Real1, Device, Index, Allocator >& a, const Vector< Real2, Device, Index, Allocator >& b )
-{
-   using ConstView1 = typename Vector< Real1, Device, Index, Allocator >::ConstViewType;
-   using ConstView2 = typename VectorView< Real2, Device, Index >::ConstViewType;
-   return Expressions::Comparison< ConstView1, ConstView2 >::LE( a.getConstView(), b.getConstView() );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator >
-bool
-operator<=( const VectorView< Real1, Device, Index >& a, const Vector< Real2, Device, Index, Allocator >& b )
-{
-   using ConstView1 = typename Vector< Real1, Device, Index, Allocator >::ConstViewType;
-   using ConstView2 = typename VectorView< Real2, Device, Index >::ConstViewType;
-   return Expressions::Comparison< ConstView1, ConstView2 >::LE( a.getConstView(), b.getConstView() );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator >
-bool
-operator<=( const Vector< Real1, Device, Index, Allocator >& a, const VectorView< Real2, Device, Index >& b )
-{
-   using ConstView1 = typename Vector< Real1, Device, Index, Allocator >::ConstViewType;
-   using ConstView2 = typename VectorView< Real2, Device, Index >::ConstViewType;
-   return Expressions::Comparison< ConstView1, ConstView2 >::LE( a.getConstView(), b.getConstView() );
-}
-
-////
-// Comparison operations - operator >
-template< typename Real, typename Device, typename Index, typename Allocator, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator>( const Vector< Real, Device, Index, Allocator >& a, const ET& b )
-{
-   using ConstView = typename VectorView< Real, Device, Index >::ConstViewType;
-   return Expressions::Comparison< ConstView, ET >::GT( a.getConstView(), b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Allocator,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator>( const ET& a, const Vector< Real, Device, Index, Allocator >& b )
-{
-   using ConstView = typename VectorView< Real, Device, Index >::ConstViewType;
-   return Expressions::Comparison< ET, ConstView >::GT( a, b.getConstView() );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator >
-bool
-operator>( const Vector< Real1, Device, Index, Allocator >& a, const Vector< Real2, Device, Index, Allocator >& b )
-{
-   using ConstView1 = typename Vector< Real1, Device, Index, Allocator >::ConstViewType;
-   using ConstView2 = typename VectorView< Real2, Device, Index >::ConstViewType;
-   return Expressions::Comparison< ConstView1, ConstView2 >::GT( a.getConstView(), b.getConstView() );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator >
-bool
-operator>( const VectorView< Real1, Device, Index >& a, const Vector< Real2, Device, Index, Allocator >& b )
-{
-   using ConstView1 = typename Vector< Real1, Device, Index, Allocator >::ConstViewType;
-   using ConstView2 = typename VectorView< Real2, Device, Index >::ConstViewType;
-   return Expressions::Comparison< ConstView1, ConstView2 >::GT( a.getConstView(), b.getConstView() );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator >
-bool
-operator>( const Vector< Real1, Device, Index, Allocator >& a, const VectorView< Real2, Device, Index >& b )
-{
-   using ConstView1 = typename Vector< Real1, Device, Index, Allocator >::ConstViewType;
-   using ConstView2 = typename VectorView< Real2, Device, Index >::ConstViewType;
-   return Expressions::Comparison< ConstView1, ConstView2 >::GT( a.getConstView(), b.getConstView() );
-}
-
-////
-// Comparison operations - operator >=
-template< typename Real, typename Device, typename Index, typename Allocator, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator>=( const Vector< Real, Device, Index, Allocator >& a, const ET& b )
-{
-   using ConstView = typename VectorView< Real, Device, Index >::ConstViewType;
-   return Expressions::Comparison< ConstView, ET >::GE( a.getConstView(), b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Allocator,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator>=( const ET& a, const Vector< Real, Device, Index, Allocator >& b )
-{
-   using ConstView = typename VectorView< Real, Device, Index >::ConstViewType;
-   return Expressions::Comparison< ET, ConstView >::GE( a, b.getConstView() );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator >
-bool
-operator>=( const Vector< Real1, Device, Index, Allocator >& a, const Vector< Real2, Device, Index, Allocator >& b )
-{
-   using ConstView1 = typename Vector< Real1, Device, Index, Allocator >::ConstViewType;
-   using ConstView2 = typename VectorView< Real2, Device, Index >::ConstViewType;
-   return Expressions::Comparison< ConstView1, ConstView2 >::GE( a.getConstView(), b.getConstView() );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator >
-bool
-operator>=( const VectorView< Real1, Device, Index >& a, const Vector< Real2, Device, Index, Allocator >& b )
-{
-   using ConstView1 = typename Vector< Real1, Device, Index, Allocator >::ConstViewType;
-   using ConstView2 = typename VectorView< Real2, Device, Index >::ConstViewType;
-   return Expressions::Comparison< ConstView1, ConstView2 >::GE( a.getConstView(), b.getConstView() );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator >
-bool
-operator>=( const Vector< Real1, Device, Index, Allocator >& a, const VectorView< Real2, Device, Index >& b )
-{
-   using ConstView1 = typename Vector< Real1, Device, Index, Allocator >::ConstViewType;
-   using ConstView2 = typename VectorView< Real2, Device, Index >::ConstViewType;
-   return Expressions::Comparison< ConstView1, ConstView2 >::GE( a.getConstView(), b.getConstView() );
-}
-
-////
-// Minus
-template< typename Real, typename Device, typename Index, typename Allocator >
-auto
-operator-( const Vector< Real, Device, Index, Allocator >& a )
-{
-   using ConstView = typename Vector< Real, Device, Index, Allocator >::ConstViewType;
-   return Expressions::UnaryExpressionTemplate< ConstView, Expressions::Minus >( a.getConstView() );
-}
-
-////
-// Scalar product
-#ifdef DOXYGEN_ONLY
-/**
- * \brief Computes scalar product of two vectors or vector expressions. Equivalent to \ref TNL::dot.
- *
- * @param a input vector or vector expression
- * @param b input vector or vector expression
- * @return scalar product of \e a and \e b.
- */
-template< typename ET1, typename ET2 >
-Real
-operator,( const ET1& a, const ET2& b ) {}
-#else
-
-template< typename Real, typename Device, typename Index, typename Allocator, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-Real
-operator,( const Vector< Real, Device, Index, Allocator >& a, const ET& b )
-{
-   return Expressions::ExpressionSum( a.getConstView() * b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Allocator,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-Real
-operator,( const ET& a, const Vector< Real, Device, Index, Allocator >& b )
-{
-   return Expressions::ExpressionSum( a * b.getConstView() );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator >
-auto
-operator,( const Vector< Real1, Device, Index, Allocator >& a, const Vector< Real2, Device, Index, Allocator >& b )
-{
-   return Expressions::ExpressionSum( a.getConstView() * b.getConstView() );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator >
-auto
-operator,( const VectorView< Real1, Device, Index >& a, const Vector< Real2, Device, Index, Allocator >& b )
-{
-   return Expressions::ExpressionSum( a.getConstView() * b.getConstView() );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator >
-auto
-operator,( const Vector< Real1, Device, Index, Allocator >& a, const VectorView< Real2, Device, Index >& b )
-{
-   return Expressions::ExpressionSum( a.getConstView() * b.getConstView() );
-}
-#endif // DOXYGEN_ONLY
-
-} //namespace Containers
-
-////
-// All functions are supposed to be in namespace TNL
-
-////
-// Min
-template< typename Real, typename Device, typename Index, typename Allocator, typename ET,
-          typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > >
-auto
-min( const Containers::Vector< Real, Device, Index, Allocator >& a, const ET& b )
-{
-   using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType;
-   return Containers::Expressions::BinaryExpressionTemplate< ConstView, ET, Containers::Expressions::Min >( a.getConstView(), b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Allocator,
-          typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > >
-auto
-min( const ET& a, const Containers::Vector< Real, Device, Index, Allocator >& b )
-{
-   using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType;
-   return Containers::Expressions::BinaryExpressionTemplate< ET, ConstView, Containers::Expressions::Min >( a, b.getConstView() );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator >
-auto
-min( const Containers::Vector< Real1, Device, Index, Allocator >& a, const Containers::Vector< Real2, Device, Index, Allocator >& b )
-{
-   using ConstView1 = typename Containers::Vector< Real1, Device, Index, Allocator >::ConstViewType;
-   using ConstView2 = typename Containers::Vector< Real2, Device, Index, Allocator >::ConstViewType;
-   return Containers::Expressions::BinaryExpressionTemplate< ConstView1, ConstView2, Containers::Expressions::Min >( a.getConstView(), b.getConstView() );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator >
-auto
-min( const Containers::VectorView< Real1, Device, Index >& a, const Containers::Vector< Real2, Device, Index, Allocator >& b )
-{
-   using ConstView1 = typename Containers::Vector< Real1, Device, Index, Allocator >::ConstViewType;
-   using ConstView2 = typename Containers::Vector< Real2, Device, Index, Allocator >::ConstViewType;
-   return Containers::Expressions::BinaryExpressionTemplate< ConstView1, ConstView2, Containers::Expressions::Min >( a.getConstView(), b.getConstView() );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator >
-auto
-min( const Containers::Vector< Real1, Device, Index, Allocator >& a, const Containers::VectorView< Real2, Device, Index >& b )
-{
-   using ConstView1 = typename Containers::Vector< Real1, Device, Index, Allocator >::ConstViewType;
-   using ConstView2 = typename Containers::Vector< Real2, Device, Index, Allocator >::ConstViewType;
-   return Containers::Expressions::BinaryExpressionTemplate< ConstView1, ConstView2, Containers::Expressions::Min >( a.getConstView(), b.getConstView() );
-}
-
-////
-// Max
-template< typename Real, typename Device, typename Index, typename Allocator, typename ET,
-          typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > >
-auto
-max( const Containers::Vector< Real, Device, Index, Allocator >& a, const ET& b )
-{
-   using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType;
-   return Containers::Expressions::BinaryExpressionTemplate< ConstView, ET, Containers::Expressions::Max >( a.getConstView(), b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Allocator,
-          typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > >
-auto
-max( const ET& a, const Containers::Vector< Real, Device, Index, Allocator >& b )
-{
-   using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType;
-   return Containers::Expressions::BinaryExpressionTemplate< ET, ConstView, Containers::Expressions::Max >( a, b.getConstView() );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator >
-auto
-max( const Containers::Vector< Real1, Device, Index, Allocator >& a, const Containers::Vector< Real2, Device, Index, Allocator >& b )
-{
-   using ConstView1 = typename Containers::Vector< Real1, Device, Index, Allocator >::ConstViewType;
-   using ConstView2 = typename Containers::Vector< Real2, Device, Index, Allocator >::ConstViewType;
-   return Containers::Expressions::BinaryExpressionTemplate< ConstView1, ConstView2, Containers::Expressions::Max >( a.getConstView(), b.getConstView() );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator >
-auto
-max( const Containers::VectorView< Real1, Device, Index >& a, const Containers::Vector< Real2, Device, Index, Allocator >& b )
-{
-   using ConstView1 = typename Containers::Vector< Real1, Device, Index, Allocator >::ConstViewType;
-   using ConstView2 = typename Containers::Vector< Real2, Device, Index, Allocator >::ConstViewType;
-   return Containers::Expressions::BinaryExpressionTemplate< ConstView1, ConstView2, Containers::Expressions::Max >( a.getConstView(), b.getConstView() );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator >
-auto
-max( const Containers::Vector< Real1, Device, Index, Allocator >& a, const Containers::VectorView< Real2, Device, Index >& b )
-{
-   using ConstView1 = typename Containers::Vector< Real1, Device, Index, Allocator >::ConstViewType;
-   using ConstView2 = typename Containers::Vector< Real2, Device, Index, Allocator >::ConstViewType;
-   return Containers::Expressions::BinaryExpressionTemplate< ConstView1, ConstView2, Containers::Expressions::Max >( a.getConstView(), b.getConstView() );
-}
-
-////
-// Dot product - the same as scalar product, just for convenience
-#ifdef DOXYGEN_ONLY
-/**
- * \brief Computes scalar product of vector and vector expression. Equivalent to \ref TNL::Containers::operator,.
- * 
- * @param a input vector
- * @param b input vector expression
- * @return scalar product of vector and vector expression
- */
-template< typename ET1, typename ET2 >
-auto
-dot( const ET1& a, const ET2& b ) {}
-#else
-
-template< typename Real, typename Device, typename Index, typename Allocator, typename ET,
-          typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > >
-auto
-dot( const Containers::Vector< Real, Device, Index, Allocator >& a, const ET& b )
-{
-   return (a, b);
-}
-
-template< typename ET, typename Real, typename Device, typename Index, typename Allocator,
-          typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > >
-auto
-dot( const ET& a, const Containers::Vector< Real, Device, Index, Allocator >& b )
-{
-   return (a, b);
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator >
-auto
-dot( const Containers::Vector< Real1, Device, Index, Allocator >& a, const Containers::Vector< Real2, Device, Index, Allocator >& b )
-{
-   return (a, b);
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator >
-auto
-dot( const Containers::VectorView< Real1, Device, Index >& a, const Containers::Vector< Real2, Device, Index, Allocator >& b )
-{
-   return (a, b);
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator >
-auto
-dot( const Containers::Vector< Real1, Device, Index, Allocator >& a, const Containers::VectorView< Real2, Device, Index >& b )
-{
-   return (a, b);
-}
-#endif // DOXYGEN_ONLY
-
-
-////
-// Abs
-template< typename Real, typename Device, typename Index, typename Allocator >
-auto
-abs( const Containers::Vector< Real, Device, Index, Allocator >& a )
-{
-   using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType;
-   return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Abs >( a.getConstView() );
-}
-
-////
-// Power
-template< typename Real, typename Device, typename Index, typename Allocator, typename ExpType >
-auto
-pow( const Containers::Vector< Real, Device, Index, Allocator >& a, const ExpType& exp )
-{
-   using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType;
-   return Containers::Expressions::BinaryExpressionTemplate< ConstView, ExpType, Containers::Expressions::Pow >( a.getConstView(), exp );
-}
-
-////
-// Exp
-template< typename Real, typename Device, typename Index, typename Allocator >
-auto
-exp( const Containers::Vector< Real, Device, Index, Allocator >& a )
-{
-   using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType;
-   return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Exp >( a.getConstView() );
-}
-
-////
-// Sqrt
-template< typename Real, typename Device, typename Index, typename Allocator >
-auto
-sqrt( const Containers::Vector< Real, Device, Index, Allocator >& a )
-{
-   using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType;
-   return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Sqrt >( a.getConstView() );
-}
-
-////
-// Cbrt
-template< typename Real, typename Device, typename Index, typename Allocator >
-auto
-cbrt( const Containers::Vector< Real, Device, Index, Allocator >& a )
-{
-   using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType;
-   return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Cbrt >( a.getConstView() );
-}
-
-////
-// Log
-template< typename Real, typename Device, typename Index, typename Allocator >
-auto
-log( const Containers::Vector< Real, Device, Index, Allocator >& a )
-{
-   using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType;
-   return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Log >( a.getConstView() );
-}
-
-////
-// Log10
-template< typename Real, typename Device, typename Index, typename Allocator >
-auto
-log10( const Containers::Vector< Real, Device, Index, Allocator >& a )
-{
-   using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType;
-   return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Log10 >( a.getConstView() );
-}
-
-////
-// Log2
-template< typename Real, typename Device, typename Index, typename Allocator >
-auto
-log2( const Containers::Vector< Real, Device, Index, Allocator >& a )
-{
-   using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType;
-   return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Log2 >( a.getConstView() );
-}
-
-////
-// Sine
-template< typename Real, typename Device, typename Index, typename Allocator >
-auto
-sin( const Containers::Vector< Real, Device, Index, Allocator >& a )
-{
-   using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType;
-   return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Sin >( a.getConstView() );
-}
-
-////
-// Cosine
-template< typename Real, typename Device, typename Index, typename Allocator >
-auto
-cos( const Containers::Vector< Real, Device, Index, Allocator >& a )
-{
-   using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType;
-   return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Cos >( a.getConstView() );
-}
-
-////
-// Tangent
-template< typename Real, typename Device, typename Index, typename Allocator >
-auto
-tan( const Containers::Vector< Real, Device, Index, Allocator >& a )
-{
-   using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType;
-   return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Tan >( a.getConstView() );
-}
-
-////
-// Asin
-template< typename Real, typename Device, typename Index, typename Allocator >
-auto
-asin( const Containers::Vector< Real, Device, Index, Allocator >& a )
-{
-   using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType;
-   return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Asin >( a.getConstView() );
-}
-
-////
-// Acos
-template< typename Real, typename Device, typename Index, typename Allocator >
-auto
-acos( const Containers::Vector< Real, Device, Index, Allocator >& a )
-{
-   using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType;
-   return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Acos >( a.getConstView() );
-}
-
-////
-// Atan
-template< typename Real, typename Device, typename Index, typename Allocator >
-auto
-atan( const Containers::Vector< Real, Device, Index, Allocator >& a )
-{
-   using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType;
-   return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Atan >( a.getConstView() );
-}
-
-////
-// Sinh
-template< typename Real, typename Device, typename Index, typename Allocator >
-auto
-sinh( const Containers::Vector< Real, Device, Index, Allocator >& a )
-{
-   using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType;
-   return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Sinh >( a.getConstView() );
-}
-
-////
-// Cosh
-template< typename Real, typename Device, typename Index, typename Allocator >
-auto
-cosh( const Containers::Vector< Real, Device, Index, Allocator >& a )
-{
-   using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType;
-   return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Cosh >( a.getConstView() );
-}
-
-////
-// Tanh
-template< typename Real, typename Device, typename Index, typename Allocator >
-auto
-tanh( const Containers::Vector< Real, Device, Index, Allocator >& a )
-{
-   using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType;
-   return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Tanh >( a.getConstView() );
-}
-
-////
-// Asinh
-template< typename Real, typename Device, typename Index, typename Allocator >
-auto
-asinh( const Containers::Vector< Real, Device, Index, Allocator >& a )
-{
-   using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType;
-   return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Asinh >( a.getConstView() );
-}
-
-////
-// Acosh
-template< typename Real, typename Device, typename Index, typename Allocator >
-auto
-acosh( const Containers::Vector< Real, Device, Index, Allocator >& a )
-{
-   using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType;
-   return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Acosh >( a.getConstView() );
-}
-
-////
-// Atanh
-template< typename Real, typename Device, typename Index, typename Allocator >
-auto
-atanh( const Containers::Vector< Real, Device, Index, Allocator >& a )
-{
-   using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType;
-   return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Atanh >( a.getConstView() );
-}
-
-////
-// Floor
-template< typename Real, typename Device, typename Index, typename Allocator >
-auto
-floor( const Containers::Vector< Real, Device, Index, Allocator >& a )
-{
-   using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType;
-   return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Floor >( a.getConstView() );
-}
-
-////
-// Ceil
-template< typename Real, typename Device, typename Index, typename Allocator >
-auto
-ceil( const Containers::Vector< Real, Device, Index, Allocator >& a )
-{
-   using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType;
-   return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Ceil >( a.getConstView() );
-}
-
-////
-// Sign
-template< typename Real, typename Device, typename Index, typename Allocator >
-auto
-sign( const Containers::Vector< Real, Device, Index, Allocator >& a )
-{
-   using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType;
-   return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Sign >( a.getConstView() );
-}
-
-////
-// Cast
-template< typename ResultType, typename Real, typename Device, typename Index, typename Allocator,
-          // workaround: templated type alias cannot be declared at block level
-          template<typename> class Operation = Containers::Expressions::Cast< ResultType >::template Operation >
-auto
-cast( const Containers::Vector< Real, Device, Index, Allocator >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< decltype(a.getConstView()), Operation >( a.getConstView() );
-}
-
-////
-// Vertical operations - min
-template< typename Real,
-          typename Device,
-          typename Index, typename Allocator >
-Real
-min( const Containers::Vector< Real, Device, Index, Allocator >& a )
-{
-   return Containers::Expressions::ExpressionMin( a.getConstView() );
-}
-
-template< typename Real,
-          typename Device,
-          typename Index, typename Allocator >
-std::pair< Index, std::decay_t< Real > >
-argMin( const Containers::Vector< Real, Device, Index, Allocator >& a )
-{
-   return Containers::Expressions::ExpressionArgMin( a.getConstView() );
-}
-
-template< typename Real,
-          typename Device,
-          typename Index, typename Allocator >
-Real
-max( const Containers::Vector< Real, Device, Index, Allocator >& a )
-{
-   return Containers::Expressions::ExpressionMax( a.getConstView() );
-}
-
-template< typename Real,
-          typename Device,
-          typename Index, typename Allocator >
-std::pair< Index, std::decay_t< Real > >
-argMax( const Containers::Vector< Real, Device, Index, Allocator >& a )
-{
-   return Containers::Expressions::ExpressionArgMax( a.getConstView() );
-}
-
-/**
- * \brief Computes sum of all vector elements.
- * 
- * @param a input vector
- * @return sum of all vector elements
- */
-template< typename Real,
-          typename Device,
-          typename Index, typename Allocator >
-auto
-sum( const Containers::Vector< Real, Device, Index, Allocator >& a )
-{
-   return Containers::Expressions::ExpressionSum( a.getConstView() );
-}
-
-/**
- * \brief Computes maximum norm of a vector.
- * \anchor TNL__maxNorm
- * 
- * @param a input vector
- * @return  maximum norm
- */
-template< typename Real,
-          typename Device,
-          typename Index, typename Allocator >
-auto
-maxNorm( const Containers::Vector< Real, Device, Index, Allocator >& a )
-{
-   return max( abs( a ) );
-}
-
-template< typename Real,
-          typename Device,
-          typename Index, typename Allocator >
-auto
-l1Norm( const Containers::Vector< Real, Device, Index, Allocator >& a )
-{
-   return Containers::Expressions::ExpressionL1Norm( a.getConstView() );
-}
-
-template< typename Real,
-          typename Device,
-          typename Index, typename Allocator >
-auto
-l2Norm( const Containers::Vector< Real, Device, Index, Allocator >& a )
-{
-   return TNL::sqrt( Containers::Expressions::ExpressionL2Norm( a.getConstView() ) );
-}
-
-template< typename Real,
-          typename Device,
-          typename Index, typename Allocator,
-          typename Real2 >
-auto
-lpNorm( const Containers::Vector< Real, Device, Index, Allocator >& a, const Real2& p )
-// since (1.0 / p) has type double, TNL::pow returns double
--> double
-{
-   if( p == 1.0 )
-      return l1Norm( a );
-   if( p == 2.0 )
-      return l2Norm( a );
-   return TNL::pow( Containers::Expressions::ExpressionLpNorm( a.getConstView(), p ), 1.0 / p );
-}
-
-/**
- * \brief Computes product of all vector elements.
- * @param a
- * @return 
- */
-template< typename Real,
-          typename Device,
-          typename Index, typename Allocator >
-auto
-product( const Containers::Vector< Real, Device, Index, Allocator >& a )
-{
-   return Containers::Expressions::ExpressionProduct( a.getConstView() );
-}
-
-template< typename Real,
-          typename Device,
-          typename Index, typename Allocator >
-auto
-logicalOr( const Containers::Vector< Real, Device, Index, Allocator >& a )
-{
-   return Containers::Expressions::ExpressionLogicalOr( a.getConstView() );
-}
-
-template< typename Real,
-          typename Device,
-          typename Index, typename Allocator >
-auto
-binaryOr( const Containers::Vector< Real, Device, Index, Allocator >& a )
-{
-   return Containers::Expressions::ExpressionBinaryOr( a.getConstView() );
-}
-
-template< typename Real,
-          typename Device,
-          typename Index, typename Allocator >
-auto
-logicalAnd( const Containers::Vector< Real, Device, Index, Allocator >& a )
-{
-   return Containers::Expressions::ExpressionLogicalAnd( a.getConstView() );
-}
-
-template< typename Real,
-          typename Device,
-          typename Index, typename Allocator >
-auto
-binaryAnd( const Containers::Vector< Real, Device, Index, Allocator >& a )
-{
-   return Containers::Expressions::ExpressionBinaryAnd( a.getConstView() );
-}
-
-} // namespace TNL
diff --git a/src/TNL/Containers/VectorView.h b/src/TNL/Containers/VectorView.h
index 1a144ea5cde79951ee059f386859322eba18cf57..4c5262d30f4ec904d176da1a33313ad94d64cd0f 100644
--- a/src/TNL/Containers/VectorView.h
+++ b/src/TNL/Containers/VectorView.h
@@ -138,7 +138,7 @@ public:
     */
    template< typename VectorExpression,
              typename...,
-             typename = std::enable_if_t< Expressions::IsExpressionTemplate< VectorExpression >::value > >
+             typename = std::enable_if_t< Expressions::HasEnabledExpressionTemplates< VectorExpression >::value && ! IsArrayType< VectorExpression >::value > >
    VectorView& operator=( const VectorExpression& expression );
 
    /**
@@ -294,8 +294,15 @@ public:
    void segmentedScan( const VectorExpression& expression, FlagsArray& flags, IndexType begin = 0, IndexType end = 0 );
 };
 
+// Enable expression templates for VectorView
+namespace Expressions {
+   template< typename Real, typename Device, typename Index >
+   struct HasEnabledExpressionTemplates< VectorView< Real, Device, Index > >
+   : std::true_type
+   {};
+} // namespace Expressions
+
 } // namespace Containers
 } // namespace TNL
 
 #include <TNL/Containers/VectorView.hpp>
-#include <TNL/Containers/VectorViewExpressions.h>
diff --git a/src/TNL/Containers/VectorViewExpressions.h b/src/TNL/Containers/VectorViewExpressions.h
deleted file mode 100644
index 6168b54066d74ac5151e40ed1100116353759556..0000000000000000000000000000000000000000
--- a/src/TNL/Containers/VectorViewExpressions.h
+++ /dev/null
@@ -1,740 +0,0 @@
-/***************************************************************************
-                          VectorViewExpressions.h  -  description
-                             -------------------
-    begin                : Apr 27, 2019
-    copyright            : (C) 2019 by Tomas Oberhuber et al.
-    email                : tomas.oberhuber@fjfi.cvut.cz
- ***************************************************************************/
-
-/* See Copyright Notice in tnl/Copyright */
-
-#pragma once
-#ifndef DOXYGEN_ONLY
-
-#include <TNL/Containers/Expressions/ExpressionTemplates.h>
-
-#include "VectorView.h"
-
-namespace TNL {
-namespace Containers {
-
-////
-// Addition
-template< typename Real, typename Device, typename Index, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-auto
-operator+( const VectorView< Real, Device, Index >& a, const ET& b )
-{
-   return Expressions::BinaryExpressionTemplate< VectorView< Real, Device, Index >, ET, Expressions::Addition >( a, b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-auto
-operator+( const ET& a, const VectorView< Real, Device, Index >& b )
-{
-   return Expressions::BinaryExpressionTemplate< ET, VectorView< Real, Device, Index >, Expressions::Addition >( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index >
-auto
-operator+( const VectorView< Real1, Device, Index >& a, const VectorView< Real2, Device, Index >& b )
-{
-   return Expressions::BinaryExpressionTemplate< VectorView< Real1, Device, Index >, VectorView< Real2, Device, Index >, Expressions::Addition >( a, b );
-}
-
-////
-// Subtraction
-template< typename Real, typename Device, typename Index, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-auto
-operator-( const VectorView< Real, Device, Index >& a, const ET& b )
-{
-   return Expressions::BinaryExpressionTemplate< VectorView< Real, Device, Index >, ET, Expressions::Subtraction >( a, b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-auto
-operator-( const ET& a, const VectorView< Real, Device, Index >& b )
-{
-   return Expressions::BinaryExpressionTemplate< ET, VectorView< Real, Device, Index >, Expressions::Subtraction >( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index >
-auto
-operator-( const VectorView< Real1, Device, Index >& a, const VectorView< Real2, Device, Index >& b )
-{
-   return Expressions::BinaryExpressionTemplate< VectorView< Real1, Device, Index >, VectorView< Real2, Device, Index >, Expressions::Subtraction >( a, b );
-}
-
-////
-// Multiplication
-template< typename Real, typename Device, typename Index, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-auto
-operator*( const VectorView< Real, Device, Index >& a, const ET& b )
-{
-   return Expressions::BinaryExpressionTemplate< VectorView< Real, Device, Index >, ET, Expressions::Multiplication >( a, b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-auto
-operator*( const ET& a, const VectorView< Real, Device, Index >& b )
-{
-   return Expressions::BinaryExpressionTemplate< ET, VectorView< Real, Device, Index >, Expressions::Multiplication >( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index >
-auto
-operator*( const VectorView< Real1, Device, Index >& a, const VectorView< Real2, Device, Index >& b )
-{
-   return Expressions::BinaryExpressionTemplate< VectorView< Real1, Device, Index >, VectorView< Real2, Device, Index >, Expressions::Multiplication >( a, b );
-}
-
-////
-// Division
-template< typename Real, typename Device, typename Index, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-auto
-operator/( const VectorView< Real, Device, Index >& a, const ET& b )
-{
-   return Expressions::BinaryExpressionTemplate< VectorView< Real, Device, Index >, ET, Expressions::Division >( a, b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-auto
-operator/( const ET& a, const VectorView< Real, Device, Index >& b )
-{
-   return Expressions::BinaryExpressionTemplate< ET, VectorView< Real, Device, Index >, Expressions::Division >( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index >
-auto
-operator/( const VectorView< Real1, Device, Index >& a, const VectorView< Real2, Device, Index >& b )
-{
-   return Expressions::BinaryExpressionTemplate< VectorView< Real1, Device, Index >, VectorView< Real2, Device, Index >, Expressions::Division >( a, b );
-}
-
-////
-// Comparison operations - operator ==
-template< typename Real, typename Device, typename Index, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator==( const VectorView< Real, Device, Index >& a, const ET& b )
-{
-   return Expressions::Comparison< VectorView< Real, Device, Index >, ET >::EQ( a, b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator==( const ET& a, const VectorView< Real, Device, Index >& b )
-{
-   return Expressions::Comparison< ET, VectorView< Real, Device, Index > >::EQ( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device1, typename Device2, typename Index >
-bool
-operator==( const VectorView< Real1, Device1, Index >& a, const VectorView< Real2, Device2, Index >& b )
-{
-   return Expressions::Comparison< VectorView< Real1, Device1, Index >, VectorView< Real2, Device2, Index > >::EQ( a, b );
-}
-
-////
-// Comparison operations - operator !=
-template< typename Real, typename Device, typename Index, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator!=( const VectorView< Real, Device, Index >& a, const ET& b )
-{
-   return Expressions::Comparison< VectorView< Real, Device, Index >, ET >::NE( a, b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator!=( const ET& a, const VectorView< Real, Device, Index >& b )
-{
-   return Expressions::Comparison< ET, VectorView< Real, Device, Index > >::NE( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device1, typename Device2, typename Index >
-bool
-operator!=( const VectorView< Real1, Device1, Index >& a, const VectorView< Real2, Device2, Index >& b )
-{
-   return ! (a == b);
-}
-
-////
-// Comparison operations - operator <
-template< typename Real, typename Device, typename Index, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator<( const VectorView< Real, Device, Index >& a, const ET& b )
-{
-   return Expressions::Comparison< VectorView< Real, Device, Index >, ET >::LT( a, b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator<( const ET& a, const VectorView< Real, Device, Index >& b )
-{
-   return Expressions::Comparison< ET, VectorView< Real, Device, Index > >::LT( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index >
-bool
-operator<( const VectorView< Real1, Device, Index >& a, const VectorView< Real2, Device, Index >& b )
-{
-   return Expressions::Comparison< VectorView< Real1, Device, Index >, VectorView< Real2, Device, Index > >::LT( a, b );
-}
-
-////
-// Comparison operations - operator <=
-template< typename Real, typename Device, typename Index, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator<=( const VectorView< Real, Device, Index >& a, const ET& b )
-{
-   return Expressions::Comparison< VectorView< Real, Device, Index >, ET >::LE( a, b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator<=( const ET& a, const VectorView< Real, Device, Index >& b )
-{
-   return Expressions::Comparison< ET, VectorView< Real, Device, Index > >::LE( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index >
-bool
-operator<=( const VectorView< Real1, Device, Index >& a, const VectorView< Real2, Device, Index >& b )
-{
-   return Expressions::Comparison< VectorView< Real1, Device, Index >, VectorView< Real2, Device, Index > >::LE( a, b );
-}
-
-////
-// Comparison operations - operator >
-template< typename Real, typename Device, typename Index, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator>( const VectorView< Real, Device, Index >& a, const ET& b )
-{
-   return Expressions::Comparison< VectorView< Real, Device, Index >, ET >::GT( a, b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator>( const ET& a, const VectorView< Real, Device, Index >& b )
-{
-   return Expressions::Comparison< ET, VectorView< Real, Device, Index > >::GT( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index >
-bool
-operator>( const VectorView< Real1, Device, Index >& a, const VectorView< Real2, Device, Index >& b )
-{
-   return Expressions::Comparison< VectorView< Real1, Device, Index >, VectorView< Real2, Device, Index > >::GT( a, b );
-}
-
-////
-// Comparison operations - operator >=
-template< typename Real, typename Device, typename Index, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator>=( const VectorView< Real, Device, Index >& a, const ET& b )
-{
-   return Expressions::Comparison< VectorView< Real, Device, Index >, ET >::GE( a, b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-bool
-operator>=( const ET& a, const VectorView< Real, Device, Index >& b )
-{
-   return Expressions::Comparison< ET, VectorView< Real, Device, Index > >::GE( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index >
-bool
-operator>=( const VectorView< Real1, Device, Index >& a, const VectorView< Real2, Device, Index >& b )
-{
-   return Expressions::Comparison< VectorView< Real1, Device, Index >, VectorView< Real2, Device, Index > >::GE( a, b );
-}
-
-////
-// Minus
-template< typename Real, typename Device, typename Index >
-auto
-operator-( const VectorView< Real, Device, Index >& a )
-{
-   return Expressions::UnaryExpressionTemplate< VectorView< Real, Device, Index >, Expressions::Minus >( a );
-}
-
-////
-// Scalar product
-template< typename Real, typename Device, typename Index, typename ET,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-auto
-operator,( const VectorView< Real, Device, Index >& a, const ET& b )
-{
-   return Expressions::ExpressionSum( a * b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index,
-          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
-auto
-operator,( const ET& a, const VectorView< Real, Device, Index >& b )
-{
-   return Expressions::ExpressionSum( a * b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index >
-auto
-operator,( const VectorView< Real1, Device, Index >& a, const VectorView< Real2, Device, Index >& b )
-{
-   return Expressions::ExpressionSum( a * b );
-}
-
-} // namespace Containers
-
-////
-// All functions are supposed to be in namespace TNL
-
-////
-// Min
-template< typename Real, typename Device, typename Index, typename ET,
-          typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > >
-auto
-min( const Containers::VectorView< Real, Device, Index >& a, const ET& b )
-{
-   return Containers::Expressions::BinaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, ET, Containers::Expressions::Min >( a, b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index,
-          typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > >
-auto
-min( const ET& a, const Containers::VectorView< Real, Device, Index >& b )
-{
-   return Containers::Expressions::BinaryExpressionTemplate< ET, Containers::VectorView< Real, Device, Index >, Containers::Expressions::Min >( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index >
-auto
-min( const Containers::VectorView< Real1, Device, Index >& a, const Containers::VectorView< Real2, Device, Index >& b )
-{
-   return Containers::Expressions::BinaryExpressionTemplate< Containers::VectorView< Real1, Device, Index >, Containers::VectorView< Real2, Device, Index >, Containers::Expressions::Min >( a, b );
-}
-
-////
-// Max
-template< typename Real, typename Device, typename Index, typename ET,
-          typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > >
-auto
-max( const Containers::VectorView< Real, Device, Index >& a, const ET& b )
-{
-   return Containers::Expressions::BinaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, ET, Containers::Expressions::Max >( a, b );
-}
-
-template< typename ET, typename Real, typename Device, typename Index,
-          typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > >
-auto
-max( const ET& a, const Containers::VectorView< Real, Device, Index >& b )
-{
-   return Containers::Expressions::BinaryExpressionTemplate< ET, Containers::VectorView< Real, Device, Index >, Containers::Expressions::Max >( a, b );
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index >
-auto
-max( const Containers::VectorView< Real1, Device, Index >& a, const Containers::VectorView< Real2, Device, Index >& b )
-{
-   return Containers::Expressions::BinaryExpressionTemplate< Containers::VectorView< Real1, Device, Index >, Containers::VectorView< Real2, Device, Index >, Containers::Expressions::Max >( a, b );
-}
-
-////
-// Dot product - the same as scalar product, just for convenience
-template< typename Real, typename Device, typename Index, typename ET,
-          typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > >
-auto
-dot( const Containers::VectorView< Real, Device, Index >& a, const ET& b )
-{
-   return (a, b);
-}
-
-template< typename ET, typename Real, typename Device, typename Index,
-          typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > >
-auto
-dot( const ET& a, const Containers::VectorView< Real, Device, Index >& b )
-{
-   return (a, b);
-}
-
-template< typename Real1, typename Real2, typename Device, typename Index1, typename Index2 >
-auto
-dot( const Containers::VectorView< Real1, Device, Index1 >& a, const Containers::VectorView< Real2, Device, Index2 >& b )
-{
-   return (a, b);
-}
-
-
-////
-// Abs
-template< typename Real, typename Device, typename Index >
-auto
-abs( const Containers::VectorView< Real, Device, Index >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Abs >( a );
-}
-
-////
-// Power
-template< typename Real, typename Device, typename Index, typename ExpType >
-auto
-pow( const Containers::VectorView< Real, Device, Index >& a, const ExpType& exp )
-{
-   return Containers::Expressions::BinaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, ExpType, Containers::Expressions::Pow >( a, exp );
-}
-
-////
-// Exp
-template< typename Real, typename Device, typename Index >
-auto
-exp( const Containers::VectorView< Real, Device, Index >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Exp >( a );
-}
-
-////
-// Sqrt
-template< typename Real, typename Device, typename Index >
-auto
-sqrt( const Containers::VectorView< Real, Device, Index >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Sqrt >( a );
-}
-
-////
-// Cbrt
-template< typename Real, typename Device, typename Index >
-auto
-cbrt( const Containers::VectorView< Real, Device, Index >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Cbrt >( a );
-}
-
-////
-// Log
-template< typename Real, typename Device, typename Index >
-auto
-log( const Containers::VectorView< Real, Device, Index >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Log >( a );
-}
-
-////
-// Log10
-template< typename Real, typename Device, typename Index >
-auto
-log10( const Containers::VectorView< Real, Device, Index >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Log10 >( a );
-}
-
-////
-// Log2
-template< typename Real, typename Device, typename Index >
-auto
-log2( const Containers::VectorView< Real, Device, Index >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Log2 >( a );
-}
-
-////
-// Sine
-template< typename Real, typename Device, typename Index >
-auto
-sin( const Containers::VectorView< Real, Device, Index >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Sin >( a );
-}
-
-////
-// Cosine
-template< typename Real, typename Device, typename Index >
-auto
-cos( const Containers::VectorView< Real, Device, Index >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Cos >( a );
-}
-
-////
-// Tangent
-template< typename Real, typename Device, typename Index >
-auto
-tan( const Containers::VectorView< Real, Device, Index >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Tan >( a );
-}
-
-////
-// Asin
-template< typename Real, typename Device, typename Index >
-auto
-asin( const Containers::VectorView< Real, Device, Index >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Asin >( a );
-}
-
-////
-// Acos
-template< typename Real, typename Device, typename Index >
-auto
-acos( const Containers::VectorView< Real, Device, Index >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Acos >( a );
-}
-
-////
-// Atan
-template< typename Real, typename Device, typename Index >
-auto
-atan( const Containers::VectorView< Real, Device, Index >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Atan >( a );
-}
-
-////
-// Sinh
-template< typename Real, typename Device, typename Index >
-auto
-sinh( const Containers::VectorView< Real, Device, Index >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Sinh >( a );
-}
-
-////
-// Cosh
-template< typename Real, typename Device, typename Index >
-auto
-cosh( const Containers::VectorView< Real, Device, Index >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Cosh >( a );
-}
-
-////
-// Tanh
-template< typename Real, typename Device, typename Index >
-auto
-tanh( const Containers::VectorView< Real, Device, Index >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Tanh >( a );
-}
-
-////
-// Asinh
-template< typename Real, typename Device, typename Index >
-auto
-asinh( const Containers::VectorView< Real, Device, Index >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Asinh >( a );
-}
-
-////
-// Acosh
-template< typename Real, typename Device, typename Index >
-auto
-acosh( const Containers::VectorView< Real, Device, Index >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Acosh >( a );
-}
-
-////
-// Atanh
-template< typename Real, typename Device, typename Index >
-auto
-atanh( const Containers::VectorView< Real, Device, Index >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Atanh >( a );
-}
-
-////
-// Floor
-template< typename Real, typename Device, typename Index >
-auto
-floor( const Containers::VectorView< Real, Device, Index >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Floor >( a );
-}
-
-////
-// Ceil
-template< typename Real, typename Device, typename Index >
-auto
-ceil( const Containers::VectorView< Real, Device, Index >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Ceil >( a );
-}
-
-////
-// Sign
-template< typename Real, typename Device, typename Index >
-auto
-sign( const Containers::VectorView< Real, Device, Index >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Sign >( a );
-}
-
-////
-// Cast
-template< typename ResultType, typename Real, typename Device, typename Index,
-          // workaround: templated type alias cannot be declared at block level
-          template<typename> class Operation = Containers::Expressions::Cast< ResultType >::template Operation >
-auto
-cast( const Containers::VectorView< Real, Device, Index >& a )
-{
-   return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Operation >( a );
-}
-
-////
-// Vertical operations - min
-template< typename Real,
-          typename Device,
-          typename Index >
-Real
-min( const Containers::VectorView< Real, Device, Index >& a )
-{
-   return Containers::Expressions::ExpressionMin( a );
-}
-
-template< typename Real,
-          typename Device,
-          typename Index >
-std::pair< Index, std::decay_t< Real > >
-argMin( const Containers::VectorView< Real, Device, Index >& a )
-{
-   return Containers::Expressions::ExpressionArgMin( a );
-}
-
-template< typename Real,
-          typename Device,
-          typename Index >
-Real
-max( const Containers::VectorView< Real, Device, Index >& a )
-{
-   return Containers::Expressions::ExpressionMax( a );
-}
-
-template< typename Real,
-          typename Device,
-          typename Index >
-std::pair< Index, std::decay_t< Real > >
-argMax( const Containers::VectorView< Real, Device, Index >& a )
-{
-   return Containers::Expressions::ExpressionArgMax( a );
-}
-
-template< typename Real,
-          typename Device,
-          typename Index >
-auto
-sum( const Containers::VectorView< Real, Device, Index >& a )
-{
-   return Containers::Expressions::ExpressionSum( a );
-}
-
-template< typename Real,
-          typename Device,
-          typename Index >
-auto
-maxNorm( const Containers::VectorView< Real, Device, Index >& a )
-{
-   return max( abs( a ) );
-}
-
-template< typename Real,
-          typename Device,
-          typename Index >
-auto
-l1Norm( const Containers::VectorView< Real, Device, Index >& a )
-{
-   return Containers::Expressions::ExpressionL1Norm( a );
-}
-
-template< typename Real,
-          typename Device,
-          typename Index >
-auto
-l2Norm( const Containers::VectorView< Real, Device, Index >& a )
-{
-   return TNL::sqrt( Containers::Expressions::ExpressionL2Norm( a ) );
-}
-
-template< typename Real,
-          typename Device,
-          typename Index,
-          typename Real2 >
-auto
-lpNorm( const Containers::VectorView< Real, Device, Index >& a, const Real2& p )
-// since (1.0 / p) has type double, TNL::pow returns double
--> double
-{
-   if( p == 1.0 )
-      return l1Norm( a );
-   if( p == 2.0 )
-      return l2Norm( a );
-   return TNL::pow( Containers::Expressions::ExpressionLpNorm( a, p ), 1.0 / p );
-}
-
-template< typename Real,
-          typename Device,
-          typename Index >
-auto
-product( const Containers::VectorView< Real, Device, Index >& a )
-{
-   return Containers::Expressions::ExpressionProduct( a );
-}
-
-template< typename Real,
-          typename Device,
-          typename Index >
-auto
-logicalOr( const Containers::VectorView< Real, Device, Index >& a )
-{
-   return Containers::Expressions::ExpressionLogicalOr( a );
-}
-
-template< typename Real,
-          typename Device,
-          typename Index >
-auto
-binaryOr( const Containers::VectorView< Real, Device, Index >& a )
-{
-   return Containers::Expressions::ExpressionBinaryOr( a );
-}
-
-template< typename Real,
-          typename Device,
-          typename Index >
-auto
-logicalAnd( const Containers::VectorView< Real, Device, Index >& a )
-{
-   return Containers::Expressions::ExpressionLogicalAnd( a );
-}
-
-template< typename Real,
-          typename Device,
-          typename Index >
-auto
-binaryAnd( const Containers::VectorView< Real, Device, Index >& a )
-{
-   return Containers::Expressions::ExpressionBinaryAnd( a );
-}
-
-} // namespace TNL
-#endif // DOXYGEN_ONLY
diff --git a/src/TNL/Containers/detail/StaticArrayAssignment.h b/src/TNL/Containers/detail/StaticArrayAssignment.h
index 9a8d7d3eeb7bdbcfd9814ad3754d4ba9131004b5..6ba6c8e02a1ab81388203cef969eca594bef29c6 100644
--- a/src/TNL/Containers/detail/StaticArrayAssignment.h
+++ b/src/TNL/Containers/detail/StaticArrayAssignment.h
@@ -21,7 +21,7 @@ struct AssignArrayFunctor
 {
    template< typename LeftValue, typename RightValue >
    __cuda_callable__
-   void operator()( int i, LeftValue& data, const RightValue& v ) const
+   void operator()( int i, LeftValue* data, const RightValue* v ) const
    {
       data[ i ] = v[ i ];
    }
@@ -31,7 +31,7 @@ struct AssignValueFunctor
 {
    template< typename LeftValue, typename RightValue >
    __cuda_callable__
-   void operator()( int i, LeftValue& data, const RightValue& v ) const
+   void operator()( int i, LeftValue* data, const RightValue& v ) const
    {
       data[ i ] = v;
    }
@@ -53,7 +53,7 @@ struct StaticArrayAssignment< StaticArray, T, true >
    static void assign( StaticArray& a, const T& v )
    {
       static_assert( StaticArray::getSize() == T::getSize(), "Cannot assign static arrays with different size." );
-      Algorithms::StaticFor< 0, StaticArray::getSize() >::exec( AssignArrayFunctor{}, a.getData(), v );
+      Algorithms::StaticFor< 0, StaticArray::getSize() >::exec( AssignArrayFunctor{}, a.getData(), v.getData() );
    }
 };
 
@@ -68,7 +68,7 @@ struct StaticArrayAssignment< StaticArray, T, false >
    __cuda_callable__
    static void assign( StaticArray& a, const T& v )
    {
-      Algorithms::StaticFor< 0, StaticArray::getSize() >::exec( AssignValueFunctor{}, a, v );
+      Algorithms::StaticFor< 0, StaticArray::getSize() >::exec( AssignValueFunctor{}, a.getData(), v );
    }
 };
 
diff --git a/src/TNL/Math.h b/src/TNL/Math.h
index 321cc7ce39e0d0beb8c3c3c2a5ab3ac7bbfddbdd..01fd527cb452d810f624e3f9f94e21fac9302889 100644
--- a/src/TNL/Math.h
+++ b/src/TNL/Math.h
@@ -79,7 +79,7 @@ ResultType max( const T1& a, const T2& b )
  * \brief This function returns absolute value of given number \e n.
  */
 template< class T,
-          std::enable_if_t< ! std::is_unsigned<T>::value, bool > = true >
+          std::enable_if_t< ! std::is_unsigned<T>::value && ! std::is_class<T>::value, bool > = true >
 __cuda_callable__ inline
 T abs( const T& n )
 {
@@ -147,7 +147,9 @@ ResultType argAbsMax( const T1& a, const T2& b )
 /**
  * \brief This function returns the result of \e base to the power of \e exp.
  */
-template< typename T1, typename T2, typename ResultType = typename std::common_type< T1, T2 >::type >
+template< typename T1, typename T2, typename ResultType = typename std::common_type< T1, T2 >::type,
+          // enable_if is necessary to avoid ambiguity in vector expressions
+          std::enable_if_t< ! std::is_class<T1>::value && ! std::is_class<T2>::value, bool > = true >
 __cuda_callable__ inline
 ResultType pow( const T1& base, const T2& exp )
 {
@@ -458,7 +460,9 @@ void swap( Type& a, Type& b )
  * It extracts the sign of the number \e a. In other words, the signum function projects
  * negative numbers to value -1, positive numbers to value 1 and zero to value 0.
  */
-template< class T >
+template< class T,
+          // enable_if is necessary to avoid ambiguity in vector expressions
+          std::enable_if_t< ! HasSubscriptOperator<T>::value, bool > = true >
 __cuda_callable__
 T sign( const T& a )
 {
diff --git a/src/TNL/Matrices/MatrixOperations.h b/src/TNL/Matrices/MatrixOperations.h
index 354b0a9e19d89ddb3cb457ce578752c8f1f513b0..d37258d615719ae7039a86a885f8ad839d69f4e8 100644
--- a/src/TNL/Matrices/MatrixOperations.h
+++ b/src/TNL/Matrices/MatrixOperations.h
@@ -46,13 +46,13 @@ public:
    template< typename RealType,
              typename IndexType >
    static void
-   gemv( const IndexType& m,
-         const IndexType& n,
-         const RealType& alpha,
+   gemv( const IndexType m,
+         const IndexType n,
+         const RealType alpha,
          const RealType* A,
-         const IndexType& lda,
+         const IndexType lda,
          const RealType* x,
-         const RealType& beta,
+         const RealType beta,
          RealType* y )
    {
       TNL_ASSERT_GT( m, 0, "m must be positive" );
@@ -164,16 +164,16 @@ public:
    template< typename RealType,
              typename IndexType >
    static void
-   geam( const IndexType& m,
-         const IndexType& n,
-         const RealType& alpha,
+   geam( const IndexType m,
+         const IndexType n,
+         const RealType alpha,
          const RealType* A,
-         const IndexType& lda,
-         const RealType& beta,
+         const IndexType lda,
+         const RealType beta,
          const RealType* B,
-         const IndexType& ldb,
+         const IndexType ldb,
          RealType* C,
-         const IndexType& ldc )
+         const IndexType ldc )
    {
       TNL_ASSERT_GT( m, 0, "m must be positive" );
       TNL_ASSERT_GT( n, 0, "n must be positive" );
@@ -326,13 +326,13 @@ public:
    template< typename RealType,
              typename IndexType >
    static void
-   gemv( const IndexType& m,
-         const IndexType& n,
-         const RealType& alpha,
+   gemv( const IndexType m,
+         const IndexType n,
+         const RealType alpha,
          const RealType* A,
-         const IndexType& lda,
+         const IndexType lda,
          const RealType* x,
-         const RealType& beta,
+         const RealType beta,
          RealType* y )
    {
       TNL_ASSERT( m <= lda, );
@@ -375,16 +375,16 @@ public:
    template< typename RealType,
              typename IndexType >
    static void
-   geam( const IndexType& m,
-         const IndexType& n,
-         const RealType& alpha,
+   geam( const IndexType m,
+         const IndexType n,
+         const RealType alpha,
          const RealType* A,
-         const IndexType& lda,
-         const RealType& beta,
+         const IndexType lda,
+         const RealType beta,
          const RealType* B,
-         const IndexType& ldb,
+         const IndexType ldb,
          RealType* C,
-         const IndexType& ldc )
+         const IndexType ldc )
    {
       TNL_ASSERT_GT( m, 0, "m must be positive" );
       TNL_ASSERT_GT( n, 0, "n must be positive" );
diff --git a/src/TNL/Meshes/Geometry/getEntityMeasure.h b/src/TNL/Meshes/Geometry/getEntityMeasure.h
index a3381ed96b1e72ddc2f0ccf25bbbdccd7e71739a..070c28c583a916a789e49166ea90d10eadc9bd63 100644
--- a/src/TNL/Meshes/Geometry/getEntityMeasure.h
+++ b/src/TNL/Meshes/Geometry/getEntityMeasure.h
@@ -116,8 +116,8 @@ getEntityMeasure( const Mesh< MeshConfig, Device > & mesh,
     const auto& v1 = mesh.template getEntity< 0 >( entity.template getSubentityIndex< 0 >( 1 ) );
     const auto& v2 = mesh.template getEntity< 0 >( entity.template getSubentityIndex< 0 >( 2 ) );
     using Point = decltype( v0.getPoint() );
-    Point p1 = v2.getPoint() - v0.getPoint();
-    Point p2 = v1.getPoint() - v0.getPoint();
+    const Point p1 = v2.getPoint() - v0.getPoint();
+    const Point p2 = v1.getPoint() - v0.getPoint();
     return getTriangleArea( p1, p2 );
 }
 
@@ -134,7 +134,10 @@ getEntityMeasure( const Mesh< MeshConfig, Device > & mesh,
     const auto& v1 = mesh.template getEntity< 0 >( entity.template getSubentityIndex< 0 >( 1 ) );
     const auto& v2 = mesh.template getEntity< 0 >( entity.template getSubentityIndex< 0 >( 2 ) );
     const auto& v3 = mesh.template getEntity< 0 >( entity.template getSubentityIndex< 0 >( 3 ) );
-    return getTriangleArea( v2.getPoint() - v0.getPoint(), v3.getPoint() - v1.getPoint() );
+    using Point = decltype( v0.getPoint() );
+    const Point p1 = v2.getPoint() - v0.getPoint();
+    const Point p2 = v3.getPoint() - v1.getPoint();
+    return getTriangleArea( p1, p2 );
 }
 
 template< typename VectorExpression >
diff --git a/src/TNL/Meshes/GridDetails/Grid1D.h b/src/TNL/Meshes/GridDetails/Grid1D.h
index 81811fe9005c44bb1239f06fe423f4d566c7c77c..67b6e78e8c7f0c3a243abc80dab2fe4d319ac8b1 100644
--- a/src/TNL/Meshes/GridDetails/Grid1D.h
+++ b/src/TNL/Meshes/GridDetails/Grid1D.h
@@ -180,16 +180,6 @@ class Grid< 1, Real, Device, Index > : public Object
     */
    __cuda_callable__
    inline RealType getSmallestSpaceStep() const;
-
-
-   template< typename GridFunction >
-   typename GridFunction::RealType getDifferenceAbsMax( const GridFunction& f1,
-                                                        const GridFunction& f2 ) const;
-
-   template< typename GridFunction >
-   typename GridFunction::RealType getDifferenceLpNorm( const GridFunction& f1,
-                                                        const GridFunction& f2,
-                                                        const typename GridFunction::RealType& p ) const;
    
    void setDistMesh(DistributedMeshType * distMesh);
    
diff --git a/src/TNL/Meshes/GridDetails/Grid1D_impl.h b/src/TNL/Meshes/GridDetails/Grid1D_impl.h
index 279ec9810184ea097212e45984183ad1ddc97e70..679b473f1cebdc9e95a515676aec7bbceeb13229 100644
--- a/src/TNL/Meshes/GridDetails/Grid1D_impl.h
+++ b/src/TNL/Meshes/GridDetails/Grid1D_impl.h
@@ -290,51 +290,6 @@ getSmallestSpaceStep() const
    return this->spaceSteps.x();
 }
 
-template< typename Real,
-          typename Device,
-          typename Index >
-   template< typename GridFunction >
-typename GridFunction::RealType
-Grid< 1, Real, Device, Index >::getDifferenceAbsMax( const GridFunction& f1,
-                                                        const GridFunction& f2 ) const
-{
-   typename GridFunction::RealType maxDiff( -1.0 );
-
-   Cell cell( *this );
-   for( cell.getCoordinates().x() = 0;
-        cell.getCoordinates().x() < getDimensions().x();
-        cell.getCoordinates().x()++ )
-   {
-      IndexType c = this->getEntityIndex( cell );
-      maxDiff = max( maxDiff, abs( f1[ c ] - f2[ c ] ) );
-   }
-   return maxDiff;
-}
-
-template< typename Real,
-          typename Device,
-          typename Index >
-   template< typename GridFunction >
-typename GridFunction::RealType
-Grid< 1, Real, Device, Index >::getDifferenceLpNorm( const GridFunction& f1,
-                                                        const GridFunction& f2,
-                                                        const typename GridFunction::RealType& p ) const
-{
-   typedef typename GridFunction::RealType FunctionRealType;
-   FunctionRealType lpNorm( 0.0 ), cellVolume( this->getSpaceSteps().x() );
-
-   Cell cell( *this );
-   for( cell.getCoordinates().x() = 0;
-        cell.getCoordinates().x() < getDimensions().x();
-        cell.getCoordinates().x()++ )
-   {
-      IndexType c = this->getEntityIndex( cell );
-      lpNorm += ::pow( abs( f1[ c ] - f2[ c ] ), p );
-   }
-   lpNorm *= cellVolume;
-   return ::pow( lpNorm, 1.0 / p );
-}
-
 template< typename Real,
           typename Device,
           typename Index >
diff --git a/src/TNL/Meshes/GridDetails/Grid2D.h b/src/TNL/Meshes/GridDetails/Grid2D.h
index b24be9ba29503f4f6b80f2c3ad0ada1097d89844..3d7335053b062baa7e92514acd1cb360b8bade00 100644
--- a/src/TNL/Meshes/GridDetails/Grid2D.h
+++ b/src/TNL/Meshes/GridDetails/Grid2D.h
@@ -174,22 +174,6 @@ class Grid< 2, Real, Device, Index > : public Object
    inline RealType getSmallestSpaceStep() const;
 
 
-   template< typename GridFunction >
-   typename GridFunction::RealType getAbsMax( const GridFunction& f ) const;
-
-   template< typename GridFunction >
-   typename GridFunction::RealType getLpNorm( const GridFunction& f,
-                                              const typename GridFunction::RealType& p ) const;
-
-   template< typename GridFunction >
-   typename GridFunction::RealType getDifferenceAbsMax( const GridFunction& f1,
-                                                        const GridFunction& f2 ) const;
-
-   template< typename GridFunction >
-   typename GridFunction::RealType getDifferenceLpNorm( const GridFunction& f1,
-                                                        const GridFunction& f2,
-                                                        const typename GridFunction::RealType& p ) const;
-   
    void setDistMesh(DistributedMeshType * distGrid);
    
    DistributedMeshType * getDistributedMesh() const;
diff --git a/src/TNL/Meshes/GridDetails/Grid2D_impl.h b/src/TNL/Meshes/GridDetails/Grid2D_impl.h
index 259181688c0566abdd3025bac1cbda1429a60d10..4f9f8fdd580f17a8e88c596127216e57e916bfee 100644
--- a/src/TNL/Meshes/GridDetails/Grid2D_impl.h
+++ b/src/TNL/Meshes/GridDetails/Grid2D_impl.h
@@ -348,76 +348,6 @@ Real Grid< 2, Real, Device, Index > :: getSmallestSpaceStep() const
    return min( this->spaceSteps.x(), this->spaceSteps.y() );
 }
 
-template< typename Real,
-          typename Device,
-          typename Index >
-   template< typename GridFunction >
-      typename GridFunction::RealType
-         Grid< 2, Real, Device, Index >::getAbsMax( const GridFunction& f ) const
-{
-   return f.absMax();
-}
-
-template< typename Real,
-          typename Device,
-          typename Index >
-   template< typename GridFunction >
-      typename GridFunction::RealType
-         Grid< 2, Real, Device, Index >::getLpNorm( const GridFunction& f1,
-                                                                 const typename GridFunction::RealType& p ) const
-{
-   typename GridFunction::RealType lpNorm( 0.0 );
-   Cell cell( *this );
-   for( cell.getCoordinates().y() = 0;
-        cell.getCoordinates().y() < getDimensions().y();
-        cell.getCoordinates().y()++ )
-      for( cell.getCoordinates().x() = 0;
-           cell.getCoordinates().x() < getDimensions().x();
-           cell.getCoordinates().x()++ )
-      {
-         IndexType c = this->getEntityIndex( cell );
-         lpNorm += ::pow( abs( f1[ c ] ), p );
-      }
-   lpNorm *= this->getSpaceSteps().x() * this->getSpaceSteps().y();
-   return ::pow( lpNorm, 1.0/p );
-}
-
-template< typename Real,
-          typename Device,
-          typename Index >
-   template< typename GridFunction >
-      typename GridFunction::RealType
-         Grid< 2, Real, Device, Index >::getDifferenceAbsMax( const GridFunction& f1,
-                                                              const GridFunction& f2 ) const
-{
-   return TNL::max( TNL::abs( f1.getData() - f2.getData() ) );
-}
-
-template< typename Real,
-          typename Device,
-          typename Index >
-   template< typename GridFunction >
-      typename GridFunction::RealType
-         Grid< 2, Real, Device, Index >::getDifferenceLpNorm( const GridFunction& f1,
-                                                                 const GridFunction& f2,
-                                                                 const typename GridFunction::RealType& p ) const
-{
-   typename GridFunction::RealType lpNorm( 0.0 );
-   Cell cell( *this );
-   for( cell.getCoordinates().y() = 0;
-        cell.getCoordinates().y() < getDimensions().y();
-        cell.getCoordinates().y()++ )
-      for( cell.getCoordinates().x() = 0;
-           cell.getCoordinates().x() < getDimensions().x();
-           cell.getCoordinates().x()++ )
-      {
-         IndexType c = this->getEntityIndex( cell );
-         lpNorm += ::pow( abs( f1[ c ] - f2[ c ] ), p );
-      }
-   lpNorm *= this->getSpaceSteps().x() * this->getSpaceSteps().y();
-   return ::pow( lpNorm, 1.0 / p );
-}
-
 template< typename Real,
           typename Device,
           typename Index >
diff --git a/src/TNL/Meshes/GridDetails/Grid3D.h b/src/TNL/Meshes/GridDetails/Grid3D.h
index 881fb0074bf642ca6fdcd1300df849c93d205792..7e3f0d5e86781d70a79bb7ef5ac83f19cd7404db 100644
--- a/src/TNL/Meshes/GridDetails/Grid3D.h
+++ b/src/TNL/Meshes/GridDetails/Grid3D.h
@@ -179,22 +179,6 @@ class Grid< 3, Real, Device, Index > : public Object
    __cuda_callable__
    RealType getSmallestSpaceStep() const;
 
-   template< typename GridFunction >
-   typename GridFunction::RealType getAbsMax( const GridFunction& f ) const;
-
-   template< typename GridFunction >
-   typename GridFunction::RealType getLpNorm( const GridFunction& f,
-                                              const typename GridFunction::RealType& p ) const;
-
-   template< typename GridFunction >
-   typename GridFunction::RealType getDifferenceAbsMax( const GridFunction& f1,
-                                                        const GridFunction& f2 ) const;
-
-   template< typename GridFunction >
-   typename GridFunction::RealType getDifferenceLpNorm( const GridFunction& f1,
-                                                        const GridFunction& f2,
-                                                        const typename GridFunction::RealType& p ) const;
-
    /**
     * \brief See Grid1D::save( File& file ) const.
     */
diff --git a/src/TNL/Meshes/GridDetails/Grid3D_impl.h b/src/TNL/Meshes/GridDetails/Grid3D_impl.h
index f4707a8ce34654544f9d7455122ebc3a340d690b..dd91a7ed852c0d961be8c3cb0811d5c687735280 100644
--- a/src/TNL/Meshes/GridDetails/Grid3D_impl.h
+++ b/src/TNL/Meshes/GridDetails/Grid3D_impl.h
@@ -407,98 +407,6 @@ Real Grid< 3, Real, Device, Index > :: getSmallestSpaceStep() const
    return min( this->spaceSteps.x(), min( this->spaceSteps.y(), this->spaceSteps.z() ) );
 }
 
-template< typename Real,
-          typename Device,
-          typename Index >
-   template< typename GridFunction >
-typename GridFunction::RealType
-   Grid< 3, Real, Device, Index >::getAbsMax( const GridFunction& f ) const
-{
-   return f.absMax();
-}
-
-template< typename Real,
-          typename Device,
-          typename Index >
-   template< typename GridFunction >
-typename GridFunction::RealType
-   Grid< 3, Real, Device, Index >::getLpNorm( const GridFunction& f1,
-                                                 const typename GridFunction::RealType& p ) const
-{
-   typename GridFunction::RealType lpNorm( 0.0 );
-   Cell cell;
-   for( cell.getCoordinates().z() = 0;
-        cell.getCoordinates().z() < getDimensions().z();
-        cell.getCoordinates().z()++ )
-      for( cell.getCoordinates().y() = 0;
-           cell.getCoordinates().y() < getDimensions().y();
-           cell.getCoordinates().y()++ )
-         for( cell.getCoordinates().x() = 0;
-              cell.getCoordinates().x() < getDimensions().x();
-              cell.getCoordinates().x()++ )
-         {
-            IndexType c = this->getEntityIndex( cell );
-            lpNorm += ::pow( abs( f1[ c ] ), p );;
-         }
-   lpNorm *= this->getSpaceSteps()().x() * this->getSpaceSteps()().y() * this->getSpaceSteps()().z();
-   return ::pow( lpNorm, 1.0/p );
-}
-
-
-template< typename Real,
-          typename Device,
-          typename Index >
-   template< typename GridFunction >
-      typename GridFunction::RealType
-         Grid< 3, Real, Device, Index >::getDifferenceAbsMax( const GridFunction& f1,
-                                                                           const GridFunction& f2 ) const
-{
-   typename GridFunction::RealType maxDiff( -1.0 );
-   Cell cell( *this );
-   for( cell.getCoordinates().z() = 0;
-        cell.getCoordinates().z() < getDimensions().z();
-        cell.getCoordinates().z()++ )
-      for( cell.getCoordinates().y() = 0;
-           cell.getCoordinates().y() < getDimensions().y();
-           cell.getCoordinates().y()++ )
-         for( cell.getCoordinates().x() = 0;
-              cell.getCoordinates().x() < getDimensions().x();
-              cell.getCoordinates().x()++ )
-         {
-            IndexType c = this->getEntityIndex( cell );
-            maxDiff = max( maxDiff, abs( f1[ c ] - f2[ c ] ) );
-         }
-   return maxDiff;
-}
-
-template< typename Real,
-          typename Device,
-          typename Index >
-   template< typename GridFunction >
-      typename GridFunction::RealType
-         Grid< 3, Real, Device, Index >::getDifferenceLpNorm( const GridFunction& f1,
-                                                                 const GridFunction& f2,
-                                                                 const typename GridFunction::RealType& p ) const
-{
-   typename GridFunction::RealType lpNorm( 0.0 );
-   Cell cell( *this );
-   for( cell.getCoordinates().z() = 0;
-        cell.getCoordinates().z() < getDimensions().z();
-        cell.getCoordinates().z()++ )
-      for( cell.getCoordinates().y() = 0;
-           cell.getCoordinates().y() < getDimensions().y();
-           cell.getCoordinates().y()++ )
-         for( cell.getCoordinates().x() = 0;
-              cell.getCoordinates().x() < getDimensions().x();
-              cell.getCoordinates().x()++ )
-         {
-            IndexType c = this->getEntityIndex( cell );
-            lpNorm += ::pow( abs( f1[ c ] - f2[ c ] ), p );
-         }
-   lpNorm *= this->getSpaceSteps().x() * this->getSpaceSteps().y() * this->getSpaceSteps().z();
-   return ::pow( lpNorm, 1.0 / p );
-}
-
 template< typename Real,
           typename Device,
           typename Index >
diff --git a/src/TNL/Meshes/MeshDetails/initializer/Initializer.h b/src/TNL/Meshes/MeshDetails/initializer/Initializer.h
index 759490234a5a04f527eb124a4237f2e0d74a9a8b..acaeeaff4ab66abf552dc97b86ac71f77e67e67c 100644
--- a/src/TNL/Meshes/MeshDetails/initializer/Initializer.h
+++ b/src/TNL/Meshes/MeshDetails/initializer/Initializer.h
@@ -65,7 +65,9 @@ template< typename MeshConfig,
           bool EntityStorage =
              MeshTraits< MeshConfig >::template EntityTraits< DimensionTag::value >::storageEnabled,
           bool EntityReferenceOrientationStorage =
-             MeshTraits< MeshConfig >::template EntityTraits< DimensionTag::value >::orientationNeeded >
+             MeshTraits< MeshConfig >::template EntityTraits< DimensionTag::value >::orientationNeeded &&
+             // orientationNeeded does not make sense without storageEnabled
+             MeshTraits< MeshConfig >::template EntityTraits< DimensionTag::value >::storageEnabled >
 class InitializerLayer;
 
 
diff --git a/src/TNL/Meshes/TypeResolver/TypeResolver_impl.h b/src/TNL/Meshes/TypeResolver/TypeResolver_impl.h
index d45016af193656cb6094f3782b304a92c224bf2a..f18188b9c5ebc40b3d40c70d22445529962fcd7c 100644
--- a/src/TNL/Meshes/TypeResolver/TypeResolver_impl.h
+++ b/src/TNL/Meshes/TypeResolver/TypeResolver_impl.h
@@ -19,6 +19,7 @@
 #include <TNL/Meshes/Readers/VTKReader.h>
 #include <TNL/Meshes/TypeResolver/GridTypeResolver.h>
 #include <TNL/Meshes/TypeResolver/MeshTypeResolver.h>
+#include <TNL/Communicators/NoDistrCommunicator.h>
 
 // TODO: implement this in TNL::String
 inline bool ends_with( const std::string& value, const std::string& ending )
@@ -117,7 +118,7 @@ template< typename CommunicatorType,
 bool
 loadMesh( const String& fileName,
           Mesh< MeshConfig, Device >& mesh,
-          DistributedMeshes::DistributedMesh< Mesh< MeshConfig, Device > > &distributedMesh )
+          DistributedMeshes::DistributedMesh< Mesh< MeshConfig, Device > >& distributedMesh )
 {
    if( CommunicatorType::isDistributed() )
    {
@@ -188,9 +189,12 @@ loadMesh( const String& fileName,
    }
 
    Mesh< MeshConfig, Devices::Host > hostMesh;
-   if( ! loadMesh( fileName, hostMesh ) )
+   DistributedMeshes::DistributedMesh< Mesh< MeshConfig, Devices::Host > > hostDistributedMesh;
+   if( ! loadMesh< CommunicatorType >( fileName, hostMesh, hostDistributedMesh ) )
       return false;
    mesh = hostMesh;
+   // TODO
+//   distributedMesh = hostDistributedMesh;
    return true;
 }
 
@@ -278,5 +282,16 @@ decomposeMesh( const Config::ParameterContainer& parameters,
       return true;
 }
 
+// convenient overload for non-distributed meshes
+template< typename Mesh >
+bool
+loadMesh( const String& fileName, Mesh& mesh )
+{
+   using Communicator = TNL::Communicators::NoDistrCommunicator;
+   using DistributedMesh = DistributedMeshes::DistributedMesh< Mesh>;
+   DistributedMesh distributedMesh;
+   return loadMesh< Communicator >( fileName, mesh, distributedMesh );
+}
+
 } // namespace Meshes
 } // namespace TNL
diff --git a/src/TNL/Solvers/Linear/BICGStabL_impl.h b/src/TNL/Solvers/Linear/BICGStabL_impl.h
index 3f41e5115d0043b168bb9425a567bf02c97159b0..5597cfdf7c231da94dcdc62b702082991d7814b4 100644
--- a/src/TNL/Solvers/Linear/BICGStabL_impl.h
+++ b/src/TNL/Solvers/Linear/BICGStabL_impl.h
@@ -102,7 +102,7 @@ solve( ConstVectorViewType b, VectorViewType x )
           */
          Matrices::MatrixOperations< DeviceType >::
             geam( size, j + 1,
-                  1.0, R.getData(), ldSize,
+                  (RealType) 1.0, R.getData(), ldSize,
                   -beta, U.getData(), ldSize,
                   U.getData(), ldSize );
 
@@ -121,7 +121,7 @@ solve( ConstVectorViewType b, VectorViewType x )
           */
          Matrices::MatrixOperations< DeviceType >::
             geam( size, j + 1,
-                  1.0, R.getData(), ldSize,
+                  (RealType) 1.0, R.getData(), ldSize,
                   -alpha, U.getData() + ldSize, ldSize,
                   R.getData(), ldSize );
 
@@ -206,18 +206,18 @@ solve( ConstVectorViewType b, VectorViewType x )
       g_2[ 0 ] = g_0[ 1 ];
       Matrices::MatrixOperations< DeviceType >::
          gemv( size, ell,
-               1.0, R.getData(), ldSize, g_2.getData(),
-               1.0, Traits::getLocalView( x ).getData() );
+               (RealType) 1.0, R.getData(), ldSize, g_2.getData(),
+               (RealType) 1.0, Traits::getLocalView( x ).getData() );
       // r_0 := r_0 - R_[1:ell] * g_1_[1:ell]
       Matrices::MatrixOperations< DeviceType >::
          gemv( size, ell,
-               -1.0, R.getData() + ldSize, ldSize, &g_1[ 1 ],
-               1.0, Traits::getLocalView( r_0 ).getData() );
+               (RealType) -1.0, R.getData() + ldSize, ldSize, &g_1[ 1 ],
+               (RealType) 1.0, Traits::getLocalView( r_0 ).getData() );
       // u_0 := u_0 - U_[1:ell] * g_0_[1:ell]
       Matrices::MatrixOperations< DeviceType >::
          gemv( size, ell,
-               -1.0, U.getData() + ldSize, ldSize, &g_0[ 1 ],
-               1.0, Traits::getLocalView( u_0 ).getData() );
+               (RealType) -1.0, U.getData() + ldSize, ldSize, &g_0[ 1 ],
+               (RealType) 1.0, Traits::getLocalView( u_0 ).getData() );
 
       if( exact_residue ) {
          /****
diff --git a/src/TNL/Solvers/Linear/GMRES_impl.h b/src/TNL/Solvers/Linear/GMRES_impl.h
index 8e653e28b2d783e4a342f899eb794554d11c131a..2e1d9fbb25a8dfbb1d05b64c186dd855a479924b 100644
--- a/src/TNL/Solvers/Linear/GMRES_impl.h
+++ b/src/TNL/Solvers/Linear/GMRES_impl.h
@@ -243,8 +243,8 @@ orthogonalize_CGS( const int m, const RealType normb, const RealType beta )
          // w := w - V_i * H_l
          Matrices::MatrixOperations< DeviceType >::
             gemv( size, i + 1,
-                  -1.0, V.getData(), ldSize, H_l,
-                  1.0, Traits::getLocalView( w ).getData() );
+                  (RealType) -1.0, V.getData(), ldSize, H_l,
+                  (RealType) 1.0, Traits::getLocalView( w ).getData() );
       }
       /***
        * H_{i+1,i} = |w|
@@ -607,8 +607,8 @@ hauseholder_cwy( VectorViewType v,
    // v = e_i - Y_i * aux
    Matrices::MatrixOperations< DeviceType >::
       gemv( size, i + 1,
-            -1.0, Y.getData(), ldSize, aux,
-            0.0, Traits::getLocalView( v ).getData() );
+            (RealType) -1.0, Y.getData(), ldSize, aux,
+            (RealType) 0.0, Traits::getLocalView( v ).getData() );
    if( localOffset == 0 )
       v.setElement( i, 1.0 + v.getElement( i ) );
 }
@@ -649,8 +649,8 @@ hauseholder_cwy_transposed( VectorViewType z,
    z = w;
    Matrices::MatrixOperations< DeviceType >::
       gemv( size, i + 1,
-            -1.0, Y.getData(), ldSize, aux,
-            1.0, Traits::getLocalView( z ).getData() );
+            (RealType) -1.0, Y.getData(), ldSize, aux,
+            (RealType) 1.0, Traits::getLocalView( z ).getData() );
 }
 
 template< typename Matrix >
@@ -691,8 +691,8 @@ update( const int k,
       // x = V * y + x
       Matrices::MatrixOperations< DeviceType >::
          gemv( size, k + 1,
-               1.0, V.getData(), ldSize, y,
-               1.0, Traits::getLocalView( x ).getData() );
+               (RealType) 1.0, V.getData(), ldSize, y,
+               (RealType) 1.0, Traits::getLocalView( x ).getData() );
    }
    else {
       // The vectors v_i are not stored, they can be reconstructed as P_0...P_j * e_j.
@@ -723,8 +723,8 @@ update( const int k,
       // x -= Y_{k+1} * aux
       Matrices::MatrixOperations< DeviceType >::
          gemv( size, k + 1,
-               -1.0, Y.getData(), ldSize, aux,
-               1.0, Traits::getLocalView( x ).getData() );
+               (RealType) -1.0, Y.getData(), ldSize, aux,
+               (RealType) 1.0, Traits::getLocalView( x ).getData() );
 
       // x += y
       if( localOffset == 0 )
diff --git a/src/TNL/Solvers/Linear/Preconditioners/ILU0.h b/src/TNL/Solvers/Linear/Preconditioners/ILU0.h
index 8a177df055c682ead7b7037aae4772ae2d1ef1ab..d5127fab5dec1e67a97d254f57e81f8d49e3d847 100644
--- a/src/TNL/Solvers/Linear/Preconditioners/ILU0.h
+++ b/src/TNL/Solvers/Linear/Preconditioners/ILU0.h
@@ -31,7 +31,26 @@ namespace Preconditioners {
 // implementation template
 template< typename Matrix, typename Real, typename Device, typename Index >
 class ILU0_impl
-{};
+: public Preconditioner< Matrix >
+{
+public:
+   using RealType = Real;
+   using DeviceType = Device;
+   using IndexType = Index;
+   using typename Preconditioner< Matrix >::VectorViewType;
+   using typename Preconditioner< Matrix >::ConstVectorViewType;
+   using typename Preconditioner< Matrix >::MatrixPointer;
+
+   virtual void update( const MatrixPointer& matrixPointer ) override
+   {
+      throw Exceptions::NotImplementedError("ILU0 is not implemented yet for the matrix type " + getType< Matrix >());
+   }
+
+   virtual void solve( ConstVectorViewType b, VectorViewType x ) const override
+   {
+      throw Exceptions::NotImplementedError("ILU0 is not implemented yet for the matrix type " + getType< Matrix >());
+   }
+};
 
 // actual template to be used by users
 template< typename Matrix >
diff --git a/src/TNL/TypeTraits.h b/src/TNL/TypeTraits.h
index d617f2b42454bce2fad7a5d2ff69b685574723c9..3183460fef20a663705c02b641f8c866e2cde1c7 100644
--- a/src/TNL/TypeTraits.h
+++ b/src/TNL/TypeTraits.h
@@ -103,6 +103,33 @@ public:
     static constexpr bool value = type::value;
 };
 
+/**
+ * \brief Type trait for checking if T has operator+= taking one argument of type T.
+ */
+template< typename T >
+class HasAddAssignmentOperator
+{
+private:
+   template< typename U >
+   static constexpr auto check(U*)
+   -> typename
+      std::enable_if_t<
+         ! std::is_same<
+               decltype( std::declval<U>() += std::declval<U>() ),
+               void
+            >::value,
+         std::true_type
+      >;
+
+   template< typename >
+   static constexpr std::false_type check(...);
+
+   using type = decltype(check<T>(0));
+
+public:
+    static constexpr bool value = type::value;
+};
+
 /**
  * \brief Type trait for checking if T is an array type, e.g.
  *        \ref Containers::Array or \ref Containers::Vector.
@@ -118,6 +145,17 @@ struct IsArrayType
             HasSubscriptOperator< T >::value >
 {};
 
+/**
+ * \brief Type trait for checking if T is a vector type, e.g.
+ *        \ref Containers::Vector or \ref Containers::VectorView.
+ */
+template< typename T >
+struct IsVectorType
+: public std::integral_constant< bool,
+            IsArrayType< T >::value &&
+            HasAddAssignmentOperator< T >::value >
+{};
+
 /**
  * \brief Type trait for checking if T has a \e constexpr \e getSize method.
  */
diff --git a/src/Tools/tnl-diff.cpp b/src/Tools/tnl-diff.cpp
index 4614738154339739421fc29dda9e71d05b03d13a..7e442c982fe777abc2d02259a881f28d945e682f 100644
--- a/src/Tools/tnl-diff.cpp
+++ b/src/Tools/tnl-diff.cpp
@@ -23,10 +23,10 @@ void setupConfig( Config::ConfigDescription& config )
       config.addEntryEnum< String >( "halves" );
    config.addEntry< bool >( "exact-match", "Check if the data are exactly the same.", false );
    config.addEntry< bool >( "write-difference", "Write difference grid function.", false );
-   config.addEntry< bool >( "write-exact-curve", "Write exact curve with given radius.", false );
+//   config.addEntry< bool >( "write-exact-curve", "Write exact curve with given radius.", false );
    config.addEntry< int >( "edges-skip", "Width of the edges that will be skipped - not included into the error norms.", 0 );
-   config.addEntry< bool >( "write-graph", "Draws a graph in the Gnuplot format of the dependence of the error norm on t.", true );
-   config.addEntry< bool >( "write-log-graph", "Draws a logarithmic graph in the Gnuplot format of the dependence of the error norm on t.", true );
+//   config.addEntry< bool >( "write-graph", "Draws a graph in the Gnuplot format of the dependence of the error norm on t.", true );
+//   config.addEntry< bool >( "write-log-graph", "Draws a logarithmic graph in the Gnuplot format of the dependence of the error norm on t.", true );
    config.addEntry< double >( "snapshot-period", "The period between consecutive snapshots.", 0.0 );
    config.addEntry< bool >( "verbose", "Sets verbosity.", true );
 }
diff --git a/src/Tools/tnl-diff.h b/src/Tools/tnl-diff.h
index e17ca7940b295d249822c59e92f34055613a136b..81a0620de91e188e9d1fff4ab62deb2059f43b87 100644
--- a/src/Tools/tnl-diff.h
+++ b/src/Tools/tnl-diff.h
@@ -394,8 +394,11 @@ bool computeDifferenceOfVectors( const MeshPointer& meshPointer, const Config::P
          //if( snapshotPeriod != 0.0 )
          outputFile << std::setw( 6 ) << ( i - half ) * snapshotPeriod << " ";
       }
-      Real l1Diff = meshPointer->getDifferenceLpNorm( v1, v2, 1.0 );
-      Real l2Diff = meshPointer->getDifferenceLpNorm( v1, v2, 2.0 );
+      Real cellVolume = meshPointer->getCellMeasure();
+//      Real l1Diff = meshPointer->getDifferenceLpNorm( v1, v2, 1.0 );
+      Real l1Diff = cellVolume * sum( abs( v1 - v2 ) );
+//      Real l2Diff = meshPointer->getDifferenceLpNorm( v1, v2, 2.0 );
+      Real l2Diff = cellVolume * std::sqrt( dot(v1 - v2, v1 - v2) );
       Real maxDiff = max( abs( v1 - v2 ) );
       if( snapshotPeriod != 0.0 )
       {
diff --git a/src/Tools/tnl-grid-setup.cpp b/src/Tools/tnl-grid-setup.cpp
index 1846dc09351a234b4068400edbb3c268f2a30bbe..261f1cf716d6f7b453b27a7acb3f2bfd7d6daa9a 100644
--- a/src/Tools/tnl-grid-setup.cpp
+++ b/src/Tools/tnl-grid-setup.cpp
@@ -15,11 +15,14 @@ void configSetup( Config::ConfigDescription& config )
 {
    config.addDelimiter( "General parameters" );
    config.addEntry        < String >( "output-file",   "Output file.", "mesh.tnl" );
-   config.addEntry        < int >      ( "verbose",       "Set the verbosity of the program.", 1 );
+   config.addEntry        < int >   ( "verbose",       "Set the verbosity of the program.", 1 );
 
-   config.addDelimiter                 ( "Grid parameters" );
+   config.addDelimiter              ( "Grid parameters" );
    config.addEntry        < String >( "grid-name",     "The grid name.", "tnl-grid" );
-   config.addRequiredEntry< int >      ( "dimensions",    "The grid dimensions." );
+   config.addRequiredEntry< int >   ( "dimension",     "The grid dimension." );
+      config.addEntryEnum< int >( 1 );
+      config.addEntryEnum< int >( 2 );
+      config.addEntryEnum< int >( 3 );
    config.addEntry        < String >( "real-type",     "Precision of the real type describing the grid.", "double" );
       config.addEntryEnum < String >( "float" );
       config.addEntryEnum < String >( "double" );
@@ -27,16 +30,16 @@ void configSetup( Config::ConfigDescription& config )
    config.addEntry        < String >( "index-type",    "Type for the indexing of the grid elements." ,"int" );
       config.addEntryEnum < String >( "int" );
       config.addEntryEnum < String >( "long-int" );
-   config.addEntry        < double >   ( "origin-x",          "The x-coordinate of the origin.", 0.0 );
-   config.addEntry        < double >   ( "origin-y",          "The y-coordinate of the origin.", 0.0 );
-   config.addEntry        < double >   ( "origin-z",          "The z-coordinate of the origin.", 0.0 );
-   config.addEntry        < double >   ( "proportions-x",     "The proportions of the grid along the x axis.", 1.0 );
-   config.addEntry        < double >   ( "proportions-y",     "The proportions of the grid along the y axis.", 1.0 );
-   config.addEntry        < double >   ( "proportions-z",     "The proportions of the grid along the z axis.", 1.0 );
-   config.addEntry        < int >      ( "size-x",            "Number of elements along the x axis." );
-   config.addEntry        < int >      ( "size-y",            "Number of elements along the y axis." );
-   config.addEntry        < int >      ( "size-z",            "Number of elements along the z axis." );
-   config.addEntry        < bool >     ( "equal-space-steps", "All space steps will be equivalent.", false );
+   config.addEntry        < double >( "origin-x",          "The x-coordinate of the origin.", 0.0 );
+   config.addEntry        < double >( "origin-y",          "The y-coordinate of the origin.", 0.0 );
+   config.addEntry        < double >( "origin-z",          "The z-coordinate of the origin.", 0.0 );
+   config.addEntry        < double >( "proportions-x",     "The proportions of the grid along the x axis.", 1.0 );
+   config.addEntry        < double >( "proportions-y",     "The proportions of the grid along the y axis.", 1.0 );
+   config.addEntry        < double >( "proportions-z",     "The proportions of the grid along the z axis.", 1.0 );
+   config.addEntry        < int >   ( "size-x",            "Number of elements along the x axis." );
+   config.addEntry        < int >   ( "size-y",            "Number of elements along the y axis." );
+   config.addEntry        < int >   ( "size-z",            "Number of elements along the z axis." );
+   config.addEntry        < bool >  ( "equal-space-steps", "All space steps will be equivalent.", false );
 }
 
 int main( int argc, char* argv[] )
@@ -50,5 +53,3 @@ int main( int argc, char* argv[] )
       return EXIT_FAILURE;
    return EXIT_SUCCESS;
 }
-
-
diff --git a/src/Tools/tnl-grid-setup.h b/src/Tools/tnl-grid-setup.h
index 896d3abb971571abcededb8bed75dcd9cb0f1fff..867cfdb73bdb75f6ba073724b0ebd2db3769f6b4 100644
--- a/src/Tools/tnl-grid-setup.h
+++ b/src/Tools/tnl-grid-setup.h
@@ -19,14 +19,18 @@ using namespace TNL;
 template< typename RealType, typename IndexType >
 bool setupGrid( const Config::ParameterContainer& parameters )
 {
-   String gridName = parameters. getParameter< String >( "grid-name" );
-   String outputFile = parameters. getParameter< String >( "output-file" );
-   int dimensions = parameters. getParameter< int >( "dimensions" );
-   if( dimensions == 1 )
+   const String gridName = parameters.getParameter< String >( "grid-name" );
+   const String outputFile = parameters.getParameter< String >( "output-file" );
+   const int dimension = parameters.getParameter< int >( "dimension" );
+   if( dimension == 1 )
    {
-      RealType originX = parameters. getParameter< double >( "origin-x" );
-      RealType proportionsX = parameters. getParameter< double >( "proportions-x" );
-      IndexType sizeX = parameters. getParameter< int >( "size-x" );
+      RealType originX = parameters.getParameter< double >( "origin-x" );
+      RealType proportionsX = parameters.getParameter< double >( "proportions-x" );
+      if( ! parameters.checkParameter( "size-x" ) ) {
+         std::cerr << "The parameter size-x is required when the grid dimension is 1." << std::endl;
+         return false;
+      }
+      IndexType sizeX = parameters.getParameter< int >( "size-x" );
 
       typedef Meshes::Grid< 1, RealType, Devices::Host, IndexType > GridType;
       typedef typename GridType::PointType PointType;
@@ -46,12 +50,16 @@ bool setupGrid( const Config::ParameterContainer& parameters )
          return false;
       }
    }
-   if( dimensions == 2 )
+   if( dimension == 2 )
    {
       RealType originX = parameters.getParameter< double >( "origin-x" );
       RealType originY = parameters.getParameter< double >( "origin-y" );
       RealType proportionsX = parameters.getParameter< double >( "proportions-x" );
       RealType proportionsY = parameters.getParameter< double >( "proportions-y" );
+      if( ! parameters.checkParameters( {"size-x", "size-y"} ) ) {
+         std::cerr << "The parameters size-x and size-y are required when the grid dimension is 2." << std::endl;
+         return false;
+      }
       IndexType sizeX = parameters.getParameter< int >( "size-x" );
       IndexType sizeY = parameters.getParameter< int >( "size-y" );
       typedef Meshes::Grid< 2, RealType, Devices::Host, IndexType > GridType;
@@ -84,17 +92,21 @@ bool setupGrid( const Config::ParameterContainer& parameters )
          return false;
       }
    }
-   if( dimensions == 3 )
+   if( dimension == 3 )
    {
-      RealType originX = parameters. getParameter< double >( "origin-x" );
-      RealType originY = parameters. getParameter< double >( "origin-y" );
-      RealType originZ = parameters. getParameter< double >( "origin-z" );
-      RealType proportionsX = parameters. getParameter< double >( "proportions-x" );
-      RealType proportionsY = parameters. getParameter< double >( "proportions-y" );
-      RealType proportionsZ = parameters. getParameter< double >( "proportions-z" );
-      IndexType sizeX = parameters. getParameter< int >( "size-x" );
-      IndexType sizeY = parameters. getParameter< int >( "size-y" );
-      IndexType sizeZ = parameters. getParameter< int >( "size-z" );
+      RealType originX = parameters.getParameter< double >( "origin-x" );
+      RealType originY = parameters.getParameter< double >( "origin-y" );
+      RealType originZ = parameters.getParameter< double >( "origin-z" );
+      RealType proportionsX = parameters.getParameter< double >( "proportions-x" );
+      RealType proportionsY = parameters.getParameter< double >( "proportions-y" );
+      RealType proportionsZ = parameters.getParameter< double >( "proportions-z" );
+      if( ! parameters.checkParameters( {"size-x", "size-y", "size-z"} ) ) {
+         std::cerr << "The parameters size-x, size-y and size-z are required when the grid dimension is 3." << std::endl;
+         return false;
+      }
+      IndexType sizeX = parameters.getParameter< int >( "size-x" );
+      IndexType sizeY = parameters.getParameter< int >( "size-y" );
+      IndexType sizeZ = parameters.getParameter< int >( "size-z" );
 
       typedef Meshes::Grid< 3, RealType, Devices::Host, IndexType > GridType;
       typedef typename GridType::PointType PointType;
@@ -115,7 +127,7 @@ bool setupGrid( const Config::ParameterContainer& parameters )
       }
       std::cout << "Setting dimensions to  ... " << grid.getDimensions() << std::endl;
       std::cout << "Writing the grid to the file " << outputFile << " .... ";      
-      
+
       try
       {
          grid.save( outputFile );
@@ -126,34 +138,34 @@ bool setupGrid( const Config::ParameterContainer& parameters )
          return false;
       }
    }
-  std::cout << "[ OK ] " << std::endl;
+   std::cout << "[ OK ] " << std::endl;
    return true;
 }
 
 template< typename RealType >
 bool resolveIndexType( const Config::ParameterContainer& parameters )
 {
-   const String& indexType = parameters. getParameter< String >( "index-type" );
-  std::cout << "Setting index type to  ... " << indexType << std::endl;
+   const String& indexType = parameters.getParameter< String >( "index-type" );
+   std::cout << "Setting index type to  ... " << indexType << std::endl;
    if( indexType == "int" )
       return setupGrid< RealType, int >( parameters );
    if( indexType == "long-int" )
       return setupGrid< RealType, long int >( parameters );
-   std::cerr << "The index type '" << indexType << "' is not defined. " << std::endl;
+   std::cerr << "The index type '" << indexType << "' is not defined." << std::endl;
    return false;
 }
 
 bool resolveRealType( const Config::ParameterContainer& parameters )
 {
-   String realType = parameters. getParameter< String >( "real-type" );
-  std::cout << "Setting real type to   ... " << realType << std::endl;
+   String realType = parameters.getParameter< String >( "real-type" );
+   std::cout << "Setting real type to   ... " << realType << std::endl;
    if( realType == "float" )
       return resolveIndexType< float >( parameters );
    if( realType == "double" )
       return resolveIndexType< double >( parameters );
    if( realType == "long-double" )
       return resolveIndexType< long double >( parameters );
-   std::cerr << "The real type '" << realType << "' is not supported. " << std::endl;
+   std::cerr << "The real type '" << realType << "' is not supported." << std::endl;
    return false;
 }
 
diff --git a/src/Tools/tnl-view.cpp b/src/Tools/tnl-view.cpp
index f426b6fe0c6bf36318e3e245ecce184b35ae0d0f..32fac87d9645c066fe111eef1fb2c66961ae1c5c 100644
--- a/src/Tools/tnl-view.cpp
+++ b/src/Tools/tnl-view.cpp
@@ -64,22 +64,22 @@ template< typename GlobalIndex > struct MeshIdTag< TNLViewBuildConfigTag, Global
 
 void setupConfig( Config::ConfigDescription& config )
 {
-   config.addDelimiter                            ( "General settings:" );
-   config.addEntry        < String >           ( "mesh", "Mesh file.", "mesh.tnl" );
-   config.addRequiredList < String >           ( "input-files", "Input files." );
-   config.addList         < String >           ( "output-files", "Output files." );
-   config.addEntry        < bool >                ( "check-output-file", "If the output file already exists, do not recreate it.", false );
+   config.addDelimiter( "General settings:" );
+   config.addEntry        < String >( "mesh", "Mesh file.", "mesh.tnl" );
+   config.addRequiredList < String >( "input-files", "Input files." );
+//   config.addList         < String >( "output-files", "Output files." );
+   config.addEntry        < bool >  ( "check-output-file", "If the output file already exists, do not recreate it.", false );
 
    config.addDelimiter( "Grid settings:");
-   config.addList         < double >              ( "level-lines", "List of level sets which will be drawn." );
-   config.addEntry        < int >                 ( "output-x-size", "X size of the output." );
-   config.addEntry        < int >                 ( "output-y-size", "Y size of the output." );
-   config.addEntry        < int >                 ( "output-z-size", "Z size of the output." );
-   config.addEntry        < double >              ( "scale", "Multiply the function by given number.", 1.0 );
-   config.addEntry        < String >           ( "output-format", "Output file format.", "gnuplot" );
-      config.addEntryEnum  < String >             ( "gnuplot" );
-      config.addEntryEnum  < String >             ( "vtk" );
-   config.addEntry        < int >                 ( "verbose", "Set the verbosity of the program.", 1 );
+//   config.addList         < double >( "level-lines", "List of level sets which will be drawn." );
+//   config.addEntry        < int >   ( "output-x-size", "X size of the output." );
+//   config.addEntry        < int >   ( "output-y-size", "Y size of the output." );
+//   config.addEntry        < int >   ( "output-z-size", "Z size of the output." );
+   config.addEntry        < double >( "scale", "Multiply the function by given number.", 1.0 );
+   config.addEntry        < String >( "output-format", "Output file format.", "gnuplot" );
+      config.addEntryEnum< String > ( "gnuplot" );
+      config.addEntryEnum< String > ( "vtk" );
+   config.addEntry        < int >   ( "verbose", "Set the verbosity of the program.", 1 );
 }
 
 int main( int argc, char* argv[] )
@@ -90,10 +90,9 @@ int main( int argc, char* argv[] )
    if( ! parseCommandLine( argc, argv, conf_desc, parameters ) )
       return EXIT_FAILURE;
 
-   String meshFile = parameters.getParameter< String >( "mesh" );
+   const String meshFile = parameters.getParameter< String >( "mesh" );
    return ! TNL::Meshes::resolveMeshType< TNLViewBuildConfigTag,
                                           Devices::Host,
                                           FilesProcessor >
-                                             ( meshFile,
-                                                parameters );
+                                        ( meshFile, parameters );
 }
diff --git a/src/Tools/tnl-view.h b/src/Tools/tnl-view.h
index 7e7b82bbfc8165245fad06e1e97dad072e621442..fd7bdd8c472095580169274b8d29452cc67a604d 100644
--- a/src/Tools/tnl-view.h
+++ b/src/Tools/tnl-view.h
@@ -415,7 +415,7 @@ struct FilesProcessor
       }
 
       bool checkOutputFile = parameters. getParameter< bool >( "check-output-file" );
-      std::vector< String > inputFiles = parameters. getParameter< std::vector< String > >( "input-files" );
+      std::vector< String > inputFiles = parameters.getParameter< std::vector< String > >( "input-files" );
       bool error( false );
    //#ifdef HAVE_OPENMP
    //#pragma omp parallel for
diff --git a/src/UnitTests/Containers/CMakeLists.txt b/src/UnitTests/Containers/CMakeLists.txt
index 6ff7570dd3b1a62051ce295180205ddac0675156..9f27aaa86078937540ccc1716069faec0f69b424 100644
--- a/src/UnitTests/Containers/CMakeLists.txt
+++ b/src/UnitTests/Containers/CMakeLists.txt
@@ -30,6 +30,11 @@ ADD_EXECUTABLE( VectorVerticalOperationsTest VectorVerticalOperationsTest.cpp )
 TARGET_COMPILE_OPTIONS( VectorVerticalOperationsTest PRIVATE ${CXX_TESTS_FLAGS} )
 TARGET_LINK_LIBRARIES( VectorVerticalOperationsTest ${GTEST_BOTH_LIBRARIES} )
 
+# FIXME
+#ADD_EXECUTABLE( VectorOfStaticVectorsTest VectorOfStaticVectorsTest.cpp )
+#TARGET_COMPILE_OPTIONS( VectorOfStaticVectorsTest PRIVATE ${CXX_TESTS_FLAGS} )
+#TARGET_LINK_LIBRARIES( VectorOfStaticVectorsTest ${GTEST_BOTH_LIBRARIES} )
+
 IF( BUILD_CUDA )
    CUDA_ADD_EXECUTABLE( ArrayTestCuda ArrayTest.cu
                         OPTIONS ${CXX_TESTS_FLAGS} )
@@ -54,6 +59,10 @@ IF( BUILD_CUDA )
 
    CUDA_ADD_EXECUTABLE( VectorVerticalOperationsTestCuda VectorVerticalOperationsTest.cu OPTIONS ${CXX_TESTS_FLAGS} )
    TARGET_LINK_LIBRARIES( VectorVerticalOperationsTestCuda ${GTEST_BOTH_LIBRARIES} )
+
+   # FIXME
+#   CUDA_ADD_EXECUTABLE( VectorOfStaticVectorsTestCuda VectorOfStaticVectorsTest.cu OPTIONS ${CXX_TESTS_FLAGS} )
+#   TARGET_LINK_LIBRARIES( VectorOfStaticVectorsTestCuda ${GTEST_BOTH_LIBRARIES} )
 ENDIF( BUILD_CUDA )
 
 ADD_EXECUTABLE( StaticArrayTest StaticArrayTest.cpp )
@@ -68,6 +77,11 @@ ADD_EXECUTABLE( StaticVectorOperationsTest StaticVectorOperationsTest.cpp )
 TARGET_COMPILE_OPTIONS( StaticVectorOperationsTest PRIVATE ${CXX_TESTS_FLAGS} )
 TARGET_LINK_LIBRARIES( StaticVectorOperationsTest ${GTEST_BOTH_LIBRARIES} )
 
+# FIXME
+#ADD_EXECUTABLE( StaticVectorOfStaticVectorsTest StaticVectorOfStaticVectorsTest.cpp )
+#TARGET_COMPILE_OPTIONS( StaticVectorOfStaticVectorsTest PRIVATE ${CXX_TESTS_FLAGS} )
+#TARGET_LINK_LIBRARIES( StaticVectorOfStaticVectorsTest ${GTEST_BOTH_LIBRARIES} )
+
 
 ADD_TEST( ArrayTest ${EXECUTABLE_OUTPUT_PATH}/ArrayTest${CMAKE_EXECUTABLE_SUFFIX} )
 ADD_TEST( ArrayViewTest ${EXECUTABLE_OUTPUT_PATH}/ArrayViewTest${CMAKE_EXECUTABLE_SUFFIX} )
@@ -77,6 +91,7 @@ ADD_TEST( VectorEvaluateAndReduceTest ${EXECUTABLE_OUTPUT_PATH}/VectorEvaluateAn
 ADD_TEST( VectorBinaryOperationsTest ${EXECUTABLE_OUTPUT_PATH}/VectorBinaryOperationsTest${CMAKE_EXECUTABLE_SUFFIX} )
 ADD_TEST( VectorUnaryOperationsTest ${EXECUTABLE_OUTPUT_PATH}/VectorUnaryOperationsTest${CMAKE_EXECUTABLE_SUFFIX} )
 ADD_TEST( VectorVerticalOperationsTest ${EXECUTABLE_OUTPUT_PATH}/VectorVerticalOperationsTest${CMAKE_EXECUTABLE_SUFFIX} )
+#ADD_TEST( VectorOfStaticVectorsTest ${EXECUTABLE_OUTPUT_PATH}/VectorOfStaticVectorsTest${CMAKE_EXECUTABLE_SUFFIX} )
 IF( BUILD_CUDA )
    ADD_TEST( ArrayTestCuda ${EXECUTABLE_OUTPUT_PATH}/ArrayTestCuda${CMAKE_EXECUTABLE_SUFFIX} )
    ADD_TEST( ArrayViewTestCuda ${EXECUTABLE_OUTPUT_PATH}/ArrayViewTestCuda${CMAKE_EXECUTABLE_SUFFIX} )
@@ -86,10 +101,12 @@ IF( BUILD_CUDA )
    ADD_TEST( VectorBinaryOperationsTestCuda ${EXECUTABLE_OUTPUT_PATH}/VectorBinaryOperationsTestCuda${CMAKE_EXECUTABLE_SUFFIX} )
    ADD_TEST( VectorUnaryOperationsTestCuda ${EXECUTABLE_OUTPUT_PATH}/VectorUnaryOperationsTestCuda${CMAKE_EXECUTABLE_SUFFIX} )
    ADD_TEST( VectorVerticalOperationsTestCuda ${EXECUTABLE_OUTPUT_PATH}/VectorVerticalOperationsTestCuda${CMAKE_EXECUTABLE_SUFFIX} )
+#   ADD_TEST( VectorOfStaticVectorsTestCuda ${EXECUTABLE_OUTPUT_PATH}/VectorOfStaticVectorsTestCuda${CMAKE_EXECUTABLE_SUFFIX} )
 ENDIF()
 ADD_TEST( StaticArrayTest ${EXECUTABLE_OUTPUT_PATH}/StaticArrayTest${CMAKE_EXECUTABLE_SUFFIX} )
 ADD_TEST( StaticVectorTest ${EXECUTABLE_OUTPUT_PATH}/StaticVectorTest${CMAKE_EXECUTABLE_SUFFIX} )
 ADD_TEST( StaticVectorOperationsTest ${EXECUTABLE_OUTPUT_PATH}/StaticVectorOperationsTest${CMAKE_EXECUTABLE_SUFFIX} )
+#ADD_TEST( StaticVectorOfStaticVectorsTest ${EXECUTABLE_OUTPUT_PATH}/StaticVectorOfStaticVectorsTest${CMAKE_EXECUTABLE_SUFFIX} )
 
 
 ADD_SUBDIRECTORY( Multimaps )
diff --git a/src/UnitTests/Containers/StaticVectorOfStaticVectorsTest.cpp b/src/UnitTests/Containers/StaticVectorOfStaticVectorsTest.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..3b4ef0987d8dee435ec7f5bcdf98e4430218e4fd
--- /dev/null
+++ b/src/UnitTests/Containers/StaticVectorOfStaticVectorsTest.cpp
@@ -0,0 +1,6 @@
+#define STATIC_VECTOR
+#define VECTOR_OF_STATIC_VECTORS
+#include "VectorBinaryOperationsTest.h"
+#include "VectorUnaryOperationsTest.h"
+#include "VectorVerticalOperationsTest.h"
+#include "../main.h"
diff --git a/src/UnitTests/Containers/VectorBinaryOperationsTest.h b/src/UnitTests/Containers/VectorBinaryOperationsTest.h
index bae5ce5f389e703711df651084994c8f39775116..e8932d3e4ad2e0426746a8e647b742aa5c875cd5 100644
--- a/src/UnitTests/Containers/VectorBinaryOperationsTest.h
+++ b/src/UnitTests/Containers/VectorBinaryOperationsTest.h
@@ -21,6 +21,9 @@
 #elif defined(STATIC_VECTOR)
    #include <TNL/Containers/StaticVector.h>
 #else
+   #ifdef VECTOR_OF_STATIC_VECTORS
+      #include <TNL/Containers/StaticVector.h>
+   #endif
    #include <TNL/Containers/Vector.h>
    #include <TNL/Containers/VectorView.h>
 #endif
@@ -176,50 +179,76 @@ protected:
    #endif
    >;
 #elif defined(STATIC_VECTOR)
-   using VectorPairs = ::testing::Types<
-      Pair< StaticVector< 1, int >,     StaticVector< 1, int >    >,
-      Pair< StaticVector< 1, double >,  StaticVector< 1, double > >,
-      Pair< StaticVector< 2, int >,     StaticVector< 2, int >    >,
-      Pair< StaticVector< 2, double >,  StaticVector< 2, double > >,
-      Pair< StaticVector< 3, int >,     StaticVector< 3, int >    >,
-      Pair< StaticVector< 3, double >,  StaticVector< 3, double > >,
-      Pair< StaticVector< 4, int >,     StaticVector< 4, int >    >,
-      Pair< StaticVector< 4, double >,  StaticVector< 4, double > >,
-      Pair< StaticVector< 5, int >,     StaticVector< 5, int >    >,
-      Pair< StaticVector< 5, double >,  StaticVector< 5, double > >
-   >;
+   #ifdef VECTOR_OF_STATIC_VECTORS
+      using VectorPairs = ::testing::Types<
+         Pair< StaticVector< 1, StaticVector< 3, double > >,  StaticVector< 1, StaticVector< 3, double > > >,
+         Pair< StaticVector< 2, StaticVector< 3, double > >,  StaticVector< 2, StaticVector< 3, double > > >,
+         Pair< StaticVector< 3, StaticVector< 3, double > >,  StaticVector< 3, StaticVector< 3, double > > >,
+         Pair< StaticVector< 4, StaticVector< 3, double > >,  StaticVector< 4, StaticVector< 3, double > > >,
+         Pair< StaticVector< 5, StaticVector< 3, double > >,  StaticVector< 5, StaticVector< 3, double > > >
+      >;
+   #else
+      using VectorPairs = ::testing::Types<
+         Pair< StaticVector< 1, int >,     StaticVector< 1, int >    >,
+         Pair< StaticVector< 1, double >,  StaticVector< 1, double > >,
+         Pair< StaticVector< 2, int >,     StaticVector< 2, int >    >,
+         Pair< StaticVector< 2, double >,  StaticVector< 2, double > >,
+         Pair< StaticVector< 3, int >,     StaticVector< 3, int >    >,
+         Pair< StaticVector< 3, double >,  StaticVector< 3, double > >,
+         Pair< StaticVector< 4, int >,     StaticVector< 4, int >    >,
+         Pair< StaticVector< 4, double >,  StaticVector< 4, double > >,
+         Pair< StaticVector< 5, int >,     StaticVector< 5, int >    >,
+         Pair< StaticVector< 5, double >,  StaticVector< 5, double > >
+      >;
+   #endif
 #else
-   using VectorPairs = ::testing::Types<
-   #ifndef HAVE_CUDA
-      Pair< Vector<     int,       Devices::Host >, Vector<     int,       Devices::Host > >,
-      Pair< VectorView< int,       Devices::Host >, Vector<     int,       Devices::Host > >,
-      Pair< VectorView< const int, Devices::Host >, Vector<     int,       Devices::Host > >,
-      Pair< Vector<     int,       Devices::Host >, VectorView< int,       Devices::Host > >,
-      Pair< Vector<     int,       Devices::Host >, VectorView< const int, Devices::Host > >,
-      Pair< VectorView< int,       Devices::Host >, VectorView< int,       Devices::Host > >,
-      Pair< VectorView< const int, Devices::Host >, VectorView< int,       Devices::Host > >,
-      Pair< VectorView< const int, Devices::Host >, VectorView< const int, Devices::Host > >,
-      Pair< VectorView< int,       Devices::Host >, VectorView< const int, Devices::Host > >,
-      Pair< Vector<     double,    Devices::Host >, Vector<     double,    Devices::Host > >,
-      Pair< VectorView< double,    Devices::Host >, Vector<     double,    Devices::Host > >,
-      Pair< Vector<     double,    Devices::Host >, VectorView< double,    Devices::Host > >,
-      Pair< VectorView< double,    Devices::Host >, VectorView< double,    Devices::Host > >
+   #ifdef VECTOR_OF_STATIC_VECTORS
+      using VectorPairs = ::testing::Types<
+      #ifndef HAVE_CUDA
+         Pair< Vector<     StaticVector< 3, double >, Devices::Host >, Vector<     StaticVector< 3, double >, Devices::Host > >,
+         Pair< VectorView< StaticVector< 3, double >, Devices::Host >, Vector<     StaticVector< 3, double >, Devices::Host > >,
+         Pair< Vector<     StaticVector< 3, double >, Devices::Host >, VectorView< StaticVector< 3, double >, Devices::Host > >,
+         Pair< VectorView< StaticVector< 3, double >, Devices::Host >, VectorView< StaticVector< 3, double >, Devices::Host > >
+      #else
+         Pair< Vector<     StaticVector< 3, double >, Devices::Cuda >, Vector<     StaticVector< 3, double >, Devices::Cuda > >,
+         Pair< VectorView< StaticVector< 3, double >, Devices::Cuda >, Vector<     StaticVector< 3, double >, Devices::Cuda > >,
+         Pair< Vector<     StaticVector< 3, double >, Devices::Cuda >, VectorView< StaticVector< 3, double >, Devices::Cuda > >,
+         Pair< VectorView< StaticVector< 3, double >, Devices::Cuda >, VectorView< StaticVector< 3, double >, Devices::Cuda > >
+      #endif
+      >;
    #else
-      Pair< Vector<     int,       Devices::Cuda >, Vector<     int,       Devices::Cuda > >,
-      Pair< VectorView< int,       Devices::Cuda >, Vector<     int,       Devices::Cuda > >,
-      Pair< VectorView< const int, Devices::Cuda >, Vector<     int,       Devices::Cuda > >,
-      Pair< Vector<     int,       Devices::Cuda >, VectorView< int,       Devices::Cuda > >,
-      Pair< Vector<     int,       Devices::Cuda >, VectorView< const int, Devices::Cuda > >,
-      Pair< VectorView< int,       Devices::Cuda >, VectorView< int,       Devices::Cuda > >,
-      Pair< VectorView< const int, Devices::Cuda >, VectorView< int,       Devices::Cuda > >,
-      Pair< VectorView< const int, Devices::Cuda >, VectorView< const int, Devices::Cuda > >,
-      Pair< VectorView< int,       Devices::Cuda >, VectorView< const int, Devices::Cuda > >,
-      Pair< Vector<     double,    Devices::Cuda >, Vector<     double,    Devices::Cuda > >,
-      Pair< VectorView< double,    Devices::Cuda >, Vector<     double,    Devices::Cuda > >,
-      Pair< Vector<     double,    Devices::Cuda >, VectorView< double,    Devices::Cuda > >,
-      Pair< VectorView< double,    Devices::Cuda >, VectorView< double,    Devices::Cuda > >
+      using VectorPairs = ::testing::Types<
+      #ifndef HAVE_CUDA
+         Pair< Vector<     int,       Devices::Host >, Vector<     int,       Devices::Host > >,
+         Pair< VectorView< int,       Devices::Host >, Vector<     int,       Devices::Host > >,
+         Pair< VectorView< const int, Devices::Host >, Vector<     int,       Devices::Host > >,
+         Pair< Vector<     int,       Devices::Host >, VectorView< int,       Devices::Host > >,
+         Pair< Vector<     int,       Devices::Host >, VectorView< const int, Devices::Host > >,
+         Pair< VectorView< int,       Devices::Host >, VectorView< int,       Devices::Host > >,
+         Pair< VectorView< const int, Devices::Host >, VectorView< int,       Devices::Host > >,
+         Pair< VectorView< const int, Devices::Host >, VectorView< const int, Devices::Host > >,
+         Pair< VectorView< int,       Devices::Host >, VectorView< const int, Devices::Host > >,
+         Pair< Vector<     double,    Devices::Host >, Vector<     double,    Devices::Host > >,
+         Pair< VectorView< double,    Devices::Host >, Vector<     double,    Devices::Host > >,
+         Pair< Vector<     double,    Devices::Host >, VectorView< double,    Devices::Host > >,
+         Pair< VectorView< double,    Devices::Host >, VectorView< double,    Devices::Host > >
+      #else
+         Pair< Vector<     int,       Devices::Cuda >, Vector<     int,       Devices::Cuda > >,
+         Pair< VectorView< int,       Devices::Cuda >, Vector<     int,       Devices::Cuda > >,
+         Pair< VectorView< const int, Devices::Cuda >, Vector<     int,       Devices::Cuda > >,
+         Pair< Vector<     int,       Devices::Cuda >, VectorView< int,       Devices::Cuda > >,
+         Pair< Vector<     int,       Devices::Cuda >, VectorView< const int, Devices::Cuda > >,
+         Pair< VectorView< int,       Devices::Cuda >, VectorView< int,       Devices::Cuda > >,
+         Pair< VectorView< const int, Devices::Cuda >, VectorView< int,       Devices::Cuda > >,
+         Pair< VectorView< const int, Devices::Cuda >, VectorView< const int, Devices::Cuda > >,
+         Pair< VectorView< int,       Devices::Cuda >, VectorView< const int, Devices::Cuda > >,
+         Pair< Vector<     double,    Devices::Cuda >, Vector<     double,    Devices::Cuda > >,
+         Pair< VectorView< double,    Devices::Cuda >, Vector<     double,    Devices::Cuda > >,
+         Pair< Vector<     double,    Devices::Cuda >, VectorView< double,    Devices::Cuda > >,
+         Pair< VectorView< double,    Devices::Cuda >, VectorView< double,    Devices::Cuda > >
+      #endif
+      >;
    #endif
-   >;
 #endif
 
 TYPED_TEST_SUITE( VectorBinaryOperationsTest, VectorPairs );
diff --git a/src/UnitTests/Containers/VectorOfStaticVectorsTest.cpp b/src/UnitTests/Containers/VectorOfStaticVectorsTest.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..859cf045c092aabd8ba11d80a88aad697efd7604
--- /dev/null
+++ b/src/UnitTests/Containers/VectorOfStaticVectorsTest.cpp
@@ -0,0 +1,5 @@
+#define VECTOR_OF_STATIC_VECTORS
+#include "VectorBinaryOperationsTest.h"
+#include "VectorUnaryOperationsTest.h"
+#include "VectorVerticalOperationsTest.h"
+#include "../main.h"
diff --git a/src/UnitTests/Containers/VectorUnaryOperationsTest.h b/src/UnitTests/Containers/VectorUnaryOperationsTest.h
index 827147cd53552209f9875370b93ca75d7514728a..aa595d8e97be4f34b9275adaf55cae182819fc02 100644
--- a/src/UnitTests/Containers/VectorUnaryOperationsTest.h
+++ b/src/UnitTests/Containers/VectorUnaryOperationsTest.h
@@ -21,6 +21,9 @@
 #elif defined(STATIC_VECTOR)
    #include <TNL/Containers/StaticVector.h>
 #else
+   #ifdef VECTOR_OF_STATIC_VECTORS
+      #include <TNL/Containers/StaticVector.h>
+   #endif
    #include <TNL/Containers/Vector.h>
    #include <TNL/Containers/VectorView.h>
 #endif
@@ -81,35 +84,57 @@ protected:
    #endif
    >;
 #elif defined(STATIC_VECTOR)
-   using VectorTypes = ::testing::Types<
-      StaticVector< 1, int >,
-      StaticVector< 1, double >,
-      StaticVector< 2, int >,
-      StaticVector< 2, double >,
-      StaticVector< 3, int >,
-      StaticVector< 3, double >,
-      StaticVector< 4, int >,
-      StaticVector< 4, double >,
-      StaticVector< 5, int >,
-      StaticVector< 5, double >
-   >;
-#else
-   using VectorTypes = ::testing::Types<
-   #ifndef HAVE_CUDA
-      Vector<     int,       Devices::Host >,
-      VectorView< int,       Devices::Host >,
-      VectorView< const int, Devices::Host >,
-      Vector<     double,    Devices::Host >,
-      VectorView< double,    Devices::Host >
+   #ifdef VECTOR_OF_STATIC_VECTORS
+      using VectorTypes = ::testing::Types<
+         StaticVector< 1, StaticVector< 3, double > >,
+         StaticVector< 2, StaticVector< 3, double > >,
+         StaticVector< 3, StaticVector< 3, double > >,
+         StaticVector< 4, StaticVector< 3, double > >,
+         StaticVector< 5, StaticVector< 3, double > >
+      >;
+   #else
+      using VectorTypes = ::testing::Types<
+         StaticVector< 1, int >,
+         StaticVector< 1, double >,
+         StaticVector< 2, int >,
+         StaticVector< 2, double >,
+         StaticVector< 3, int >,
+         StaticVector< 3, double >,
+         StaticVector< 4, int >,
+         StaticVector< 4, double >,
+         StaticVector< 5, int >,
+         StaticVector< 5, double >
+      >;
    #endif
-   #ifdef HAVE_CUDA
-      Vector<     int,       Devices::Cuda >,
-      VectorView< int,       Devices::Cuda >,
-      VectorView< const int, Devices::Cuda >,
-      Vector<     double,    Devices::Cuda >,
-      VectorView< double,    Devices::Cuda >
+#else
+   #ifdef VECTOR_OF_STATIC_VECTORS
+      using VectorTypes = ::testing::Types<
+      #ifndef HAVE_CUDA
+         Vector<     StaticVector< 3, double >, Devices::Host >,
+         VectorView< StaticVector< 3, double >, Devices::Host >
+      #else
+         Vector<     StaticVector< 3, double >, Devices::Cuda >,
+         VectorView< StaticVector< 3, double >, Devices::Cuda >
+      #endif
+      >;
+   #else
+      using VectorTypes = ::testing::Types<
+      #ifndef HAVE_CUDA
+         Vector<     int,       Devices::Host >,
+         VectorView< int,       Devices::Host >,
+         VectorView< const int, Devices::Host >,
+         Vector<     double,    Devices::Host >,
+         VectorView< double,    Devices::Host >
+      #endif
+      #ifdef HAVE_CUDA
+         Vector<     int,       Devices::Cuda >,
+         VectorView< int,       Devices::Cuda >,
+         VectorView< const int, Devices::Cuda >,
+         Vector<     double,    Devices::Cuda >,
+         VectorView< double,    Devices::Cuda >
+      #endif
+      >;
    #endif
-   >;
 #endif
 
 TYPED_TEST_SUITE( VectorUnaryOperationsTest, VectorTypes );
@@ -297,7 +322,7 @@ TYPED_TEST( VectorUnaryOperationsTest, abs )
    EXPECT_EQ( abs(V1), V1 );
    // unary expression
    EXPECT_EQ( abs(-V1), V1 );
-   // unary expression
+   // binary expression
    EXPECT_EQ( abs(-V1-V1), V2 );
 }
 
diff --git a/src/UnitTests/Containers/VectorVerticalOperationsTest.h b/src/UnitTests/Containers/VectorVerticalOperationsTest.h
index 93ff286ae65fb5b9dc170903d6aeb16032ebaa69..0650e3154a74830afd6ca24e2640df2f0ebe0b0e 100644
--- a/src/UnitTests/Containers/VectorVerticalOperationsTest.h
+++ b/src/UnitTests/Containers/VectorVerticalOperationsTest.h
@@ -21,6 +21,9 @@
 #elif defined(STATIC_VECTOR)
    #include <TNL/Containers/StaticVector.h>
 #else
+   #ifdef VECTOR_OF_STATIC_VECTORS
+      #include <TNL/Containers/StaticVector.h>
+   #endif
    #include <TNL/Containers/Vector.h>
    #include <TNL/Containers/VectorView.h>
 #endif
@@ -120,35 +123,57 @@ protected:
    #endif
    >;
 #elif defined(STATIC_VECTOR)
-   using VectorTypes = ::testing::Types<
-      StaticVector< 1, int >,
-      StaticVector< 1, double >,
-      StaticVector< 2, int >,
-      StaticVector< 2, double >,
-      StaticVector< 3, int >,
-      StaticVector< 3, double >,
-      StaticVector< 4, int >,
-      StaticVector< 4, double >,
-      StaticVector< 5, int >,
-      StaticVector< 5, double >
-   >;
-#else
-   using VectorTypes = ::testing::Types<
-   #ifndef HAVE_CUDA
-      Vector<     int,       Devices::Host >,
-      VectorView< int,       Devices::Host >,
-      VectorView< const int, Devices::Host >,
-      Vector<     double,    Devices::Host >,
-      VectorView< double,    Devices::Host >
+   #ifdef VECTOR_OF_STATIC_VECTORS
+      using VectorTypes = ::testing::Types<
+         StaticVector< 1, StaticVector< 3, double > >,
+         StaticVector< 2, StaticVector< 3, double > >,
+         StaticVector< 3, StaticVector< 3, double > >,
+         StaticVector< 4, StaticVector< 3, double > >,
+         StaticVector< 5, StaticVector< 3, double > >
+      >;
+   #else
+      using VectorTypes = ::testing::Types<
+         StaticVector< 1, int >,
+         StaticVector< 1, double >,
+         StaticVector< 2, int >,
+         StaticVector< 2, double >,
+         StaticVector< 3, int >,
+         StaticVector< 3, double >,
+         StaticVector< 4, int >,
+         StaticVector< 4, double >,
+         StaticVector< 5, int >,
+         StaticVector< 5, double >
+      >;
    #endif
-   #ifdef HAVE_CUDA
-      Vector<     int,       Devices::Cuda >,
-      VectorView< int,       Devices::Cuda >,
-      VectorView< const int, Devices::Cuda >,
-      Vector<     double,    Devices::Cuda >,
-      VectorView< double,    Devices::Cuda >
+#else
+   #ifdef VECTOR_OF_STATIC_VECTORS
+      using VectorTypes = ::testing::Types<
+      #ifndef HAVE_CUDA
+         Vector<     StaticVector< 3, double >, Devices::Host >,
+         VectorView< StaticVector< 3, double >, Devices::Host >
+      #else
+         Vector<     StaticVector< 3, double >, Devices::Cuda >,
+         VectorView< StaticVector< 3, double >, Devices::Cuda >
+      #endif
+      >;
+   #else
+      using VectorTypes = ::testing::Types<
+      #ifndef HAVE_CUDA
+         Vector<     int,       Devices::Host >,
+         VectorView< int,       Devices::Host >,
+         VectorView< const int, Devices::Host >,
+         Vector<     double,    Devices::Host >,
+         VectorView< double,    Devices::Host >
+      #endif
+      #ifdef HAVE_CUDA
+         Vector<     int,       Devices::Cuda >,
+         VectorView< int,       Devices::Cuda >,
+         VectorView< const int, Devices::Cuda >,
+         Vector<     double,    Devices::Cuda >,
+         VectorView< double,    Devices::Cuda >
+      #endif
+      >;
    #endif
-   >;
 #endif
 
 TYPED_TEST_SUITE( VectorVerticalOperationsTest, VectorTypes );